Commit Graph
4 Commits
Author SHA1 Message Date
swaitsandClaude Opus 5.5 4d8d5daf37 store: refusals leave the live books untouched; per-filing names; spec suite
check / check (push) Canceled after 0s
The refusal property gained the converse law (an accepted command
journals something; only batch runs may find nothing to do) and checks
the store's class and payroll listings. It found a schedule registered
with an out-of-range total whose first month was refused after its entry
was begun: the live ledger kept a draft the journal never had.

- Core: compound commands (post_schedule_month, reverse_entry,
  close_period_to, create_invoice, create_bill, receive_payment,
  pay_bill, run_payroll, remit_payroll_taxes) run inside
  Ledger::atomically, so a refusal partway leaves the ledger exactly as
  it was.
- Core: a schedule total no line could carry, or finer than a cent, and
  an asset cost beyond the line range, are refused at registration.
  Replay keeps older schedules (replay_register_schedule).
- Store: add_line, add_line_fx, mark_cleared, set_fx_rate,
  post_schedule_month and close_period_to changed the live ledger before
  journaling; they now run on a copy, journal what it produced, then
  swap it in, so a failed write leaves the live books as journaled.

New spec-blind suite tests/spec_store.rs (57 tests written from the
store's specs alone). Its two findings, adjudicated:
- A file filed twice under different names listed the first name and
  type for both (the projection kept them per blob). Schema v8 gives
  each attachment its own; older databases backfill and heal by verify.
- Withdrawn attachments stay in the store's listing, marked (the MCP
  listing hides them): the spec and doc said "omit" and are corrected.

Also removes journal::truncate_to_last_good_seq: unused, and it dropped
everything after the first bad complete line, which the books now treat
as corruption for a person, never repaired automatically.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
2026-10-13 19:24:34 -06:00
swaitsandClaude Opus 5.5 22d1a3d449 store: refusal property reaches every success path; two engine fixes
check / check (push) Canceled after 0s
The refusal property now starts from real books and adds compound
commands with valid arguments (book an entry, register an asset or
schedule, raise an invoice or bill, close a month to members), so every
command's success path is exercised. Compound commands checkpoint after
each step, so the law is checked against the one command refused.
STORE_CASES sets the case count (256 by default).

It found two bugs:

- run_recurring created drafts dated inside a closed period (B-12).
  generate_recurring now refuses them, atomically; the store leaves
  them ungenerated and books.run_recurring reports them in
  skipped_closed_period for a human to decide. Replay uses
  replay_generate_recurring so older journals still open. The store
  also journals before mutating the ledger here, as everywhere else.
- Disposing an asset for no proceeds (scrapping it) journaled a
  catch-up depreciation entry and a half-built draft with a 0.00 line,
  then refused. Zero lines are now left out (Store::disposal_lines,
  shared with the MCP preview), and the whole disposal is rehearsed on
  a clone before anything is written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
2026-10-13 17:48:20 -06:00
swaitsandClaude Opus 5.5 d0490bf106 test(core): every surviving mutant killed or argued equivalent
check / check (push) Canceled after 0s
Max-testing pass, step 8. The final mutation run left 112 survivors
(89% caught). Three agents triaged them by file, by the playbook's
table: spec the boundary then test it, a law rather than one more
pinned value, assert the real value, never weaken a test. Every expected
value is hand-computed.

- reports.rs (35): 28 killed, chiefly cash flow (inclusive start date,
  each line's sign and label, a loss on disposal moving to investing,
  financing designation), general ledger and members' equity date
  boundaries, and the balanced() checks (a real report nudged by a cent
  must stop balancing). 7 equivalent: four >/>= after an early return on
  zero; two in dead code (removed in this commit); one sign of a zero
  cleaned on output.
- ledger.rs, kernel.rs, journal.rs, money.rs (52, plus one new): 49
  killed, including every replay_* mutant at the core level (ids,
  accumulation, status, vendor tags, out-of-order refusal), FX rates,
  0%/100% deductible boundaries, a dividend sweep with no income, the
  legacy member rounding at close, a bill paid on its own date, a
  liability-account reconciliation, mixed-currency entries (via serde),
  ISO 4217 minor units, Display/Debug. 3 equivalent: zero refused before
  a </<= check; a period whose end is in a closed period refused earlier;
  columns(0).
- schedules, tax, analysis, payouts, assets, form1099 (25): 23 killed
  (schedule length 1-600, recurring end on its start, frequency parsing
  and stepping, cost of goods in tax net, a zero payout, disposal on the
  purchase date, quarter starts, labels); 2 equivalent (zero adds zero;
  days_held is provably >= 1).

Two small production cleanups the triage surfaced: kernel::columns(0)
returned a negative-zero credit that would print "-0" (regression
a_zero_movement_has_no_negative_zero_column, shown to fail before); and
cash_flow computed a book value it never used.

Spec lines added where a boundary wasn't specified (cash flow's
inclusive start and line signs, members' equity start date, payout with
no deposit, disposal on the purchase date, bill paid on its own date).
`just mutants` now runs core and store tests (the store's replay tests),
not the whole workspace, which rebuilt the viewer for every mutant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
2026-10-13 17:00:45 -06:00
swaitsandClaude Opus 5.5 ddb67a2ca2 feat: prepaid/deferred amortization schedules and recurring entries
Amortization schedules spread a prepaid expense or deferred revenue over
the months it covers, to the cent, posting on month ends; runs preview
first, are idempotent, honor closed periods, and are exempt from the
receipt policy like depreciation. Recurring entries generate drafts only,
never posts. Six new tools (59 total); four new journal events, replayed
and checked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtYEaR6M6Ybdhm6X98BWNu
2026-10-11 21:09:43 -07:00