14 Attribution
Stage 2: which layer caused a defect class
14.1 Why attribution comes first
A repair removes a defect class only if it changes the layer that produced it. A normalizer cannot restore text that the engine never transcribed; a new OCR pass cannot correct a DTD that forbids a structure the source prints. The attribution assigns each class one layer before any remedy is chosen.
14.2 Layers
| Layer | The defect is | The remedy changes |
|---|---|---|
reocr |
text missing from the page | nothing in code; the next engine of the chain transcribes the page |
prompt-overlay |
wrong structure produced by the engine | the engine’s overlay (or the shared base template) |
normalizer |
a deterministic rewrite of the XML repairs it | the collection’s normalizer module |
css |
the XML is right, the rendering is wrong | page.css |
dtd |
the schema lacks a structure the source prints | page.dtd via schema-derive |
engine |
one engine fails where another succeeds | the order of engine_chain |
source |
the scan is defective | a new scan |
14.3 Sources of the assignment
- The collection’s
config/audit_rules.yaml: the fieldlayerof a structure rule or a cue rule. It takes precedence. pdai/skills/pipeline/pdai-cure/defect_layers.yamlassigns the text-validity codes, which have no per-collection rule.- The fault dossier of
pdai-audit: the fix type of its cases (prompt_overlay,normalizer,normalizer_map,dtd_schema). A code whose cases name one layer takes it; the compound typeprompt_and_normalizernames two layers and leaves the code unattributed.
14.4 Defect codes and their layers
Structure codes (layer from audit_rules.yaml of copernicus-prim):
| Code | Defect | Layer |
|---|---|---|
LOOP-REP |
generation loop: padding or one unit repeated | prompt-overlay |
TRUNC |
output stops before </page> |
prompt-overlay |
NORM-REOCR |
the normalizer cut a loop or closed a truncated page | reocr |
EMPTY-MAIN |
<main> nearly empty although the scan carries ink |
reocr |
TABLE-FLAT |
a number grid transcribed as pipe-separated <p> rows |
prompt-overlay |
DUP-BLOCK |
an apparatus entry or note transcribed twice | prompt-overlay |
FN-BIJECTION |
a marker without its note | prompt-overlay |
FN-MARKER |
a note without a marker | normalizer |
TAG-VARIANT |
HTML tags or legacy footnote forms | normalizer |
Text-validity codes (layer from defect_layers.yaml):
| Code | Defect | Layer |
|---|---|---|
TXT-PAGE-LOST |
most of the page text is missing | reocr |
TXT-GAP |
two or more consecutive scan lines missing | reocr |
FN-MISSING |
a printed note number without <footnote> |
reocr |
FN-PARTIAL |
a footnote shorter than its scan lines | reocr |
TXT-EXCESS |
XML text without a counterpart in the scan | prompt-overlay |
BODY-IN-FN |
body lines filed as a note | prompt-overlay |
FN-IN-BODY |
note lines filed as body text | prompt-overlay |
SEG-ORDER |
zones out of the scan’s reading order | prompt-overlay |
Codes of the collection’s cue rules (SCH-*) carry no layer until the owner assigns one. On 2026-09-26 the baseline found SCH-APPARATUS (copernicus-prim, GW-II and GW-IV, 7 pages) and SCH-REGEST-MISSING, SCH-SALUTATION-MISSING (pirckheimer, 3 pages) unattributed. LN-DRIFT (marginal line numbers out of step with the lines) is a candidate code of the line-numbered editions without a rule.
14.5 Output and gate
The op pdai:cure_attribute collects the flags of fail and warn pages, every code of the pdai-audit defect register (quality/<doc>_defects.json) and the codes of the fault dossier, and produces one class per code: page count, layer, anchor, the source of the layer and the first five pages as specimen candidates. A code without a layer from any source is listed as unattributed and fails the stage. The role attribute-uncoded (kimi-k2.7-code:cloud, fallback gemini-3.8-flash) may propose a layer; the owner confirms it before it is written into the rule file.