docs: falsification against provenance as invariant, mutations measured

30 mutations, all red against the whole suite. Green control 1189 passed / 5 skipped.
Golden byte-unchanged (ea8c534773acdbe41ae68f2c55724d69aaf8be4f); node-ID superset
strict (1094 -> 1194, 0 removed). Three of the plan's predicted signatures were
falsified by the measurement and are recorded as measured, not as predicted.

Co-Authored-By: Claude <claude-opus-5>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-02 23:40:54 +02:00
commit 8e5e33d2d5

108
CLAUDE.md
View file

@ -1212,6 +1212,114 @@ Python ≥3.10. MAF (`agent-framework-core` 1.16.0, `-orchestrations` 1.1.1 —
docstring advarer mot) feilet i den første fullkjøringen etter bumpen og var GRØNN ved mutasjonen,
altså rekkefølge-avhengig og flaky. Fiksen står på den observerte feilen, ikke på et rødt vitne.
Rapport: `docs/2026-09-02-f15-maf-pinnen.md`.
- **Falsifisering MOT PROVENIENS: en dom hviler på det basen faktisk BÆRER, og det den ikke kunne
fortelle deg er en del av dommen (B4, Steg 113, økt 75+76):** `parse_frontmatter` er
linjeorientert og leser en flow-verdi som ÉN streng, så `verified: { by: …, at: … }` — SPEC §5.2s
kanoniske form — nådde konsumenten som ulesbar tekst, og en blokkform nådde den som **tom** streng.
Begge så ut som «ingen proveniens». **Den defekten er den samme fra begge sider, og produsenten
MÅLTE den selv:** `llm-ingestion-okf`s egen guard-parser avviser sin EGEN golden
(`docs/okf-nokkelinventar.md:219`, `OKFFrontmatterError … '['`) — bekreftet på nytt ved Steg 13 mot
`62b6192`. **Ett skann, to LESERE, aldri to parsere:** `_split_frontmatter` er modulens ENESTE sted
`---` sammenlignes (gatet av en skanner-tellende arm, M14 → 1 rød), og `decode_flow_value` er den
ene navngitte sømmen over de rå linjene. Dekoderen er **nøkkel-agnostisk** (aldri hardkodet
`{id, resource}` — den avtalte segmenterte formen legger til `segment_id`/`source_offset`, så en
to-nøkkels dekoder ville nektet nøyaktig de basene sømmen finnes for; M3 → 12 røde) og gjør
**ingen YAML-1.1-koersering** (`yes`/`on`/`1` forblir strenger — en bevisst divergens fra PyYAMLs
resolver, skrevet ned i stedet for arvet i stillhet; M4 → 1 rød, en ratchet grønn ved
konstruksjon).
**Tre tilstander, og den tredje ER poenget:** `evidence_for` svarer `present` / `absent` /
`unreadable`, og den ulesbare bærer trippelen `(state, reason, items_seen)` — «hvilken FORM» og
«hvor MANGE» er to ulike operative spørsmål, `BudgetExceeded`-kø-(y)-regelen anvendt på en
dokumentleser. Å kollapse `unreadable` inn i `absent` gjør en dom om MANGLENDE bevis til bevis for
FRAVÆR (M7 → 4 røde); å rapportere én fast form for alle (M8 → 9 røde). K5-terskelen bor ÉTT sted
(`admits_falsification`: `present` OG en tier over `unverified`) og har TO konjunkter som måles
hver for seg (M19a → 2 røde, M19b → 1 rød). **Nevneren er skrevet ned:** SPEC §5.1 navngir SEKS
oppføringsnøkler og produsenten skriver TO (`62b6192`), så terskelen krever kun det som faktisk
emitteres — å kreve `author`/`usage_count`/`last_modified` ville gjort den unåbar i praksis mens
den så streng ut på papiret. **`adjudication` har en TREDJE token som er VÅR:** vokabularet på
tråden er lukket (`proposed` | `adjudicated`), og `unknown` er hva FRAVÆR betyr — aldri noe et
dokument får erklære (M20a → 2 røde), og en bærer som gir fra seg en payload uten tilstanden er
vokabularet uten sømmen (M20b → 1 rød). **`evidence_for` KUNNE IKKE drive den** (D-e → 5 røde):
MÅLT er `adjudication` en SKALAR, og begge gyldige verdier kommer tilbake som ETT identisk
`unreadable`/`unsupported-flow`-record, så den ruten kan ikke skille dem i det hele tatt;
`parse_frontmatter` er skalarleseren over SAMME skann.
**Skriveren nekter nøyaktig det leseren ikke kan lese**, og det er strukturelt, ikke en konvensjon:
`verified_field` og `write_concept_file` reiser den SAMME navngitte `FlowDecodeError` (M5 → 5 røde,
M16 → 3 røde, M17 → 1 rød). Det usikre tegnsettet er TRANSKRIBERT fra produsentens eget
`_FLOW_UNSAFE_RE` (`materialize.py:176`, `[,\[\]{}]|:\s`) — ikke oppfunnet — og er BEVISST
smalere: vår parseparator er kolon-MELLOMROM, så `":\t"` kan ikke restrukturere en av våre par.
**Ko-drift er stengt av skrivesidens gate, ikke bare oppdagbar via en ekstern referent:** planen
spådde at M9 (skriver OG dekoder flyttes til blokkform sammen) ville la rundturen stå GRØNN.
**MÅLT er den spådommen ikke konstruerbar** — skriveren kan ikke flytte alene (M9a → 26 røde + 8
feil), fordi `render_frontmatter` enlinjer hver verdi OG `write_concept_file` nekter formen; M9
krevde derfor at BEGGE vaktene ble slått av samtidig, og ga 17 røde inkludert rundturen. Det er et
sterkere utfall enn planen ba om, og det er skrevet ned som målt, ikke som spådd.
**Navigasjonen forblir TOLERANT mens dekoderen nekter** (OKF SPEC §4), bevist med BYTES: M10 →
**1 rød, ett navngitt vitne**, mens begge nav-goldenene og demo-transkriptet står.
**Identitet er PARET `(bundle_id, concept_id)` (D6/B1), og `origin` har TRE verdier:**
`okf.reconcile_bundle_id` er den ENE avledningsregelen — konseptets egen frontmatter først, rot-
`index.md` som fallback, mountets basename til sist — og `ResolvedBundleId.origin` sier hvilken
(`declared-concept` / `declared-index` / `mount-derived`). **Påkrevd uten default**, av
`cost_baseline_anchored`s grunn: begge defaults ville løyet om en hendelse. **Ikke en boolean**
en kaller som ikke kan skille «konseptet sa det» fra «vi falt tilbake to ganger» har fått et
stempel den ikke kan revidere (D-i → 3 røde). **MÅLT: null `^bundle_id`-treff** noe sted under
`shared/`, `src/`, `tests/` mot en kjent-positiv kontroll på 31 filer med `^type:`, så begge
erklærte grener er DEFENSIVE (`budget_stop`-presedensen) og drives fra CRAFTED baser; alle 27
`bundle_dirs=`-kallsteder står grønne. **`explore._bundle_index` forblir REN** — to av dens egne
armer konfigurerer kataloger som ikke finnes og forventer en id-feil, ikke en I/O-feil — så
avstemmingen skjer der en base faktisk ÅPNES: `explore.read_bundle` (M11a → 1 rød),
`run_project`s bundle-arm (M11b → 2 røde) og dispatcheren (M11c → 1 rød, som erstattet en privat
`Path(raw).name`-kopi). En base uten lesbar `index.md` er **ukjent, ikke uerklært**
`navigate_bundle`s fail-fast propagerer. `BundleIdMismatch` subklasser `ValueError` så den lander
på CLI-ens nekt-tuppel og hostings 400-arm, aldri krasj-kanalen; nekten måles på **null
modellkall**, ikke på exit-koden (M12 → 2 røde. **Ærlighets-grense, MÅLT:** planens påstand
«exit-koden forblir 1 uansett» HOLDER IKKE for denne argv — mutanten reiser
`BudgetExceeded: rounds limit=12 observed=13` før noen nekt, så sink-asserten nås aldri. Asserten
på KALL er likevel riktig design; den er det som ville fanget en nekt-etter-forbruk som DID
returnerte rent).
**En kryss-base-kollisjon rapporteres, aldri droppet i stillhet (D2):** `VerdictStore.add` er
first-write-wins og `_mint_id` ekskluderer korpuset ved konstruksjon, så to baser som beskriver
SAMME kandidat kollapser på én dom. `_mint_id` er URØRT (normativ i `shared/method-spec.md`,
commons-eid) og `add` likeså — en drop DER kan like gjerne være mot en Steg-7-innboksdom eller et
bundle-frø. Regnskapet bor i dispatcheren, som er det ENE stedet som holder id→base-kartet
(M13 → 2 røde). **Id-en hentes fra `run_project`s EKSISTERENDE `notify`-søm, aldri fra
`RunResult.verdict`** (D-l): `notify` fyrer INNE i fangst-blokka, altså nøyaktig når en dom finnes
(F2), og båsen bygges FERSK hver iterasjon — hoistes den ut, leser en senere base forrige bases dom
og fabrikkerer en kollisjon som aldri skjedde (D-l → 1 rød). `MultiBaseResult.collisions`
DEFAULTER til tom tuppel (`skipped_links`-halvdelen: en tom trace er et ærlig POSITIVT utsagn), og
`collision_notice` returnerer `None` på den — omisjon, aldri tom rad.
**Metoden er en DELT Agent Skill, forfattet i commons (D4):** `shared/skills/falsification-
reviewer/` kommer KUN via `git subtree pull` — lokal forfatting ville gitt et wheel søskenet aldri
arver, og INGEN test i suiten oppdager det avviket. Terminologi-gaten er den som biter
(`OKF bundle` i kundevendt prosa → M18a, 1 rød), og den er paret med en KJENT-POSITIV kontroll på
at regexen KAN finne strengen. Rammeverks-nøytraliteten har ÉN kopi
(`test_method_spec_is_framework_neutral`), utvidet av Amendment 2 fra `expert-reviewer` alene til
`GUARDED_SKILL_DIRS` — den nye skillen hadde ingen vakt i det hele tatt (M18b → 1 rød, egen
signatur) — pluss en fail-closed arm som blir rød når et fremtidig subtree-pull bringer en TREDJE
skill som ikke er listet. Det verkede eksempelet materialiseres fra `frontmatter_verbatim`
ORDRETT (Amendment 3): den linjeorienterte `frontmatter`-projeksjonen kan ved konstruksjon ikke
bære blokkform, så å bygge fra den ville gjort det ulesbare tilfellet `absent` og armen ville stått
GRØNN mens den beviste det motsatte av sin egen docstring. Eksempelets egen dom er `undecided`, ikke
`survived` — en påstand hvis ene mulige gjendriver var ulesbar ble aldri angrepet.
**Load-bearing MÅLT: 30 mutasjoner, ALLE røde mot HELE suiten**, grønn kontroll **1189 passed /
5 skipped**, alle tre byte-fasitene OK og `demo-transcript.stdout` BYTE-UENDRET
(`ea8c534773acdbe41ae68f2c55724d69aaf8be4f`); node-ID-supersettet holder strengt (1094 → 1194,
**0 fjernet**). Per mutasjon: M1 27 · M2 2 · M3 12 · M4 1 · M5 5 · M6 1 · M7 4 · M8 9 · M9a 26+8E ·
M9 17 · M10 1 · M11a 1 · M11b 2 · M11c 1 · M12 2 · M13 2 · M14 1 · M15 1 · M16 3 · M17 1 ·
M18a 1 · M18b 1 · M19a 2 · M19b 1 · M20a 2 · M20b 1 · D-b 1 · D-e 5 · D-i 3 · D-l 1.
**TRE av planens spådde signaturer ble FALSIFISERT av målingen, og de står som målt:** M9s
«rundturen forblir grønn» (ikke konstruerbar), M12s «exit-koden forblir 1» (mutanten reiser i
stedet), og M17s spådde PAR (kun 1 rød — `verified_field("a: b", …)` runder faktisk trippen, fordi
`_find_pair_separator` tar FØRSTE kolon-mellomrom og verdien beholder sitt eget kolon).
**Operatørbeslutninger:** D1 én dekoder-søm · D2 dispatcher-side kollisjonsregnskap · D3 én
linjekilde bak begge lesere · D4 skillen forfattes i commons · D5 ingen ny avhengighet (ingen
PyYAML) · D6/B1 identitet = `(bundle_id, concept_id)`, konseptet først. **D7-speiling er ÅPEN** for
dekoder-semantikken, som S3.2 og S4.0. **Ærlighets-grenser, uttalt:** `evidence_for(path, key=…)`
med en ANNEN nøkkel enn `verified` REISER for enhver verdi som dekoder til oppføringer uten `by`,
fordi `tier` avledes ubetinget — MÅLT: alle 11 eksisterende kallsteder bruker defaulten, så
parameteren har aldri vært øvet, og det er RAPPORTERT, ikke fikset (utenfor denne ordren);
`verified_field` validerer ikke `at`; og at en LEVENDE modell kaller falsifiseringsskillen godt er
ikke bevist (structured-output-grensens klasse).
- **STATE.md er local-only** (gitignored). Voyage session-state er efemert; STATE.md er kanonisk kontinuitet.
- Prosess: Voyage-plugin (`/trekbrief → /trekplan → /trekexecute → /trekreview`) per større fase.