docs(plan): F1 direction — free-text sources belong in ingest-spec door A
llm-ingestion-okf is blocked: door A has no free-text connector. Assessment requested by the implementation repo; this is direction, not a spec edit. Recommendation: solve in the spec. The real defect is that §5 conflates source type (transport) with body form — `http` already renders verbatim, so the verbatim mode exists but is bound to the wrong axis. Separate them with an extraction-level `render: table|verbatim`; no new source type needed. Also specifies what §5 must say about verbatim render (strict UTF-8, CRLF→LF vs the LF-only rule, deterministic fence width, mandatory fencing as a navigation-injection defence per method-spec §3 Step 1, max_rows semantics), and flags that free text is untrusted-by-origin over a local transport — which may pull guard Trigger A forward. ingest-spec.md is untouched. Decision is the operator's. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HBJNsFsBRaAhqGKjjiGjoQ
This commit is contained in:
parent
84191c60e7
commit
a013e8b5c3
1 changed files with 111 additions and 0 deletions
111
docs/plan/2026-07-20-f1-freetext-connector-direction.md
Normal file
111
docs/plan/2026-07-20-f1-freetext-connector-direction.md
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
# 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue