portfolio-optimiser/docs/2026-09-04-syretest-s7b-k2.md
Kjell Tore Guttormsen 0b8e727a84 docs(s7b): syretesten paa K2 - maaledokumentet med de fire tallene og tretten roede
DEL B av ordre 20260903T204605Z-215167684-from-.claude, pluss maalingen bak DEL A og
DEL C som landet i b75387c.

HOVEDRESULTATET: hele aatte-stegs-loekka kjoerte paa et INGESTERT korpus uten
validator-input.json - utforskning -> mandat -> generering -> deterministisk validator
-> dom. Foer soem 1 stoppet samme kommando paa FileNotFoundError foer foerste modellkall.

De fire tallene ordren ber om:
 (1) Validert besparelse: 850 000 NOK av et prisskjema paa 3 852 500 (22,1 %), fordelt
     paa tre av fem tilnaerminger.
 (2) Validatoren feller 2 av 5, paa TO ULIKE stages: a2 paa stage 4 (P90 feasible
     612 000) og a5 paa stage 5 (METHOD_CAPS 112 500). a5 baerer SAMME kostlinje og
     SAMME krav som a3 og skiller seg bare ved at labelen ordrett er et REGISTRERT
     metodenavn - saa metode-cap-grensen fra forslag-fra-mandat-dokumentets par 2.1 er
     naa konkret og ikke bare uttalt.
 (3) Tokenbruk per fase: utforskning 18 355 (0,9 %), debatt+generering 1 947 342
     (99,1 %), deterministisk dom 0. DET DOMINERENDE FUNNET: MAJOR-3/S7a-3 gjorde
     utforskningen billig, men DEBATTEN stapper fortsatt hele basen inn i hver prompt -
     bundle_context paa K2 er 648 962 o200k-tokens og rir i TRE kopier. Formen var kjent
     (MAJOR-3-raden sier debattens 3x er urort); det NYE er nevneren paa et ekte korpus.
     Ingen terskel settes - det er operatoerens.
 (4) Hvilke konsepter navigatoeren aapnet: fire verktoeykall med path, list_bundles ->
     read_bundle -> read_dir -> read_file paa ETT dokument. S7a-3 pkt. 3s path-felt er
     dét som gjoer sporet lesbart over 630 konsepter i det hele tatt.

ET PREMISS FELT FOER NOE BLE BYGGET PAA DET: ordren sier K2s prisskjema er upriset
(0/28). MAALT er det verre - K2 som levert har NULL kandidat-tabeller, fordi
prissammenstillingen renderes som en pandoc SIMPLE table med EN kolonne-overskrift og
derfor aldri navngir rollene Postnr/Mengde/Enhetspris. Monteringen av MAJOR-4s
syntetiske skjema legger dermed til noeyaktig en tabell, og "mer enn en"-nekten er ikke
i veien. PRISENE ER SYNTETISKE - sagt i dokumentets foerste blokk.

INSTRUMENTET ER VALIDERT MOT EN KJENT POSITIV foer bruk: rotnivaa-listingen paa levert
K2 maales til 3 954 tegn / 1 495 o200k-tokens over 629 konsepter, som reproduserer
S7a-3s publiserte tall eksakt.

MAALINGEN: 13 mutasjoner, ALLE ROEDE mot HELE suiten, groenn kontroll 1290/5 (fra
1275/5 - supersett, 0 fjernet), golden demo-transcript.stdout BYTE-UENDRET
(shasum -a 1 av INNHOLDET = ea8c534773acdbe41ae68f2c55724d69aaf8be4f). To mutasjoner har
vitner UTENFOR den nye fila: M2 roedner to tester eldre enn dette arbeidet, M4 roedner
fire eksisterende multibase-/bundle-id-armer - noeyaktig retningen hovedarmen
strukturelt ikke kan se. Ingen mutasjon forble groenn.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 09:04:51 +02:00

