portfolio-optimiser-claude/docs/2026-07-16-sesjonsplan-paritet.md
Kjell Tore Guttormsen d746891f06 docs(review): full-paritet review + sesjonsplanverk + beslutningsbrief (Fable 5 + 6 Opus-agenter)
Operatør-mandat 2026-07-16: full MAF-paritet (D-G pkt. 2). Review-økt, ingen kildekode.

- review-paritet.md: C-serien re-verifisert (alle åpne), 10 nye R-funn. Kjørt-bevist av
  orkestrator: R-2 (Infinity → validates=True, NaN avvist), R-3 (tom CSV krasjer ingest →
  delvis bundle). R-1 = §11-raden «Closed loop» ubundet. 4/4 detach røde i throwaway-kopi;
  SDK-premisser holder mot 0.2.110→0.2.120; model-id gyldig+billigst; docs §1-ærlige.
- sesjonsplan-paritet.md: ERSTATTER 2026-07-10-planen. 35-raders paritetsmatrise (opphevet
  «Overføres IKKE»-lista, re-klassifisert rad for rad). 16 ugatede sesjoner + gatede med
  eksakte utløsere + avhengighetsgraf + binær leveringsklar-sjekkliste.
- beslutningsbrief.md: operatør-køen i klarspråk (D-A+C-P1, amendment, toolkit-§8, D-B,
  + nytt foreslått delt punkt).
- 2026-07-10-sesjonsplan-d7.md: superseded-merket med peker.

Steg 0 verifisert: commons-amendment IKKE landet, okf-toolkit-repo finnes IKKE.
STATE.md er local-only (gitignored) — ikke committet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 08:36:07 +02:00

751 lines
60 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

