portfolio-optimiser/docs/plan/2026-07-10-sesjonsplan-fase2-6.md
Kjell Tore Guttormsen a3b238307c docs(repo): meet the org repo-standard gate — 0 ERROR
Ran `repo-standard` (v0.1.1, class `standalone`) and fixed everything it
flagged as ERROR, plus the WARN links that were genuinely dead.

README first screen:
- opening line is now byte-identical to the forge description, so
  description == catalog == README is machine-checkable (badges moved below).
- `## Install` (required for class `standalone`): clone + `uv sync`, stated as
  clone-only because the shared spec, persona skill and example bundles under
  `shared/` are read from the working tree at run time. `uv run pytest` named as
  the verification, with the fact that no CI runner exists said out loud rather
  than implied by a badge.
- `## Non-goals` (required): the five limits already binding in CLAUDE.md —
  not a compliance product, not a portfolio-level reallocator, not autonomous
  decision-making, not turnkey, not a model benchmark.

Dead relative links (measured, not guessed):
- `docs/plan/2026-07-10-sesjonsplan-fase2-6.md` pointed at
  `../2026-07-14-revisjonspakke-DF-DI.md` six times; the file sits in
  `docs/plan/`, not `docs/`. (The sibling `../review-2026-07.md` links are
  correct and untouched.)
- the Fase-1 spike brief linked repo-root-relative from
  `.claude/projects/…/`; re-anchored with `../../../`.

The one remaining README ERROR was a gate false positive: `checkInternalLinks`
resolves targets against `git ls-files`, which lists files only, so a link to a
directory can never resolve. `[shared/](shared/)` now points at
`shared/README.md` — a better target anyway, since that file carries the
pull-only subtree rule. Not fixed here: the classifier lives in another repo.

Remaining WARNs are all inside `shared/`, deliberately untouched: it is a
pull-only commons subtree, and the nav-golden files are byte-level fixtures
that gate `test_nav_golden_*` — four of them are OKF bundle-internal links,
and the `/etc/passwd` ones are the negative escape fixture doing its job.

Suite green: 630 passed, 4 skipped (markdown-only diff; no test touched).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ri3aVJPfynCZtHRhesCzUH
2026-08-03 21:56:19 +02:00

44 KiB
Raw Blame History

Sesjonsplan — Fase 2 → offline-fullførings-grense (S2.0S5.3 · D-AD-E · M1M3)

Status: GJELDENDE sesjonsplan. Forfattet som re-plan-forslag av kryssmodell-reviewen 2026-07-09 (Fable 5); promotert til gjeldende plan 2026-07-10 på operatør-instruks. Roadmapen (2026-07-06-reell-kjoring-analyse-plan.md) er revidert med kryssreferanser hit. Revidert 2026-07-14: beslutningene D-FD-I (kunnskapsinnholdsmodell, OKF-modul/fabrikk/evaluator, oppsett/brukervennlighet, verdibevis/kostnadsstyring) ble truffet i operatør-samtale og er flettet inn her (§2-oppføringer + nye sesjoner S3.5/S3.6/S5.4 + S5.3-utvidelse); fasit i revisjonspakke D-FD-I. Funn-referanser (F1F14, P1P6, U-1U-4) peker til reviewen. Beslutnings-sesjonene D-AD-E er fortsatt ÅPNE (operatør-kø): bygg-sesjoner gated på dem starter ikke før beslutning foreligger; S2.0/S2.1/S2.5 er byggbare NÅ (ingen beslutnings-avhengighet). Endringer mot roadmapen er merket [ENDRET] / [NY]. Frosne dokumenter (målbilde, ingest-målbilde, method-spec) er IKKE endret — amendments skjer kun via D-A/D-B + commons (PULL-ONLY).

Prinsipp: hver bygg-sesjon er én-sesjons-stor, offline, gratis (skriptede klienter), TDD (Iron Law), og Opus-eksekverbar med kun «Les STATE.md og følg instruksjonene». Kost/tenant/ ekspert-gatede steg er operatør-milepæler (M1M3), aldri autonome Opus-sesjoner.


1. Endringer mot roadmapen (oppsummert)

Roadmap Endring Begrunnelse
Fase 2 «MCP wiret i kjørestien» [ENDRET]MCP-ingest-konnektor (ny kildefamilie i manifestet), aldri kjøresti-wiring P2: method-spec §3 forbyr query-time retrieval; CLAUDE.md-invariant
Fase 2 «live-kilde-herding, inkrementell re-ingest» [ENDRET] → gated på beslutning D-B; default-scope er herding av http-konnektoren mot mock (timeouts/retry/feilkategorier), IKKE live kilde/inkrementell P1/U-3: frossen ingest-målbilde §8/§11/§12 forbyr dette; bevisst amendment kreves
Fase 3 «concurrent fan-out» [ENDRET] → krever beslutning D-D først (determinisme-modell) + fikse F1/F6 FØR concurrency Concurrent==sekvensiell er i dag selvmotsigende (delt store, RMW-index)
Fase 4 [ENDRET] → splittes i offline-byggbar del (S4.0S4.2, autonome sesjoner) + operatør-milepæler (M1/M2) Mandat-skille
Fase 5 [ENDRET] → forutsetter outbox (S2.1) som roadmapen ikke nevner P4: output-laget (målbilde §3) er ubygget
[NY] S2.0 (portefølje-læringssløyfe), S2.1 (outbox), S2.5 (inbox-herding), S2.7 (validator-stramming), S4.0 (kostbaseline-forankring) Injisert av funn F1, P4, F7/F11, F2, F3
[NY] Beslutnings-sesjoner D-AD-E FØRST §4-restene + spec-amendments må avgjøres før bygg

Funn → sesjon-mapping: F1→S2.0 · F2→D-A+S2.7 · F3→D-A+S4.0 · F4→D-A (spec) · F5→D-A+S3.2 · F6→D-D+S3.3 · F7→S2.5 · F8→S4.0 · F9→D-E+S2.0(guard) · F10→S3.4 · F11→S2.5 · F12→S2.0 · F14→D-A (tekst) · P1→D-B · P4→S2.1 · P6→S4.1/S5.2/S5.3.

Commons-regel (gjelder alle spec-amendments): shared/ er PULL-ONLY subtree. Endringer i method-spec/ingest-spec/bundle-layout skrives i portfolio-optimiser-commons og pulles hit (git subtree pull --prefix=shared commons main --squash). D7-søskenet må speile senere — UTENFOR dette repoets sesjoner; flagges i hver berørt sesjon.


2. Beslutnings-sesjoner (FØRST — operatør + kort AI-brief, ingen kode)

