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>
The catalogue goes 45 to 47 and the runner stays `killed N of N`, exit 0.
`P8` is PM's own survivor from `44ad845`: the cursor rule one row too lenient
(`height - 1` -> `height - 2`), which survived 51 tests because no arm in
`CURSOR_CASES` stopped a row early. `P13` removes the clause this round added,
so the round leaves a mutant behind and not only a test. Both are judged by
`tests/test_asset_viewable.py`, which is why the per-mutant suite added in the
previous round was worth having.
CHANGELOG under 0.10.1, no new version and no tag.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The runner could only run one test file, which is why PM's three
survivors from `43331fc` could not be added: two are held by the gate's
row 3 and one by the soft-hyphen door's suite. A mutant now names its
suite; the catalogue goes 39 to 45.
X3 and X4 rewritten against the code as it now stands -- a mutant table
is a copy of the code it mutates, and this round moved the lines both of
them quoted. X6 is the defeated state exactly, X7 cuts the ledger off at
its source, X8 removes the cursor rule, P6/P11/P12 are PM's three.
Two survivors on the first run, both findings, both closed:
- X4 survived because every forgery arm now fails on the ledger check
before the binding is reached. An arm was added where the run DID book
the pair and the block stating it points at another picture.
- X5 survived the WHOLE suite -- 2134 passed with the disarming removed
-- because a document-supplied field can no longer reach the gate. The
property is about the BUNDLE and not about one judge, so it is kept and
measured in `tests/test_assets.py`, with a known-positive counting the
run's own two fields on the same expression.
killed 45 of 45, exit 0. Report, CHANGELOG and CLAUDE.md written.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
killed 39 of 39, exit 0 (36 before this round). Three new mutants, one per
check that closes PM's measured forgery, each felled by its own arm:
- X3 restores the pre-round `_conversions` verbatim -- the clause read from
anywhere in the bundle text. Felled by the body-text and table-cell arms.
- X4 drops the tie between the clause and the asset its block points at.
Felled by the arm where the clause stands in another asset's block.
- X5 drops `_inline`'s checksum disarming. Felled by the end-to-end arm where
an `<img alt>` carries the clause.
X5 IS WHY THE HARNESS CHANGED, and it is a finding about the harness rather
than about the code: it SURVIVED 112 green tests on the first run, and it had
never been applied. The copy is run with the venv's interpreter, which carries
an editable install pointing at the working tree, so `import llm_ingestion_okf`
in the copy resolved to the original `src/`. The subprocess now gets the copy's
own `src/` on `PYTHONPATH`, which wins over the editable finder, and X5 dies on
the first run under it -- the survivor/killed pair is the measurement. The gate
and the witness were never affected; the suite reaches those through the copy's
own `tools/`.
The docstring's "the twenty-six mutants" now says "twenty-six of them", since
the list has been 39 for a while and the sentence is about their provenance.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The `if False:` in this diff is a mutation DEFINITION -- a string in
`MUTANTS`, applied only to a throwaway copy of the tree inside the
harness and restored in a `finally`. No branch in this repository is
pinned by it.
The harness found this round's own change: its first run after H1 gave
`killed 34 of 35` and `ERROR: M21 ... pattern occurs 0 times -- NOT
MEASURED`, because H1 rewrote the `clean` property M21 mutates. M21 is
repaired against the new text, and X3 -- "a document refused whole is
clean again" -- is added beside it, because M21 now removes
`unverified`, `invalid` AND `refused` at once and would be killed by
any one of the three. Final run: killed 36 of 36, 0 survived, 0
errors, exit 0.
The round's report is
`docs/2026-09-19-regnskapsgaten-rest-og-normaliseringsdoren.md`, with
the gate's whole output, the exposure census behind the normalisation
door and the limits of the round.
CHANGELOG: this round's entries are folded into the UNTAGGED `[0.10.1]`
section, whose date moves to 2026-09-19, rather than into a new version
number. `v0.10.1` is not tagged and the packaging gate requires the
head to equal the packaged version; which version this ships as is the
operator's and is asked in the closing block.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`measures_no_class(units)` returns a sentence when EVERY document of a
corpus has no declared fate, and row 6 prints it beside that corpus's
tally. On N200 that is 16 549 elements of `u` which look like a finding
about the build and are a finding about the run: the build exits 2 on
0 proposed plans before the accounting door is reached, so no
accounting file exists to read a fate from.
The function's docstring carries what it would take, because that is a
capability and not a threshold: `.json` is read as generic JSON, and
the publisher's STS delivery in that form would have to reach the
markdown grammar `_extract_xml` writes for the XML one. Measured
2026-09-19, with the query validated against a known positive:
`standardContent` occurs 0 times in `src/` and 4 in the witness.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PM wrote this mutant outside the tree 2026-09-18 and it survived 155
green tests. Reproduced here on the mutant as committed: `98 passed`,
rc 0, the pattern applied exactly once.
`_document_unit` refuses a report that declares a document `rejected`
while a concept in the bundle names it -- one of the six refusals B-1
introduced, and the only one no test drives from either side. The check
works; nothing stops the next refactor removing it. With H4 in place
the harness now exits 1 on this survivor, so the red is the harness's
own verdict and not a line in its output.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`verdict(survived, errors)` is the one place the run's exit code is
decided: 2 when a mutant could not be applied (it was never measured,
and that outranks everything), 1 when one survived, 0 otherwise.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Row 6 was GREEN with R761 100 % rejected: every element of a refused document
is booked as a coded rejection, so u = 0 and d = 0 and the bundle is empty.
`refused_whole` asks that question on its own now -- the build order asked for
an honest red there, and PM re-measured the green on 2026-09-18 with
`okf build` exiting 1 unseen.
A skipped row no longer leaves the verdict unqualified (`GATE GREEN (row 6 not
run: ...)`), and the exit code is non-zero locally when a corpus source is on
the machine and its row did not run. m-2.
N200 Vegbygging:2024 joins R761 as a second real corpus. R761 holds 0 `fig`,
0 formulas and 0 references, so the only real corpus could not have found the
hole in the STS role map; N200 carries 194 citations, 49 figures and 135
footnotes. A `.json` whose root holds an STS node tree is counted as STS
rather than as keys and leaves -- the container is not the content.
M-4: the review's 26 mutants, ported to the code as it stands, plus 8 for the
new checks. 34 of 34 killed. `tools/okf_gate_mutants.py` runs on a copy of the
tree, and a pattern that does not match is an ERROR and exit 2 -- a mutant
that could not be applied was never measured. That fired once, on M13, after a
refactor moved the line it edits.
m-3: `APPROVED_EXCEPTIONS` was read by no row, so approving one changed
nothing. Each pair is now checked against the witness's own vocabulary and the
run says why it moves no denominator. The gate also prints its OWN limits
beside the verdict, m-5 among them.
The product's accounting tests state the new truth instead of the old one:
`okf build --accounting` over the fixture corpus exits 1 with SIX unaccounted
elements in its own vocabulary -- its first real finding, reachable only now
that fixtures carry the constructs. Four shared element names disagree with
the witness, each pinned with its cause; one of the four is a double count
this package makes (a text box's paragraph, once inside the box and again in
the paragraph carrying it).
Three fixture defects were found and fixed while building them, each of which
would have reported a loss the build never had: a shared string table not
related to the workbook, a `graphicData` with no `uri`, and an odt
`styles.xml` without `<office:styles/>`.
Report: docs/2026-09-18-regnskapsgaten-herdet.md
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>