The "D7-status i dag" column was measured in Steg 0 on 2026-07-16 and never updated. Twelve build sessions have landed since, so twelve rows still read "MANGLER" for capabilities that now exist — a later session reading the column as current would rebuild something already built. The note names each landed row with its commit (verified against git, not against STATE's claim), and points at git history + STATE.md as the ground truth for what exists today. The MAF column and the gate statuses are NOT stale and remain valid planning input; only the D7 column is pinned to its measurement date. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQu2xxwedckjU56byu1aUG
61 KiB
Sesjonsplan — full MAF-paritet (K-serien + videreførte C-sesjoner · delt kø D-A–D-E)
Status: GJELDENDE sesjonsplan for dette repoet. ERSTATTER
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; R-serien til review-paritet 2026-07-16; MAF-referansene (S2.0–S5.4, D-A–D-I, M1–M3, 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.mdog2026-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-A–D-E (delt kø) | ÅPNE | MAF-plan §2 + MAF-STATE 2026-07-16 («Operatør-kø uendret») |
| D-F–D-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.
⚠️ Kolonnen «D7-status i dag» er en MÅLING FRA 2026-07-16 — den er IKKE oppdatert siden. Les den som utgangspunktet planen ble lagt fra, aldri som dagens tilstand. Sesjonene K1–K12 er landet etter målingen, så disse radene er bygget selv om de fortsatt står «MANGLER»: rad 2–3 (K1,
698e8f2) · rad 4 (K2,f2c64da) · rad 5 (K3,9bae4fb) · rad 6 (K4,d4efdd9) · rad 7 (K5,a926e4a) · rad 18 (K6,1600c18) · rad 20 (K7,c08d92a) · rad 21 (K8,08ffddb) · rad 22 (K9,b9dd479) · rad 23 (K10,a2acfc0) · rad 24 (K12,da93a68, inngang C2.03587854) · rad 25 (K11,4dcdd80). Gate-status og MAF-kolonnen er derimot fortsatt gyldige som planleggingsgrunnlag. Ground truth for hva som finnes i dag er git-historikken +STATE.md, ikke denne kolonnen.
| # | 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) | LANDET (S5.3-serien 905b2f9/1b990f0/d44305c/c0d3ba4, bekreftet av MAF 2026-07-25; MERK: deres c0d3ba4 dokumentsync er IKKE test-håndhevet — de tok imot formen vår, køet ikke bygget) |
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) | LANDET — MAF 878c989..7dab2df (6 commits, avsluttes av 7dab2df; hash oppgitt 2026-07-25, verifisert av dem mot git — ikke etterprøvbar herfra, vi leser aldri MAF-src). Divergens bekreftet: de runder et kronebeløp, vi runder ingen — live, ikke uenighet; ingen side patcher unilateralt før amendmenten er inne |
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 M1–M3 | 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 4–5 (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 20–21 (SDK-nativ
analog, BYGGBAR NÅ; kun Foundry-auth speiles ikke); S5.x → rad 22–25 (BYGGBAR NÅ-kjede);
M1–M3 → rad 32. Setningen «extending.md står: ingen D7-HTTP/MCP-økt planlagt» er ikke
lenger dekkende — K14–K16 planlegges nå, gated D-B; extending.md oppdateres i K16
(docs-ærlighet, §1).
2. Den delte beslutnings-køen (uendret — bor i HOVEDREPOET)
D-A–D-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. 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.pybyte-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 ettertest_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 motshared/): (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-felteneproject_id/measure/affected_items/code/quantity/unit_cost/assumptions, golden-felteneoutcome/validates/nominal_feasible/p10/p50/p90, learning-surface-feltene,type, vokabular-verdieneapproved/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.mdfør mutasjons-parametrene. - Verifisering:
uv run pytest tests/test_method_spec_loadbearing.pygrø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), nytests/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.idmed path-traversal (../../escaped) → avvist/sanert FØRwrite_verdictskriver (detach id-grammatikken → fil skrives utenfor inbox → rød; sikkerhetsagentens kjørte bevis blir fixturen; speil_ID_REfraingest.pyellerpromotion._filename_token-saneringen). RØD: versjonsvakt mot fake-versjon (monkeypatchimportlib.metadata.version) — melding skal navngisdk_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 versjonenuv syncfaktisk resolver. I tillegg (fra R4/R5, test-detach + sdk-review): (5) bindsdk_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) retttest_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 overrationaleer 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_skippedforblir 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 komposisjonsfunksjoncompose_run_context(bundle_dir, inbox_dir=None, k=...)+ tynn CLIpython -m portfolio_optimiser_claude.run --bundle/--inbox/--outsom gjenbruker contracts/meter/artifacts), nytests/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-114aldri 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_bundleuendret — 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.mdviser 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 —
Infinityklarerer ikke porten vakuøst lenger. - Scope (filliste):
ir.py(allow_inf_nan=Falsepå de numeriske feltene, eller eksplisitt finitthetssjekk avquantity/unit_cost/claimed_saving_nok+ bånd-endepunkter; forby negative bånd-verdier),contracts.py(min_lengthpå modell-id-verdier — tom-streng- bug),loop.py(fjern/dokumentér den dødecheck_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 dagValidatedProposal(validates=True, p90=inf)— reviewens kjørte R-2-bevis blir fixturen; detach-punkt: gjeninnførallow_inf_nan=True→ inf validerer → rød); RØD:assumptions-bånd medInfinity/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_mikroforblir 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 tomrowsmed fail-fast FØR disk-mutasjon — aldri delvis bundle; R-4: les CSV medutf-8-sig; R-7 valgfritt:LIMIT max_rows+1/fetchmanyfor 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, ikkeshared/). - IKKE-scope: ny kildefamilie (K14–K16, 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
codeikkecode(detachutf-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 overrun.py-komposisjonen + persona-artefakten + promotion; ScriptedClient; null modellkall), nytests/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
markerer substring avrationale(spec §4.3) — allerede bundet avtest_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 2–3; 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(typetSavingsLedger;realizeKUN med eksplisitt ekspert-argument + eksplisitt timestamp — samme determinisme-regel som promotion §6; deterministisk JSON-persistens sort_keys/indent 2/LF), nygoals.py(GoalContract: absolutt mål, hard/soft; fail-fast konstruksjon §10-stil), nyetests/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:
realizeuten 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_portfoliokjø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), nydata/reference_projects.json(eksempel-konfig; skjema-validert fail-fast icontracts.py-stil),contracts.py(konfig-modell), mini-bundle-fixture repo-lokalt undertests/data/(ALDRI ishared/), nytests/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(gjenbrukerartifacts.py-serialisering; skriver{run_id}-proposal.json+{run_id}-outcome.jsonmed outcome-type, reason/percentiler, checker_verdict, provenance-referanse, verdict-id;run_idPÅKREVD når outbox er satt — ingen wall-clock-default),run.py(valgfrittoutbox_dir/run_id), nytests/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 →
difftom) (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/Rejectioner 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ØRclient.complete),sdk_client.py(eksponer akkumulerttotal_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_usdakkumuleres 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), nydata/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 » (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.costsimgir 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_KEYsatt + ikke-placeholder-form — nøkkelVERDIEN valideres aldri online), model_map-konsistens (profil finnes,defaultfinnes, modell-id-form), placeholder-nekt også iresolve_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.preflightkorrekt 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-konfignøkkel → ekspertskjema-validert fail-fast — nøkkelen er en konfig-streng nå, dimensjonskatalog-integrasjon kommer med K13), CLIpython -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, nyttdocs/oppskrift-kunnskapsbase.md(D-H pkt. 1: dokumentert team-prosess, ærlig 1–2-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 K1–K11-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 underdata/; (2)ingest.py—library-kildefamilien (4a/5a:library-{id}.md, kuratert frontmatter + additivt provenance-lag, kildebelegg-håndheving fail-fast ved tom/manglendesources); (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-caseexamples/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
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):
- C1.1 → C2.5 → C2.0 (vakt → herding → inngang)
- 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)
- K4 (closed-loop-sim — lukker §11-gapet R-1 tidlig)
- K1 → K2 → K3 (portefølje-fundamentet)
- K5 → C3.5 → K6 → K7 → K8 (outbox/kost/preflight/drill)
- K9 → K10 → K11 → K12 (HITL/varsling/verdirapport/CLI-sluttsync)
- Ved D-A (når som helst, uavhengig av 1–5): 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.
- 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.pybyte-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 tilopenskjer 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 K14–K16, gated D-B |
| (fantes ikke) | K-serien: K1–K20 (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 |