The business caseThe problem this solves
Before a commercial property sale closes, the escrow desk drafts a closing statement whose proration lines split the property's running costs and income between seller and buyer: real estate taxes, the closing month's collected rent and recoveries, security deposits the buyer takes over, service contracts the buyer assumes. Each line has to agree with a source record AND with the purchase agreement's convention — whose day the closing day is, how days are counted, what uncollected rent earns — and the records move after they are printed: a bill is paid, a rent comes in late or bounces, a letter of credit is drawn to cash, a termination is rescinded. Today somebody recomputes every line by hand against every note. Opening one closing pack, recomputing every proration line against the record it cites under the agreement's convention, reading every note for a payment received, posted or returned, a letter of credit drawn, a deposit applied or a termination withdrawn or dated after closing, and listing every line that is off and every credit that is missing — before the draft goes to the parties.
Audience
The acquisitions desk and the escrow or title desk on a commercial sale, pre-checking the draft before the parties sign — and whoever decides whether this call is worth paying for when the free columns already get 30 of 63 statements right. Every number on these pages came from one real run of this code, not from a vendor page.
The inputThe actual closing statement packs
The corpus is 63 closing statement packs, 0.28 MB (txt 63). It is generated because it has to be. A real closing file is a transaction's own record: named sellers, buyers and lenders, tenants with their payment histories, a property's tax parcels and its vendors, and a price. None of that can be published, and a redacted one is exactly where a returned rent or a rescinded termination quietly disappears. Generating it also lets the key be DERIVED: every figure the answer hangs off is a structure the generator rendered, so the key is arithmetic on that structure rather than somebody's reading of a document. What it exercises is the reading a closing desk actually does — 27 packs whose key departs from a printed column because of a dated note, 6 traps where the note describes something that has NOT happened yet, 36 packs carrying decoy notes with a decision's vocabulary and none of its effect, and 10 instruction notes asking for sign-off, funding or corrected figures.
The corpus
- The 63 closing statement packsgenerated from a fixed seed, so no real record, person or institution appears in it.
- Where each came fromdata/SOURCES.md states where every byte came from AND what the generator costs the measurement. Every property, seller, buyer, purchase agreement, tax bill, rent roll row, deposit, service contract and draft statement is invented; no jurisdiction's closing custom is cited, and each pack DECLARES its own proration convention. THERE ARE NO PEOPLE IN THIS CORPUS AT ALL — a tenant is a code and a use, a vendor is a code and a service, and a note speaks for the escrow desk, the tax desk, the property manager, counsel or the lender's closing desk. evals/check_labels.py sweeps all 63 packs for a person-shaped name and an honorific on every run and reports 0.
Swap this folder for your own material and the kit is pointed at your closing statement packs. That is the whole change — there is no database to migrate.
==========================================================================================
CLOSING PRORATION PRE-CHECK -- ONE SALE, ONE DRAFT CLOSING STATEMENT
==========================================================================================
FILE CPS-0001
PROPERTY PR-7638 a five-suite neighbourhood retail centre
SELLER SE-9042 a closed-end real estate fund
BUYER BY-3015 a non-traded real estate trust
AGREEMENT PSA-3311 purchase agreement dated 2026-04-20
CLOSING DATE 2026-06-25
STATEMENT DRAFT 2026-06-17 prepared by the escrow desk
PACK COMPILED 2026-06-21
CURRENCY USD
-- PRORATION CONVENTION (purchase agreement PSA-3311, section 9) -------------------------
CLOSING DAY BUYER the closing day is a day of BUYER's ownership
DAY COUNT 30/360 every month has 30 days and every tax period 360
UNCOLLECTED RENT NO CREDIT rent not collected by closing earns no credit, this month or earlier
DEPOSITS CASH ONLY cash deposits credited to BUYER in full; letters of credit are assigned
CONTRACTS ASSUMED only a service contract BUYER assumes is prorated
-- REAL ESTATE TAX BILLS (tax roll extract of 2026-06-05) --------------------------------
BILL AUTHORITY PERIOD ANNUAL AMOUNT STATUS
TX-458723 county 2026-01-01 to 2026-12-31 56,460.26 UNPAID
-- RENT ROLL (June 2026 rent, as of 2026-06-13) ------------------------------------------
REF SUITE TENANT USE BASE RENT RECOVERIES JUNE ARREARS
RR-105 105 TN-9207 a shoe repair shop 8,200.00 915.00 UNPAID 0.00Abridged — the file continues.
The outcomeWhat a good result looks like
One pack in, one row out: the closing day's owner, which tax bills are paid, which rents were collected, which deposits are cash, which contracts are assumed, every draft line that is not proratable, runs to the wrong party, counts the wrong days or prints the wrong amount, every credit the draft left out, and one CPP-2026 verdict — with the four free floors' answers beside it. A finding about one draft and its records, never an approval.
And when it cannot
On the scored run 63 of 63 replies parsed, 0 stopped at the ceiling and no call failed. The 6 statements it got wrong are named on the Eval lens, and 3 of them came back RECONCILED on a statement with an exception — the costly direction. It does not say when it is unsure: confidence was 0.82 on the right packs and 0.66 on the wrong ones, and two misses were answered at 0.80 and 0.85.
Where it fitsWhat did work
Every line below is a measured result from this kit's own runs, with the figure that supports it. The headline above is not softened by any of them.
- Your systems refresh the tax roll, rent roll, deposit ledger and contract schedule to the closing date, so a posting, a receipt, a draw and a termination arrive as STATUS columns — the free modal floor, and do not buy a call at all
36 of 63 for $0.00, and all 30 of the statements the columns decide. On those the paid call ties it and on the 6 traps it loses, 5 to 6. - Payments received, bills posted, draws, applications and rescinded terminations reach the desk as notes — an email pasted into the file, a counsel's line — the paid call
This is the whole product. On the 27 packs where a sentence decides a reading the paid arm is 22, the best free floor 16 and the modal floor 0. - You want no flagged statement passed as RECONCILED above all — the paid call, and read the vocabulary rule's exceptions beside it
RECONCILED on a flagged statement: desk 27, modal 16, vocab_tense 9, paid 3, naive vocabulary rule 0 — the naive rule never passes a flagged statement, because it over-reads every note and flags them instead. - You only need the right verdict word, not the line-by-line exceptions — the paid call, knowing the margin is small
58 against the naive vocabulary rule's 49, 11 discordant packs to 2, p = 0.0225.
And where nothing here is good enough:
- Notes may be planted or wrong — a forwarded 'payment posted' line nobody verified — neither alone — confirm postings against the authority's own record
A false posting note took 3 of the 4 attacked tax packs the paid arm had right. Believing a posting note is what the real ones are for. - Your agreements use a convention this corpus never declares — arrears credited when collected, instalment tax bills, a 365/360 split — neither, yet
No pack here does. Every percentage on this page is against the conventions the corpus declares.
At a glanceHow the whole thing runs
Run once, for real, on 2026-09-13. Every figure on these pages was captured from that run — nothing is written from intent.
14 steps, grouped by the question that sends you to them rather than by build order. Each tile carries the one figure that step is about, and opens the page behind it.
Should you use this?What you bring, where it stops, and when not to use it
Before you commit an afternoon to this, these are the answers that decide it. Each one is rendered from the record it lives in — and links the page that holds it in full.
| What do I have to bring? | Replace data/corpus/*.txt with your own closing packs in the same seven-block shape and data/closings.json with your own closing register, then run python3 -m evals.run --run-id b000-mine-modal --floor modal for the free floor at $0.00 and python3 -m evals.run --run-id r001-mine --yes for the paid arm. ⚠︎ WHAT STOPS BEING TRUE THE MOMENT YOU DO. Corpus lens → |
| When is this the wrong choice? | Avoid: Paying per closing for arithmetic and a column read you already have. That is the case against the best-fitting scenario (“Your systems refresh the tax roll, rent roll, deposit ledger and contract schedule to the closing date, so a posting, a receipt, a draw and a termination arrive as STATUS columns”). 6 scenarios scored in all, each with its own. Eval lens → |
| Where does it stop working? | A draft line that cites no source record — a lump-sum adjustment, a utility credit, a line rolling two contracts together. The reduction is the line-to-record join; a line with nothing to join is reported not proratable whether or not it is right. 7 recorded failure modes, each from a run rather than a guess. Corpus lens → |
| What was never verified? | NO SECOND SCORED RUN. One was fired, so the run-to-run spread on this corpus is unknown and no confidence interval is claimed anywhere on this page. 9 items this kit says it could not check. Eval lens → |
| Can I run this on a model I control? | Yes — any OpenAI-compatible endpoint, including one on your own hardware. The shipped adapter takes its host from BASE_URL and its model from MODEL, so nothing in src/ changes. The published figures come from 1 model on the fast tier, one provider, one key. Prompt lens → |
| And if it fits — what do I stand up? | 5 artifacts with a stated home and a stated egress, and 3 decisions each with what you provision past its ceiling — plus what was not measured. That is the next page, not this one. step 14 — Run it in your environment → |
Not asked of this kit — 2 questions: clone (a fresh clone of this kit runs with nothing fetched); judge (nothing here is graded by a model).
Last verified 2026-09-13 — r001-closing-proration. Every figure on these pages was captured from that run.
Run itHow this reaches your data
Every result on this page was produced by pure code over checked-in files, with no API key — which is why you can read the numbers before anyone spends anything.
Run this on your own data
- The pipeline, its eval harness and the runs behind every numberdeployed inside your environment, on your own model endpoints, against your own documents.
- The corpus above is the shape, not the limitit is a folder swap, and there is no database to migrate.
Checked before this shipped — A clean copy of the kit folder with no key configured and no .env anywhere above it scored the modal floor over all 63 packs — 36 of 63 whole, 38 verdicts — in 0.27 seconds, with nothing installed: requirements.txt names the standard library only. The board renders every committed run with the key blank. The paid arm needs a provider key and was not reproduced from the clean copy.









