ENGINE 50
SFS-E50-WPB · WORKPAPER CONSTRUCTION · REV 2026-08-05 · PRODUCTION
PRODUCTION = runnable end-to-end, CI-backed, full test suite passing. All data fictional and seeded.
Tax Workpaper Build & Carry-Down
It builds the new year's workpaper package from the locked ledger and the signed prior year, then proves every cell it constructed against the inputs it came from.
Once a year the annual tax workpaper package has to become next year's package. In practice somebody opens last year's file, saves it under a new name, and edits it -- and every failure mode that follows shares one property: the package still foots. This engine builds the new package instead of editing the old one. It reads a locked general-ledger extract scoped to one entity block, the prior year's signed package, a member allocation register carrying the split pairs in integer basis points, a register of exceptions a reviewer has already accepted, the counterpart entity's copy of the investment held in the block, and an image of the working file captured immediately before the build ran. From those it constructs a current-year trial balance harvested by exact account number; a balance sheet and statement of operations classified from the prior-year map and footing to zero; a members' equity schedule in which every prior-year layer is carried byte-equal, every rolling caption is advanced by exactly one year, each current-year contribution and distribution is computed as the movement in its own account rather than typed, and the result is allocated on the carried split; a new year block per member in the capital accounts, book and tax, with liability share and outside basis; an earnings-and-profits roll-forward; an evidence tab with its citation block and a subtotal that has to foot to zero; and a build register naming every constructed cell beside the derivation that produced it. Twenty-four controls then prove what it built. The build is a pure function of its inputs, takes no clock reading, and never writes to the extract, the prior package or the registers.
Rolling a workpaper is not copying one. A copied file inherits last year's captions, last year's frozen history and last year's formulas, and the person doing the roll is asked to notice which of those should have changed -- in a file that adds up either way. Every defect this engine is built against survives review for the same reason: the schedule still foots. A prior-year layer moves because a sort was applied or a formula was left live in a frozen row, and history, which is supposed to be a constant, quietly gets a new value. A caption keeps last year's date, so a reviewer reconciles a current-year column against a prior-year heading and has no reason to suspect the heading. A contributions account holding every contribution since the entity was formed is dropped onto a current-year row, restating the whole history as this year's activity -- and the closing total was footed from that same row, so it agrees. A row's form is read off a formula rather than off the balances at both year-ends, which gets it wrong every time a formula was filled down. The rebuild touches a cell nobody declared, and the only way to know is to hold the pre-build image and diff against it. Because the engine builds rather than edits, each of those becomes a derivation with a name: the frozen layers are carried byte-equal and compared byte-equal, the captions are advanced arithmetically and checked arithmetically, the flows are computed as source-less-prior movements, the row form is decided from balances at both year-ends, and the edit scope is the build register or it is a finding. And because a workpaper package is the opening position of every year after it, a penny tolerated here is not a rounding difference -- it is frozen into every future year's history.
Architecture
functional block stack · static overviewSelect a layer
Seven stages run in build order over each file, and the controls that prove each stage sit with the stage that produced it -- twenty-four controls in all. The order is the order the package is constructed, from the ledger the year is harvested out of to the register that says what the build was allowed to touch, so a finding lands on the earliest derivation that can explain it.
Key specifications
at a glanceWhat it does for you
plain termsThe annual tax workpaper package has to become next year's package, and the way that is done is by opening last year's file, saving it under a new name and editing it. Everything that goes wrong from there shares one property: the package still foots. A prior-year layer moves, because a sort was applied or a formula was left live in a frozen row, and a figure that was signed off quietly acquires a new value. A caption keeps last year's date, so a reviewer reconciles a current-year column against a prior-year heading and cannot make it agree. A contributions account holding every contribution since the entity was formed is dropped onto a current-year row, restating the whole history as this year's activity -- and the closing total was footed from the same row, so the schedule agrees with itself. A row's form is read off a formula that was filled down rather than off the balances at both year-ends. A rebuild touches a cell nobody declared, and without a pre-build image there is nothing to diff against. And because the package is the opening position of every year after it, none of these is a one-year error.
The seeded demo builds every package, then proves what it built7. The CLI generates twenty-seven fictional build files -- one clean baseline and one carrying each of the twenty-six planted defects -- builds a package and a build register for each into a generated output folder, then runs all twenty-four controls over the built artifacts and writes both reports. The clean baseline returns PASS on all twenty-four. Each defect file returns exactly the finding its control exists for and nothing else, which is what proves the controls are independent rather than merely present. The run as a whole returns FAIL, and that is the engine working: a corpus carrying a planted defect for every registered control is supposed to fail.
A life-to-date balance presented as a year of activity8. A member contribution column is typed from the equity account balance rather than derived. That account holds every contribution since the entity was formed, so the current-year row now states the whole history, and because the closing total was footed from the same row the schedule agrees with itself, cross-foots, and rolls. Nothing on the page is inconsistent. capital_flow_equals_delta re-derives the row as the current source balance less the prior-year balance for that account and reports the difference against the account it belongs to, and member_capital_chain re-derives the closing from the corrected components -- so the defect is found in the derivation rather than in the arithmetic, which is the only place it exists.
A frozen layer that moved, and a cell nobody declared9. A sort applied to the equity schedule leaves every cell present and the total unchanged, but the frozen history is now in a different order -- and history is supposed to be a constant. frozen_layers_byte_equal compares each prior-year layer against the layer the signed package carried, byte for byte and in order, so the sort is reported rather than absorbed. Separately, a rebuild edits a note the build register does not name. edit_scope_matches_register diffs the built package against the pre-build image and fails the undeclared cell, quoting what it was and what it became; prebuild_image_digest_matches makes that diff meaningful by failing a custody backup that is no longer the one that was taken.
Functional block diagram
engineering · each block links to its sourcePlain terms
- Inputs and Artifacts. the six documents the build is a function of, and the three it emits
- Seeded Build Files. fictional build files enter the builder and then the control registry
- Harvest and Classify. the year is pulled by account number and given its statement shape
- Freeze and Advance. history is carried byte-equal and every rolling caption moves one year
- Flows and Splits. each current-year flow is a movement, and the split is carried down
- Member and E&P Blocks. a new year block per member, book and tax, and a new E and P year
- Evidence and Citation. the harvested rows, the citation that opens them, and a subtotal that foots to zero
- Register and Manifest. every constructed cell beside the derivation that produced it, and three digests
- Custody and Edit Scope. only the cells the register declared are allowed to differ
- Twenty-Four Controls. the registry that proves what the builder built
- Verdict and Findings. every finding, with the derivation behind the cell, ends at a person
Engineering
- Inputs and Artifacts. Six artifacts go in: the locked general-ledger extract with its citation fields and book-to-tax adjustment, scoped to one entity block; the prior year's signed package carrying frozen history, the classification map, last year's equity total, member closings, accumulated earnings and profits and every rolling caption; the allocation register holding the member split pairs in integer basis points by purpose; the exception register naming the account numbers and tie-out differences a reviewer has already accepted; the counterpart stub holding the other side of the investment carried in this block; and the pre-build image, the working file captured immediately before the build ran. Three come out: the built package, the build register naming every constructed cell beside its derivation, and the manifest carrying the locked-source, pre-build and built-package digests.
- Seeded Build Files. generate_corpus writes one clean baseline plus one planted-defect file for every registered control and one for the integer-cents guard, twenty-seven files in all. Only base facts are stated: the locked source accounts, titles and balances, the prior year's frozen layers and captions, the split pairs, the registered exceptions, the counterpart stub and the pre-build image. Everything the controls later read is a constructed figure -- the trial balance, the classified statements, every equity row and its total, each member block book and tax, the earnings-and-profits year, the evidence rows and subtotal and every digest -- produced through the same build kernel the builder and the controls both import. So a defect that changes a base fact rebuilds the package around it and keeps the break confined to one control.
- Harvest and Classify. Current-year balances are harvested from the locked source by exact account number and scoped to one entity block, then classified into a balance sheet and a statement of operations from the prior-year map, footing to zero. An account with no balance carries no figure onto the workpaper and stays on the evidence tab, so completeness is provable rather than assumed, and each row's form -- cumulative residual or year delta -- is decided from the account's balances at both year-ends, never from the formula in the cell.
- Freeze and Advance. Every prior-year layer is carried through byte-equal and in order, and every rolling caption is advanced arithmetically by exactly one year. Order is part of what is carried, because a re-sorted schedule holds the same cells and what a sort actually breaks is the sequence of a frozen history. No history label the prior package carried is allowed to disappear in the roll.
- Flows and Splits. Each current-year contribution and distribution is computed as the current source balance less the prior-year balance for that account, so a life-to-date balance can never be presented as a year of activity. Income rows are allocated on the split carried from the allocation register in integer basis points, each pair summing to exactly one hundred per cent, and the equity total is re-derived as prior total plus flows plus result.
- Member and E&P Blocks. A year block is appended per member -- opening from last year's closing, contributions, ordinary income on the carried split, distributions and closing, in both the book and the tax column -- together with the liability share and outside basis derived as tax capital plus that share. The earnings-and-profits roll-forward gains a dated year: prior accumulated plus current taxable.
- Evidence and Citation. The evidence tab carries the harvested rows with a citation block naming the source file, the tab, the balance column and the harvest date, and a subtotal that is the sum of its rows and has to be zero. Every row ties the locked source by exact account number, so the tab is something a reviewer can open and re-derive rather than a page that merely accompanies the package.
- Register and Manifest. The build register names every cell the build constructed and the derivation that produced it, which is what turns the package from a file into something reviewable cell by cell. The manifest carries three content digests -- the locked source, the pre-build image and the built package -- so a source that moved after the build, or a custody backup that was retaken, invalidates the build rather than quietly passing.
- Custody and Edit Scope. The built package is diffed against the pre-build image and any cell that differs without the build register naming it is a finding, because an edit nobody declared is an edit nobody reviewed. The diff is only meaningful while the image is still the one that was taken, which is why the image digest is a control of its own rather than a note in the manifest.
- Twenty-Four Controls. Twenty-four controls run over every build file: frozen layers byte-equal and in order, captions advanced one year, flows equal to their source-less-prior delta, split pairs summing to one, income rows exact on the split, the equity total rolled and tied to the balance sheet, the member chain closed book and tax and tied to equity, basis as capital plus liability share, the earnings-and-profits chain rolled, beginning retained earnings continuous, row form read from balances, evidence tied to the source and footing to zero, the citation correct, three digests matched, the edit scope inside the register, cross-schedule reciprocity, source completeness, registered exceptions honoured, render hygiene, and history labels intact.
- Verdict and Findings. Findings roll up per build file: any FAIL is FAIL, FLAGs without FAILs are REVIEW, clean is PASS. The CLI exit code is the verdict, so a pipeline can gate on it. Each finding cites the cell and the derivation that produced it, and reports carry no timestamps and no absolute paths, which is what makes the committed report diffable -- a change in the diff is a change in the build or the controls, not a change in when the run happened.
Instruction set
every public command| Command | Operation | Output | Exit | Artifacts |
|---|---|---|---|---|
python run.py | regenerate the seeded fictional corpus, build every package and register, run all twenty-four controls, write both reports | per-file verdicts and every actionable finding, then the overall verdict | 2 for the bundled corpus, which carries a planted defect for every control by design | workpaper_report.json, workpaper_report.md, samples/, out/ |
python -m workpaper_engine samples --build out | rebuild each package from its inputs and write it, with its build register, into a folder | per-file verdicts and findings over what was built | 0 PASS / 1 REVIEW / 2 FAIL / 3 usage | out/ |
python -m workpaper_engine samples --quiet | run the controls over an existing folder of build files and print only the overall verdict | a single verdict line | 0 PASS / 1 REVIEW / 2 FAIL / 3 usage | none |
python -m pytest workpaper_engine/tests -q | run the full test suite for this engine | 10367 passed | 0 when every test passes | none |
Benchmarks
measured demo results| Measure | Result |
|---|---|
| Engine tests10 | 10,367 tests collected live collection from the engine directory |
| Registered controls11 | 24 controls counted from the registry, not from documentation |
| Planted defects12 | 26 defect files every registered control has at least one file that trips it, plus one for the integer-cents guard |
| Control coverage13 | 100 percent of controls with a planted defect no control ships without a file demonstrating it firing |
Control characteristics
engineeringPlain terms
The engine builds a package and proves it; it never signs one. It writes only the artifacts it declares -- the built package, the build register and the manifest -- and never to an input. A person reads the findings and decides whether the year closes on this package, and a disclosed difference is flagged for that person rather than resolved, because whether a disclosure is right is a judgement and not a computation.
Engineering
Deterministic envelope. seeded fictional inputs, offline default mode.
Demo gate. FAIL on the bundled corpus, by design -- it carries a planted defect for every registered control
| Severity | Verdict | Action |
|---|---|---|
| No findings above PASS | PASS | carry the built package into the documented preparer review and the signature that closes the year |
| One or more FLAG, no FAIL | REVIEW | a human resolves each flag; an equity-to-balance-sheet difference the package itself discloses lands here, quantified to the cent, because the engine can confirm the disclosure exists and cannot judge whether it is right |
| One or more FAIL | FAIL | the package is not signed until the failing control is cleared -- a frozen layer that moved, a caption still at last year's date, a flow that is not its account's movement, a member chain that does not close, an evidence subtotal that does not foot, a digest that no longer matches, or a cell edited outside the build register |
- The build is a pure function of its inputs: it never writes to the locked extract, the prior package or the registers, and the controls never write at all, so neither can introduce the break the other reports.
- Integer cents throughout, compared with exact ==; there is no tolerance band on any figure, and because this engine builds the workpaper, a tolerated penny would be frozen into every future year's history.
- Every prior-year layer is carried byte-equal and in order, and compared against the layer the signed prior package carried rather than against arithmetic, because a re-sorted or re-derived history still adds up.
- Every current-year flow is derived as the current source balance less the prior-year balance for that account, never read from a balance, so a life-to-date total can never be presented as a year of activity.
- Each row's form -- cumulative residual or year delta -- is decided from the account's balances at both year-ends and never from the formula in the cell, because a formula survives a copy and a balance does not.
- Member split pairs are carried in integer basis points and every pair must sum to exactly one hundred per cent, so an allocation is exact rather than nearly exact.
- Cells are keyed by row identity and never by position, so a re-sorted schedule holds exactly the same cells and the thing a sort actually breaks -- the order of a frozen history -- has a control of its own.
- The built package is diffed against a pre-build image and any cell that differs without the build register naming it is a finding; the image and the locked source are digest-pinned, so a retaken backup or a moved source invalidates the build rather than passing quietly.
- One derivation kernel: the builder, the generator and the controls all import the same build module, so a control cannot quietly disagree with the pipeline about how a cell was derived, and a planted defect keeps its break confined to one control.
- Every fiscal year and every date is read from the file and never from the system clock, so a run in a later year returns the same package bytes and the same findings.
- Deterministic and byte-stable: the same inputs produce the same built package, the same build register and the same findings in the same order, with no timestamps and no absolute paths in any output.
- An account left off the workpaper must be flat in the locked source, so completeness is proved from the source rather than assumed from the package.
Operating limits
what it refuses to do- The engine builds a package and proves it against its inputs. It never signs a workpaper, files a return, posts an entry or writes to the locked extract, the prior package or any register.14
- It does not resolve classification judgement. Where an account's placement is arguable, the engine reproduces the prior year's map and reports what it built; deciding the map is a person's work.15
- It cannot judge a disclosed difference. Where the equity schedule and the balance sheet disagree and the package discloses it, the finding is flagged and quantified to the cent, and the question of whether the difference is right is left open.16
- It builds from the extract it is given. The ledger pull stays manual and automation begins downstream, so the engine can prove the package ties the locked extract and its own pre-build image but not that the extract is itself complete.17
- All shipped data is fictional. The groups, entity blocks, members, account numbers, titles, balances, splits, citations and fiscal years are invented, and the fiscal years are set in a fictional future.18
See it run
brand animationIntegration
how to run itDistribution: public repository, MIT license.
- 1python -m pytest --collect-only -q -o addopts= (workpaper-build-automation/)
- 2len(workpaper_engine.engine.REGISTRY)
- 3workpaper-build-automation/README.md, the schedule-by-schedule build list
- 4samples/*.json after python run.py
- 5len(workpaper_engine.model.DOC_TYPES)
- 6workpaper_engine/tests boundary tests on every cent
- 7python run.py (workpaper-build-automation/); workpaper_engine/tests planted-defect suite
- 8workpaper_engine/engine.py check_capital_flow_equals_delta; samples/member_contribution_column_typed__Alderpoint_Terraces_Partners.json
- 9workpaper_engine/engine.py check_frozen_layers_byte_equal and check_edit_scope_matches_register; samples/frozen_layer_reordered__Rivermont_Holdings.json and samples/cell_edited_outside_register__Copperfield_Yards_Group.json
- 10python -m pytest --collect-only -q -o addopts= (workpaper-build-automation/)
- 11len(workpaper_engine.engine.REGISTRY)
- 12len(workpaper_engine.generate.DEFECTS)
- 13workpaper_engine/tests: every registered rule has a planted defect
- 14workpaper-build-automation/README.md and workpaper_engine read-only / determinism tests
- 15workpaper-build-automation/README.md out-of-scope statement
- 16workpaper_engine/engine.py check_equity_ties_balance_sheet
- 17workpaper_engine/build.py and workpaper-build-automation/README.md
- 18workpaper_engine/generate.py and workpaper-build-automation/README.md
Show us where the hours go.
One conversation: you describe the work that consumes your team's month; we tell you plainly what this engine can take over, what it can't, and what a scoped first phase would cost. Your people keep approval authority.
Book a free consultation