docs(k3): round 16, the whole title takes the route precision could not

The report, the CHANGELOG entry under [Unreleased] and the README's ranking
section. No version bump and no tag: v0.8.0 was released this same day.

R761, delivered ranks, before -> after: hit@1/8/50 3/6 - 5/6 - 5/6 -> 6/6 -
6/6 - 6/6 at default k and 3/6 - 5/6 - 6/6 -> 6/6 - 6/6 - 6/6 at --k 50, with
the known-positive at rank 1 on all four and the known-negative still not a
hit. --no-title-covered on the new binary reproduces the old row exactly.

Nothing else moves, measured on the bytes: the pinned K2 bundle and Arm B keep
(1,1,1,1,1,5) with payloads byte-identical on 6 of 6 questions each,
n100/n200/n500 payloads byte-identical on 5 each, the 828-file HTML corpus at
828 plans / 0 unreadable / 6 015 md with diff -rq empty, the five-document
folder diff -r-identical at 26/52, and okf project still byte-equal to okf
build.

README's test count corrected to what this round measures: 1583 collected,
1582 passed, 1 skipped. The published 1575 was the passed count.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-10 22:26:57 +02:00
commit 4d1b5222b7
4 changed files with 392 additions and 9 deletions

View file

@ -7,6 +7,65 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- **`--title-covered` (ON by default, opt out with `--no-title-covered`): a
question that accounts for a concept's WHOLE title reads that concept first.**
On the 2 761-concept bundle of one standard, the answering section was
delivered at rank 1 on **3 of 6** scored questions and **none of the reading
side's six flags moved that number** -- the whole sweep sits at 3/6 or worse.
Measured on that bundle, before and after: hit@1/8/50 **3/6 - 5/6 - 5/6 ->
6/6 - 6/6 - 6/6** at default `k` and **3/6 - 5/6 - 6/6 -> 6/6 - 6/6 - 6/6** at
`--k 50`, with the known-positive holding rank 1 at both and the
known-negative still not a hit. S1 4 -> 1, S5 not delivered -> 1, S6 3 -> 1.
- **THE DEFECT IS THAT BOTH LEXICAL SIGNALS ARE UNNORMALISED COVERAGE
COUNTS.** They measure how much of the QUESTION a candidate answers and
nothing measures how much of the CANDIDATE the question accounts for, so a
section titled with the question's subject alone scores what a narrower
section titled with that subject PLUS a qualifier scores, and then loses on
the body count. Decomposed per miss: S1 turns on `hvordan`, an interrogative
pronoun; S5 on `hvilke` and `stilles` in a body 7x the gold's, and on
`betonghvelv ~ betongkonstruksjoner` through the four-character stem
`betong`; S6 on an exact tie broken by `concept_id`.
- **A PARTITION, never a fourth RRF signal, and the arithmetic is why.** RRF
consumes ranks alone, so with shared ranks a rule whose positive group has
`m` members is worth `1/61 - 1/(61 + m)` -- a rule firing on ONE concept of
2 761 is worth 0.00026 against a body gap of 0.0029. **A precise rule is
worth LEAST under this fusion.** Measured as a signal it moves hit@1 not at
all (3/6, both as a third and as a fourth signal); as a partition it reaches
6/6. `lookup_hits` is the same shape for the same measured reason, and it
still wins: the new partition lands below it, with a test and its control.
- **By EQUALITY, never by shared prefix.** Four shared leading characters take
the group from 1 to 6 on one question and 9 to 31 on another, with the
answering section falling to candidate rank 6 and the known-positive to 2.
- **TWO CANDIDATE REPAIRS WERE MEASURED AND FELLED FIRST.** Pivoted length
normalisation of the body signal collapses at every value swept
(b = 0.25/0.5/0.75/1.0 -> hit@8 3/6, 1/6, 1/6, 0/6, and at b = 1.0 the
known-positive falls to rank 49): the median concept holds 22 tokens against
a mean of 60, so length normalisation promotes thousands of tiny concepts.
Title PRECISION as a signal reaches candidate hit@1 5/6 and takes the
known-positive from 1 to 4 every time it does.
- **NOTHING ELSE MOVES AND IT IS MEASURED ON THE BYTES.** The pinned K2 bundle
keeps `(1,1,1,1,1,5)` and its 7 pin tests, Arm B keeps `(1,1,1,1,1,5)`, and
the payloads on both are **byte-identical on 6 of 6 questions**; n100/n200/
n500 payloads are byte-identical on 5 questions each; the 828-file HTML
corpus still gives 828 plans, 0 unreadable and 6 015 md with `diff -rq`
empty; the five-document folder is `diff -r`-identical at 26 concepts / 52
md; `okf project` stays byte-equal to `okf build`. hit@k on n100/n200/n500
is **NOT MEASURED** -- this repository holds no gold set for them, which is
0 gold sets and not 0 hits.
- **THIS IS THE FOURTH READING-SIDE CHANGE THAT MOVES A PAYLOAD WITH NO BUNDLE
CHANGING.** A consumer pinned to the previous excerpt order needs
`--no-title-covered`. The rule fires on **0 of 21** measured cells outside
that one bundle, so "no regression" there means it never fires -- not that
it fires harmlessly. Report:
`docs/2026-09-10-k3-runde16-hele-tittelen-tar-ruten.md`.
- `build_payload`'s signature defaults are now held equal to the consume CLI's
argparse defaults by a test, for every same-named parameter. This is O6's
defect in the other command: `cli.build` defaulted two flags `False` in the
signature and `True` in argparse, and a caller reaching it as a function read
the signature.
## [0.8.0] — 2026-09-10
### Added

