Evidence and confidence
Cite document regions, keep word tokens in parsed_document, and score recognition separately from extraction.
Evidence selectors
Evidence uses openparser.document-region selectors. geometryGranularity
describes what the coordinates physically bound. A table cell id may also be
present under logicalAddress; it identifies the logical row/column even when
the provider supplied only a table-region bounding box. Consumers must never
render element/table geometry as a cell-precise highlight.
The locator points to the parsed_document returned beside the lineage, so
clients can render highlights without duplicating the entire document in each
field record.
Word tokens live in the parsed document
Lineage is a companion to parsed_document, not a replacement for it.
Per-word text, spans, and recognition scores are not duplicated as lineage
entities. Resolve them through the region entity's locator.uri (the parsed
document) and selector.value.elementId, then read the word/symbol elements
under that element. Only the region-level aggregate is carried in lineage.
This keeps the document small enough to return inline on every extraction — a typical 15-field result is a few KB per field rather than hundreds of KB — while losing no information a client can't already address.
Evidence context
Source entities retain the complete parsed element or table transcription in
value. Two fields citing one paragraph read different fragments of it; each
fragment is the extract output's value — the field itself when the model
copied, a source-text: entity when it rewrote — so the citation does not
restate it. The per-field recognition score on the resolved_source_evidence
input remains: that is how well those words scanned, which is per-edge
information. openparser:sourceContext appears only when the wider element
text differs from the region itself, as it does for a table cell. The optional
openparser:selectionReason is reserved for a concise provider-reported reason
for choosing that region. OpenParser does not emit it today.
The verbatim text a field was read from is never an annotation on the field. It is an entity value, so the graph states it once. Its offsets and containing element are not stored either, because searching the parsed text for that value recovers both. How that value is justified is on extraction and transforms.
OCR confidence
Recognition is scored twice, because "how well did this region scan" and "how well did this value scan" are different questions once two fields cite the same paragraph.
Each cited region carries a derived recognition_source_region assertion over
every OCR word inside it (method: region_word_minimum): its weakest word, with
minimum, maximum, and regionMean in attributes. This describes the
region, and nothing else.
Each field then scores the words it actually read, on the derivation input that
cites the region (method: cited_minimum_context_downblend). The weakest word
behind the value sets the score, and the rest of the region may pull it down by
at most 15% of the gap — never up. So a crisp 2448 in a sentence whose street
name scanned badly stays crisp, discounted slightly because a region that
defeated the scanner once may have defeated it twice. When the extracted text
cannot be located in the region there is nothing to narrow to, so the score falls
back to the region's own weakest word and the input reports
method: region_word_minimum — a score over the whole region never claims to
have narrowed to a value.
Page-only confidence remains on the page entity. When a region has no aggregate
and no provider score of its own, openparser:inheritedRecognition names the
page entity to fall back to; the score itself is never copied onto a region,
cell, or field entity.
Extraction and transform confidence
Extraction confidence is deterministic source-text alignment: the extracted text was verified to appear in the parsed document. When a later transform rewrites that text, the transform step carries its own score — a proven representation change, a coarse model ordinal, or nothing. The two claims are never folded into one number.
openparser:alignmentStatus on a derived assertion records how the extracted
text was matched: match_exact and match_fuzzy when that text is present in
the document, and ungrounded when nothing supporting it could be found. There
is no status meaning "this was rewritten". A rewrite is a second step, not a
grade of the first.
The assertion's sources names every activity that moved the number, so a
score reduced because grounding came back partial or ungrounded lists
activity:grounding-resolution alongside activity:extract.
Why not one number
The alternative is one edge carrying one score for two different claims. That tells you neither whether the read checked out nor whether the rewrite was proven, self-reported, or unmeasured. Two edges let each claim carry only the confidence that actually applies to it.
A consumer that walks a field's ancestors and takes the weakest scored step can show a single conservative headline number. A consumer that needs to explain uncertainty can point at the exact extraction or transform assertion instead.
Signed confirmations append to this graph without rewriting it. See human review.