288 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# S7b — søm 1 og syretesten på K2
**Dato:** 2026-09-04 · **Ordre:** `20260903T204605Z-215167684-from-.claude` (DEL A, B, C)
**Base:** `~/corpora/okf-telling-20260829/K2-bundle-20260903/` (erklært id `k2-trinn1-20260903`)
> **⚠️ PRISENE ER SYNTETISKE.** K2s eget prisskjema er upriset — dette er et anbud FØR tildeling.
> Hver kroneverdi i dette dokumentet stammer fra MAJOR-4s syntetiske prisskjema-fikstur
> (`tests/fixtures/k2-prisskjema-SYNTETISK/`), montert inn i en arbeidskopi av basen. Ingen av
> tallene er priser noen har tilbudt for Stange skole. Det som måles her er at **maskineriet**
> kommer helt fram — fra et ingestert korpus til en dom med et beløp — ikke hva beløpet er.
---
## 0. Sammendrag
| spørsmål ordren stiller | svar |
|---|---|
| Validert besparelse per kandidat | § 3.2 |
| Hvor mange kandidater validatoren feller, og på hvilket stage | § 3.3 |
| Tokenbruk per fase | § 3.4 |
| Hvilke konsepter navigatøren åpnet | § 3.5 |
Ingen terskel settes her — det er operatørens.
---
## 1. DEL A — søm 1, og de to premissene som ble felt
### 1.1 Formen
`okf.load_optional_ir_projection` ved siden av den fail-faste `load_ir_projection`, nøyaktig
`load_cost_baseline`/`load_optional_cost_baseline`-paret. Et **par**, ikke et `required=`-flagg:
PM-tillegg 5 målte hva en uøvet parameter koster (alle elleve `evidence_for`-kallsteder brukte
defaulten, så den andre grenen råtnet til den reiste), og et flagg ville dessuten gjort usanne de
docstringene på tvers av `hitl`/`ledger`/`verdicts`/`contracts` som siterer `load_ir_projection`
som **den** fail-faste presedensen.
**Toleransen stopper ved fravær.** En projeksjon som FINNES men er malformed reiser fortsatt, og
en `name` som rømmer basen reiser fortsatt. Å lese en korrupt projeksjon som «ingen projeksjon»
ville gitt en unøklet kjøring i forkledning — S4.0-radens egen regel.
### 1.2 Tre kallsteder, tre ULIKE stillinger
Nevneren er skrevet ned i `docs/2026-09-03-forslag-fra-mandat.md § 1.1`, og linjenumrene der er
premisser som ble verifisert mot kilden før de ble handlet på.
| kallsted | stilling ved fravær | hva som fortsatt nekter |
|---|---|---|
| `run._project_from_bundle` | hopper over en fail-fast som ikke har noe å sjekke mot | en projeksjon som FINNES og navngir et ANNET prosjekt |
| `run.run_mandate_across_bundles` | ruter på basens ERKLÆRTE `bundle_id` (S7a-3) | — (fila vinner når den finnes) |
| `verdicts.bundle_candidate_features` | Steg-1-folden hopper over, og SIER hvor mange dommer som falt ut | `seed_store_from_bundle`: en dom uten egen strukturell nøkkel NEKTES ved navn |
**Presedensen i dispatcheren bærer i BEGGE retninger.** Erklæring-først ville re-adressert hver
eksisterende base der `project_id``bundle_id` — fila er dét de basene alltid har vært rutet
etter. Fil-bare var nekten sømmen fjerner: et ingestert korpus bærer ingen projeksjon, så det
kunne ikke rutes i det hele tatt.
**De to konsumentene av den tredje sømmen svarer ULIKT, og det er designet.** Folden hopper over
fordi fraværet av en kandidat er et faktum om basen; `seed_store_from_bundle` nekter fordi å mynte
en nøkkel for en dom som erklærer ingen er nøyaktig defekten S3.2 lukker (dommen ville blitt
festet til en kandidat den ikke handler om). Validering, ALDRI reparasjon.
### 1.3 Synligheten: et ANTALL, og bæreren er målt
`RunResult.unkeyed_verdicts` teller de tidligere ekspertdommene som lå i storen men IKKE kunne
foldes inn i hypotese-prompten. `run.unkeyed_verdicts_notice` er ENESTE renderer og returnerer
`None` ved null — omisjon, aldri tom rad.
* **Et ANTALL, ikke et flagg.** «Folden skjedde ikke» og «to dommer nådde aldri modellen» er ulike
operative fakta — `BudgetExceeded`-kø-(y)-regelen ett nivå ned.
* **Null er et ærlig POSITIVT utsagn** («hver dom storen holdt var nøklbar»), så feltet defaulter,
som `skipped_links`' tomme tuppel — motsatt av `cost_baseline_anchored`, der begge defaults ville
løyet.
* **Bæreren er MÅLT, ikke valgt.** `DryRunReport` kan ikke bære den: dry-run-kuttet returnerer
OVER folden, så et felt der kunne bare rapportert null — ulikt `cost_baseline_anchored` og
`skipped_links`, som begge oppløses over kuttet. `ProvenanceStamp` heller ikke: stempelet
beskriver gaten som dømte ÉN kandidat, mens dette avgjøres én gang per kjøring før noen kandidat
finnes (`skipped_links`' egen begrunnelse).
**Ærlighets-grenser, uttalt.** (1) Feltet når ikke utboksen — `write_proposal` dumper stempelet, og
dette er ikke på stempelet; det er samme grense `skipped_links` alt har. (2) Portefølje-armen er
BEVISST ikke wiret: folden er gatet på `bundle_dir`, som intet referanse-prosjekt setter, så en
utskrift der ville vært død kode. Det er `bundle_id_notice`s avgjørelse, ikke
`cost_baseline_notice`s (som ble wiret defensivt og drevet fra en crafted `PortfolioResult`) —
asymmetrien står her fordi stillhet om den er det eneste gale svaret.
### 1.4 To premisser felt før noe ble bygget på dem
**(a) Prosjektnavnet var et ikke-spørsmål.** Den arkiverte selv-ordren flagget fallbacken for
`Project.name` som «en REELL beslutning». MÅLT: `SavingsProposal` har fem felt — `project_id`,
`measure`, `affected_items`, `claimed_saving_nok`, `assumptions` — og ingen av dem er et navn.
Projeksjonen har **aldri** vært en navnekilde. `Project.name` kommer fra `type: project`-konseptets
`title` med den forespurte id-en som siste utvei, uendret før og etter.
**(b) DEL B kan ikke være ÉN kommando.** Ordren skriver kjeden
`--explore → --mandate → --proposals-from-mandate → validator → --revise`. Målt i kilden:
`--explore` NEKTES sammen med `--mandate` (to kilder til ett mandat), `--proposals-from-mandate` er
en TERMINAL modus som settler og returnerer før enhver kjøre-dispatch, og det finnes **ingen
`--revise`-flagg** i det hele tatt. Kjeden er derfor tre faser (§ 3), og `--revise` leses som
plan-review-døra `--plan-review` åpner (`approve` / `revise <hva>`) — sagt her som en tolkning,
ikke som en oppdagelse.
---
## 2. DEL C — sidefunnet
`--mandate` sto IKKE i `report_forbidden`-partisjonen, så `--report --ledger X --mandate Y`
droppet kommisjonen i **stillhet**: rapporten ble skrevet, kommisjonen hverken annonsert eller
settlet, exit 0. Report-modus returnerer over hver dispatch, så en utelatelse der er et stille
DROPP og ikke en nekt — F4-klassen. Flagget er nå en rad, og testarmen kjører mot en argv
report-modus ellers ville AKSEPTERT (gyldig `--ledger`, pluss en kontroll som beviser rc 0 uten
flagget), så rc 1 er mutantens motsatte utfall.
---
## 3. DEL B — syretesten på K2
### 3.1 Oppsettet, og hva som er syntetisk
Basen er KOPIERT ut av `~/corpora` (aldri mutert der), og MAJOR-4s syntetisk prisede
prisskjema er montert inn i K2s egen `del-ii-bilag-7-prisskjema/`-katalog, kryss-lenket fra den
katalogens `index.md``navigate_bundle` følger lenker, aldri katalog-enumerering, så en umontert
fil ville vært usynlig.
**Et premiss ble målt før noe ble bygget på det.** Ordren sier K2s prisskjema er upriset (0/28).
Målt er det verre enn som så: K2 som levert har **null** kandidat-tabeller —
`prissammenstilling-sheet-1.md` renderes som en pandoc SIMPLE table med ÉN kolonne-overskrift
(`Prisskjema`), så den navngir ikke rollene `Postnr`/`Mengde`/`Enhetspris` i det hele tatt. Det
betyr at monteringen legger til nøyaktig én kandidat-tabell, og at
`derive_cost_baseline`s «mer enn én tabell»-nekt ikke er i veien.
Basen etter montering: **630 konseptfiler, 0 ufulgte lenker**, erklært id `k2-trinn1-20260903`
mot monteringsnavnet `K2-priset-SYNTETISK` — så S7a-3-slakken øves samtidig, og kjøringen sier det
(`bundle_id_notice` fyrer).
Det avledede prisskjemaet (SYNTETISKE priser):
| kode | mengde | enhetspris | sum |
|---|---|---|---|
| 21.1 Grunnarbeider | 1 250 | 850 | 1 062 500 |
| 24.2 Bærekonstruksjon stål | 48 000 | 42,5 | 2 040 000 |
| 36.1 Ventilasjonsaggregat | 4 | 187 500 | 750 000 |
| **sum** | | | **3 852 500** |
### 3.2 At løkka kommer HELT fram — hovedresultatet
Hele åtte-stegs-løkka kjørte på et ingestert korpus UTEN `validator-input.json`:
utforskning → mandat → generering → deterministisk validator → dom. Det er nøyaktig nekten søm 1
fjerner; før i dag stoppet den samme kommandoen på `FileNotFoundError` før første modellkall.
```
uv run portfolio-optimiser K2 \
--docs-dir scratchpad/s7b-syretest/K2-priset-SYNTETISK \
--bundle-dir scratchpad/s7b-syretest/K2-priset-SYNTETISK \
--derive-cost-baseline \
--explore "Finn kostnadsbesparelser i Stange skole-anbudet" \
--explore-config scratchpad/s7b-syretest/explore-config.json \
--scripted-replies scratchpad/s7b-syretest/scripted-replies.json \
--outbox-dir scratchpad/s7b-syretest/outbox --run-id syretest-s7b
```
`K2: ValidatedProposal (no expert verdict given; verdict key=be8535e204cdc4c6)`, mandatet settlet
2 av 2 tilnærminger validert, beste 200 000 NOK.
### 3.3 Validert besparelse per kandidat, og hvem validatoren feller
Den deterministiske døra, med en kommisjon på fem tilnærminger — **null modellkall**
(`evaluate_mandate_candidates` er SYNC, så det er en egenskap ved typen, ikke et løfte kroppen må
holde):
```
uv run portfolio-optimiser K2 \
--docs-dir scratchpad/s7b-syretest/K2-priset-SYNTETISK \
--bundle-dir scratchpad/s7b-syretest/K2-priset-SYNTETISK \
--derive-cost-baseline --proposals-from-mandate \
--mandate scratchpad/s7b-syretest/kommisjon.json
```
| id | tiltak | kostlinjer | krav | utfall | stage |
|---|---|---|---|---|---|
| a1 | Redusert sprengningsvolum i sone A | 21.1 | 200 000 | **VALIDERT** | — |
| a2 | Slankere stålprofiler | 24.2 | 900 000 | FELT | **stage 4** — P90 feasible 612 000 |
| a3 | Færre ventilasjonsaggregater | 36.1 | 150 000 | **VALIDERT** | — |
| a4 | Samordnet rigg | 21.1 + 24.2 | 500 000 | **VALIDERT** | — |
| a5 | `energy_efficiency` (samme linje som a3) | 36.1 | 150 000 | FELT | **stage 5** — metode-cap 112 500 |
**Validert i alt: 850 000 NOK** av et prisskjema på 3 852 500 NOK (22,1 %). **2 av 5 felt, på TO
ULIKE stages.**
a5 er ikke pynt: den bærer SAMME kostlinje og SAMME krav som a3, og skiller seg bare ved at
`label` ordrett er et REGISTRERT metodenavn. Da slår `METHOD_CAPS` inn med 15 % i stedet for den
generiske 30 %-en, og samme tall felles. Det er § 2.1s grense i `docs/2026-09-03-forslag-fra-mandat.md`
gjort konkret: en ekspert-label treffer metode-cap-en KUN når den ER et registrert metodenavn.
**Ærlighets-grense, uttalt (og den er strukturell):** stage 0 — avstemmingen mot baselinen — kan
**ikke** felle noe på denne veien, fordi kandidaten er BYGGET fra baselinen og derfor avstemmer med
0 % avvik ved konstruksjon. Det er samme faktum som M7 i økt 82, som forble grønn av samme grunn.
Og `assumptions` er tom (et bånd kan ikke avledes fra én pris), så Monte Carlo er degenerert:
P10 == P50 == P90. Det som faktisk binder er stage 4/4b og stage 5.
### 3.4 Tokenbruk per fase — og det dominerende funnet
Instrumentet (`o200k_base`, prompt lest som tekst + `function_call` + `function_result`) er
validert mot en KJENT POSITIV før bruk: rotnivå-listingen på levert K2 måles til **3 954 tegn /
1 495 o200k-tokens over 629 konsepter**, som reproduserer S7a-3s publiserte tall eksakt.
| fase | prompter | o200k-tokens | andel |
|---|---|---|---|
| 1 — utforskning (navigatør 5, manager 6, hypotesiser 1) | 12 | **18 355** | 0,9 % |
| 2 — debatt + generering (proposer 3, checker 1) | 4 | **1 947 342** | 99,1 % |
| 3 — deterministisk dom | 0 | **0** | 0 % |
| **sum** | **16** | **1 965 697** | |
**Funnet:** MAJOR-3 og S7a-3 gjorde UTFORSKNINGEN billig — den koster nå 18 355 tokens over hele
K2 — men **debatten stapper fortsatt hele basen inn i hver prompt**. `okf.bundle_context` på denne
basen er **648 962 o200k-tokens**, og den rir i **3 kopier** (2 debatt-turer + genererings-prompten):
3 × 648 962 = 1 946 886, altså praktisk talt hele fase 2. Nitti-ni prosent av en K2-kjørings
tokenkostnad er kontekst ingen ba om på nytt.
Dette er IKKE en ny oppdagelse i sin form — CLAUDE.mds MAJOR-3-rad sier allerede at «debattens 3×
er PM-ens egen beslutning og er urørt», og at prefiks-caching er NOTERT, ikke bygget. Det nye er
**nevneren på et ekte korpus**: på de tre eksempelbasene var den samme kopien 12 04739 104 tokens,
her er den 648 962. Ingen terskel settes her; det er operatørens.
### 3.5 Hvilke konsepter navigatøren åpnet
Fra `{run_id}-exploration.json`s `tool_calls`, i KALL-REKKEFØLGE (S7a-3 pkt. 3s `path`-felt er dét
som gjør dette lesbart i det hele tatt — uten det leser sporet `read_file, k2` og hvilken av 630
det var kan ikke leses ut av leveransen):
| # | verktøy | bundle_id | path |
|---|---|---|---|
| 1 | `list_bundles` | — | — |
| 2 | `read_bundle` | `k2-trinn1-20260903` | — |
| 3 | `read_dir` | `k2-trinn1-20260903` | `del-ii-bilag-7-prisskjema` |
| 4 | `read_file` | `k2-trinn1-20260903` | `del-ii-bilag-7-prisskjema/prisskjema-SYNTETISK.md` |
Stigen brukes som den er ment: katalog → basens rotnivå → én underkatalog → ETT dokument.
`tokens_spent` i artefaktet er 96 (ledger-regnskapet, ikke prompt-tokens — de to måler ulike ting).
### 3.6 Ærlighets-grenser for hele DEL B
* **Prisene er syntetiske.** Ingen levende K2-pris er lest. Det som er vist er at maskineriet
kommer fram, ikke hva et tilbud koster.
* **Ingen levende modell er kalt.** Hver agent-replikk kommer fra `--scripted-replies`; banneret
sier det på hver kjøring. Dette er den GRATIS halvdelen av måleprotokollens stige.
Multiplikatoren 3 gjelder dette manuset.
* **Kjeden er tre faser, ikke én kommando** (§ 1.4 b), og `--revise` er lest som plan-review-døra.
* **Artefaktet bærer ikke de formede tilnærmingene.** `{run_id}-exploration.json` har
`rounds`/`tool_calls`/`plan_reviews`/`quick_validations`, mens hvilke approaches løkka formet
står i mandat-annonseringen på stdout. Uttalt, ikke endret.
* **`BudgetExceeded` ut av `--explore` tracebacker fortsatt** — målt her ved et uhell, da et
uparsebart proposer-svar brant rundetaket. Det er CLAUDE.mds egen uttalte grense fra økt 57, nå
observert på et ekte korpus.
---
## 4. Mutasjonsmålingen (DEL A + DEL C)
Grønn kontroll **1290 passed / 5 skipped** (fra 1275/5 — supersett, 0 fjernet), golden
`demo-transcript.stdout` BYTE-UENDRET, `shasum -a 1` av **INNHOLDET** =
`ea8c534773acdbe41ae68f2c55724d69aaf8be4f` (ikke git-blob-id-en). Hver mutasjon kjørt mot HELE
suiten, én om gangen, alltid restaurert.
| id | mutasjon | røde |
|---|---|---|
| M1 | `_project_from_bundle` tilbake til den fail-faste loaderen | 4 |
| M2 | toleransen utvidet fra FRAVÆR til UENIGHET | 3 |
| M3 | den valgfrie loaderen svelger en MALFORMED projeksjon også | 1 |
| M4 | presedensen INVERTERT: erklært id slår den håndskrevne projeksjonen | 7 |
| M5 | dispatcheren tilbake til den fail-faste loaderen | 1 |
| M6 | folden hoppes over i STILLHET (ingenting telles) | 2 |
| M7 | over-rapportering: hver kjøring med en store påstår at dommene var unøklbare | 1 |
| M8 | antallet forlater aldri `run_project` (konstant 0 på resultatet) | 2 |
| M9 | rendereren skriver ALLTID linja — omisjonen er selv gatet | 1 |
| M10 | rendereren kalles aldri fra CLI-en | 1 |
| M11 | en unøklbar dom hoppes STILLE over i stedet for å nektes | 1 |
| M12 | seedens fallback beholder den fail-faste loaderen | 3 |
| M13 | `--mandate` faller ut av report-partisjonen igjen (DEL C) | 1 |
**To mutasjoner har vitner UTENFOR den nye fila, og det er dét som gjør dem sterke.** M2 (toleranse
utvidet til uenighet) rødner `test_content_keyed_script_loadbearing::test_the_project_id_is_data_too`
og `test_live_dry_run::test_cli_live_dry_run_local_unknown_project_no_azure_hint` — begge eldre enn
dette arbeidet. M4 (invertert presedens) rødner fire eksisterende armer i
`test_multibase_loadbearing` og `test_bundle_id_reconciliation_loadbearing`, altså nøyaktig den
retningen hovedarmen strukturelt ikke kan se.
**Ingen mutasjon forble grønn.** Alle tretten rødnet en NAVNGITT test.