test(propose): pin today's grid-table split with a golden that can fire

The K3 Arm E round (order 20260907T075834Z-18584396-from-.claude) measures a
rule that has not been written yet. This commit pins what the code does TODAY,
so the later claim "the default did not move" rests on a committed artifact
rather than on reading a diff.

Three characterization tests and one new golden fixture. Every count they
assert was measured against unmodified code before the test was written:
GRID_TABLE yields 3 candidates, TWO_TABLES_BLANK_SEPARATED yields 3,
TWO_TABLES_RULE_SEPARATED 2, PIPE_TABLE 1, PROSE_WITH_A_STRAY_RULE 1.

The second golden is not duplication. `propose-golden-default.json` is taken
over `OUTLINE_DOCUMENT`, which contains no `|` row and no `+` rule line, so no
table rule -- present or future -- can move its bytes. It is a guard that
cannot fire. `propose-golden-grid-default.json` is taken over a document that
has a pandoc grid table, and it is generated here from PRE-Arm-E code: a
fixture recorded after the change would pin post-change bytes and prove
nothing about the default.

Two fixture shapes are load bearing and say so in the band's comment. The
second table in TWO_TABLES_BLANK_SEPARATED has exactly ONE row group, so it
cannot be joined -- that is the only shape that catches a join whose pending
state is never cleared. And `propose()` is excluded from this band: it pops
`source` and discards every other kwarg, so an Arm E test written through it
would silently measure the default and pass.

Tests first: 1 red (the golden did not exist), then green. 1230 -> 1233.
ruff check: exit 0. ruff format --check: exit 0. pytest -q: exit 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-07 10:45:05 +02:00
commit 3fa772e917
3 changed files with 267 additions and 0 deletions

View file

@ -162,3 +162,25 @@ two independent parsers return the same wrong shape, because the breakage is in
the documents' ruling geometry rather than in either library. PDFs enter this
library as **prose**, and structured tables are out of scope until that is
decided separately.
## `propose-golden-grid-default.json`
Pins the DEFAULT proposer artifact over a document containing a pandoc **grid
table**. Generated on unmodified code, before Arm E's rule existed, with
exactly the command the test runs:
```
write(tmp_path, GRID_GOLDEN_DOCUMENT, "grid.md")
okf_propose_segments.main([source, "--out", out, "--proposed-at", "2026-09-03T00:00:00Z"])
```
It exists because `propose-golden-default.json` **cannot** pin this. That
golden is taken over `OUTLINE_DOCUMENT`, which contains no `|` row and no `+`
rule line, so no table rule -- present or future -- can move its bytes. A guard
that is structurally incapable of firing is a trap written down but never
armed. This one is taken over a document that has a grid table, so an
accidentally default-on table rule turns it red.
Both goldens transitively pin `observed_extractor_version` and `PROPOSER_VERSION`.
A red here after a dependency change is a legitimate red: read the diff and
decide, do not re-record the expectation.

View file

@ -0,0 +1,92 @@
{
"version": "1",
"source_sha256": "4a50a27785e57b8d12319e3aad1118529251287b6ae8ecd3060bbac9fe04aee4",
"text_sha256": "4a50a27785e57b8d12319e3aad1118529251287b6ae8ecd3060bbac9fe04aee4",
"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": "romskjema.md",
"title": "Romskjema",
"okf_type": "reference",
"span": [
0,
67
],
"ingested_at": "2026-09-03T00:00:00Z",
"anchor": {
"quote": "# Romskjema\n\nInnledende avsnitt om romskjemaet.\n\n+-------+-------+\n",
"prefix": "",
"suffix": "| Navn | Verdi |\n+=======+=======+\n| Areal | 12"
},
"derived": [
"PROPOSED",
"rule:heading"
]
},
{
"segment_id": "p2",
"path": "tabell-linje-6.md",
"title": "Tabell linje 6",
"okf_type": "reference",
"span": [
67,
103
],
"ingested_at": "2026-09-03T00:00:00Z",
"anchor": {
"quote": "| Navn | Verdi |\n+=======+=======+\n",
"prefix": "ende avsnitt om romskjemaet.\n\n+-------+-------+\n",
"suffix": "| Areal | 120 |\n+-------+-------+\n| Hoyde | 3 "
},
"derived": [
"PROPOSED",
"rule:table-block"
]
},
{
"segment_id": "p3",
"path": "tabell-linje-8.md",
"title": "Tabell linje 8",
"okf_type": "reference",
"span": [
103,
139
],
"ingested_at": "2026-09-03T00:00:00Z",
"anchor": {
"quote": "| Areal | 120 |\n+-------+-------+\n",
"prefix": "--+-------+\n| Navn | Verdi |\n+=======+=======+\n",
"suffix": "| Hoyde | 3 |\n+-------+-------+\n"
},
"derived": [
"PROPOSED",
"rule:table-block"
]
},
{
"segment_id": "p4",
"path": "tabell-linje-10.md",
"title": "Tabell linje 10",
"okf_type": "reference",
"span": [
139,
175
],
"ingested_at": "2026-09-03T00:00:00Z",
"anchor": {
"quote": "| Hoyde | 3 |\n+-------+-------+\n",
"prefix": "==+=======+\n| Areal | 120 |\n+-------+-------+\n",
"suffix": ""
},
"derived": [
"PROPOSED",
"rule:table-block"
]
}
]
}