111 lines
7.1 KiB
Markdown
111 lines
7.1 KiB
Markdown
# F1 — fritekst-kilder i ingest-spec: retningsvurdering
|
||
|
||
**Status:** vurdering, ikke vedtak. Spec-en er IKKE endret. Beslutning tas av operatøren.
|
||
**Foranledning:** `llm-ingestion-okf` v0.3.1 har ingen fritekst-connector; `file` er en streng
|
||
CSV-leser og §5-body rendres som markdown-tabell med newline-kollaps. To uavhengige repo
|
||
(`claude-playlist-corpus`, `claude-code-llm-wiki`) blokkeres. Spørsmålet stilt til commons:
|
||
løses dette i `ingest-spec.md` (dør A) eller i bibliotekets dør B (innboks, ikke spec-styrt)?
|
||
|
||
---
|
||
|
||
## 1. Retning: løses i spec-en, i dør A
|
||
|
||
Fire grunner, i synkende vekt:
|
||
|
||
1. **Arkitekturregelen krever det.** §1: *«data reaches the model ONLY via OKF bundles»*, og
|
||
bundlen materialiseres deterministisk FØR loopen. Fritekst er data. Ingenting i §1–§3
|
||
skiller tabulært fra ustrukturert — utelukkelsen er et artefakt av at v1s `file`-connector
|
||
ble en CSV-leser, ikke en prinsipiell grense. Skyves den vanligste kunnskapsbase-kilden ut
|
||
til dør B, faller den samtidig utenfor provenance-stemplingen (§7), verdict-reservasjonen
|
||
(§3), golden-regimet (§11) og determinismen (§10) — spec-ens dekning uthules der den betyr
|
||
mest.
|
||
2. **Sitatkravet peker samme vei.** Method-spec §9 krever *«file + exact text span +
|
||
snippet»*. En span inn i en tabell-rendret, newline-kollapset body er i praksis ubrukelig;
|
||
en verbatim dokument-body er det naturlige span-målet. Fritekst gjennom dør A gjør
|
||
sitatkjeden bedre, ikke svakere.
|
||
3. **Determinismen er lettere, ikke vanskeligere.** Verbatim bytes har ingen typekoercion,
|
||
ingen tallformatering, ingen NULL-semantikk — hele §5s tabell-fallgruvefelt forsvinner.
|
||
Det finnes ikke noe determinisme-argument for å holde fritekst ute.
|
||
4. **Spec-en har allerede render-modusen — feilplassert.** §5 sier for `http`: *«the response
|
||
body verbatim inside a fenced code block»*. Verbatim-render finnes altså, men er bundet til
|
||
**transport** (`http`) i stedet for til **innholdsform**. Det er den faktiske defekten: §5
|
||
konflaterer kildetype og body-form. F1 er symptomet.
|
||
|
||
**Grensen mot dør B holder likevel — men den går ikke ved innholdsform.** Den går ved
|
||
*adresserbarhet + re-eksekverbarhet*: en kilde med manifest-deklarert, repeterbar `query` mot
|
||
en adresserbar kilde hører i dør A (en transkripsjonsfil under `root` kvalifiserer). Materiale
|
||
uten re-eksekverbar kilde-query — limt inn tekst, en e-post, et engangsdropp — hører i dør B.
|
||
Bruker vi innholdsform som grense i stedet, havner halve kunnskapsbasen utenfor spec-en av en
|
||
grunn som ikke er prinsipiell.
|
||
|
||
### Foreslått form (retning, ikke spec-tekst)
|
||
|
||
Ikke en ny kildetype `document` — den ville duplisere `file`s `root`- og
|
||
grensesjekk-logikk. I stedet: **skill body-form fra kildetype.** Et nytt påkrevd
|
||
extraction-felt (arbeidsnavn `render`) med `table` | `verbatim`. `file`+`table` = dagens
|
||
CSV-leser; `file`+`verbatim` = fritekst-dokumentet som mangler; `http` beskrives retroaktivt
|
||
som `verbatim` og blir dermed konsistent i stedet for et unntak. Ett felt, én rad i §12s
|
||
kryssjekk-tabell, ingen ny kildetype.
|
||
|
||
## 2. Hva §5 må si om verbatim body-render
|
||
|
||
Seks punkter. De fire første er ikke valgfrie — dagens `http`-render mangler dem alle, så
|
||
dette lukker et latent hull samtidig som det løser F1.
|
||
|
||
- **Bytes og dekoding.** Innholdet leses som bytes og dekodes som UTF-8, strengt. Dekodefeil
|
||
er en ERROR — aldri erstatningstegn, aldri lossy koercion. Samme disiplin som §5s *«any
|
||
other value type MUST fail (never silent coercion)»*.
|
||
- **Linjeskift — her er «verbatim» nødt til å vike.** §5 krever LF-only og nøyaktig én
|
||
avsluttende newline. CRLF/CR MÅ derfor normaliseres til LF, og etterfølgende blank plass ved
|
||
EOF kollapses til nøyaktig én LF. Uten denne regelen motsier «verbatim» og «LF-only»
|
||
hverandre, og golden-ekstraksjoner blir plattformavhengige. Spec-en MÅ si rett ut at
|
||
renderen dermed er lossy mot kildens eksakte bytes — og at en eventuell kildehash regnes
|
||
over **kildens** bytes, ikke de rendrede.
|
||
- **Fencing — obligatorisk, med deterministisk bredde.** Fence-lengde =
|
||
`max(3, lengste backtick-run i innholdet + 1)` (CommonMark-standard, deterministisk).
|
||
- **Fencing er sikkerhetsbærende, ikke kosmetikk.** Ufenset markdown-passthrough er IKKE v1.
|
||
Grunnen er konkret: method-spec §3 Step 1 navigerer ved å følge body-lenker
|
||
(`](target.md)`), så et ufenset ingested dokument kan injisere navigasjonskanter utenom
|
||
`index.md` og forsøke bundle-escape-stier. I tillegg rendres read-context som
|
||
`## {type}: {title}`-seksjoner — et dokument med egne `##`-overskrifter visker ut
|
||
seksjonsgrensene, og en ledende `---` kan leses som et nytt frontmatter-blokk. Fenset
|
||
innhold har ingen av delene. (Ufenset passthrough = utvidelsespunkt.)
|
||
- **`max_rows` for dokumenter.** Feltet er radorientert og meningsløst for fritekst. Enkleste
|
||
konsistente lesning: for `verbatim` teller `max_rows` LF-delimiterte linjer, og overskridelse
|
||
er ERROR (§8, aldri stille trunkering). **Åpen underbeslutning:** en 40 MB transkripsjon
|
||
passerer en linjegrense lenge før den blir håndterbar — trengs et valgfritt `max_bytes` i
|
||
tillegg? Anbefaling: ja, valgfritt, men dette er verdt et eksplisitt operatørvalg.
|
||
- **`source_query` og provenance ellers:** uendret — relativ sti, whitespace-kollapset (§5/§7).
|
||
|
||
### `ingested_at`-determinismen bevares — med én felle å lukke eksplisitt
|
||
|
||
Verbatim-render leser ingen klokke. `ingested_at` forblir et eksplisitt påkrevd argument,
|
||
stemplet ordrett; §5s regel er urørt. Fellen er en fristende «forbedring»: å stemple kildefilens
|
||
mtime eller størrelse som ekstra provenance. Det MÅ forbys — git bevarer ikke mtime, så et
|
||
golden-fixture ville gi ulikt resultat ved frisk utsjekking, og §11s byte-for-byte-krav brytes.
|
||
Verdt en eksplisitt MUST NOT.
|
||
|
||
### §11 — nye seams
|
||
|
||
- Ny golden-case, konvensjon `examples/ingest-golden-verbatim/`. Fixturet MÅ inneholde et
|
||
dokument med CRLF, en backtick-run ≥ 3, en ledende `---`, og ikke-ASCII — så escape-reglene
|
||
fryses av golden i stedet for å leve i prosa.
|
||
- Ny load-bearing rad: testen MÅ feile når fence-bredden slutter å vokse med innholdets
|
||
lengste backtick-run (dvs. når ingested innhold kan bryte ut av fencen).
|
||
|
||
## 3. Sikkerhetsobservasjon (til operatøren, ikke en spec-endring)
|
||
|
||
Dette er første gang dør A materialiserer innhold som er **untrusted av opphav** selv om
|
||
transporten er lokal og first-party: `root` eies av operatøren, men en transkripsjon eller
|
||
artikkel under `root` er tredjeparts tekst. Guard-adopsjonsplanen
|
||
([2026-07-16](2026-07-16-llm-ingestion-guard-adoption.md) §4) definerte Trigger A som «når
|
||
`http`/MCP-kildetypen bygges». En fritekst-connector treffer samme untrusted-grense uten å gå
|
||
via `http` — så Trigger A bør trolig omformuleres fra *transport* til *opphav*, og kan dermed
|
||
inntreffe tidligere enn planen antar. Flagget her, ikke besluttet.
|
||
|
||
## 4. Hva dette IKKE avgjør
|
||
|
||
- Ingen spec-tekst er skrevet. §4, §5, §11 og §12 er urørt.
|
||
- `render`-feltnavnet er et arbeidsnavn.
|
||
- `max_bytes`-spørsmålet står åpent (§2).
|
||
- Dør B (innboks) berøres ikke: den beholder materiale uten re-eksekverbar kilde-query.
|