The business caseThe problem this solves
A season-ticket plan is a schedule of dates and amounts the member agreed to, and a ledger of what the box office managed to take. The two drift apart quietly: a card settles and the bank takes it back a fortnight later, a payment lands against the household's other account and the overnight job matches it here, a decline is retried and both halves get posted, a catch-up covering three instalments is keyed as "3", and somewhere in the account notes a member asked to move to the extended plan and was quoted a figure they never took up. The arrears number the system prints is right on most accounts and wrong on some of them, and the only record of which is a sentence written under a ledger row. On this corpus the printed panel is wrong about what settled on 21 of 62 accounts and wrong about the verdict on 20. Opening one account's plan file, adding the schedule up to today by hand, adding the settled column up, reading each note printed under a posting to decide whether the money is actually there, hunting the account notes for a re-schedule and deciding whether it was applied or merely offered, then working out how far back the first unpaid instalment goes. It does not replace the decision about the seat, and it does not take a payment.
Audience
A venue's membership or ticketing desk working an arrears list before a renewal window, and the finance analyst behind it. Whoever has to answer a committee asking which season-ticket accounts are behind on their plan, by how much, and for how long — and has to be able to point at the ledger row for every figure. Every number on these pages came from one real run of this code, not from a vendor page.
The inputThe actual plan reconciliation files
The corpus is 62 plan reconciliation files, 0.17 MB (txt 62). It is generated because it has to be. A real plan ledger is a member's own payment history and a club's own trading record, and the exact shapes this kit measures — a settlement the bank took back, a payment matched to the wrong household account, a re-schedule that was quoted and refused — are rare, scattered and identifying. Generating them means the case mix is known rather than hoped for: 21 of 62 files carry a ledger the office got wrong, 6 carry a plan change the printed schedule does not show, 14 carry a note about a reversal OF SOMETHING ELSE that must not move the total, and 10 carry a re-schedule that was never applied. It also means every number on this page is reproducible by anybody with the repo and no key.
The corpus
- The 62 plan reconciliation filesgenerated 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 venue is an invented trading name printed with
(invented)beside it; account numbers, plan codes, instalment ids, posting ids and authorisation references are arithmetic on the file index. evals/check_labels.py sweeps every file for five families of identifier on every run and reports 0.
Swap this folder for your own material and the kit is pointed at your plan reconciliation files. That is the whole change — there is no database to migrate.
==============================================================================
SEASON TICKET PLAN RECONCILIATION FILE SPR-0001
Venue: VEN-3102 - Copperfield Park (invented)
Account: ACC-40011 Plan: PL-6007 Season: 2026-27 As of: 2026-04-08 Procedure: SPR-2026
==============================================================================
ACCOUNT AND PLAN AS THE MASTER HOLDS IT
seats 6
plan total 2400.00 as issued
instalments 10 as issued
tolerance 25.00 in money, both directions
arrears threshold 400.00 or more
days threshold 30 days or more
PLAN SCHEDULE AS ISSUED
INSTALMENT DUE DATE AMOUNT
INST-0001 2026-01-15 240.00
INST-0002 2026-02-15 240.00
INST-0003 2026-03-15 240.00
INST-0004 2026-04-15 240.00
INST-0005 2026-05-15 240.00
INST-0006 2026-06-15 240.00
INST-0007 2026-07-15 240.00
INST-0008 2026-08-15 240.00
INST-0009 2026-09-15 240.00
INST-0010 2026-10-15 240.00
PAYMENT LEDGER AS POSTED BY THE TICKETING OFFICE
PAYMENT DATE AMOUNT KIND STATUS APPLIED REF MEMO
PAY-0100 2026-01-15 240.00 instalment SETTLED INST-0001 AU-40000 scheduled charge to the card on file, authorisation AU-40000
NOTE: the duplicate posting the member queried was on the prior season plan and was backed out then; this line is the only posting for this instalment.
PAY-0101 2026-01-19 240.00 instalment DECLINED INST-0001 AU-40007 presentation declined by the issuer, response code 51Abridged — the file continues.
The outcomeWhat a good result looks like
One account in, one row out: which postings this procedure treats differently from the ledger that printed them (each with its ledger row quoted verbatim), whether a plan change was in force, and then — derived in code, never taken off the reply — the amount due to date, what actually settled, the arrears, the age of the oldest unsatisfied instalment and one verdict.
And when it cannot
And what it does when it cannot. On the scored run 62 of 62 replies parsed and nothing stopped at the ceiling, so there is no unparsed column to report. A reply that does not parse is counted WRONG and stays in the denominator; it is never re-fired. A cited posting id that is not on the file is dropped by the station and counted (0 on this run). A plan change whose date, code or amount will not parse is dropped WHOLE and the printed schedule stands (0 on this run).
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.
- An arrears list before a renewal window — the paid call
it names each account behind, by how much and since when, and quotes the ledger row for every posting it treats differently from the system. 53 of 62 accounts whole against the best free code's 35, paired p 0.000912. - A ledger with no notes under its rows — free code
the reading lives in the sentence. With no sentence the column parser and the paid arm answer the same thing, and one of them is free. - Deciding whether to release a seat — a person, with this kit's row in front of them
it reports the state of a plan and refuses every disposition. SP-2 puts an account on a review list; a person decides what happens to the seat. - Telling a member what they are entitled to — somebody who has done the research
it states nobody's rights or obligations, by design and in code. The research behind any such claim is owed and unwritten. - Taking the payment — your own payment system
no money moves. No card is charged, re-presented, refunded or credited anywhere in the pipeline, and the answer schema offers no field that could express it.
At a glanceHow the whole thing runs
Run once, for real, on 2026-09-11. 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 plan files in the same shape and data/accounts.json with your own register, then rebuild the key with tools/build_corpus.py or label it yourself in the same gold.jsonl shape. ⚠︎ WHAT STOPS BEING TRUE THE MOMENT YOU DO. Corpus lens → |
| When is this the wrong choice? | Avoid: Reading the headline as a per-field result. The arm's own arithmetic is right on 39 of 62; the pure-code station is what carries it to 53, and the station is free. That is the case against the best-fitting scenario (“An arrears list before a renewal window”). 5 scenarios scored in all, each with its own. Eval lens → |
| Where does it stop working? | A ledger that is not fixed-width columns. src/ledger.py's row regex is the shape these files print; a CSV export or a PDF statement needs a different parser and nothing else. 6 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 unclaimed. 8 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? | 6 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-11 — r001-seasonplan-recon. 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 checkout with no key configured renders the whole board, all four free floors, all seven committed runs and every screenshot. tools/build_corpus.py --check, python3 -m evals.check_labels and every free arm run with no network at all.







