docs(invarianter): the outbox doors, and the two steps that stay shut [skip-docs]

The row the seam needs: why the outcome is derived rather than declared (the writer
branches on the TYPE, so a door taking it as an argument would let anyone author an
outbox of claims), why the outbox directory is always the caller's to name, why the
shape guard is a 3 and not a 2, and where the ground truth for each probe comes from.

It also writes down what did NOT move and why, so the next session does not rediscover
it: `rundebinding` and `rapport` share `round_builder`'s `main` with nothing in argv to
tell them apart, and `build_report` is a sub-step of `build_round` — a `report`
subcommand would be new capability, not a door over an existing step.

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

View file

@ -3534,3 +3534,45 @@
erklæring. **Kjøringen var målrettet mot de to filene som eier sømmen**, ikke mot hele suiten: erklæring. **Kjøringen var målrettet mot de to filene som eier sømmen**, ikke mot hele suiten:
et drap er monotont i testmengden, så et drap her er et drap; bare en OVERLEVENDE ville krevd et drap er monotont i testmengden, så et drap her er et drap; bare en OVERLEVENDE ville krevd
den brede kjøringen, og ingen overlevde. den brede kjøringen, og ingen overlevde.
- **Utboks-dørene — verktøykassens steg 4 (20.09, ordre `20260920T082234Z-615289758`):** alle sju
`outbox.write_*` i kjørestien fikk hver sin underkommando — `write-run-config`, `write-coverage`,
`write-outbox`, `write-prepass`, `write-parse-failures`, `write-proposal-reviews`,
`write-debate-tools`. De var kallbare bare gjennom `run.main`, og HVER vei gjennom den bygger en
chatklient; stegene selv trenger ingen modell — de tar ferdig rendret data og legger den på disk
i en byte-deterministisk form. Rad 1: **8 → 15 av 17**, exit 1 uendret, ingen annen rad flyttet
seg; 0 chatklient-navn nåbare fra `toolbox` (kontroll 24 i `run.py`).
**Utfallet er UTLEDET, ikke oppgitt, og det er den bærende beslutningen:** `outbox.write_outbox`
forgrener på outcome-TYPEN — en `ValidatedProposal` skriver persentiler, en `Rejection` skriver
grunnen sin — så en dør som tok utfallet som argument ville latt hvem som helst forfatte en
utboks av PÅSTANDER og gi den til Steg 8 som resultater. Døren kjører forslaget gjennom den
samme blokkerende gaten kjørestien kjører det gjennom, og skriver det som kom tilbake. Et
blokkert forslag er exit 3 MED artefaktene skrevet — det er der avvisningen bor. `verdict_id`
forblir et argument: `verdict-key` eier allerede den myntingen, og to produsenter av
læringsnøkkelen er nøyaktig det A5 finnes for å hindre.
**Utboks-katalogen er alltid kallerens å navngi**, aldri en default og aldri repoets egen: et
steg som skrev inn i en mappe rammeverket også leser som innboks ville gått utenom Steg 8s
forfremmelses-gate, og en probe som gjorde det ville lagt igjen filer en senere kjøring teller
som sine. `--stop-reason` er PÅKREVD framfor defaultet til tom streng, arvet fra kjernefunksjonens
egen målte grunn: «kjøringen ble ferdig» og «vi fikk aldri vite» må ikke være samme verdi.
**Formvakten er en avvisning, ikke en usage-feil:** skriverne tar `Mapping`/`Sequence` og ville
serialisert hva som helst, så en liste der et objekt hører hjemme blir en gyldig fil med feil
form — og kjøringen som LESER den senere er den som feiler. Døren feller formen med en gang, som
3 (kallet parset, så 2 er feil kode), og legger ikke igjen katalog.
**Fasiten er komponert i testen, aldri lest av modulen:** nyttelasten armen selv skrev og selv
teller, og byte-formen kontrakten krever (`sort_keys=True, indent=2` + linjeskift) — ikke
`outbox._dump`, som ville målt modulen mot seg selv.
**Load-bearing:** `tests/test_toolbox_outbox_doors.py` (9 armer), `tests/test_b_gate.py`
(`_EXTERNAL_TODAY` 8 → 15, `_WITH_A_DOOR_TODAY` navngir HVILKE femten, og de fire
«uten dør»-assertene er INVERTERT framfor slettet — de var armens diskriminator).
**11 av 11 mutanter felt** (kontroll 9 av 9 på dør-probene og 123 av 123 på gate-armene FØR
første tall, isolasjon verifisert på `toolbox.__file__` og `b_gate.__file__`), 0 ikke målt. Den
ellevte muterte KONTRAKTEN: `coverage` pekt på `write-prepass`, en underkommando proben aldri
kjører, og raden falt til 14 av 17.
**De to stegene som STÅR IGJEN, og hvorfor:** `rundebinding` (`build_round`) og `rapport`
(`build_report`) deler `evals/round_builder.py`s `main`. Gaten krever at kommandolinja NAVNGIR
steget når mer enn ett steg står bak samme dør, og den CLI-en har ingen underkommando å navngi
dem med. `build_report` er dessuten et DELSTEG av `build_round` (den returnerer strengen
`build_round` skriver), så en egen `report`-underkommando ville vært ny kapabilitet — en andre
vei til å produsere rapporten — ikke en dør over et eksisterende steg. Å gi proben et navn i
argv ved å døpe en katalog «rapport» ville vært å tøye proben for å få tallet. Rad 1 er derfor
**15 av 17**, uttalt, ikke 17.