feat(propose): --shell-parent points a heading-only section at the ancestor holding its text

A plan entry whose span holds its heading alone gets `parent_id` naming the
nearest preceding entry at a smaller level whose own span holds text, passing
over an ancestor that is empty too; the door writes the existing `parent:`
key. Nothing is copied and no boundary moves. The rule reads the plan's level
and order, never the row. Off by default: `okf consume` reads no `parent`
key, so no payload ranks differently, while the flag moves the bytes of every
bundle holding a heading-only section.

Measured before building on one 2 761-concept process code: 710 concepts are
heading-only; the level route names the ancestor the document's own <sec>
nesting names on 708 of 710 (two sit at depth 7, clipped to 6, and point one
level too high), where reading section numbers gets 686 (`12` begins with
`1`); 35 have no ancestor holding text and get none.

The red test expected only concept files to move. The index is a projection
of the frontmatter and shows the key as a facet, so the test now holds both;
the facet renders a segment id as unresolved (`p1?`), because `structure`
reads `parent` as a document number -- named in README, CLAUDE.md and the
CHANGELOG, not repaired here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-11 05:14:15 +02:00
commit edd3b70a90
6 changed files with 140 additions and 4 deletions

View file

@ -596,6 +596,21 @@ and fixtures, never code.
which would make that door claim a Door B file) is refused before anything
is read. `okf project` does not take it -- it owns no flag that moves a
bundle's bytes.
- **`--shell-parent` (K3-20) is OFF and is not a segmentation flag either**:
a plan entry whose span holds its heading alone gets `parent_id` naming the
nearest PRECEDING entry at a smaller level whose own span holds text
(`propose._link_shells`), passing over an empty ancestor; the door writes
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 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,
clipped to 6), where reading section numbers gets 686 (`12` begins with
`1`). 35 of 710 have no ancestor holding text and get none. Off because
`okf consume` reads no `parent` key. **The index renders every such parent
UNRESOLVED** (`parent: p1?`): `structure` reads `parent` as a document
NUMBER, and a segment id answers to none -- the one key with two meanings
`inbox.py` already names for a declared parent. Report:
`docs/2026-09-11-k3-runde20-delt-katalog-og-arvet-kontekst.md`.
- **A TWELFTH flag, `--pdf-outline`, is OFF** (round 12, 2026-09-10) and it is
the only one here that does not read the extracted text at all: it cuts a PDF
at the boundaries its own `/Outlines` bookmark tree declares. It is NOT Arm D