Home › Use Cases › Check a suite licence invoice against its own fee schedule
Use caseUC0330
🧪 Use-case kit · runnable

Check a suite licence invoice against its own fee schedule

A small, forkable project that does one job end to end. Run once for real, and every figure on these pages captured from that run.

The business caseThe problem this solves

A club sends a suite licensee one annual invoice for a premium-seating licence, and somebody on the licensee's side has to read it against the licence. The licence sets a base annual fee in year one and an escalator that lifts every rate in the fee schedule, compounding, in each later year; it includes a stated allowance of suite tickets, parking passes, catering credit and attendant service per home date; and it prices post-season home dates higher than regular-season ones. So every line has to be checked against a licence year, a closed list of charge codes, an allowance that must be netted first, a rate that is a base-year figure escalated to this year, and one multiplication — and two of those checks turn on a fact the invoice does not print. Reading every invoice line against a licence term record, a fee schedule and an escalator by eye; deciding from the line's own prose whether the licence already paid for it and what kind of fixture the date was; and compounding a base-year rate to the current licence year in whole cents. It does not replace the conversation with the club — a QUERY goes back with the lines named and a person owns it.

Audience

A finance or premium-seating reviewer at the licensee — a corporate suite holder's controller, a sponsorship or hospitality manager — who receives one annual invoice per licence and has the licence itself to check it against. Every number on these pages came from one real run of this code, not from a vendor page.

The inputThe actual annual suite licence invoices

The corpus is 62 annual suite licence invoices, 0.21 MB (json 3 · jsonl 1 · md 2 · txt 62). Because the shape of a suite-invoice failure is not the arithmetic, and a corpus made only of arithmetic would measure the wrong thing. 260 of the 277 lines are settled by the columns alone — a date against a licence year, a code against Schedule 3, a base-year rate compounded to this year, one multiplication — and 17 are not. On those 17 the invoice agrees with itself perfectly and the answer is in the line's own narrative: 9 where the Basis column puts a charge on the wrong side of Clause 5's allowance, and 8 where the Class column names the wrong kind of fixture. That split is DERIVED rather than asserted — the builder parses its own rendered output back with the column reader and calls a line reading-required when the column answer differs from the key.

The corpus

  • The 62 annual suite licence invoicesgenerated from a fixed seed, so no real record, person or institution appears in it.
  • Where each came fromNowhere — all 62 invoices, data/licences.json and the whole answer key are generated in-process by the file that sits beside them. Every licensee, club, venue, suite, licence number, invoice reference, charge code, item name, fixture, date, rate, narrative and signature is invented. PSL-2026 is invented too and is not a league rule, a venue's real premium-seating terms or anybody's suite licence. See data/SOURCES.md.

Swap this folder for your own material and the kit is pointed at your annual suite licence invoices. That is the whole change — there is no database to migrate.

One annual suite licence invoice, as the model receives itSI-0001.txt · 1 of 62
SUITE LICENCE INVOICE - ANNUAL, AGAINST THE LICENCE'S OWN FEE SCHEDULE

INVOICE HEADER
  Invoice            SI-0001
  Licence            PSL-3100-01
  Licensee           Aldenmere Logistics Group
  Club               Quarrenden Rovers
  Venue              Quarrenden Park
  Suite              Suite 214, Club Level
  Invoice date       2027-01-05
  Raised by          M. Hallberg, for Quarrenden Rovers

