docs(okr): fase-4-kartlegging for llm-ingestion-okf (planned, ingen kode)
Forarbeid mot fase 4: all OKF-kode (okf-check/okf-index/innboks-ingest, lib/okf-*.mjs, lib/innboks-*.mjs, lib/convert/) lest mot ground truth og skilt i generelt vs. okr-spesifikt. Kravliste for at okr skal kunne vendore en delt Node-utgave, samt okrs faktiske bruk av okf_version (ekko-tekst i rot-index.md, kb-layout-2026-06) og hvorfor avviket mot spec-ens 0.1 er et felt-type-avvik, ikke bare en verdiforskjell. Ingen kode endret, ingenting wiret. Markørlinje satt til planned i STATE.md (local-only). Meldt avvik: bibliotekets koordineringsvedlegg er utdatert. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AGkEqS3Zxf7rVuUQHrsQG2
This commit is contained in:
parent
482effbad1
commit
29401bcd60
1 changed files with 163 additions and 0 deletions
163
docs/llm-ingestion-okf-fase4-kartlegging-2026-07.md
Normal file
163
docs/llm-ingestion-okf-fase4-kartlegging-2026-07.md
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
# llm-ingestion-okf — fase 4-kartlegging (okr-siden)
|
||||
|
||||
**Status:** `planned` — kartlegging og kravgrunnlag. Ingen kode endret, ingenting wiret.
|
||||
**Dato:** 2026-07-20. **Grunnlag:** ground-truth-lesing av all OKF-kode i dette repoet
|
||||
(suite 149/149 grønn ved kartleggingstidspunkt).
|
||||
|
||||
Node-halvdelen av `llm-ingestion-okf` finnes ikke ennå. Dette dokumentet er forarbeid:
|
||||
hva okr faktisk har, hva som er generelt vs. okr-spesifikt, og hva et delt bibliotek må
|
||||
oppfylle før okr kan vendore det i stedet for å eie egen kode.
|
||||
|
||||
---
|
||||
|
||||
## 1. Kartlegging — hva finnes i dag
|
||||
|
||||
Zero-runtime-dependency Node/ESM. Alle moduler er både importerbare (named exports) og
|
||||
CLI-kjørbare (`import.meta.url === process.argv[1]`-vakt). Node >= 22.
|
||||
|
||||
| Modul | Linjer | Rolle | Løftbarhet |
|
||||
|---|---|---|---|
|
||||
| `lib/frontmatter.mjs` | 70 | Flat FM-parse/skriv. BOM+CRLF-tolerant, siterte verdier bevarer intern `#`, multi-linje list-verdier tolereres | **Generell** |
|
||||
| `lib/okf-links.mjs` | 39 | Den ENE lenke-allow-listen: trygg bundle-lenke = leading `/`, `.md`, ingen scheme/`..`/backslash/NUL. `resolveBundleLink` re-sjekker confinement | **Generell** |
|
||||
| `lib/okf-vocab.mjs` | 73 | Lukket TYPE/TAGS-vokab + `routeLevel(type)` | **okr-spesifikk data, generell mekanisme** |
|
||||
| `lib/innboks-split.mjs` | 100 | Ren funksjon: `#`/`##`-heading-split → konsepter. Preamble bevares, flat-fallback | **Generell** (én no-detalj) |
|
||||
| `lib/innboks-frontmatter.mjs` | 96 | Regelbasert FM-projeksjon. `timestamp` = kilde-mtime (idempotens by construction) | **Blandet** |
|
||||
| `lib/innboks-relations.mjs` | 49 | Relasjoner innen kjøringens sett, exact-title-substring → root-lenker. Assert zero-dangling | **Generell** |
|
||||
| `lib/innboks-write.mjs` | 186 | Atomisk skriv (temp+rename), path-confinement, realpath/symlink-guard, reservert-navn-guard, kuratert-fil-vern (`kilde: innboks`), kryss-kilde-`claimed`-register | **Generell** (én okr-konstant) |
|
||||
| `lib/convert/index.mjs` | 132 | docx/eml/pdf/txt/md → md. Lenke-nøytralisering i alle fem lenkeformer | **Generell** |
|
||||
| `scripts/okf-check.mjs` | 160 | Bundle-validering. Default tolerant (kun `type` kreves); `--strict-ingest` = vokab + lenke-allow-liste + `files`-scoping | **Generell** |
|
||||
| `scripts/okf-index.mjs` | 162 | Per-nivå `index.md`, idempotent, `sanitizeEntry` (C0/C1, zero-width, bidi, Unicode-tags, link-nøytralisering), atomisk | **Generell** |
|
||||
| `scripts/innboks-ingest.mjs` | 240 | Orkestrator: discover → per-dok staging → gate → discard-on-fail → relasjoner → index → sluttsjekk | **Generell arkitektur** |
|
||||
|
||||
**Arkitektur-invarianter verdt å bevare i et løft:**
|
||||
- Ingen LLM. Fil-settet er en funksjon av (drop-zone-innhold + mtime) alene → run1 og run2
|
||||
byte-identisk. Veggklokke brukes aldri.
|
||||
- Per-dokument-isolasjon (Map-Reduce): ett fiendtlig dokument discardes alene og forgifter
|
||||
ikke de andre. Relasjoner emitteres ETTER gaten, så hvert mål garantert er på disk.
|
||||
- Strict-gaten scopes til kjøringens skrevne filer, ALDRI hele roten — ellers feller den
|
||||
legitimt håndkuratert innhold med lovlige eksterne lenker.
|
||||
- Ikke-destruktiv: originalene blir liggende i drop-zonen; hver original får en peker-fil.
|
||||
|
||||
---
|
||||
|
||||
## 2. Hva er okr-spesifikt vs. generelt
|
||||
|
||||
### Generelt (kan løftes tilnærmet uendret)
|
||||
`frontmatter.mjs`, `okf-links.mjs`, `innboks-split.mjs`, `innboks-relations.mjs`,
|
||||
`okf-index.mjs`, `okf-check.mjs`-kjernen, `convert/`-adapterne, og hele skrive-/
|
||||
confinement-maskineriet i `innboks-write.mjs`. Ingenting her vet at domenet er OKR.
|
||||
|
||||
### okr-spesifikt (må parametriseres før løft)
|
||||
1. **`TYPE_VOCAB`/`TAGS_VOCAB`/`LEVEL_BY_TYPE`** (`okf-vocab.mjs`) — norske, lukkede,
|
||||
OKR-domene. Mekanismen (lukket vokab + type→nivå-ruting) er generell; *innholdet* er
|
||||
ikke. Må inn som konfigurasjon, ikke kode. Merk at spec-en er engelskspråklig konvensjon
|
||||
mens vokabet er norsk — eierskapet (bibliotek-default vs. konsument-profil) må avklares.
|
||||
2. **`HOME_ORG`-konstanten** (`innboks-write.mjs:44`, `~/.claude/okr/org`) — okrs to-rot-
|
||||
modell. Generaliseres til en «forbudte skriverøtter»-liste fra kaller.
|
||||
3. **Type-utledningen** (`deriveType`, `innboks-frontmatter.mjs`) — matcher vokab-termer som
|
||||
helt ord i tittel + kilde-basename, med `\p{L}\p{N}`-lookaround fordi `\b` ikke håndterer
|
||||
æ/ø/å. Regelen er generell, vokabet ikke.
|
||||
4. **`slugify`s æ→ae/ø→oe-translitterering** (`innboks-split.mjs:15-25`) — nordisk, ikke
|
||||
universelt. NFKD dekomponerer *ikke* æ/ø, så uten dette faller bokstaven bort. Et delt
|
||||
bibliotek trenger en pluggbar translitterasjonstabell, ellers regresserer norsk input.
|
||||
5. **Faste nivånavn** (`strategisk-kontekst`/`historikk`/`dokumenter`) og
|
||||
`.claude/okr/innboks/` som drop-zone. Rene konfig-verdier.
|
||||
6. **Norske feilmeldinger og `kilde: innboks`-provenansnøkkelen.** Meldingsspråk må være
|
||||
pluggbart hvis biblioteket skal tjene ikke-norske konsumenter; `kilde`-nøkkelen er en
|
||||
OKF-extension key okr er avhengig av for kuratert-fil-vernet.
|
||||
|
||||
### `lib/convert/` spesielt
|
||||
Adapterne er **domene-agnostiske** og det mest direkte gjenbrukbare i repoet. Men:
|
||||
- Fire exact-pinnede deps (mammoth 1.12.0, turndown 7.2.4, postal-mime 2.7.5, unpdf 1.6.2).
|
||||
okrs zero-dep-posisjon er bevart ved at de er lazy-importert med norsk installasjonshint,
|
||||
og at txt/md kjører helt dependency-fritt. **Et delt bibliotek må bevare denne
|
||||
egenskapen** — deps må være valgfrie (peer/optional), aldri obligatoriske. Vendored-vs-peer
|
||||
er en åpen beslutning som må tas sammen, ikke arves.
|
||||
- `turndown` er pinnet til `headingStyle: 'atx'`. Default er setext, som heading-splitten
|
||||
aldri ser. Denne koblingen mellom konverter og splitter må dokumenteres i kontrakten,
|
||||
ellers reintroduseres bugen i en delt utgave.
|
||||
- `unpdf` kalles med eksplisitt `isEvalSupported: false` (CVE-2024-4367), selv om det er
|
||||
default i 1.6.2. Belte + seler — må overleve løftet.
|
||||
- PDF gir flat tekst uten headings (kjent v1-caveat): PDF-dokumenter blir alltid ett konsept.
|
||||
- **`neutralizeExternalLinks` er sikkerhetskritisk** og hører sammen med `okf-links.mjs`.
|
||||
Emit-siden og validerings-siden deler allow-liste nettopp for at de aldri skal divergere.
|
||||
Splittes de i et løft, er divergens et spørsmål om tid.
|
||||
|
||||
---
|
||||
|
||||
## 3. Forutsetninger for at okr kan vendore en delt utgave
|
||||
|
||||
Rangert, alle må være oppfylt:
|
||||
|
||||
1. **Vokabet er data, ikke kode.** Bibliotekets API tar TYPE/TAGS/`routeLevel` som argument.
|
||||
Uten dette må okr forke uansett.
|
||||
2. **Zero-dep-kjerne bevart.** txt/md-stien må kjøre uten npm-installasjon. Binærformat-deps
|
||||
optional/lazy med samme feilmeldings-kvalitet (klar hint, aldri traceback).
|
||||
3. **Sikkerhetsegenskapene er testbart bevart.** Path-confinement, realpath/symlink-guard,
|
||||
reservert-navn-guard, kuratert-fil-vern, `sanitizeEntry`-settet (C0/C1, ZWSP, bidi,
|
||||
Unicode tag-blokk), lenke-nøytralisering i alle fem former, `--strict-ingest`-scoping.
|
||||
Alle 149 testene her er tilgjengelige som seed; et løft som ikke porter dem er ikke
|
||||
ferdig. Særlig: gate-scoping (`files`) og discard-on-fail-isolasjon er lærte lekser fra
|
||||
B5/B2 — de er ikke kosmetikk.
|
||||
4. **Idempotens by construction.** mtime-basert timestamp, deterministisk sortering,
|
||||
stabil kryss-kilde-disambiguering. Et bibliotek som introduserer veggklokke er ubrukelig
|
||||
for okr.
|
||||
5. **Pluggbar slugify-translitterering** (æ/ø/å), ellers regresjon på norsk input.
|
||||
6. **Pluggbar meldingsstreng/språk**, eller minst en `onNotice`-seam som i dag.
|
||||
7. **Versjonspinning etter polyrepo-disiplinen.** okr vendorer mot en tag, ikke mot main.
|
||||
8. **Guard-grensen respekteres.** Dør A er ugatet; `llm-ingestion-okf` er plumbing.
|
||||
okrs egen strict-gate er *ikke* en sikkerhetsguard i guard-repoets forstand og skal ikke
|
||||
forveksles med en. Vil vi ha guard-gating, går det via `llm-ingestion-guard` på kallstedet
|
||||
— og det er en separat beslutning, ikke en del av fase 4.
|
||||
|
||||
---
|
||||
|
||||
## 4. `okf_version` — hvordan okr bruker feltet i dag (kjent avvik)
|
||||
|
||||
**Faktisk bruk, verifisert:**
|
||||
- Verdien er `kb-layout-2026-06` (`scripts/okf-index.mjs:27`, eksportert som `OKF_VERSION`).
|
||||
- Den bor som **markdown-tekstlinje i rot-`index.md`**, ikke i frontmatter — `index.md` er
|
||||
OKF-reservert og bærer aldri frontmatter. Kun rot-index; undernivåer har den aldri
|
||||
(testet eksplisitt).
|
||||
- `okf-check.mjs` **ekkoer** verdien for menneskelig sammenligning. Den validerer den ikke,
|
||||
sammenligner den ikke mot noe, og feiler aldri på den. Hooks/scripts er no-network, så
|
||||
auto-fetch mot en standard er utelukket by design.
|
||||
- `okf-index.mjs` **bevarer** eksisterende verdi ved re-kjøring; en eksplisitt
|
||||
`--okf-version <ver>` vinner (bump-mekanismen). Begge grener er testet.
|
||||
- Feltet er per rot: prosjekt-`.claude/okr/` og home-`~/.claude/okr/org/` har hver sin.
|
||||
|
||||
**Avviket:** spec-en sier `0.1`; okr sier `kb-layout-2026-06`. Dette er ikke bare ulik
|
||||
verdi — det er to ulike *typer* felt. okrs verdi navngir hvilket **layout-mønster** treet
|
||||
følger (datert konvensjons-snapshot); spec-ens `0.1` er et **spec-versjonsnummer**. De kan
|
||||
begge være riktige og likevel uforenlige i ett felt.
|
||||
|
||||
**okrs posisjon:** dette avgjøres av catalog som konvensjonseier, ikke av okr og ikke av
|
||||
biblioteket. okr har lav byttekostnad — feltet er ren ekko-tekst uten validerings-semantikk,
|
||||
så en verdiendring koster én konstant + fixture-oppdateringer. Men hvis begge betydningene
|
||||
skal bæres, trenger vi to felt (f.eks. `okf_version` = spec-versjon, `okf_layout` =
|
||||
layout-snapshot), og det er en spec-endring som må gå via commons/catalog.
|
||||
|
||||
---
|
||||
|
||||
## 5. Hva som aldri bør flyttes til biblioteket
|
||||
|
||||
- **`okf-vocab.mjs`s innhold** — norsk OKR-domenevokab hører hjemme i konsumenten eller i
|
||||
en profil, aldri som bibliotek-default.
|
||||
- **Orkestratoren `innboks-ingest.mjs` som helhet** — fase-rekkefølgen er generell og verdt
|
||||
å dele som *mønster*, men den konkrete drop-zone-plasseringen, to-rot-modellen og
|
||||
peker-filkonvensjonen er okrs. Del kjeden, ikke policyen.
|
||||
- **Hook-integrasjonen** (`inject-okr-context.mjs`, `coaching-hook.mjs`) og
|
||||
`okr-second-brain-search`-skillen — ren plugin-UX.
|
||||
- **Alt sikkerhetsansvar.** Guard-grensen står: `llm-ingestion-guard` eier sikkerhet,
|
||||
`llm-ingestion-okf` er plumbing, og okr reimplementerer ingen av delene.
|
||||
|
||||
---
|
||||
|
||||
## 6. Neste steg (ikke utført)
|
||||
|
||||
1. Operatør melder kartleggingen inn til biblioteket som kravgrunnlag (§3 er kravlisten).
|
||||
2. Catalog avklarer `okf_version`-semantikken (§4) — blokkerer løftet.
|
||||
3. Parser-sett + vendored-vs-peer avgjøres i samråd (§2, `lib/convert/`).
|
||||
4. Først når Node-halvdelen finnes med §3 oppfylt: vurder adopsjon i egen sesjon.
|
||||
|
||||
Ingen av disse stegene endrer kode i okr. Markørlinjen i STATE.md står på `planned`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue