Home › Use Cases › Check an enrollment packet's proofs of residency against the district rule
Use caseUC0414
🧪 Use-case kit · runnable

Check an enrollment packet's proofs of residency against the district rule

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 guardian brings a stack of paper to a registration counter and a clerk keys it in: a type from a drop-down, the name on the document, the service address, the date. Somebody then has to look at each one and decide whether it is evidence at all. That means joining every document to the district's boundary register, to the enrolling guardian on the packet, and to a window that is DIFFERENT FOR EVERY DOCUMENT TYPE — a lease has a year, a paystub has forty-five days — and then deciding whether the packet as a whole has the one primary and one supporting proof the rule requires. It is done at a counter, in front of the family, at the busiest week of the year. The two things hardest to see are the two that decide it: the drop-down type is what somebody SAID the document was, and the date column is what somebody KEYED, and both can be wrong in a document that looks perfect in every other column. The by-eye pass a registrar makes over a submitted packet: four comparisons and one per-type-window date test on every document, then the tier arithmetic on the packet. It replaces none of the deciding — nothing here enrols, denies, assigns, asks a family for anything or opens an investigation — and the free half of it needs no model at all.

Audience

A registrar or enrollment lead deciding whether to build this, and what it can be trusted with. The honest answer this kit publishes is a qualified one: the paid call buys the two readings and loses the arithmetic under them, and a free keyword floor written with this corpus open matches the paid arm within noise. Every number on these pages came from one real run of this code, not from a vendor page.

The inputThe actual submitted enrollment packets

The corpus is 60 submitted enrollment packets, 0.18 MB (json 4 · jsonl 1 · md 2 · txt 60). Because the two things that decide a residency packet are the two a column cannot show, and a corpus has to contain both or the measurement is free. The type is what somebody SAID the document was and the date is what somebody KEYED, so 10 documents are filed under a type their body contradicts and 8 carry a body that names a different effective day. Both traps run in BOTH DIRECTIONS, which a corpus of one-directional traps would never show: a document the columns call stale can be inside its window once the body is read. And the type carries the TIER as well as the window, so 18 packets have a column-only outcome that is simply wrong — more than the 14 documents whose own verdict moves. The families are stated rather than sampled, and data/corpus-stats.json counts every one of them.

The corpus

  • The 60 submitted enrollment packetsgenerated from a fixed seed, so no real record, person or institution appears in it.
  • Where each came fromNowhere. Every student, guardian, householder, address, street, locality, district, attendance area, registrar clerk, utility, bank, insurer, employer and county office is drawn from the word pools at the top of tools/build_corpus.py by a seeded random.Random. THE SUBJECT OF AN ENROLLMENT PACKET IS A CHILD AND THE DISPUTED FACT IS A HOME ADDRESS, so the corpus carries no date of birth, no telephone number, no email address, no emergency contact, no account or case number that resolves anywhere, no immigration or benefit detail, no medical detail and no demographic field of any kind. Addresses exist because a residency rule is a rule ABOUT an address. RESIDENCY-2026 is invented too and is not a state education code, a federal rule, a McKinney-Vento provision or any real district's policy. See data/SOURCES.md.

Swap this folder for your own material and the kit is pointed at your submitted enrollment packets. That is the whole change — there is no database to migrate.

One submitted enrollment packet, as the model receives itPKT-0001.txt · 1 of 60
RESIDENCY EVIDENCE QC PACKET - A SUBMITTED ENROLLMENT PACKET'S PROOFS OF RESIDENCY AGAINST THE DISTRICT RESIDENCY RULE

PACKET HEADER
  Packet               PKT-0001
  District             Halbrook Ridge Unified School District
  Student              Mira Mchugh  (STU-41011)
  Grade                11
  Enrolling guardian   M. Mchugh
  Address of record    587 Corveth Drive, Oakhurst Park
  Submitted            2026-02-15
  Taken by             N. Oyelaran, enrollment assistant

RESIDENCY RULE IN FORCE (RESIDENCY-2026, invented for this kit)
  Required             one Tier A proof and one Tier B proof, each satisfying every clause
  Tier A and windows   utility-bill 60 days, mortgage-statement 60 days, lease 365 days, property-tax-bill 365 days, residency-affidavit 90 days
  Tier B and windows   bank-statement 60 days, paystub 45 days, insurance-declaration 365 days, voter-registration 365 days, benefit-award-letter 365 days
  Not accepted         mobile-phone-bill, drivers-license, medical-bill, personal-mail
  Affidavit rule       Clause R-7: a residency affidavit must be notarised and supported by a Tier A proof in the affiant's own name

