portfolio-optimiser-claude/docs/2026-08-18-funn-koeer-og-gater.md
Kjell Tore Guttormsen 7b934275d8 test(cost): the money rule exists in four copies, and the gate it serves is switched off
D7 mirror candidate (p) `to_ore`, measured offline with the mutation harness.

`to_ore` does not exist here (0 of 80 .py files in src+tests; positive control:
`unit_cost` found in 19). Our money axis is the accumulated USD spend, and its
conversion is the rounding to six decimals — present in FOUR literal copies with
no named source (run.py:159, run_s10.py:110 and :130, costsim.py:125) while the
share rounding one file over DOES have one (`_SHARE_DIGITS`). The sibling's drift
form is present.

Three of the four copies are never executed: replacing the whole expression with
`999.0` left all 984 green at each. Their green under a detach was never evidence
about the rounding — it was "not measured" (ansikt 4 on the apparatus). The
default branch WAS pinned; the value branch was not.

The one path that decides with the cost — the C3.5 pre-call USD belt — is a
permanent no-op: `max_cost_usd` is set in 0 of 27 src modules (positive control:
`max_budget_usd_per_call` is found by the same scan). The gate is built; no path
hands it a cap.

Seven mutations, all VALUE-PROVED with collateral controls green in both runs.
No src change: folding the copies is a refactor, wiring the run-total cap is a
feature. The tests pin today's boundary so neither lands silently.

984 -> 997 (strict superset, 0 lost node ids).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 07:28:44 +02:00