D-A — Spec-amendments i commons (method-spec)

  • Avgjør: (1) validator nominal-gate + IR-invariant low ≤ unit_cost ≤ high (F2 — golden- kompatibel, verifisert); (2) kostbaseline-avstemmings-stage (F3); (3) /-prefiksede cross-links mappes til bundle-rot (F4/U-1); (4) per-verdict seeding-nøkkel (F5/U-4); (5) tekst-justering «Magentic eksperimentell» → «planleggingstung/uprøvd utenfor Magentic-One» (F14; kun begrunnelse, valget står).
  • Output: godkjent/avvist per punkt + utkast til commons-endringer. Blokkerer: S2.7, S3.2, S4.0.

D-B — Fase 2-scope vs frossen ingest-målbilde

  • Avgjør: (1) amendes ingest-målbildet bevisst (live-kilde/inkrementell/§11), eller nedskopes roadmap-B til mock-herding (P1/U-3 — anbefalt: nedskop nå, live utsettes til M3-forberedelse); (2) §4.4 første live-kilde (anbefalt: SQL/databaseread_sql er allerede den mest herdede konnektoren, read-only by construction); (3) dokument-konnektor-avgrensning: PDF-tekst via pypdf (ny dep) nå, DOCX utsatt; (4) MCP-kildefamiliens nettverks-/subprosess-grant-form.
  • Output: Fase 2-scope-erklæring + evt. målbilde-amendment. Blokkerer: S2.2, S2.3, S2.4.

D-C — Vektor-store (§4.5)

  • Grunnlag (delegert research, kildeført i review §6): ved 1005 000 dokumenter er ANN unødvendig; eksakt søk er deterministisk og offline-testbart. Rangering: 1) numpy brute-force (BSD, universelle wheels, delt format .npy+jsonl er enklest for begge stacker), 2) sqlite-vec 0.1.9 (eksakt KNN, MIT/Apache, x86_64-wheel OK — men pre-v1.0, pin), 3) faiss-cpu (x86_64-wheel krever macOS 15+ — sjekk sw_vers først). LanceDB: dealbreaker (ingen Intel-Mac-wheel); ChromaDB/DuckDB-VSS: frarådet (tunge deps / eksperimentell VSS).
  • Avgjør: valg (anbefalt: numpy) + delt lagringsformat med SDK-søskenet + embeddings-kilde for ekte kjøring (Azure OpenAI embeddings vs lokal — kun konfig; tester bruker alltid fake-embedder).
  • Output: beslutning D8. Blokkerer: S3.1.

D-D — Concurrency- og feil-modell (Fase 3)

  • Avgjør: (1) determinisme-modell for concurrent fan-out — anbefalt: bølge-modell (kjøringer i en bølge ser samme store-snapshot; deterministisk merge-barriere mellom bølger; sekvensiell == bølgestørrelse 1); (2) én-skriver-regel eller fil-lås for index/ledger (F6); (3) feilpolicy ved delvis feil midt i portefølje (anbefalt: collect-and-continue, per-run-feil i PortfolioResult, aldri tap av fullførte runs — i dag kastes alt, review §3).
  • Output: concurrency-kontrakt. Blokkerer: S3.3, S3.4.

D-E — Mål-semantikk-rest + stack-paritet

  • Avgjør: (1) prosent-måls baseline-kilde (F9: subset-avhengig i dag; bundle-prosjekter har baseline 0) — anbefalt: eksplisitt baseline_ore i GoalContract/GoalConfig, aldri implisitt sum; (2) §4.6 stack-paritet for den ekte kjøringen (MAF, SDK eller begge — operatørens kost-avveining; liveness-asymmetri-erklæringen i sammenligningsprotokollen §3 består uansett).
  • Output: semantikk-beslutning. Blokkerer: del av S2.0 (guard-form), M2-konfig.

D-FD-I — BESLUTTET 2026-07-14 (operatør-samtale, intensjonsanalyse). Til forskjell fra D-AD-E over er disse fire allerede avgjort; fasit-protokoll + innplassering i revisjonspakke D-FD-I. Frosne dokumenter er IKKE endret ennå — amendments skjer via commons (PULL-ONLY) i egne økter. Oppføringene under oppsummerer beslutningen + hva den blokkerer/åpner (ikke hele fasiten).

D-F — Kunnskapsinnholdsmodell [BESLUTTET 2026-07-14]

  • Status: BESLUTTET 2026-07-14. Fasit: revisjonspakke §1.
  • Kjerne: ny delt innholdsmodell i commons (kunnskapstyper tiltaksmønstre/erfaringsnotater/faglige råd, alle med påkrevd kildebelegg) — KUN lesestoff for forslagsstilleren, validatorens regler urørt. Streng separasjon fra dommene (bibliotek via bundle_context; korreksjoner KUN via ExpeL-folden). Delt dimensjonsbibliotek materialiseres inn i hver bundle via ingest-mønsteret (generated: true, flat navigasjon — ikke kryssbundle-lenker); dimensjonskatalog som skjema-validert konfig; trinnvis lesing (sammendrag-først) er nytt krav.
  • Blokkerer/åpner: gated på commons-amendment FØRST (PULL-ONLY; D7-speiling flagges) → åpner S3.5 (koordineres med S3.2). Realistisk energi-innhold (§1 pkt. 7) = egen senere innholds- produksjonsjobb, ikke del av S3.5. Fabrikk-avhengige deler venter på toolkit-repoet (D-G).

