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
761 lines
61 KiB
Markdown
761 lines
61 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.
|
||
|
||
> ⚠️ **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.0 `3587854`) · 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](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 |
|