docs(invarianter): the B gate's row — what it measures, what it refuses to conclude

Repo convention: every measured decision gets a row in the ledger with the load-bearing test that
turns red when the decision is undone. The row records the three choices the gate states in its
own output (CLI door over MCP, no budget ceiling in toolbox mode, row 6 never green without the
operator), the base64 reason, and the eight mutants that fell in the scratch clone — including
M-6, which shows row 3's green is a measurement and not a vacuous zero: without the
fenced-block rule one prose line in a research doc turns the row red.

v1 gate re-measured after the work: 0/3 · 0/3 · 3/8 · ingen rapport · 3/8 · IKKE MÅLT · 1/20 —
unchanged. PLAN.md § Ferdig-kriteriet untouched, as the order required.

Suite after git add: 2106 passed / 5 skipped / 5 xfailed, rc=0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-19 10:02:39 +02:00
commit 207337c8a2
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q

View file

@ -3198,3 +3198,44 @@
ikke et påbud; digesten dekker hver fil, så en `.DS_Store` som dukker opp i kopien er et AVVIK
(MÅLT: null `.DS_Store` og null symlenker i alle fire basene da kopien ble tatt); og kopien ble
tatt 18.09 fra vegnormals mappe KUN ved lesing — kildens mtimer er uendret.
- **B-gaten måler po som VERKTØYKASSE Claude Code driver — og po får aldri en vei tilbake til
Claude (19.09, ordre `20260919T040628Z-4756715055`):** operatørbeslutningen er at Claude Code
LEDER i utvikling og test, at po er verktøykassen, og at produksjon kjører Foundry uten Claude i
det hele tatt. `python -m portfolio_optimiser.evals.b_gate` er kontrakten den kapabiliteten skal
leveres inn i, skrevet RØD før noe bygges: **3 av 13 · 0 av 2 · 6 av 6 · 0 av 3 · 1 av 2 · IKKE
MÅLT**, exit 1. **Nevnerne kommer fra KILDEN, aldri fra en liste i gaten:** et steg teller bare
når symbolet finnes i modulen OG et navngitt kallsted i kjørestien kaller det (`measure_steps`),
og rollene leses av `workflow._MAKER_CHECKER_ROLES` slik den står (`run_roles`) — derfor felles
en hardkodet nevner av en konstruert kilde med ett steg mindre, ikke av repoet.
**«Kallbar utenfra» betyr uten chatklient:** en inngang som når steget via en vei der
`create_chat_client`/`client_factory`/`_default_factory` nevnes, teller IKKE (`entry_reaches`) —
det er hele grunnen til at de ti `run.py`-stegene er røde mens rundebinderen og v1-gaten er
grønne. Sjekken er med vilje strengere enn nødvendig: den leser hele det `main` når i sin egen
modul, ikke bare den ene veien ned. **Rad 3 er den eneste raden som er grønn, og den er grønn
som en MÅLING:** seks vakter, hver med sin kjent-positive OG kjent-negative prøve, over 435
publiserte filer. En vakt som ikke treffer sin egen kjent-positive telles ikke — «0 treff» fra
et mønster som ikke kan treffe er ikke null, det er ingenting. **I markdown teller kun linjer
inne i kodeblokk** («docs med kjørbare kommandoer»): uten den regelen blir raden rød av én
prosa-linje i `docs/research/2026-06-24-maf-vs-claude-agent-sdk.md:185` som vurderer og forkaster
et pakkenavn — målt, som mutant M-6. **Mønstrene ligger base64-kodet i `b_gate.json`** fordi
flaten gaten leser er den samme flaten gaten bor i; klartekst ville registrert kontrakten som sitt
eget funn og tvunget fram en unntaksliste, og en rad med unntaksliste kan skrus av ved å legge en
fil på lista. **Tre valg gaten uttaler i sin egen output** (operatøren kan ikke svare på dem uten
å lese kode): døren ut er en CLI-underkommando, ikke MCP (po har allerede fem `main()`; gaten
teller likevel en MCP-registrert dør, så valget binder ikke neste ordre) · budsjettvernet i B er
IKKE po sitt — `BudgetMiddleware` er fail-closed på manglende usage og konstrueres aldri uten
chatklient, så å beholde det her ville gjort fail-closed til fail-open; taket i B er Claude
Code-øktens eget forbruk, som po verken ser eller styrer, og Foundry-veien beholder sitt tak
uendret · rad 6 er `IKKE MÅLT` og aldri grønn før operatøren bekrefter at kjøreboka faktisk drev
en analyse — en fil gaten ALDRI skriver selv, samme regel som `attestering.txt` på v1-gaten.
**Load-bearing:** `tests/test_b_gate.py` (34 armer, hver nevner talt uavhengig i testen).
**8 mutanter felt i scratch-klone** (kontroll 1 failed / 2100 passed / 10 skipped / 5 xfailed —
den ene er `test_package_leaks_no_local_or_secret_files` sin EGEN kontroll-assert, `STATE.md`
finnes ikke i en klone): nevner hardkodet (5 armer) · chatklient-sjekken droppet (2) · et
rad 3-mønster fjernet (4) · «byte-identisk» byttet til «finnes» (1) · gaten skriver attesteringen
(1) · markdown-prosa teller som kommando (2) · kjent-positiv ikke validert (1) · kallstedet ikke
krevd (1). **v1-gatens tall er uendret** (0/3 · 0/3 · 3/8 · ingen rapport · 3/8 · IKKE MÅLT ·
1/20, målt etter). **Grensen, uttalt:** gaten beviser ikke at verktøykassen VIRKER — den sier
hvor langt unna den er. Rad 2, 4 og 5b er navngitte prober som ikke finnes ennå, og en test som
ikke finnes er RØD, aldri hoppet over.