15 Remedy and gate
Stages 3 and 4: one change, tested on 3–5 pages
15.1 Stage 3 — Remedy
A remedy is the smallest change on the attributed layer. The iteration declares it as input of the Partitur:
remedy:
kind: normalizer # normalizer | reocr | overlay
code: FN-MARKER
specimen: [copernicusGW-IV/page_127, copernicusGW-IV/page_347, copernicusGW-IV/page_553]Without a specimen list the first pages of the class are taken. All specimen pages come from one document, so that the gate runs against one document’s settings and placement rule.
| Kind | How the remedy is made |
|---|---|
normalizer |
a rule in the collection’s normalizer module, loaded through cure.yaml normalizer.module; generic tree rules live in ocr_runner/tree_rules.py |
reocr |
no code change; the next engine of engine_chain transcribes the page |
overlay |
a new overlay version proposed and A/B-tested by ocr_runner.cure_learn |
15.1.1 Document normalizers
A collection registers its document-level normalizer in the shared registry of ocr_runner/normalize.py:
from .normalize import DocumentNormalizer, register_document
register_document("copernicus-prim", DocumentNormalizer(
id=NORMALIZER_ID, normalize_document=normalize_document, page_hook=copernicus_hook))normalize_apply and the runner find the module through cure.yaml; a module that does not register itself raises an error instead of running without rules.
15.1.2 Overlay revision
.venv/bin/python -m ocr_runner.cure_learn --collection <c> --engine kimi --rounds 1The learning sample is the sample_pages list of agent-store/ocr_instruction_learning_agent/<c>.partitur.setting.yaml. It must contain pages with the defect. On copernicus-prim, three screenshot pages already scored 1.000 under the current kimi overlay; an A/B on those three pages could not show any difference between two authors (see Reference).
15.2 Stage 4 — Gate
# normalizer: specimen normalized in memory, nothing written
.venv/bin/python -m ocr_runner.normalize_apply --collection <c> --doc <d> --specimen 127,347,553
# re-OCR or overlay: pilot tree under <tmp>/pilot/<d>/<stamp>/
.venv/bin/python -m ocr_runner.cure_run --collection <c> --doc <d> --pilot --sample 5 --also 127,347,553The two gates check different properties.
| Gate | A specimen page passes when |
|---|---|
normalizer (normalize_apply --specimen) |
the rule changes the page (a no-op fails), the result is well-formed, applying the rule again changes nothing (idempotent), and the word sequence is preserved except for rejoined hyphenations |
re-OCR and overlay (cure_run --pilot) |
the best engine answer reaches verdict ok without a reject code (LOOP-REP, TRUNC, SYN-WELLFORMED), or the current XML is already valid and is kept; no page is deferred by the budget |
The normalizer gate stores for every passed page the hash of the source XML and the structural_hash of the result in <data>/quality/<d>_norm_gate.json. --apply refuses when the gate is missing, belongs to another normalizer version, or when a specimen page changed after the gate.
For a document of more than 50 pages the pilot adds five random pages to the specimen. That is the obligatory pilot gate of book-sized documents; the random pages show whether the remedy damages pages that were not defective.
Both commands exit 0 only on PASS. The op pdai:cure_gate reads the exit code and the verdict and publishes a FAIL as an error, so the stage grades FAILED and the Partitur does not reach stage 5.