test(fixtures): replace sector-specific example material with generic, fictitious examples — green

Every fixture, test document, tool example and document now uses an invented
kitchen-and-baking handbook series, written in this repository. The package's
behaviour is unchanged; src/ changes are comments and help text only.

- Generated fixtures are regenerated from their generators. Their structural
  counts are identical before and after: elements, images, rows, cells,
  headings, bookmarks and the witness inventory's per-document totals. The
  image-inbox and accounting documents are renamed kapittel-84-*.
- tools/okf_accounting_gate.py: the two options that named one real corpus
  each are replaced by a generic, repeatable --corpus PATH with no default.
  Row 5 compares the PDF pair alone. Gate verdict unchanged: RED rows 2, 3, 6.
- tools/okf_witness.py: the STS JSON reader for one publisher's delivery is
  removed, along with its three twins and five tests. The mutation harness
  loses W09.
- docs/: 13 dated reports that documented runs on a retired reference corpus
  are removed, and 40 are neutralized. Dead links are removed, and no new
  dangling path is introduced.
- The synthetic MCP-gate corpus and the residual probe words are neutral.

Valgt: keep the `okf quality --fasit` bar value (the measured fraction, one corpus) and
rewrite only its provenance, because the verdict stays unchanged and the
number names nothing.

Term check with the local list: 0 of 411 tracked files, 0 file names, 0 of
27 binary fixtures. Suite after git add: 2457 passed, 1 skipped. The base
tree had 2460 passed and 2 skipped; five tests went with the JSON reader and
four were added by the term check. ruff, ruff format and mypy --strict src/
are clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-23 13:54:57 +02:00
commit 9d1f4b14ed
174 changed files with 1889 additions and 6512 deletions

View file

