portfolio-optimiser/docs/plan/2026-08-12-demo-runbook.md
Kjell Tore Guttormsen c7a57d8c76 docs(P4.5): demo-runbooken skrevet — beslutningene mandag, målingene onsdag
Runbooken var gatet til "VED frysen onsdag". Gaten gjelder hashen X og verbatim
output-utdrag — ikke forfatter-dømmekraften. Planens egen onsdags-regel er at
dagen skal MÅLE og UTFØRE, ikke avgjøre; en runbook skrevet fra bunnen på en
enveis-dag under tidspress er nøyaktig det den regelen forbyr. Derfor to-trinns
med vilje: alt kjennbart nå, tre målte felt onsdag.

Samler de fire spredte kildene I5 navnga (demo-uke-plan §1 · innholdsgate §5
JA-varianten · P4 pkt. 4 · §0 Spor 2) og forankrer hver setning i en LINJE i det
pinnede transkriptet, så operatøren finner stedet uten å lete.

MANDAT-SETNINGEN ER SKREVET. Den sto i Spor 2 som "én muntlig setning" og fantes
ikke som tekst noe sted — en udraftet setning til en live demo. Nå formulert mot
docs/bestille-en-kjoring.md: bestillingen styrer hva som VURDERES, aldri hva som
GODKJENNES.

UTFYLLINGEN ER GJORT TIL EN SJEKKET STEG, ikke en husket. Tre placeholders med
greppbar form, og grep-en er SELV-SIKKER: monsteret '<<[A-ZÆØÅ-]*>>' matcher
ikke sin egen tekst (målt: 3 treff, ingen av dem kommandolinjene). Et uutfylt
felt er samme drift-klasse som plan-radene økt 4, 5 og 6 hver for seg fant.

VEDLEGGET FELLER TRE STATE-PREMISSER. Alle tre "scene-kosmetiske" punkter er
målt mot det pinnede transkriptet, og INGEN er synlige:
- 23700 NOK/aar: rationale er 389 tegn, beløpet står ca. tegn 370, demoen
  klipper på 300 -> linja ender "pga. overes…". grep -c "23700" -> 0.
  STATEs "printes fortsatt ordrett" var et premiss, ikke en måling.
- 0.82 hører til bygg-goldenen, ikke veglys. grep -c -> 0.
- docs/ekspert-svar.md leses ikke av demoen.
Torsdagen slipper altså tre setninger den var fortalt at den måtte bære.

CHANGELOG-DATOEN GJORT TIL EN MÅLING: sjekklista sier "les datoen på dagen"
(date +%F), ikke det forhåndsskrevne 2026-08-12 — samme premiss-klasse som
hashen planen allerede nekter å skrive ned.

Frysen er IKKE flyttet fram. Tirsdagen er tom og fristet, men onsdag er en
dato-beslutning på en enveis-handling (tag + frys), og risikoen den ville hedget
er allerede retirert: økt 6 målte samme kjøresti grønn, og d0e8bb0..HEAD er
dokumenter alene.

Målt: 810 passed / 4 skipped uendret. docs/-gaten passert via datert sti.
Kjørestien urørt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011GtvZy6hn3k2iTFGjRVzLi
2026-08-10 21:16:10 +02:00

220 lines
12 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.