View file

@ -408,6 +408,46 @@ number that had stopped being true in the same commit. A flag's "off by
measurement" is a measurement of a *configuration*, not a property of the flag.
`docs/2026-09-10-k3-runde7-forste-spenn-og-rangeringen.md`.
`--title-covered` is **on** by default since 2026-09-10 (opt out with
`--no-title-covered`), and it is the fourth widening here that alters a payload
with no bundle changing. A concept whose EVERY title token is a token of the
question is read before the concepts the fusion ranked above it. The defect it
repairs is that both lexical signals are unnormalised COVERAGE COUNTS: they
measure how much of the question a candidate answers, and nothing measures how
much of the CANDIDATE the question accounts for, so a section titled with the
question's subject alone scores exactly what a narrower section titled with that
subject plus a qualifier scores — and then loses on the body count, because a
longer title and a longer body can only reach more of the question. Measured on
a 2 761-concept bundle of one standard, where **none of the six flags above
moved the number at all**: hit@1/8/50 **3 of 6 · 5 of 6 · 5 of 6 → 6 of 6 · 6 of
6 · 6 of 6** at default `k`, the same 6 of 6 at `--k 50`, the known-positive
holding rank 1 at both and the known-negative still not a hit. The three
recovered rows go 4 → 1, not-delivered → 1 and 3 → 1.
It is a PARTITION and not a fourth RRF signal, and the arithmetic is the
reason: RRF consumes ranks alone, so with shared ranks a rule whose positive
group has `m` members is worth `1/61 1/(61 + m)`, and a rule firing on ONE
concept of 2 761 is worth 0.00026 against a body-signal gap of 0.0029 — **a
precise rule is worth least under this fusion, backwards from what precision is
for**. Measured as a signal the same predicate moves hit@1 not at all; as a
partition it reaches 6 of 6. `lookup_hits` is the same shape for the same
measured reason, and it still wins: this partition lands below it. The title is
read by EQUALITY, never by shared prefix — four shared leading characters take
the group from 1 to 6 on one question and 9 to 31 on another, with the answering
section falling to candidate rank 6 and the known-positive to 2.
Two candidate repairs were measured and felled first. Pivoted length
normalisation of the body signal collapses at every value swept (b = 0.25, 0.5,
0.75, 1.0 give hit@8 3, 1, 1 and 0 of 6, and at 1.0 the known-positive falls to
rank 49), because the median concept holds 22 tokens against a mean of 60 — so
length normalisation promotes thousands of tiny concepts over the section that
treats the subject. Title *precision* as a signal reaches candidate hit@1 5 of 6
and takes the known-positive from rank 1 to 4 every time it does. The reach of
what shipped is narrow and stated as such: it fires on 6 of 8 questions on that
bundle and on **0 of 21** measured cells across the pinned K2 bundle, Arm B and
the three N bundles, whose payloads are byte-identical either way.
`docs/2026-09-10-k3-runde16-hele-tittelen-tar-ruten.md`.
It emits the § 8 shape — `contract`, `bundle` (`bundle_id` plus a
`sha256-tree:` content identity), `budget` (unit, instrument, limit, spent and a
validated known-positive), `denominators`, `excerpts` and `withheld` — and every
@ -764,12 +804,14 @@ From a checkout, the test suite runs with:
.venv/bin/python -m pytest
```
The suite is the verification surface for everything above: **1575 tests**,
run on 2026-09-10 against the `v0.8.0` release commit with the `[extract]`
extra installed.
The suite is the verification surface for everything above: **1583 tests
collected, 1582 passed and 1 skipped**, run on 2026-09-10 with the `[extract]`
extra installed. Both numbers are given because they are two measurements: the
figure published before this round was the PASSED count, and `pytest
--collect-only -q` reported one more.
(The figure stood at 596 until 2026-09-09 — measured 2026-08-21 and never
updated as the suite grew — and at 1515 until this release: a count is a
measurement with a date on it.)
updated as the suite grew — at 1515 until the `v0.8.0` release and at 1575
through it: a count is a measurement with a date on it.)
Without the extra the same suite skips the tests covering the parser path;
that split was last counted on 2026-08-21 as 589 passed and 7 skipped and has
**not** been re-measured since. The tests holding the fail-fast rejection for

View file

@ -0,0 +1,282 @@
# K3 round 16 — a question that accounts for the WHOLE title takes that section first
Round 15's bundle of one standard delivered the answering section at rank 1 on
**3 of 6** scored questions, and none of the reading side's six flags moved that
number. This round decomposes the three misses, falsifies two candidate repairs
on the corpus, and ships one rule: `--title-covered`, on by default, opt-out
`--no-title-covered`.
Commits: `14ae36a` (red test) · `6bb2189` (the rule) · `ff06b92` (the two
guarantees this round states) · this report.
## 0 Deviations from the order, stated before anything is built on them
Every premise the order named was reproduced. Two readings differ, and in both
cases the number below is the one measured here.
| premise | order | measured here | command |
|---|---|---|---|
| HEAD | `02f9876` | `02f9876` | `git log -1` |
| tag `v0.8.0` | exists, annotated, on `4d1f9d3` | exists, on `4d1f9d3` | `git tag --points-at 4d1f9d3` |
| version | `0.8.0` | `0.8.0` | `grep -n '^version' pyproject.toml` |
| remote `main` | `078b7df` | `078b7df` | `git ls-remote origin refs/heads/main` |
| worktree | clean | clean, `uv.lock` untouched | `git status --short` |
| suite at HEAD | 1575 passed, 1 skipped | **1575 passed, 1 skipped**, 95.84 s | `pytest -q` |
| collected at HEAD | 1576 | **1576** | `pytest --collect-only -q` |
| R761 build | rc 0, 23.2 s, 2 737 dirs, 2 761 concepts | rc 0, **25 s**, 2 737 dirs, **2 761** concepts | `okf build inn-xml …` |
| R761 at default `k` | 3/6 · 5/6 · 5/6, KP 1 | **identical**, and S1 rank 4 · S5 not delivered · S6 rank 3 | `hitk_sk2.py` |
| R761 at `--k 50` | 3/6 · 5/6 · 6/6, KP 1 | **identical** | `hitk_sk2.py --k 50` |
**Deviation 1.** The order's table gives S1 rank **4**; that is its rank at
default `k`. At `--k 50` it is **3**. Both are measured here; the order states
only the first and the two are not in conflict.
**Deviation 2, and it is about an INSTRUMENT rather than about the code.** The
sweep harness written for this round ranks CANDIDATES and the published figures
are DELIVERED ranks, so the two do not agree and must not be read as one number.
On the same bytes the harness gives S1 5 · S3 2 · S6 3 where the CLI delivers
4 · 1 · 3: the cut runs after the fusion and removes candidates above the gold.
Every harness figure in § 3 is labelled `candidate rank`; every figure in § 4 and
§ 5 came out of `okf consume` itself.
Everything was measured in frozen `git archive` exports under
`/tmp/k3r16/{export,export2}`, each `uv sync --frozen --extra extract`, using
that export's own `.venv/bin/okf`. `~/repos/vegnormal-okf` and
`~/okf-test/dokumenter` were read and never written.
## 1 The diagnosis, per miss
The fusion has three signals. Two are lexical COVERAGE COUNTS — one per question
token the candidate answers to, over the title-and-id text and over the body.
The third is the document prior.
**The third signal carries no information on this bundle, and that is measured
rather than inferred.** `document_score` is keyed on
`concept_id.split("/", 1)[0]`, which is the source document; R761 is one XML
file, so the prior takes **one distinct value over all 2 761 concepts**. With
`tie_shared_rank` on, every concept receives the same constant from it. The
order's hypothesis is CONFIRMED. Its evidence — that `--no-tie-shared-rank`
drops hit@1 to 0/6 — is confirmed too: a signal that separates nothing still
imposes an alphabetical order when the tie-break is by id.
So on this bundle the ranking is decided by two coverage counts, and the
question is which of them turns each miss over. Decomposed per candidate, with
the question tokens each one answers:
**S1** — «Hvordan er Prosesskoden delt inn i hovedprosesser?», tokens
`(hvordan, prosesskoden, delt, inn, hovedprosesser)`.
| rank | concept | title cov | body cov | body tokens answered | bytes |
|---|---|---|---|---|---|
| 1 | `11/oversikt-over-prosesser` | 1 | 3 | prosesskoden, delt, hovedprosesser | 114 728 |
| 2 | `hovedprosess-81-l-smasser` | 1 | 3 | **hvordan**, prosesskoden, hovedprosesser | 2 103 |
| 3 | `hovedprosess-83-…` | 1 | 3 | — | 14 529 |
| 4 | `hovedprosess-84-betong` | 1 | 3 | **hvordan**, prosesskoden, hovedprosesser | 4 410 |
| **5** | **`2-1/hovedprosesser`** | 1 | **2** | prosesskoden, hovedprosesser | 1 047 |
The body signal turns it over, and the token it turns on is `hvordan` — an
interrogative pronoun. The title signal separates nothing: every one of these
scores 1 and sits in a tie group thousands of concepts wide.
**S5** — «Hvilke krav stilles til armering i betongkonstruksjoner?».
| rank | concept | title cov | body cov | body tokens answered | bytes |
|---|---|---|---|---|---|
| 1 | `84-4/betongst-p` | 1 | **5** | **hvilke**, krav, **stilles**, armering, betongkonstruksjoner | 19 658 |
| 2 | `34-43/armering-av-betonghvelv` | **2** | 3 | krav, armering, betongkonstruksjoner | 442 |
| … | | | | | |
| **12** | **`84-3/armering`** | 1 | 3 | krav, armering, betongkonstruksjoner | 2 759 |
Two mechanisms, not one. The rank-1 concept wins on `hvilke` and `stilles`,
both grammatical; its body is 7x the gold's, and a longer body can only reach
MORE distinct question tokens. The rank-2 concept wins on the TITLE, at
`betonghvelv ~ betongkonstruksjoner` through the four-character stem `betong`
a longer title can only reach more too.
**S6** — «Hva omfatter inspeksjon av bruer og konstruksjoner?».
| rank | concept | title cov | body cov | body tokens answered | bytes |
|---|---|---|---|---|---|
| 1 | `88-14/enkel-inspeksjon` | 1 | 4 | omfatter, inspeksjon, bruer, **konstruksjoner** | 446 |
| 2 | `81-6/masser-…-konstruksjoner-under-vann` | 1 | 3 | omfatter, bruer, konstruksjoner | 715 |
| **3** | **`88-1/inspeksjon`** | 1 | 3 | omfatter, inspeksjon, bruer | 585 |
Rank 2 is a TIE with the gold on both signals, broken by `concept_id` — the
declared tie-break, doing what it is declared to do because nothing else
separates them.
**The order's reading of the pattern is confirmed and can be stated more
precisely.** The three golds carry the bare term as their title
(`Hovedprosesser`, `Armering`, `Inspeksjon`) and lose to a title that is that
term plus a qualifier, or to a much larger neighbour. The mechanism under all
three is one thing: **both signals measure how much of the QUESTION the
candidate answers, and nothing measures how much of the CANDIDATE the question
accounts for.** Coverage is recall with no precision beside it, so surface area
— a longer title, a longer body — can only help.
What does not fit the order's phrasing: on S6 the gold is not beaten by the
larger neighbour at all, it is beaten by `concept_id` order at an exact tie, and
on S1 the deciding token is a pronoun rather than a qualifier. Both are the same
defect seen from different sides.
**It is not a segmentation miss on this bundle, and the control says so.**
`bundle-xml/<doc>/2-1`, `/84-3`, `/88-1` and `/1` all exist as concept
directories. On the PDF arm (`build/sk2-bundle-default`, read only)
`find . -maxdepth 2 -type d -name '22' / '53' / '1'` are all EMPTY — only
`22-1`, `53-1` … exist — so S3/S4/KP are segmentation misses there. That is the
known-positive proving the presence query can find a difference.
## 2 Two candidate repairs, measured and FELLED
Both were measured on the corpus before the shipped rule was written.
**Length normalisation of the body signal — falsified.** The textbook answer to
"unnormalised coverage favours long documents" is pivoted length normalisation,
`cov / (1 - b + b*len/avg)`. Swept at b = 0.25, 0.5, 0.75, 1.0 over the eight
questions (candidate ranks):
| b | hit@1 | hit@8 | S1 | S3 | S4 | S5 | KP |
|---|---|---|---|---|---|---|---|
| off (baseline) | 2/6 | 5/6 | 5 | 2 | 1 | 12 | 1 |
| 0.25 | 1/6 | 3/6 | 3 | 55 | 72 | 42 | 1 |
| 0.5 | 1/6 | 1/6 | 32 | 90 | 61 | 183 | 1 |
| 1.0 | 0/6 | 0/6 | 59 | 96 | 64 | 200 | **49** |
It collapses at every value including the known-positive. The reason is the
corpus's shape: the median concept holds **22** tokens against a mean of 60, so
thousands of tiny concepts mentioning a term once are promoted over the section
that treats it. Length is not what is wrong with the body signal.
**Title precision as a signal — falsified on the control.** `|Q ∩ T| / |T|` over
the title alone reaches candidate hit@1 5/6 in one arrangement, and takes the
known-positive from rank 1 to **4** every time it does. KP's gold is titled
`Bruksområder for Prosesskoden` — a phrase, one of whose three tokens the
question answers — so a ratio that rewards short titles demotes it. The fasit's
own comment says a KP below rank 1 means the instrument is broken, so this is
not a trade to make.
## 3 Why a PARTITION and not a fourth signal
The order asks for this to be answered rather than assumed, and the arithmetic
answers it.
RRF consumes RANKS ALONE, so one signal contributes at most `1/(RRF_K + 1)`.
With shared ranks, a signal whose positive group has `m` members gives the group
position 1 and everyone else position `m + 1` — so its whole separating power is
`1/61 - 1/(61 + m)`. **A rule that fires on ONE concept of 2 761 is worth
0.00026**, while the body-signal gap it must close on S1 is
`1/61 - 1/74 = 0.0029`, an order of magnitude larger. **A precise rule is worth
LEAST under this fusion, exactly backwards from what precision is for.**
Measured, not just derived. The same title-subset predicate, as a signal:
| form | hit@1 (candidate) | hit@8 | S1 | S5 | S6 | KP |
|---|---|---|---|---|---|---|
| baseline | 2/6 | 5/6 | 5 | 12 | 3 | 1 |
| as a 3rd signal (replacing the dead prior) | 3/6 | 6/6 | 5 | 2 | 2 | 1 |
| as a 4th signal | 3/6 | 6/6 | 5 | 2 | 2 | 1 |
| **as a PARTITION** | **6/6** | **6/6** | **1** | **1** | **1** | **1** |
This is the same measurement `concept_scores` already records for `lookup_hits`:
a fourth RRF signal put the named concept at 26/15/19 of 446/1 133/270 and
delivered none of them, so the lookup became a partition. The rule shipped here
is that shape for the same reason, and the figures above are its own — not
borrowed from that one.
## 4 The rule
`title_covered_hits(concepts, question)` returns the concepts whose EVERY title
token is a token of the question. `concept_scores` reads them first, keeping the
fusion's order inside each part, BELOW the lookup partition.
**By equality, never by shared prefix.** `tokens_match` accepts four shared
leading characters. Under a prefix-matching form the group goes 1 → 6 on S1 and
9 → 31 on S5, and the gold falls to candidate rank 6 with the known-positive to
2. Under equality both hold rank 1. The precedent is `tokens_match`'s own rule
that an identifier matches by equality alone.
**Reads `title` and not the concept id.** An id segment is this library's own
reduction of the title, so counting it would let the same words qualify twice,
and on a single-document bundle the id carries a uuid that is in no question.
**Reach, measured, and it is narrow.** Group size per question on R761:
| S1 | S2 | S3 | S4 | S5 | S6 | KP | KN |
|---|---|---|---|---|---|---|---|
| 1 | 1 | 1 | 1 | 9 | 2 | **0** | **0** |
It fires on 6 of 8 questions there and on **0 of 6** K2 questions and **0 of 15**
N-bundle cells (§ 5). It never fires on the known-negative.
## 5 The row, and every other row measured
**R761, delivered ranks from `okf consume`, 2 761 concepts, one source document:**
| | before, default `k` | after, default `k` | before, `--k 50` | after, `--k 50` |
|---|---|---|---|---|
| hit@1 | **3/6** | **6/6** | **3/6** | **6/6** |
| hit@8 | 5/6 | **6/6** | 5/6 | **6/6** |
| hit@50 | 5/6 | **6/6** | 6/6 | **6/6** |
| KP rank | 1 | **1** | 1 | **1** |
| KN | not a hit | **not a hit**, same top-1 | not a hit | not a hit |
| S1 · S5 · S6 | 4 · · 3 | **1 · 1 · 1** | 3 · 11 · 3 | **1 · 1 · 1** |
**The known-negative on the same bytes.** `--no-title-covered` on the NEW binary
reproduces the old row exactly — S1 4, S5 not delivered, S6 3, hit 3/6 · 5/6 —
identical row for row to the OLD binary at shipped defaults. The pin names its
own cause.
**Nothing else moves, and it is measured on the bytes:**
| row | denominator | before | after |
|---|---|---|---|
| K2 pinned default bundle, hit@8 ranks | 6 questions, 453 concepts | `(1,1,1,1,1,5)` | **identical**, payloads **byte-identical on 6 of 6** |
| Arm B bundle, hit@8 ranks | 6 questions, 629 concepts | `(1,1,1,1,1,5)` | **identical**, payloads **byte-identical on 6 of 6** |
| `tests/test_default_bundle_pin.py` | 7 tests | 7 passed | **7 passed**, file unedited |
| n100-2023 | 5 questions, 446 concepts | — | payloads **byte-identical**, rule fires 0 of 5 |
| n200-2024 | 5 questions, 1 133 concepts | — | payloads **byte-identical**, rule fires 0 of 5 |
| n500-2024 | 5 questions, 270 concepts | — | payloads **byte-identical**, rule fires 0 of 5 |
| 828-file HTML corpus | 828 documents | 828 plans, 0 unreadable, 6 015 md | **828 plans, 0 unreadable, 6 015 md**; `diff -rq` empty apart from `log.md`'s converter PATH (same pandoc 3.9) |
| `~/okf-test/dokumenter` | 5 documents | 26 concepts / 52 md | **26 / 52**, `diff -r` **EMPTY** |
| `okf project` vs `okf build` | same folder | byte-equal | **byte-equal**, `diff -r` empty |
| suite | — | 1575 passed, 1 skipped | **1582 passed, 1 skipped**, 1583 collected |
| `ruff check src tests tools` · `ruff format --check .` · `mypy src` | ruff 0.16.6 | clean | **clean** (118 files, 21 source files) |
**hit@k on N100/N200/N500 is NOT MEASURED, and the denominator is why:** this
repository holds no gold set for those three bundles — 0 gold sets, not 0 hits.
What is measured there is that the payload does not change.
## 6 Honesty limits
- **N = 6.** hit@k here rests on ONE fasit with SIX scored questions on ONE
corpus from ONE publisher in ONE schema. A move from 3/6 to 4/6 would be one
question; this round moves three. Three questions is not a retrieval
evaluation.
- **The fasit is another repository's and was not touched.** It was set in
`vegnormal-okf` on 2026-09-10 before any lookup ran, and this round read it
and the instrument and wrote to neither.
- **KP and KN are CONTROLS, not results.** Neither enters hit@k. KP holding rank
1 is what says the instrument still counts; KN staying not-a-hit is what says
the rule invents nothing.
- **The PDF arm's zeros on the same questions are a SEGMENTATION miss**, not a
ranking one, and are not comparable with the XML arm's ranks. The presence
check in § 1 is what separates the two.
- **"Solved" means three measured misses were decomposed and the row moved.** It
does not mean a fourth failure shape does not exist. Coverage is still
unnormalised; this rule adds a precision statement about the title and none
about the body.
- **The rule's reach outside R761 is ZERO in everything measured.** "No
regression on K2 and the three N bundles" is really "the rule never fires
there" — 0 of 21 cells — not "it fires and is harmless". A corpus whose
section titles are phrases rather than terms gets nothing from it.
- **S5's group is 9 concepts, all titled `Armering`**, and the fusion's own
order put the right one first. That is one case, not a property: where a
publisher reuses a title, this rule floats all holders and decides nothing
between them.
- **The sweep harness is not the product.** Its candidate ranks and the CLI's
delivered ranks differ by the cut; the falsifications in § 2 and the
arithmetic in § 3 are harness figures, everything in § 4 and § 5 is not.
- **This is the fourth reading-side change that moves a payload with NO bundle
changing.** A consumer pinned to the previous excerpt order needs
`--no-title-covered`. Measured, that consumer is nobody on K2 or the N
bundles: their payloads are byte-identical either way.

View file

@ -1159,14 +1159,14 @@ DEFAULT_STEM_PREFIX = True
#: Round 16. Whether a concept whose WHOLE title the question accounts for is
#: read before the concepts the fusion ranked above it. ON since 2026-09-11.
#: read before the concepts the fusion ranked above it. ON since 2026-09-10.
#:
#: THE DEFECT IT REPAIRS. Both lexical signals are unnormalised COVERAGE
#: COUNTS -- one per question token the candidate answers to -- so nothing in
#: the fusion measures how much of the CANDIDATE the question accounts for. A
#: section titled with the question's subject and nothing else scores exactly
#: what a narrower section titled with that subject PLUS a qualifier scores,
#: and then loses to it on the body count. Measured 2026-09-11 on a
#: and then loses to it on the body count. Measured 2026-09-10 on a
#: 2 761-concept bundle of one standard, where the answering section carries
#: the bare term as its title on three of six scored questions: `Hovedprosesser`
#: behind `Hovedprosess 81 ...`, `Armering` behind `Armering av ...`,
@ -1976,12 +1976,12 @@ def parse_args(argv: list[str] | None) -> argparse.Namespace:
default=DEFAULT_TITLE_COVERED,
help=(
"read a concept whose WHOLE title the question accounts for before "
"the concepts the fusion ranked above it. ON since 2026-09-11. "
"the concepts the fusion ranked above it. ON since 2026-09-10. "
"Measured on a 2 761-concept bundle of one standard: hit@1 over six "
"questions 3 of 6 -> 6 of 6 with the known-positive holding rank 1, "
"where none of the six existing reading-side flags moved that "
"number at all. The title is read by EQUALITY, never by shared "
"prefix. See docs/2026-09-11-k3-runde16-hele-tittelen-tar-ruten.md"
"prefix. See docs/2026-09-10-k3-runde16-hele-tittelen-tar-ruten.md"
),
)
parser.add_argument(