LICENCE TERM RECORD (the club's own record of the licence this invoice is billed under)
  Initial licence year     2025-01-01 to 2025-12-31
  Current licence year     2026-01-01 to 2026-12-31
  Licence year number      Clause 3: licence year 2 of 10
  Base annual licence fee  $138,500.00, the licence year 1 rate in Schedule 3
  Annual escalator         Clause 7: 2.50 pct, compounding, one lift for each licence year after the first
  Included entitlements    Clause 5: 12 suite tickets, 3 parking passes and a food and beverage credit of $1,000.00, being 10 catering blocks, per home date, and attendant service on every home date
  Post-season              Clause 9: a home date is post-season only where it is a play-off, wild-card, divisional, conference or final-series fixture

FEE SCHEDULE (Schedule 3, BASE-YEAR rates for licence year 1; every rate is escalated to the licence year above)
   CODE Item                                                 Per           Regular season    Post-season
   LIC  Annual suite licence fee                             licence year     $138,500.00    $138,500.00
   TKT  Suite ticket above the included allowance            ticket               $136.00        $257.00
   PKG  Parking pass above the included allowance            pass                  $74.00        $101.00

Abridged — the file continues.

The outcomeWhat a good result looks like

Every line of the invoice carries a verdict, the licence term it rests on, the amount at issue to the cent WITH ITS SIGN, and one row copied verbatim out of the invoice as evidence; the invoice carries PASS or QUERY, the queried lines in order, and the total. Nothing here issues a credit, re-invoices, approves or holds a payment, quotes a corrected rate, waives a clause or touches the licence.

And when it cannot

⚠︎ THE INVOICE-LEVEL NUMBER IS 4 OF 62 AND THAT IS NOT A TYPO. order_all_correct demands every field on every line AND the recommendation, the queried set and the total. One behaviour caps it: the answer contract and the quoting rule both say a line that ties has no row to cite and must return null, and the reply quoted a row on 131 of the 277 lines anyway. The recommendation alone is 53 of 62 rechecked and the queried-line set is 53 of 62; it is the citation that collapses the all-correct column.

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 club codes the Basis and Class columns correctly and your invoice arguments are about dates, codes, escalations and arithmetic. — the free column floor alone — python3 -m evals.run --floor rules
    Every one of those is a date test, a lookup, an escalation and one multiplication. The floor is 260 of 277 line verdicts and 45 of 62 invoices for $0.00, no key and no network — and it gets every escalation defect in this corpus, including all 6 base-year-anchor lines.
  • Your invoice narratives are written by people and say things like 'the licensee's party outgrew the suite' or 'the tie that put the club into the conference final', and the Basis and Class columns are somebody's data entry. — the paid call for the two readings, and the pure-code station for everything else
    The readings are the only two things a column reader cannot establish, and the call got 268 of 277 entitlements and 270 of 277 classes — 11 of the 17 lines that actually move, where the column floor gets 0 by construction. Everything downstream of the reading is then recomputed in code, which is why the verdict column goes from 132 to 264.
  • You want the number this page reports to transfer to your own invoices. — build your own answer key first, then re-run everything here against it
    Every percentage on this page is measured against a key this kit could DERIVE because it also wrote the invoices and therefore knew the two facts they do not print. The machinery transfers in an afternoon; the key does not transfer at all.
  • You need the answer to be defensible line by line back to the club. — this kit's citation discipline, whichever arm you run
    The verdict is the claim and the quoted row is the evidence. A query queue where nobody can see the row in one glance is a queue nobody works, and src/citation.py scores a quote by locating it and comparing character intervals rather than by substring.

At a glanceHow the whole thing runs

86%invoice recommendation correct rechecked pct
3,901 msp50, end to end

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?Point data/corpus/ at your own exported invoices and data/licences.json at your own licence terms, keeping the panel headings and the column order, and every free floor, the label gate, the board and the scorer run unchanged with no key. The boundary is the ANSWER KEY, not the documents. Corpus lens →
When is this the wrong choice?Avoid: Paying for a reading you do not need — and paying it once a year for every licence you hold. That is the case against the best-fitting scenario (“Your club codes the Basis and Class columns correctly and your invoice arguments are about dates, codes, escalations and arithmetic.”). 4 scenarios scored in all, each with its own. Eval lens →
Where does it stop working?An invoice whose panels are not the seven this parser knows. src/rules.py splits on the headings INVOICE HEADER, LICENCE TERM RECORD, FEE SCHEDULE, INVOICE LINES, BILLING NOTES, ISSUED BY and END OF INVOICE, and reads the line rows with one fixed-column regular expression. 6 recorded failure modes, each from a run rather than a guess. Corpus lens →
What was never verified?RUN-TO-RUN VARIANCE. One scored run was bought. 7 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, configured in .env; 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 4 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-suite-invoice. 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.

Talk to us →

Checked before this shipped — Clone and run python3 -m evals.baseline with no key, no network and no install: it scores all four free floors over the whole corpus in about a second. python3 -m evals.check_labels re-derives the key independently. python3 -m src.app serves the board. Only --stub-less evals/run.py and the board's one Check button ever reach a provider.

A living map of modern AI — kept current every morning