D-G — OKF: felles modul, fabrikk, evaluator [BESLUTTET 2026-07-14]

  • Status: BESLUTTET 2026-07-14. Fasit: revisjonspakke §2 (+ kryssrepo-inventar §0.2).
  • Kjerne: standard-kompatibel OKF (F4//-lenkeformen rettes — forsterker D-A pkt. 3), egne utvidelser dokumenteres eksplisitt som utvidelser. Felles OKF-kode JA (endrer D7s «from spec alone» bevisst; gir Claude-repoet skrive-halvdelen A2 mangler i dag). Nytt tredje signatur-repo (arbeidstittel okf-toolkit): delt les/naviger/skriv-kjerne + conformance-testsett + bundle-evaluator
    • bundle-fabrikk. Rekkefølge: modul + formatprøve først (fjerner 6-steders-duplikasjonen), fabrikk + evaluator deretter mot energi-caset.
  • Blokkerer/åpner: toolkit lever i EGET repo utenfor denne sesjonskøen → ekstern avhengighet (T0) som blokkerer fabrikk-avhengige deler av D-F/D-H. Guard forblir eget sikkerhets-repo (avhengighet).

D-H — Oppsett og brukervennlighet [BESLUTTET 2026-07-14]

  • Status: BESLUTTET 2026-07-14. Fasit: revisjonspakke §3.
  • Kjerne: oppsett gjøres ALLTID av et lite team (teknisk + fag); leveransen er en oppskrift (dokumentert prosess), ikke en veiviser (B9-onboarding + guidet dom-kommando FORKASTET). Fagpersonen leverer filer i egne formater — aldri skjema/JSON; fabrikken (D-G) AI-oversetter fri-format-dommer til strengt format, godkjenning i praksis = stikkprøver med provenance-peker til ekspertens originalfil. Demo-sti: klon → unzip energi-eksempel i bundle-innboks → fabrikk bygger → hele sløyfa kjører. Obsidian/VS Code som lese-løsning først.
  • Blokkerer/åpner: oppskrift-dokumentet (§3 pkt. 1) legges til S5.3 som dokumentleveranse; dom-oversettelse + demo-sti er fabrikk-avhengige (D-G/T0), blokkert til toolkit finnes.

D-I — Verdibevis + kostnadsstyring [BESLUTTET 2026-07-14]

  • Status: BESLUTTET 2026-07-14. Fasit: revisjonspakke §4.
  • Kjerne: publiserings-påstand = nivå 2 (realistisk case, modellerte tall, aldri salgsspråk over beleggsnivået); nivå 3 (ekte pilot) er åpen invitasjon. Verdirapport per kjøring (kjerne): hovedbok-basert modellert→korrigert→realisert, målprogresjon, tallfestet læringseffekt, kost-mot-verdi. Kostnadssimulering FØR kjøring (MÅ-krav): what-if over modell-mappet (modeller × effortnivåer), prisdata som skjema-validert konfig (aldri hardkodet), kvalitetsutsagn merket som veiledning med kilde.
  • Blokkerer/åpner: åpner S5.4 (verdirapport, etter S2.1-outbox + ledger) og S3.6 (kostnadssimulering, fri/offline). README oppdateres FØRST når nivå-2-beviset finnes (pkt. 1).

3. Opus-sesjons-specs (offline, autonome)

Felles for alle: Iron Law (failing test først); uv run pytest / uv run ruff check . / uv run mypy src grønne ved slutt; skriptede klienter (null modell-kost); commit per sesjon i repoets Conventional-Commit-stil; STATE.md overskrives ved sesjonsslutt.

S2.0 [NY] Portefølje-læringssløyfe + ærlighets-fiks (F1, F12, P5, F9-guard)

  • Mål: en dom på prosjekt k når prosjekt k+1s hypotese-PROMPT i run_portfolio — og ingen docstring påstår mer enn koden gjør.
  • Scope: per-prosjekt bundle_dir (valgfritt felt i reference_projects.json) + verdict_dir-parameter tres gjennom run_portfoliorun_project. Percent-goal-guard: eksplisitt feil (ValueError) når percent-mål settes og baseline er 0. CHANGELOG oppdateres (Fase 1 + denne). IKKE bygges: concurrency, semantisk henting, outbox.
  • Avhengigheter: ingen (første bygg-sesjon).
  • Filer: run.py, reference_domain.py, data/reference_projects.json (+ evt. mini-bundle fixture under data/), tests/test_portfolio.py, ny tests/test_portfolio_learning_loadbearing.py, CHANGELOG.md.
  • TDD: (1) RØD: test der prosjekt k får dom (via delt store, bundle-sti) og k+1s genererings-prompt MÅ inneholde dommens id+markør — detach-punkt: fjern bundle_dir-trådingen i run_portfolio → rød (i dag ER den rød — det er poenget). (2) RØD: empty-store-kontroll. (3) RØD: percent-mål + baseline 0 → ValueError.
  • Nøkkelantakelser: bundle-fixture kan gjenbruke bygg-energi-mikro-form uten commons-endring (test: legg fixture under src/portfolio_optimiser/data/, aldri i shared/).
  • Verifisering: uv run pytest tests/test_portfolio_learning_loadbearing.py → grønn; detach (revert tråding) → rød; full suite + ruff + mypy grønne; grep -n "cross-project learning" src/ viser docstring som nå stemmer med wiring.

S2.1 [NY] Outbox-persistens — output-laget materialiseres (P4)

  • Mål: hver kjørings forslag/avvisning/provenance persisteres som deterministisk JSON i en outbox-mappe (målbilde §3s output-lag), så utestående dommer kan spores (Fase 5) og live-artefakter fanges (sammenligningsprotokoll §4.2).
  • Scope: run_project(outbox_dir=..., run_id=...) (begge valgfrie; run_id er påkrevd når outbox er satt — ingen wall-clock-default). Skriver {run_id}-proposal.json / {run_id}-outcome.json (outcome-type, reason/percentiler, checker_verdict, provenance, verdict-id). Systemet SKRIVER outbox (lovlig: rolledelingen §3 gjelder inbox/wiki, ikke systemets eget output-lag — sitér method-spec §2 i docstring). IKKE bygges: ruting, varsling.
  • Avhengigheter: ingen (parallell med S2.0).
  • Filer: run.py, ny outbox.py (ren stdlib+pydantic — MAF-fri? Nei: importerer validator-typer som er rene; hold agent_framework-fri og legg til i _MAF_FREE_MODULES), tests/test_outbox_loadbearing.py.
  • TDD: RØD: kjøring med outbox_dir → forventet filpar finnes, byte-deterministisk (sort_keys, indent 2, LF); detach-punkt: fjern outbox-skrivingen → rød. Kontroll: uten outbox_dir skrives ingenting.
  • Nøkkelantakelser: ValidatedProposal/Rejection er JSON-serialiserbare via eksplisitt mapping (test først med begge utfallstyper).
  • Verifisering: ny testfil grønn; detach → rød; full gate grønn; to kjøringer med samme input+run_id → byte-identiske filer (diff).

S2.2 MCP-ingest-konnektor (gated: D-B) [ENDRET fra «MCP i kjørestien»]

  • Mål: en fjerde kildefamilie mcp i ingest-manifestet materialiserer OKF-filer fra en MCP-server — datainntak, aldri kjøresti.
  • Scope: ingest-spec-amendment i commons FØRST (skjema for {type:"mcp", id, server_ref, tool}; server_ref = navn på env-var med kommando, mirror connection_ref) → subtree pull → impl i ingest.py. Transport: stdio-klient via mcp-pakken (allerede dep). Per-run-grant: gjenbruk allow_network-mønsteret med nytt eksplisitt flagg (per D-B). Test: in-process fixture-server (gjenbruk datasource.build_mcp_server-kjernen mot committed docs — det AV-DEMOER extension-pointet). IKKE: fjern-servere, auth utover env-ref.
  • Avhengigheter: D-B (+ commons-pull).
  • Filer: ingest.py, tests/test_ingest_mcp*.py, golden-fixture examples/ingest-golden-mcp/ (i commons — flagg), docs/extending.md-avsnitt.
  • TDD: RØD: manifest med type: mcp uten grant → IngestError (grant-detach → rød); RØD: golden-materialisering mot fixture-server → byte-deterministisk bundle; RØD: verdict-reservasjonen gjelder også mcp-familien.
  • Nøkkelantakelser: mcp-klient kan drives i-prosess mot FastMCP uten socket (test som første steg — hvis ikke, subprosess mot python -m-fixture med eksplisitt merking).
  • Verifisering: uv run pytest tests/test_ingest_mcp*.py grønn; detach grant-sjekken → rød; full gate grønn.

S2.3 Dokument-konnektor (doc-familie; gated: D-B)

  • Mål: PDF-rapport → OKF-konseptfil med provenance, deterministisk mot committed fixtures.
  • Scope: ingest-spec-amendment (commons) for {type:"doc"}; pypdf som ny dep (D-B); tekst-ekstraksjon per side, fenced-verbatim-rendering (gjenbruk _render_fenced_block-regler), max_rows-cap, fail-fast på ikke-tekst-PDF. DOCX: IKKE (utsatt per D-B).
  • Avhengigheter: D-B; uavhengig av S2.2.
  • Filer: ingest.py, pyproject.toml (+pypdf), tests/test_ingest_doc*.py, golden-fixture med liten committed PDF.
  • TDD: RØD: golden byte-determinisme; RØD: kodefence-linje i ekstrakt → IngestError (gjenbruk http-regelen); RØD: cap-overskridelse → feil, aldri trunkering.
  • Nøkkelantakelser: pypdf-ekstraksjon er bit-stabil på tvers av versjoner for fixture-PDF-en (test: pin versjon; golden fanger drift).
  • Verifisering: nye tester grønne + detach → rød; full gate grønn.

S2.4 Konnektor-herding mot mock (gated: D-B) [ENDRET fra «live-kilde-herding»]

  • Mål: http-konnektoren tåler virkelighetens feilmoduser — bevist mot injisert transport, aldri live.
  • Scope: timeout-parameter på _urllib_get; feilkategorisering (transport/auth/decode) i IngestError-melding; ingest-logg beriket (§8: kilde, tidspunkt, radantall — aldri innhold); retry KUN hvis D-B sier ja (default nei — determinisme). Inkrementell re-ingest: IKKE (frossen §8) med mindre D-B amender.
  • Avhengigheter: D-B.
  • Filer: ingest.py, tests/test_ingest_http*.py.
  • TDD: RØD per feilmodus (canned transport som raiser URLError/timeout/feil-encoding) → presis IngestError; detach timeout → rød.
  • Verifisering: nye tester grønne; full gate grønn; grep bekrefter ingen nye socket-stier utenfor _urllib_get.

S2.5 [NY] Inbox- og robusthets-herding (F7, F11)

  • Mål: verdict-inboxen slutter å være en uvalidert injeksjonsflate, og offline-bevisets MAF-avhengighet får en versjonsvakt.
  • Scope: (1) load_verdicts_from_dir: decision-vokabular-sjekk (§4.2 — ukjent decision → SKIP, fortsatt tolerant, aldri raise), tak på rationale-lengde + antall filer per merge (konfigurerbart, fail-fast ved overskridelse — aldri stille kutt); (2) konsolider de fire _inner_get_response-duplikatene (conftest ×3 + simulation) til én delt scripted-klient (plassering: tests/-hjelper + simulation beholder sin — eller flytt til simulation.py og importér i conftest; velg det som ikke gir src→tests-import); (3) MAF-versjonsvakt: test som feiler med handlingsrettet melding hvis agent_framework.__version__ ikke matcher pinnet versjon (tvinger bevisst re-verifisering av privat-API-premissene ved oppgradering); (4) pin agent-framework-core>=1.9.0,<2 i pyproject.
  • Avhengigheter: ingen.
  • Filer: verdicts.py, conftest.py, simulation.py, pyproject.toml, tests/test_verdicts.py, ny tests/test_maf_version_guard.py.
  • TDD: RØD: inbox-fil med decision: "banana" → hoppes over (detach vokabular-sjekken → den entrer storen → rød); RØD: rationale > tak → skip + logg; versjonsvakt-testen rød mot en fake-versjon.
  • Verifisering: full gate grønn; grep -c "_inner_get_response" tests/ src/ viser redusert duplikat-antall.

S2.7 [NY] Validator-stramming (F2; gated: D-A + commons-pull)

  • Mål: den deterministiske validatoren håndhever sin egen stage-2-grense, og assumptions kan ikke forfattes forbi den.
  • Scope: (1) strukturell blokk claimed > nominal_feasible → Rejection (i tillegg til P90); (2) IR-invariant: hvert assumption-band MÅ omslutte itemets unit_cost (low ≤ unit_cost ≤ high) — Pydantic model_validator. Golden-kompatibilitet er verifisert i review (claim 30k ≤ 90k; band [0.70,1.40] ∋ 1.0). IKKE: kostbaseline-avstemming (S4.0), metode-registry (S4.0).
  • Avhengigheter: D-A pkt. 1 + commons-spec pullet.
  • Filer: validator.py, ir.py, tests/test_validator.py, tests/test_ir*.py (eller tilsvarende), tests/test_bygg_energi_mikro.py (uendret grønn — regresjonsbevis).
  • TDD: RØD: reviewens moteksempel #1 (claim 100k, nominal 90k, band [0.70,1.40]) MÅ bli Rejection; RØD: band [1.8,2.2] rundt unit_cost 1.0 → ValidationError ved konstruksjon; detach-punkt: fjern nominal-blokken → moteksempel-testen rød.
  • Nøkkelantakelser: ingen eksisterende test/fixture bruker band som ikke omslutter unit_cost — VERIFISERT 2026-07-09 av reviewer (skann av alle JSON-fixtures + inline-band-grep: null brudd; se review §6). Antakelsen er dermed et bekreftet premiss, ikke en risiko.
  • Verifisering: uv run pytest tests/test_validator.py tests/test_bygg_energi_mikro.py grønn; golden uendret; full gate grønn. Flagg: D7-søsken må speile (egen sesjon i søsken-repoet).

S3.1 Semantisk henting bak seam (gated: D-C) [roadmap C]

  • Mål: hentingen skalerer forbi feature-key-match uten å ofre determinisme/offline-testbarhet.
  • Scope (per D-C-anbefaling numpy): Retriever-protokoll; HybridRanker = dagens strukturelle score + cosine over lagrede vektorer (vekting konfig); vektor-lager = .npy + id-jsonl ved siden av verdict-storen; Embedder-protokoll med deterministisk fake i tester (hash-basert); ekte embeddings-klient (Azure/lokal) KUN som konfig-punkt, aldri kalt i tester. IKKE: ANN, ekstern DB, endring i shared/.
  • Avhengigheter: D-C; uavhengig av S2.x.
  • Filer: ny semretrieval.py (MAF-fri, i _MAF_FREE_MODULES), verdicts.py (retrieve-seam), run.py (opt-in), pyproject.toml (numpy), nye tester.
  • TDD: RØD: syntetisk stor base (500+ verdicts) der KUN cosine-komponenten kan rangere riktig dom øverst (strukturell score uavgjort ved konstruksjon) — detach cosine → rød; RØD: determinisme (to kjøringer → identisk rangering); RØD: fake-embedder-bit-stabilitet.
  • Nøkkelantakelser: numpy-dep er akseptabel i MAF-repoet (IKKE i shared/) — bekreftet av D7-grensen (semantikk-laget er stack-lokalt).
  • Verifisering: nye tester grønne + detach → rød; full gate grønn; test_okf_is_maf_free utvidet til semretrieval.py grønn.

S3.2 Multi-kandidat ExpeL-substrat (F5; gated: D-A pkt. 4 + commons-pull)

  • Mål: dommer nøkles på SIN kandidat, ikke bundelens ene IR-projeksjon.
  • Scope: seed leser features fra verdict-filas egen frontmatter (nye valgfrie felt: affected_codes/measure_type/claimed_saving_nok; fallback = dagens kandidat-nøkling for bakoverkompatibilitet); promote_verdict skriver disse feltene; multi-kandidat-bundle-fixture.
  • Avhengigheter: D-A + commons (spec §3 Steg 1 seeding-regel + bundle-eksempel).
  • Filer: verdicts.py, tests/test_step8_promotion_loadbearing.py, ny multi-kandidat-fixture (repo-lokal under data/), nye tester.
  • TDD: RØD: to kandidater i én bundle → dom om kandidat B når ALDRI kandidat As hypotese-prompt (detach per-verdict-nøklingen → rød fordi B-dommen feil-nøkles til A).
  • Verifisering: nye tester grønne; eksisterende step1/step7/step8-suite uendret grønn (fallback-kompatibilitet); full gate grønn. Flagg: D7-speiling.

S3.3 Concurrent fan-out (F6; gated: D-D) [roadmap C]

  • Mål: N kjøringer parallelt med bevart determinisme: concurrent == sekvensiell.
  • Scope (per D-D bølge-modell): run_portfolio(concurrency=k); bølge = inntil k prosjekter med samme store-SNAPSHOT; deterministisk merge-barriere (sortert på project_id) mellom bølger; feilpolicy collect-and-continue (RunResult-slot med feil-felt, fullførte runs bevares); én-skriver-regel for index/ledger håndheves (ingen promote/realize i kjørestien — allerede sant; assert + dok).
  • Avhengigheter: D-D, S2.0 (bundle-portefølje), helst S3.1 (men ikke hard).
  • Filer: run.py, tests/test_portfolio_concurrent_loadbearing.py.
  • TDD: RØD: concurrency=3 gir BYTE-identisk aggregat + store-innhold som concurrency=1 på 3-prosjekt-fixturen (detach barrieren → udeterministisk → rød over repetisjoner — kjør testen med fast rekkefølge-probe, ikke tidsavhengig); RØD: injisert feil i prosjekt 2 → prosjekt 1+3s resultater bevart.
  • Nøkkelantakelser: MAF-klienter er asyncio-samtidige i én loop (dokumentert modell er asyncio; OS-tråd-garanti er IKKE dokumentert — hold alt i én loop).
  • Verifisering: ny test grønn ×20 repetisjoner (pytest --count el. loop); full gate grønn.

S3.4 Kostnadsstyring på tvers (F10) [roadmap C]

  • Mål: et globalt token-tak over HELE porteføljepasset (og på tvers av pass), håndhevet FØR kall — ikke bare per kjøring etterpå.
  • Scope: PortfolioBudget (globalt tak + per-run-tak); pre-call-guard i BudgetMiddleware (nekt kall når rest < 0 — i tillegg til dagens post-charge); spend-persistens (deterministisk JSON, eksplisitt stamp-argument); oppstartsnekt når resttak < konfigurert minimum per kjøring.
  • Avhengigheter: D-D (deler feilpolicy), S3.3 (bølge-integrasjon) — kan bygges før S3.3 mot sekvensiell sti.
  • Filer: budget.py, run.py, tests/test_budget.py, ny loadbearing-test.
  • TDD: RØD: globalt tak krysses midt i passet → strukturert stopp med fullførte runs bevart (detach global-sjekken → passet løper forbi taket → rød); RØD: pre-call-guard nekter kallet (klient-mock som teller kall — kallet skal ALDRI skje).
  • Verifisering: nye tester grønne + detach → rød; full gate grønn.

S3.5 [NY] Innholdsmodell + fagbibliotek-materialisering (D-F; gated: commons-amendment)

  • Mål: delt kunnskapsinnholdsmodell (tiltaksmønstre/erfaringsnotater/faglige råd med kildebelegg) materialiseres inn i prosjekt-bundles som rent lesestoff for forslagsstilleren — uten å røre validatoren og uten å blande seg med dommene.
  • Scope (revisjonspakke §1 pkt. 16): (1) nye kunnskapstyper i delt spec (commons-amendment FØRST — PULL-ONLY, D7-speiling flagges); (2) dimensjonskatalog som skjema-validert konfig (id, label, allowed_measure_types, allowed_code_prefixes) + fail-fast loader — rammeverket shipper eksempel-katalog, deployer eier sin; (3) bibliotek-materialisering via ny ingest-kildefamilie (generated: true, manifest-ref, re-materialisering eier egne filer — flat/same-dir navigasjon, IKKE kryssbundle-lenker, IKKE manuell duplisering); (4) trinnvis lesing i bundle_context: sammendrag-først (én linje per kunnskapsfil), fulltekst hentes ved behov. Streng separasjon håndheves: bibliotek via bundle_context, organisasjonens korreksjoner KUN via ExpeL-folden. IKKE i scope: energi-innholdet i realistisk skala (§1 pkt. 7 = egen senere innholds-produksjonsjobb, avhengig leveranse); validator↔bibliotek-kobling (framtidig beslutning); toolkit-fabrikken (D-G, eget repo).
  • Avhengigheter: commons-amendment for innholdsmodellen (D-F-utkast operatør-godkjent + git subtree pull) FØRST; koordineres med S3.2 (multi-kandidat — deler seed/frontmatter-stien). Etter S2.0/S2.1/S2.5.
  • Filer: okf.py (trinnvis lesing / sammendrag-seam — MAF-fri, håndhevet av test_okf_is_maf_free), ny dimension_catalog.py (loader, fail-fast), ingest.py (bibliotek-kildefamilie), commons-spec + eksempel-katalog (i commons — flagg), repo-lokal bibliotek-fixture under data/, nye tester.
  • TDD: (1) RØD: dimensjonskatalog med ugyldig felt (ukjent allowed_measure_type-referanse) → fail-fast ved lasting — detach-punkt: fjern skjema-valideringen → passerer → rød; (2) RØD: materialisert bibliotek-fil når forslags-prompten via bundle_context (markør fraværende fra bundelen ellers) — detach materialiseringen → markøren forsvinner → rød; (3) RØD: trinnvis lesing gir sammendraget i navigert kontekst men IKKE fulltekst før eksplisitt henting — detach sammendrag-seamen → hele fullteksten stuffes inn → rød; (4) RØD: en bibliotek-fil MÅ ALDRI nå hypotese-prompten via dom-kanalen (separasjons-kontroll — biblioteket lekker aldri inn i ExpeL-folden).
  • Nøkkelantakelser: trinnvis-lesing-kravet (D-F pkt. 6) kan realiseres uten å bryte method-spec §3 Steg 1s render-kontrakt — HVIS ikke, er sammendrag-seamen del av commons-amendmenten (flagges eksplisitt, jf. revisjonspakke §6-nøkkelantakelsen). Bibliotek-fixture ligger repo-lokalt under data/ (aldri i shared/) til energi-innholdet materialiseres.
  • Verifisering: nye tester grønne + hvert detach-punkt → rød; test_okf_is_maf_free utvidet grønn; full suite + ruff + mypy grønne. Flagg: commons-amendment + D7-speiling (egen sesjon i søsken-repoet).

S3.6 [NY] Kostnadssimulering før kjøring (D-I pkt. 3; offline, ikke gated)

  • Mål: operatøren ser estimert kost for en portefølje-kjøring FØR den startes — what-if over modell-mappet (modeller × effortnivåer) — så kjøringskost blir en informert beslutning, ikke en overraskelse etterpå.
  • Scope (revisjonspakke §4 pkt. 3): python -m portfolio_optimiser.costsim (+ funksjons-API): estimér tokens/kost for en gitt portefølje under valgt modell + effortnivå; prisdata som skjema- validert konfig (kr/1k tokens per modell, med kilde- + dato-felt — ALDRI hardkodet; fail-fast ved manglende/ugyldig pris); kvalitets-avveininger per modellvalg merket som veiledning med kilde, aldri målt fakta uten belegg; output = estimat-tabell (per rolle/modell/effort) + kost-mot-verdi-felt klart for verdirapporten (S5.4). Deler tak-begreper med budsjettmaskineriet (PortfolioBudget / BudgetMiddleware fra S3.4), men estimerer FØR kall. Adopsjonssti dokumenteres (start liten → eskaler med tilliten). IKKE: live prisoppslag (nettverk), faktisk modellkall (rent offline), kvalitets-benchmarking.
  • Avhengigheter: ingen commons-avhengighet (offline, stack-lokalt); drar nytte av S3.4 (budsjett-typer) og mater S5.4 (verdirapport). Kan bygges før S3.5.
  • Filer: ny costsim.py (ren stdlib + pydantic — MAF-fri, legg i _MAF_FREE_MODULES), data/pricing.example.json (skjema + eksempelpriser med kilde/dato), budget.py (deling av tak-begreper), nye tester.
  • TDD: (1) RØD: konfig uten pris for en modell i mappet → fail-fast «missing price for » — detach-punkt: fjern pris-valideringen → estimatet gjettes → rød; (2) RØD: estimatet er deterministisk og skalerer med modell × effort (to modeller, samme portefølje → forskjellig, reproduserbart estimat) — detach effort-faktoren → identisk estimat → rød; (3) RØD: hardkodet pris i kildekode fanges av grep-guard (pris MÅ komme fra konfig).
  • Nøkkelantakelser: token-estimatet kan bygges fra portefølje-formen (antall prosjekter × runder × tak) uten et modellkall — deterministisk øvre-grense-estimat, ikke prediksjon; merkes eksplisitt som estimat i output.
  • Verifisering: nye tester grønne + detach → rød; uv run python -m portfolio_optimiser.costsim gir estimat-tabell uten nettverk (grep-guard: ingen socket-sti i modulen); full gate grønn.

S4.0 [NY] Validator-forankring mot kostbaseline (F3, F8; gated: D-A pkt. 2)

  • Mål: affected_items avstemmes fail-closed mot prosjektets faktiske kostbaseline — den deterministiske gaten kan ikke lenger mates med hallusinerte kostlinjer.
  • Scope: baseline-projeksjon i bundle (cost-baseline.json: code→{quantity, unit_cost} — commons-amendment) + fra reference_domain.cost_items på road-stien; ny avstemmings-stage i validate_proposal (kode finnes ikke i baseline → Rejection; quantity/unit_cost utenfor toleranse → Rejection; toleranse konfig); metode-registry: metode-caps keyes via dimensjon/konfig, ikke strengen energy_efficiency (F8). Baseline-argument er VALGFRITT i første omgang (None = dagens oppførsel) så eksisterende suite står — men run-stiene SETTER den.
  • Avhengigheter: D-A + commons; S2.x-ingest kan generere baseline-projeksjonen (soft).
  • Filer: validator.py, run.py, okf.py (baseline-loader, fail-fast), commons-fixture, nye tester.
  • TDD: RØD: reviewens F3-scenario (dikta kode XX, 10 MNOK) → Rejection «unknown cost code» (detach avstemmingen → validated → rød); kontroll: ekte baseline-linje validerer som før.
  • Verifisering: nye tester grønne + detach → rød; golden uendret; full gate grønn. Flagg: D7-speiling. MÅ være grønn før M2.

S4.1 Azure/Foundry-preflight (offline) [roadmap D, offline-delen]

  • Mål: alt som KAN valideres uten et modellkall, valideres før operatøren betaler for ett.
  • Scope: python -m portfolio_optimiser.preflight --profile azure: env-kontrakt (PORTFOLIO_FOUNDRY_PROJECT_ENDPOINT satt + URL-form; deployment-navn ≠ REPLACE-WITH-*; modell-map-konsistens), credential-sjekk KUN som dokumentert manuelt steg (aldri auto-login). Nekter live-profil med placeholders (fail-fast også i resolve_model-stien). Dokumentér auth-oppskrift (Entra: az login / DefaultAzureCredential; FoundryChatClient tar project_endpoint+model+credential — verifisert mot MS Learn, se review §6). Env-override for model_map (PORTFOLIO_MODEL_MAP sti) så tenant-navn aldri committes.
  • Avhengigheter: ingen (uavhengig av Fase 2/3).
  • Filer: ny preflight.py, backends.py, contracts.py (placeholder-regel), tester.
  • TDD: RØD: placeholder-deployment + azure-profil → strukturert nekt (detach placeholder-sjekken → rød); RØD: manglende endpoint-env → aksjonérbar feilmelding.
  • Verifisering: uv run python -m portfolio_optimiser.preflight --profile azure gir korrekt nekt/OK uten nettverk (bevis: kjør med nettverk utilgjengelig antatt — ingen socket-kode i modulen, grep-guard); full gate grønn.

S4.2 Live-kjørings-drill + artefakt-fangst (offline) [roadmap D, offline-delen]

  • Mål: den ENE fremtidige live-kjøringen (M2) er ferdig-rigget: alt bygges, artefakter fanges, og drillen er øvd offline.
  • Scope: --live-dry-run-modus i main(): last kontrakter, bygg klienter, valider budsjett, STOPP før første modellkall (bevist med kall-tellende mock); kjøringskonfig-logg (modell-id, parametre, tak — sammenligningsprotokoll §4.3); outbox-fangst (S2.1) av proposal/checker/ validator/tokens per §4.2.
  • Avhengigheter: S2.1, S4.1.
  • Filer: run.py, preflight.py/main, tester.
  • TDD: RØD: dry-run mot mock-faktory → null chat-kall skjedde (detach stopp-punktet → kall telles → rød); RØD: artefakt-settet komplett i outbox.
  • Verifisering: nye tester grønne; full gate grønn.

S5.1 Verdict-ruting + sporing [roadmap E]

  • Mål: teamet ser hvilke forslag som venter på dom, og hvem som skal dømme.
  • Scope: pending-registry = outbox-forslag uten matchende inbox-dom (id-join); ruting-konfig dimension → ekspert (fail-fast skjema); CLI python -m portfolio_optimiser.hitl pending|route; ren fil-basert (ingen server). IKKE: varsling (S5.2), web-UI.
  • Avhengigheter: S2.1 (outbox); S2.0 (verdict_dir i portefølje).
  • Filer: ny hitl.py, tester.
  • TDD: RØD: forslag i outbox uten dom → listes utestående; dom lander i inbox → forsvinner (detach id-joinen → rød).
  • Verifisering: nye tester grønne; full gate grønn.

S5.2 Varsling — B11 fra stub til ekte [roadmap E]

  • Mål: notify= får leverbare implementasjoner uten å bryte ingen-stille-egress.
  • Scope: Notifier-protokoll + console/file/webhook-impl; webhook krever eksplisitt per-kjøring opt-in-flagg (mirror allow_network, ingest §8-mønsteret) + injiserbar transport (canned i tester — null socket i suiten); konfig fail-fast.
  • Avhengigheter: S5.1 (naturlig kobling), ellers uavhengig.
  • Filer: ny notify.py, run.py (seam består), tester.
  • TDD: RØD: webhook uten opt-in → nekt fail-fast (detach → rød); RØD: canned transport mottar korrekt payload; RØD: ingen socket-sti utenfor den injiserbare seamen (grep-guard à la _urllib_get).
  • Verifisering: nye tester grønne; full gate grønn.

S5.3 CLI-paritet + dokumentsync (P6, F12-rest)

  • Mål: operatøren kan drive ALT bygget (dimensjon, mål, ledger, bundle-portefølje, inbox, outbox) fra kommandolinja, og dokumentene påstår nøyaktig det koden gjør.
  • Scope: main() (+ evt. portfolio-subkommando): --dimension-config, --ledger, --goals, --bundle-dir, --verdict-dir, --outbox-dir; README/extending.md/CHANGELOG-sync; ærlighets-grep (ingen «learning loop»-claims på stier uten fold).
  • Scope (D-H pkt. 1, tillegg): oppsett-oppskrift som dokumentleveranse — dokumentert team-prosess (teknisk + fag) for å bygge en kunnskapsbase, med ærlig README-forventning (en god base tar 12 uker dedikert arbeid; kvaliteten på investeringen avgjør resultatet); IKKE en veiviser / B9-onboarding- intervju (FORKASTET).
  • Avhengigheter: S2.0, S2.1 (og drar nytte av alt over).
  • Filer: run.py, README.md, docs/extending.md, CHANGELOG.md, CLI-tester.
  • TDD: RØD: CLI-kjøring med goals+ledger på fixtures → GoalReached-stopp observerbar i output.
  • Verifisering: CLI-tester grønne; full gate grønn; manuell uv run python -m portfolio_optimiser.run …-røyk på fixtures dokumentert i STATE.

S5.4 [NY] Verdirapport per kjøring (D-I pkt. 2)

  • Mål: hver kjøring (og porteføljepass) produserer en deterministisk verdirapport — modellert → ekspert-korrigert → realisert per prosjekt/dimensjon, målprogresjon, tallfestet læringseffekt og kost-mot-verdi — som artefakt, uten et eneste modellkall.
  • Scope (revisjonspakke §4 pkt. 2): hovedbok-basert rapportgenerator over ledgeren + outbox (S2.1): (a) besparelses-kolonner modellert/korrigert/realisert per prosjekt + dimensjon; (b) målprogresjon mot GoalContract; (c) læringseffekt tallfestet — godkjenningsandel per kjøring + om modellert-vs- forventet-gapet krymper over kjøringer; (d) kost-mot-verdi («kjøringen kostet X, identifiserte kvalitetssikret modellert besparelse Y» — X fra S3.6-estimat / faktisk token-forbruk). Rapport = deterministisk artefakt (JSON + markdown-render; sort_keys / indent / LF / byte-stabil). Ærlighet: realiserte tall KUN der dom finnes; modellerte merkes som modellert (aldri salgsspråk over beleggsnivået, D-I pkt. 1). IKKE: web-dashboard, live-oppdatering, modellkall.
  • Avhengigheter: S2.1 (outbox — forslag/utfall-artefakter) + ledger (S2.0-læringssløyfe); konsumerer S3.6-kostestimat for kost-mot-verdi-feltet.
  • Filer: ny valuereport.py (ren stdlib + pydantic — MAF-fri, _MAF_FREE_MODULES), run.py (opt-in --value-report), nye tester.
  • TDD: (1) RØD: to kjøringer med økende godkjenningsandel → læringseffekt-metrikken stiger og gap-krympingen rapporteres — detach-punkt: fjern gap-beregningen → flat/feil → rød; (2) RØD: prosjekt uten dom → «realisert» er tomt/umerket, ALDRI lik modellert — detach ærlighets-grensen → realisert = modellert → rød; (3) RØD: byte-determinisme (samme ledger + outbox → identisk rapport, diff).
  • Nøkkelantakelser: ledgeren + outbox bærer allerede alt rapporten trenger (modellert fra proposal, korrigert/realisert fra dommene, kost fra token-forbruk / S3.6) — rapporten er ren projeksjon, ingen ny tilstand (test: bygg rapport fra committede fixtures uten kjøring).
  • Verifisering: nye tester grønne + detach → rød; run.py --value-report på fixtures gir byte-stabil rapport uten nettverk; full gate grønn.

4. Operatør-gatede milepæler (IKKE autonome Opus-sesjoner)

M1 — Foundry-tenant-oppsett + smoke (etter S4.1)

  • Forutsetninger: operatør oppretter i tenant: én Foundry-prosjekt-endpoint + ÉN Global-Standard-deployment av billig modell (gpt-4o-mini-/gpt-5-mini-klassen — én deployment dekker begge roller; research-verifisert). az login. Sett PORTFOLIO_FOUNDRY_PROJECT_ENDPOINT + PORTFOLIO_FOUNDRY_DEPLOYMENT + model_map-override.
  • Manuelle steg: kjør preflight (S4.1) → grønn; kjør uv run pytest tests/test_foundry_profile_live.py.
  • Kost: ett trivielt kall (øre-nivå; pris ikke verifisert — sjekk Azure-priser først).

M2 — Første live-modell-kjøring, liten skala (etter S4.0 + S4.2 + M1)

  • Forutsetninger: S4.0 grønn (validator forankret — F3 lukket FØR ekte modell), harde tak satt lavt (f.eks. max_tokens 20k), outbox-fangst på.
  • Manuelle steg: én run_project mot energi-bundelen, azure-profil; artefakter arkiveres; utfall re-rulles IKKE (sammenligningsprotokoll §4.5).
  • Kost: én kjøring innenfor taket; dokumenteres i rapport med konfig-logg.

M3 — Fase 6-pilot (etter Fase 5 + M2 + D-B-amendment for live kilde)

  • Forutsetninger: én ekte kilde (per §4.4-beslutningen) herdet og materialisert med ekte provenance; én ekte fagekspert onboardet på inbox/outbox-kontrakten (samme mappe-grensesnitt som personaen); ruting+varsling (S5.1/S5.2) i drift; ingest-målbilde-amendment på plass (P1).
  • Manuelle steg: én dimensjon × ett prosjekt ende-til-ende; verifiser målbilde §7-sløyfa mot virkeligheten; FØRST deretter skalering mot N×10.

5. Avhengighetsgraf + anbefalt sekvens

flowchart TB
    subgraph DEC["Beslutnings-sesjoner (operatør)"]
        DA["D-A spec-amendments"]; DB["D-B Fase2-scope/ingest-målbilde"]
        DC["D-C vektor-store"]; DD["D-D concurrency"]; DE["D-E mål/paritet"]
    end
    S20["S2.0 portefølje-læring (F1)"]; S21["S2.1 outbox (P4)"]; S25["S2.5 inbox-herding (F7/F11)"]
    S27["S2.7 validator-stramming (F2)"]; S22["S2.2 MCP-ingest"]; S23["S2.3 doc-konnektor"]; S24["S2.4 http-herding"]
    S31["S3.1 semantisk henting"]; S32["S3.2 multi-kandidat (F5)"]; S33["S3.3 concurrent (F6)"]; S34["S3.4 kost på tvers (F10)"]
    S40["S4.0 kostbaseline-forankring (F3)"]; S41["S4.1 preflight"]; S42["S4.2 live-drill"]
    S51["S5.1 ruting/sporing"]; S52["S5.2 varsling"]; S53["S5.3 CLI-paritet"]
    S35["S3.5 innholdsmodell/bibliotek (D-F)"]; S36["S3.6 kostnadssimulering (D-I)"]; S54["S5.4 verdirapport (D-I)"]
    DFC["D-F commons-amendment (PULL-ONLY)"]; T0[["T0 toolkit-repo (eget repo — okf-toolkit)"]]
    M1{{"M1 tenant+smoke"}}; M2{{"M2 første live-kjøring"}}; M3{{"M3 pilot"}}

    DA --> S27; DA --> S32; DA --> S40
    DB --> S22; DB --> S23; DB --> S24; DB -. amendment .-> M3
    DC --> S31; DD --> S33; DD --> S34; DE --> M2
    S20 --> S33; S20 --> S51; S21 --> S42; S21 --> S51
    S41 --> M1; S40 --> M2; S42 --> M2; M1 --> M2
    S51 --> S52; S20 --> S53; S21 --> S53
    S33 --> M3; S34 --> M3; S52 --> M3; M2 --> M3; S31 --> M3; S32 --> M3
    DFC --> S35; S32 -. koordineres .-> S35
    S21 --> S54; S34 -. kost .-> S54; S36 -. kost-mot-verdi .-> S54
    T0 -. fabrikk .-> M3

Anbefalt sesjonssekvens (parallellitet mulig der grafen tillater; én fase = Voyage-syklus):

  1. D-A, D-B (kan tas i samme operatør-bolk; D-C/D-D/D-E kan vente)
  2. S2.0 → S2.1 → S2.5 (ingen beslutnings-avhengighet — kan starte FØR/parallelt med D-runden)
  3. S2.7 (etter D-A + commons-pull) · S2.2 → S2.3 → S2.4 (etter D-B)
  4. D-C, D-D, D-ES3.1 → S3.2 → S3.4 → S3.3; S3.5 etter D-F commons-amendment + koordinert med S3.2; S3.6 fritt (offline, når som helst — mater S5.4)
  5. S4.1 (når som helst) → M1 (operatør) · S4.0 → S4.2M2 (operatør)
  6. S5.1 → S5.2 → S5.3 · S5.4 etter S2.1 + ledger → M3 (operatør; krever også D-B-amendment + ekte ekspert + toolkit-fabrikken T0)

Ekstern avhengighet (T0 toolkit-repo, eget repo — okf-toolkit, D-G): delt OKF-modul + conformance

  • bundle-evaluator + bundle-fabrikk lever i sitt eget signatur-repo, utenfor denne sesjonskøen. Fabrikk-avhengige deler av D-F/D-H (realistisk energi-innhold via fabrikken, ekspert-dom-oversettelse, demo-sti, M3-pilot) er blokkert til T0 finnes; S3.5/S3.6/S5.4 er valgt slik at de IKKE er fabrikk-gatede.

Offline-fullførings-grensen går etter S5.3/S5.4: alt over den linjen er gratis, autonomt og load-bearing-testbart (også de nye S3.5/S3.6/S5.4). To ikke-autonome forbehold blant det nye: S3.5s commons-amendment (operatør-godkjenning + PULL-ONLY) og T0 toolkit-repoet (eget repo). M1M3 er fortsatt de eneste stegene som koster penger, krever tenant eller krever et menneske.