The test-case reference
GreatBook’s claim is that judgment-heavy accounting work can be turned into deterministic, inspectable behaviour. This page is the evidence for that claim, enumerated rather than asserted. Three surfaces hold the whole system to account, and they are not the same kind of thing.68 eval cases
Judgment, measured against a reference answer.
104 Close checksums
Reconciliations that run at close and report.
18 GL invariants
Preconditions that run before the write and refuse.
What is being tested, and why the split matters
The engine is not evaluated, it is proven. An unbalanced entry does not post most of the time; it is refused by an invariant, every time, before anything is written. What cannot be made correct by construction is judgment. No database constraint makes a misclassification impossible, so the classification, the extraction, the account proposal and the scope decision are each driven against a real compiled graph with the real model and graded on a written reference answer. Every case on this page runs the real thing. No eval stubs the component it is testing, and a missing prerequisite reports SKIP rather than a pass - the rule and the guards behind it are set out in Never stub what you test.The board
Pass rates are from the runs dated 2026-07-26 to 2026-07-27.
How to read a case
Each case is one row of a JSON dataset, and it has the same four parts everywhere.
A case passes when every score it received is 1.0.
An evaluator that returns nothing scores nothing, so a mixed dataset never manufactures a 1.0 for a case that was not graded on that dimension.
A case that fails for a known, accepted reason declares it in
metadata.expected_baseline, naming the score keys it excuses and the exact run shape that excuses them.
Those cases report XFAIL rather than turning the board red, and an XPASS - the defect appearing fixed - fails the run so the marker gets removed.
A bare “this case may fail” flag would swallow a new regression inside a case that was already red, so naming the keys is the load-bearing part.Clerk · 15 cases
The Clerk classifies an uploaded document against the 146-type registry, extracts its fields against that type’s real schema, and flags rather than guesses. Real compiled graph, real keyless Agent SDK extractor; only the queue store and file sink are in-memory doubles, so no eval run writes into the live intake queue.Classification · 5 cases
Extraction · 4 cases
Each case is written against the doc type’s real extraction schema, not against what seems reasonable, because the graph’s allowlist drops anything outside it.The bank-statement case once demanded the ISO form of
period alone, which graded a free formatting choice and failed roughly one run in three.
Accepting any faithful rendering is the fix, and it is why the expectation is a list.Uncertainty and governance · 2 cases
Scope gate · 4 cases
scoped_answer_judge is the only model-judged score in the entire suite, and it fails closed: an unavailable judge scores 0, never a pass.
Nothing accounting-shaped is ever judged by a model - account codes, balance, entry counts, chain findings, flag fields and scope verdicts are exact comparisons.Bookkeeper · 11 cases
One approved intake record becomes the right balanced Dr/Cr in the canonical GL, behind a human posting gate, exactly once. Real graph, real posting rules and the realLedgerService writer against a real alembic-migrated Postgres, so the advisory lock, the 18 GL invariants, the hash chain and the GL idempotency key are all live.
Proposal correctness · 5 cases
Posting, idempotency and refusal · 6 cases
raises_expected_error is graded as an actual raise, not as “nothing was posted”.
A silent no-op would satisfy the weaker check while leaving the caller with no way to tell refusal from success.Auditor · 26 cases
Continuous read-only verification of the book of record. Each case seeds a real migrated GL through the real single writer, injects at most one fault out of band, then asks the real auditor graph a question. Every case additionally assertsread_only_guarantee: the org’s entry, line and intake counts and the chain tail are unchanged across the run.
Reconciliation graph · 4 cases
Close phases · 4 cases
Document completeness · 4 cases
Durable register · 3 cases
Accountant · 5 cases
The close checklist runs the real workbook Close-list oracle over a real migrated GL, and an adjusting entry is routed through the real Bookkeeper graph to its human posting gate.acct_no_direct_ledger_write is checked by counting rows in journal_entries, never by reading what the answer claims.
Typewriter · 11 cases
A described document or a pasted list becomes schema-conformant proposals: the right one of the 146 types, the stated facts in the fields the ontology declares for them, the declared types honoured, nothing undeclared, and nothing written. This graph has one injected boundary - the model - and no storage at all, so nothing is substituted.Composition · 4 cases
Selection, tabulation and anti-fabrication · 4 cases
Scope gate · 3 cases
None of these three reaches the model.The Close checksums
A Close checksum is a reconciliation over the whole book: it runs at close and it reports.close_checks.py declares 104 checksums - 82 must-be-zero and 22 explainable balances - and the number that actually executes on a run is data-dependent, because nine definitions expand per rail, per currency, per stock item or per facility and sixteen are conditional.
Each one carries a generated phase and layer tag, which is what lets 78 of them run nightly rather than at close.
The distinction is load-bearing.
A deposit held on behalf of a customer is supposed to be a non-zero liability, and reporting it as a break would train people to ignore breaks.
The seven families
settlement · the AP/AR spine and the rails
settlement · the AP/AR spine and the rails
Ties the sub-ledgers to their control accounts, and the book to external bank evidence per rail per currency.Representative must-be-zero:
AP-CONTROL, AR-CONTROL, PAYMENT-CROSSFOOT, RECEIPT-CROSSFOOT, RAIL-CATALOG, FLOAT-GL-TIE, and RAIL-AP:<rail>:<ccy> / RAIL-AR:<rail>:<ccy> per active rail.Explainable: FLOAT-HELD, DEPOSIT-244, DEPOSIT-344, AP-OUTSTANDING, AR-OUTSTANDING.AP-CONTROL is the one to read first: it compares GL 2000 outstanding against the sum of bill dues, and catches a posting to the control account that bypassed the AP sub-ledger entirely.costing · inventory, WIP and the 627 pool
costing · inventory, WIP and the 627 pool
Representative must-be-zero:
WIP-154, POOL-627, GRNI, TOTAL-154, INVENTORY-GL-TIE, NEG-STOCK-QTY, NEG-STOCK-VALUE, LANDED-COST, BILL-LINE-FOOT, ITEM-CATALOG.Explainable: SAMPLE-POOL, and STOCK:<item> per item on hand.This is the largest family, because the bill-line spine and the cost catalogs are each checked for orphans as well as for totals.payroll · needs a period
payroll · needs a period
Representative must-be-zero:
EMPLOYER-COST, LABOUR-ALLOC, CONTRACT-ASOF, PIT-TIE, NET-TIE, PIT-GL-CARRY, PAYROLL-SETTLEMENT-EVIDENCE, VARIANCE-UNEXPLAINED, VARIANCE-CLASSIFIED, LEAVE-NONNEG.Explainable: MEAL-PIT-BASE, EMPLOYER-COST-TOTAL, THIRTEENTH-LIABILITY.PIT-TIE and NET-TIE compare what payroll computed against the obligations actually raised, which is the tie a spreadsheet cannot make.loans and treasury
loans and treasury
Representative must-be-zero:
INTEREST-OVERPAID, FLOAT-FACILITY-TIE, NONRECOURSE-NODEBT, and FACILITY-BAL:<id>, HEADROOM:<id>, FACTOR-FLAG:<id> per facility.Explainable: FACILITY-OWED:<id>, FACTOR-RECOURSE:<id>, FACTOR-DERECOG:<id>.VN VAT and statutory
VN VAT and statutory
Representative must-be-zero:
VAT-INTEGRITY-IN, VAT-INTEGRITY-OUT, VAT-133-TIE, VAT-3331-TIE, VAT-CASH-5M.Explainable: VAT-INPUT, VAT-OUTPUT, VAT-NET, VAT-NONDEDUCTIBLE, FCT-PAYABLE.VAT-INTEGRITY-OUT is a GreatBook addition: the workbook’s per-line integrity check only ever covered input VAT.adjustment notes
adjustment notes
Representative must-be-zero:
ADJ-ORPHAN, ADJ-QTYPRICE, ADJ-STOCK-LEG, ADJ-QTY-CEILING, ADJ-RATE-MATCH, ADJ-OUTSTANDING, ADJ-BASIS, ADJ-AUTHORITY.Explainable: ADJ-NET-AP, ADJ-NET-AR.A credit note may not exceed the quantity of the document it adjusts, and it must carry the original’s VAT rate.consolidation
consolidation
Representative must-be-zero:
IC-MIRROR, FX-REVAL, DIVIDEND-PIT.Explainable: IC-OUTSTANDING, FX-RESERVE.GROUP-TB is deliberately absent because adding balanced journals would restate a structural GL rule without proving group membership, translation, completeness, or eliminations.period.
Without one it is skipped rather than run against an undefined scope, which is the same fail-honestly rule the evals use for a missing prerequisite.
Two related numbers, and it is worth saying which you mean: the v12 workbook carries roughly 91 Close-list rows, and the code declares 104 checksums, of which a live run executes however many they expand to against that book’s data.
The Close checksums page enumerates every code in every family with its phase and its layer, generated from the inventory rather than hand-maintained.
What runs them
test_close_list is the capstone: one close touching six families with live worked data, asserting the whole surface is green.
The 18 GL invariants
A GL invariant is a precondition. It runs before the write and it refuses - and on any failure the writer raises a typed error and writes nothing. All eighteen are validated inside one function,LedgerService.post_entry(), and they are numbered in the source so a refusal can be traced to a rule.
backend/tests/test_ledger_engine.py covers every rule below against a throwaway migrated Postgres.
The last column names what else exercises it - a second unit suite, or the eval case that reaches it through a real agent run.
Invariants 12, 14 and 16 are what make the chain evidence rather than decoration, and the 18 GL invariants page sets out each rule’s typed error and exactly what it rejects.
Where these cases live
Running them
--only <case-id> …, --concurrency N, --json out.json, and --strict, which makes a SKIP fatal in an environment that is supposed to have everything wired.
The test that would fail if it broke
langgraph_chat/agents/evals/tests/test_evals_ci.py is the guard on the guards.
test_every_reference_key_is_graded_by_some_evaluator asserts that every key in every case’s outputs is read by at least one evaluator, because an expectation nobody reads is worse than no expectation - the case still shows PASS.
test_every_served_graph_is_graded asks langgraph.deploy.json which graphs production serves and requires each to be bound in the registry, which is what closes the hole the Typewriter shipped through: an agent that was never registered at all keeps every guard green.
Related
- The scoreboard - the pass rates, per dimension and per score key, with the run behind each number
- Never stub what you test - what is real per agent and what is substituted
- Worked cases - a handful of these cases in full, input to output
- How this gates a release - which of these runs on every PR
- The Close checksums - every checksum code, family by family
- The 18 GL invariants - each rule’s typed error and what it rejects
- The two API surfaces - the HTTP reference these cases sit beside