test(propose): pin the default artifact with a committed golden

This commit is contained in:
Kjell Tore Guttormsen 2026-09-07 01:20:31 +02:00
commit c97e250f69
3 changed files with 140 additions and 0 deletions

View file

@ -47,6 +47,30 @@ structurally valid input, silently reduced output, exit code 0 and no warning:
the xlsx extracts with the sheet name intact and **every cell value gone**.
The fixture therefore uses a `dimension` element and a shared string table.
## The proposer's default-profile golden
`propose-golden-default.json` is the artifact `tools/okf_propose_segments.py`
produces for `OUTLINE_DOCUMENT` (defined in `tests/test_propose_segments.py`)
with **no flags at all**, generated at commit `798f64a` with
`--proposed-at 2026-09-03T00:00:00Z`. The timestamp is an explicit argument
because the artifact carries it verbatim; a wall-clock default would make the
golden unreproducible by construction.
**Why the fixture is `OUTLINE_DOCUMENT` and not `DOCUMENT`.** The golden exists
to go red if any later rule is accidentally defaulted ON. `DOCUMENT` was
measured to contain **zero** bare-integer lines, so a golden over it would stay
byte-identical through exactly the regression it was named to catch -- a trap
written down but unable to fire. `OUTLINE_DOCUMENT` carries a bare-integer
ascending run of three, which today's rules do not match (measured: bare `1` /
`1.` / `1)` yield 0 candidates), so the golden pins that absence and breaks the
moment it stops being true.
**It transitively pins `observed_extractor_version`**
(`src/llm_ingestion_okf/segmentation.py`): the field is written into every
artifact, so a converter or extractor bump turns this golden red. That red is
legitimate -- read the diff and decide, exactly as for the frozen PDF literal
below. Regenerate only after that decision, never to make a red go away.
## Why the expected office text is frozen as a literal
The same reason as the PDF text below, with one addition: the literals are

View file

@ -0,0 +1,52 @@
{
"version": "1",
"source_sha256": "5eb8f9f9c1c7584f66182beb886de3aec9fab3446892a5a430509bb6fc68031b",
"text_sha256": "5eb8f9f9c1c7584f66182beb886de3aec9fab3446892a5a430509bb6fc68031b",
"extractor_id": "md",
"extractor_version": "stdlib-1",
"adjudicated_at": "2026-09-03T00:00:00Z",
"adjudicated": false,
"proposed_by": "okf-propose-segments/1",
"entries": [
{
"segment_id": "p1",
"path": "stange-skole-teknisk-grunnlag.md",
"title": "Stange skole -- teknisk grunnlag",
"okf_type": "reference",
"span": [
0,
297
],
"ingested_at": "2026-09-03T00:00:00Z",
"anchor": {
"quote": "# Stange skole -- teknisk grunnlag\n\nInnledende tekst som gir dokumentet en kropp foer kapitlene begynner.\n\n1 Innledning\n\nBakgrunnen for prosjektet og omfanget av arbeidet.\n\n2 Krav\n\nKrav til seksjonering av bygget over flere etasjer.\n\n3 Gjennomfoering\n\nFramdrift, faser og overlevering av bygget.\n\n",
"prefix": "",
"suffix": "1.1 Brannkonsept\n\nTo uavhengige roemningsveier f"
},
"derived": [
"PROPOSED",
"rule:heading"
]
},
{
"segment_id": "p2",
"path": "1-1/brannkonsept.md",
"title": "Brannkonsept",
"okf_type": "reference",
"span": [
297,
365
],
"ingested_at": "2026-09-03T00:00:00Z",
"anchor": {
"quote": "1.1 Brannkonsept\n\nTo uavhengige roemningsveier fra hver branncelle.\n",
"prefix": "g\n\nFramdrift, faser og overlevering av bygget.\n\n",
"suffix": ""
},
"derived": [
"PROPOSED",
"rule:heading"
]
}
]
}

View file

@ -52,6 +52,42 @@ Hovedbaeresystemet skal ha R60 dokumentert baereevne.
"""
#: The golden fixture's document. It carries a BARE-INTEGER ascending run of
#: three (`1`, `2`, `3`), which today's rules do not match at all -- measured,
#: bare `1` / `1.` / `1)` yield 0 candidates. That is precisely why the golden
#: is taken over THIS text and not over `DOCUMENT`: `DOCUMENT` has no
#: bare-integer line, so a golden over it would stay byte-identical even if the
#: outline rule were accidentally defaulted ON, and the guard would be a trap
#: written down but never able to fire. The ATX heading and the dotted heading
#: are here so the shipping rules fire too, and the golden pins their output as
#: well as the outline rule's absence.
OUTLINE_DOCUMENT = """# Stange skole -- teknisk grunnlag
Innledende tekst som gir dokumentet en kropp foer kapitlene begynner.
1 Innledning
Bakgrunnen for prosjektet og omfanget av arbeidet.
2 Krav
Krav til seksjonering av bygget over flere etasjer.
3 Gjennomfoering
Framdrift, faser og overlevering av bygget.
1.1 Brannkonsept
To uavhengige roemningsveier fra hver branncelle.
"""
#: Frozen in the golden's bytes. An explicit argument because the artifact
#: carries it verbatim, and a wall-clock default would make the golden
#: unreproducible by construction.
GOLDEN_PROPOSED_AT = "2026-09-03T00:00:00Z"
def write(tmp_path: Path, text: str = DOCUMENT, name: str = "n500.md") -> Path:
path = tmp_path / name
path.write_text(text, encoding="utf-8", newline="")
@ -511,3 +547,31 @@ def test_an_unbreakable_line_longer_than_the_cap_is_still_cut(
for entry in plan["entries"]:
start, end = entry["span"]
assert end - start <= 3000
# --- the default profile, pinned byte for byte ----------------------------
#
# The one guard that can go red on an accidental default-on regression of any
# rule added later. It compares the WHOLE artifact, so a new candidate, a moved
# span, a changed `derived` list or a renamed path all break it.
def test_the_default_artifact_matches_its_committed_golden(tmp_path: Path) -> None:
"""The default profile is a promise to consumers; this is what keeps it.
The golden transitively pins `observed_extractor_version` too, so a
converter bump turns this red. That is a legitimate red, not a defect:
read the diff and decide, per `tests/fixtures/README.md`.
"""
source = write(tmp_path, OUTLINE_DOCUMENT, "outline.md")
out = tmp_path / "outline-plan.json"
assert (
okf_propose_segments.main(
[str(source), "--out", str(out), "--proposed-at", GOLDEN_PROPOSED_AT]
)
== 0
)
golden = Path(__file__).parent / "fixtures" / "propose-golden-default.json"
assert out.read_bytes() == golden.read_bytes(), (
"the default artifact diverges from its committed golden bytes"
)