Generalprøve ×2 grønn på777b9f7(exit 0, 61/4 begge ganger, golden-diff TOM begge ganger, kjøringene byte-identiske med hverandre). K1 distinkt = 8, linje-telling 9 som forventet. K2: REJECTED 2100000 mot P90 1769915 → VALIDATED 445500, samme kandidat. Rent tre målt FØR X ble notert. Frys-gaten prøvekjørt begge armer: arm 1 tom per konstruksjon (lime-inn-sjekk av hashen passerte), arm 2 motc255662ikke-tom (6 filer) — gaten diskriminerer. Utfyllings-gaten TOM. Denne commiten er Y. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DWeYxduEnFQeynXbrtEA6o
394 lines
25 KiB
Markdown
394 lines
25 KiB
Markdown
# 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** | `777b9f7225cc1d4d4d9d45a1d3bdc7033ebaeb1a` | `git rev-parse HEAD` rett etter grønn generalprøve ×2 |
|
||
| Generalprøve ×2 | 2026-08-12 20:15 | tidspunktet begge kjøringene var grønne |
|
||
|
||
**Det finnes med vilje ingen rad for taggen, og fraværet er bærende.** Et tag-felt kunne først
|
||
fylles ut *etter* §5s punkt 10 (push) — men §5s punkt 6 krever at utfyllings-gaten er **tom**, altså
|
||
før. Å fylle det ærlig ville krevd en commit **etter** taggen, og da står HEAD på den commiten mens
|
||
taggen står på `Z`: torsdagens §6 steg 2 (`git describe --tags --exact-match HEAD` → `v1.0.0`)
|
||
ville vært **rød på demo-morgenen**, av den ene gaten som måler identitet. Å la feltet stå ufylt
|
||
bryter gaten i stedet. Taggen bekreftes derfor **der den settes** (§5 punkt 11, tre kommandoer i
|
||
terminalen) og måles på nytt torsdag av §6 steg 2 — den er en handling som verifiseres, aldri et
|
||
tall som avskrives hit.
|
||
|
||
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: <systemets temp-katalog>/po-sim-…)`.
|
||
|
||
**Katalogen varierer, prefikset gjør ikke det.** På macOS er temp-katalogen `/var/folders/…/T/`,
|
||
**ikke** `/tmp/` — så linja på skjermen blir lang og stygg, og det er riktig. `po-sim-` er den delen
|
||
som er konstant, fordi programmet setter den (`mkdtemp(prefix="po-sim-")`); resten tilhører miljøet.
|
||
Fasiten maskerer nøyaktig dette skillet. En lang `/var/folders/…`-sti er altså **ikke** et tegn på
|
||
at noe er galt, og ingen grunn til å gå til abortstien.
|
||
|
||
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 1–5, 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 7–9)
|
||
|
||
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 11–33)
|
||
|
||
| Skjerm | Steg | Det ene poenget |
|
||
|---|---|---|
|
||
| 12–15 | 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 |
|
||
| 16–19 | 2 — Hypotese | forslaget med parametere og kostlinjer; påstått **2 100 000 NOK** |
|
||
| 20–22 | 3 — Debatt | to deltakere; checkeren gater **resonnementet** og sier `VERDICT=APPROVE` |
|
||
| 23–24 | 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 |
|
||
| 25–27 | 5 — Forbedre | grunnen mates tilbake i neste forsøk, **bundet** av `max_attempts` → **VALIDATED 445 500** |
|
||
| 28–29 | 6 — Forkast eller foreslå | typet utfall forlater kjøringen (`validator=validated, checker=approve`) |
|
||
| 30–33 | 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 35–46)
|
||
|
||
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** (37–41): 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** (43–46): 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 48–54)
|
||
|
||
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 56–61)
|
||
|
||
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 /Users/ktg/repos/portfolio-optimiser/tests/golden/demo-transcript.stdout
|
||
```
|
||
|
||
**Stien er absolutt med vilje.** Prosaen under peker på feil katalog som en sannsynlig årsak — og en
|
||
relativ sti ville feilet av nøyaktig den årsaken (målt: `cat: tests/golden/…: No such file or
|
||
directory`). En abortsti som deler failure-mode med det den aborterer fra, er ingen abortsti; den
|
||
gjør ett synlig problem til to.
|
||
|
||
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?» | **Biblioteket** har porteføljekjøring med bølge-modell og et globalt token-tak. Kommandolinja eksponerer ikke taket, og **porteføljekjøring er ikke det denne demoen viser** — den kjører ett prosjekt. Ikke tilby en live demonstrasjon av porteføljestien; den er ikke prøvekjørt denne uka. |
|
||
| «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. Onsdag 12. — elleve punkter i rekkefølge (etter generalprøve ×2)
|
||
|
||
**Følges i terminalen. Hakene settes ALDRI i denne fila.** Punkt 6 er runbook-commiten `Y`, og alt
|
||
fra punkt 7 og ut skjer *etter* den. Et hake satt der havner enten ucommittet i treet — målt:
|
||
`git status --short --untracked-files=no` svarer da ` M docs/plan/2026-08-12-demo-runbook.md`, så
|
||
torsdagens §6 steg 1 blir rød — eller i en commit **etter** taggen, som gjør §6 steg 2s identitet
|
||
rød. Samme motsigelse som §0s manglende tag-rad, samme to gater. **Fila skrives i punkt 4 og punkt 6
|
||
— begge FØR runbook-commiten `Y` — og røres ikke etter den.** Det er *etterpå* som er den bærende
|
||
egenskapen, ikke antallet skrivinger: en hash notert i punkt 4 og først skrevet ned tre steg senere
|
||
er en hash båret i hodet gjennom tre gate-kjøringer. Bruk papir, en annen skjerm eller hukommelsen
|
||
til **hakene** — de er det eneste som ellers ville havnet i fila etter `Y`.
|
||
|
||
- [ ] 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.)*
|
||
- [ ] **Rent tre FØR X noteres** — `git status --short --untracked-files=no` → **TOMT**.
|
||
Prøven du nettopp kjørte leste **arbeidstreet**; **X** er en **commit**. Frys-gaten under er
|
||
commit-til-commit og kan ikke se en ucommittet endring i `src/` — **begge** kjøringene av den
|
||
ville stått tomme mens det taggede treet var noe annet enn det prøvde. Samme kommando som
|
||
§6 steg 1, tredje tidspunkt, egen jobb. Utrackede filer holdes utenfor av samme grunn som der:
|
||
`presentasjon-*.html` eies av en annen sesjon.
|
||
**Ikke tomt: commit eller forkast — og kjør så prøven OM IGJEN.** Ikke fristes til å committe
|
||
og gå videre: den commiten flytter HEAD, så **X** ville pekt på et tre prøven aldri så. Ved X
|
||
er ingenting redigert ennå — runbooken (Y) og CHANGELOG (Z) skrives *etter* dette punktet.
|
||
- [ ] **X** notert (`git rev-parse HEAD`) og skrevet inn i tabellen i §0
|
||
- [ ] **Frys-gaten prøvekjørt — BEGGE armer.**
|
||
|
||
```
|
||
git diff --stat <X>..HEAD -- . ':(exclude)docs/' ':(exclude)CHANGELOG.md' # → TOMT
|
||
git diff --stat c255662..HEAD -- . ':(exclude)docs/' ':(exclude)CHANGELOG.md' # → IKKE tomt
|
||
```
|
||
|
||
Den første armen er **tom, og kan ikke være annet**: `<X>` **er** HEAD her — punkt 4 leste den
|
||
nettopp, og ingenting er committet siden — så `<X>..HEAD` er tom uansett hva treet inneholder.
|
||
Målt med en endret `src/`-fil liggende i treet: gaten sto fortsatt tom. Den er altså en
|
||
**lime-inn-sjekk** av hashen (`fatal: bad revision` hvis du bommet), ikke en frys-sjekk.
|
||
Frysen selv måles av punkt 3 (rent tre) og punkt 9 (etter Y og Z).
|
||
**Den andre armen er den som gir punkt 9 mening** — den beviser at kommandoen *kan* bli
|
||
ikke-tom, før punkt 9 hviler på at den er tom. Målt: **6 filer**. `c255662` ligger fast bak
|
||
både Y og Z, så den forblir ikke-tom uansett hvor HEAD står i morgen.
|
||
**Er den andre armen også tom, er det pathspec-en som er ødelagt** — feilskrevet
|
||
`':(exclude)…'`, eller quoting som ikke overlevde skallet (repoets MULTIOS-lærdom: en kommando
|
||
som ser riktig ut kan lyve). Punkt 9 ville da vært grønn på feil grunnlag, og du ville tagget
|
||
et utestet tre. **Ikke gå videre før den andre armen er ikke-tom.**
|
||
**De to måtene armen kan svikte på ser IKKE like ut, og det er med vilje:** *stille tomt* =
|
||
pathspec-en er ødelagt (det er dette armen finnes for). *`fatal: bad revision`* = du bommet på
|
||
hashen — den er `c255662`, målt ikke-tom 08-11. En tom utskrift er altså aldri «feil hash»;
|
||
da hadde git ropt.
|
||
- [ ] Runbooken fylt ut (§0s to felt) + `grep -n '<<[A-ZÆØÅ-]*>>' docs/plan/2026-08-12-demo-runbook.md`
|
||
→ TOMT — **og så `git commit`. Den commiten ER `Y`.** Uten den er runbooken en ucommittet
|
||
endring resten av sekvensen ikke kan se: frys-gaten (punkt 5 og 9) ekskluderer `docs/`, så den
|
||
passerer **stille**; punkt 11s anker passerer også, fordi HEAD da fortsatt er `X` og `X` er det
|
||
taggede. Først torsdagens §6 steg 1 roper — foran demoen.
|
||
- [ ] CHANGELOG-overskriften stemplet — **datoen LESES, ikke skrevet på forhånd og ikke tatt fra
|
||
veggklokka:** `git log -1 --format=%cs` (HEAD står nå på `Y`) — **og så `git commit`. Den
|
||
commiten ER `Z`, og det er `Z` taggen settes på.** Uten den blir `v1.0.0` tagget med
|
||
`## [Unreleased]` fortsatt i CHANGELOG — frys-gaten unntar `CHANGELOG.md` og ser det ikke —
|
||
og punkt 8 ville sammenlignet datoen mot en fil som ikke er committet.
|
||
- [ ] **Datoen RE-LEST etter at stempel-commiten (Z) finnes, FØR taggen** — `git log -1 --format=%cs`
|
||
på nytt → må være **IDENTISK** med den stemplede overskriften. Første lesning skjedde med HEAD
|
||
på **Y** (runbook-commiten), og **Y blir aldri tagget**. Faller midnatt mellom Y og Z, stemplet
|
||
du gårsdagens dato inn i commiten som faktisk tagges. Avvik = `git commit --amend` på
|
||
overskriften, les på nytt, ikke tag før de er like. *(Sklir HELE sekvensen til torsdag morgen,
|
||
er alt i orden — Y og Z er da samme dag. Det er bare midnatt MELLOM dem som brekker enigheten.)*
|
||
- [ ] **Frys-gaten kjøres ÉN GANG TIL, rett før taggen** — samme kommando som punkt 5s første arm.
|
||
**Dette er den første kjøringen som kan si noe.** Punkt 5s arm mot `<X>` var tom *per
|
||
konstruksjon* (X var HEAD da); her har runbook-commiten (Y) og CHANGELOG-stempelet (Z) flyttet
|
||
HEAD forbi X, så en `src/`-endring imellom ville dukket opp. Tom her = **det taggede treet er
|
||
beviselig det prøvde treet**. Ikke tomt = IKKE tag.
|
||
- [ ] `git tag -a v1.0.0 -m "v1.0.0 — first complete eight-step loop"` + `git push origin v1.0.0`
|
||
(**`origin` alene** — `open/` er P5-vinduet).
|
||
**Annotert (`-a`), ikke lettvekts.** Repoets eneste andre tag er annotert — målt:
|
||
`git cat-file -t v0.1.0` → `tag`, med tagger-header og meldingen `v0.1.0 — first tagged release`.
|
||
En lettvekts `v1.0.0` ville gjort hovedreleasen til den eneste taggen uten forfatter, dato eller
|
||
melding. **Meldingen står literalt her nettopp for at den ikke skal improviseres på en enveis-dag**
|
||
— den er *ikke* et felt i §0, og utfyllings-gaten forblir derfor på **2**.
|
||
Formen er tørrkjørt 08-11 (eget engangs-repo, ikke dette treet): `-a` med em-dash gir
|
||
`git tag -l` → `v1.0.0`, `git describe --tags --exact-match HEAD` → `v1.0.0`, filtrert
|
||
`ls-remote` → **1 linje**, og em-dashen overlevde skallet.
|
||
- [ ] **Taggen bekreftet der den ble satt** — `git tag -l v1.0.0` → `v1.0.0` · `git ls-remote --tags
|
||
origin v1.0.0` → **én linje** · `git describe --tags --exact-match HEAD` → `v1.0.0`.
|
||
Dette **er** tag-bekreftelsen; den skrives ikke inn i §0 (begrunnelsen står der). Den tredje
|
||
kommandoen er nøyaktig ankeret torsdagens §6 steg 2 leser — kjørt her koster den sekunder, og
|
||
en tag som landet på feil commit oppdages på **frysedagen** i stedet for på demo-morgenen.
|
||
Samme grunn som at §6 selv ble flyttet fra «under demoen» til «før rommet fylles».
|
||
**«Én linje» gjelder BEGGE tag-former**, så punkt 10s `-a` endrer ikke forventningen her.
|
||
Målt mot ekte `origin` 08-11: den annoterte `v0.1.0` gir **to** linjer *uten* filter
|
||
(`refs/tags/v0.1.0` + den peelede `refs/tags/v0.1.0^{}`), men **én** med `v0.1.0` som refspec —
|
||
`^{}` matcher ikke pattern-et. Kjør den derfor **med** taggnavnet, som over.
|
||
**⚠️ TOM UTSKRIFT ER TVETYDIG — LES EXIT-KODEN.** `origin` rate-limiter SSH på burst. Målt
|
||
08-11: de to første `ls-remote` gikk igjennom, de fire neste ga `Connection refused`, og porten
|
||
svarte igjen etter en pause — Forgejo-weben var oppe hele tiden (HTTP 303), så serveren var
|
||
aldri nede. Punkt 11 kjører to SSH-kall rett etter en push, altså nøyaktig et burst.
|
||
**Begge tilfellene gir null linjer på stdout** (målt): taggen mangler = **exit 0** og tom
|
||
stderr · kom ikke fram = **exit 128** og `ssh: connect to host … Connection refused` på stderr.
|
||
Et `| wc -l` alene kan altså ikke skille dem, og lest som «taggen landet ikke» er det en abort
|
||
på feil grunnlag — dagen etter at push-en faktisk lyktes. **Exit 128: vent til porten svarer
|
||
igjen, og bruk en probe — ikke en klokke:** `ssh -T git@git.fromaitochitta.com` → `Hi there,
|
||
ktg!`. Det er dette som kom tilbake da forbindelsen løsnet 08-11; **ingen fast ventetid er
|
||
målt**, så et tall her ville vært gjettet. Kjør så kommandoen på nytt. `git tag -l` er lokal og
|
||
svarer uansett; den skiller «tagget lokalt» fra «nådde origin» uten å røre nettverket.
|
||
**Ble PUSH-en selv rate-limitet (punkt 10), er retry både riktig og trygt** — målt: `git push`
|
||
av en uendret tag gir `Everything up-to-date`, exit 0. **Det som ALDRI skal gjøres er å FLYTTE
|
||
taggen** (`git tag -f` + force-push). Uten force er selv det fail-closed — målt: remote svarer
|
||
`! [rejected] … already exists`.
|
||
|
||
---
|
||
|
||
## 6. Torsdag 13., FØR noen er i rommet — tre kommandoer
|
||
|
||
Ingenting her vises fram. Dette er sjekken som gjør at en feil blir et ikke-problem i stedet for en
|
||
abortsti foran publikum, og den koster sekunder: demoen selv kjører på under 3 sekunder (målt).
|
||
|
||
**Hvorfor den finnes:** golden-transkriptet ble sjekket inn nettopp for å fange regresjon **mellom
|
||
onsdag og torsdag** — selv-identitet (kriterium 6) fanger ikke-determinisme, men ikke at noe flyttet
|
||
seg over natta (egnethetsreview-planen pkt. 3). Kommandoen som gjør det står allerede i §1, under
|
||
«Hvis du vil vise at outputen er den frosne». **Torsdag er den ikke valgfri, og den kjøres FØR du
|
||
går på — ikke som et show underveis.** Samme kommando, annet tidspunkt, helt annen jobb: kjørt på
|
||
scenen oppdager den regresjonen samtidig med publikum.
|
||
|
||
**1 — Rent tre**
|
||
|
||
```
|
||
git status --short --untracked-files=no
|
||
```
|
||
|
||
Forventet: **TOMT** (målt). Utrackede filer holdes bevisst utenfor: `docs/presentasjon-portfolio-optimiser.html`
|
||
eies av en annen sesjon, og en gate som roper på den lærer deg å ignorere gaten. Kommer det linjer
|
||
her, er det **sporet** innhold som har endret seg — les hva før du gjør noe annet.
|
||
|
||
**2 — Treet du kjører ER det taggede**
|
||
|
||
```
|
||
git describe --tags --exact-match HEAD
|
||
```
|
||
|
||
Forventet: **`v1.0.0`**. Torsdag skriver ingenting, så forventningen er **IDENTITET** — ikke
|
||
frys-gatens «tom modulo `docs/` og `CHANGELOG.md`». De to unntakene var begrunnet i at *onsdagen*
|
||
skriver nøyaktig dem; arvet hit ville de gjort gaten blind for den ene skriveren vi vet er aktiv i
|
||
repoet (den parallelle sesjonens `docs/`-fil).
|
||
|
||
**Feiler den, er det en BESKJED — ikke nødvendigvis en abort.** Målt: uten tag på HEAD sier git
|
||
`fatal: no tag exactly matches '<sha>'` (exit 128); finnes ikke taggen i det hele tatt, sier den
|
||
`fatal: bad revision` — da landet ikke onsdagens siste steg. Begge feiler høylytt; ingen av dem kan
|
||
forveksles med grønt. Les så hva som faktisk landet:
|
||
|
||
```
|
||
git diff --stat v1.0.0..HEAD
|
||
```
|
||
|
||
**Ingen unntak her, med vilje.** Rører det `src/`, `tests/`, `shared/`, `pyproject.toml` eller
|
||
`uv.lock` → **ikke kjør demoen fra dette treet**, gå til §3. Er det bare `docs/`, er demoen
|
||
upåvirket — men da *vet* du det, i stedet for å ha hatt en gate som tidde.
|
||
|
||
**3 — Outputen er fortsatt den frosne**
|
||
|
||
Kjør blokka i §1 («Hvis du vil vise at outputen er den frosne»). Forventet: `diff` **TOMT**.
|
||
|
||
*(Skriver `uv` en `Resolved`/`Audited`/`Installed`-linje før programmet starter, er det miljø-sjekken
|
||
sin og ikke en feil. Målt på varmt miljø er `uv run` stille — stderr er de fire linjene §1 beskriver
|
||
— men en første kjøring for dagen kan si fra. Det er ingen grunn til abort.)*
|
||
|
||
**Er 3 ikke tom: ikke debug — gå til §3.** Forskjellen er at du vet det på forhånd, så «dette er den
|
||
frosne kjøringen, sjekket inn som fasit» blir en planlagt setning i stedet for en redning.
|
||
|
||
---
|
||
|
||
## 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.
|