Commit Graph
4 Commits
Author SHA1 Message Date
swaitsandClaude Opus 5.5 c4c4ce05c3 test: fuzzing, Miri, benchmarks, CI, and a strategy note; the journal refuses floats
Max-testing pass, ranks 4-6 and step 9 for ledger-core.

Fuzzing (rank 4): fuzz_op_sequence now drives balanced pairs, foreign
lines, periods, closes, and amounts from raw decimal bits, and asserts
the books stay valid (TB balances, posted entries validate, no draft in
a closed period); new fuzz_core_serde (every persisted core type
round-trips) and fuzz_store_open (a corrupt journal is an error, never a
panic); hangs count (-timeout=10). 54M executions; one crash:
- fuzz_journal_line: a number too big for an integer parsed as a float,
  and its canonical form (which the hash chain covers) re-canonicalized
  differently. The journal never holds floats (R-2), so the reader now
  refuses them (JournalLine::parse, used by every journal reader);
  regression a_journal_line_with_a_float_is_refused. Checked first: the
  real books' journal has none. Rerun: 13.2M executions, clean.
Seeds in fuzz/seeds/ (synthetic, minimal); the grown corpora stay out of
git. `just fuzz <target> <seconds>`.

Miri (rank 4): the core's unit, bridge, and invariant tests under Miri
(our code has no unsafe; rust_decimal and chrono do): no undefined
behavior. `just miri`. A pinned nightly (nightly-2026-10-01, with miri)
is now in mise.toml.

Benchmarks (rank 6): criterion (new dev-dependency: the playbook's Rust
benchmark tool; none existed) in benches/books.rs; baselines in
docs/testing.md. The store's per-command rehearsal clone costs ~1 ms at
10k entries. No budget yet, so nothing gates on them. `just bench`.

CI: .github/workflows/check.yml runs `just check` on every push;
scheduled.yml runs proofs, the GnuCash oracle, fuzzing, and mutation
weekly. Tools come from mise.toml.

docs/testing.md: every layer, its oracle rank, command, runtime, and
gate; benchmark baselines; the ASSUMED invariants for the owner to reject;
the gap list with triggers. docs/oracle.md's fuzzing paragraph had
claimed persistent corpora that didn't exist; corrected.

Also: ledger-import now inherits the workspace lints (nightly cargo
warned).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
2026-10-13 15:09:22 -06:00
swaitsandClaude Opus 5.5 4ff5d1a40b feat: receipt unlink and attachment withdrawal
Posted entries stay immutable (R-3), but their evidence can now change the
same way the ledger does: by appending events, never by editing or
deleting. New R-13a.

- books.unlink_receipt {attachment_id, reason} journals receipt.unlinked
  and leaves the receipt filed, unlinked. The receipt policy holds: an
  entry that requires a receipt can't lose its last one (structured
  receipt_required error), so a replacement is attach-new, then
  unlink-old. Drafts and reversals are exempt, as at posting.
- books.withdraw_attachment {attachment_id, reason} journals
  attachment.withdrawn for an unlinked receipt or a filed document: hidden
  from list_receipts (unless include_withdrawn), never linkable again. The
  blob stays in the store, hash-verified and readable.
- link_receipt now refuses an already-linked or withdrawn attachment.
  Before, re-linking silently moved a receipt off a posted entry,
  bypassing the policy; evidence now leaves an entry only through a
  recorded unlink. dispose_asset checks its receipt ids before posting
  instead of after.
- Schema v5 adds attachments.withdrawn_at/withdrawn_reason; existing
  stores migrate on open and replay rebuilds the projection.

Tests: store test (errors, reopen, rebuild, verify, journal history) and
an MCP stdio test (policy refusal, replace flow, withdraw, listings,
under-threshold unlink). Dry-run and live use on the the first company books:
8 migrated .eml attachments swapped for their PDF renders, trial balance
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtYEaR6M6Ybdhm6X98BWNu
2026-10-11 18:40:51 -07:00
swaits 6352921c28 Payroll accounting, class tracking, CPA handoff package (48 MCP tools) 2026-10-11 15:32:03 +00:00
swaits 0b35794c1f First slice: ledger-store (journal+blobs+sqlite) and ledger-mcp (18 tools, receipt policy) 2026-10-11 01:37:13 +00:00