test(core): every surviving mutant killed or argued equivalent

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
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-13 17:00:45 -06:00
1 parent b2b49267db
commit bf3f5b4cdb
15 files changed
+989 -5

No files matched your search

+7 -2
View File
@@ -826,6 +826,7 @@ pub struct MembersEquityStatement {
/// 3. Unclosed earnings and the period's income MUST be split by share,
/// to the cent, by largest remainder (DECISION, owner 2026-10-13).
/// 4. NEVER hide an unexplained change: it goes in "other".
/// 5. An entry dated `start` is period activity, not beginning capital.
/// SCENARIOS:
/// 1. IF shares don't sum to 1, or are not positive: SHOULD refuse.
/// ```
@@ -1111,6 +1112,12 @@ pub struct CashFlowStatement {
/// 4. Financing MUST hold changes in equity (other than earnings) and in
/// the liabilities named as financing.
/// 5. NEVER count closing entries.
/// 6. The period is `[start, end]`, inclusive: an entry dated `start` is
/// period activity, not part of the beginning cash balance.
/// 7. Every line's amount is its cash effect: positive is cash in. Its
/// label names the direction the balance moved ("Increase in" /
/// "Decrease in"; "Proceeds from" / "Repayment of" for financing
/// debt; "Owner contributions" / "Owner distributions" for equity).
/// ```
pub fn cash_flow(
ledger: &Ledger,
@@ -1330,10 +1337,8 @@ pub fn cash_flow(
_ => {}
}
}
let book_value = cost_amount - accum_debit;
// Sanity: the entry balances, so proceeds + accum debit = cost + gain - loss.
debug_assert!((proceeds + accum_debit - cost_amount - gain + loss).is_zero());
let _ = book_value;
disposal_gain_loss += gain - loss;
investing.push(CashFlowLine {
label: format!("Sale of fixed assets — {proceeds_label}"),