# MAJOR-2 — en dør for menneskelig tilbakemelding på forslaget som ligger på bordet > **Status: DELVIS — steg 9 er påbegynt, ikke fullført.** M1–M37 er målt; **M38, M39 og M40 > gjenstår**, og K2-omkjøringen (§ 3) er ikke kjørt. Steg 10 (invariantraden + README) er ikke > skrevet. Dokumentet er committet i denne tilstanden fordi økten skiftes ved sømmen; neste økt > fortsetter fra M38. > > **Måledato:** 2026-09-05 (stien bærer ordredatoen, headeren måledatoen — S7b/S2c-formen) > **Ordre:** `20260904T173146Z-8102814273-from-portfolio-optimiser` > **Kode målt ved:** `ee7da3b` (steg 1–8: `ce4c15e` · `d4c8691` · `bbf4d3b` · `59f3fce` · > `c391fb5` · `fedf989` · `bfc634d` · `ee7da3b`) --- ## 0. Hva døra er | Spørsmål | Før | Etter | |---|---|---| | Kan et menneske svare på forslaget mens det ligger på bordet? | nei | ja — `--proposal-review` | | Hvor mange menneske-sømmer finnes inne i løkka? | 1 (`plan_reviewer`, som fyrer FØR enhver hypotese finnes) | 2 | | Hva skjer med svaret? | — | `revise` kjøper ETT forsøk til under det EKSISTERENDE taket; ordene når neste prompt ORDRETT | | Hvem avgjør utfallet? | validatoren | validatoren — dens SISTE dom (D6) | | Mynter en `approve` en dom? | — | nei; F2 står | | En kjøring uten reviewer | — | byte-identisk: samme prompter, samme utboks-filer, golden uendret | Målt før arbeidet startet (`docs/2026-09-02-misjonsreview-v2.md` § 3, re-målt mot HEAD): `grep -n "prior_" generate.py` finner nøyaktig ÉN søm — `prior_rejection`, maskinens egen falsifisering matet tilbake inne i samme kjøring. Et menneskes dom lander i NESTE kjøring (Steg-7-innboksen). «Improved proposals given feedback» var altså, for en person, en to-kjørings løkke med dager imellom. --- ## 1. Løkkas exit-kontrakt — og et premiss målingen felte **FØR** (`generate.py` ved `bcf3337`): ```python if isinstance(result, ValidatedProposal): return GenerationResult(outcome=result, refinements=tuple(fed_back)) last = result assert last is not None # max_attempts >= 1, so at least one validation ran return GenerationResult(outcome=last, refinements=tuple(fed_back)) ``` `last` settes KUN av en validator-avvisning. Planen (§ Risks, «Critical» #1) sa at «validert → revise» på hvert forsøk derfor ville nå slutten av løkka med `last is None` og dø på asserten. **ETTER**: en eksplisitt bærer `last_ruling: ValidatedProposal | Rejection | None`, satt etter HVER `validate_proposal`; D6 leses rett av den. **⚠️ PLANENS PREMISS ER FALSIFISERT AV MÅLINGEN — M29 forble GRØNN (0 røde av 1363).** Mutasjonen reverterer bæreren til `assert last is not None`, og HELE suiten står grønn. Grunnen er strukturell og ble først synlig da mutasjonen ble kjørt: D1(a) gjør at en `revise` med `attempts_remaining == 0` **returnerer** den validerte dommen inne i løkka, og på siste forsøk er `remaining = max_attempts - i - 1` alltid 0. Løkka kan derfor bare falle GJENNOM til halen etter en validator-**avvisning**, som setter `last` også. `last_ruling` og `last` er dermed identiske i det ene punktet halen leser dem. Konsekvens, uttalt heller enn skjult: **bæreren er UVITNET** (`budget_stop`-presedensen). Den står fordi den gjør D6 eksplisitt og fjerner en assert som hviler på en ikke-lokal invariant — ikke fordi en test holder den. Kommentaren i `generate.py` som påsto at asserten ville fyrt er en påstand flaten gjør om seg selv (Fase-3-klassen) og **må rettes i neste økt**, sammen med commit-teksten for `bbf4d3b` som bærer samme påstand (historikken skrives ikke om; rettelsen står her og i invariantraden). --- ## 2. Mutasjonstabellen — M1–M37 målt, M38–M40 gjenstår **Grønn kontroll:** `uv run pytest -q` → **1363 passed / 5 skipped**. Node-ID-settet er et **strengt supersett** av pre-MAJOR-2-baselinen: 1319 → 1368, **0 fjernet**, 49 lagt til. `ruff check src tests`, `ruff format --check src tests` og `mypy src` rene. Golden `tests/golden/demo-transcript.stdout` **BYTE-UENDRET**, `shasum -a 1` av INNHOLDET = `ea8c534773acdbe41ae68f2c55724d69aaf8be4f` (ikke git-blob-id-en). Protokoll per mutasjon: hele suiten, maks to mutasjoner per Bash-kall, restaurert fra `scratchpad/major2/pristine/` og verifisert med `shasum -c` — aldri `git checkout`. Alle 38 kjøringer rapporterte `restore=OK`. | M | hva mutasjonen gjør | røde | første navngitte armer | uavhengige vitner | |---|---|---|---|---| | M1 | detach reviewer-kallet (returner på validert som før) | 16 | T1, T2, T3a … | — | | M2 | ignorer beslutningen (alltid approve) | 13 | T1, T2, T3a … | — | | M3 | drop `prior_feedback`-injeksjonen (print-and-discard) | 6 | ordrett-armen, komposisjons-armen, T1 … | — | | M4 | tøm feedback etter ett forsøk (ikke-klebrig) | 1 | T6 alene | — | | M5 | akkumuler avvisninger i prompten | 1 | T6 alene | — | | M6 | vis også en AVVIST kandidat til revieweren | 4 | T4, T6, T10 … | — | | M7 | la en revise slippe å tikke rundeboka | 1 | T3a alene | — | | M8 | la revisjoner løkke UTENFOR `max_attempts` | 36 | A5, mandat, portefølje … | **ja** — 18 testfiler, alle eldre enn dette arbeidet | | M9 | `honoured` konstant `True` (og ingen forfremmelse) | 6 | T2, T3a, T3b, T7 … | — | | M10 | `approach_id` alltid `None` | 3 | T5, T8, T5-run | — | | M11 | skriv artefaktet etter returen, ikke fra `finally` | 2 | T9, T16 | — | | M12 | skriv artefaktet kun når lista er ikke-tom | 2 | T10, T16 | — | | M13 | skriv artefaktet også uten reviewer | 3 | T11 | **ja** — `test_a5_per_approach_artifacts`, `test_parse_failure_capture` | | M14 | la en `approve` mynte en `Verdict` | 1 | T12 alene | — | | M15 | les EOF som approve | 2 | T16-unit, T16-CLI | — | | M16 | fang ikke `ProposalReviewInputError` ved navn | 1 | T16-CLI alene | — | | M17 | enhver ikke-revise-linje er approve | 1 | T15 alene | — | | M18 | drop `single_only`-raden | 1 | T17 alene | — | | M19 | drop `report_forbidden`-raden | 1 | T18 alene | — | | M20 | bibliotekssømmen wiret, argparse-flagget borte | 9 | T13, T16, T17 … | — | | M21 | strømmene bundet ved konstruksjon | 1 | T20 alene | — | | M22 | slett den hostede navngitte nekten | 1 | T21 alene | — | | M23 | videresend det hostede feltet i stedet for å nekte | 4 | T21, partisjons-armen | **ja** — Fase-4e-armene i `test_explore_callsites` + `test_hosting` | | M24 | fersk reviewer per base i dispatcheren | 1 | T22 alene | — | | M25 | render kandidaten som repr | 2 | T14, T13 | — | | M26a | trunker feedback til 20 tegn | 5 | T1, T3b, T8 … | — | | M26b | trunker feedback til 40 tegn (sentinelen OVERLEVER) | 3 | T1, T8, T13 | — | | M27 | fall tilbake til siste validerte forslag (D6-alternativ b) | 1 | T13-loop alene | — | | M28 | drop `verdict_key` fra posten | 2 | payload-armen, run-payload-armen | — | | **M29** | **reverter exit-kontrakten til `assert last is not None`** | **0** | **— (se § 1)** | — | | M30 | drop `--live-dry-run`-nekten | 1 | dry-run-armen alene | — | | M31 | drop `--proposals-from-mandate`-nekten | 1 | pfm-armen alene | — | | M32 | notice-rendereren skriver linja uten reviewer | 2 | notice-armen, CLI-kontrollen | — | | M33 | notice-rendereren returnerer `None` på null | 3 | notice-armen, null-armen, CLI-null-armen | — | | M34 | feedback løftet ut av per-approach-kallet (krysser tilnærminger) | 5 | T1, T7, T5-run … | — | | M35 | bygg posten fra en RETURNERT liste i stedet for kaller-eid sink | 1 | T9 alene | — | | M36 | dispatcheren slutter å tråde revieweren | 1 | T22 alene | — | | M37 | detach CLI-utskriften mens rendereren fortsatt returnerer linja | 2 | T13, CLI-null-armen | — | | M38 | `attempts_remaining` regnet fra `max_attempts` alene | — | **IKKE MÅLT** | — | | M39 | drop `--checkpoint-dir`-nekten | — | **IKKE MÅLT** | — | | M40 | `honoured=True` satt ved revise-tid i stedet for etter hentingen | — | **IKKE MÅLT** | — | **Sum så langt: 38 kjøringer, 37 røde, 1 grønn (M29).** ### To signaturer verdt å lese * **M13 og M23 er røde i tester som er ELDRE enn dette arbeidet.** «Skriv artefaktet iff en reviewer ble gitt» (D4) holdes av A5-ens eksakte fire-navns-listing og av parse-fangstens kontroll; den hostede partisjonen holdes av Fase-4es to asserts. Sømmene er altså gatet av uavhengige vitner, ikke bare av sine egne armer. * **M26a og M26b har ULIKE signaturer, og det var ikke gitt.** Ved 40 tegn overlever `PROPOSAL-REVIEW-SENTINEL-9c41ae` (31 tegn) i de armene hvis feedback er kortere enn taket, så T3b og T9 blir grønne igjen mens T1, T8 og T13 — de med lengre feedback — forblir røde. Planens to-lengde-skjerping virker altså etter hensikten her. --- ## 3. K2-omkjøringen — IKKE KJØRT Kriterium 8 (S7b DEL-B-kommandoen over `scratchpad/s7b-syretest/K2-priset-SYNTETISK` pluss `--proposal-review` med et pipet `revise`/`approve`-manus, mot en approve-only-kontroll) gjenstår. Manuset er forberedt: `scratchpad/major2/scripted-replies-major2.json` bærer et FIRE-stegs proposer-manus (to tilnærminger × to forsøk), der annethvert steg oppgir 150 000 i stedet for 200 000, slik at «svaret ble BRUKT» er utfallet og ikke bare at en post finnes. K2-basen er **utracket og finnes kun på denne maskinen**, så kriteriet er verifiserbart her og rapporteres — det asserteres aldri av suiten. --- ## 4. Ærlighets-grenser (så langt) * **`last_ruling`-bæreren er uvitnet** — se § 1. Planens «Critical risk #1» er falsifisert. * **Steg 5 under-rapporterer på en revidert kjøring:** en `revise` bruker ett av de SAMME `max_attempts`-forsøkene en validator-avvisning ville brukt, så en kjøring kan bruke opp forsøkene på ekspert-revisjoner og aldri nå en andre validator-falsifisering. `refinements` under-rapporterer da ved konstruksjon. Uttalt, ikke reparert. * **`coverage`-radene navngir ikke en revise som årsak.** Hver revise tikker den DELTE rundeboka, så en eksperts egne revisjoner kan la halen av en kommisjon stå `not_evaluated`. Detaljen forblir «budget exhausted before this approach was evaluated» — sann, og `coverage` er et non-goal. Terminalen viser `attempts remaining` FØR hvert svar, og review-posten er der årsaken kan leses. * **Checker-gaten (6b) og dimensjons-gaten (6c) overstyrer ETTER at genereringen har returnert.** En `approve` registrert ordrett i artefaktet kan derfor sitte på en kjøring hvis utfall er en checker-kildet `Rejection`. Posten sier hva mennesket SÅ og SVARTE, aldri hva kjøringen konkluderte; at de to er uenige er tilsiktet, og å blande dem er nøyaktig det to-falsifiserer-raden forbyr. * **Feedback-teksten er UBEGRENSET**, som plan-review-feedback — belastet `max_tokens`, som er bunden. At den når en proposer som holder navigatør-verktøyene er uttalt, ikke voktet. * **F4s traceback-asymmetri er urørt:** `PlanReviewInputError` forlater fortsatt CLI-en som en traceback, mens `ProposalReviewInputError` fanges ved navn. Uttalt, ikke fikset her. * **`run_portfolio` tar ingen reviewer**, og fraværet er assertert. * **Ingen levende modell har svart på en review.** Alt her er skriptede stand-ins (structured-output-grensens klasse).