docs(k3): round 21, parent all the way to the reader

The record for K3-21 A-D: what an excerpt, a heading-only body, the checker
and the index now carry, and every gate with its denominator -- the pinned K2
bundle (7 passed in each export), 32 regression payloads, R761 with and
without `--shell-parent` (hit@1/8/50 6/6 at both k, the known-positive at
rank 1, 675 of 710 shells with exactly one link and 0 broken, 710 of 710
pointing at the source's own ancestor after D), consumption 6 of 6 in both
forms, the byte cost against the consumer's 51.0 %, the ranking cost the
link's path carries, and the 35 shells with no ancestor holding text, listed.
Deviations from the order stated first; honesty limits last.

CHANGELOG under Unreleased; README and CLAUDE.md say 710 of 710, 17 rules,
and that the outline mark keeps its depth. The README's project measurement
was re-run (26 concepts, 0 checkout paths, `okf check` 17 rules, 0 findings).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-11 14:28:42 +02:00
commit e98ca6d25f
4 changed files with 407 additions and 8 deletions

View file

@ -7,8 +7,54 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added
- **`parent` reaches the reader (K3-21 A).** `okf consume` resolves a
concept's `parent:` pointer -- a `segment_id`, unique only inside one
document's plan -- among the concepts sharing its `source_file`, and an
excerpt carries `parent: { concept_id, title }`, conditional like
`req_number`; a pointer that lands nowhere is named `parent_unresolved:
true`. A heading-only body whose plan entry has a parent gains ONE line,
`Enclosing section: [<title>](/<bundle-relative path>)` (SPEC § 5.1, § 6.1).
Measured on the one standard with such sections: 675 of 710 carry exactly
one link, 0 broken, 72 265 B = 4.49 % of body bytes; hit@1/8/50 6/6 at both
`k` with the known-positive at rank 1.
- **`okf consume --follow-parent` (K3-21 B, off).** `parent` also carries the
enclosing concept's `text` with that concept's own `sha256`, placed after the
cut from the room it left, in rank order -- the delivered set is the same
with it as without it (16 of 16 payloads); a text that does not fit is cut
and marked `truncated`.
### Changed
- **`okf check` has seventeen rules** (`parent_unfollowable`): a `parent` that
is not a `concept_id` and `title`, names its own excerpt, or names a concept
in neither `excerpts` nor `withheld`. Every "16 rules" line a consumer quotes
is now "17 rules". Contract § 8 gains point 6, and its sentence "additional
members are permitted and are not read by the checker" now says the checker
reads only the members § 8 names. A consumer that does not know `parent`
has nothing to do: it is conditional and absent on every bundle without it.
- **The § 7.4 known-positive moved** (13 238 / 12 893 / 345 -> 14 721 /
14 346 / 375), because it IS the contract document: every payload's
`budget.known_positive` block moves with no bundle changing. Measured on 32
regression payloads, everything outside that block is byte-identical.
- **`--shell-parent` stays off, on a measurement** rather than on "`okf
consume` reads no `parent` key", which A made false: the link's absolute
path repeats the document's directory in 675 bodies and moved the delivered
set on 2 of 8 questions at the default `k` (3 of 8 at `k` 50), hit@k
unchanged.
### Fixed ### Fixed
- **The index resolves a `parent` naming a segment of its own document
(K3-21 C).** 675 of 675 such facets rendered `parent: pN?` while the concept
stood in the bundle; now 0. The two segmented goldens' index files move one
`?` each (4 lines).
- **A declared section below markdown's sixth level keeps its level in the
plan (K3-21 D).** The NISO-STS reader clipped the outline mark to 6 along
with the heading; the mark now carries the declared depth. On one standard
the plan moves on exactly 2 entries (`--shell-parent` only), and 710 of 710
shells point at the ancestor the `<sec>` nesting names (708 before).
- **Frontmatter this library writes is YAML a YAML reader reads back the same - **Frontmatter this library writes is YAML a YAML reader reads back the same
(K3-22).** SPEC § 11 point 1 requires "a parseable YAML frontmatter block" in (K3-22).** SPEC § 11 point 1 requires "a parseable YAML frontmatter block" in
every file. Measured with PyYAML 6.0.3 before the change, the pinned K2 every file. Measured with PyYAML 6.0.3 before the change, the pinned K2

View file

@ -73,7 +73,9 @@ one boundary rule:
and XML has no such universal; the allowlist is load-bearing at 1 701 and XML has no such universal; the allowlist is load-bearing at 1 701
`<italic>` and 1 396 `<bold>` inside that document's prose. The ATX ceiling is `<italic>` and 1 396 `<bold>` inside that document's prose. The ATX ceiling is
6 and STS nesting reaches 7, so the depth is CLIPPED and not dropped: 9 of 6 and STS nesting reaches 7, so the depth is CLIPPED and not dropped: 9 of
2 761 sit at depth 7 and `#######` matches nothing. A `<!DOCTYPE` is REFUSED 2 761 sit at depth 7 and `#######` matches nothing. Since K3-21 the clip is
the HEADING's alone: the `OutlineMark` beside it carries the declared depth,
so the plan reads those 9 at 7. A `<!DOCTYPE` is REFUSED
unparsed with its own code, a guarantee about the code rather than about the unparsed with its own code, a guarantee about the code rather than about the
machine -- measured on 3.14.0 with pyexpat 2.7.3, an external SYSTEM entity machine -- measured on 3.14.0 with pyexpat 2.7.3, an external SYSTEM entity
is refused by the stdlib but the billion-laughs limit comes from libexpat is refused by the stdlib but the billion-laughs limit comes from libexpat
@ -623,8 +625,9 @@ and fixtures, never code.
the existing `parent:` key. Nothing is copied -- a consumer's own build of the existing `parent:` key. Nothing is copied -- a consumer's own build of
the same standard copied the inherited text in and took hit@1 6/6 -> 2/6. the same standard copied the inherited text in and took hit@1 6/6 -> 2/6.
The route reads the PLAN, never the row: on R761 it names the ancestor the The route reads the PLAN, never the row: on R761 it names the ancestor the
`<sec>` nesting names on **708 of 710** shells (the 2 misses sit at depth 7, `<sec>` nesting names on **710 of 710** shells since K3-21 D (708 before: the
clipped to 6), where reading section numbers gets 686 (`12` begins with 2 misses sit at depth 7, and the reader clipped the outline mark to 6 along
with the heading), where reading section numbers gets 686 (`12` begins with
`1`). 35 of 710 have no ancestor holding text and get none. **Since K3-21 `1`). 35 of 710 have no ancestor holding text and get none. **Since K3-21
`okf consume` reads the key** (`consume.link_parents`, resolved among the `okf consume` reads the key** (`consume.link_parents`, resolved among the
concepts of the concept's OWN `source_file`, because `p1` exists in every concepts of the concept's OWN `source_file`, because `p1` exists in every

View file

@ -168,8 +168,10 @@ smaller level, passing over an ancestor that is empty too. It copies no text
and moves no boundary. It exists for a document that states its points once and and moves no boundary. It exists for a document that states its points once and
lets every nested section inherit them: measured on one process code, **710 of lets every nested section inherit them: measured on one process code, **710 of
2 761** concepts are heading-only, and the plan's level and order name the same 2 761** concepts are heading-only, and the plan's level and order name the same
ancestor as the document's own nesting on **708 of 710** (the two others sit at ancestor as the document's own nesting on **710 of 710** since K3-21 (708
depth 7, which a markdown heading clips to 6, and point one level too high). It before: the two others sit at depth 7, and the reader clipped their level to 6
in the plan as well as in the markdown heading, so they pointed one level too
high). It
was off because `okf consume` did not read `parent`. Since K3-21 it does: an was off because `okf consume` did not read `parent`. Since K3-21 it does: an
excerpt carries `parent` as the enclosing concept's `concept_id` and `title` excerpt carries `parent` as the enclosing concept's `concept_id` and `title`
(resolved inside the concept's own document, never the raw segment id), and a (resolved inside the concept's own document, never the raw segment id), and a
@ -596,9 +598,11 @@ puts the project somewhere other than the current directory.
Measured 2026-09-09 from a fresh `uv tool install` with this repository nowhere Measured 2026-09-09 from a fresh `uv tool install` with this repository nowhere
on the path: 5 documents in, **26** concepts out, a skill carrying **0** paths on the path: 5 documents in, **26** concepts out, a skill carrying **0** paths
into any checkout, and `okf check` conformant on its own payload (16 rules, 0 into any checkout, and `okf check` conformant on its own payload (17 rules, 0
findings; the count was 15 until `bundle_mismatch` landed 2026-09-10, and the findings; the count was 15 until `bundle_mismatch` landed 2026-09-10 and 16
pair was re-measured rather than carried over). The 2026-09-08 run of the same measurement reported 15 concepts, and until `parent_unfollowable` landed 2026-09-11, and the pair was re-measured each
time rather than carried over -- the last time from a frozen export of this
repository, with 26 concepts and 0 checkout paths again). The 2026-09-08 run of the same measurement reported 15 concepts, and
that number was the defect rather than the result: `okf project` was calling that number was the defect rather than the result: `okf project` was calling
`build()` as a function and reading its signature's defaults, which disagreed `build()` as a function and reading its signature's defaults, which disagreed
with argparse's on two flags. Two tests now hold the two default sets equal. Before that day the same result took a `PYTHONPATH`, a snapshot of a with argparse's on two flags. Two tests now hold the two default sets equal. Before that day the same result took a `PYTHONPATH`, a snapshot of a

View file

@ -0,0 +1,346 @@
# K3 round 21: `parent` all the way to the reader
**Date:** 2026-09-11 · **Base:** `e717b1c` · **Commits:** `a5cd7c5` (red),
`4f7bd61` (A), `ca83dad` (red), `839bd61` (B), `46e555d` (B, defaults),
`c188a0c` (red), `5970369` (C), `9822e55` (red), `bd13c5f` (D) · **Measured
from:** frozen `git archive` exports of the base and of `4f7bd61`, `839bd61`,
`5970369` and `bd13c5f` (Python 3.11.14, each `__file__` under a scratch
directory), never the working tree and never the `okf` on PATH.
Round 20 gave a section whose body is its heading alone a `parent:` key naming
the nearest ancestor that holds text (`okf build --shell-parent`) -- 675 of
710 such sections in one 2 761-concept standard -- and no reader could see it:
`okf consume` did not read the key, the payload did not carry it, the body held
no link, and the index rendered it unresolved. Four deliveries, in order, each
with its own red test and its own commit: **A** the pointer reaches the excerpt
and the body; **B** the ancestor's text reaches the reader, in two forms, and
both defaults are chosen on numbers; **C** the index resolves the pointer; **D**
the depth-7 trap.
## 0. Where the measurement differs from the order, first
- **HEAD was `e717b1c`, not `4595dde`,** and the suite baseline **1 753
passed, 1 skipped, rc 0**, not 1 667 / 1: K3-22 landed after dispatch. The
shell rule (`--shell-parent`, `propose._link_shells`) is in the tree.
- **The order's R761 build command exits 2 on `e717b1c`.** K3-22 refuses a
`--frontmatter sources=` flow value whose URL carries `?`. Every R761 bundle
here is built with the same command minus that flag (`utgave` kept), so
`sources` falls back to the document's own layer. **The base row still
reproduces round 20's numbers exactly:** hit@1/8/50 6/6 at both `k`, the
known-positive (KP) at rank 1 at both, delivered per question 7 8 7 8 8 8 7
7 at the default `k`.
- **The known-positive moved in every payload.** SS 7.4's known-positive IS
`docs/consumption-contract.md`, and A and B edit its SS 8, so
`budget.known_positive` moves in every payload with no bundle changing
(13 238 / 12 893 / 345 -> 14 455 / 14 083 / 372 -> 14 721 / 14 346 / 375).
Every "byte-identical" row below after A and after B is measured with that
block removed, and the whole-payload count is given beside it.
- **The hit@k instrument moved.** The consumer repository stands on `f783e52`,
not `4f70e9d`; `experiments/hitk_sk2.py` was last changed in `6fad6a2`, as
stated. The scratch copy differs from it in two lines (the payload path,
because a concurrent session writes the hard-coded one), and the form (b)
copy in one more (`--follow-parent` on the `okf consume` call). The consumer
repository's `git status --porcelain` is empty before and after.
- **The generated skill tells a reader to write `/tmp/payload.json`,** a path a
concurrent session shares. Each consumption run used a scratch copy of the
skill whose only change is that path (and, for form (b), the flag line).
- **The link's first design failed on the fixture before it shipped.** Read as
body text, `Enclosing section: [...](/...)` is a bundle-local link target,
and structure derivation turned it into a SECOND relation -- `references:
[/...md?]` with `derived: [references]`, rendered unresolved because nothing
resolves the absolute form. The link is therefore appended after derivation
and screened on its own, the rule `description` already follows.
- **One red test met a mechanism instead of the rule.** B's "no room" case
asked through `build_payload` at `limit == spent`, where the knapsack's
500-byte buckets admit nothing (`budget_admits_nothing`). The green commit
holds the rule at `attach_parent_text` and says so.
## 1. The spec, verbatim, and which paragraph each half leans on
Canonical `SPEC.md` at `ad30107`:
- **SS 4.1, Extensions:** "Producers MAY include any additional keys.
Consumers SHOULD preserve unknown keys when round-tripping and MUST NOT
reject documents with unrecognized fields." -- the ground for the `parent:`
KEY and for the payload member.
- **SS 5.1:** "Lineage is expressed through links, not a dedicated field." --
the ground for the LINK: the key alone is not the spec's form of lineage.
- **SS 6.1:** "Absolute (bundle-relative): begins with `/`, interpreted
relative to the bundle root. This is the **recommended** form because it is
stable when documents are moved within their subdirectory." And: "The
specific kind (parent/child, references, joins-with, depends-on) is conveyed
by the surrounding prose, not by the link itself." And: "Consumers MUST
tolerate broken links: a link whose target does not exist in the bundle is
not malformed; it may simply represent not-yet-written knowledge." -- the
link's form, its two words of prose, and why an unresolved pointer is named
in the payload rather than refused.
Contract SS 8, first paragraph, **changed**: "Additional members are permitted
and are not read by the checker." now reads "Additional members are permitted;
the checker reads only the members this section names." -- because A's rule
reads `parent`, which point 6 now names.
## 2. A: the pointer reaches the excerpt and the body
**The payload.** `consume.link_parents` resolves `parent` among the concepts
sharing the pointing concept's `source_file`: a segment id is unique only
inside one document's plan, so `p1` exists in every document of a
multi-document bundle. One pass over concepts already read, no file opened
again. An excerpt carries `parent: { concept_id, title }` -- never the raw
`segment_id`, which a reader can open nothing with -- and
`parent_unresolved: true` where the pointer lands nowhere. The member is
conditional, like `req_number`.
**What the excerpt carries was chosen on this:** the raw id costs least and
can be followed only by enumerating the bundle, which SS 9.2 forbids; the
concept id is one `Read`; the title is what a citation is made of. Measured
cost of the chosen member: 5 members, about 528 B, over the 60 excerpts of the
eight default-`k` payloads; 34 members, about 3 927 B, over 353 at `k` 50.
**The body.** A heading-only body whose plan entry has a parent gains ONE line:
`Enclosing section: [<title>](/<bundle-relative path>)`. Only such a body --
the segmented goldens' declared parents are bodies holding text, and stay
byte-identical. The two words are English and generic, because the code
cannot know the source's language; the relation they name is true of an
adjudicator's parent and of a shell's nearest ancestor holding text alike.
**The checker.** Seventeenth rule, `parent_unfollowable`: a `parent` that is
not a `concept_id` and a `title`, names its own excerpt, or names a concept in
neither `excerpts` nor `withheld`. Those two lists together name every concept
the pre-pass considered (SS 5.2), so the rule sees a dangling pointer without
opening the bundle. `parent_unresolved` is not a finding (SS 6.1).
| row | result | denominator |
|---|---|---|
| K2 pin in the export, gold set copied in | **7 passed** | 7 |
| K2 default + K2 Arm B + N100/N200/N500 + five-document bundle | **32 of 32 identical without `known_positive`**; 0 of 32 whole | 12 + 15 + 5 |
| K2 ranks, both bundles | `(1,1,1,1,1,5)` unchanged; `parent` members **0** | 6 · 6 |
| five-document bundle, known-negative row | rank 1 unchanged (`[1,1,1,1,2]`) | 5 |
| R761 without the flag | **16 of 16** payloads identical without `known_positive`; bundle `diff -r` only `log.md` (the converter's path) | 16 · 2 761 |
| R761 with the flag, hit@1 · 8 · 50 | **6/6 · 6/6 · 6/6** at both `k`, KP rank **1 / 1** | 6 |
| shells carrying exactly one link | **675 of 710**, 0 with more, **0 broken**, 675 of 675 targets = the `parent` | 710 |
| files differing from the flagged base bundle | 676 = 675 concepts + `log.md`; **0 index files** | 5 518 |
| `okf check` on the flagged payloads | **16 of 16 rc 0, 17 rules, 0 findings** | 16 |
| known-negatives | a dangling `concept_id` and the raw `"p1977"`: **1 finding each, rc 1** | 2 |
| link bytes | **72 265 B = 4.49 %** of all body bytes (D2's inheritance section: 51.0 %); 69.2 % of the 675 linked bodies; median line 103 B, max 247 B | 1 610 590 B |
| shells, PM script / concepts with no source text of their own | **35 / 710** | 2 761 |
**The honest shell count is 710.** The PM script counts non-empty lines not
starting with `#`, and a link line is one; 675 of the 710 now carry a line and
still no text of their own.
**What the link costs in ranking, measured.** hit@k does not move. The
delivered SET does: at the default `k` S2-S6 and KP are identical, while S1
exchanges 3 of 7 places and KN 2 of 7, every newcomer a linked shell; at `k` 50
three of eight questions move (KP 23 in / 19 out). Of the newly delivered
shells, those matching the question ONLY through the link line are 1 of 3
(S1), 4 of 7 (S1 at `k` 50), 6 of 23 (KP at `k` 50) and 0 of 2 / 0 of 8 (KN),
and in every such case through the PATH, never the title: the bundle-absolute
form repeats the document's directory in 675 bodies -- the saturation round 20
took out of the id signal, back in through the body. The rest of the movement
is not decomposed per signal.
## 3. B: the ancestor's text reaches the reader
**Form (a), the pointer**, is A. **Form (b), `okf consume --follow-parent`**,
puts the enclosing concept's `text` inside `parent`, with that concept's own
`sha256`, AFTER the cut and only from the room the cut left, in rank order. A
parent the payload already holds, or one a higher-ranked excerpt carried,
travels once; a text that does not fit is cut to the longest prefix that does
and marked `truncated`. Inherited text therefore cannot displace an excerpt --
the mechanism a consumer measured when copied-in ancestor text pushed the
right section to withheld place 504 and 1 069.
| row | (a) pointer | (b) `--follow-parent` | denominator |
|---|---|---|---|
| hit@1 · 8 · 50, default `k` | 6/6 · 6/6 · 6/6 | **6/6 · 6/6 · 6/6** | 6 |
| hit@1 · 8 · 50, `k` 50 | 6/6 · 6/6 · 6/6 | **6/6 · 6/6 · 6/6** | 6 |
| KP rank, both `k` | 1 / 1 | **1 / 1** | 1 |
| delivered list and withheld list equal to (a) | -- | **16 of 16** | 16 |
| consumption correct | **6 of 6** | **6 of 6** | 6 |
| the fasit section cited first | 4 of 6 | 5 of 6 | 6 |
| `spent`, default `k`, where it differs | S1 28 020, KN 10 514 | S1 30 508, KN 13 260 (the other six equal) | 8 |
| `spent`, `k` 50, largest difference | KP 96 965 | KP 117 782 (12 texts, 0 truncated) | 8 |
| `okf check` | 16 of 16 rc 0 | **16 of 16 rc 0, 17 rules** | 16 |
**The row that is the point: one heading-only section as a reader gets it.**
Question: a shell's own title (33.212). Top-1 is its sibling 33.211, whose
title differs only in a token too short to score; both are shells under
33.2 "Sikringsbolter". Eight excerpts delivered in each form.
| | before A | (a) | (b) |
|---|---|---|---|
| the excerpt's `text` | its heading line | its heading + `Enclosing section: [Sikringsbolter](/.../33-2/sikringsbolter.md)` | same |
| `parent` | absent | `concept_id`, `title` | + `sha256`, `text` (3 847 characters, not truncated) |
| excerpt bytes | 858 | 1 034 | 5 067 |
| payload `spent` | 6 864 | 8 272 | 12 305 |
| what the reader must do to learn what the section inherits | nothing it can do: no pointer | one `Read` of the named concept (SS 2.2: the payload names it reachable) | nothing: it is in the payload |
**The consumption difference is not the form.** S1-S6's answers are never
heading-only sections. The first-cited difference (S4) sits on a payload that
carries no parent at all and is identical in both forms apart from the
known-positive block, so it is the draw, not the form. S1's form (a) answer
used the pointer on its own: it named a delivered shell's enclosing section by
its `parent`.
**Defaults, one sentence each:**
- **`--follow-parent`: off.** It delivers the same set as the pointer by
construction and measured, and on six questions whose answers are never
shells it bought nothing a reader scored, at +2 488 and +2 746 B on the 2 of
8 default-`k` payloads holding a linked shell and up to +20 817 B at `k` 50.
- **`--shell-parent`: off, with the reason rewritten.** "`okf consume` reads no
`parent` key" is false after A; the measured reason is the path saturation
above -- hit@k intact, the delivered set moved on 2 of 8 questions at the
default `k` and 3 of 8 at `k` 50. It moves the bytes of a bundle holding a
heading-only section and nothing else: 0 of 453 K2 bodies are heading-only
and the five-document folder builds byte-identical with it.
## 4. C: the index resolves the pointer
`structure._segment_lookup` keys `(source_file, segment_id)` off each
concept's own frontmatter (`DocumentStructure.declared`, no file read again)
and `resolve_structure` asks it first for a `parent` edge, inside the pointing
concept's document. A value no segment answers to is a document number and is
looked up as before; a pointer naming nothing keeps `?`. The rendering rule is
untouched -- a resolved relation renders as its subject -- so `parent: p1977?`
becomes `parent: p1977`. `consume`'s document prior reads only an index
entry's `label`, never its facets, so C moves no rank.
| row | before | after | denominator |
|---|---|---|---|
| `parent` facets resolved, R761 with the flag | 0 | **675** | 675 |
| `parent` facets with `?` | 675 | **0** (`?` anywhere: 792 -> 117, the unflagged bundle's own count) | 675 |
| concepts whose `derived:` names `parent` | 0 | **0** (the regex finds a fabricated positive) | 2 761 |
| files differing from A's flagged build | -- | 676: index files and `log.md`, **0 concepts** | 5 518 |
| R761 without the flag, five-document folder | -- | only `log.md` differs | 2 |
| segmented goldens | `parent: s0?` | `parent: s0` -- 4 lines; the four goldens `test_the_four_existing_goldens_are_untouched` guards are not among them | 4 |
| hit@k, both `k`; KP | 6/6; 1 | **6/6; 1**, delivered and withheld lists identical to A's, 16 of 16 | 16 |
| regression payloads | -- | **32 of 32 wholly identical to B's** | 32 |
| `okf check` | -- | **16 of 16 rc 0, 17 rules** | 16 |
## 5. D: the depth-7 trap
`_StsReader._walk` wrote one clipped level into the ATX heading and the
`OutlineMark` alike. The heading keeps the clip; the mark carries the declared
depth. The extracted text does not move one character.
**The gate, every row measured:**
| row | result | denominator |
|---|---|---|
| mark levels 1-7 | 28 / 118 / 500 / 1 141 / 868 / **97 / 9** (before: 106 at 6, 0 at 7) | 2 761 |
| extracted text | identical (`text_sha256` equal) | 1 |
| plan without the flag | **0 entries changed** | 2 761 |
| plan with the flag | **2 entries changed**: `p646` and `p647` (36.73211, 36.73212), `parent_id` `p644` (36.732) -> `p645` (36.7321) | 2 761 |
| shells pointing at the ancestor the `<sec>` nesting names | **710 of 710** (708 before); direct parent 533 (531) | 710 |
| concept count | 2 761 | -- |
| bundle with the flag vs C | the 2 concepts, their 2 index files, `log.md` | 5 518 |
| bundle without the flag, five-document folder | only `log.md` | 2 |
| the four goldens | untouched (the suite's own test, repository root) | 4 |
| regression payloads | **32 of 32 wholly identical to C's** | 32 |
| hit@k, both `k`; KP | **6/6; 1**, lists identical to C's, 16 of 16 | 16 |
`_unit_fold`'s unit level, the risk the order named, is not reached: the
declared route closes its candidates with `unit_fold=False`, and the plan
confirms it with 0 changes outside the two entries.
## 6. The 35 shells with no ancestor holding text
No pointer was invented for them. **13** sit at depth 1 with no ancestor at
all; **22** have ancestors, every one heading-only too. **28** are containers
with titled descendants; **7** are leaves. None has a direct lettered point.
| segment | label | depth | titled descendants |
|---|---|---:|---:|
| p3 | 2 | 1 | 4 |
| p9 | 4 | 1 | 8 |
| p11 | 4.2 | 2 | 3 |
| p21 | 8 | 1 | 7 |
| p28 | 8.7 | 2 | 0 |
| p32 | 12 | 1 | 0 |
| p33 | Hovedprosess 1 | 1 | 97 |
| p34 | 11 | 2 | 11 |
| p42 | 11.5 | 3 | 3 |
| p46 | 12 | 2 | 28 |
| p129 | 17 | 2 | 0 |
| p130 | 18 | 2 | 0 |
| p131 | Hovedprosess 2 | 1 | 191 |
| p132 | 21 | 2 | 25 |
| p170 | 23 | 2 | 46 |
| p217 | 24 | 2 | 56 |
| p225 | 24.4 | 3 | 6 |
| p228 | 24.43 | 4 | 3 |
| p249 | 24.6 | 3 | 9 |
| p306 | 27 | 2 | 16 |
| p323 | Hovedprosess 3 | 1 | 331 |
| p653 | Prosess 37 | 2 | 0 |
| p654 | Prosess 38 | 2 | 0 |
| p655 | Hovedprosess 4 | 1 | 218 |
| p874 | Hovedprosess 5 | 1 | 97 |
| p972 | Hovedprosess 6 | 1 | 94 |
| p975 | 62 | 2 | 0 |
| p1033 | 66 | 2 | 14 |
| p1067 | Hovedprosess 7 | 1 | 264 |
| p1108 | 72 | 2 | 19 |
| p1186 | 75 | 2 | 60 |
| p1238 | 75.6 | 3 | 7 |
| p1275 | 77 | 2 | 56 |
| p2108 | Hovedprosess 86 | 1 | 44 |
| p2153 | Hovedprosess 87 | 1 | 229 |
What they are in the source: the front-matter chapters 2, 4, 8 and 12 and the
main processes 1-7, 86 and 87 are containers whose text lives below them, not
above; 17, 18, 37, 38 and 62 are placeholder processes reserved for operation
and maintenance; 8.7 is a worked-example section; the first 12 is the chapter
that introduces the processes. A rule pointing at an ancestor WITHOUT text
would reach at most 22 of the 35, and only with a pointer to another heading.
It is not built.
## 7. Suites and gates
| when | working tree | frozen export |
|---|---|---|
| base | 1 753 passed, 1 skipped | -- |
| A red, after add and after commit | 11 failed (all new), 1 754 passed, 1 skipped | -- |
| A | 1 765 passed, 1 skipped | 1 764 passed, 1 skipped, 1 failed |
| B red | 7 failed (all new), 1 766 passed | -- |
| B / defaults | 1 773 / 1 774 passed, 1 skipped | 1 772 passed, 1 failed |
| C red / C | 3 failed (new), 1 776 / 1 779 passed | 1 778 passed, 1 failed |
| D red / D | 2 failed (new), 1 780 / 1 782 passed | 1 781 passed, 1 failed |
The one export failure is the known artefact
`test_segmented_golden.py::test_the_four_existing_goldens_are_untouched` (an
export is no git repository). `ruff check src tests tools`, `ruff format
--check .` and `mypy --strict src` were clean at every green commit, rc
captured directly. The first red commit (`a5cd7c5`) carried a test file `ruff
format` rewrote in the next one; no other file moved that way. `uv.lock` was
never staged.
## Honesty limits
- **Everything about shells is measured on ONE document (N = 1).** "Every
outline document" is a claim about the code, which reads the plan's level and
order; the fixtures and the five-document folder (0 shells of 26) are the
only other rows.
- **Consumption is one non-deterministic draw per question**, twelve runs on a
subscription (`ANTHROPIC_API_KEY` unset), judged by reading the answer
against the fasit section. Answer texts are not reproduced. The six
questions never have a shell as their answer, so form (b)'s value shows only
in the probe row, and that probe is one question chosen here, not a fasit.
- **"Byte-identical" after A and B excludes `budget.known_positive`.** The
contract document is the known-positive, so whole-payload identity is 0 of
32 across A and B and 32 of 32 across B, C and D.
- **The K2 statement for `--shell-parent` is read off the pinned bundle** (0 of
453 bodies heading-only), not off a rebuild with the flag.
- **The link's ranking cost is attributed only where a newcomer matches
through the link alone;** the rest of the delivered-set movement, and any
effect of the heavier excerpts on the knapsack, is not decomposed.
- **The instrument is someone else's, with two lines changed** (three for form
(b)), and it scores a title or a section-number pair, not an answer.
- **C's "resolved" says a concept of the same document answers the id,** not
that it is the right ancestor; D's 710 of 710 is what checks that, against
the source's own nesting.
- **Conformance is the floor and never the proof.** `okf check` is green on
all 48 flagged payloads here, including the known-negative question's, which
answers nothing.