BOUNDARY TABLE (the district's own attendance-area register for every address this packet references)
   Address                                     Attendance area                             In district
   587 Corveth Drive, Oakhurst Park            Halbrook Ridge Hillside Attendance Area     yes
   338 Windermoor Court, Oakhurst Park         Halbrook Ridge Lakeside Attendance Area     yes

DOCUMENTS FILED
   #   Type as filed           Name on document      Service address                             Dated       Notarised  Names guardian  Document

Abridged — the file continues.

The outcomeWhat a good result looks like

For every filed document: a verdict from a closed set of seven, the clause it rests on, the age in days that clause measured, and one row of the packet copied verbatim as the evidence. For the packet: SATISFIED, INSUFFICIENT or MISSING, the list of documents that do not satisfy, and how many of the two required tiers are short. A registrar reads a note on a queue rather than re-deriving four comparisons per document by eye.

And when it cannot

It calls a document short that satisfies. On the published run the call did that 71 times out of 203 — never the other way round, not once — and every one of those is a family told to come back with a paper they already brought. The pure-code station cuts it to 5, and the run record carries both numbers under their own names (satisfied_called_short, short_called_satisfied) because they are different harms to different people and an aggregate hides which one happened.

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.

  • You want the packet answer and you can run pure code beside the model — the call plus src/recheck.py
    59 of 60 packet outcomes against 34 for the raw reply, and the difference is free — the station is 200 lines of Python over the call's own two readings.
  • Your documents are as regular as this corpus and you can write the keyword lists — the free phrase floor, and no model at all
    201 of 203 document verdicts and 58 of 60 packets for $0.00, and a paired McNemar exact test cannot separate it from the paid arm on this set (p = 0.4531).

And where nothing here is good enough:

  • Your documents are scanned, photographed or free-form — neither of the above yet
    Every arm here reads a rendered COLUMN LAYOUT. A packet whose columns are one space apart does not parse at all, and a photograph is a different kit with a capability stage in front of it.
  • You need the rule's real exceptions — military, homeless, shared custody — nothing on this page
    RESIDENCY-2026 has none of them. A packet that should be resolved by one will be reported short, which is the failure mode with the worst consequences on this kit.

At a glanceHow the whole thing runs

98%doc verdict pct
2,355 msp50, end to end
$1.89per 1,000 submitted enrollment packets · OpenAI GPT-5.6 Luna

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?Drop your own packets in data/corpus as .txt with the same panel headings, put the district's own record for each in data/districts.json, and the parser, the engine, all four free floors and the whole board run unchanged with no key. Every percentage on this page stops being true the moment you do. Corpus lens →
When is this the wrong choice?Avoid: Trusting the reply's own verdict field; it is right 132 of 203 times. That is the case against the best-fitting scenario (“You want the packet answer and you can run pure code beside the model”). 4 scenarios scored in all, each with its own. Eval lens →
Where does it stop working?A packet whose columns are separated by ONE space. src/rules.py splits the name from the address and the address from the date on a run of two or more, because both fields contain single spaces of their own. 6 recorded failure modes, each from a run rather than a guess. Corpus lens →
What was never verified?Whether the phrase floor's advantage transfers to any other corpus. Its lists were written with this one open; the memorisation count is published beside it and the de-memorised floor ships as the honest rival, but nobody ran either against a second corpus. 5 items this kit says it could not check. Eval lens →
Can I run this on a model I control?The shipped adapter is an OpenAI-compatible chat-completions endpoint over HTTPS, reached from src/adapters/ and nowhere else in the kit; 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-11 — r001-residency-evidence. 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 — A clean checkout with NO key configured renders the whole board, runs all four free floors and writes a scored result file: the column floor over 60 packets and 203 documents completed in 0.33 s and cost $0.00. python3 -m evals.check_labels re-derives the key and its --self-test red-proves the gate, both offline. The requirements file is empty on purpose — the kit is Python standard library end to end — so there is no install step to fail.

A living map of modern AI — kept current every morning