books.rename_account; account names trimmed, bounded, refused when a
sibling's or TIN-shaped; books.show refuses what its target ignores. A
report asked for without dates covers this fiscal year so far, everywhere
(one rule for tools, descriptions and the viewer; the IIF and CPA package
keep their own dates). policy.require_tax_category warns or refuses; a
Form 4797 gain is shown apart on every return.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3gXMVt7XJPi6ens1or9Dj
Ledger::renumber_account changes only the code (entries name accounts by
id): refuses an unknown account, a blank or used code, and a control code
for an account of the wrong type or a placeholder. Journaled as
account.renumbered (with the previous code), replayed, projected, shown
in the viewer's journal. The MCP tool lists wanderbooks.toml settings
that still name the old code. The server instructions now warn that the
engine can't tell a same-type account with another purpose at a control
code (a hosting expense at payroll's 6100).
Tests: core property (only the code changes; trial balance equal), core
refusals, the store's command property, MCP end to end with restart.
Mutation on the new code: 8 of 8 viable caught.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
CI's run of the store refusal property found a payroll run that posted
$65.27794: the employer tax was passed in unrounded and nothing refused
it, though rules.md B-3 already says a ledger in one money holds no
fractions of its smallest unit. Sums of it then differed in scale
between journal replay and the SQLite read-back.
- Ledger::post_entry refuses any line finer than its currency's ISO 4217
minor unit (FinerThanMinorUnit), whatever made the line: payroll,
closes, disposals. add_line refuses it up front. Older journals replay
as booked through replay_post_entry. Spec tests for the kernel's
ten-place limit now run on the replay path.
- The property's body is now run_ops, so failing sequences become named
regression tests (regression_payroll_with_a_fraction_of_a_cent). The
generator rounds payroll tax to the cent, as callers must.
- Ledger derives PartialEq and gains differs_from; Store::verify compares
the live ledger with the journal replay in full (drafts, documents,
schedules, periods, settings), not just balances, and names the parts
that differ. The property checks the ledger its commands built against
that replay and against the reopened books.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
wanderbooks is a general MCP-first accounting application: every
business needs its accounts mapped to where they land on its income tax
return, and its CPA needs book-to-tax differences surfaced, not hidden.
- ledger_core::tax: a catalog of stable categories (gross_receipts,
commissions_fees, meals, guaranteed_payments, officer_compensation,
nondeductible, ...) with kind (income, cost of goods, deduction), the
returns each appears on (Schedule C, 1065, 1120-S, 1120), a default
deductible percent (meals 50, nondeductible 0), and guidance. Keys,
not line numbers: form lines move from year to year.
- Accounts carry tax_category and an optional deductible_percent
override, validated against the account type (and the return, at the
MCP layer), journaled as account.tax_set, replayed, projected (schema
v6).
- tax_summary(start, end, form): the P&L grouped by category, book and
deductible amounts (half away from zero to the cent), contra income
(refunds) reducing receipts, and every account still uncategorized.
- MCP: books.tax_categories (filtered to the configured return),
books.set_tax_category, a tax_summary report in every format and in
the CPA package, chart output with categories, and a fifth
tax_category column in chart CSV imports, validated before anything is
created. [company] tax_form, or derived from tax_classification.
Scope stays book basis: no tax depreciation, basis, or filing.
Tests: a hand-computed quarter (50% meals 333.33 -> 166.67, penalties at
0%, refunds as negative receipts, guaranteed payments, one uncategorized
account; book net 5,276.67 vs tax 5,483.33); overrides; category/account
/return validation; form parsing and derivation; CSV parsing; stdio:
filtered catalog, mapping, refusal, summary, all-or-nothing import.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtYEaR6M6Ybdhm6X98BWNu
Zero warnings from `cargo clippy --workspace --all-targets`, which is now
a hard rule rather than "clean except pre-existing":
- ChartOfAccounts::add takes the Account it registers instead of eight
loose parameters (too_many_arguments); Ledger::add_account builds it.
Same validation, same errors.
- close_period tool: collapse the nested if-let into a let chain.
- iif.rs docs: the IIF layout example shows tabs as `\t` instead of
literal tab characters (tabs_in_doc_comments).
- Tests: drop an unused binding; assert! instead of assert_eq! against a
literal bool.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtYEaR6M6Ybdhm6X98BWNu