ADR 0007: Banks map their own documents by pointing at values; the rule stored is a label-anchored region
Status: Accepted, 2026-09-02
Context
Section titled “Context”The template studio (release 0.2.0) made extraction extensible as data: a bank’s document family is a
TemplateOverlay of declarative rules (header_cell, grid, party_column, sentence, disbursement_table) that
run ahead of the built-ins. It worked, and it was the wrong interface for the people who have to use it. Four of the
five rule shapes depend on a label the engine already knows how to find; the fifth is a regular expression with a
named capture. Real-world packages showed the cost: a memo’s keywords missed the classifier threshold, a shaded header
grid defeated header_cell, and the only remedy was editing JSON by hand. Loan-operations staff do not write regular
expressions, and an AI-drafted template that a person cannot correct on the page is not a control anyone will sign
off on.
The operator’s mental model is simple (“this box on the page is the principal”), and the engine already produces a box for every value it reads. The question was what to store when a person draws one.
Decision
Section titled “Decision”- A sixth rule type,
region, stores what the operator drew: the page, the box as page fractions, and an anchor. The anchor is the printed label the engine proposes beside the box (RegionReader.SuggestAnchor: the run of words immediately left of the value on its line, else the words directly above), with its own box. - At extraction time the box follows the anchor, not the coordinates.
RegionReader.Readfinds the occurrence of the anchor’s words nearest to where the studio recorded them (case-folded, trailing punctuation dropped, within a quarter of the page), moves the drawn box by the anchor’s displacement, and reads the words whose centers fall inside. Without an anchor, or when it cannot be found, the box is read where it was drawn at reduced certainty (Candidate.Certainty0.9 or 0.75 scales the layout-only and single-pass confidences; dual-pass agreement is evidence in itself and keeps its full confidence). A miss lowers confidence rather than inventing a value, so the review threshold routes it to a person. - The studio reads the box back before anything is stored.
POST /v1/extraction-templates/read-regionreturns the raw text, the tight box, the proposed anchor and, with a field named, the rule and the value it proves on that sample, through the same extractor the pipeline runs. Prove runs the whole template and draws every value on the page; Save stores the overlay exactly as before. The AI suggester and the raw JSON editor remain as optional starting points under “technical details”. - A real loan teaches the same way.
POST /v1/extraction-templates/correctionstakes a box drawn on a loan document’s page in the workstation (“Fix where this comes from”), reads it, and replaces that field’s rule in the document type’s template; the loan itself is unchanged until it is reprocessed.
Consequences
Section titled “Consequences”- Mapping a form is minutes of pointing, with immediate feedback, instead of rule-writing; the same page viewer that shows provenance is the editor. The end-to-end test suite drives it with a real drag on the real PDF.
- Region rules survive a scan’s offset and a form’s re-flow as long as the label survives; a re-labeled form degrades to reduced confidence rather than silently reading the wrong text (proved on the golden packages: a rule drawn on BK-DEMO-001’s boarding sheet reads BK-DEMO-002, BK-DEMO-003 and the scanned copy).
- Runtime extraction stays deterministic and inspectable: a region rule is data in
extraction.templates, versioned with every other setting and visible in the settings audit. - Not solved here: anchors are text-only (no geometric fallback when a label is renamed), studio samples are stored by hash and never purged, and corrections are an administrator’s action (a reviewer proposes, an administrator applies). Each is a follow-on, not a blocker.