# Demo-runbook — torsdag 13. august 2026
> **Én side å ha i hånda på scenen.** Kjøresekvens · hva som sies hvor · abortstien.
>
> **Status:** beslutnings-innholdet er skrevet **mandag 10. august** (økt 7) — alt som er kjennbart
> uten frysen. **Onsdag 12. fyller ut de målte feltene** og krysser av nederst. Runbooken er
> lesestoff, ikke kjøresti: den ligger under `docs/`, som er unntatt frys-gaten, så den kan skrives
> og fylles ut uten å røre det frosne treet.
>
> **Onsdagens utfyllings-sjekk (kjør FØR demoen):**
> ```
> grep -n '<<[A-ZÆØÅ-]*>>' docs/plan/2026-08-12-demo-runbook.md # → TOMT
> ```
> Ikke tomt = runbooken er et utkast, ikke en runbook. Et uutfylt felt er samme drift-klasse som
> plan-radene økt 4, 5 og 6 hver for seg fant: et dokument som instruerer om noe som ikke stemmer.
---
## 0. Målte felt — fylles onsdag
| Felt | Verdi | Hvor det kommer fra |
|---|---|---|
| Frosset commit **X** | `<<X-HASH>>` | `git rev-parse HEAD` rett etter grønn generalprøve ×2 |
| Tag | `<<TAG-BEKREFTET>>` | `git tag -l v1.0.0` etter push til `origin` |
| Generalprøve ×2 | `<<PROEVE-DATO-TID>>` | tidspunktet begge kjøringene var grønne |
Alt annet i dette dokumentet er målt mandag 10. august mot det pinnede transkriptet
(`tests/golden/demo-transcript.stdout`, 61 linjer) og står uendret.
---
## 1. Kjøresekvensen
**Kommandoen — kjør denne, ingen andre flagg:**
```
uv run python -m portfolio_optimiser.simulation
```
Forventet: **exit 0**, **61 linjer stdout**, **4 linjer stderr**.
Stderr er fire linjer og skal være der: to `ExperimentalWarning` fra MAF (Skills + MemoryStore),
en blanklinje, og `(arbeidskopi: /tmp/po-sim-…)`. De to advarslene dempes **ikke** med vilje — de
fyrer mens biblioteket importeres, og å dempe dem ville betydd at rammeverket bestemmer hva MAF
får si til enhver konsument. Rund-tak-linjene («forcing completion») er dempet og skal **ikke** vises.
**Hvis du vil vise at outputen er den frosne:**
```
uv run python -m portfolio_optimiser.simulation > /tmp/demo.out 2>/dev/null
diff /tmp/demo.out tests/golden/demo-transcript.stdout # → TOMT
```
*(Konsoll-kommandoen `portfolio-optimiser-demo` gir byte-identisk stdout og virker like godt.
`-m`-formen står her fordi den ikke antar noe om PATH. `PYTHONIOENCODING=utf-8` er pinnet i
testene; i en vanlig UTF-8-terminal trengs den ikke.)*
---
## 2. Hva som sies — i rekkefølge, forankret i skjermlinjene
Linjenumrene under er linjene i det pinnede transkriptet, så du kan finne igjen stedet uten å lete.
### Åpningen (skjermlinje 15, banneret står allerede der)
Banneret sier det selv. Les det, ikke pynt det bort, og legg til de **tre ærlighets-punktene**
(demo-uke-planen §1 — nivå-2-påstanden, D-I):
1. **Agent-svarene er skriptet.** Dette beviser dataflyten, den deterministiske ryggraden og at
læringssløyfa lukkes — ikke at en levende modell ville produsert nettopp dette forslaget.
2. **Innholdet er håndkuratert, ikke fabrikkert.** Et menneske lagde kunnskapsbasen.
3. **Tallene er modellerte, ikke målte.** Ingen pilot har validert dem i drift.
> Dette er ikke en unnskyldning som svekker demoen — det er grunnregelen repoet er bygget på
> (A5: koden får ikke påstå mer enn den gjør). En demo som overselger bryter med det den demonstrerer.
### Ærlighets-avsnittet — leses opp ORDRETT (innholdsgate-planen §5, **JA-varianten**)
Spor B landet 2026-08-09, så det er JA-varianten som gjelder. NEI-varianten brukes **ikke**.
> «To ting om innholdet dere ser. For det første: denne kunnskapsbasen er laget for hånd, ikke
> produsert av systemet. Det finnes en ingest-vei som henter eksterne kilder inn i formatet, men
> eksempelet her gikk ikke gjennom den, og den generiske fabrikken som skulle laget slike baser er
> ikke bygget — den er bevisst utsatt.
> For det andre, om sikkerhet: ingest-veien skanner nå innholdet før det skrives, med en egen
> sikkerhetskomponent, slik at forgiftet kildeinnhold ikke havner i basen.»
*(Forbeholdet hvis noen graver: gaten er **opt-in** — `materialize_gated` er den gatede inngangen,
`materialize` er bevisst ugatet, og en kaller som vil ha gaten ber om den ved navn. Det står slik i
CHANGELOG-ens Security-oppføring. Si det hvis det spørres; ikke som en fotnote i opplesningen.)*
### Kunnskapsbasen (skjermlinje 79)
Linje 9 **er** ærlighets-setningen om provenans — den står allerede på skjermen og skal ikke sies
på nytt: *«tallene er levert i kunnskapsbasen — utledet av fagkilder (Håndbok V124, NMFV), ikke av
demo-manuset»*. Pek på den. Poenget er at kostbaselinen er **erklært**, og at validatorens stage 0
avstemmer forslagets kostlinjer mot den **før** løseren.
### Kjøring A, steg for steg (skjermlinje 1133)
| Skjerm | Steg | Det ene poenget |
|---|---|---|
| 1215 | 1 — Forstå konteksten | fem konseptfiler ble **navigert**, ikke søkt opp som tekstbiter; **0** tidligere dommer, og markøren er `False` — det er kontrollen som gjør Kjøring B beviselig |
| 1619 | 2 — Hypotese | forslaget med parametere og kostlinjer; påstått **2 100 000 NOK** |
| 2022 | 3 — Debatt | to deltakere; checkeren gater **resonnementet** og sier `VERDICT=APPROVE` |
| 2324 | 4 — Valider | **REJECTED** — 2 100 000 overstiger P90 feasible **1 769 915**. Dette er hele poenget: checkeren sa ja, tallene sa nei, og tallene vinner |
| 2527 | 5 — Forbedre | grunnen mates tilbake i neste forsøk, **bundet** av `max_attempts`**VALIDATED 445 500** |
| 2829 | 6 — Forkast eller foreslå | typet utfall forlater kjøringen (`validator=validated, checker=approve`) |
| 3033 | 7 — Tilbakemelding (kort løkke) | ekspert-personaen godkjenner **med realiseringskorreksjon** (0.79) |
**Setningen som bærer demoen** (skjermlinje 22 mot 24): *«Checkeren godkjente resonnementet. Den
deterministiske validatoren avviste tallet. To uavhengige falsifiserere, og det er den som regner
som blokkerer.»*
### Mellom kjøringene (skjermlinje 3546)
To **uavhengige** tilbakemeldings-veier, én per tidsskala — og de bærer hver sin markør nettopp
for at ingen av dem skal kunne ta æren for den andre:
- **Steg 7, lang løkke** (3741): en ekspert legger en fil i innboksen **etter** kjøringen
(`realiseringsgrad=0.66`). Rollene byttes aldri: systemet **leser** mappa, eksperten **skriver**
den. Dager kan gå.
- **Steg 8, promotering** (4346): den godkjente dommen løftes inn i wikien (`realiseringsgrad=0.79`).
Gaten er **fail-closed** — kun en godkjent dom promoteres, rå agent-output aldri.
### Kjøring B (skjermlinje 4854)
Kun det som **endret seg** vises. Begge markørene er `True`, og linje 51 sier hvor dommene kom fra:
**1 av 3 fulgte med kunnskapsbasen, de øvrige 2 er dem demoen lærte i denne økten**. Den splitten
er **regnet ut** av kjøringen, ikke skrevet ned — derfor stemmer den også når basen en dag shipper
flere dommer.
Utfallet er **det samme tiltaket til samme beløp**. Det er riktig og verdt å si høyt: læringen
endret ikke svaret her, den endret **grunnlaget** svaret ble formet på.
### Avslutningen (skjermlinje 5661)
Les blokken. Poenget er den siste setningen: **ingen av de to veiene gikk gjennom minnet** — begge
gikk gjennom fil.
### Mandat-setningen (MUNTLIG — ingenting av dette vises på skjermen)
Svaret på «kan vi styre hva som analyseres?»:
> «Ja. En kjøring kan bestilles med en oppdragsfil: du skriver hva kjøringen er til for, og hvilke
> tilnærminger du vil ha vurdert — hver av dem får sin egen vurdering og sin egen linje i oppgjøret,
> og systemet kan i tillegg foreslå sitt eget. Men bestillingen styrer hva som **vurderes**, aldri
> hva som **godkjennes**: validatoren gjelder uendret, så ber du om noe tallene ikke bærer, blir det
> avvist — og avvisningen kommer tilbake til deg med begrunnelsen. Det er ikke vist i denne demoen;
> det er et eget flagg (`--mandate`), og det er dokumentert.»
Dokumentet er [`docs/bestille-en-kjoring.md`](../bestille-en-kjoring.md). Søsterdokumentet for den
andre enden — å avgi dommen etterpå — er `docs/ekspert-svar.md`.
---
## 3. Abortstien
**Feiler live-kjøringen på scenen: ikke debug. Vis fila.**
```
cat tests/golden/demo-transcript.stdout
```
Den fila **er** transkriptet — ordrett, uten normalisering — fra den frosne kjøringen. Si høyt hva
den er:
> «Dette er den frosne kjøringen fra onsdag, sjekket inn som fasit. Det dere ser er ikke en
> gjenfortelling, det er outputen ordrett — og at den er sjekket inn er grunnen til at jeg kan vise
> den nå.»
Ikke prøv å fikse noe under demoen. Miljøet er den sannsynlige årsaken (`uv sync` / feil katalog),
og feilsøking på scenen koster mer enn fila.
---
## 4. Forventede spørsmål
| Spørsmål | Svar |
|---|---|
| «Hvorfor viste Kjøring A **0** tidligere dommer når basen shipper ett dom-frø?» | Med vilje: Kjøring A kjøres mot en **tom** wiki. Uten den kontrollen kunne markøren i Kjøring B like gjerne kommet fra basen som fra læringen — kontrollen er det som gjør sløyfa beviselig, ikke bare påstått. |
| «Er dette en ekte LLM?» | Nei — agent-svarene er skriptet, og det står i banneret. Det som er ekte er dataflyten, den deterministiske validatoren og at læringen faktisk går gjennom fil. |
| «Hva om modellen hallusinerer et tall?» | Stage 0 avstemmer hver kostlinje mot prosjektets **erklærte** kostbaseline før løseren i det hele tatt kjører. Ukjent kostkode, eller en mengde/enhetspris utenfor toleransen, avvises — validering, aldri reparasjon. |
| «Kan den kjøre en hel portefølje?» | Ja, og det finnes et globalt token-tak i biblioteket. **Ærlig forbehold:** kommandolinja kobler det taket ikke på ennå — det står som eksplisitt utenfor v1. |
| «Er den generiske fabrikken for kunnskapsbaser med?» | Nei, bevisst utsatt. Basen her er håndkuratert. Det er punkt 2 i åpningen. |
| «Hva med `open/`-speilet / hvor ligger koden?» | Taggen `v1.0.0` er satt på det private repoet. Det offentlige speilet synkes etter demoen, sammen med READMEen som forklarer commitene. |
---
## 5. Krysses av onsdag 12. (etter generalprøve ×2)
- [ ] Generalprøve ×2 grønn — golden-diff tom begge ganger
- [ ] K1: `grep -oE "^ *Steg [1-8]" <stdout> | tr -d ' ' | sort -u | wc -l`**8**
*(linje-tellingen gir **9** — kjent og forventet: Steg 7 har to linjer, én per tidsskala.
Kjør kommandoen, ikke prosaen.)*
- [ ] **X** notert (`git rev-parse HEAD`) og skrevet inn i tabellen i §0
- [ ] Frys-gaten grønn: `git diff --stat <X>..HEAD -- . ':(exclude)docs/' ':(exclude)CHANGELOG.md'` → TOMT
- [ ] CHANGELOG-overskriften stemplet — **les datoen på dagen du utfører** (`date +%F`), ikke en dato
skrevet på forhånd
- [ ] `git tag v1.0.0` + `git push origin v1.0.0` (**`origin` alene** — `open/` er P5-vinduet)
- [ ] `grep -n '<<[A-ZÆØÅ-]*>>' docs/plan/2026-08-12-demo-runbook.md` → TOMT
---
## Vedlegg — tre punkter som IKKE trenger en setning på scenen (målt 2026-08-10)
STATE bar tre «scene-kosmetiske» punkter. Alle tre er målt mot det pinnede transkriptet, og
**ingen av dem er synlige i demoen**:
1. **`23700 NOK/aar` når aldri skjermen.** Personaens `rationale` er 389 tegn og beløpet står helt
til slutt (ca. tegn 370); demoen klipper på **300** tegn, så linja ender på `pga. overes…`.
Målt: `grep -c "23700" tests/golden/demo-transcript.stdout`**0**. STATEs formulering
(«printes fortsatt ordrett») var et premiss, ikke en måling. Det trengs altså **ingen** setning
på scenen — kun hvis noen åpner selve persona-fila.
2. **`0.82` vs `0.79`.** `0.82` hører til bygg-eksempelets golden, ikke veglys-kjøringen.
Målt: `grep -c "0\.82" tests/golden/demo-transcript.stdout`**0**.
3. **`docs/ekspert-svar.md`** er en operatør-guide og leses ikke av demoen.
Punktene står fortsatt som post-demo-opprydding i sine egne spor; de er bare ikke noe torsdagen
må bære.