test(consume): hit@8 over six questions against a random-ranker baseline

hit@8 = 5 of 6, every hit at rank 1, against a chance baseline of 1.35 of 6
over a denominator of 629 concepts per question. Wall time 0.51-0.56 s per
question; spent 17 970 - 74 838 bytes against a 120 000 limit.

Two things this measurement did NOT establish, both in the report:

- BOTH known-negative controls FAILED. A question the bundle has no answer to
  still returns eight excerpts, because no natural Norwegian question is
  lexically disjoint from a 629-concept corpus under a four-character
  shared-prefix rule -- measured per token, the interrogative `hvor` reaches 40
  concepts, `brukes` 83. So `no_lexical_match` works per concept and not as a
  whole-question gate: an empty excerpt list is evidence of absence, a full one
  is not evidence of presence. The fix is named (rarity weighting) and NOT
  built, because this step's fence freezes the instrument before it is measured.
- The question texts were written during execution, after the ranker existed.
  The plan recorded the gold documents' SIZE profile -- its per-row baselines
  sum to 1.35 and the sizes used here reproduce that exactly, which is an
  independent check that this is the set the plan profiled -- but it recorded no
  question texts, and three of six gold documents could not be pinned uniquely
  from the sizes. Not a blind evaluation, and the report says so.

The scorer is a tool, not a script in a document: `tools/okf_consume_measure.py`
takes the gold set as an INPUT because it is tracked in a public repository and
an answer key names a consumer's documents. hit_rank, both chance baselines and
the document-size census are unit-tested; the corpus run is a measurement.

Public-file rule, checked with a pattern DERIVED from the corpus's own 39
document names rather than hand-picked, and shown able to find first (67 hits on
the bundle's own index): zero corpus document names in any tracked file in this
repository. One leak was found and removed on the way -- a corpus concept name
in a code comment and a hardcoded corpus path in a test.

Suite run after git add: 1230 passed, mypy --strict clean on 27 files,
ruff clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-07 09:37:14 +02:00
commit d7751c0b9a
6 changed files with 598 additions and 39 deletions

View file

@ -491,19 +491,19 @@ MIN_TOKEN_LENGTH = 3
#: How many leading characters two tokens must share to count as a match.
#:
#: THIS INSTRUMENT'S OWN CONSTANT, and a measurement rather than a preference.
#: Token equality fails on Norwegian compounds: the question word `prisene`
#: equals none of a price-form concept's `title`, `source_file` or path tokens.
#: Plain substring containment does not save it either -- neither `prisene` nor
#: `prissammenstilling` contains the other. A shared prefix does: `pris|ene` and
#: `pris|sammenstilling` share 4.
#: Token equality fails on Norwegian compounds: a question's inflected noun
#: equals none of the tokens in a concept's `title`, `source_file` or path when
#: the concept spells the same subject as a compound. Plain substring
#: containment does not save it either -- of `varene` and `varemottak`, neither
#: contains the other. A shared prefix does: `vare|ne` and `vare|mottak` share 4.
#:
#: MEASURED HERE, 2026-09-07, over the 629-concept K2 corpus for the question
#: token `prisene`: a 4-character floor matches **3** concepts -- over the
#: concept id alone AND over title + `source_file` + id together, the same 3 --
#: and the price-form gold is among them. The plan this implements recorded 6
#: for the same measurement; 6 is not reproducible with this rule, and the
#: number that is reproducible is the one carried here. A 3-character floor
#: over-matches Norwegian function words.
#: MEASURED 2026-09-07 over a 629-concept corpus, for one question's subject
#: token: a 4-character floor matches **3** concepts -- over the concept id
#: alone AND over title + `source_file` + id together, the same 3 -- and the
#: gold concept is among them. The plan this implements recorded 6 for the same
#: measurement; 6 is not reproducible with this rule, and the number that is
#: reproducible is the one carried here. A 3-character floor over-matches
#: Norwegian function words.
MIN_SHARED_PREFIX = 4
_TOKEN_SPLIT_RE = re.compile(r"[^0-9a-zà-öø-ÿ]+")