Building Numeron's tax engine with Zurdo
How Zurdo builds Numeron's tax engine: one PRD per change, goldens frozen before the generator, and a criterion that scores every golden through the real engine.
Numeron's tax engine is the project Zurdo was built for. This post is about what the engine is made of and what Zurdo does there. Every count below is as of 2 November 2026.
Two substrates
The engine has two layers.
The first is a knowledge graph of tax law: forms, lines, calculations, eligibility rules and the relationships between them. Every fact in it points back to the reading of the law it came from. The graph answers what the law says. Its contract has 9 node labels and 12 edge types.
The second is the IRS's Fact Graph, the open-source evaluator behind Direct File, vendored into the repository under its CC0 licence. It loads a dictionary, accepts the facts a filer writes, and derives the rest. The engine answers what the number is.
Between them sits a compiler that reads the graph and emits one dictionary per entity type and tax year. The graph is built offline from recorded extraction runs over the law, and the individual return's generator is written by hand.
Goldens before generators
Each entity type is scored against goldens: hand-worked scenarios with declared inputs and expected derived values, authored from cited statutory authority. A golden is written and frozen before the generator meant to pass it.
Seven dictionary releases ship: federal individual for 2024 and 2025, federal partnership, S corporation and C corporation for 2025, and Arizona individual and partnership for 2025. Each release carries a run report of the goldens it scored. Across the seven reports, 195 goldens are scored and 195 pass.
One PRD per change
Every change to the engine goes through a PRD, and Zurdo runs it. The repository holds 93 PRDs across 7 milestones, from foundation to Arizona, with 443 tasks between them. The tasks carry over 1,100 typed acceptance criteria, most of them [shell:] criteria that run a command and read its exit code. Zurdo drives the coding agent through each task and checks every criterion against the working tree itself, instead of reading the agent's report. Beside the PRDs sit 56 lessons, corrections that one run recorded for the runs after it.
The criterion that every dictionary change carries builds the dictionary fresh from the graph and scores each of that entity's goldens through the engine. The same command runs in CI.
Why the criterion runs the engine
In June 2026 the partnership dictionary was checked two ways: a Python re-implementation of its logic compared against the 8 partnership goldens, and a check that the dictionary compiled in the engine. Scored through the engine itself, the dictionary passed 0 of 8. One input type could not be set through the engine's bridge, so every derived value stayed empty, and the scoring script addressed the facts under the wrong names.
The design review that followed set three rules, and each became a criterion:
- a partnership dictionary passes when the engine scores 8 of 8, with no partial result accepted;
- the re-implementation stays as a self-consistency check and certifies nothing;
- a lint refuses any input fact whose type the engine cannot set, before the dictionary is written.
The federal partnership release now scores 10 of 10 goldens through the engine, and the Form 1040 dictionary for tax year 2025 carries 337 facts, 220 of them derived. The whole graph holds 1,342 facts.
By the numbers
All counts as of 2 November 2026, at the repository's current commit.
| Number | What it counts | Source |
|---|---|---|
| 93 | PRDs, across 7 milestones | prds/ |
| 443 | tasks in those PRDs | prds/ |
| over 1,100 | typed acceptance criteria in those PRDs | prds/ |
| 56 | lessons | lessons/ |
| 7 | dictionary releases | packages/dictionaries/releases/ |
| 195 | goldens scored and passed by those releases | each release's run-report.json |
| 1,342 | facts in the graph | the graph contract and releases |