portfolio-optimiser-claude/docs/2026-08-18-funn-koeer-og-gater.md
Kjell Tore Guttormsen 1041687d31 test(experience): the id was pinned, the keying was not - and the two paths disagree
S3.2 measured with scripts/mutation_harness.py, denominator tests/ (963), every
run sha256-restored. The mirroring question answerable offline: is today's
boundary - "the id comes from the FILE, the keying comes from the BUNDLE" -
load-bearing in both halves?

The id half is pinned on both sides (re-minting RED, dropping the mint fallback
RED). The keying half is green-but-dead: empty features and the gated C3.2 fix's
own shape each left all 963 green. Nothing observed what a seeded verdict is
keyed on. One rationale clause too: requiring BOTH learning fields, whose
either-or form emits a marker naming the absent field as None (honesty, §1).

New beyond C-F5: the sibling's drift form DOES exist here. A verdict is keyed in
exactly two places by different rules - the bundle seed (bundle-wide) and the
file/inbox path (per-verdict) - so the same verdict id lands in the same
first-write-wins slot with a keying decided by LOAD ORDER. And promote writes no
candidate features at all, which is why the fix's shape is a no-op against every
fixture in the repo and had to be measured against one carrying the fields.

Pinned by tests/test_experience_keying_loadbearing.py (11 tests, 963 -> 974,
strict superset, 0 node ids lost). No src/ change: C-F5 is GATED on D-A pkt. 4,
and these tests exist so the gated work must arrive as a visible red test and a
decision. Two behaviour-preserving mutations carry their own controls (a third
VerdictRecord site; hoisting the projection read into the loop). Dated under the
D7 frame: work after 2026-08-09, never independent convergence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 23:40:07 +02:00

18 KiB
Raw Blame History

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. Fire er målt, 4 står igjen:

  • S2.7MÅLT 2026-09-07, se under
  • S3.2MÅLT 2026-09-12, se under
  • S4.0 (126807a)
  • (p) to_ore — TO kallsteder
  • (a)/(i) unquote_scalarMÅLT 2026-08-31, se under
  • mandate.py
  • A5 — TO halvdeler
  • B4 ToolCallRecorderBESVART 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ØDtest_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ØDtest_validator.py fanger den.
  • Alt gaten REGNER UT er RØDT, og goldenen er grunnen: policy-taket (0.300.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.

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.