# Sesjonsplan — full MAF-paritet (K-serien + videreførte C-sesjoner · delt kø D-AD-E)
> **Status:** GJELDENDE sesjonsplan for dette repoet. ERSTATTER
> [`2026-07-10-sesjonsplan-d7.md`](2026-07-10-sesjonsplan-d7.md) (markert superseded med peker
> hit). Forfattet 2026-07-16 (Fable 5, review-/plan-økt) på operatør-mandatet **FULL
> MAF-PARITET** (D-G pkt. 2: «Claude-repoet skal være minst like godt som MAF-repoet»,
> operatør-besluttet 2026-07-16). Den gamle planens §4-liste «Overføres IKKE hit
> (MAF-spesifikt)» er **OPPHEVET som blanko-unntak** — hvert punkt er re-klassifisert i
> paritetsmatrisen (§1). Ingen stille kutt.
>
> Funn-referanser: C-serien peker til [review 2026-07-10](review-2026-07.md); R-serien til
> [review-paritet 2026-07-16](2026-07-16-review-paritet.md); MAF-referansene (S2.0S5.4,
> D-AD-I, M1M3, T0) til hovedrepoets `docs/plan/2026-07-10-sesjonsplan-fase2-6.md`,
> `2026-07-14-revisjonspakke-DF-DI.md`, `2026-07-14-commons-amendment-utkast.md` og
> `2026-07-14-toolkit-repo-brief.md` — lest på KAPABILITETS-/PLAN-nivå; MAF-kildekode leses
> aldri (D7-regelen står for metode-laget; D-G endrer den bevisst KUN for OKF-formatlaget,
> og kun via okf-toolkit når det finnes).
>
> Prinsipp (uendret): hver bygg-sesjon er én-sesjons-stor, offline, gratis (ScriptedClient),
> TDD (Iron Law: failing test først), load-bearing (§11: detach-punkt per søm), og
> **Opus 4.8 xhigh-eksekverbar** med «Les STATE.md og følg instruksjonene». Ingen
> live-kjøringer: D6 står — S10 var programmets ene; ny spend krever eksplisitt
> operatør-godkjenning (M2-analogen §6 er operatør-milepæl, aldri autonom sesjon).
> «Suiten kjører uten nøkkel/nett» er invariant i ALLE sesjoner under.
---
## 0. Faktisk gate-status ved planleggingstidspunktet (verifisert 2026-07-16)
| Gate | Status | Belegg |
|---|---|---|
| D-AD-E (delt kø) | ÅPNE | MAF-plan §2 + MAF-STATE 2026-07-16 («Operatør-kø uendret») |
| D-FD-I | BESLUTTET 2026-07-14 | revisjonspakka (fasit) |
| Commons-amendment (D-F/D-G-utkastet) | **IKKE landet** — utkast venter operatør | subtree-diff `HEAD:shared``commons/main`: kun `.gitignore` + guard-adopsjonsdoc, ingen spec-endring |
| okf-toolkit-repo (T0) | **Finnes IKKE** | `ls ~/repos/okf-toolkit` + `git ls-remote` mot Forgejo → not found |
| MAF-fremdrift | Fase 1 + Fase 2-bolk A (S2.0/S2.1/S2.5) + S3.6 + S4.1 + S4.2 + S5.1 komplett; S5.2 EXECUTE neste; suite 389 | MAF `STATE.md` 2026-07-16 07:40 |
| Dette repoet | 265 passed offline · ruff/mypy rene · HEAD `b46f32c` == origin/main; open @ `42f320b` | kjørt i Steg 0 (review-paritet §0) |
| `shared/`-subtree | 2 commons-commits bak (docs-only) | samme diff; hentes ved neste koordinerte pull — ingen spec-endring, ufarlig |
Planen bygger på DENNE statusen. Endres gate-status (amendment lander, toolkit-repo opprettes),
gjelder §4-sesjonenes utløser-tekst, ikke antakelsene her.
## 1. Paritetsmatrise MAF ↔ D7 (kapabilitetsnivå)
Kilde: MAF-planene/STATE (aldri MAF-src). Klassifisering: **FINNES HER** (kapabiliteten er
bygget og testet i dette repoet) / **BYGGBAR NÅ** (ingen beslutnings-gate) / **GATED**
(navngitt gate) / **SPEILES IKKE** (etterprøvbar begrunnelse). Alle den gamle planens
«Overføres IKKE»-punkter er re-klassifisert her; ingen rad er stille droppet.
| # | Kapabilitet (MAF-referanse) | MAF-status | D7-status i dag (belegg) | Klassifisering | D7-sesjon |
|---|---|---|---|---|---|
| 1 | Dimensjons-begrep + katalog (Fase 1 / D-F pkt. 5 / amendment §13.3) | Bygget (Fase 1); katalog spec-es av amendmenten | MANGLER — ingen dimensjons-modell i src (filkatalog) | **GATED: commons-amendment (D-F)** — katalog-kontrakten blir spec (§13.3); bygges fra spec-en når den lander, ikke fra utkast | K13 |
| 2 | Mål-kontrakt (absolutt/prosent, hard/soft, stopp ved mål) (Fase 1) | Bygget; prosent-baseline åpen (D-E) | MANGLER | **BYGGBAR NÅ** (absolutt + hard/soft); prosent-baseline-semantikken alene er **GATED: D-E** | K1 |
| 3 | Besparelses-hovedbok (typet ledger, fail-closed `realize`-ekspertgate, provenance) (Fase 1) | Bygget | MANGLER | **BYGGBAR NÅ** (stack-lokal — MAF bygde den også uten delt spec) | K1 |
| 4 | Portefølje-kjøring (flere prosjekter, referanse-konfig, sekvensiell) (Fase 1) | Bygget | MANGLER — eneste kjøresti er `run_s10.py` (én bundle, fasit-frossen) | **BYGGBAR NÅ** | K2 |
| 5 | Portefølje-læringssløyfe — dom på prosjekt k når k+1s prompt (S2.0) | **FERDIG** (bolk A) | MANGLER (ingen portefølje-sti; primitivene finnes: store/fold/inbox) | **BYGGBAR NÅ** (etter K2) | K3 |
| 6 | Offline closed-loop-bevis — to-kjørings-simulering m/ markør (method-spec §11-raden «Closed loop»; MAF-original) | Bygget (originalbygget, `test_simulation_loadbearing`-raden) | **MANGLER** — step7/step8-testene beviser hver sin halvdel; ingen test kjører markøren gjennom to komponerte kjøringer (funn **R1**) | **BYGGBAR NÅ** — også et konformitetsgap, ikke bare paritet | K4 |
| 7 | Outbox-persistens (S2.1) | **FERDIG** | DELVIS — `artifacts.py` persisterer proposal/result/provenance/usage deterministisk (også stop-artefakter), men uten run_id-navngitt forslag/utfall-par → ingen pending-sporing mulig | **BYGGBAR NÅ** (utvidelse av artifacts-laget) | K5 |
| 8 | MCP-ingest-konnektor (S2.2, D-B-gated) | GATED D-B | MANGLER; `extending.md` ærlig «ubygd» | **GATED: D-B + commons-ingest-amendment** — SDK-nativ analog: in-process MCP-fixture via `create_sdk_mcp_server` (SDK-primitiv, verifisert i CLAUDE.md) i stedet for MAFs `mcp`-pakke-klient | K14 |
| 9 | Dokument-konnektor PDF (S2.3, D-B-gated) | GATED D-B | MANGLER | **GATED: D-B + commons-ingest-amendment** | K15 |
| 10 | Konnektor-herding http (S2.4, D-B-gated) | GATED D-B (MAF HAR http-demo å herde) | MANGLER MER — D7 har ingen http-kilde i det hele tatt (avvist fail-fast, `ingest.py:129`; valgfri per ingest-spec §1) | **GATED: D-B** — sesjonen bygger http-familien + herding + guard-G1-wiring i ett | K16 |
| 11 | Inbox-/robusthetsherding (S2.5 ↔ C2.5) | **FERDIG** (bolk A) | MANGLER — vokabular-sjekk/tak finnes ikke (C-F7 kjørt-bevist); SDK-pin løs uten versjonsvakt (C-N3) | **BYGGBAR NÅ** | C2.5 |
| 12 | Validator-stramming nominal-gate + band-invariant (S2.7 ↔ C2.7) | GATED D-A | Samme spec-defekt bekreftet her (C-F2, kjørt bevis) | **GATED: D-A pkt. 1 + commons-pull** | C2.7 |
| 13 | Semantisk henting (S3.1, D-C) | GATED D-C | MANGLER; OBS delt kollisjon C-P1: D-C som planlagt (cosine over tekst) bryter frossen §3 Steg 1 «structural, never textual» | **GATED: D-C OG C-P1-avklaring i D-A-bolken** (begge må lande) | K17 |
| 14 | Multi-kandidat ExpeL-seeding (S3.2 ↔ C3.2) | GATED D-A | Feature-halvdelen bekreftet defekt her (C-F5); id-halvdelen alt løst (verbatim) | **GATED: D-A pkt. 4 + commons-pull** | C3.2 |
| 15 | Concurrency/feilmodell (S3.3, D-D) | GATED D-D | Ikke anvendbar i dag (ingen portefølje-sti) — blir reell når K2 lander | **GATED: D-D** (+ K2 som forutsetning) | K18 |
| 16 | Kostnadsstyring på tvers av kjøringer (S3.4) | GATED D-D | MANGLER; pre-call-guard-delen er ugatet (C-N4) | **GATED: D-D** for portefølje-delen; pre-call-guard + run-total USD-tak er **BYGGBAR NÅ** | K19 (gated) + C3.5 (nå) |
| 17 | Innholdsmodell/bibliotek-materialisering + summary-tier-render (S3.5, D-F) | GATED amendment | MANGLER | **GATED: commons-amendment (D-F/D-G-utkastet)** — inkluderer §13-typene, `library`-ingest-familien (4a/5a), summary-tier (§3 Steg 1-endringen) og dimensjonskatalogen (rad 1) | K13 |
| 18 | Kostnadssimulering FØR kjøring (S3.6, D-I pkt. 3 — MÅ-krav) | **FERDIG** | MANGLER | **BYGGBAR NÅ** — D7-analog: what-if over `model_map.json` (Claude-modeller × effort), prisdata som skjema-validert konfig m/ kilde+dato | K6 |
| 19 | Kostbaseline-forankring (S4.0 ↔ C4.0) | GATED D-A | Samme spec-defekt bekreftet her (C-F3, 2.9 MNOK-beviset) | **GATED: D-A pkt. 2 + commons-pull** | C4.0 |
| 20 | Preflight (S4.1 — Foundry-spesifikk i MAF) | **FERDIG** | MANGLER | **BYGGBAR NÅ** — SDK-nativ analog: Anthropic-API/SDK-preflight, offline (env-kontrakt, model-map-konsistens, placeholder-nekt) — Foundry-auth-delen SPEILES IKKE (sant MAF-spesifikk på kapabilitetsnivå: D7s backend er Anthropic-API) | K7 |
| 21 | Live-kjørings-drill + artefakt-fangst (S4.2) | **FERDIG** | MANGLER | **BYGGBAR NÅ** (etter K5+K7) — `--live-dry-run`: bygg alt, STOPP før første modellkall (kall-tellende mock beviser 0 kall) | K8 |
| 22 | HITL-verdict-ruting + pending-sporing (S5.1) | **FERDIG** | MANGLER | **BYGGBAR NÅ** (etter K5 — id-join outbox↔inbox) | K9 |
| 23 | Varsling/Notifier (S5.2) | Plan klar, EXECUTE neste | MANGLER (D7 har ingen notify-stub engang — bygges rent) | **BYGGBAR NÅ** — kapabilitets-koordinering med MAF S5.2 (protokoll-form, webhook-opt-in, socket-fri suite), aldri kode-titting | K10 |
| 24 | CLI-paritet + dokumentsync + D-H-oppskrift (S5.3) | Gjenstår i MAF | MANGLER — ingen leverbar CLI utover fasit-stien | **BYGGBAR NÅ** (sist i ugatet rekke; C2.0 er første skritt) | C2.0 (inngang) + K12 (full paritet) |
| 25 | Verdirapport per kjøring (S5.4, D-I pkt. 2) | Gjenstår i MAF | MANGLER | **BYGGBAR NÅ** (etter K5 + K1 + K6) | K11 |
| 26 | okf-toolkit-adopsjon inkl. skrive-halvdelen A2 (D-G/T0) | T0 blokkerer også MAF | MANGLER — `okf.py` er kun-les (134 l); skrive-primitivene (promotion har egne) deles ikke | **GATED: T0** (repoet finnes ikke, verifisert 2026-07-16) + operatør (§8-spørsmålene i toolkit-briefen) | K20 |
| 27 | llm-ingestion-guard-wiring | MAF: planned (S2.4/S2.5-utvidelse) | Planned her (guard-plan 2026-07-16): G1 http-persist-gate / G2 inbox-depth / G3 import_bundle | G1 **GATED: D-B** (inn i K16) · G2 valgfri depth **vurderes i C2.5** · G3 **GATED: D-E**-retning | K16 / C2.5 / (D-E) |
| 28 | Steg-7 kjøresti-inngang (C2.0 — D7-egen) | (MAF har den via run-laget) | MANGLER (C-N2) | **BYGGBAR NÅ** | C2.0 |
| 29 | Method-spec-integritetsvakt (C1.1 — §11-raden «Spec integrity») | MAF HAR (`test_method_spec_loadbearing.py`, referert i amendment-utkastet §5.1) | MANGLER (C-N1) | **BYGGBAR NÅ** | C1.1 |
| 30 | OKF `/`-lenke-mapping (C2.8 / D-A pkt. 3 / D-G pkt. 1) | GATED D-A (MAF mangler også bygg-sesjon — flagget) | Spec-tro skip i dag (`okf.py:112`) | **GATED: D-A pkt. 3 + commons-pull** | C2.8 |
| 31 | Budsjett-guard pre-call + run-total USD (C3.5) | Del av S3.4 i MAF | MANGLER (C-N4; per-kall-USD-tak finnes alt — bedre enn MAF) | **BYGGBAR NÅ** | C3.5 |
| 32 | Operatør-milepæler M1M3 | Definert i MAF-planen | Ingen definert her | **SPEILES som milepæl-definisjoner** (§6) — aldri autonome sesjoner. M1-analogen (tenant+smoke) er Foundry-spesifikk; D7-ekvivalenten (nøkkel + preflight grønn) foldes inn i M2-analogens forutsetninger | §6 |
| 33 | Validator robust mot ikke-finite tall (review-paritet R-2 — D7-EGEN korrekthet) | (egen implementasjons-defekt) | **DEFEKT**`Infinity` gir `validates=True` (kjørt-bevist) | **BYGGBAR NÅ** | C2.6 |
| 34 | Ingest robust mot tom/BOM/malformert kilde (R-3/R-4/R-5/R-7 — D7-EGEN) | (egen implementasjons-defekt) | **DEFEKT** — tom CSV krasjer midt i materialisering → delvis bundle (kjørt-bevist) | **BYGGBAR NÅ** | K2.9 |
| 35 | Closed-loop to-kjørings-vakt (R-1 — §11-raden «Closed loop») | MAF HAR (`test_simulation_loadbearing`) | MANGLER — §11 rad 8 ubundet | **BYGGBAR NÅ** | K4 |
**Re-klassifisering av den opphevede «Overføres IKKE»-listen** (gammel plan §4): S2.0-portefølje
→ rad 45 (BYGGBAR NÅ); S2.1-outbox → rad 7 (BYGGBAR NÅ — «output-laget finnes her» var bare
delvis sant); S2.2 MCP → rad 8 (GATED D-B, SDK-nativ analog); S2.3 doc → rad 9 (GATED D-B);
S2.4 http-herding → rad 10 (GATED D-B); S3.1 → rad 13 (GATED D-C+C-P1); S3.3 → rad 15 (GATED
D-D); S3.4 → rad 16 (delt: C3.5 nå, K19 gated); S4.1/S4.2-Foundry → rad 2021 (SDK-nativ
analog, BYGGBAR NÅ; kun Foundry-*auth* speiles ikke); S5.x → rad 2225 (BYGGBAR NÅ-kjede);
M1M3 → rad 32. Setningen «`extending.md` står: ingen D7-HTTP/MCP-økt planlagt» er ikke
lenger dekkende — K14K16 planlegges nå, gated D-B; `extending.md` oppdateres i K16
(docs-ærlighet, §1).
## 2. Den delte beslutnings-køen (uendret — bor i HOVEDREPOET)
D-AD-E ligger i MAF-planens §2 og besluttes der; dette repoet planlegger ingen egen variant —
kun sesjoner gated på den. Det som gater arbeid HER, med anbefaling i klarspråk, står i
[beslutningsbriefen](2026-07-16-beslutningsbrief.md). Koblings-flagget **C-P1** (D-C ↔ frossen
§3 Steg 1) står uendret og MÅ inn i D-A-bolken. Ett NYTT beslutnings-kandidat-punkt foreslås
inn i den delte køen via briefen (delbarhet av ledger-/outbox-format) — det besluttes ALDRI
ensidig her.
**Commons-regel (uendret):** amendments skrives i commons, pulles med
`git subtree pull --prefix=shared commons main --squash`. ALDRI subtree push. Etter hver
amendment-bølge re-pinner/puller BEGGE repo og BEGGE suiter kjøres (sammenligningsprotokollen);
golden re-fryses kun koordinert i commons.
## 3. Byggbare NÅ (ingen beslutnings-gate) — anbefalt rekkefølge
> Felles verifisering for ALLE sesjoner (gjentas ikke per sesjon): full gate
> (`uv run pytest` + `uv run ruff check .` + `uv run ruff format --check .` +
> `uv run mypy src`) grønn; golden-regresjonen (`test_bygg_energi_mikro.py` +
> ingest-goldens) uendret grønn; suiten kjører uten nøkkel/nett; `runs/s10/` urørt;
> `run_s10.py` byte-urørt (fasit-sti). Nye moduler holdes SDK-frie (ren stdlib+pydantic)
> med mindre sesjonen eksplisitt sier noe annet, og SDK-frihet bindes med import-vakt etter
> `test_okf`-purity-mønsteret.
### C1.1 Method-spec-integritetsvakt (C-N1) — UENDRET fra gammel plan, ÅPNING
- **Mål:** §11-raden «Spec integrity» håndheves lokalt — spec-drift i subtree-synken fanges her.
- **Scope (filliste):** ny `tests/test_method_spec_loadbearing.py` (KUN testkode).
- **IKKE-scope:** ingen src-endring, ingen spec-endring, ingen endring i ingest-spec-vakten.
- **Gate:** ingen.
- **TDD-plan:** testen er selv vakten; RØD-bevis via mutert spec-KOPI i `tmp_path`
(parametrisert mot kopien, aldri mot `shared/`): (a) slett fila → rød; (b) injiser
rammeverksnavn (MAF/Claude/Anthropic/Azure/…, samme navneliste som ingest-vakten) → rød;
(c) fjern et konsumert §12-felt → rød. Innhold: (1) fil-eksistens + struktur-markører
(`## 1.``## 12.`, `### Step 1``### Step 8`, «MUST»); (2) framework-nøytralitet;
(3) §12-dekning for feltene DENNE koden konsumerer (`decision`, `rationale`, `id`,
`proposal_features`, `affected_codes`, `measure_type`, `claimed_saving_nok`, `description`,
IR-feltene `project_id`/`measure`/`affected_items`/`code`/`quantity`/`unit_cost`/`assumptions`,
golden-feltene `outcome`/`validates`/`nominal_feasible`/`p10`/`p50`/`p90`,
learning-surface-feltene, `type`, vokabular-verdiene `approved`/`rejected`/
`approved_with_adjustment`). Feltlisten valideres mot review-paritet §-vedlegget
(spec-konformitetsagentens konsumliste) i sesjonen. Presisjons-lærdom fra
detach-stikkprøven av ingest-vakten (review-paritet §3): substring-hvor-som-helst-assertion
gjør at et felt som også nevnes i løpeteksten ikke detacher ved ren tabell-fjerning —
dokumentér samme begrensning i method-spec-vakten, eller scope assertion til
§12-tabellblokken der det er praktisk.
- **Nøkkelantakelse (+test):** markørene i dagens method-spec matcher listen — testes FØRST
ved å kjøre vakten grønn mot uendret `shared/method-spec.md` før mutasjons-parametrene.
- **Verifisering:** `uv run pytest tests/test_method_spec_loadbearing.py` grønn; mutasjons-
parametrene røde mot kopi; full gate. **VIKTIG koordinering:** amendment-utkastet (§5.1) er
konstruert mot MAFs vakt-design (presence-asserts, ikke forbud mot nye seksjoner) — bygg
vakten HER med samme presence-semantikk, så en senere amendment-pull ikke gjør den rød.
### C2.5 Inbox-herding + SDK-versjonsvakt (C-F7, C-N3) — UENDRET + guard-G2-vurdering
- **Mål:** inboxen slutter å være en uvalidert injeksjonsflate; SDK-attributt-premissene får
en vakt som tvinger bevisst re-verifisering ved oppgradering.
- **Scope (filliste):** `src/portfolio_optimiser_claude/inbox.py`, `pyproject.toml`,
`tests/test_step7_async_loop_loadbearing.py` (utvidelse), ny `tests/test_sdk_version_guard.py`.
- **IKKE-scope:** guard-*wiring* (kun vurderingsnotat, se under); endring i tolerant-lasting-
semantikken for øvrige felter; `experience.py`.
- **Gate:** ingen.
- **TDD-plan:** RØD: inbox-fil med `decision: "hva-som-helst"` når ALDRI storen — reviewens
kjørte C-F7-bevis blir fixturen (detach-punkt: fjern vokabular-sjekken → den entrer → rød).
Vokabular på fil-laget = §4.2-settet {approved, rejected, approved_with_adjustment}; ukjent
→ SKIP, aldri raise (tolerant-regelen består). RØD: rationale > konfigurerbart tak →
fail-fast med presis feil (aldri stille kutt); RØD: antall filer > tak → fail-fast. RØD
(R-6): `VerdictDocument.id` med path-traversal (`../../escaped`) → avvist/sanert FØR
`write_verdict` skriver (detach id-grammatikken → fil skrives utenfor inbox → rød;
sikkerhetsagentens kjørte bevis blir fixturen; speil `_ID_RE` fra `ingest.py` eller
`promotion._filename_token`-saneringen). RØD:
versjonsvakt mot fake-versjon (monkeypatch `importlib.metadata.version`) — melding skal
navngi `sdk_client.py`-premissene som må re-verifiseres. Pin: **`claude-agent-sdk>=0.2.111,<0.3`**
(sdk-review 2026-07-16: alle attributt-premisser verifisert mot installert 0.2.110 OG mot
releases t.o.m. nyeste 0.2.120 — ingen brudd; 0.2.111 bærer NDJSON-/content-parsing-fikser
som treffer nettopp denne klientens leseløkke, se review-paritet §2). Sesjonen re-kjører
attributt-verifiseringen mot versjonen `uv sync` faktisk resolver.
I tillegg (fra R4/R5, test-detach + sdk-review): (5) bind `sdk_client._complete_async`-
meldingshåndteringen offline med en syntetisk strøm (fake_query som yield-er
AssistantMessage/ResultMessage-verdier: tekst-aggregering, error-fail-paths,
usage/kost-ekstraksjon, `_total_tokens`-fail-closed, `max_budget_usd_per_call<=0`-guarden
— i dag kjøres ingenting av dette i suiten); (6) rett `test_sdk_isolation`-docstringen som
hevder `--system-prompt ""`-serialisering testkroppen ikke beviser (grønn-men-død for
akkurat den claimen — ærligst å omformulere docstringen; å binde transport-serialisering
ville lese SDK-privat API og gjeninnføre F11-skjørhet).
- **Guard-G2-vurdering (leveranse i sesjonen, ikke wiring):** kort avsnitt i commit-meldingen/
STATE om `scan_output`-depth over `rationale` er verdt en senere additiv økt —
C2.5-allowlisten er den nødvendige delen (guard-planen §4 G2). Markørlinjen i STATE
oppdateres hvis vurderingen endrer trigger-bildet.
- **Nøkkelantakelse (+test):** step7-suitens tolerant-lasting består uendret — kontrolltest:
eksisterende `test_non_json_broken_and_incomplete_files_are_skipped` forblir grønn.
- **Verifisering:** nye tester grønne + detach → rød; step7-suiten uendret grønn; full gate.
### C2.0 Steg-7 kjøresti-inngang (C-N2) — UENDRET
- **Mål:** en skipbar inngang komponerer §5-sekvensen (merge inbox → seed → fold → run), så
README-ens inbox-avsnitt er sant om en leverbar sti.
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/run.py` (offline-testbar
komposisjonsfunksjon `compose_run_context(bundle_dir, inbox_dir=None, k=...)` + tynn CLI
`python -m portfolio_optimiser_claude.run --bundle/--inbox/--out` som gjenbruker
contracts/meter/artifacts), ny `tests/test_run_entrance_loadbearing.py`, README-avsnittet
om inboxen (peker på ny inngang).
- **IKKE-scope:** `run_s10.py` (byte-urørt fasit); ny live-kjøring (CLI testes kun med
ScriptedClient; SDK-klienten wires men eksekveres ikke i suiten); portefølje (K2).
- **Gate:** ingen.
- **TDD-plan:** RØD: dom droppet i inbox-mappe → inngangens komponerte kontekst bærer dommens
markør (detach-punkt: fjern merge-kallet i komposisjonen → rød); kontroll: tom/manglende
inbox → base-kontekst uendret; RØD: inngangen skriver ALDRI til inboxen (byte-sammenligning
før/etter, §5-rolledelingen); RØD (fra R3, test-detach-coverage): budsjett-stopp under
kjøring via den NYE inngangen → stopp-artefaktene persisteres + strukturert exit
(ScriptedClient + lavt tak — binder orkestrerings-grenen `run_s10.py:99-114` aldri fikk
bundet; fasit-stien forblir byte-urørt, bindingen skjer på den nye stien).
- **Nøkkelantakelse (+test):** komposisjonen gjenbruker `fold_experience`/
`merge_inbox_into_store`/`seed_store_from_bundle` uendret — ingen ny søm, kun wiring;
testes ved at ingen eksisterende testfil endres.
- **Verifisering:** ny testfil grønn + detach → rød; `grep -n "inbox" README.md` viser claim
som matcher en skipbar sti; full gate.
### C2.6 Validator/IR finitthets- og gyldighets-hardening (R-2 primær) — NY, BYGGBAR NÅ, HØY VERDI
- **Mål:** den obligatoriske validatoren kan ikke lenger settes ut av spill av ikke-finite
eller ugyldige tall — `Infinity` klarerer ikke porten vakuøst lenger.
- **Scope (filliste):** `ir.py` (`allow_inf_nan=False` på de numeriske feltene, eller eksplisitt
finitthetssjekk av `quantity`/`unit_cost`/`claimed_saving_nok` + bånd-endepunkter; forby
negative bånd-verdier), `contracts.py` (`min_length` på modell-id-verdier — tom-streng-
bug), `loop.py` (fjern/dokumentér den døde `check_turn_safety_net`-vokteren `:111` — eller
gjør §8s turn-safety-net faktisk nåbar), `tests/test_ir.py`, `tests/test_validator.py`,
`tests/test_contracts.py`.
- **IKKE-scope:** kostbaseline (C4.0); nominal-gate (C2.7, D-A-gated) — dette er ren
finitthets-/gyldighets-hardening, ikke spec-strammingen.
- **Gate:** ingen. **Golden uendret** (golden-tallene er finite).
- **TDD-plan:** RØD: `unit_cost: Infinity` → IR-konstruksjon eller validering avvises (i dag
`ValidatedProposal(validates=True, p90=inf)` — reviewens kjørte R-2-bevis blir fixturen;
detach-punkt: gjeninnfør `allow_inf_nan=True` → inf validerer → rød); RØD: `assumptions`-bånd
med `Infinity`/negativ endepunkt → avvist; kontroll: NaN avvises fortsatt (regresjon);
kontroll: golden-bundelens finite tall validerer uendret; RØD: tom-streng modell-id →
ModelMapContract avviser.
- **Nøkkelantakelse (+test):** ingen golden-/fixture-tall er ikke-finite — VERIFISERT
(golden.json + alle fixtures er finite); bindes ved at `test_bygg_energi_mikro` forblir grønn.
- **Verifisering:** nye tester grønne + detach → rød; golden uendret; full gate.
### K2.9 Ingest-robusthet (R-3/R-4/R-5/R-7) — NY, BYGGBAR NÅ
- **Mål:** ingest krasjer ikke midt i materialisering på tomme/BOM-/malformerte kilder, og
etterlater aldri en delvis bundle.
- **Scope (filliste):** `ingest.py` (R-3: vokt tom `rows` med fail-fast FØR disk-mutasjon —
aldri delvis bundle; R-4: les CSV med `utf-8-sig`; R-7 valgfritt: `LIMIT max_rows+1`/
`fetchmany` for SQL + streaming-tell for CSV), `okf.py` (R-5: eksplisitt beslutning for
malformert-men-eksisterende lenket concept-fil — tolerér-og-hopp ELLER dokumentert fail-fast,
ikke stille asymmetri), nye tester + evt. golden-fixture-tillegg (repo-lokalt, ikke `shared/`).
- **IKKE-scope:** ny kildefamilie (K14K16, D-B-gated); endring i eksisterende ingest-goldens
(byte-fasit).
- **Gate:** ingen.
- **TDD-plan:** RØD: tom CSV-ekstraksjon → fail-fast MED bundle uendret (detach fail-fast-
vakten → delvis bundle + krasj → rød; kontroll: byte-sjekk at ingen fil ble skrevet ved feil);
RØD: BOM-CSV → header `code` ikke `code` (detach `utf-8-sig` → korrupt header → rød); RØD:
malformert lenket fil → valgt semantikk bevist (hopp-og-fortsett: resten av bundelen
navigeres; ELLER fail-fast: presis feil) — detach → motsatt oppførsel → rød.
- **Nøkkelantakelse (+test):** eksisterende ingest-goldens er upåvirket (ingen tom/BOM/
malformert fixture i dem) — bindes ved at begge ingest-golden-suiter forblir grønne.
- **Verifisering:** nye tester grønne + detach → rød; ingest-goldens uendret; full gate.
### K4 Closed-loop to-kjørings-simulering (R-1 — §11-raden «Closed loop»; MAF-paritet rad 6)
- **Mål:** §11s siste udekkede rad (utover C1.1) lukkes: en skriptet to-kjørings-simulering
beviser at persona-markøren krysser kjøringer VIA promotering — og IKKE krysser uten.
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/simulation.py` (deterministisk
to-run-driver over `run.py`-komposisjonen + persona-artefakten + promotion; ScriptedClient;
null modellkall), ny `tests/test_simulation_loadbearing.py`.
- **IKKE-scope:** endring i loop/promotion/persona-primitivene; live-kjøring; portefølje.
- **Gate:** ingen (forutsetter C2.0 — komposisjonsinngangen er kjøretøyet).
- **TDD-plan:** RØD: kjøring A → persona-dom (markør fra `shared/skills/expert-reviewer/`-
artefakten) → promotering → kjøring B med FERSK store: markøren MÅ nå Bs hypotese-prompt
(detach-punkt 1: fjern promoterings-steget → markøren uteblir → rød). RØD (symmetrisk
kontroll): UTEN promotering krysser markøren ALDRI (detach-punkt 2: la konteksten rendre
verdict-laget → markøren lekker → rød — gjenbruker verdict-eksklusjonens invariant på
simulerings-nivå). Honesty-krav: modulen docstring-merkes som skriptet stand-in (§1).
- **Nøkkelantakelse (+test):** persona-artefaktens `marker` er substring av `rationale`
(spec §4.3) — allerede bundet av `test_persona_skill_loadbearing.py`; simuleringen
gjenbruker den, ingen ny persona-kilde.
- **Verifisering:** ny testfil grønn + begge detach-punkter røde; full gate.
### K1 Besparelses-hovedbok + mål-kontrakt (paritetsrad 23; Fase-1-analog)
- **Mål:** D7 får en typet hovedbok over realiserte besparelser (fail-closed ekspert-gate,
provenance-stemplet) og en mål-kontrakt (absolutt beløp, hard/soft) med «stopp når mål
nådd»-logikk — distinkt fra token-budsjettet.
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/ledger.py` (typet `SavingsLedger`;
`realize` KUN med eksplisitt ekspert-argument + eksplisitt timestamp — samme
determinisme-regel som promotion §6; deterministisk JSON-persistens sort_keys/indent 2/LF),
ny `goals.py` (`GoalContract`: absolutt mål, hard/soft; fail-fast konstruksjon §10-stil),
nye `tests/test_ledger_loadbearing.py` + `tests/test_goals.py`.
- **IKKE-scope:** prosent-mål-baseline (D-E-gated — kontrakten reserverer feltet med
eksplisitt `NotImplementedError`-nekt + TODO-peker til D-E, aldri stille semantikk);
portefølje-wiring (K2); verdirapport (K11).
- **Gate:** ingen for absolutt-delen. **Prosent-delen: D-E.**
- **TDD-plan:** RØD: `realize` uten ekspert-stempel → nekt (detach-punkt: fjern gate-sjekken
→ uekspederte «realiserte» tall entrer boken → rød); RØD: hovedboken akkumulerer og
persisterer deterministisk (to identiske sekvenser → byte-identisk fil); RØD: hardt mål
nådd → strukturert stopp-signal (typet event, aldri stille); soft mål → flagg uten stopp;
RØD: prosent-mål forsøkt konstruert → eksplisitt nekt med D-E-melding.
- **Nøkkelantakelse (+test):** ledger-semantikk kan speiles på kapabilitetsnivå fra
MAF-planens beskrivelse (typet store, fail-closed realize, dimensjonsfri sum-nøkkel mot
dobbelttelling) uten MAF-kode — RISIKO: detaljsemantikk kan divergere fra MAF; markeres i
docstring som stack-lokal kontrakt (delbarhet er foreslått beslutningspunkt i briefen).
Test på antakelsen: dimensjonsfri sum-nøkkel bindes med en to-dimensjoner-samme-prosjekt-
fixture der summen IKKE dobbelttelles.
- **Verifisering:** nye tester grønne + detach → rød; full gate.
### K2 Portefølje-kjøring (paritetsrad 4; Fase-1-analog)
- **Mål:** `run_portfolio` kjører N prosjekter sekvensielt fra en skjema-validert
referanse-konfig (per-prosjekt bundle-sti), med collect-per-prosjekt-resultater — den
kjørestien MAF fikk i Fase 1 og D7 aldri har hatt.
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/portfolio.py`
(`run_portfolio(projects, client, meter, ...)` + `PortfolioResult`), ny
`data/reference_projects.json` (eksempel-konfig; skjema-validert fail-fast i
`contracts.py`-stil), `contracts.py` (konfig-modell), mini-bundle-fixture repo-lokalt under
`tests/data/` (ALDRI i `shared/`), ny `tests/test_portfolio.py`.
- **IKKE-scope:** læringstreing på tvers (K3); concurrency (K18/D-D); goals/ledger-wiring
utover å ta imot dem som valgfrie argumenter; endring i `loop.py`-kjernen.
- **Gate:** ingen.
- **TDD-plan:** RØD: to-prosjekt-konfig → begge kjøres, resultatliste i konfig-rekkefølge
(deterministisk); RØD: malformet konfig (manglende bundle-sti) → fail-fast FØR første
kjøring (§10-disiplin; detach-punkt: fjern skjema-valideringen → kjøring starter på
ugyldig konfig → rød); RØD: feil i prosjekt 1 propagerer som typet feil — feilpolicyen
(collect-and-continue vs raise) dokumenteres eksplisitt som stack-lokalt valg inntil D-D
(default: raise, som «i dag kastes alt» — endres bevisst av K18 når D-D lander).
- **Nøkkelantakelse (+test):** loop-kjernen er re-entrant per prosjekt (fresh debate-state
per run — spec §3 Steg 3) — bindes med test: to sekvensielle kjøringer deler ingen
muterbar tilstand utover eksplisitt delt store.
- **Verifisering:** nye tester grønne + detach → rød; full gate.
### K3 Portefølje-læringssløyfe (S2.0-analog; paritetsrad 5)
- **Mål:** en dom på prosjekt k når prosjekt k+1s hypotese-prompt i samme porteføljepass —
delt store + verdict_dir tres gjennom `run_portfolio`.
- **Scope (filliste):** `portfolio.py` (delt store + `verdict_dir`-parameter tres gjennom;
inbox-merge FØR hver kjørings fold — gjenbruker C2.0-komposisjonen),
`tests/test_portfolio_learning_loadbearing.py`.
- **IKKE-scope:** semantisk henting (K17); multi-kandidat-nøkling (C3.2 — dagens
feature-nøkling brukes som den er, med kjent C-F5-begrensning notert).
- **Gate:** ingen (forutsetter K2 + C2.0).
- **TDD-plan:** RØD: dom om prosjekt k (droppet i verdict_dir mellom kjøringene / promotert
i ks bundle) → k+1s genererings-prompt bærer dommens id+markør (detach-punkt: fjern
store-/verdict_dir-trådingen gjennom porteføljen → rød); kontroll: tom store/inbox → k+1
uendret base-prompt.
- **Nøkkelantakelse (+test):** first-write-wins-merge (§4.2) gjør gjentatte merges over
porteføljepasset idempotente — bindes med dobbel-merge-test på porteføljenivå.
- **Verifisering:** ny testfil grønn + detach → rød; full gate.
### K5 Outbox-persistens (S2.1-analog; paritetsrad 7)
- **Mål:** hver kjørings forslag/utfall persisteres run_id-navngitt i en outbox-mappe, så
utestående dommer kan spores (K9) og live-artefakter fanges (K8) — sammenligningsprotokoll
§4.2-formen.
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/outbox.py` (gjenbruker
`artifacts.py`-serialisering; skriver `{run_id}-proposal.json` + `{run_id}-outcome.json`
med outcome-type, reason/percentiler, checker_verdict, provenance-referanse, verdict-id;
`run_id` PÅKREVD når outbox er satt — ingen wall-clock-default), `run.py` (valgfritt
`outbox_dir`/`run_id`), ny `tests/test_outbox_loadbearing.py`.
- **IKKE-scope:** ruting/pending (K9); varsling (K10); endring i `artifacts.py`-formatene
(S10-fasiten leses av dem).
- **Gate:** ingen.
- **TDD-plan:** RØD: kjøring med outbox_dir → filparet finnes, byte-deterministisk
(sort_keys/indent 2/LF; to kjøringer samme input+run_id → `diff` tom) (detach-punkt: fjern
outbox-skrivingen → rød); kontroll: uten outbox_dir skrives ingenting; RØD: outbox satt
uten run_id → fail-fast. Docstring siterer method-spec §2: systemet EIER output-laget
(rolledelingen §5 gjelder inbox/wiki, ikke systemets eget output-lag).
- **Nøkkelantakelse (+test):** `ValidatedProposal`/`Rejection` er JSON-serialiserbare via
eksplisitt mapping — testes FØRST med begge utfallstyper (artifacts.py gjør alt dette i
dag for run-artefaktene; antakelsen er at samme mapping bærer outcome-formen).
- **Verifisering:** ny testfil grønn + detach → rød; full gate.
### C3.5 Budsjett-guard (C-N4) — VIDEREFØRT, løftet fra «valgfri» til paritetskrav (rad 16/31)
- **Mål:** pre-call-guard (nekt kall når rest-tak < 0) + eksplisitt run-total USD-grense over
SDK-klientens akkumulerte kost — på plass FØR enhver fremtidig live-kjøring.
- **Scope (filliste):** `budget.py` (pre-call-sjekk-primitiv + run-total USD-tak i meteren),
`loop.py` (guard-kall FØR `client.complete`), `sdk_client.py` (eksponer akkumulert
`total_cost_usd` — leses allerede fra ResultMessage), `tests/test_budget.py` (+utvidelse).
- **IKKE-scope:** portefølje-nivå-tak (K19, D-D-gated); endring i post-charge-semantikken
(består som belte-og-seler).
- **Gate:** ingen.
- **TDD-plan:** RØD: mock-klient som teller kall — når rest < neste kall er kallet ALDRI
gjort (detach-punkt: fjern pre-call-guarden → kallet skjer → rød); RØD: run-total USD-tak
krysset → strukturert stopp (samme event-form som token-stoppen, §8); kontroll:
usage-fail-closed-testen (`test_budget`) uendret grønn.
- **Nøkkelantakelse (+test):** `ResultMessage.total_cost_usd` akkumuleres pålitelig per kall
på 0.2.110 (verifisert i sdk-review 2026-07-16, review-paritet §2) — versjonsvakten fra
C2.5 dekker drift.
- **Verifisering:** nye tester grønne + detach → rød; full gate.
### K6 Kostnadssimulering før kjøring (S3.6-analog; D-I pkt. 3 MÅ-krav; paritetsrad 18)
- **Mål:** operatøren ser estimert kost for en (portefølje-)kjøring FØR start — what-if over
model_map (Claude-modeller × effortnivåer), prisdata som skjema-validert konfig.
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/costsim.py` (funksjons-API +
`python -m portfolio_optimiser_claude.costsim`; deterministisk øvre-grense-estimat fra
portefølje-form × tak — merket ESTIMAT i output), ny `data/pricing.example.json` (skjema:
kr-eller-USD/Mtok per modell-id, PÅKREVD kilde+dato-felt; fail-fast ved manglende/ugyldig
pris — aldri hardkodet), `contracts.py` (pris-skjema), nye tester.
- **IKKE-scope:** live prisoppslag (nett); faktisk modellkall; kvalitets-benchmarking
(kvalitetsutsagn kun som veiledning-med-kilde, D-I-regelen).
- **Gate:** ingen.
- **TDD-plan:** RØD: konfig uten pris for en modell i model_map → fail-fast «missing price
for <modell-id>» (detach-punkt: fjern pris-valideringen → estimat gjettes → rød); RØD:
deterministisk og skalerer med modell × effort (to modeller, samme portefølje →
forskjellig, reproduserbart estimat; detach effort-faktoren → identisk → rød); RØD:
grep-guard: ingen pris-literal i `costsim.py`-kildekode (pris MÅ komme fra konfig).
- **Nøkkelantakelse (+test):** eksempel-prisene kan kildeføres mot offisiell Anthropic-
prisside med dato (sdk-modelmap-reviewens kilder gjenbrukes); IKKE VERIFISERT utover
review-datoen — derfor kilde+dato-felt i skjemaet, så stale priser er synlige, aldri stille.
- **Verifisering:** nye tester grønne + detach → rød; `uv run python -m
portfolio_optimiser_claude.costsim` gir estimat-tabell uten nettverk; full gate.
### K7 SDK-/API-preflight (S4.1-analog, SDK-nativ; paritetsrad 20)
- **Mål:** alt som KAN valideres uten et modellkall valideres før operatøren betaler for ett.
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/preflight.py`
(`python -m portfolio_optimiser_claude.preflight --profile anthropic`): env-kontrakt
(`ANTHROPIC_API_KEY` satt + ikke-placeholder-form — nøkkelVERDIEN valideres aldri online),
model_map-konsistens (profil finnes, `default` finnes, modell-id-form), placeholder-nekt
også i `resolve_model`-stien, SDK-importerbarhet + bundlet CLI til stede
(claude-agent-sdk-premisset), budsjett-/stoppkontrakt satt. Nekt-liste med aksjonérbar
melding per mangel. Tester.
- **IKKE-scope:** faktisk API-kall (aldri — preflighten er selve grensen); Foundry/Azure
(SPEILES IKKE, rad 20-begrunnelsen).
- **Gate:** ingen.
- **TDD-plan:** RØD: manglende env-nøkkel → strukturert nekt med aksjonérbar melding
(detach-punkt: fjern env-sjekken → preflight «grønn» uten nøkkel → rød); RØD:
placeholder-modell-id i map → nekt; RØD: grep-guard ingen socket-/httpx-sti i modulen.
- **Nøkkelantakelse (+test):** «bundlet CLI til stede» kan sjekkes offline via SDK-pakkens
egne filer (verifiseres i sesjonen mot installert 0.2.110; hvis ikke mulig offline —
droppes sjekken eksplisitt med begrunnelse i docstring, aldri en nett-sjekk).
- **Verifisering:** nye tester grønne + detach → rød; `uv run python -m
portfolio_optimiser_claude.preflight` korrekt nekt/OK uten nettverk; full gate.
### K8 Live-kjørings-drill + artefakt-fangst (S4.2-analog; paritetsrad 21)
- **Mål:** en eventuell fremtidig live-kjøring (M2-analogen, operatør-gated) er ferdig-rigget:
alt bygges, artefakter fanges, drillen er øvd offline — uten ett modellkall.
- **Scope (filliste):** `run.py` (`--live-dry-run`: last kontrakter, kjør preflight, bygg
klient-konfig, valider budsjett, skriv kjøringskonfig-logg (modell-id, parametre, tak —
sammenligningsprotokoll §4.3-form) til outbox, STOPP før første modellkall), tester med
kall-tellende mock.
- **IKKE-scope:** selve live-kjøringen (M2-analog, operatør); endring i preflight/outbox.
- **Gate:** ingen (forutsetter K5 + K7).
- **TDD-plan:** RØD: dry-run mot kall-tellende mock-klient → NULL kall skjedde (detach-punkt:
fjern stopp-punktet → kall telles → rød); RØD: artefakt-settet (konfig-logg + preflight-
resultat) komplett og deterministisk i outbox.
- **Nøkkelantakelse (+test):** klient-konstruksjon uten kall er gratis og nøkkel-fri
(CLAUDE.md-verifisert SDK-premiss: import og konstruksjon fungerer uten API-nøkkel) —
bindes med test som konstruerer klienten i suiten (uten nøkkel).
- **Verifisering:** nye tester grønne + detach → rød; full gate.
### K9 HITL verdict-ruting + pending-sporing (S5.1-analog; paritetsrad 22)
- **Mål:** operatøren ser hvilke forslag som venter på dom og hvem som skal dømme — ren
fil-basert id-join outbox↔inbox.
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/hitl.py` (pending-registry =
outbox-forslag uten matchende inbox-/promotert dom, id-join på verdict-id; ruting-konfig
`nøkkel → ekspert` skjema-validert fail-fast — nøkkelen er en konfig-streng nå,
dimensjonskatalog-integrasjon kommer med K13), CLI `python -m portfolio_optimiser_claude.hitl
pending|route`, tester.
- **IKKE-scope:** varsling (K10); web-UI; skriving til inbox (rolledelingen §5 — hitl LESER
begge lag).
- **Gate:** ingen (forutsetter K5).
- **TDD-plan:** RØD: forslag i outbox uten dom → listes utestående; dom lander i inbox →
forsvinner fra pending (detach-punkt: fjern id-joinen → dømt forslag listes fortsatt →
rød); RØD: malformet ruting-konfig → fail-fast; RØD: hitl skriver aldri (byte-sammenligning
av outbox+inbox før/etter).
- **Nøkkelantakelse (+test):** outbox-outcome bærer verdict-id-en å joine på (K5-formen) —
bindes i K5s testfil og gjenbrukes her.
- **Verifisering:** nye tester grønne + detach → rød; full gate.
### K10 Varsling/Notifier (S5.2-analog; paritetsrad 23)
- **Mål:** leverbare varslings-implementasjoner uten å bryte ingen-stille-egress.
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/notify.py` (`Notifier`-protokoll +
`console`/`file`/`webhook`; webhook krever eksplisitt per-kjøring opt-in-flagg — mirror av
ingest-spec §8-mønsteret («flagget er et run-argument, aldri konfig-felt») — + injiserbar
transport, canned i tester, null socket i suiten), `run.py`/`hitl.py` (opt-in seam), tester.
- **IKKE-scope:** e-post/Teams-adaptere; retry-politikk; kø.
- **Gate:** ingen. **Koordineringspunkt (kapabilitetsnivå):** MAF S5.2 eksekveres nå — les
MAF-STATE/plan-oppsummeringen (aldri koden) før sesjonen og speil kapabilitetsvalgene
(protokoll-form, webhook-opt-in, socket-fri suite) der de er beskrevet på plan-nivå.
- **TDD-plan:** RØD: webhook uten opt-in → nekt fail-fast (detach-punkt: fjern opt-in-sjekken
→ transporten kalles → rød); RØD: canned transport mottar korrekt payload (struktur, ikke
prosa); RØD: grep-guard ingen socket-sti utenfor den injiserbare seamen.
- **Nøkkelantakelse (+test):** payload-formen kan holdes stack-lokal (ingen delt spec for
varsling) — divergens mot MAF er akseptert og dokumentert i docstring.
- **Verifisering:** nye tester grønne + detach → rød; full gate.
### K11 Verdirapport per kjøring (S5.4-analog; D-I pkt. 2; paritetsrad 25)
- **Mål:** hver kjøring/porteføljepass produserer en deterministisk verdirapport — modellert →
ekspert-korrigert → realisert, målprogresjon, tallfestet læringseffekt, kost-mot-verdi —
uten ett modellkall.
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/valuereport.py` (ren projeksjon
over ledger (K1) + outbox (K5) + costsim-estimat (K6); JSON + markdown-render, byte-stabil
sort_keys/indent/LF), `run.py`/`portfolio.py` (opt-in `--value-report`), tester + committede
fixtures.
- **IKKE-scope:** dashboard; live-oppdatering; modellkall; nivå-2-README-påstander (kommer
FØRST når beviset finnes — D-I pkt. 1).
- **Gate:** ingen (forutsetter K1 + K5 + K6).
- **TDD-plan:** RØD: to kjøringer med økende godkjenningsandel → læringseffekt-metrikk stiger
og gap-krymping rapporteres (detach-punkt: fjern gap-beregningen → flat/feil → rød); RØD:
prosjekt uten dom → «realisert» tomt/umerket, ALDRI lik modellert (detach ærlighets-grensen
→ realisert=modellert → rød); RØD: byte-determinisme (samme ledger+outbox → identisk
rapport, `diff`).
- **Nøkkelantakelse (+test):** ledger+outbox bærer alt rapporten trenger — rapporten er ren
projeksjon, ingen ny tilstand; testes ved å bygge rapport fra committede fixtures uten
kjøring.
- **Verifisering:** nye tester grønne + detach → rød; full gate.
### K12 CLI-paritet + dokumentsync + D-H-oppskrift (S5.3-analog; paritetsrad 24) — SISTE ugatede
- **Mål:** operatøren driver ALT bygget (kjøring, portefølje, inbox, outbox, ledger, goals,
pending, costsim, preflight, verdirapport) fra kommandolinja; README/extending.md/CHANGELOG
påstår nøyaktig det koden gjør (§1); D-H-oppskriften leveres som dokument.
- **Scope (filliste):** `run.py` (samlende CLI-flater: `--bundle/--inbox/--outbox/--verdict-dir/
--goals/--ledger/--portfolio/--value-report`), `README.md`, `docs/extending.md`,
`CHANGELOG.md`, nytt `docs/oppskrift-kunnskapsbase.md` (D-H pkt. 1: dokumentert team-prosess,
ærlig 12-ukers-forventning; IKKE veiviser — B9 er FORKASTET i D-H), CLI-tester.
- **IKKE-scope:** nye kapabiliteter; fabrikk-/demo-sti (T0-gated — oppskriften peker på den
som fremtidig, merket ubygd).
- **Gate:** ingen (forutsetter at K1K11-kjeden er landet — ellers krymper scope ærlig).
- **TDD-plan:** RØD: CLI-kjøring med goals+ledger på fixtures → mål-stopp observerbar i
output (detach-punkt: koble goals fra CLI-stien → stopp uteblir → rød); RØD:
ærlighets-grep i testform: README-claims-listen (inbox, portefølje, CLI) matcher skipbare
stier (testen leser README og asserter at hver dokumentert kommando finnes i CLI-hjelpen).
- **Nøkkelantakelse (+test):** ingen — ren wiring + docs.
- **Verifisering:** CLI-tester grønne; manuell `uv run python -m portfolio_optimiser_claude.run
--help`-røyk dokumentert i STATE; full gate.
## 4. Gatede sesjoner (startes IKKE før gaten er utløst — eksakt utløser per sesjon)
> Felles mal for D-A-bølgen (uendret fra gammel plan): amendment lander i commons →
> koordinert subtree-pull i BEGGE repo → BEGGE suiter kjøres → failing test først
> (review-moteksemplene ER fixturene) → impl → detach-bevis → full gate → golden uendret
> (eller koordinert re-frosset i commons FØRST).
### C2.7 Validator-stramming (C-F2) — **Gate: D-A pkt. 1 godkjent + commons-pull utført**
Uendret fra gammel plan §3: (a) strukturell blokk `claimed > nominal_feasible` → `Rejection`;
(b) IR-invariant `low ≤ unit_cost ≤ high` (Pydantic `model_validator`). Premiss VERIFISERT
2026-07-10 (golden- og fixture-kompatibel: alle ikke-tomme bands omslutter unit_cost;
golden-claim 30 000 ≤ 90 000). TDD: moteksempel #1 (claim 100k/nominal 90k/band [0.70,1.40])
→ MÅ bli Rejection; band [1.8,2.2] om unit_cost 1.0 → ValidationError; detach nominal-blokken
→ rød. Filer: `validator.py`, `ir.py`, `tests/test_validator.py`, `tests/test_ir.py`;
`test_bygg_energi_mikro.py` uendret grønn.
### C2.8 OKF `/`-lenke-mapping (C-F4) — **Gate: D-A pkt. 3 godkjent + commons-pull utført**
Uendret fra gammel plan §3: ledende `/` mappes til bundle-rot i `navigate_bundle`;
boundary-sjekken består fail-closed. TDD: `](/tiltak.md)` → navigeres (detach → rød);
`](/../escape.md)` → fortsatt skippet. Filer: `okf.py`, `tests/test_okf.py`. Merk: MAF-siden
mangler fortsatt egen F4-byggsesjon — flagget står (operatøren legger den til der).
**Toolkit-kobling:** lander T0/K20 FØR D-A pkt. 3, flyttes `/`-mappingen inn i okf-core og
C2.8 blir en konsum-oppgradering — sesjonene merges da eksplisitt.
### C3.2 Per-verdict seeding (C-F5) — **Gate: D-A pkt. 4 godkjent + commons-pull utført**
Uendret fra gammel plan §3: seed leser features fra verdict-filas egen frontmatter (nye
valgfrie felt `affected_codes`/`measure_type`/`claimed_saving_nok`; fallback = dagens
nøkling); `promote` skriver feltene; multi-kandidat-fixture repo-lokal. TDD: to kandidater i
én bundle → dom om B når ALDRI As prompt via retrieval på As features (detach → rød);
eksisterende step1/step7/step8 uendret grønne (fallback). **R-8 (count-ærlighet, foldet inn):**
`seed_store_from_bundle` skal returnere FAKTISK lagret antall (eller logge drops), ikke
fil-antallet — RØD: to seed-filer uten `verdict_id`, ulik decision → i dag `seeded=2` men
`len(store)==1`; med per-verdict-nøkling blir de distinkte, og count matcher (detach nøklingen
→ count/antall divergerer igjen → rød). Filer: `experience.py`, `promotion.py`,
loadbearing-testene, ny fixture.
### C4.0 Kostbaseline-forankring (C-F3) — **Gate: D-A pkt. 2 godkjent + commons-pull utført**
Uendret fra gammel plan §3: baseline-projeksjon i bundle (`cost-baseline.json`,
commons-format) + fail-closed avstemmings-stage i `validate_proposal` (ukjent kode →
Rejection; utenfor toleranse → Rejection; toleranse konfig; baseline-argument VALGFRITT =
dagens oppførsel, men kjøresti-inngangen (C2.0/`run.py`) SETTER den når fila finnes). TDD:
F3-moteksemplet (diktet kode, 10 MNOK) → Rejection «unknown cost code» (detach → validated →
rød); golden-bundelen (uten baseline-fil) validerer uendret. Filer: `validator.py`,
`okf.py`/`ir.py` (loader), commons-fixture, nye tester. **MÅ være grønn før M2-analogen.**
### K13 Innholdsmodell + bibliotek + dimensjonskatalog + summary-tier (S3.5-analog) —
**Gate: commons-amendmenten (D-F/D-G-utkastet 2026-07-14) operatør-godkjent, committet i
commons OG pullet hit (koordinert med MAF; begge suiter grønne etter pull)**
- **Scope:** bygg fra den nye spec-teksten (aldri fra utkastet før det er landet):
(1) `dimension_catalog.py` — §13.3-katalogen, skjema-validert fail-fast (id, label,
allowed_measure_types, allowed_code_prefixes) + scoping-gate; eksempel-katalog under
`data/`; (2) `ingest.py` — `library`-kildefamilien (4a/5a: `library-{id}.md`, kuratert
frontmatter + additivt provenance-lag, kildebelegg-håndheving fail-fast ved tom/manglende
`sources`); (3) `okf.py` — summary-tier-render for bibliotek-typene (description-linje
default; full body kun for deterministisk pre-run-utvalg — kandidatens dimensjon); (4) ny
golden-case `examples/ingest-golden-library/` KUN hvis commons shipper den (fasit eies der).
- **TDD:** RØD per amendmentens fire detach-punkter (S3.5-malen): ugyldig katalog → fail-fast;
materialisert bibliotek-fil når prompten via `bundle_context` (detach → markør borte → rød);
summary-tier gir én linje, ikke fulltekst (detach → fulltekst-stuffing → rød);
separasjons-kontroll: bibliotek-fil når ALDRI prompten via dom-kanalen (folden).
- **Nøkkelantakelse (+test):** default uten bibliotek-filer er byte-identisk med dagens
render (amendment §3.2s garanti) — bindes med regresjonstest på eksisterende bundle FØR ny
funksjonalitet skrives. C1.1-vakten skal forbli GRØNN gjennom pullen (amendment §5.1 er
konstruert for det — verifiseres som pull-ens første sjekk).
- **Verifisering:** nye tester grønne + detach → rød; `test_bygg_energi_mikro` + begge
ingest-goldens uendret; full gate; sammenligningsprotokoll-kjøring i BEGGE repo.
### K14 MCP-ingest-konnektor (S2.2-analog) — **Gate: D-B besluttet + ingest-spec-amendment
(mcp-familien) landet i commons + pullet hit**
SDK-nativ analog: kildefamilie `mcp` i manifestet; test-fixture = in-process MCP-server via
SDK-primitivet `create_sdk_mcp_server`/`@tool` (av-demoer extension-pointet uten socket).
Per-run-grant: eksplisitt flagg (ingest-spec §8-mønsteret — run-argument, aldri manifest-felt).
TDD: manifest med `type: mcp` uten grant → `IngestError` (detach → rød); golden-materialisering
mot fixture-server byte-deterministisk; verdict-reservasjonen gjelder også mcp-familien.
Nøkkelantakelse (testes FØRST i sesjonen): SDK-MCP-serveren kan drives i-prosess uten socket —
hvis ikke, subprosess-fixture med eksplisitt merking. OBS: `ingest.py` er i dag SDK-fri —
mcp-konnektoren legges i EGEN modul (f.eks. `ingest_mcp.py`) så ingest-kjernens renhet består
(detach-vaktene i `test_ingest_loadbearing` urørte).
### K15 Dokument-konnektor PDF (S2.3-analog) — **Gate: D-B besluttet (inkl. pypdf-dep-valget)
+ ingest-spec-amendment (doc-familien) landet + pullet**
Tekst-ekstraksjon per side, fenced-verbatim-render (gjenbruk http-regelen fra spec §5),
`max_rows`-cap, fail-fast på ikke-tekst-PDF; DOCX utsatt (D-B). TDD: golden byte-determinisme;
cap-overskridelse → feil, aldri trunkering; pin pypdf-versjon (golden fanger drift).
### K16 http-kilde + konnektor-herding + guard-G1 (S2.4-analog) — **Gate: D-B besluttet MED
http/live-kilde i scope (i dag eksplisitt utenfor D7-roadmap)**
Bygger http-familien (i dag avvist fail-fast — det er selve utløseren som endrer det):
`base_url`/`credential_ref` per ingest-spec §4, nettverks-opt-in per §8 (fail-fast uten flagg
— load-bearing §11-raden «Network gate»), timeout + feilkategorisering mot injisert transport
(aldri live), OG guard-planens G1-wiring i samme økt: `prepare_input` → deterministisk render
→ `screen_output` FØR skriving av konseptfila; FAIL_SECURE → ikke skriv, alert med gate-kode
uten innhold. Guard-dep pinnes + versjonsvakt (samme disiplin som C2.5). TDD: per feilmodus
canned transport → presis IngestError; uten opt-in → nekt (detach → rød); injeksjons-fixture →
fila skrives ALDRI (detach guard-gaten → payload lander i bundelen → rød — guard-planens §7).
STATE-markørlinjen oppdateres `planned` → `integrated` med detach-bevis.
### K17 Semantisk henting (S3.1-analog) — **Gate: D-C besluttet OG C-P1 avklart i D-A-bolken
(amendment av ranking-regelen ELLER re-scoping til strukturelle features) + evt. commons-pull**
Scope avhenger av C-P1-utfallet: (a) amendment-varianten: `Retriever`-seam +
`HybridRanker` (strukturell + cosine over lagrede vektorer, delt format .npy+jsonl per D-C),
deterministisk fake-embedder i tester; (b) re-scoping-varianten: embeddings over strukturelle
features alene. Uansett: ny `semretrieval.py` SDK-fri, opt-in seam i `experience.py`, ingen
endring i `shared/`. TDD: syntetisk base der KUN den nye komponenten kan rangere riktig dom
øverst (detach → rød); determinisme ×2 kjøringer; fake-embedder bit-stabil.
`test_surface_text_never_contributes` består i variant (b); i variant (a) endres den KUN slik
amendmenten krever.
### K18 Concurrency/feilmodell (S3.3-analog) — **Gate: D-D besluttet (+ K2 landet)**
Bølge-modellen fra D-D-fasiten når den kommer: `run_portfolio(concurrency=k)`, snapshot per
bølge, deterministisk merge-barriere, collect-and-continue-feilpolicy (erstatter K2s
raise-default bevisst). TDD: concurrency=3 byte-identisk med concurrency=1 på 3-prosjekt-
fixturen (detach barrieren → rød over repetisjoner); injisert feil i prosjekt 2 → 1+3 bevart.
Nøkkelantakelse å teste FØRST: asyncio-samtidighet i én event-loop med ScriptedClient
(SDK-klienten er async — anyio-premisset verifiseres i sesjonen).
### K19 Kostnadsstyring på tvers (S3.4-analog) — **Gate: D-D besluttet (deler feilpolicy)**
`PortfolioBudget` (globalt tak + per-run-tak) over C3.5-primitivene; spend-persistens
(deterministisk JSON, eksplisitt stamp); oppstartsnekt når rest < minimum per kjøring. TDD:
globalt tak krysses midt i passet → strukturert stopp med fullførte runs bevart (detach → rød);
pre-call-guard nekter kallet (kall-tellende mock).
### K20 okf-toolkit-adopsjon inkl. skrive-halvdelen (D-G/T0) — **Gate: okf-toolkit-repoet
finnes, T1 (okf-core + formatprøve) er publisert/installerbar, OG operatøren har godkjent
koordinert A1+A2-migrering (toolkit-briefens §7: migreringene er koblet, ikke uavhengige)**
- **Scope:** importér `okf-core`; `okf.py`-lesekjernen delegerer/erstattes; skrive-halvdelen
(render_frontmatter/write_concept_file/link_in_index-ekvivalentene) blir tilgjengelig her —
D-Gs «minst like godt»-hovedgevinst; kjør formatprøven (conformance-testsettet) mot egne
bundler i suiten; `pyproject.toml` (+dep, pin + versjonsvakt samme disiplin som C2.5).
- **TDD:** RØD: formatprøven kjører i suiten og en bevisst malformert fixture-bundle feiler
minst én conformance-test; RØD: skrive-primitivene importérbare og brukt av promotion-stien
(detach → promotion faller tilbake/feiler → rød); eksisterende okf-purity-vakt beholdes
(okf-core er stdlib-only per toolkit-briefen §2 — verifiseres, ikke antas).
- **Bevisst avvik:** dette endrer «from spec alone» for formatlaget — operatør-besluttet
(D-G pkt. 2, revisjonspakke §0.2); dokumenteres i README/CLAUDE.md i samme sesjon.
- **Verifisering:** full gate; golden uendret; sammenligningsprotokoll-kjøring i BEGGE repo
(A1-migreringen skjer koordinert på MAF-siden).
### Guard G3 (`okf.import_bundle`) — **Gate: delt D-E-retning åpner bundle-utveksling**
Ingen egen sesjon planlegges før gaten: wiring-formen står i guard-planen §4 G3.
## 5. Avhengighetsgraf + anbefalt sekvens
```mermaid
flowchart TB
subgraph OPER["Operatør-gater (delt kø i HOVEDREPOET + amendment/toolkit)"]
DA["D-A (+C-P1)"]; DB["D-B"]; DC["D-C"]; DD["D-D"]; DE["D-E"]
AMD["commons-amendment D-F/D-G"]; T0[["T0 okf-toolkit (finnes ikke)"]]
end
C11["C1.1 spec-vakt"] --> C25["C2.5 inbox+SDK-vakt+R6"] --> C20["C2.0 kjøresti-inngang"]
C26["C2.6 validator-finitthet (R2)"]; K29["K2.9 ingest-robusthet (R3-R7)"]
C20 --> K4["K4 closed-loop-sim (R1)"]
C20 --> K2["K2 portefølje-kjøring"]
K1["K1 ledger+goals"] --> K2 --> K3["K3 portefølje-læring"]
K5["K5 outbox"] --> K8["K8 live-drill"]; K7["K7 preflight"] --> K8
K5 --> K9["K9 HITL-ruting"] --> K10["K10 notifier"]
K1 --> K11["K11 verdirapport"]; K5 --> K11; K6["K6 costsim"] --> K11
C35["C3.5 budsjett-guard"] --> K8
K3 --> K12["K12 CLI-paritet+oppskrift"]; K9 --> K12; K11 --> K12
DA --> C27["C2.7 validator"]; DA --> C28["C2.8 /-lenker"]; DA --> C32["C3.2 seeding"]; DA --> C40["C4.0 kostbaseline"]
AMD --> K13["K13 bibliotek+katalog+summary-tier"]
DB --> K14["K14 MCP-ingest"]; DB --> K15["K15 doc-PDF"]; DB --> K16["K16 http+guard-G1"]
DC --> K17["K17 semantisk henting"]; DA -. C-P1-avklaring .-> K17
DD --> K18["K18 concurrency"]; DD --> K19["K19 kost på tvers"]; K2 --> K18; C35 --> K19
T0 --> K20["K20 okf-core-adopsjon"]
C40 --> M2A{{"M2-analog: evt. ny live-kjøring (operatør + D-E + D6-ny-godkjenning)"}}
K8 --> M2A; DE --> M2A
```
**Anbefalt sekvens (ugatet først — åpningen C1.1 → C2.5 → C2.0 står, med review-begrunnelse
uendret):**
1. **C1.1 → C2.5 → C2.0** (vakt → herding → inngang)
2. **C2.6 → K2.9** (korrekthets-hardening — R-2 validator-omgåelsen har høyest verdi av alt
ugatet; kan tas rett etter C1.1 hvis ønskelig, uavhengig av C2.5/C2.0)
3. **K4** (closed-loop-sim — lukker §11-gapet R-1 tidlig)
4. **K1 → K2 → K3** (portefølje-fundamentet)
4. **K5 → C3.5 → K6 → K7 → K8** (outbox/kost/preflight/drill)
5. **K9 → K10 → K11 → K12** (HITL/varsling/verdirapport/CLI-sluttsync)
6. Ved D-A (når som helst, uavhengig av 15): **C2.7 → C2.8 → C3.2 → C4.0** etter koordinert
pull; ved amendment: **K13**; ved D-B: **K14 → K15 → K16**; ved D-C+C-P1: **K17**; ved
D-D: **K18 → K19**; ved T0: **K20**.
7. Vedlikehold når som helst: koordinert subtree-pull av de to docs-only commons-commitene
(ingen spec-endring — men kjør begge suiter etter pull likevel, protokoll-regelen).
**Koordineringspunkter med MAF (absolutte):** (a) etter HVER amendment-bølge: begge repo
puller subtree og BEGGE suiter kjøres — aldri én side alene; (b) golden re-fryses kun
koordinert i commons; (c) K10 speiler MAF S5.2 på kapabilitetsnivå (plan-lesing, aldri kode);
(d) K20/A1-migreringen er koblet på tvers av repoene (toolkit-brief §7); (e) C2.8-flagget om
manglende MAF-F4-byggsesjon står til operatøren har lagt den til der.
## 6. Operatør-milepæler (aldri autonome sesjoner)
- **M2-analog — eventuell ny live-kjøring:** krever ALT av: eksplisitt operatør-godkjenning
(D6: ny spend), D-E (stack-paritet for ekte kjøring — avgjør om D7 i det hele tatt skal
kjøre live igjen), C4.0 grønn (kostbaseline FØR ekte modell), C3.5 + K6 + K7 + K8 grønne
(guard, estimat, preflight, drill), harde tak satt. Forutsetningen «nøkkel satt + preflight
grønn» er D7-ekvivalenten av MAFs M1. Utfall re-rulles ikke (protokoll §4.5).
- **M3-analog (pilot):** følger MAF-planens M3 — ikke planlagt her før D-B/D-E/toolkit-
fabrikken foreligger; D7-deltakelse avgjøres av D-E.
## 7. Leveringsklar-definisjon (binær sjekkliste)
«Leveringsklart» er nådd når ALLE punkter under er sanne (hver enkelt er kommando-verifiserbar):
- [ ] Alle paritetsmatrise-rader (§1) er enten **FINNES HER** (bygget + load-bearing-testet)
eller **SPEILES IKKE** med begrunnelse operatøren har sett — ingen rad står i BYGGBAR
NÅ; GATED-rader er enten utløst+bygget eller eksplisitt operatør-akseptert som
utestående (beslutnings-køens ansvar, dokumentert i STATE).
- [ ] Full gate grønn: `uv run pytest` (alle tester, offline uten nøkkel/nett) +
`uv run ruff check .` + `uv run ruff format --check .` + `uv run mypy src`.
- [ ] §11-tabellen komplett: hver rad (inkl. «Spec integrity» C1.1 og «Closed loop» K4) har
en navngitt test som er detach-bevist rød (bevis i testfil eller sesjonslogg).
- [ ] README/docs ærlige (§1): hver kapabilitets-påstand matcher en skipbar sti (K12s
ærlighets-test grønn); skriptede stand-ins merket; ingen nivå-2-verdipåstand uten
D-I-belegget.
- [ ] Guard-markørlinjen i STATE.md er korrekt (planned/integrated per faktisk wiring-status,
med detach-bevis hvis integrated).
- [ ] Golden-bytene uendret mot commons (eller re-frosset KOORDINERT i commons med begge
suiter grønne).
- [ ] `runs/s10/` byte-urørt; `run_s10.py` byte-urørt.
- [ ] Subtree i synk med commons (ingen utestående spec-commits; verifisert med subtree-diff).
- [ ] STATE.md oppdatert etter konvensjonen; CHANGELOG dekker alle landede sesjoner.
- [ ] **`open`-speiling som EGEN operatør-gated sluttpost:** push til `open` skjer ALDRI
automatisk — operatøren godkjenner eksplisitt hvilke commits som speiles, som siste
handling etter alt over.
## 8. Endringer mot 2026-07-10-planen
| Gammel plan | Endring |
|---|---|
| §4 «Overføres IKKE hit (MAF-spesifikt)» | **OPPHEVET** — re-klassifisert rad for rad i §1 (operatør-mandat 2026-07-16) |
| C1.1/C2.0/C2.5/C2.7/C2.8/C3.2/C3.5/C4.0 | Videreført uendret i substans (C3.5 løftet fra «valgfri» til paritetskrav; C2.5 utvidet med guard-G2-vurdering) |
| «ingen D7-HTTP/MCP-økt planlagt» | Erstattet av K14K16, gated D-B |
| (fantes ikke) | K-serien: K1K20 (paritetssesjoner) + M2-/M3-analoger + leveringsklar-definisjon (§7) |
| (fantes ikke) | Review-paritet R-serien (2026-07-16): C2.6 (R-2 validator-finitthet), K2.9 (R-3/R-4/R-5/R-7 ingest-robusthet), K4 (R-1 closed-loop); R-6→C2.5, R-8→C3.2, R-10→C2.0/C2.5 |