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>
751 lines
60 KiB
Markdown
751 lines
60 KiB
Markdown
# 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`](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.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.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-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.
|
||
|
||
| # | 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 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](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 (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 `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 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` (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 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 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 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**.
|
||
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 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 |
|