# Q3 — flate vs. hierarkiske bundles: en reell konflikt i method-spec §3 **Status:** funn + retningsvurdering. Spec-en er IKKE endret. Beslutning tas av operatøren. **Foranledning:** spørsmål 3 fra `llm-ingestion-okf` (postkasse `_okf-interim`, trinn C): dør A produserer flate bundles; second-brain-siden (okr, catalog) bruker hierarkisk form med per-nivå-indekser. Sier spec-en noe om dette, og bør den? --- ## 1. Funnet: spec-en sier noe — og den forbyr hierarki, stilltiende Spørsmålet var stilt som om spec-en er taus. Den er ikke det. **method-spec.md:66-69 (§3 Step 1):** > Navigation starts at `index.md` and follows its intra-bundle markdown cross-links > (`](target.md)`). **Targets containing a path separator are out-of-bundle and MUST be > skipped.** Dette er verifisert implementert i MAF-halvdelen, `portfolio-optimiser/src/portfolio_optimiser/okf.py:123-125`: ```python for target in _LINK_RE.findall(index.body): if "/" in target or target in seen: continue # only same-dir bundle files; de-dup repeated links ``` Og okr-siden produserer nøyaktig det som forkastes: - `okr/scripts/okf-index.mjs:110` emitterer underkatalog-pekere som `` `${sd}/index.md` ``. - `okr/lib/okf-links.mjs:23` **krever** ledende `/`: `if (!target.startsWith('/')) return false;` — «maa vaere bundle-root-relativ». Sammensatt: **hver eneste lenke okr produserer inneholder `/`, og hver eneste av dem forkastes av navigatoren.** okr kan ikke engang skrive flatt — `routeLevel()` (`lib/okf-vocab.mjs:71`, konsumert i `lib/innboks-frontmatter.mjs:74`) ruter alltid til en underkatalog. Dette er ikke et kantttilfelle; det er okrs normaltilstand. **Det verste er at feilen er stille.** method-spec.md:72-73 krever det: *«A broken or bundle-escaping cross-link MUST be tolerated — skipped, never raised (OKF robustness rule).»* En hierarkisk bundle gir altså ikke en feilmelding — den gir en read-context som inneholder rot-indeksen og ingenting annet. På okrs eget fixture `tests/fixtures/okf-realistic/` forsvinner alle 8 konseptfiler, fordi ingen av dem ligger i roten. Symptomet operatøren ville sett er «modellen kjente ikke innholdet», ikke «bundelen er ugyldig». **To spec-er kolliderer på samme paragrafnummer — ved et sammentreff.** `catalog`s svar siterer «§3 MUST» for per-nivå-indeks. Det er `catalog/docs/okf-second-brain/spec.md:45`, et *annet* dokument enn method-spec.md §3. De er ikke to lesninger av én regel; de er to normative regimer som tilfeldigvis møtes på «§3». Verdt å holde fra hverandre i all videre diskusjon. ## 2. Hvorfor regelen er gal — den er feil proxy for riktig egenskap Separator-forbudet ble åpenbart skrevet som en *sikkerhets*regel: hindre at en lenke rømmer bundelen. Men den forveksler «inneholder separator» med «rømmer bundelen». `sub/index.md` rømmer ingenting. `../../etc/passwd` gjør det. Og method-spec **har allerede den riktige mekanismen**, to linjer lenger ned (:73): > path resolution MUST be boundary-checked against the bundle directory, fail-closed. Så §3 Step 1 bærer både den presise regelen og en grov proxy — og det er proxyen som gjør skaden. Den presise regelen alene er tilstrekkelig. **Den korrekte formen finnes allerede som fungerende prior art hos okr** (`lib/okf-links.mjs:20-26`): avvis null-byte, backslash, URL-scheme, `..`-segment; krev `.md`; krev bundle-rot-relativ form. Dette er resolve-og-grensesjekk gjort riktig. Retningen er derfor ikke å oppfinne noe, men å løfte disse semantikkene inn i method-spec §3 Step 1 og la separator-forbudet gå ut. ## 3. Retning: la navigatoren traversere hierarki; la dør A fortsatt produsere flatt To beslutninger som med fordel holdes fra hverandre: **(a) Navigasjon (method-spec §3 Step 1) bør støtte hierarki.** Alternativet — flat-only for alltid — betyr at okr/catalogs output aldri kan mate optimiser-loopen, og at de to halvdelene ikke kan dele fixture-suite i det hele tatt (se §4). Kostnaden ved å åpne er håndterbar; se åpne punkter under. **(b) Dør A (ingest-spec §5) bør forbli flat i v1.** `ingest-{id}.md` uten katalogkomponent, extraction-id-grammatikken utelukker `/`. En flat bundle er et gyldig degenerert tre, så ingenting brekker. Hierarkisk *produksjon* er et utvidelsespunkt, ikke v1 — og å holde det utenfor gjør at F1 (fritekst) og Q3 (form) forblir uavhengige beslutninger. Det er navigatoren som må lese begge former, ikke materialisereren som må produsere begge. ### Hva som må avklares hvis (a) velges — ikke gratis - **Lenkesyntaks, normativt.** To former er i omløp: okr emitterer rot-relativt `/foo/bar.md`; catalog spec.md:76 tillater både rot-relativt og relativt. Spec-en MÅ velge. Anbefaling: støtt begge, med `/` = **bundle-rot-relativ, IKKE filsystem-absolutt**. Den lesningen er nøyaktig der en naiv implementasjon blir en path traversal-sårbarhet (`open("/etc/passwd")`), så den må være normativ og dekkes av en load-bearing test. - **Traverseringsrekkefølge.** Dagens «index first, then links in first-seen order» er definert for én flate. For et tre må dybde-først vs. bredde-først pinnes, ellers er read-context ikke deterministisk og golden-suiten brekker. - **Dedup på *resolvert* sti**, ikke rå target — ellers teller `./a.md` og `a.md` som to oppføringer, og sykler (`a/index.md` → `b/index.md` → `a/index.md`) termineres ikke. - **Verdict-eksklusjonen må holde på alle nivåer.** method-spec §3 Step 1 utelukker `type: verdict` fra read-context; med hierarki må det gjelde rekursivt, ikke bare i roten. Dette er lekkasjeflaten hvis den glemmes. - **Read-context-rendering.** `## {type}: {title}`-seksjoner har ingen nivåforestilling. Anbefaling: behold flat seksjonsrendering også for hierarkiske bundles (nivået er navigasjonsstruktur, ikke presentasjonsstruktur) — men si det eksplisitt. ## 4. Konsekvens for delt fixture-suite (det spørsmålet egentlig gjaldt) Direkte svar: **Python- og Node-halvdelen kan dele fixture-suite kun hvis traverserings- kontrakten er én kontrakt.** - Velges flat-only, er okrs `okf-realistic` ikke en gyldig input til Python-navigatoren, og de to halvdelene deler ikke bundle-fixtures i det hele tatt — bare ingest-fixtures. - Velges hierarki, MÅ fixture-suiten inneholde en hierarkisk case, og begge halvdeler MÅ produsere **identisk read-context** fra den. okr har allerede kandidaten ferdig (`tests/fixtures/okf-realistic/`, tre nivåer dypt, per-nivå-indekser), og et flatt motstykke (`okf-minimal/`). De bør adopteres som delte fixtures, ikke gjenskapes. Med andre ord: (a) er det som gjør delt fixture-suite mulig i første omgang. Det er hovedargumentet, sterkere enn eleganse. ## 5. Løse tråder som ikke er mine å lukke - **Versjonsdrift:** `catalog/docs/okf-second-brain/spec.md:47` oppgir rotmarkøren som «currently `0.1`», mens `okr/scripts/okf-index.mjs:27` setter `OKF_VERSION = 'kb-layout-2026-06'`. Spec og referanse-implementasjon er ikke i sync. Meldt, ikke rørt. - **okrs lukkede vokabular håndheves kun på skrivestien** (`lib/okf-vocab.mjs:6-8`); lesesiden aksepterer ukjente typer. Relevant for catalogs krav (i) — se svarfilen.