463 lines
32 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Målte funn, køer og gater (flyttet ut av STATE.md 2026-08-18)
> Bakgrunn: `STATE.md` er current state-of-play og har et tak på ~120 linjer. Den 18.08 lå
> fila på 149. Operatørbeslutningen samme dag var å flytte tre punkter hit og la STATE
> beholde ÉN peker per punkt på formen `fil § Overskrift` — et grep-bart paragraf-anker,
> aldri et linjenummer. **Ingenting er slettet:** state er flyttet, ikke fjernet.
>
> Alt under er MÅLERESULTATER med en dato, ikke fakta om verden. Datoen står ved hver
> påstand, og en påstand herfra er et premiss som skal verifiseres på nytt før den handles
> på — særlig tall som råtner (versjoner, testantall, oppstrøms-tilstand).
## Negative funn
Steder som ER undersøkt for en manglende søm, og hvor svaret var «ingen søm å feste». De er
ferdig avklart i økt 1722 og skal **ikke re-måles** — enumerert her nettopp for at ingen
senere økt skal bruke tid på dem igjen:
- `test_preflight` (9 tilfeller)
- `test_zero_model_calls`
- `notify` :224
- `ir` :69
- `validator` :56
- `step1_expel` :99
- cli_paritet-parene
- `method_spec` + `ingest_spec` (6 tilfeller — merk: **ikke lenger dekkende**, se under)
- alle 8 fra økt 22
**Korreksjon 2026-08-18 (økt 32):** `ingest_spec`-oppføringen gjaldt den §12-ankrede vakten.
Økt 32 målte et hull den enumereringen ikke fanget — enhver seksjon §1§11 kunne tømmes uten
at én test i suiten ble rød (10 av 11 seksjoner; §7 var eneste overlapp, via O2-ratchet-en).
Hullet er lukket med `_STRUCTURE_MARKERS` i `tests/test_ingest_spec_loadbearing.py` (commit
`40b4631`). Lærdommen er generell: **et negativt funn har et scope, og scopet er den
spørringen som ble kjørt** — ikke fila den ble kjørt mot.
## D7-speilingskøen
Åtte kandidater for speiling mellom D7-søsknene. **Ingen er besluttet** — de står som
kandidater, ikke som planlagt arbeid. **Seks er målt, 2 står igjen:**
- ~~S2.7~~ — **MÅLT 2026-09-07, se under**
- ~~S3.2~~ — **MÅLT 2026-09-12, se under**
- ~~S4.0~~ (`126807a`) — **MÅLT 2026-09-13, se under**
- ~~(p) `to_ore`~~ — **MÅLT 2026-09-13, se under**
- ~~(a)/(i) `unquote_scalar`~~ — **MÅLT 2026-08-31, se under**
- `mandate.py`
- A5 — TO halvdeler
- ~~B4 `ToolCallRecorder`~~ — **BESVART 2026-08-25, se under**
**B4 spurte OSS:** gir Claude-SDK-siden serveridentiteten gratis? MAF får verktøynavn UTEN
server-prefiks. Åpent hos søskenet: MAF S3.4 (F10).
### B4 — svaret er NEI (målt 2026-08-25, offline, mot `claude-agent-sdk` 0.2.139)
`create_sdk_mcp_server` emitterer det **bare** verktøynavnet. Serveridentiteten finnes — på
`McpSdkServerConfig["name"]` og `Server.name` — men den er **disjunkt fra hvert navn
verktøylista bærer**. Strengen `mcp__` forekommer i **0 av 24** Python-filer i pakken
(positiv kontroll: `create_sdk_mcp_server` blir funnet av samme spørring, så spørringen KAN
finne). Konstruksjonssiden namespacer altså ingenting: en `ToolCallRecorder` hengt der ser
`record_call`, ikke `mcp__tool_call_recorder__record_call`, og må få servernavnet fortalt.
Det er **samme pris som søskenet betaler**.
**Ærlig grense — hva målingen IKKE sier.** Den navnerommede formen `mcp__<server>__<tool>`
eksisterer: den bygges inne i CLI-en som følger med SDK-en (`_bundled/claude`, 178 literale
`mcp__`-forekomster, konstruksjonen på formen `` `mcp__${…}__${…}` ``). Det er **lest av
artefaktet, ikke observert i en kjøring hos oss** — å se den emittert krever en live
`query()`, som både D6-kostnadsregelen og suitens offline-invariant forbyr. Funnet er derfor
scopet til den sømmen vi faktisk kan bygge på: den in-process konstruksjonssiden. Prefikset
finnes på et lag vi bevisst ikke kjører, og et lag vi ikke kjører er ikke en søm vi kan feste
en recorder i.
**Pinnet av** `tests/test_sdk_tool_namespace_loadbearing.py` (4 tester). Value-beviset er
kjørt, ikke påstått: SDK-en ble mutert til å namespace ved konstruksjon (`"name":
f"mcp__{name}__{tool_def.name}"`) — **grønn før, 3 av 4 røde etter**, og den ene som forble
grønn er nettopp populasjons-kontrollen, som den skal. SDK-fila ble restaurert byte-identisk
(sha256 verifisert begge veier).
**Datering (D7-rammen):** dette er arbeid ETTER 2026-08-09 og skal **ikke** leses som
uavhengig konvergens selv om svaret er identisk med søskenets.
### (a)/(i) `unquote_scalar` — svaret er JA, den var ÉN regel, men pinnet bare i kanten (målt 2026-08-31)
Kandidaten står i køen fordi søskenet vokste en navngitt `unquote_scalar` etter at en
**duplisert konvertering hadde driftet** — to steder som fjernet anførselstegn fra en
frontmatter-skalar, etter to regler. Speilings-spørsmålet er derfor ikke «har vi funksjonen»,
men det søskenets defekt faktisk stiller: **er den ÉN regel hos oss, og er selve regelen
load-bearing?**
**Populasjonen først.** `unquote_scalar` finnes ikke hos oss: **0 treff av 76 undersøkte
`.py`-filer** i `src`+`tests` (positiv kontroll: samme spørring finner `parse_frontmatter` i
`okf.py`), og `unquote` finnes ikke i repoet utenfor `.venv`. Vår motpart er
`okf._strip_matching_quotes` — **én definisjon, ett kallsted** (`_parse_frontmatter_and_body`).
Søskenets drift-form finnes altså ikke her.
**Men regelen var dekket bare i kanten.** Med `scripts/mutation_harness.py`, nevner `tests/`
(hele suiten, 950 tester), hver kjøring sha256-restaurert:
- Å detache regelen helt (`return value[1:-1]` → `return value`) er **RØD** —
`test_okf.py::TestFrontmatter::test_unknown_fields_preserved_and_quotes_stripped` fanger den.
- Hver av de tre **klausulene** var **grønn-men-død**: å svekke lengdevakten (`>= 2` → `>= 1`),
å droppe matching-kravet (`value[0] == value[-1] and`), og å utvide quote-settet med en
symmetrisk delimiter (backtick) lot hele suiten stå grønn.
Samme klasse som `_STRUCTURE_MARKERS`-hullet i økt 32: sømmen var NAVNGITT og kant-dekket, som
ikke er det samme som dekket. **Pinnet av** `tests/test_okf_unquote_loadbearing.py` (5 tester,
950 → 955). Value-beviset er kjørt, ikke påstått: hver klausul-test er grønn før og rød etter
nøyaktig sin egen mutasjon, med populasjons-kontrollen grønn i begge (mutasjonen landet ikke
for bredt), og ledd 3 pinnet på linje via `--red-at`.
**EN MÅLETRAP, MÅLT — ny lærdom om harnesset.** Første forsøk på klausul 3 utvidet settet med
`'['`. Suiten forble grønn, hvilket leses som «klausulen er ikke dekket» — men mutasjonen er en
**no-op**: `'['` kan aldri tilfredsstille matching-kravet, siden `[` ikke er `]`. Flow-form-
verdier er altså beskyttet av **matching-klausulen, ikke av quote-settet**, og en grønn kjøring
under den mutasjonen var aldri bevis om quote-settet i det hele tatt. **Harnesset kan ikke
skille en oppførsels-bevarende mutasjon fra en udekket søm — begge kommer ut som «stayed
GREEN».** En mutasjon må vises å endre oppførsel før dens grønne leses som et hull. Dette er
Verifiseringsloven ansikt 4 anvendt på selve måleapparatet: et negativt resultat fra en
spørring som ikke KAN finne, er ikke null — det er ikke målt.
**Ærlig grense — hva dette IKKE sier.** Å pinne at flow-verdier passerer **urørt** er ikke
flow-DEKODING, og fila legger ingen til: `tags: [a, b]` forblir strengen `"[a, b]"`. Den
linje-orienterte parseren har ingen nesting-modell ved design (§1 ærlighets-regelen). Den
additive flow-dekoderen er søskenets B4-arbeid i `portfolio-optimiser` og er bevisst **ikke**
bygget her; testene pinner dagens grense slik at det arbeidet ikke kan lande stille på denne
siden.
**Datering (D7-rammen):** arbeid ETTER 2026-08-09 — skal **ikke** leses som uavhengig konvergens.
### S2.7 — gaten er ÉN regel, og den var pinnet i ARITMETIKKEN, ikke i BESLUTNINGEN (målt 2026-09-07)
Kandidaten står i køen fordi søskenet strammet validatoren i to halvdeler: (a) en strukturell
blokk på `claimed > nominal_feasible`, og (b) en IR-invariant `low ≤ unit_cost ≤ high`. **Begge
halvdeler er GATET her** på D-A pkt. 1 + commons-pull (paritetsplanens rad 12), og defekten de
svarer på er bekreftet på vår side som C-F2 (`docs/review-2026-07.md`). Speilings-spørsmålet som
KAN besvares offline i dag er derfor et annet: **er dagens grense — «den ENE numeriske gaten er
p90» — load-bearing?**
**Populasjonen først.** En claim er numerisk avgrenset i nøyaktig TO steder i `src/`, med hver
sin spec-rolle: skjema-invarianten (claim ≤ items-total, §7.1, `ir.py:50`) og validator-gaten
(claim ≤ p90, §3 Steg 4, `validator.py:68`). `_FEASIBLE_FRACTION` forekommer kun i `validator.py`,
og det finnes ingen annen Monte Carlo eller `quantiles`-beregning i pakken (positiv kontroll:
samme spørring finner `validate_proposal` i `loop.py:284`). Søskenets drift-form — to gater som
har glidd fra hverandre — finnes altså ikke her.
**Men dekningen deler seg rent på tvers av regelen.** Med `scripts/mutation_harness.py`, nevner
`tests/` (hele suiten, 955 tester), hver kjøring sha256-restaurert:
- Å detache gaten helt (`if … > p90:` → `if False:`) er **RØD** — `test_validator.py` fanger den.
- Alt gaten **REGNER UT** er RØDT, og goldenen er grunnen: policy-taket (`0.30` → `0.31`),
band-grenen (ignorér bands), band-endepunktenes rekkefølge, MC-seeden, p90-kuttpunkt-indeksen
og `nominal_feasible`-formelen reddet alle suiten.
- Alt gaten **BESLUTTER MED** er **grønn-men-dødt**: å bytte grensen til `p10`, å bytte den til
`nominal_feasible`, og å løsne `>` til `>=` lot alle 955 testene stå grønne.
Det skillet ER funnet, og det er skarpere enn «sømmen er tynn»: goldenen fryser hvert tall
validatoren PRODUSERER, og kan derfor ikke hjelpe med det ene den ikke observerer — hvilken
grense gaten LESER. Konsekvensen er konkret: **å bytte `p90` mot `nominal_feasible` ER den gatede
S2.7-halvdel (a), og den ville landet med suiten grønn**, før D-A er besluttet.
**Pinnet av** `tests/test_validator_gate_loadbearing.py` (8 tester, 955 → 963). Value-beviset er
kjørt, ikke påstått: hver klausul-test er grønn før og rød etter nøyaktig sin egen mutasjon, med
golden-tallene grønne i BEGGE kjøringer — som mekanisk viser at mutasjonen flyttet BESLUTNINGEN,
ikke aritmetikken. De to IR-testene er pinnet med `--red-at` mot invariantens egen feilmelding,
fordi de dør i en hjelpefunksjon og ikke i testkroppen.
**Mutasjonene ble vist å endre oppførsel FØR deres grønne ble lest som hull** (fellen fra økt 39).
Alle tre grensetilfellene er nåbare og ble kjørt: en claim nøyaktig PÅ p90 finnes (degenerert
band, `0.30 × 1000 == 300.0`), og med goldenens eget band valideres en claim på 100 000 mens
`nominal_feasible` er 90 000 — C-F2s første moteksempel, reprodusert live på p90 = 121 057.09,
sammen med det andre (claim 55 000 mot nominal 30 000, p90 = 65 058.49). Begge tallene er
identiske med review-ens, som bekrefter at defekten er spec-båren.
**To ting målingen ga i tillegg.** (1) Populasjonskontrollen (AST) ble bevist mot en
**oppførselsbevarende** mutasjon — `> p90` utvidet til `> p10 and > p90`, som er logisk identisk
når `p10 ≤ p90` — og alle tre oppførselskontrollene forble grønne. En ny gate-plassering er
usynlig for enhver oppførselstest; det er nettopp derfor AST-kontrollen står der. (2) Under
containment-mutasjonen forble golden-testen **grønn**, hvilket mekanisk bekrefter review-ens
påstand om at S2.7 halvdel (b) er golden-kompatibel når D-A lander.
**Nytt utover C-F2:** IR-en har heller ingen ORDNING på band-endepunktene. `(1.40, 0.70)`
aksepteres; `random.uniform(1.40, 0.70)` trekker fortsatt fra [0.70, 1.40], så området korrumperes
ikke — men den seedede strømmen vandres baklengs, hvilket er en ANNEN p90 (målt: 120 456.91 mot
121 057.09). Et band hvis betydning avhenger av argument-rekkefølgen er ennå ikke et band.
**Ærlig grense — hva dette IKKE sier.** Å pinne at en claim over `nominal_feasible` validerer i
dag er ingen godkjenning av oppførselen; C-F2 kaller den en MAJOR spec-nivå-defekt, og fiksen er
GATET, ikke avvist. Testene pinner grensen slik at det gatede arbeidet MÅ ankomme som en synlig
rød test og en beslutning, aldri som et stille bytte. Ingen `src/`-endring er gjort, ingen
spec-tekst rørt, og fasiten er ikke berørt.
**Datering (D7-rammen):** arbeid ETTER 2026-08-09 — skal **ikke** leses som uavhengig konvergens.
### S3.2 — id-en er pinnet, NØKLINGEN er ikke, og de to nøklings-stiene er uenige (målt 2026-09-12)
Kandidaten står i køen fordi søskenet fikset flerkandidat-ExpeL-seeding: frøet skal lese den
dømte kandidaten fra verdict-filas EGEN frontmatter (promoteringen skriver den), med dagens
nøkling som fallback. Feature-halvdelen av den defekten er bekreftet her som C-F5
(`docs/review-2026-07.md`) og **GATET** på D-A pkt. 4 + commons-pull (paritetsplanens rad 14),
mens id-halvdelen alt er løst: en lastet `verdict_id` leses VERBATIM (§4.2). Speilings-
spørsmålet som KAN besvares offline i dag er derfor: **er dagens grense — «id-en kommer fra
FILA, nøklingen kommer fra BUNDELEN» — load-bearing i BEGGE halvdeler?**
**Populasjonen først.** En dom nøkles i nøyaktig TO steder i `src/`, med hver sin spec-rolle:
bundle-frøet (`experience.py:146`, §3 Steg 1 — nøklet på bundelens ENE IR-projeksjon) og
fil/inbox-stien (`inbox.py:105`, §4.2 — nøklet på dommens egne `proposal_features`). Ingen
tredje konstruksjon finnes (AST-målt over hele pakken; positiv kontroll: samme AST-spørring
finner `VerdictStore`-konstruksjon i tre moduler, så spørringen KAN finne). **Og her finnes
søskenets drift-form — i motsetning til S2.7 og `unquote_scalar`:** de to stiene nøkler ETTER
ULIKE REGLER.
**Dekningen deler seg rent mellom id og nøkling.** Med `scripts/mutation_harness.py`, nevner
`tests/` (hele suiten, 963 tester), hver kjøring sha256-restaurert:
- Å detache sømmen (frøet itererer ingenting) er **RØD**; det samme er type-filteret,
decision-defaulten og `description`-lesningen.
- **ID-halvdelen er pinnet på BEGGE sider:** å re-minte i stedet for å lese frontmatter-id-en
er RØD (`test_step8`), og å droppe mint-fallbacken — slik at ikke-promoterte dommer nøkles på
en tom id — er også RØD.
- **NØKLINGS-halvdelen er grønn-men-død.** Å bytte bundle-projeksjonen mot tomme features lot
alle 963 stå grønne, og det gjorde også den gatede fiksens EGEN form (les kandidaten fra
verdict-filas frontmatter, fallback dagens nøkling). **Ingenting i suiten observerte hva en
seedet dom er nøklet PÅ.**
- Én klausul i rasjonalet var grønn-men-død i tillegg: kravet om BEGGE læringsfeltene før
markøren emitteres. Svekket til enten-eller forble suiten grønn — og konsekvensen er en
ærlighets-defekt (§1): markøren navngir da det fraværende feltet som `None`.
**Mutasjonene ble vist å endre oppførsel FØR deres grønne ble lest som hull** (fellen fra økt
39). Tom nøkling senker den seedede dommens similarity mot sin egen bundle-projeksjon fra 1.00
til 0.15 — observerbart, og rangerings-relevant i det øyeblikket en andre oppføring finnes.
C-F5s rest-defekt er reprodusert live: to promoterte dommer om ULIKE kandidater (LED vs.
ventilasjon) seedes begge nøklet på bundelens ENE projeksjon, så en spørring som bærer
ventilasjons-kandidatens egne features scorer BEGGE til 0.0 og avgjøres av hex-id-rekkefølge,
ikke av struktur.
**NYTT UTOVER C-F5 — nøklingen er sti-avhengig, og dermed rekkefølge-avhengig.** Samme dom —
samme kandidat, samme mintede id (`c8c97c9d992229dc`), altså samme first-write-wins-slot —
nøkles på `VENT-AGG-01`/250 000 via inbox-stien og på `ENERGI-TOTAL-EL`/30 000 via bundle-frøet.
Hvilken nøkling som overlever avgjøres av LASTE-REKKEFØLGEN, ingenting annet. Og fiksen kan
ikke være ensidig: `promote` skriver `verdict_id` og `description`, men **ingen** kandidat-felt
(målt frontmatter-nøkkelsett: `decision`, `description`, `provenance`, `tags`, `title`, `type`,
`verdict_id`) — hvilket er grunnen til at fiksens egen form er en **no-op mot enhver fixture i
repoet i dag**, og derfor måtte måles mot en fixture som bærer feltene.
**Pinnet av** `tests/test_experience_keying_loadbearing.py` (11 tester, 963 → 974, strengt
supersett: 0 tapte node-id-er). Value-beviset er kjørt, ikke påstått: hver test er grønn før og
rød etter nøyaktig sin egen mutasjon, med fold-markøren grønn i BEGGE kjøringer — som mekanisk
viser at mutasjonen flyttet NØKLINGEN, ikke sømmen. To sammensatte tester ble SPLITTET fordi en
rød test bare beviser sin FØRSTE assert (§1-halvdelen er i tillegg pinnet med `--red-at None`).
**To kontroller utover oppførselen.** (1) Populasjonskontrollen (AST) ble bevist mot en
oppførselsbevarende mutasjon — en tredje, ubrukt `VerdictRecord`-konstruksjon — med alle
oppførselstestene grønne. (2) Å heve projeksjons-lesningen INN i seedings-loopen er likeledes
oppførselsbevarende (tre oppførselskontroller grønne), og er samtidig første halvdel av den
gatede fiksen; derfor er formen pinnet strukturelt (`load_validator_input` kalles nøyaktig ÉN
gang i `seed_store_from_bundle`) eller ikke i det hele tatt.
**Ærlig grense — hva dette IKKE sier.** Å pinne at alle dommer i en bundle deler ÉN nøkling i
dag er ingen godkjenning; C-F5 kaller den en MAJOR spec-nivå-defekt, og fiksen er GATET, ikke
avvist. Testene pinner grensen slik at det gatede arbeidet MÅ ankomme som en synlig rød test og
en D-A pkt. 4-beslutning — samme ratchet-rolle `test_ingest_stamp_conformance_loadbearing.py`
har oppstrøms. Ingen `src/`-endring er gjort, ingen spec-tekst rørt, og **fasiten er ikke
involvert i nøklingen i det hele tatt** — hvilket er nettopp derfor den ikke kunne hjelpe.
**Datering (D7-rammen):** arbeid ETTER 2026-08-09 — skal **ikke** leses som uavhengig konvergens.
### S4.0 — baselinen er lastet, og den er strukturelt utenfor dommerens rekkevidde (målt 2026-09-13)
Kandidaten står i køen fordi søskenet forankrer `affected_items` mot en kostbaseline. Defekten
er bekreftet her som C-F3 (`docs/review-2026-07.md`, MAJOR, spec-nivå: en diktet kostlinje
validerer en 2,9 MNOK-claim), og fiksen — en fail-closed avstemmings-stage — er **GATET** på
D-A pkt. 2 + et commons-amendment for `cost-baseline.json` (paritetsplanens rad 19).
Speilings-spørsmålet som KAN besvares offline i dag er derfor: **er dagens grense — «hvert
kosttall validatoren dømmer på stammer fra forslaget selv» — load-bearing?**
**Populasjonen først.** En `SavingsProposal` blir til i nøyaktig TRE steder, med hver sin
proveniens: det modell-forfattede parset (`loop.py:89`), bundelens baseline-projeksjon
(`ir.py:64`) og det re-leste system-outputet (`hitl.py:132`). AST-målt over alle 27
`src/*.py` (positiv kontroll: samme spørring finner `validate_proposal`s ENE kallsted,
`loop.py:284`). **Kun den FØRSTE når validatoren.** Det er C-F3 uttrykt som en måling.
Baselinen LASTES på hver komposisjonssti — `run.py:123`, `run_s10.py:71`, `experience.py:132`
— og det eneste feltet noen leser direkte av den er `project_id` (fire steder). Alt annet
forlater lastingen gjennom `CandidateFeatures.from_proposal`, som leser kodene, `measure` og
claimen. **`quantity`, `unit_cost` og usikkerhets-bandene er skjema-validert og deretter
aldri lest igjen av noe.** Fiksens egen input ligger altså i minnet i samme
`ComposedRunContext` som dommen felles fra, og ingen sti fører den dit.
**Målingene.** Med `scripts/mutation_harness.py`, nevner `tests/` (hele den gamle suiten,
974 tester), hver kjøring sha256-restaurert fra disk:
- **M1 — baselinen erstattes med den svakeste skjemagyldige varianten** (kodene, `measure`,
claimen og `project_id` bevart; `quantity`/`unit_cost` flatet, band tømt): tre nye tester
RØDE, og **alle 974 gamle GRØNNE i begge kjøringer**. Bundelens kosttall kan byttes ut på
run-stien uten at én eneste eksisterende test merker det.
- **M2 — `ComposedRunContext.ir_projection: SavingsProposal` → `object`**: AST-testen RØD,
alle oppførselstester GRØNNE. En stille innsnevring av det bårne feltet er usynlig for
oppførsel — og ville slettet den eneste kostbaselinen på run-stien.
- **M3 — S10-stien slutter å kalle `load_validator_input`** (oppførselsbevarende alias):
loader-populasjonen RØD, `test_s10_run_layer.py` + `test_preflight.py` GRØNNE.
- **M4 — validatoren får en `baseline`-parameter** (den gatede fiksens signatur, default
`None`): signatur-ratchet-en RØD, **goldenen GRØNN** — som mekanisk bekrefter at S4.0s
signatur-halvdel er golden-kompatibel når D-A pkt. 2 lander.
- **M5 — kallstedets argument blir et keyword**: proveniens-kontrollen RØD, oppførselen
uendret.
- **M6 — fail-closed kodesett-gate i validatoren** (fiksens EGEN form, hardkodet baseline):
grense-testen RØD, **goldenen GRØNN i begge**.
- **M7 — retrieval slutter å lese kodene**: disjunkthets-testen RØD, golden + validator GRØNNE.
**En måletrap unngått — mutasjonen må vises å endre oppførsel, ikke bare å være skrevet**
(økt 39, her i motsatt retning). Første M1-forsøk flatet kostlinjene til `1.0 × 1.0` og
gjorde `test_run_entrance_loadbearing.py` RØD. Det så ut som dekning, men var det ikke:
total 1,0 < claim 30 000 bryter IR-invarianten (`ir.py:46`), så mutasjonen var en
**konstruksjonsfeil**, ikke en baseline-fjerning, og rødheten attribuerte til pydantic.
Harnessets kollateral-kontroll fanget den. Den korrekte mutasjonen holder invarianten — og
da er alle 974 grønne.
**NYTT UTOVER C-F3 — bundelen BÆRER en kostbaseline, og retrieval ser den allerede.** C-F3
formulerer defekten som «ingenting i bundle-formatet bærer en kostbaseline å avstemme mot».
Målt her er det for sterkt: `validator-input.json` bærer `ENERGI-TOTAL-EL` à 300 000 NOK, og
den lastes på hver run-sti. C-F3s kjørte bevis er reprodusert med review-ens egne tall (claim
2 900 000, degenererte percentiler 3 000 000) og skjerpet: det diktede kostgrunnlaget er
**33,3× hele bundelens baseline**, claimen er **9,67× byggets totale årlige energikost**, og
den diktede koden har **null overlapp** med bundelens kodesett. Det overlappet BEREGNES —
`CandidateFeatures` bruker det til å rangere erfaring. **Systemet holder altså beviset som
ville avslørt dikteringen, bruker det på rangering, og aldri på å dømme.** Defekten er ikke
at baselinen mangler; den er at den ikke er koblet til dommeren.
**Hvor bredt fiksen slår ut (en telling, ikke et load-bearing-bevis — derfor ikke harnesset,
men git-verifisert restaurering):** med fiksens form hardkodet til bundelens kodesett er **30
av 974** røde. Fiksen er altså bredt synlig i suiten, ikke stille. Ærlig grense: det tallet er
målt på en HARDKODET baseline; den ekte fiksen ville lest bundelens baseline per kjøring, og
hver testfixtures egen baseline ville da definert sitt eget kodesett — så 30 er et tak på
støyen, ikke et estimat på arbeidet.
**Pinnet av** `tests/test_cost_baseline_loadbearing.py` (10 tester, 974 → 984, strengt
supersett: 0 tapte node-id-er). To testpar er SPLITTET fordi en rød test bare beviser sin
FØRSTE assert: kostlinjene fra bandene, og valideringen av den diktede linja fra dens
magnitude.
**Ærlig grense — hva dette IKKE sier.** Å pinne at baselinen ankommer intakt er ingen påstand
om at den BRUKES; det gjør den ikke, og C-F3 står som MAJOR. Testene pinner grensen slik at
det gatede arbeidet MÅ ankomme som en synlig rød test og en D-A pkt. 2-beslutning — samme
ratchet-rolle `test_ingest_stamp_conformance_loadbearing.py` har oppstrøms. Ingen
`src/`-endring er gjort, ingen spec-tekst rørt, og goldenen kan ikke hjelpe: den fryser hva
validatoren REGNER UT av et forslag, og baselinen er ikke en input til den beregningen i det
hele tatt. De to magnitude-/disjunkthets-påstandene er dessuten faktapåstander om
bundle-fixturen og deler anker med goldenen — de er konsistens-tester, ikke uavhengige
søm-bevis, og er merket som det over.
**Datering (D7-rammen):** arbeid ETTER 2026-08-09 — skal **ikke** leses som uavhengig
konvergens.
### (p) `to_ore` — regelen finnes i FIRE kopier, tre av dem kjøres aldri, og gaten den skulle tjene er slått av (målt 2026-09-13)
Kandidaten står i køen fordi søskenet vokste en navngitt `to_ore` etter at en **pengekonvertering
hadde driftet i to kopier** — `run.py` re-implementerte `ledger.to_ore` privat, og de to kopiene
møttes på hver sin side av én målsammenligning (`_goal_limit_if_reached`). Søskenets beslutning ble
«kvantiser per linje, summer heltall», pinnet med `assert run_mod.to_ore is ledger_mod.to_ore`.
Speilings-spørsmålet er derfor ikke «har vi funksjonen», men: **er vår pengekonvertering ÉN regel,
og er den load-bearing der den beslutter noe?**
**Populasjonen først.** `to_ore` finnes ikke hos oss: **0 treff av 80 undersøkte `.py`-filer** i
`src`+`tests` (positiv kontroll: samme spørring finner `unit_cost` i 19 av dem, så spørringen KAN
finne). Vi har ingen NOK→øre-akse i det hele tatt — vår pengeakse er den akkumulerte
USD-forbruket `total_cost_usd`, og vår konvertering er avrundingen til seks desimaler. Den finnes
i **fire literale kopier uten navngitt kilde**: `run.py:159` (`_client_cost_usd`), `run_s10.py:110`
og `:130` (de to persisterings-kallstedene) og `costsim.py:125` (per-celle-estimatet). Én fil
unna gjør det samme pakket det motsatte: `valuereport.py` avrunder gjennom `_SHARE_DIGITS`.
**Søskenets drift-form finnes altså her** — i den halvdelen som ikke har fått sin ene kilde.
**Og driften har et møtested.** På en `cost_usd`-stopp skriver ETT kall begge tall: `stop.json`
bærer `observed` fra `BudgetExceeded` — den **rå** verdien gaten sammenlignet — mens `usage.json`
bærer `cost_usd` **avrundet**. To tall for samme størrelse, fra samme kall, etter to regler.
**Men det skarpeste funnet er at tre av de fire kopiene aldri kjøres.** Med
`scripts/mutation_harness.py`, nevner `tests/` (hele den gamle suiten, 984 tester), hver kjøring
sha256-restaurert fra disk — og med positivkontrollen først: å erstatte HELE avrundingsuttrykket
med konstanten `999.0` lot **alle 984 stå grønne** på `run.py:159`, `run_s10.py:110` og `:130`.
Grenene utøves aldri med en kost. Deres grønne under en detach var derfor aldri bevis om
avrundingen — det var «ikke målt» (økt 39, Verifiseringsloven ansikt 4 på måleapparatet). Kun
`costsim.py` var dekket. **DEFAULT-en var derimot pinnet:** `getattr(client, "total_cost_usd",
None)` → `0.0` er rød i `test_run_entrance_loadbearing.py`. Nøkkelen var pinnet i sitt navn og fri
i sin verdi (økt 41) — her: default-grenen pinnet, verdi-grenen ukjørt.
**Gaten som skulle bruke tallet er slått av på hver eneste sti.** `max_cost_usd` settes i **0 av
27 `src`-moduler** (positiv kontroll: samme AST-skann finner `max_budget_usd_per_call`, som ER
wiret). Alle fire `BudgetMeter(...)`-konstruksjoner i `src` tar default `None`, og
`guard_before_call` returnerer før den sammenligner. C3.5-beltet er altså ikke-no-op **kun i sin
egen enhetstest**. Samme klasse som S4.0, ett hakk verre: der var feltet lastet og utenfor
dommerens rekkevidde; her er dommeren bygget og ingen sti gir den et tak.
**SYV mutasjoner, alle VALUE-PROVED** (grønn før / rød etter, hver med kollateral-kontroll grønn i
begge kjøringer); anker → erstatning ordrett:
- **M1 — avrundingen detaches** (`run.py`): `return None if cost is None else round(float(cost), 6)`
→ `return None if cost is None else float(cost)`. To RØDE (kvantiseringen og «ikke den rå
verdien», splittet); kontroll `test_the_value_branch_is_reached_at_all` GRØNN i begge.
- **M2 — sifferantallet drifter** (`run.py`): `return None if cost is None else round(float(cost), 6)`
→ `return None if cost is None else round(float(cost), 2)`. Kvantiserings-testen RØD; samme
kontroll GRØNN.
- **M3 — beltet leser den AVRUNDEDE kosten** (`loop.py`, søskenets drift innført):
`meter.guard_before_call(spent_usd)` → `meter.guard_before_call(round(spent_usd, 6))`.
Stopp-testen RØD; kontrollen «den avrundede ville ikke ha stoppet» GRØNN i begge.
- **M4 — stop-eventet rapporterer den avrundede** (`budget.py`):
`raise BudgetExceeded("cost_usd", self._max_cost_usd, spent_usd)` →
`raise BudgetExceeded("cost_usd", self._max_cost_usd, round(spent_usd, 6))`. `observed`-testen
RØD; at beltet fortsatt STOPPER GRØNN — rødheten attribuerer til rapporteringen, ikke til gaten.
- **M5 — én kopi drifter til et annet sifferantall** (`costsim.py`):
`cost = round(estimated_tokens * price.usd_per_mtok / _TOKENS_PER_MTOK, 6)` → samme med `, 2)`.
Siffer-settet RØDT; kopi-tellingen GRØNN (mutasjonen endrer siffer, ikke antall).
- **M6 — én kopi foldes bort** (`run_s10.py`, fiksens retning):
` cost_usd=round(client.total_cost_usd, 6),` → ` cost_usd=client.total_cost_usd,`.
Kopi-tellingen RØD; siffer-settet og modul-settet GRØNNE.
- **M7 — noen wirer run-total-taket** (`run.py`, ratchet-en): ` run_label = run_id or out_dir.name`
+ ` meter = BudgetMeter(contracts.termination)` → samme med
` meter = BudgetMeter(contracts.termination, max_cost_usd=1.0)`. Fraværs-testen RØD;
positivkontrollen og «en meter uten tak stopper aldri» GRØNNE.
**Fixturen fiksen LESER, bygget** (økt 41). `ScriptedClient` bærer ingen `total_cost_usd` i det
hele tatt, og det er nettopp derfor hver eksisterende run-sti-test bare utøver den ærlige
null-grenen. `CostingScriptedClient` legger på en — 0.1234567891 USD, mer presisjon enn regelen
beholder, så den persisterte verdien forteller hvilket tall som ble skrevet. Belte-testene bruker
en forbruks-verdi som ligger STRENGT MELLOM taket og sin egen avrunding (0.10000004 mot tak 0.1,
`round(…, 6) == 0.1`): rå verdi stopper, avrundet slipper gjennom. Uten den konstruksjonen er M3 en
no-op og ville sett ut som en udekket søm.
**Pinnet av** `tests/test_cost_usd_quantization_loadbearing.py` (13 tester, 984 → 997, strengt
supersett: 0 tapte node-id-er). Tre testpar er SPLITTET fordi en rød test bare beviser sin FØRSTE
assert: «kvantisert til seks desimaler» fra «ikke den rå verdien», «beltet stopper» fra «stoppet
bærer den rå verdien», og siffer-settet fra kopi-tellingen.
**Ærlig grense — hva dette IKKE sier.** Ingen `src/`-endring er gjort, og det er en beslutning, ikke
en forglemmelse. Å gi de fire kopiene én navngitt kilde er en refaktorering, ikke en fiks på en målt
defekt; å wire run-total-taket inn i inngangen er en FEATURE — et CLI-flagg og et kontraktsfelt, med
`--help`/README-paritetsvakten bak seg — og per-kall-taket `max_budget_usd_per_call` binder allerede
et live forbruk gjennom SDK-en. Testene sier heller ikke at dagens tilstand er ønskelig: de sier at
den er MÅLT, og de gjør hver av de tre endringene synlig som en rød test i stedet for en stille
landing. Kopi-tellingen er dessuten en tekstlig AST-egenskap, ikke et oppførselsbevis — den fanger
en femte kopi og et endret sifferantall, ikke en femte kopi skrevet på en annen form (`f"{x:.6f}"`,
`Decimal`). Og `run_s10.py` er byte-frossen og importeres aldri i suiten: dens to kallsteder er
pinnet ved AST, ikke ved kjøring, hvilket er den sterkeste sømmen som finnes mot en fil vi ikke
kjører.
**Datering (D7-rammen):** arbeid ETTER 2026-08-09 — skal **ikke** leses som uavhengig konvergens.
Rammen rundt køen: å lese søskenets kode er tillatt (`3bdf7f0`), men kopiering skal kun skje
der det tjener løsningen, aldri som snarvei. **Uavhengighets-beviset er DATERT** t.o.m.
2026-08-09; arbeid etter den datoen kan ikke leses som uavhengig konvergens.
## D-A-gater og fasit-berøring
- **D-A#5 mangler story-etikett oppstrøms** — avklar med MAF før teksten låses. En ny
hovedbok-kontrakt MÅ inn i §12s kryssjekktabell i SAMME amendment; ellers blir tabellen
ufullstendig i det øyeblikket kontrakten finnes.
- **D-A#2 rører fasiten.** commons er meldt at vår §12-vakt keyer på ordrett `| `generated` |`
⇒ et amendment som ERSTATTER raden gjør oss RØDE. Det er **by design**: en fasit-endring
skal koste en synlig rød test, ikke gli gjennom.
- **Gates:** D-F/D-G → K13 · D-B → K14/K15 · D-E · okf-toolkit-§8 · delbarhet av ledger-/
outbox-format. R-9 er valgfri.