ENGINE 49
SFS-E49-IRP · INVESTOR REPORTING · REV 2026-07-29 · PRODUCTION
PRODUCTION = runnable end-to-end, CI-backed, full test suite passing. All data fictional and seeded.
JV Investor Reporting Package
Every statement re-derived from the sources that were supposed to produce it, and nothing released over an open exception.
Every month a developer issues a financial reporting package to the joint-venture equity partner of a single project entity: a cover, a trial balance, a balance sheet, a statement of operations, a statement of members' capital, a development cost schedule, a job cost bridge, cash support, notes and a release record. It is assembled by hand, per project, per investor, and the failure mode is a wrong figure sent to an outside partner. This engine reads the five sources that package is built from -- the project entity's general ledger extract, the job cost detail by division, the executed equity draw schedule, the parent entity's ledger carrying the reciprocal investment account, and the package issued for the period before -- and runs twenty-five deterministic controls over the package that came out of them. Does the trial balance net to zero, does it cover every account with activity, and does each balance agree to its ledger account by account number rather than by row position; does the balance sheet balance and is a credit intercompany balance reclassified rather than netted against assets; does each member's capital agree to the ledger, do the contributions foot, does the Total column cross-foot every row, does each member roll forward, and does the result agree to the statement of operations; does the development cost schedule tie to work in process, does the job cost bridge close with every difference itemized and disclosed, is every division covered; do contributions agree per member to the executed draw schedule and does the parent's investment agree to the capital it represents; is a nil statement genuinely nil, is cash supported, does every quoted footnote figure match its cell, does every caption fit its schedule, does the cover agree with what the notes disclose; and are the tie-out rows and preparer artifacts out, does the package continue from last period, is it complete, and was it allowed to leave. It never mutates an input and never posts an entry.
Five of these controls are not hypotheticals. They were written from five genuine defects found during a manual build of one such package -- errors that took three rounds of human review to surface, and none of which looked wrong on the page. A job cost difference absorbed into a rounding line instead of being itemized and disclosed, so the partner receives a figure nobody can rebuild. A contribution column typed from a funding notice rather than footed against the draw schedule the partner also holds, with the variance never quantified. A cost-to-date schedule still carrying a caption saying the cost arose in the period, so a reader adds a month of spend that was really every month since the ground broke -- every figure on the page correct. A cover asserting the package is free of exceptions while the notes disclose one, on the page most readers read closest. A reviewer's own tie-out arithmetic left inside the print area and shipped to the investor as though it were a line of the statement. What these have in common is that the package still foots, still balances and still reads plausibly, so a review that reads the page cannot find them; only re-derivation from the sources can. So the engine joins the package to the ledger on the account number and only on the account number, requires a bridge to close exactly rather than nearly, sums the member columns across every row including the sharing-ratio row, reads either side of an account rather than its net, and holds the whole package on any one open exception -- with no materiality gate, because materiality is a judgement about a figure the partner has not seen yet.
Architecture
functional block stack · static overviewSelect a layer
Seven control areas run in registry order over each package file, twenty-five controls in all. They are ordered the way the package is assembled -- from the trial balance the statements are struck from, out to the release decision that lets it leave -- so a finding lands on the earliest artifact that can explain it.
Key specifications
at a glanceWhat it does for you
plain termsThe monthly investor reporting package is assembled by hand, per project, per investor, from five sources that were never designed to agree with one another. It foots, it balances and it reads plausibly even when it is wrong, because the arithmetic that would expose the error is the arithmetic that produced the figure. Five failures found during a manual build of one such package took three rounds of human review to surface: a job cost difference absorbed into a rounding line rather than itemized and disclosed; a contribution column typed from a funding notice rather than footed against the draw schedule the partner also holds; a cost-to-date schedule carrying a caption saying the cost arose in the period; a cover asserting the package is free of exceptions while the notes disclose one; and a reviewer's own tie-out check row left inside the released print area. None of them looked wrong on the page. All of them were addressed to somebody outside the company.
The seeded demo runs every control over every package file7. The CLI generates twenty-seven fictional package files -- one clean baseline and one carrying each of the twenty-six planted defects -- then runs all twenty-five controls over every file and writes both reports. The clean baseline returns PASS on all twenty-five. Each defect file returns exactly the finding its control exists for, and the run as a whole returns FAIL, which is the engine working: a corpus with a planted defect for every control is supposed to fail. Every defect file is also marked held, because a package with a known exception is held -- a defect file left marked released would trip the release gate as well as its own control, and a corpus in which one break fires two controls cannot prove that either of them is independent. The release gate's own file is the exception, because being released over an open exception is precisely what it is for.
A trial balance pasted beside the ledger instead of joined to it8. The package trial balance is exported in reading order and the ledger extract comes out in account order. Pasted one column beside the other, the package agrees on the rows where the two orders coincide and is wrong everywhere else -- and it foots, it nets, and the balance sheet struck from it balances. tb_agrees_ledger joins on the account number and only on the account number, so each mismatched row is reported against its own account; and where the stated balance does match the ledger account occupying the same row position, the finding says so. That is the fingerprint of a positional paste rather than a posting error, and naming it is the difference between an hour of investigation and a re-export.
A bridge that nearly closes, and a Total that does not sum its row9. jobcost_bridge does not require the job cost report and the ledger to agree; it requires the report plus everything itemized against it to reach the ledger exactly. There is no closing tolerance, because a bridge that nearly closes has an unexplained figure in it, and any reconciling item carried in the bridge without being disclosed fails on its own account. total_cross_foots sums the member columns across every row of the capital statement, including the sharing-ratio row: a Total cell linked to the ledger, to a funding notice or to last period's total instead of summing the row it sits on is right often enough to survive review, and wrong exactly in the month a member column moves.
Functional block diagram
engineering · each block links to its sourcePlain terms
- Seeded Package Files. fictional monthly reporting packages enter the control registry
- Trial Balance. does it net, does it cover the ledger, does it agree by account number
- Balance Sheet. does it balance, and is a credit intercompany balance a liability
- Members' Capital. does every member's column tie, foot, cross-foot and roll forward
- Development and Job Cost. does the schedule tie work in process, and is every difference disclosed
- External Agreement. does the package agree with documents held outside it
- Presentation. does the page say what the figures underneath it say
- Release. is it clean enough to leave, and did it leave anyway
- Sources and Package. the fifteen artifacts and the roles every rule resolves against
- Verdict and Findings. every finding, with the reason it exists, ends at a person
Engineering
- Seeded Package 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 total. Only the base facts are stated: the non-capital ledger accounts, the job cost detail by division, the cost carried in the ledger and not in the cost report, the equity draw schedule, the prior package's closing capital, each member's distributions and sharing ratio, the presentation the statement of operations declares, the cover's assertions, the notes' cell references, the tie-out rows and the artifact list. Everything the engine later checks is a derived figure -- the trial balance, the balance sheet and its section totals, every capital column and the Total across it, the contribution detail, the development cost total, the job cost report total, the bank reconciliation balances, the parent's reciprocal investment and every figure quoted in a note -- computed through the same package kernel and the same recompute helpers the controls recompute with. So a defect that changes a base fact re-derives the package and keeps the break confined to one control.
- Trial Balance. Three controls: the trial balance nets to zero, every ledger account with activity on either side appears in it, and each balance agrees to its own ledger account matched by account number and never by row position -- with a positional paste named as such when the stated figure matches the account sitting in the same row.
- Balance Sheet. Two controls: each section is re-footed from its own rows and total assets must equal liabilities plus members' equity, and an intercompany account in a credit balance is reclassified to liabilities rather than netted against assets -- a netting that leaves the statement balancing and understates both sides by the same amount.
- Members' Capital. Five controls: each member's ending balance agrees to its ledger capital account, contributions foot to their detail, the Total column sums the member columns on every row including the sharing-ratio row, ending is re-derived as beginning plus contributions plus net income less distributions, and net income equals the statement of operations bottom line.
- Development and Job Cost. Three controls: the development cost schedule total equals the ledger work-in-process account, the job cost bridge closes exactly with no tolerance and fails any reconciling item carried without being disclosed, and every division in the report appears in the schedule or in a disclosed reconciling item.
- External Agreement. Two controls: contributions agree per member to the executed equity draw schedule with any variance quantified and only executed draws counted, and the parent entity's investment account equals the project entity's capital account -- the one relationship that has to hold across two sets of books.
- Presentation. Five controls: a nil statement of operations is nil only if every revenue and expense account is nil, unsupported cash is flagged rather than failed because the engine cannot manufacture a bank statement, every figure quoted in a note equals the cell it describes, every schedule's caption fits its type, and the cover's basis-of-presentation assertions are consistent with every disclosed exception.
- Release. Five controls: internal tie-out check rows are excluded from the released print area, no preparer-only artifact ships, opening balances equal the prior package's closing balances, every statement named in the contents exists and is non-empty, and the package is held unless every control above passes.
- Sources and Package. Five source documents go in -- the project entity's general ledger extract, the job cost detail by division, the executed equity draw schedule, the parent entity's ledger carrying the reciprocal investment account, and the package issued for the period before. Ten make up the package itself: the cover with its contents list and basis-of-presentation assertions, the trial balance, the balance sheet, the statement of operations, the statement of members' capital, the development cost schedule, the job cost report and its bridge, the cash support, the notes, and the release record. Ledger accounts carry a declared role -- cash, work in process, intercompany or capital -- so every control locates the accounts it needs by role rather than by name or position, and each schedule declares its type so a caption can be tested against what the schedule actually is.
- Verdict and Findings. Findings roll up per package 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. 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 controls, not a change in when the report was run.
Instruction set
every public command| Command | Operation | Output | Exit | Artifacts |
|---|---|---|---|---|
python run.py | regenerate the seeded fictional corpus, run all twenty-five 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 | investor_report.json, investor_report.md, samples/ |
python -m investor_engine samples | analyze an existing folder of package files without regenerating it | per-file verdicts and findings | 0 PASS / 1 REVIEW / 2 FAIL / 3 usage | none unless --json or --md is passed |
python -m investor_engine samples --generate --quiet | regenerate the corpus and print only the overall verdict | a single verdict line | 0 PASS / 1 REVIEW / 2 FAIL / 3 usage | samples/ |
python -m pytest investor_engine/tests -q | run the full test suite for this engine | 10432 passed | 0 when every test passes | none |
Benchmarks
measured demo results| Measure | Result |
|---|---|
| Engine tests10 | 10,432 tests collected live collection from the engine directory |
| Registered controls11 | 25 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 has no write path and therefore no autonomy to gate. It produces findings; a person decides whether the package goes to the partner. There is no materiality threshold, because materiality is a judgement about a figure the partner has not seen yet.
Engineering
Deterministic envelope. seeded fictional inputs, read-only operation, 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 mechanically clean package into the documented preparer review and partner sign-off before it is issued |
| One or more FLAG, no FAIL | REVIEW | a human resolves each flag; cash whose bank reconciliation has not arrived or does not agree lands here, because the engine can see the support is absent and cannot manufacture it |
| One or more FAIL | FAIL | the package does not go to the partner until the failing control is cleared -- a balance off its ledger account, a bridge difference carried undisclosed, a contribution that does not agree to the executed draws, a Total that does not sum its row, a caption that misstates its schedule, a cover that contradicts the notes, or a check row inside the print area |
- Read-only: package files are parsed and never written back, so the engine cannot introduce the break it reports, and it never posts an entry.
- Integer cents throughout, compared with exact ==; there is no tolerance band on any figure, and a penny off the re-derivation is reported as a break.
- Package balances are matched to the ledger by account number and never by row position, and a stated figure that matches the account in the same row position is named as a positional paste rather than reported as an unexplained difference.
- Completeness reads either side of a ledger account and never its net, so a clearing account that took in an amount and released the same amount cannot be dropped behind a nil balance.
- The job cost bridge must close exactly rather than within a tolerance, and a reconciling item carried in the bridge without being disclosed fails on its own account.
- The Total column is summed across every row of the capital statement, including the sharing-ratio row, so a Total cell linked elsewhere instead of summing its row is caught in the month it first disagrees.
- One derivation kernel: the controls and the generator share the same package module and the same recompute helpers, so a stated figure cannot disagree with the logic that produced it, and a planted defect keeps its break confined to one control.
- Only executed equity draws are treated as contributions; a scheduled or cancelled draw is never counted, and any variance against the executed schedule is quantified rather than reported as a bare mismatch.
- A figure that should be integer cents but is not produces an AMOUNT_INVALID finding contained to the one field it was read on, rather than being coerced into the number the engine is meant to audit.
- Every executed draw is tested against the reporting period the file carries, never against the system clock, so a run in a later month returns the same findings.
- Deterministic and byte-stable: same inputs produce the same findings in the same order, with no timestamps or absolute paths in any output.
- Absent evidence is never a passing control; a statement named on the contents page and missing from the package fails completeness rather than letting the controls that read it report nothing and pass unread.
Operating limits
what it refuses to do- The engine never assembles a package, issues a statement, posts an entry or writes to a source artifact. It reads the package file and stops.14
- It does not resolve classification judgement. Where the ledger labels a cost one thing, the payment went somewhere else and the draw schedule calls it a third, the engine reports that two sources disagree and must not pick a winner.15
- It cannot manufacture a document that does not exist yet. Cash whose bank reconciliation has not arrived is raised as a FLAG and left to a person; the engine reports the absence and never fills it.16
- It writes no disclosure wording. Whether and how to tell the partner about an exception is a decision, not a computation; the engine insists the difference is quantified and disclosed, and writes none of the sentence.17
- It audits the extract it is given. The ledger pull stays manual and automation begins downstream, so the engine can prove the package ties to the extract but not that the extract is itself complete. All shipped data is fictional -- the project entities, the members, the chart of accounts, the divisions of job cost, the equity draws, the notes and every balance and reporting date are invented, and the reporting period is 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= (investor-reporting-automation/)
- 2len(investor_engine.engine.REGISTRY)
- 3investor-reporting-automation/README.md control table, summing to the registry
- 4samples/*.json after python run.py
- 5len(investor_engine.model.DOC_TYPES)
- 6investor_engine/tests boundary tests on every cent
- 7python run.py (investor-reporting-automation/); investor_engine/tests planted-defect suite
- 8investor_engine/engine.py check_tb_agrees_ledger; samples/balance_taken_by_position__Alderpoint_Terraces.json
- 9investor_engine/engine.py check_jobcost_bridge and check_total_cross_foots; samples/bridge_difference_undisclosed__Dunmore_Flats.json and samples/total_row_links_elsewhere__Alderpoint_Terraces.json
- 10python -m pytest --collect-only -q -o addopts= (investor-reporting-automation/)
- 11len(investor_engine.engine.REGISTRY)
- 12len(investor_engine.generate.DEFECTS)
- 13investor_engine/tests: every registered rule has a planted defect
- 14investor-reporting-automation/README.md and investor_engine read-only / determinism tests
- 15investor-reporting-automation/README.md out-of-scope statement
- 16investor_engine/engine.py check_cash_supported
- 17investor-reporting-automation/README.md out-of-scope statement
- 18investor_engine/generate.py and investor-reporting-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