# P16 — stressrunde 1: the good, the bad and the ugly Ordre `20260914T091846Z-2971522127-from-.claude`, økt 120, 14.09.2026. Fire betalte kjøringer mot n100-2023 / n500-2024 / n200-2024 / r761-2025, dømt av en ny deterministisk dommer. Alle tall her er MÅLT i denne økten mot disk og mot artefaktene kjøringene etterlot, ikke lest ut av en tidligere rapport. **Kortversjonen.** Rammeverket kjører ende-til-ende mot fire ekte kunnskapsbaser og navigerer dem riktig. Ingen av de fire kjøringene traff et eneste av de 26 fasit-konseptene. Tre av fire avviste alt som ugrunnet; den fjerde **validerte falsifiseringsarmen** — tilnærmingen som ved konstruksjon ikke kan forankres — og gjorde det ved å bruke basens eget navn som kostkode. --- ## 1. Hva som ble bygget først (DEL A) `src/portfolio_optimiser/stress.py` — `score_context_set(context_dir, outbox_dir, run_id, bundle_dir)`. Den leser KUN artefakter som alt finnes: `{run_id}[-{approach}]-proposal.json`, `-outcome.json` og `{run_id}-debate.json`, pluss settets `mandate.json` / `fasit.json` / `bundle.txt`. Ingen kjøring fikk et nytt felt. ### 1.1 Ordrens (a)-definisjon var vakuøs, og det ble målt før noe ble bygget på den Ordren definerer *grounded* som «en `must_cite`-sti er ÅPNET **eller** SITERT». På S2c-stien stempler `run_project` `citations = bundle_citations(bundle)` — **én sitering per konseptfil**. | Base | Kontekstfiler | Siteringer i stempelet | Fasit-stier «sitert» før noe modellkall | |---|---|---|---| | n100-2023 | 446 | 446 | **6 av 6** | En dommer som fulgte ordren ordrett ville altså vært en gate som bare kan bli grønn — repoets egen vakuøs-gate-klasse, inne i gaten som ble bygget for å fange den. Derfor: en **sitering** grunner kun når siteringslista er SMALERE enn basen (et erklært pre-pass-kutt). Begge halvdeler rapporteres uansett (`opened` / `cited` / `citation_scope`), så avviket er uttalt, aldri stille. **(b′) ble sjekket for SAMME vakuitet og var ren nok til at ordren står:** siteringenes `snippet` er konsept-BODYER mens `ref`/`title` bor i FRONTMATTER — målt inneholder **0 av 446** n100-bodyer strengen `Krav 4.1.2—1`. Se likevel § 6.2: målingen på r761 viser at snippet-armen er svak for KORTE referanser, og `named_in_measure` er den halvdelen som tåler vekt. ### 1.2 Falsifiseringsarmen fikk en kjørbar form (A2) `po` er ikke et oppslagsverktøy (D-1), så et «ubesvarbart spørsmål» hadde ingen kjørbar form: ingen kjøresti konsumerte `fasit.json`s `unanswerable`-rader. Samme faktum rir nå en **fjerde bestilt tilnærming** per sett (`a4-…`) hvis kostlinje basen ikke bærer grunnlaget for, og `fasit.json` bærer `must_refuse` (`approach_id` / `anchors` / `rationale`) **i stedet for** `unanswerable` — én form, aldri to kopier av ett faktum. Spørsmålene overlever i `rationale`, som ingenting nøkler på. Regel U er URØRT og dens kjent-positiv er fortsatt rød. ### 1.3 Mutasjonstabell (DEL A) Alle elleve røde på sin egen arm, grønn kontroll **1663 passed / 5 skipped**, golden `demo-transcript.stdout` BYTE-UENDRET (`shasum -a 1` av INNHOLDET = `ea8c534773acdbe41ae68f2c55724d69aaf8be4f` — ikke git-blob-id-en). | # | Mutasjon | Røde | Arm | |---|---|---|---| | M1 | helbase-siteringer grunner igjen | 2 | (b) + (a) | | M2 | en åpnet sti grunner ikke | 4 | (a), (d), (f), (k) | | M3 | (b′) dropper snippet-armen | 1 | (e) | | M4 | hallusinerte siteringsfiler ignoreres | 1 | (f) | | M5 | hallusinerte koder ignoreres | 1 | (f) | | M6 | gjettet lesesti forgifter ikke `ferdig` | 1 | (f) | | M7 | tom utboks gir rent resultat | 1 | (h) | | M8 | `not_evaluated`-rader utelates | 1 | (j) | | M9 | kode-lekkasjearmen i `must_refuse` droppes | 1 | (g) | | M10 | en tom base tolereres | 1 | (i) | | M11 | Regel U-ens kjent-positiv (P14 M3) | 1 | context-sets | --- ## 2. Gratis-trinnet betalte seg tre ganger (DEL B2) ### FUNN 1 — den dokumenterte kommandoen kunne ikke kjøres `STATE.md`, `docs/2026-09-12-p14-kontekstsett.md § 4.1` og ordren publiserer alle den samme kommandoen, som ender `--max-rounds 8 --max-tokens 120000`. **MÅLT: `run.py` tok ingen av dem.** Alle fire `--live-dry-run` nektet med `unrecognized arguments`. Verre: `main()` sendte **aldri** `max_rounds`/`max_tokens` videre til `run_project`, så HVER CLI-kjøring noensinne var stille bundet til `_DEFAULT_MAX_ROUNDS=3` / `_DEFAULT_MAX_TOKENS=100_000`, uten noen operatørflate for å heve eller senke taket på noe man betalte for. Tre flater beskrev en dør som ikke fantes. **Fikset før betaling** (B2s egen instruks), commit `5f94c92`: begge flagg DEFAULTER til nøyaktig de historiske verdiene (utvidelse, aldri bryting), wiret til BEGGE dispatcher (`run_project` OG `run_portfolio` — `main()` droppet dem der også) og nektet ved navn i report-modus. Seks armer, alle røde før fiksen; fire mutasjoner. ### FUNN 2 — `--docs-dir` er påkrevd også når `--bundle-dir` er oppgitt `run.py:2953` nekter enkeltprosjekt-modus uten `--docs-dir`, selv om `docs_dir` er ubrukt på bundle-stien. Den dokumenterte kommandoen ville nektet av DEN grunnen også. READMEs egen form (`--docs-dir --bundle-dir `) virker. **Målt, rapportert, IKKE fikset.** ### FUNN 3 — annonseringen løy i det øyeblikket flagget fantes `announce` leste `_DEFAULT_*` direkte. Det var korrekt kun så lenge `main()` ikke kunne gjøre annet. Målt på den første gratis-turen etter at flaggene landet: samme stdout sa `Stops at: 3 rounds / 100000 tokens` **to linjer over** `max_rounds=8, max_tokens=120000`. Annonseringen er det ENE som printes før første betalte kall, og hele jobben dens er å si hva kjøringen vil gjøre — Fase-3-klassen, innført av nettopp det flagget som annonseres. **Fikset** (commit `a61a3cc`); M16 (les konstantene igjen) → 1 rød, den armen alene. ### Prediksjonen fra gratis-trinnet, notert FØR betaling Alle fire dry-runs stoppet rent (rc 0) og sa det samme: > `Cost baseline: NONE in the bundle — this run is un-anchored` > `Grounding offer: N distinct identifier(s) and **0 cost line(s)** … every candidate it invents > will be refused as ungrounded` | Sett | Identifikatorer | Kostlinjer | Tegn | |---|---|---|---| | gate-nordvik (n100) | 435 | **0** | 437 129 | | tunnel-hauglia (n500) | 272 | **0** | 389 103 | | fv412 (n200) | 982 | **0** | 1 441 501 | | kontrakt-sorasen (r761) | **3** | **0** | 6 561 594 | Predikert utfall: 0 validerte. Se § 4 for hva som faktisk skjedde. --- ## 3. Kjøringene (DEL B3) Parametrene ble endret underveis, hver gang med årsaken navngitt FØR ny kjøring (B3s regel). | # | Sett | Base | Runder | Tak | rc | Observert | Veggtid | Maks RSS | |---|---|---|---|---|---|---|---|---| | 1 | gate-nordvik | n100 | 8 | 120 000 | **1** | 150 999 | 24,7 s | — | | 2 | gate-nordvik | n100 | 8 | 500 000 | **1** | 530 881 | 114,0 s | 149 MB | | 3 | gate-nordvik | n100 | **3** | 600 000 | 0 | 509 310 | 140,1 s | 149 MB | | 4 | tunnel-hauglia | n500 | 3 | 600 000 | 0 | 255 418 | 73,5 s | 144 MB | | 5 | fv412 | n200 | 3 | 600 000 | **1** | 604 159 | 121,1 s | 168 MB | | 6 | fv412 | n200 | **2** | 900 000 | 0 | 523 633 | 176,0 s | 171 MB | | 7 | kontrakt-sorasen | r761 | 3 | 900 000 | 0 | 104 905 | 218,7 s | **298 MB** | Totalt betalt: **2 679 305 tokens** over sju kjøringer, hvorav tre døde på taket. `gpt-4-1-mini`, profile `azure`, `PACE_SECONDS=2`, 0× 429. **Kostnad — IKKE VERIFISERT.** Ingen faktura er lest. Med listepris for `gpt-4.1-mini` ($0,40/M inn, $1,60/M ut) og et antatt 90/10-forhold inn/ut lander 2,68 M tokens på ≈ **USD 1,4 ≈ NOK 15**. Inn/ut-forholdet er ikke målt — `token_usage` er en totalsum — så tallet er et anslag med en uttalt antakelse, ikke en måling. ### R761 mot P13s referanse P13 målte NAVIGASJON av r761 til **7,1 s / 131 MB** (`docs/2026-09-12-p13-okf-pin-r761.md`). En hel LEVENDE kjøring koster **218,7 s / 298 MB** — 31× tiden og 2,3× minnet. De to måler ikke det samme (navigasjon mot navigasjon + fire debattrunder + generering + validering), og sammenligningen sier derfor bare at navigasjonen er en liten del av begge. --- ## 4. Dommen (DEL B4) `python -m portfolio_optimiser.stress contexts/ --outbox-dir … --run-id …`, fire `*-verdict.json` skrevet. | Sett | (a) grunnet | (b′) navngitt | (c) hallusinasjoner | a4 / `must_refuse` | ferdig | |---|---|---|---|---|---| | gate-nordvik (n100) | **0 / 4** | 0 / 4 | 7 | **PASS** | nei | | tunnel-hauglia (n500) | **0 / 4** | 0 / 4 | 5 | **PASS** | nei | | fv412 (n200) | **0 / 4** | 0 / 4 | 6 | **PASS** | nei | | kontrakt-sorasen (r761) | **0 / 4** | 3 / 4 | 9 | **FAIL** | nei | Nevnere, alltid: tool_calls 18 / 16 / 12 / 18 · siteringer 1 784 / 810 / 2 266 / 11 024 · approach-rader 4 / 3 / 2 / 4 · konsepter i basen 446 / 270 / 1 133 / 2 756. `validated` totalt: **2 av 20 rader**, begge i r761 — a4 (falsifiseringsarmen) og own-proposal. --- ## 5. THE GOOD 1. **Stigen virker, og den virker på ekte korpus.** Alle fire kjøringer gikk `list_bundles → read_bundle → read_dir → read_file` uten å bli instruert i det. r761 gikk rett ned i `R761/6` → `R761/6/65` — altså brukte den hierarkiet S7a-3 bygde, og betalte **104 905** tokens for den største basen, mindre enn n100 brukte på den minste. 2. **Falsifisererne biter.** 18 av 20 rader ble avvist, og alle med P7s stadium 0b, med identifikatoren navngitt i klartekst. Hver eneste avvisningsgrunn var sann. 3. **P8s forankringstilbud predikerte utfallet gratis.** «0 kostlinjer» ble sagt før betaling og holdt i alle fire kjøringer. 4. **Artefaktene bar beviset.** Dommeren trengte ingen ny instrumentering: `debate.json`, `proposal.json` og `outcome.json` svarte på alt — også for de tre kjøringene som døde på taket, der `debate.json` og `runconfig.json` fortsatt lå der. 5. **Alle fire dry-runs stoppet rent** før første modellkall, og gjorde det etter at flaggfunnet var fikset. --- ## 6. THE BAD ### 6.1 Ikke ett fasit-konsept ble åpnet — 0 av 26, i 24 `read_file`-kall | Sett | `read_file` | distinkte | fasit ønsket | overlapp | |---|---|---|---|---| | gate-nordvik | 10 | 9 | 6 | **0** | | tunnel-hauglia | 8 | 5 | 8 | **0** | | fv412 | 4 | 4 | 6 | **0** | | kontrakt-sorasen | 10 | 6 | 6 | **0** | Det er hovedresultatet av stressrunden. Navigasjonen fungerer mekanisk og treffer ikke faglig. Grunnen er lesbar i listingen: konseptfilene heter `id-.md`, og `read_dir` gir `name`, `type`, `title`, `chars`. På n100 må modellen velge blant **446** slike titler i ett svar. **LØSNING (navngitt, ikke bygget):** gi `directory_listing` en valgfri, *bundet* filtrering på `req_number`/`title`-delstreng — ett nytt argument på `read_dir`, samme rung, samme gate. Anslag: én økt, ~6 armer, ingen ny flate i `run.py`. Alternativ b: la `read_bundle` returnere basens egen `index.md`-body når den er prosa (n-basene har ingen), som ikke hjelper her — derfor a. ### 6.2 (b′)s snippet-arm er svak for KORTE referanser — et funn om min egen dommer r761 ga `named = 3 / 4`, men `named_in_measure` var sann for kun **1** av dem. De to andre ble båret av snippet-armen, og på r761 er referansene prosessnumre som `12.1` — som forekommer i mange bodyer i et helbase-sitert stempel. Målingen på n100 (0 av 446 bodyer bærer `Krav 4.1.2—1`) generaliserer altså ikke. **LØSNING:** la snippet-armen kun telle når `citation_scope == "narrowed"`, nøyaktig som (a). Anslag: én linje + to armer. Ikke bygget i denne økten — dette er PMs beslutning, ikke min, fordi det strammer ordrens egen definisjon en gang til. ### 6.3 En gjettet sti gir modellen en ugjennomsiktig feil Målt 12 gjettede `read_file`-stier over de fire kjøringene (3 / 2 / 3 / 4). En sti som ikke finnes reiser `FileNotFoundError`, som funn-99 eksplisitt holder **utenfor** `_RETURNABLE_REFUSALS`, så modellen får MAFs `"Error: Function failed."` uten grunn. På n200 fyrte MAFs egen `Maximum consecutive function call errors reached (3). Stopping further function calls for this request.` — altså ble verktøybruken avskåret midt i en forespørsel. **Korrigering av min egen første diagnose:** jeg antok først at dette drev budsjettdøden. Det gjorde det ikke — mønsteret er 2× på *hvert* kall (to agenter, samme vandring), ikke en retry-loop. **LØSNING:** utvid funn-99s returnerte-nekt-form til `read_file` på en sti som ikke finnes (`REFUSED (BundlePathNotFound): …`), og skriv om den eksisterende armen `test_a_nonexistent_sibling_is_still_an_os_error`. Anslag: én økt, ~8 armer, og den eksisterende gaten må skrives om, ikke svekkes. --- ## 7. THE UGLY ### 7.1 Falsifiseringsarmen ble VALIDERT på r761 — og basens eget navn var kostkoden ``` a4-indeksregulering VALIDATED 250000 NOK measure: "Kutt ved gunstigere indeksregulering av kontraktssummen" affected_items: [{"code": "R761", "quantity": 1.0, "unit_cost": 10000000.0}] checker_verdict: approve p10/p50/p90: 2 876 396 / 3 004 495 / 3 126 462 ``` a4 er ved konstruksjon ugrunnbar: rule U bekrefter at `indeksregulering`, `nåverdi`, `kostnadsestimat`, `markedspris` og `prisstigning` alle er FRAVÆRENDE fra r761. Likevel passerte den: * **den deterministiske validatoren** — stadium 0 var hoppet over (uforankret base), * **P7s stadium 0b** — fordi regelen er `code in grounding`, en eksakt DELSTRENG uten mønster, og `"R761"` forekommer overalt i et 6,5 MB R761-korpus, * **checkeren** — `approve`. Modellen fant altså ikke på en kostkode som *lignet* på en ekte: den brukte **basens navn**. `unit_cost` 10 000 000 er ren oppfinnelse, `p10 ≈ p50 ≈ p90` fordi `assumptions` er tom (degenerert Monte Carlo), og hele kjeden rapporterte `validated`. P7-raden uttaler selv at regelen «har intet mønster» og at «rene tall er den ene inerte klassen». Denne målingen legger til en andre inert klasse: **korte, allestedsnærværende tokens** — og den er verre, fordi et rent tall ikke *ser* ut som en kostkode mens `R761` gjør det. **LØSNING (navngitt, ikke bygget), rangert:** * **(a) minstelengde + treffnevner.** Krev at en identifikator er ≥ N tegn OG at den forekommer i færre enn M distinkte konsepter — et token som står i 2 756 av 2 756 dokumenter identifiserer ingenting. Anslag: én økt, ~10 armer, ingen ny flate. Nevneren finnes alt i `delivered`. * **(b) forankre mot det kjøringen ÅPNET, ikke mot hele korpuset.** `debate_tool_calls` er alt kaller-eid og skrevet; en identifikator som kun står i dokumenter kjøringen aldri åpnet er ikke noe forslaget «bygde på». Anslag: én økt, ~8 armer. Strammere enn (a), men endrer hva stadium 0b betyr — PMs beslutning. * **(c) `--require-cost-baseline` som default for mandatkjøringer mot uforankrede baser.** Flagget finnes (F4) og ville nektet alle sju kjøringene før første kall. Det løser ikke 0b, men gjør «validated» umulig å utstede uforankret. Anslag: en partisjons-rad + en beslutning. Ingen av dem er bygget her — ordren forbyr det eksplisitt. ### 7.2 Én katalogvisning er opptil 113× taket S7a-3 satte, og den rir hver tur | Base | Konsepter | Nivåer | Rot | Verste listing | ~tokens | × 1 500-tegns-taket | |---|---|---|---|---|---|---| | n100-2023 | 446 | 4 | 118 ch | `krav/N100` 69 250 ch | 23 083 | **46×** | | n500-2024 | 270 | 4 | 118 ch | `krav/N500` 39 853 ch | 13 284 | 27× | | n200-2024 | 1 133 | 4 | 119 ch | `krav/N200` 169 974 ch | **56 658** | **113×** | | r761-2025 | 2 756 | 2 758 | 171 ch | `R761` 110 874 ch | 36 958 | 74× | S7a-3 binder 1 500 tegn per listing over **de basene gaten kan se** (de tre eksempelbasene), og uttaler selv at K2s verste nivå er 6 073 tegn. De fire vegnormalbasene er 6,5–28× dét igjen, fordi hierarkiet er FLATT: `krav/ → krav/N100/ → 446 filer`. Rung 2 hjelper ikke når korpuset er to nivåer dypt med hundrevis av blader. Konsekvensen er ikke teoretisk: **tre av sju kjøringer døde på tokentaket**, og n100 — den minste basen — trengte over 500 000 tokens ved 8 runder. Den dypt hierarkiske basen (r761) var den billigste. **LØSNING (navngitt, ikke bygget):** paginer `read_dir` — `offset`/`limit` med et bundet vindu og et `total`-felt, så listingen koster O(vindu) og modellen kan be om mer. Det er S7a-3s egen form ett hakk videre, og annonsering av avkorting er alt løst der (`index_truncated`). Anslag: én økt, ~8 armer, gaten binder vinduet i TESTEN som i dag. Sekundært: la `okf build` i vegnormal-okf sub-dele `krav/N100` etter kapittel — men det er en produsent-endring i et annet repo, altså en coord-sak, ikke vår. ### 7.3 Ordrens eget budsjett var 4,4× for lite, og ingen visste det `--max-tokens 120000` er publisert tre steder. Den minste basen brukte **509 310**. At ingen visste det er selve funnet: flaggene fantes ikke, så tallet hadde aldri vært brukt av noe. --- ## 8. Ærlighetsgrenser (uttalt) * **Én kjøring per sett. Ingen varians er målt.** En andre kjøring av samme sett kan navigere annerledes; ingenting her sier hvor stabilt utfallet er. * **a4-armen beviser at ingen validert rad hviler på den — ikke at modellen forsto hvorfor.** Manuell lesning av de fire a4-utfallene (merket MANUELT): i **n100** skrev modellen ekspertens etikett ordrett som `measure` og fant på koden `gangfelt_opphoyd` med `unit_cost` 150 000 × 10 — ingen setning om at basen mangler grunnlag; 0b avviste den. I **n500** og **n200** ble a4 aldri evaluert (budsjettet var brukt opp før raden), så det finnes ingen tekst å lese. I **r761** skrev modellen igjen etiketten ordrett og fant på `R761`. **Ingen av de to a4-radene som faktisk ble evaluert uttalte at basen ikke bærer grunnlaget.** Det er en annen og svakere observasjon enn «armen bestod» — og for to av fire sett er selv den observasjonen ikke gjort. * **Parametrene varierer mellom settene** (3/600k, 3/600k, 2/900k, 3/900k). n200 kjørte på 2 runder mot de andres 3. Tallene i § 4 er derfor ikke strengt sammenlignbare på tvers. * **Kostnaden er et anslag fra listepris,** ikke lest fra faktura, og inn/ut-forholdet er antatt. * **Prosjektene er oppdiktet.** Hvert `fasit.json` sier i sitt eget `honesty`-felt hva som er konstruert: navn, lengder, ÅDT og alle beløp, samt a4 og dens kostkode. Kravene i `must_cite` er lest ordrett ut av basenes egen frontmatter. * **`` kunne ikke leses av basen.** Ordren ba om «det basens egen IR-projeksjon erklærer». MÅLT: ingen av de fire basene har `validator-input.json`, så `load_optional_ir_projection` returnerer `None` (S7b søm 1) og id-en er kaller-oppgitt. Settets eget navn ble brukt. * **Dommeren leser HVA kjøringen åpnet og siterte, aldri om modellen FORSTO det.** --- ## 9. Verifiseringslogg | Påstand | Hvordan målt | |---|---| | 446/446 siteringer, 6/6 fasit-stier sitert før modellkall | `bundle_citations` mot navigert n100 | | 0 av 446 n100-bodyer bærer `Krav 4.1.2—1` | telling over `bundle.context_files` | | `--max-rounds`/`--max-tokens` fantes ikke | `run.py --help` + fire nektede dry-runs | | `main()` sendte dem aldri videre | lesing av begge `run_project`-kallsteder + `run_portfolio`-kallstedet | | annonseringen sa 3/100000 mot 8/120000 | samme stdout, gratis dry-run | | listing-størrelser | `okf.directory_listing` over hvert nivå i hver base | | token/veggtid/RSS | `/usr/bin/time -l` + `provenance.token_usage` i artefaktene | | 0 overlapp fasit vs åpnede | `debate.json` `read_file`-stier ∩ `fasit.must_cite` | | a4 validert med `code: R761` | `*-a4-indeksregulering-proposal.json` + `-outcome.json` | | rule U holder for alle a4-anchors | `tests/test_context_sets_loadbearing.py::test_c_rule_u…`, grønn | | suite / golden | `uv run pytest -q` = 1670/5 · `shasum -a 1` = `ea8c534…` |