Commit Graph
3 Commits
Author SHA1 Message Date
swaitsandClaude Fable 5.1 73dd967b1a feat(checker): examples() and spec_files() carry the specification's files
check / check (push) Canceled after 0s
A consumer of the checker crate needs no path into this repository.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp
2026-10-29 16:35:29 -06:00
swaitsandClaude Fable 5.1 f8cd4abbce feat(bookspec): GnuCash as the second engine, its differences settled (P13 step 5)
bookspec-gnucash implements the Engine trait over the oracle container
(oracle/gnucash/books.py) and claims the rules whose examples ask only
for balances. It passes BS-entry-3, BS-ledger-3, BS-statement-1 and
BS-statement-2 and differs from three examples, each adjudicated from the
sources and pinned by tests: GnuCash accepts an unbalanced entry and
parks the difference in an Imbalance account (BS-entry-1 refuses it); it
reads a credit of minus 100 as a debit (BS-entry-2 is a convention that
removes the ambiguity); it rounds 10.005 to 10.01 silently (BS-ledger-1
is the owner's choice not to). The example stands in each case: GnuCash
is a cross-check, not the authority.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp
2026-10-29 12:51:30 -06:00
swaits 7350adb07a feat(bookspec): the checker crate, the Engine trait and the runner (P13)
bookspec is a specification first: every rule normative and sourced,
every rule demonstrated by concrete examples, and any accounting engine
checked against them through one interface (D-34). This moves the
examples' schema out of the test that happened to parse them and makes
the interface explicit.

- `bookspec/checker` (its own workspace, inside this repository until
  the harness is stable): `Example`, `Setup`, `Event`, `Expect`, `Query`,
  `Refusal` and the TOML parser, every structure `deny_unknown_fields`,
  with `Example::from_toml` checking the cross-field shape (closed lists,
  exact decimal amounts, dates, one event kind, `reverses` counting from
  1, the shares summing to 1, commands accepted or refused and not both).
- `Engine` (`load`, `apply`, `query`, `claims`) and `Refusal { rule,
  reason }`; the refusal's rule is the bookspec identifier, so a refusal
  names the rule it belongs to. `Claims` also carries the option an
  engine picks for a CHOICE rule.
- `bookspec/runner` drives any `Engine` through the examples and reports
  per rule: pass, fail, not claimed. It compares the answer itself; an
  engine is never asked whether it agrees with itself.
- `crates/ledger-core/tests/bookspec.rs` is the wanderbooks adapter over
  `Store`: the loader parses through the checker, its own checks are
  unchanged, and the new `the_runner_reports_every_claimed_rule_green`
  runs all 56 examples through the trait. The IIF appendix is answered
  through `ledger_package::export_iif`, the code its own test checks.
- `just check` runs the bookspec workspace's fmt, clippy, rustdoc and
  tests too, so an example cannot rot (D-34, Z-17).

The plan's trait has four methods and no path for an example's
`[[changes]]` (a rename, the policy, an asset correction), which post no
entry: `change` is the fifth, required so an engine cannot skip those
examples silently. This is reported to the EM as the one departure.

One money rule holds here too: an answer's figures are exact decimal
strings, never JSON numbers, so no engine can round a cent through a
float.
2026-10-26 21:22:46 -06:00