docs(invarianter): the B gate's row, rewritten around the denominators that turned out to be its own

The row claimed three things the checkpoint measured as false: that every denominator comes from
the source (row 1's M=13 was a curated list in the gate's own b_gate.json), that the surface is
what is published (it was a hand list of eleven roots seeing 433 of 512 files), and that the gate
counts an MCP-registered door as callable (there was no code for it — "kind" appeared 0 times).
The 435-file figure was the working tree, two gitignored .local.md files included, so it was not
reproducible from the commit either.

Rewritten to what is true after the repair, with the old numbers kept as history so the row reads
as a correction and not as a clean slate: 3 of 17 · 0 of 2 · 9 of 9 · 0 of 3 · 4 of 5 · IKKE MAALT.
The markdown-fence rule's own measurement is refreshed too: on the bigger surface it now carries
TWO prose lines, not one — the second is a plan document quoting a command the operator ran in his
own session.

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

View file

@ -3235,42 +3235,75 @@
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.
Claude (19.09, ordre `20260919T040628Z-4756715055`, REPARERT samme dag etter PM-sjekkpunktet,
ordre `20260919T082156Z-338455001`):** 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 17 · 0 av 2 · 9 av 9 · 0 av 3 · 4 av 5 · IKKE MÅLT**, exit 1.
(Første utgave sa `3 av 13 · … · 6 av 6 · … · 1 av 2`; sjekkpunktet viste at tre av de nevnerne
var gatens egne tall, ikke kildens. Ingen rad ble GRØNNERE av reparasjonen — nevnerne ble sanne.)
**Rad 1s nevner UTLEDES av kjørestien** (`run_path_calls`): 41 po-funksjoner kalles i
`run.py::run_project` (PMs 39 deterministiske + `generate_via_llm`/`fresh_workflow`, som holdes
utenfor fordi de krever chatklient). Et kall som verken er erklært som steg eller navngitt som
holdt utenfor, teller i nevneren UTEN en dør — derfor kan den ikke krympe stille slik en kuratert
liste i gatens egen `b_gate.json` kunne: fjernes et steg fra kontrakten, står N uendret og
foreldreløsen navngis. 28 kall er holdt utenfor, hvert med sin grunn skrevet i gatens output. De
fire utboks-skriverne kjørestien bruker og ingen hadde erklært (`write_prepass`,
`write_parse_failures`, `write_proposal_reviews`, `write_debate_tools`) er steg nå: artefakt-
familien er sju skrivere av ti definerte, ikke tre. **En dør må være REGISTRERT og BEVIST:**
`entry["kind"]` leses (den ble lest 0 ganger før) og må være én av tre arter gaten har kode for å
etterprøve — `console-script` i pyproject, `module-main` med sin egen `__main__`-vakt,
`subcommand` registrert i modulens egen argparse — og hvert steg må dessuten ha en navngitt probe
som kaller døren og leser artefaktet. Målt: en modul med bare `def main(): return <symbol>()` tok
rad 1 fra 3 til 4 av 13 før; nå avvises den under alle fire arter, med grunn.
**«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.
det er hele grunnen til at `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:** ni vakter, hver med sin kjent-positive OG kjent-negative prøve, over **512 publiserte
filer lest av REPO-MANIFESTET** (`git ls-files`, eller filtreet selv i et rent uttrekk — som ER
det publiserte). Håndlista på elleve `roots` den erstattet så 433 av dem: `main.py`,
`examples/`, `spikes/`, `contexts/`, `CLAUDE.md` og `llms.txt` lå utenfor, og alle seks
kjent-positive kunne plantes i `main.py` uten at raden merket det. Manifestet gjør tallet
reproduserbart: 433 i uttrekk og 435 i arbeidstreet var de to gitignorerte `.local.md`-filene
under `docs/plan/`. **Tre av de ni vaktene feller INDIREKTE kall** — absolutt sti, liste lagt i en
variabel, konstant, shell-streng — så 5 av 5 av sjekkpunktets varianter avvises, med 0 falske
positive målt over hele flaten. **En tom flate er `IKKE MÅLT`, aldri grønn:** raden krever en
sentinel-fil og skriver både filtallet, hvilket manifest den leste og hvor mange filer som ikke
lot seg avkode (1 — en `.sqlite`-fixture). **I markdown teller kun linjer inne i kodeblokk**
(«docs med kjørbare kommandoer»): uten den regelen blir raden rød av TO prosa-linjer — målt på
den nye flaten 19.09 — `docs/research/2026-06-24-maf-vs-claude-agent-sdk.md:185`, som vurderer og
forkaster et pakkenavn, og `docs/plan/2026-08-09-fable-egnethetsreview-prompt.md:11`, som siterer
en kommando operatøren kjørte i SIN egen økt. Ingen av dem er en vei po kan gå.
**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. Samme grunn
gjelder de plantede variantene i testfila. **Rad 4, 5 og 6 har nevnere med navngitt kilde:**
rad 4 teller bare sjekker hvis kilde-symbol faktisk finnes i koden (`run_project`, `build_round`,
`v1_gate.FORM_OK`), rad 5 teller hvert strukturkrav for seg (to profil-medlemmer + fabrikk + søm
+ probe = 5) i stedet for å blande tre til én enhet, og rad 6s N er artefaktene kontrakten
navngir. **Attesteringen VALIDERES nå:** den må navngi kontraktens kjørebok, bære dens sha256,
si hvem som kjørte den, og ha en ekte ISO-dato som ikke ligger i framtiden (v1-gatens egen
`_parse_given`, gjenbrukt; BOM tåles som der). Før reparasjonen ga `kjørebok: x`, `dato: x`,
framtidsdatoen `3026-01-01` og en peker til en annen fil alle **2 av 2 GRØNN**.
**To valg gaten uttaler i sin egen output** (operatøren kan ikke svare på dem uten å lese kode):
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. **Påstanden om at gaten teller en MCP-registrert dør er STRØKET:**
den beskrev kode som ikke fantes.
**Load-bearing:** `tests/test_b_gate.py` (65 armer, hver nevner talt uavhengig i testen).
**12 av 12 mutanter felt i scratch-klone** (kontroll 65 av 65): nevneren krymper stille (3 armer)
· udeklarert kall teller ikke (2) · stub teller som dør (5) · ukjent inngangsart godtas (1) ·
navn teller som atferd (3) · tom flate blir grønn (1) · flaten snevres inn til en håndliste (6) ·
de tre indirekte vaktene fjernet (5) · sjekksummen ignoreres (1) · framtidsdato godtas (1) ·
rad 4s kilde ignoreres (1) · rad 5 teller strukturen som én enhet (3). Runden før felte 8 av sine
egne. **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. Rad 3 er en TEKSTVAKT, ikke en dataflyt-analyse: et
kommandonavn satt sammen av deler ved kjøretid og et navn lest ut av en miljøvariabel står
igjen, og raden sier det selv i stedet for å la GRØNN bety mer enn den bærer.