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

@ -400,7 +400,7 @@ def test_normalise_drops_tokens_under_three_characters() -> None:
def test_normalise_holds_an_identifier_number_as_one_token() -> None:
# MEASURED 2026-09-08 over three vegnormal bundles (446, 1133 and 270
# MEASURED 2026-09-08 over three third-party bundles (446, 1133 and 270
# concepts): `_TOKEN_SPLIT_RE` shatters `10.2-2` into `10`, `2`, `2` and
# `MIN_TOKEN_LENGTH` then drops every piece, so a question naming a
# requirement number reaches the ranker carrying only the word `krav` --
@ -410,7 +410,7 @@ def test_normalise_holds_an_identifier_number_as_one_token() -> None:
assert "10.2-2" in okf_consume.normalise("Krav 10.2\u20142")
assert okf_consume.normalise("3.3.1\u201413") == ("3.3.1-13",)
assert okf_consume.normalise("2.9.2\u201412") == ("2.9.2-12",)
assert okf_consume.normalise("R610.4") == ("r610.4",)
assert okf_consume.normalise("P610.4") == ("p610.4",)
assert okf_consume.normalise("4.2.1") == ("4.2.1",)
@ -1730,7 +1730,7 @@ def test_the_cli_exposes_the_reservation_and_omitting_it_reproduces_the_default_
#: identifier, and the identifier is worth the same as the common word because
#: `_overlap` counts. Synthetic rather than borrowed from a bundle, because a
#: fixture that is a corpus measures that corpus.
RARITY_QUESTION = "Hva krever Krav 10.2-2 i N500? Gjengi det sentrale vilkåret."
RARITY_QUESTION = "Hva krever Krav 10.2-2 i Q500? Gjengi det sentrale vilkåret."
RARITY_GOLD = "krav/c-29"
@ -1765,7 +1765,7 @@ def _rarity_corpus(*, identifier_in_body: bool) -> list[okf_consume.Concept]:
real corpora turned out to have, and it decides whether the weight can do
anything at all -- see the two tests below.
"""
common = "Kravet i N500 gjengir det sentrale vilkåret for anlegget."
common = "Kravet i Q500 gjengir det sentrale vilkåret for anlegget."
concepts = [
_synthetic(f"krav/c-{index:02d}", f"Krav 3.{index}-1 Alminnelig bestemmelse", common)
for index in range(29)
@ -1819,7 +1819,7 @@ def test_counting_leaves_the_identifier_worth_no_more_than_the_common_word() ->
def test_weighting_a_hit_by_its_rarity_lifts_the_identifier_into_the_cut() -> None:
# The arm where the weight can act: the identifier is in the body too, so
# weighting REORDERS the body signal. This is the shape N200 and the K2
# weighting REORDERS the body signal. This is the shape a third-party bundle and the K2
# price sheet have, and both moved (withheld -> delivered rank 8; candidate
# rank 10 -> 2).
concepts = _rarity_corpus(identifier_in_body=True)
@ -1840,7 +1840,7 @@ def test_a_rarity_weight_cannot_move_a_signal_the_gold_already_leads() -> None:
When the identifier is in the title alone, the gold already leads the title
signal by counting, the weight makes its lead larger and its RANK identical,
and the two signals that hold it down cannot see the identifier at all.
Measured on the real bundles: N500 35 -> 35, N100 96 -> 103.
Measured on two real bundles: 35 -> 35 and 96 -> 103.
"""
concepts = _rarity_corpus(identifier_in_body=False)
weights = okf_consume.rarity_weights(
@ -1943,7 +1943,7 @@ def test_a_word_every_concept_carries_weighs_exactly_nothing() -> None:
okf_consume.normalise(RARITY_QUESTION), okf_consume.searchable_text(concepts)
)
assert weights["krav"] == 0.0
assert weights["10.2-2"] > weights["n500"] > 0.0
assert weights["10.2-2"] > weights["q500"] > 0.0
def test_a_question_token_no_concept_carries_is_weighted_but_never_consumed() -> None:
@ -1956,9 +1956,9 @@ def test_a_question_token_no_concept_carries_is_weighted_but_never_consumed() ->
def test_the_weight_is_computed_from_the_bundle_and_not_from_a_constant() -> None:
# Same question, two corpora, two different weights for the same token:
# the number comes from the bundle in hand or it comes from nowhere.
small = okf_consume.rarity_weights(("n500",), ["N500 gjelder", "noe helt annet"])
large = okf_consume.rarity_weights(("n500",), ["N500 gjelder"] + ["noe helt annet"] * 9)
assert large["n500"] > small["n500"]
small = okf_consume.rarity_weights(("q500",), ["Q500 gjelder", "noe helt annet"])
large = okf_consume.rarity_weights(("q500",), ["Q500 gjelder"] + ["noe helt annet"] * 9)
assert large["q500"] > small["q500"]
def test_the_weight_is_off_by_default_and_the_default_payload_is_unmoved() -> None:
@ -2036,15 +2036,15 @@ def test_the_weight_reaches_the_title_signal_and_reorders_it() -> None:
# answers THREE, so counting puts the gold behind all of them; only the
# rarity of the identifier can turn that around, and only if the weight
# reaches the title-and-id signal. Bodies are identical, so the body signal
# decides nothing. This is the N200 shape, where the gold's title-signal
# decides nothing. This is a third-party bundle's shape, where the gold's title-signal
# rank moved 8 -> 4 and the gold went from withheld to delivered.
body = "Denne bestemmelsen gjelder for anlegget."
concepts = [
_synthetic(f"krav/t-{index:02d}", f"Krav 3.{index}-1 N500 gjengir bestemmelsen", body)
_synthetic(f"krav/t-{index:02d}", f"Krav 3.{index}-1 Q500 gjengir bestemmelsen", body)
for index in range(29)
]
concepts.append(_synthetic("krav/t-29", "Krav 10.2-2 Tekniske bygg", body))
question = "Hva krever Krav 10.2-2 i N500? Gjengi det sentrale vilkåret."
question = "Hva krever Krav 10.2-2 i Q500? Gjengi det sentrale vilkåret."
weights = okf_consume.rarity_weights(
okf_consume.normalise(question), okf_consume.searchable_text(concepts)
)
@ -2142,7 +2142,7 @@ def test_a_short_identifier_becomes_reachable_because_equality_has_no_floor() ->
assert okf_consume.tokens_match("9.2", "9.2") is True
assert okf_consume.tokens_match("9.2", "9.3") is False
# The floor still stands for words, which is what it was measured for.
assert okf_consume.tokens_match("veg", "veg") is False
assert okf_consume.tokens_match("ost", "ost") is False
def test_the_identifier_rule_makes_a_unique_number_unique_in_the_document_frequency() -> None:
@ -2162,7 +2162,7 @@ def test_the_identifier_rule_makes_a_unique_number_unique_in_the_document_freque
def test_is_identifier_names_numbers_and_not_words() -> None:
assert okf_consume.is_identifier("3.3.1-13") is True
assert okf_consume.is_identifier("10.2-2") is True
assert okf_consume.is_identifier("r610.4") is True
assert okf_consume.is_identifier("p610.4") is True
assert okf_consume.is_identifier("brannsikring") is False
assert okf_consume.is_identifier("krav") is False
# A bare number is not an identifier: it has no separator, and every page
@ -2273,7 +2273,7 @@ def test_the_lookup_keeps_the_fused_order_among_the_concepts_it_lifts() -> None:
#: and a concept carrying neither address nor locator. It exists because the
#: two real bundles are complementary and neither exercises both forms --
#: measured 2026-09-08, K2 writes `sources` in FLOW form on 629 of 629 concepts
#: and carries `req_number` on 0, while the N500 bundle writes BLOCK form on 270
#: and carries `req_number` on 0, while a third-party bundle writes BLOCK form on 270
#: of 270, carries `req_number` on 269 and carries no locator key at all.
PROVENANCE = PROJECT_ROOT / "tests" / "fixtures" / "consume-provenance"
PROVENANCE_QUESTION = "Hva krever Krav 10.2-2?"
@ -2405,7 +2405,7 @@ def test_every_top_level_source_key_passes_through_including_one_this_library_ne
tmp_path: Path,
) -> None:
# A named list is a list of the producers someone thought of. Measured
# 2026-09-08 on the N500 bundle: 269 of 274 concepts carry
# 2026-09-08 on a third-party bundle: 269 of 274 concepts carry
# `source_element_id`, a locator that repository chose under O3's own rule
# ("the key says what it indexes") and that this library does not write. A
# four-key allowlist drops it, and the excerpt then names a document without
@ -2632,7 +2632,7 @@ def test_a_near_miss_is_named_so_a_reader_can_ask_for_it() -> None:
"""Every entry carries the title and the document, not just the id.
`--withheld-titles` bought the title for all one entry per withheld concept and was off by
measurement (+37.9 % on N500). At twenty entries the same field costs
measurement (+37.9 % on a third-party bundle). At twenty entries the same field costs
nothing and is the one thing that makes the list usable: a reader who sees
a near miss by name can ask for it.
"""