portfolio-optimiser-claude/docs/2026-07-10-sesjonsplan-d7.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

175 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.

# Sesjonsplan D7 — speilings-sesjoner + egne funn (C1.1C4.0 · delt kø D-AD-E)
> **⚠️ SUPERSEDED 2026-07-16:** erstattet av
> [`2026-07-16-sesjonsplan-paritet.md`](2026-07-16-sesjonsplan-paritet.md) (operatør-mandat
> full MAF-paritet; §4-listen «Overføres IKKE hit» er OPPHEVET og re-klassifisert der).
> C-sesjonene C1.1/C2.0/C2.5/C2.7/C2.8/C3.2/C3.5/C4.0 er videreført i den nye planen.
> Dokumentet under beholdes uendret som historikk.
>
> **Status:** ~~GJELDENDE~~ sesjonsplan for dette repoet. Forfattet av kryssmodell-reviewen
> 2026-07-10 (Fable 5) — funn-referanser (C-F2/C-F3/C-F4/C-F5/C-F7, C-N1C-N4, C-P1) peker
> til [reviewen](review-2026-07.md); MAF-referanser (F1F14, D-AD-E, S2.x/S3.x/S4.x) peker
> til hovedrepoets `docs/review-2026-07.md` og `docs/plan/2026-07-10-sesjonsplan-fase2-6.md`.
>
> **Beslutnings-køen D-AD-E er DELT med MAF-søskenet** (identisk semantikk som MAF-planens
> §2): beslutningene tas ÉN gang av operatøren, materialiseres som commons-amendments, og
> gjelder begge repo via PULL-ONLY subtree. Dette repoet planlegger INGEN egen variant av
> køen — kun bygg-sesjoner gated på den. **C1.1/C2.0/C2.5 er byggbare NÅ** (ingen
> beslutnings-avhengighet).
>
> Prinsipp (uendret fra I-programmet): hver sesjon er én-sesjons-stor, offline, gratis
> (ScriptedClient), TDD (Iron Law), og Opus-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.
## 1. Den delte beslutnings-køen (operatør — tas i hovedrepoet, gjelder begge)
| Beslutning | Innhold (MAF-planens §2, uendret) | Blokkerer HER |
|---|---|---|
| **D-A** | Spec-amendments i commons: (1) nominal-gate + band-invariant (F2/C-F2); (2) kostbaseline-stage (F3/C-F3); (3) `/`-lenker → bundle-rot (F4/C-F4); (4) per-verdict seeding (F5/C-F5); (5) Magentic-tekst (MAF-only) | C2.7, C2.8, C3.2, C4.0 |
| **D-B** | Fase-2-scope vs frossen ingest-målbilde (live-kilde, doc-konnektor, MCP-grant) | ingenting her (MAF-scope; D7 speiler evt. ingest-spec-amendments når de lander i commons) |
| **D-C** | Vektor-store (§4.5): valg + DELT lagringsformat (.npy + jsonl er anbefalingen) | evt. C-semretrieval (ikke spesifisert her ennå) — se koblings-flagget under |
| **D-D** | Concurrency-/feilmodell | ingenting her i dag (ingen portefølje-sti); blir gate hvis D7 får portefølje-speil |
| **D-E** | Mål-semantikk + stack-paritet for ekte kjøring | M2-konfig på MAF-siden; her kun paritetsspørsmålet (§4.6) |
**Koblings-flagg til den delte køen (fra C-P1, MÅ tilbake til hovedrepoet):** D-C som
planlagt (cosine over tekst-embeddings) kolliderer med frossen method-spec §3 Steg 1
(«structural, never textual»). D-C må enten få et D-A-punkt som amender ranking-regelen
bevisst, eller re-scopes til strukturelle features. Uten det er S3.1 (MAF) og enhver
D7-speiling uimplementerbar spec-konformt.
**Commons-regel (alle spec-amendments):** skrives i `portfolio-optimiser-commons`, pulles
hit med `git subtree pull --prefix=shared commons main --squash`. ALDRI subtree push.
**Sammenligningsprotokoll-konsekvens:** etter en D-A-amendment re-pinnes/pulles subtree i
BEGGE repo og BEGGE suiter kjøres — aldri én side alene. Endres golden-bytene, re-fryses de
koordinert i commons (D-A eier det); begge repo konsumerer fasit uendret.
## 2. Byggbare NÅ (ingen beslutnings-avhengighet)
### C1.1 Method-spec-integritetsvakt (C-N1)
- **Mål:** §11-raden «Spec integrity» håndheves lokalt — spec-drift i subtree-synken fanges her.
- **Scope:** ny `tests/test_method_spec_loadbearing.py` etter `test_ingest_spec_loadbearing.py`-
mønsteret: (1) spec-fila finnes; (2) forbidden-toolkits-liste (samme som ingest-vaktens);
(3) §12-kontraktsfelt-dekning for feltene DENNE implementasjonen konsumerer (`decision`,
`rationale`, `id`, `proposal_features`, `affected_codes`, `measure_type`,
`claimed_saving_nok`, `description`, IR-feltene, golden-feltene, `type`,
vokabular-verdiene). KUN testkode — ingen src-endring, ingen spec-endring.
- **TDD:** testen er selv vakten — RØD-bevis via mutert spec-KOPI i tmp_path (test-parametrisert
mot kopi, aldri mot `shared/`): fjern et felt fra §12 → rød; injiser toolkit-navn → rød;
slett fila → rød.
- **Verifisering:** `uv run pytest tests/test_method_spec_loadbearing.py` grønn; full gate
(pytest/ruff/mypy) grønn; detach-bevis (mutasjons-parametrene) dokumentert i testen selv.
### C2.0 Steg-7 kjøresti-inngang (C-N2)
- **Mål:** en skipbar inngang komponerer §5-sekvensen (merge inbox → seed → fold → run), så
«a later run ingests it» er sant om en leverbar sti — ikke bare om primitivene.
- **Scope:** ny `run.py` (offline-testbar komposisjonsfunksjon `compose_run_context(bundle_dir,
inbox_dir=None, k=...)` + tynn CLI med `--bundle/--inbox/--out` som gjenbruker
contracts/meter/artifacts). `run_s10.py` forblir URØRT (fasit-sti, S10-artefaktene er
frosne). README-avsnittet om inboxen oppdateres til å peke på den nye inngangen.
IKKE: ny live-kjøring (CLI-en testes kun med ScriptedClient; SDK-klienten wires men
eksekveres ikke i suiten).
- **TDD:** RØD: dom droppet i inbox-mappe → inngangens komponerte kontekst MÅ bære
dommens markør (detach-punkt: fjern merge-kallet i komposisjonen → rød); kontroll: tom/
manglende inbox → base-kontekst uendret; RØD: rolledelingen — inngangen skriver ALDRI
til inboxen (byte-sammenligning før/etter).
- **Nøkkelantakelse (testes først):** komposisjonen kan gjenbruke `fold_experience`/
`merge_inbox_into_store` uendret — ingen ny søm, kun wiring.
- **Verifisering:** ny testfil grønn; detach → rød; full gate grønn; `grep -n "inbox" README.md`
viser claim som nå matcher en skipbar sti.
### C2.5 Inbox-herding + SDK-versjonsvakt (C-F7, C-N3, C-S3-rester)
- **Mål:** inboxen slutter å være en uvalidert injeksjonsflate; SDK-attributt-premissene får
en vakt som tvinger bevisst re-verifisering ved oppgradering.
- **Scope:** (1) `merge_inbox_into_store`/`load_inbox`: decision-vokabular-sjekk (ukjent
decision → SKIP, fortsatt tolerant, aldri raise — §4.2-vokabularet {approved, rejected,
approved_with_adjustment} på fil-laget), konfigurerbart tak på rationale-lengde + antall
filer per merge (fail-fast ved overskridelse, aldri stille kutt); (2) pin
`claude-agent-sdk>=0.2,<0.3` i pyproject; (3) versjonsvakt-test som feiler med
handlingsrettet melding når installert SDK-versjon ikke matcher pinnet serie (premissene i
`sdk_client.py:12-17` må re-verifiseres bevisst); (4) vurder `_total_tokens`-strictness
(delsum ved felt-drift — dokumentér valget i docstring).
- **TDD:** RØD: inbox-fil med `decision: "hva-som-helst"` når ALDRI storen (detach
vokabular-sjekken → den entrer → rød — reviewens kjørte bevis blir testens fixture);
RØD: rationale > tak → skip/feil per valgt semantikk; RØD: versjonsvakt mot fake-versjon.
- **Verifisering:** nye tester grønne + detach → rød; full gate grønn; eksisterende
step7-suite uendret grønn (tolerant-lasting består).
## 3. Speilings-sesjoner (gated: D-A + commons-pull — startes IKKE før amendment er pullet)
> Felles mal (= MAF-planens S2.7/S3.2/S4.0-mal): amendment lander i commons → subtree-pull →
> failing test først (moteksemplene fra reviewen ER test-fixturene) → impl → detach-bevis →
> full gate → golden-regresjon uendret (eller koordinert re-frosset i commons FØRST).
### C2.7 Validator-stramming (C-F2; gated: D-A pkt. 1)
- **Scope:** (a) strukturell blokk `claimed > nominal_feasible` → `Rejection` (i tillegg til
p90); (b) IR-invariant: hvert band MÅ omslutte itemets `unit_cost` (Pydantic
`model_validator`). IKKE: kostbaseline (C4.0).
- **Premiss (VERIFISERT 2026-07-10 av reviewer):** golden- og fixture-kompatibel her — alle
ikke-tomme bands omslutter unit_cost; golden-claim 30 000 ≤ nominal 90 000.
- **TDD:** RØD: reviewens moteksempel #1 (claim 100k, nominal 90k, band [0.70,1.40]) → MÅ
bli `Rejection`; RØD: band [1.8,2.2] rundt unit_cost 1.0 → `ValidationError` ved
konstruksjon; detach nominal-blokken → moteksempel-testen rød.
- **Filer:** `validator.py`, `ir.py`, `tests/test_validator.py`, `tests/test_ir.py`;
`tests/test_bygg_energi_mikro.py` uendret grønn (regresjonsbevis).
- **Verifisering:** `uv run pytest tests/test_validator.py tests/test_ir.py
tests/test_bygg_energi_mikro.py` grønn; golden uendret; full gate grønn.
### C2.8 OKF `/`-lenke-mapping (C-F4; gated: D-A pkt. 3)
- **Scope:** ledende `/` i cross-link-mål mappes til bundle-rot i `navigate_bundle`;
boundary-sjekken består fail-closed (subkatalog-policy følger amendmentens ordlyd).
- **TDD:** RØD: bundle med `](/tiltak.md)` → tiltaket navigeres og renders (detach mappingen
→ kun index → rød); RØD: `](/../escape.md)` → fortsatt skippet (boundary består);
eksisterende skip-tester oppdateres KUN slik amendmenten krever.
- **Filer:** `okf.py`, `tests/test_okf.py`. **Merk:** MAF-siden mangler i dag en tilsvarende
bygg-sesjon for F4 — flagget i reviewen §1 C-F4; operatøren bør legge den til der.
- **Verifisering:** nye tester grønne + detach → rød; full gate grønn; golden-bundelen
navigerer uendret.
### C3.2 Per-verdict seeding (C-F5; gated: D-A pkt. 4)
- **Scope:** `seed_store_from_bundle` leser features fra verdict-filas EGEN frontmatter (nye
valgfrie felt `affected_codes`/`measure_type`/`claimed_saving_nok`; fallback = dagens
bundle-projeksjon for bakoverkompatibilitet); `promote` skriver feltene. Multi-kandidat-
fixture repo-lokalt (aldri i `shared/` uten commons-endring).
- **TDD:** RØD: to kandidater i én bundle → dom om B når ALDRI As hypotese-prompt via
retrieval på As features (detach per-verdict-nøklingen → feil-folding → rød — reviewens
F5-bevis blir fixturen); eksisterende step1/step7/step8 uendret grønne (fallback).
- **Filer:** `experience.py`, `promotion.py`, `tests/test_step1_expel_loadbearing.py`,
`tests/test_step8_promotion_loadbearing.py`, ny fixture + tester.
- **Verifisering:** nye tester grønne + detach → rød; full gate grønn.
### C4.0 Kostbaseline-forankring (C-F3; gated: D-A pkt. 2)
- **Scope:** baseline-projeksjon i bundle (`cost-baseline.json`, commons-amendment/fixture)
+ fail-closed avstemmings-stage i `validate_proposal` (ukjent kode → Rejection;
quantity/unit_cost utenfor toleranse → Rejection; toleranse konfig). Baseline-argumentet
VALGFRITT (None = dagens oppførsel) så eksisterende suite står — men kjøresti-inngangen
(C2.0) SETTER den når fila finnes i bundelen. Ingest-laget er den naturlige produsenten
av projeksjonen (egen liten oppfølging hvis commons definerer format).
- **TDD:** RØD: reviewens F3-moteksempel (diktet kode, 10 MNOK) → Rejection «unknown cost
code» (detach avstemmingen → validated → rød); kontroll: ekte baseline-linje validerer
som før; golden-bundelen (uten baseline-fil) validerer uendret.
- **Filer:** `validator.py`, `okf.py`/`ir.py` (loader, fail-fast ved malformet fil —
tolerant ved fraværende), commons-fixture, nye tester.
- **Verifisering:** nye tester grønne + detach → rød; golden uendret; full gate grønn.
**MÅ være grønn før enhver eventuell fremtidig live-kjøring i dette repoet.**
## 4. Valgfri / lav prioritet (ubesluttet — foreslått, ikke godkjent)
- **C3.5 Budsjett-guard (C-N4):** pre-call-sjekk i loop-laget (nekt kall når rest-tak < 0)
+ eksplisitt run-total USD-grense over `SdkModelClient.total_cost_usd`. Mest verd rett før
en eventuell ny live-kjøring; ingen gate.
**Overføres IKKE hit (MAF-spesifikt):** S2.0-portefølje, S2.1-outbox (output-laget finnes
her: `artifacts.py`), S2.2 MCP-konnektor, S2.3 doc-konnektor, S2.4 http-herding, S3.1/S3.3/
S3.4, S4.1/S4.2-Foundry, S5.x, M1M3. `extending.md` står: ingen D7-HTTP/MCP-økt planlagt.
## 5. Anbefalt sekvens
1. **C1.1 → C2.5 → C2.0** (autonome, ingen gate — i den rekkefølgen: vakt først, herding,
så ny kjøresti-inngang som drar nytte av herdet inbox)
2. **Operatør: D-A** (i hovedrepoet; ta C-P1-koblingsflagget med i samme bolk) → commons-
amendment → subtree-pull HER
3. **C2.7 → C2.8 → C3.2 → C4.0** (etter pull; C2.7 først — minst avhengigheter, størst
spec-verdi)
4. Etter hver amendment-bølge: **begge repo** re-pinnes/pulles og **begge suiter** kjøres
(sammenligningsprotokollen) — aldri én side alene.