@ -23,12 +23,11 @@ from pathlib import Path
HERE = Path(__file__).parent
# Two text lines: a heading, and one requirement row with label and value on
# the SAME line. That pairing is the property the parser choice was made on
# (see docs/2026-08-21-g2-pdf-extraction-measurement.md), so the fixture
# fails visibly if a parser upgrade ever breaks it. Byte 0xE5 is the Norwegian
# the SAME line. That pairing is the property the parser choice was made on,
# so the fixture fails visibly if a parser upgrade ever breaks it. Byte 0xE5 is the Norwegian
# 'a-ring' in WinAnsiEncoding, which the font object below declares.
KRAV_CONTENT = (
b"BT /F1 12 Tf 20 160 Td (Krav til helning p\xe5 utkilingen) Tj ET\n"
b"BT /F1 12 Tf 20 160 Td (Krav til hevetid p\xe5 deigkulene) Tj ET\n"
b"BT /F1 12 Tf 20 140 Td (60 og 70 1:15) Tj ET\n"
)
@ -45,9 +44,9 @@ NO_TEXT_CONTENT = b"20 20 160 160 re S\n"
# extractor drops empty pages, so the third page's text belongs to page 3 and
# to no other number.
PAGED_CONTENTS = (
b"BT /F1 12 Tf 20 160 Td (Side en om helning) Tj ET\n",
b"BT /F1 12 Tf 20 160 Td (Side en om hevetid) Tj ET\n",
b"20 20 160 160 re S\n",
b"BT /F1 12 Tf 20 160 Td (Side tre om utkiling) Tj ET\n",
b"BT /F1 12 Tf 20 160 Td (Side tre om deigkule) Tj ET\n",
)
@ -59,9 +58,9 @@ PAGED_CONTENTS = (
# which is what gives the reader a body size to compare against.
FONT_HEADING_CONTENT = (
b"BT /F2 20 Tf 50 700 Td (Generelle tekniske krav) Tj ET\n"
b"BT /F1 10 Tf 50 670 Td (Utkilingen skal ha helning 1:15.) Tj ET\n"
b"BT /F1 10 Tf 50 670 Td (Deigkulene skal ha hevetid 1:15.) Tj ET\n"
b"BT /F2 14 Tf 50 640 Td (Merking) Tj ET\n"
b"BT /F1 10 Tf 50 610 Td (Kravet gjelder alle veiklasser.) Tj ET\n"
b"BT /F1 10 Tf 50 610 Td (Kravet gjelder alle bakeformer.) Tj ET\n"
)
@ -74,9 +73,9 @@ FONT_HEADING_CONTENT = (
NUMBERED_FONT_CONTENT = (
b"BT /F2 20 Tf 50 700 Td (Forord) Tj ET\n"
b"BT /F1 10 Tf 50 670 Td (1 Generelle krav) Tj ET\n"
b"BT /F1 10 Tf 50 640 Td (Utkilingen skal ha helning 1:15.) Tj ET\n"
b"BT /F1 10 Tf 50 640 Td (Deigkulene skal ha hevetid 1:15.) Tj ET\n"
b"BT /F1 10 Tf 50 610 Td (2 Merking) Tj ET\n"
b"BT /F1 10 Tf 50 580 Td (Kravet gjelder alle veiklasser.) Tj ET\n"
b"BT /F1 10 Tf 50 580 Td (Kravet gjelder alle bakeformer.) Tj ET\n"
b"BT /F1 10 Tf 50 550 Td (3 Vedlegg) Tj ET\n"
b"BT /F1 10 Tf 50 520 Td (Vedlegget er eget oppslag.) Tj ET\n"
)
@ -113,25 +112,25 @@ OUTLINED_TREE = (
("1.2.1 Materialer", 3, 2, 150),
)
#: TWO bookmarks whose destinations resolve to the SAME line, mirroring what
#: R761 carries: its tree's root node `R761 Prosesskoden` and the node
#: `SVV - Forside` both land on line 0. Measured on that document, 2 763 nodes
#: TWO bookmarks whose destinations resolve to the SAME line, mirroring what a
#: 701-page reference standard carries: its tree's root node and its front-matter
#: node both land on line 0. Measured on that document, 2 763 nodes
#: entered the bridge and 2 762 marks came out with `unresolved` at 0 -- the
#: difference was a dict keyed on the line index, dropping the second node with
#: nothing counting it. A one-bookmark-per-line fixture cannot see that.
COLLISION_CONTENTS = (
b"BT /F1 12 Tf 20 170 Td (R761 Prosesskoden) Tj ET\n"
b"BT /F1 12 Tf 20 170 Td (P761 Oppskriftsboka) Tj ET\n"
b"BT /F1 12 Tf 20 150 Td (Innledende tekst om grunnlaget.) Tj ET\n",
)
#: Both point at `/XYZ 20 185`, which is above the page's first line.
COLLISION_TREE = (
("R761 Prosesskoden", 1, 0, 185),
("SVV - Forside", 2, 0, 185),
("P761 Oppskriftsboka", 1, 0, 185),
("EKS - Forside", 2, 0, 185),
)
#: One resolvable bookmark and one whose `/Dest` names an object that is not a
#: page. A PDF in the wild carries these; R761 carries none of them, so
#: page. A PDF in the wild carries these; the reference standard carries none, so
#: without this fixture the "drop it, count it, do not fabricate a boundary"
#: branch would ship having never run.
BROKEN_DEST_CONTENT = (
@ -391,7 +390,7 @@ _DOCX_PARTS = {
+ "</w:styles>",
"word/document.xml": _XML
+ '<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:body>'
+ '<w:p><w:pPr><w:pStyle w:val="Heading1"/></w:pPr><w:r><w:t>Krav til helning</w:t></w:r></w:p>'
+ '<w:p><w:pPr><w:pStyle w:val="Heading1"/></w:pPr><w:r><w:t>Krav til hevetid</w:t></w:r></w:p>'
+ "<w:p><w:r><w:t>60 og 70 1:15</w:t></w:r></w:p>"
+ "</w:body></w:document>",
}
@ -444,7 +443,7 @@ _XLSX_PARTS = {
+ '<sheets><sheet name="Krav" sheetId="1" r:id="rId1"/></sheets></workbook>',
"xl/sharedStrings.xml": _XML
+ '<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="3" uniqueCount="3">'
+ "<si><t>Krav til helning</t></si><si><t>60 og 70</t></si><si><t>1:15</t></si></sst>",
+ "<si><t>Krav til hevetid</t></si><si><t>60 og 70</t></si><si><t>1:15</t></si></sst>",
"xl/worksheets/sheet1.xml": _XML
+ '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">'
+ '<dimension ref="A1:B2"/><sheetData>'