The business caseThe problem this solves
An acquisition sends an estoppel certificate to every tenant in the building and gets them back over three weeks, filled in by whoever happened to be at the tenant's desk. Somebody then has to sit with each one beside the buyer's own abstract and rent roll and answer, item by item: is this what our file says, and if it is not, is the tenant TELLING US SOMETHING — an abatement, an amendment, an option they exercised, a landlord default — or did one of the two documents get typed wrong? The two are the same difference on the page and completely different findings. One is a claim against the file that changes what the buyer is buying; the other is a reconciliation item. And the third answer nobody counts is the item the tenant did not certify at all, which looks exactly like agreement when the box is filled in and the remark beside it quietly withdraws it. Reading a returned estoppel against an abstract extract by eye, item by item, deciding from the tenant's own free text whether a difference is a claim or a typo, and doing the subtraction. It does not replace the decision: every exception goes to a person, and nothing here accepts, rejects, returns or re-issues an estoppel, amends an abstract or a rent roll, or touches the transaction.
Audience
Acquisitions and due-diligence analysts, asset managers and the lease-abstraction team that produced the file the certificate is being checked against. Every number on these pages came from one real run of this code, not from a vendor page.
The inputThe actual returned tenant estoppel certificates
The corpus is 62 returned tenant estoppel certificates, 0.13 MB (json 4 · jsonl 1 · md 1 · txt 62). Because the job is a judgement about prose sitting beside two columns of structured data, and that is the only shape on which the free floor and the paid call can be told apart. 343 of the 372 items are settled by the two printed columns alone — a box that carries one of the legend's non-answers, a figure that matches the file, a figure that does not — and 29 are not. Those 29 are the whole kit: 16 of them look like AGREEMENT to a column reader, 11 look like a plain recording difference, and 2 look like an open item. Every one of them turns on the tenant's own free text and on nothing else.
The corpus
- The 62 returned tenant estoppel certificatesgenerated from a fixed seed, so no real record, person or institution appears in it.
- Where each came fromNowhere — all 62 certificate packets, data/abstracts.json and the whole answer key are generated in-process by the file that sits beside them. Every property, suite, tenant, landlord, managing agent, certificate number, amount, date and remark is invented, and there is no personal data in it. ESTOPPEL-2026 is invented too and is not a statute, a title standard or anybody's diligence manual. See data/SOURCES.md.
Swap this folder for your own material and the kit is pointed at your returned tenant estoppel certificates. That is the whole change — there is no database to migrate.
TENANT ESTOPPEL CERTIFICATE - RETURNED, WITH THE BUYER'S ABSTRACT EXTRACT
CERTIFICATE HEADER
Certificate EC-0001
Property Northgate Exchange, Tower 2
Suite Suite 310
Tenant Sablecreek Coffee Roasters
Landlord Tarrenfield Industrial LP
Managing agent Halloway & Pike Management
Requested 2026-08-07
Returned 2026-08-16
Signed by S. Molyneux, Finance Lead, for the Tenant
ABSTRACT EXTRACT (the buyer's own file for this suite, from the lease abstract and the rent roll)
# Item Kind File value
1 Monthly base rent now payable money $8,760.00
2 Security deposit held by landlord money $26,280.00
3 Prepaid rent held by landlord money $8,760.00
4 Lease expiration date date 2029-01-31
5 Renewal options remaining count 0
6 Landlord in default under the lease yes-no No
CERTIFIED BY THE TENANT (the boxes exactly as they came back on the certificate)
A box left unfilled is printed --. The entries --, As per lease, See lease, To be confirmed and Not known certify nothing.
# Item Certified
1 Monthly base rent now payable $8,760.00
2 Security deposit held by landlord $26,280.00
3 Prepaid rent held by landlord $8,760.00
4 Lease expiration date 2029-01-31
5 Renewal options remaining 0
6 Landlord in default under the lease No
TENANT'S REMARKS (free text the tenant added beside an item; an item with nothing written beside it does not appear here)
The tenant added no remark against any item.
REMARKS TO LANDLORDAbridged — the file continues.
The outcomeWhat a good result looks like
One returned certificate in, one line per certified item out: what the tenant actually certified, whether it is what the file carries, and where it is not, whether the tenant is asserting a different fact or the two documents are recording the same fact differently — with the row it turns on quoted verbatim out of the packet and a signed dollar difference on every money item. The disposition, the exception list, the monthly rent at issue and the balances at issue follow in pure code.
And when it cannot
⚠︎ THE MEASURED FAILURE DIRECTION IS THE QUOTE, NOT THE FINDING. On the published run the verdict is right on 370 of 372 items and every one of the 372 money amounts is right to the cent with its sign; what fails is the citation, on 9 items — 6 rows quoted where the item AGREES and the contract says null, 2 quotes that do not appear in the packet at all, and 1 below the coverage floor. A reviewer reading a determination sees a quote beside an item that agrees. That is what caps item, all six right at 357 of 372 while the verdict column reads 370.
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 tenants return the requested form, fill in every box, and almost never write in the remarks column. — the free column floor alone — evals/run.py --floor rules
Every item is then a lookup, a comparison and one subtraction. The floor is 343 of 372 item verdicts and 33 of 62 certificates for $0.00, no key and no network. - Your tenants write in the remarks column, and what they write is sometimes about a different suite, a lease you do not hold, or an abatement that ended two years ago. — the paid call, rechecked
That is the only place it separates from a floor a forker could actually write: 28 of the 29 reading-required items against the de-memorised keyword floor's 4, and 53 of 62 certificates against its 37, exact two-sided p = 0.0037. - You want the reply itself to be the artefact — verdicts, amounts and quotes, as written, with no post-pass. — the reply plus src/recheck.py, which is the product
The station discards the verdict, the term, the amount, the disposition, the exception list and both totals and recomputes all six from the arm's two readings. On this run the two columns are close — 370 against 369 item verdicts — which is itself the measurement: the arm's own arithmetic was already right. - Your diligence file already holds the amendment stack for every lease. — the free column floor, and read data/SOURCES.md first
Then a remark naming 'the Third Amendment' stops being a reading and becomes a lookup, and a large share of the 29 items this kit pays for stop being questions.
At a glanceHow the whole thing runs
Run once, for real, on 2026-09-09. 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? | Render your own certificates into the same panel layout — CERTIFICATE HEADER, ABSTRACT EXTRACT, CERTIFIED BY THE TENANT, TENANT'S REMARKS, REMARKS TO LANDLORD, EXECUTION — drop them in data/corpus/, put your own item catalogue in data/policy.json and your own rules in data/policy.md, and run the free floors first. What you will NOT have is a key. Corpus lens → |
| When is this the wrong choice? | Avoid: Paying for a reading you do not need, once per tenant, on every acquisition. That is the case against the best-fitting scenario (“Your tenants return the requested form, fill in every box, and almost never write in the remarks column.”). 4 scenarios scored in all, each with its own. Eval lens → |
| Where does it stop working? | A certificate returned on the tenant's own form rather than the requested one. The parser is a fixed-column regular expression over a fixed layout and a different layout parses to no items at all. 6 recorded failure modes, each from a run rather than a guess. Corpus lens → |
| What was never verified? | ONE SCORED RUN. A repeat on the identical gold set at the identical tier is the cheapest thing this kit could buy next — 62 calls, about $0.05 off peak — and until it exists nothing here separates run-to-run variance from a real difference. 5 items this kit says it could not check. Eval lens → |
| Can I run this on a model I control? | The shipped adapter is one provider, one key, reached only through src/adapters/; the Prompt lens states what swapping it costs. The published figures come from 1 model on the fast tier, reasoning disabled (THE PUBLISHED RUN). Prompt lens → |
| And if it fits — what do I stand up? | 4 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-09 — r001-estoppel-compare. 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 — Clone, no key, no network: python3 tools/build_corpus.py --check (byte-identical rebuild), python3 -m evals.check_labels (343 verified, 29 declared unverifiable, 0 problems), python3 -m evals.baseline (all four floors), python3 -m evals.run --run-id t000-estoppel-compare-stub --stub (the whole pipeline end to end), and python3 -m src.app for the board. The committed scored run replays off its result file. Nothing in that list opens a socket.




