docs(review): full-paritet review + sesjonsplanverk + beslutningsbrief (Fable 5 + 6 Opus-agenter)
Operatør-mandat 2026-07-16: full MAF-paritet (D-G pkt. 2). Review-økt, ingen kildekode. - review-paritet.md: C-serien re-verifisert (alle åpne), 10 nye R-funn. Kjørt-bevist av orkestrator: R-2 (Infinity → validates=True, NaN avvist), R-3 (tom CSV krasjer ingest → delvis bundle). R-1 = §11-raden «Closed loop» ubundet. 4/4 detach røde i throwaway-kopi; SDK-premisser holder mot 0.2.110→0.2.120; model-id gyldig+billigst; docs §1-ærlige. - sesjonsplan-paritet.md: ERSTATTER 2026-07-10-planen. 35-raders paritetsmatrise (opphevet «Overføres IKKE»-lista, re-klassifisert rad for rad). 16 ugatede sesjoner + gatede med eksakte utløsere + avhengighetsgraf + binær leveringsklar-sjekkliste. - beslutningsbrief.md: operatør-køen i klarspråk (D-A+C-P1, amendment, toolkit-§8, D-B, + nytt foreslått delt punkt). - 2026-07-10-sesjonsplan-d7.md: superseded-merket med peker. Steg 0 verifisert: commons-amendment IKKE landet, okf-toolkit-repo finnes IKKE. STATE.md er local-only (gitignored) — ikke committet. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b46f32c682
commit
d746891f06
4 changed files with 1254 additions and 1 deletions
|
|
@ -1,6 +1,12 @@
|
|||
# Sesjonsplan D7 — speilings-sesjoner + egne funn (C1.1–C4.0 · delt kø D-A–D-E)
|
||||
|
||||
> **Status:** GJELDENDE sesjonsplan for dette repoet. Forfattet av kryssmodell-reviewen
|
||||
> **⚠️ SUPERSEDED 2026-07-16:** erstattet av
|
||||
> [`2026-07-16-sesjonsplan-paritet.md`](2026-07-16-sesjonsplan-paritet.md) (operatør-mandat
|
||||
> full MAF-paritet; §4-listen «Overføres IKKE hit» er OPPHEVET og re-klassifisert der).
|
||||
> C-sesjonene C1.1/C2.0/C2.5/C2.7/C2.8/C3.2/C3.5/C4.0 er videreført i den nye planen.
|
||||
> Dokumentet under beholdes uendret som historikk.
|
||||
>
|
||||
> **Status:** ~~GJELDENDE~~ sesjonsplan for dette repoet. Forfattet av kryssmodell-reviewen
|
||||
> 2026-07-10 (Fable 5) — funn-referanser (C-F2/C-F3/C-F4/C-F5/C-F7, C-N1–C-N4, C-P1) peker
|
||||
> til [reviewen](review-2026-07.md); MAF-referanser (F1–F14, D-A–D-E, S2.x/S3.x/S4.x) peker
|
||||
> til hovedrepoets `docs/review-2026-07.md` og `docs/plan/2026-07-10-sesjonsplan-fase2-6.md`.
|
||||
|
|
|
|||
122
docs/2026-07-16-beslutningsbrief.md
Normal file
122
docs/2026-07-16-beslutningsbrief.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
# Beslutningsbrief til operatøren — hva som venter på deg, og hva det låser opp her (2026-07-16)
|
||||
|
||||
> Skrevet i klarspråk, uten funn-ID-er i selve spørsmålene (ID-er kun i fotnoter).
|
||||
> Beslutningene tas i HOVEDREPOETS delte kø — ingenting under besluttes i dette repoet.
|
||||
> Kontekst: operatør-mandatet 2026-07-16 er full paritet med MAF-repoet; den nye
|
||||
> [sesjonsplanen](2026-07-16-sesjonsplan-paritet.md) planlegger rundt gatene under, aldri
|
||||
> forbi dem. Alt ugatet arbeid (16 sesjoner) kan kjøres uavhengig av alle punktene her.
|
||||
|
||||
## 1. Spec-rettelsene i regelverket (den delte «D-A»-bolken)
|
||||
|
||||
**Hva det gjelder:** Fire kjente svakheter i det delte regelverket begge søsken bygger fra:
|
||||
(1) validatoren har en beregnet «maksimalt gjennomførbar besparelse»-grense som aldri
|
||||
håndheves, og modellen forfatter selv usikkerhetsbåndene som kan blåse den; (2) det finnes
|
||||
ingen forankring mot prosjektets faktiske kostlinjer, så oppdiktede kostlinjer kan passere
|
||||
validering; (3) lenkeformen med ledende skråstrek, som standardformatet anbefaler, hoppes over
|
||||
i stedet for å forstås; (4) læringslageret nøkler alle dommer i en bundle på ett og samme
|
||||
kandidat-tiltak, så dommer om ulike tiltak blandes.
|
||||
|
||||
**Hva det låser opp her:** fire ferdig-spesifiserte byggesesjoner med kjørte moteksempler som
|
||||
test-fixtures.¹ Rettelse (2) er i tillegg et absolutt krav FØR en eventuell ny live-kjøring.
|
||||
|
||||
**Anbefaling:** godkjenn alle fire som én bolk. Kompatibiliteten er ferdig verifisert på denne
|
||||
siden: regel-strammingen (1) bryter verken fasit-eksemplet eller noen eksisterende testdata.
|
||||
Etter godkjenning: rettelsene skrives i fellesrepoet, BEGGE søsken henter dem, og BEGGE
|
||||
testsuiter kjøres — aldri én side alene.
|
||||
|
||||
**Ta samtidig stilling til en kollisjon vi har flagget:** planen for semantisk henting (egen
|
||||
beslutning, se pkt. 5) står i dag i direkte konflikt med regelverkets frosne krav om at
|
||||
likhets-rangering aldri skal bygge på overflatetekst. Enten må regelverket bevisst amenderes
|
||||
på det punktet (som del av denne bolken), eller så må semantisk henting re-scopes til å bygge
|
||||
på strukturelle kjennetegn alene.² **Anbefaling:** re-scoping — det bevarer det frosne
|
||||
prinsippet og er implementerbart uten regelendring.
|
||||
|
||||
## 2. Innholdsmodell-amendmenten (kunnskapsbibliotek + dimensjonskatalog)
|
||||
|
||||
**Hva det gjelder:** Utkastet fra 14. juli (ligger klart i hovedrepoet³) som gir regelverket
|
||||
et kildebelagt kunnskapsbibliotek (tiltaksmønstre/erfaringsnotater/faglige råd), en
|
||||
dimensjonskatalog som konfig, og «sammendrag først»-lesing så biblioteket kan vokse uten å
|
||||
drukne prompten. Venter kun på din godkjenning av teksten.
|
||||
|
||||
**Hva det låser opp her:** hele bibliotek-/katalog-sesjonen i dette repoet (K13 i den nye
|
||||
planen) — som også er dette repoets eneste planlagte kilde til dimensjons-begrepet, som igjen
|
||||
gir ruting og scoping full verdi. Tilsvarende sesjon på MAF-siden (S3.5) venter på det samme.
|
||||
|
||||
**Anbefaling:** godkjenn utkastet. Det er konstruert for å holde begge repoenes
|
||||
spec-integritetsvakter grønne, og fasit-eksemplene endres ikke. Merk at dette repoets egen
|
||||
spec-vakt bygges i første ugatede sesjon (C1.1) med samme robusthet, så amendmenten kan landes
|
||||
før eller etter den — rekkefølgen er likegyldig.
|
||||
|
||||
## 3. Verktøykasse-repoet (okf-toolkit)
|
||||
|
||||
**Hva det gjelder:** Besluttet 14. juli: felles formatverktøykasse i eget repo. Repoet finnes
|
||||
ennå ikke (verifisert i dag), og briefens fire åpne spørsmål venter på deg: endelig navn,
|
||||
lisens (MIT-presedens), publiseringsrekkefølge (kjerne først?), og bekreftelse på eget
|
||||
Forgejo-repo.⁴
|
||||
|
||||
**Hva det låser opp her:** skrive-halvdelen av formatlaget, som dette repoet mangler og
|
||||
MAF-repoet har — selve hovedgevinsten i «minst like godt»-mandatet ditt. Adopsjonssesjonen
|
||||
(K20) er planlagt og venter kun på at verktøykassa finnes og at du godkjenner koordinert
|
||||
migrering i begge søsken samtidig.
|
||||
|
||||
**Anbefaling:** svar på de fire spørsmålene og kjør repo-init-prompten i briefen. Inntil da
|
||||
er skrive-halvdelen udekket her, og skråstrek-lenkerettelsen (pkt. 1.3) bygges lokalt med en
|
||||
eksplisitt merknad om senere flytting inn i verktøykassa.
|
||||
|
||||
## 4. Omfanget for ekte datakilder (den delte «D-B»-beslutningen)
|
||||
|
||||
**Hva det gjelder:** Om (og hvordan) ingest-laget skal utvides mot virkeligheten:
|
||||
MCP-kildefamilie, PDF-dokumentkilde, og http/live-kilde med herding — som i dag er bevisst
|
||||
avvist i begge søsken og krever en bevisst amendment av det frosne ingest-målbildet.
|
||||
|
||||
**Hva det låser opp her:** tre konnektor-sesjoner (K14–K16). Merk endringen fra forrige plan:
|
||||
paritetsmandatet ditt betyr at disse nå SKAL speiles her når beslutningen lander — den gamle
|
||||
planens «ingen HTTP/MCP-økt i dette repoet» er opphevet. Sikkerhetsvakten
|
||||
(llm-ingestion-guard) wires inn i samme økt som http-kilden — det er dens hovedplass.⁵
|
||||
|
||||
**Anbefaling:** som MAF-planens anbefaling (nedskop til mock-herding nå; SQL som første
|
||||
live-kilde senere) — men med eksplisitt tillegg om at amendmenten skrives felles så begge
|
||||
søsken bygger samme kildefamilier.
|
||||
|
||||
## 5. De øvrige delte beslutningene (vektor-lager, samtidighet, mål/paritet)
|
||||
|
||||
**Hva det gjelder / låser opp her:**
|
||||
- **Vektor-lager** (semantisk henting): låser opp K17 her — MEN se kollisjonen i pkt. 1.
|
||||
- **Samtidighet/feilmodell:** låser opp K18/K19 her (parallell porteføljekjøring +
|
||||
kostnadsstyring på tvers). Blir først aktuelt etter at porteføljefundamentet (K1–K3, ugatet)
|
||||
er bygget — ingen hast fra dette repoets side.
|
||||
- **Mål-semantikk + stack-paritet for ekte kjøring:** låser opp prosentmål-delen av
|
||||
målkontrakten her, og avgjør om dette repoet i det hele tatt skal kjøre live igjen
|
||||
(M2-analogen). Uten den beslutningen bygges alt live-forberedende (estimat, preflight,
|
||||
drill) ferdig offline — og stopper der.
|
||||
|
||||
**Anbefaling:** ingen hast på noen av disse tre fra dette repoets side; ta dem når MAF-løpet
|
||||
trenger dem. Kun koblingen i pkt. 1 (semantisk henting vs. frossen rangeringsregel) bør tas
|
||||
NÅ, fordi den hører hjemme i samme bolk som spec-rettelsene.
|
||||
|
||||
## 6. NYTT beslutningsbehov avdekket av paritetsplanen (foreslås inn i den delte køen)
|
||||
|
||||
**Hva det gjelder:** Paritetsplanen gir dette repoet en besparelses-hovedbok, målkontrakt og
|
||||
outbox (K1/K5) som MAF allerede har — men formatene er i dag stack-lokale på begge sider.
|
||||
Skal de to søsknenes hovedbok-/outbox-artefakter være SAMMENLIGNBARE på filnivå (delt format i
|
||||
fellesrepoet), eller holder det at kapabiliteten er lik mens formatene divergerer?
|
||||
|
||||
**Hvorfor det er ditt valg:** delt format krever en commons-amendment (mer koordinering, men
|
||||
direkte sammenlignbare kjøringsartefakter til sammenligningsprotokollen og verdirapporten);
|
||||
stack-lokalt er raskere og kan konvergeres senere via verktøykasse-repoet.
|
||||
|
||||
**Anbefaling:** stack-lokalt NÅ (K1/K5 bygger uten å vente), med eksplisitt
|
||||
konvergens-vurdering når verktøykassa (pkt. 3) og verdirapportene på begge sider finnes.
|
||||
Foreslås protokollert som nytt punkt i den delte køen i hovedrepoet — ikke besluttet her.
|
||||
|
||||
---
|
||||
|
||||
**Fotnoter (pekere for etterprøving):**
|
||||
¹ D-A pkt. 1–4 ↔ funn C-F2/C-F3/C-F4/C-F5 (`review-2026-07.md` §1) → sesjonene
|
||||
C2.7/C4.0/C2.8/C3.2 (`2026-07-16-sesjonsplan-paritet.md` §4).
|
||||
² C-P1 (`review-2026-07.md` §1) — method-spec §3 Steg 1 «structural, never textual» vs
|
||||
MAF-planens S3.1/D-C.
|
||||
³ `portfolio-optimiser/docs/plan/2026-07-14-commons-amendment-utkast.md` (§5.2 flagger
|
||||
D7-speilingen eksplisitt).
|
||||
⁴ `portfolio-optimiser/docs/plan/2026-07-14-toolkit-repo-brief.md` §8.
|
||||
⁵ `docs/2026-07-16-llm-ingestion-guard-plan.md` §4 G1; K16 i den nye sesjonsplanen.
|
||||
374
docs/2026-07-16-review-paritet.md
Normal file
374
docs/2026-07-16-review-paritet.md
Normal file
|
|
@ -0,0 +1,374 @@
|
|||
# Review-paritet — portfolio-optimiser-claude (2026-07-16)
|
||||
|
||||
> **Reviewer:** Fable 5 (xhigh) som orkestrator + seks Opus 4.8 xhigh-subagenter (spec-
|
||||
> konformitet, sikkerhet/injeksjon, SDK+model-map, testkvalitet/detach, ærlighet §1,
|
||||
> korrekthet). **Mandat:** full review + paritetsgap-kartlegging under operatør-mandatet FULL
|
||||
> MAF-PARITET (2026-07-16). Ingen live-fil endret; alle kjørbare eksperimenter i throwaway-
|
||||
> kopier (scratchpad) med import-isolasjon verifisert, eller rene in-memory-kall mot
|
||||
> live-moduler (read-only). Ingen API-kall, ingen nettverk (unntatt SDK-agentens
|
||||
> dokumentasjons-oppslag mot PyPI/Anthropic, eksplisitt tillatt).
|
||||
>
|
||||
> **Ny funn-serie R (kolliderer ikke med C-serien i [review 2026-07-10](review-2026-07.md)).**
|
||||
> Paritetsmatrisen + sesjonsplanen ligger i
|
||||
> [`2026-07-16-sesjonsplan-paritet.md`](2026-07-16-sesjonsplan-paritet.md); operatør-køen i
|
||||
> [`2026-07-16-beslutningsbrief.md`](2026-07-16-beslutningsbrief.md).
|
||||
|
||||
## 0. Baseline (verifisert 2026-07-16, ikke sitert fra STATE)
|
||||
|
||||
| Påstand | Resultat | Belegg |
|
||||
|---|---|---|
|
||||
| Testsuite | **265 passed** (1.68s) — STATE-tallet stemmer | `uv run pytest -q` (kjørt) |
|
||||
| Lint / format / typer | ruff clean (40 filer) · ruff format clean · mypy clean (16 filer, strict) | kjørt |
|
||||
| Push-status | HEAD `b46f32c` == `origin/main`; `open/main` @ `42f320b` (to review/guard-commits foran open — bevisst ikke speilet); `commons/main` @ `84191c6` | `git rev-parse` alle |
|
||||
| Subtree-status | `shared/` 2 commons-commits bak (docs-only: `.gitignore` + guard-adopsjonsdoc — INGEN spec-endring) | subtree-diff `HEAD:shared`↔`commons/main` |
|
||||
| Commons-amendment (D-F/D-G) | **IKKE landet** i commons | samme diff |
|
||||
| okf-toolkit-repo | **finnes ikke** (lokalt + Forgejo) | `ls` + `git ls-remote` → not found |
|
||||
| Detach-stikkprøver (4/4) | ALLE RØDE i kopi, revert→grønn, arbeidstre urørt | testkvalitetsagent, §3 |
|
||||
| SDK-premisser | alle attributter holder mot installert 0.2.110 + t.o.m. nyeste 0.2.120 | SDK-agent, §2 |
|
||||
| S10-artefakter | `runs/s10/` urørt (fasit) — kun lest | ikke re-kjørt |
|
||||
|
||||
**Konklusjon baseline:** ingen BLOCKER. STATE-ens tall er korrekte. De nye funnene under er
|
||||
robusthets-/korrekthetsdefekter (mest alvorlige R-2/R-3, begge MEDIUM) + paritetsgap +
|
||||
konformitetsgapet R-1 (§11-raden «Closed loop» ubundet).
|
||||
|
||||
---
|
||||
|
||||
## 1. Status på eksisterende funn (C-serien, review 2026-07-10)
|
||||
|
||||
Alle re-verifisert; ingen har endret premiss. Stikkprøvene under er kjørt på nytt, ikke sitert.
|
||||
|
||||
| C-funn | Status 2026-07-16 | Belegg (re-verifisert) |
|
||||
|---|---|---|
|
||||
| C-F2 (nominal gater aldri) | **ÅPEN, bekreftet** | `validator.py:53` beregner `nominal_feasible`, `:73` bruker den kun i avvisnings-*meldingen*; eneste numeriske gate er p90 (`:68`) |
|
||||
| C-F3 (ingen kostbaseline) | **ÅPEN, bekreftet** | `ir.py:43-48` sjekker kun claim ≤ Σ quantity·unit_cost; diktede kostlinjer validerer |
|
||||
| C-F4 (`/`-lenker skippes) | **ÅPEN, spec-tro** | `okf.py:112` skip; spec §3 Steg 1 pinner regelen |
|
||||
| C-F5 (seeding-nøkling) | **ÅPEN med nyanse** | features fra `load_validator_input(bundle_dir)` (`experience.py:132`), ikke per verdict-fil; id-halvdel løst (verbatim `verdict_id` `:147`). Ny konkret drop/count-effekt: **R-8** |
|
||||
| C-F7 (inbox-injeksjon) | **ÅPEN, kjørt-bevist på nytt** | injeksjons-`rationale` OG `decision` når prompt verbatim; `decision` tillater newline som bryter linjeformatet (sikkerhetsagent §a). Ny run-path-nyanse: **R-9** |
|
||||
| C-N1 (method-spec-vakt mangler) | **ÅPEN, bekreftet** | ingen `test_method_spec_loadbearing.py`; §12-kompletthet dermed ikke håndhevet (spec §12 lover det) |
|
||||
| C-N2 (Steg-7 kjøresti-inngang) | **ÅPEN, bekreftet** | `merge_inbox_into_store` refereres kun fra tester (grep); `run_s10.py` har ingen `--inbox` |
|
||||
| C-N3 (løs SDK-pin) | **ÅPEN, bekreftet** | `pyproject.toml:8` `>=0.2` uten øvre grense; «verifisert mot 0.2.110» kun i docstrings, ingen kjørbar versjonssjekk. Anbefalt pin nå: `>=0.2.111,<0.3` (§2) |
|
||||
| C-N4 (budsjett post-charge / USD per-kall) | **ÅPEN, bekreftet** | `charge_tokens` etter `client.complete` (`loop.py:90-91`); per-kall-USD via `max_budget_usd`, ingen run-total |
|
||||
| C-S1 (REJECT-substring-presedens) | **ÅPEN, spec-pinnet** | `_REJECT_PATTERN` først med presedens (`loop.py:188-191`) |
|
||||
| C-S2 (max_rows etter innlesing) | **ÅPEN, bekreftet + utvidet** | `_read_csv` (`ingest.py:191-195`) OG `_read_sql` `fetchall()` (`:244-248`) — se **R-7** |
|
||||
| C-S3 (promotion RMW ikke-atomisk) | **ÅPEN, dokumentert MVP-grense** | `promotion.py:92-103` |
|
||||
| C-P1 (D-C ↔ frossen §3 Steg 1) | **ÅPEN, delt** | står til D-A-bolken (beslutningsbrief pkt. 1); `test_surface_text_never_contributes` håndhever regelen i dag |
|
||||
|
||||
---
|
||||
|
||||
## 2. Nye funn (R-serien, rangert)
|
||||
|
||||
### R-1 [MEDIUM · konformitet] §11-raden «Closed loop» er ubundet — `test_simulation_loadbearing.py` mangler
|
||||
|
||||
- **Belegg:** method-spec §11 (`method-spec.md:408`) navngir sømmen «the two-run simulation's
|
||||
marker crosses runs [via] promotion (or fails to cross with it)». Filen finnes ikke; ingen
|
||||
test importerer både `promote` og en run-komposisjon (grep, spec-konformitetsagent). Den
|
||||
nærmeste — `test_step8_promotion_loadbearing.py:143` — binder `promotion→seed→fold` (markør i
|
||||
prompt), IKKE en to-kjørings-simulering med negativ kontroll. `test_step7` binder
|
||||
to-kjørings-flippen, men via **inbox**-stien, ikke promotering.
|
||||
- **Feilscenario:** hvis promoterings-stien slutter å lukke lærings-loopen på run-nivå
|
||||
(promotert verdict seedes ikke inn i en senere kjøring), går INGEN test rød. Dette er §11s
|
||||
eneste udekkede rad utover C-N1s spec-vakt.
|
||||
- **Distinkt fra C-N1** (spec-integritet, §11 rad 11) og **C-N2** (Steg-7 kjøresti-inngang,
|
||||
D7-egen kjørbarhet). R-1 er §11 rad 8.
|
||||
- **Fiks:** ny `tests/test_simulation_loadbearing.py` + tynn deterministisk to-run-driver
|
||||
(`simulation.py`, ScriptedClient) → sesjon **K4** (byggbar nå, forutsetter C2.0-inngangen).
|
||||
|
||||
### R-2 [MEDIUM · korrekthet] `Infinity` beseirer den deterministiske validatoren — KJØRT-BEVIST (også av orkestrator)
|
||||
|
||||
- **Belegg:** Pydantic v2 har `allow_inf_nan=True` som default, så `float('inf')` tilfredsstiller
|
||||
`unit_cost: Field(gt=0)` (`ir.py:27`) og de ubegrensede `assumptions`-båndene (`ir.py:37`);
|
||||
`json.loads` godtar det ikke-standard JSON-tokenet `Infinity`.
|
||||
- **Kjørt bevis (orkestrator, mot live-modul, read-only):**
|
||||
`unit_cost: Infinity` → `SavingsProposal` konstrueres, `validate_proposal` →
|
||||
`ValidatedProposal(validates=True, nominal_feasible=inf, p90=inf)`. Samme via
|
||||
`assumptions: {"A":[1.0, Infinity]}` → `validates=True, p90=inf`. **NaN avvises korrekt**
|
||||
(kontroll: `ValidationError`) — kun `inf` slipper gjennom.
|
||||
- **Feilscenario:** validatoren er spec-ens obligatoriske, blokkerende anker mot
|
||||
swarm-selvbekreftelse (§4). Ett `Infinity`-token fra proposer-modellen — nåbart på kjørestien
|
||||
via `loop._parse_candidate` — får ethvert claim til å klarere porten vakuøst (`claimed > inf`
|
||||
er alltid False).
|
||||
- **Fiks:** `allow_inf_nan=False` på de numeriske IR-feltene (eller eksplisitt finitthetssjekk
|
||||
av `quantity`/`unit_cost`/`claimed_saving_nok` + bånd-endepunkter). Ingen beslutnings-
|
||||
avhengighet, golden uendret (golden-tallene er finite) → sesjon **C2.6** (byggbar nå).
|
||||
|
||||
### R-3 [MEDIUM · korrekthet/robusthet] Tom kilde-CSV krasjer ingest MIDT i materialisering → delvis bundle
|
||||
|
||||
- **Belegg (kjørt av korrekthetsagent; mekanisme re-verifisert av orkestrator):**
|
||||
`_render_table([])` kaster `ValueError: not enough values to unpack` (`ingest.py:176`,
|
||||
`header, *data = rows`). `_read_csv` returnerer `[]` for 0-byte fil (`ingest.py:188-197`;
|
||||
`data_rows=0` → ingen max_rows-brudd fanger det).
|
||||
- **Feilscenario:** en ekstraksjon med tom CSV → krasj INNE i `materialize`s skrive-løkke,
|
||||
ETTER at stemplede filer er fjernet og tidligere ekstraksjoner skrevet, FØR `_update_index`
|
||||
→ bundle etterlatt delvis materialisert (bekreftet: `ingest-first.md` skrevet, ingen
|
||||
`index.md`, gamle stemplede filer allerede slettet). SQL-stien er immun (header alltid til
|
||||
stede).
|
||||
- **Fiks:** vokt tom `rows` med klar fail-fast FØR disk-mutasjon (eller behandle som tom
|
||||
tabell) → sesjon **K2.9** (byggbar nå).
|
||||
|
||||
### R-4 [LOW–MEDIUM · korrekthet] UTF-8 BOM korrumperer stille første CSV-header
|
||||
|
||||
- **Belegg (kjørt av korrekthetsagent; encoding re-verifisert av orkestrator: 5×
|
||||
`encoding="utf-8"`, ingen `utf-8-sig` i `ingest.py`):** Excel/Windows-CSV med ledende BOM →
|
||||
første header-celle blir `'code'` i stedet for `'code'`; korrupt header flyter verbatim
|
||||
inn i markdown-tabell + concept-fil. Ingen krasj — stille datakorrupsjon.
|
||||
- **Fiks:** les CSV med `utf-8-sig` → sesjon **K2.9**.
|
||||
|
||||
### R-5 [LOW–MEDIUM · robusthet] Malformert men EKSISTERENDE lenket concept-fil avbryter ALL bundle-navigasjon
|
||||
|
||||
- **Belegg (kjørt av korrekthetsagent):** `parse_concept_file(resolved)` i `navigate_bundle`
|
||||
(`okf.py:118`) kaster `ValueError` for en lenket fil som eksisterer men mangler
|
||||
frontmatter/`type` — fanges ikke. Robusthetsregelen (skip broken/escaping links) dekker kun
|
||||
ikke-eksisterende / utenfor-bundle mål.
|
||||
- **Feilscenario:** én dårlig generert/kuratert fil tar ned hele lese-konteksten: `bundle_context`,
|
||||
`build_citations` OG `seed_store_from_bundle` (seeding avbrytes helt i stedet for å hoppe over
|
||||
den ene fila). Kan være tiltenkt fail-fast — **asymmetrien mot skip-broken-links fortjener en
|
||||
eksplisitt beslutning** (tolerér-og-hopp vs fail-fast), ikke stille divergens.
|
||||
- **Fiks:** beslutt semantikk + bind med test → sesjon **K2.9** (med eksplisitt valg dokumentert).
|
||||
|
||||
### R-6 [LOW · sikkerhet, latent] `inbox.write_verdict` mangler id-grammatikk → path-traversal ved skriving
|
||||
|
||||
- **Belegg (kjørt av sikkerhetsagent; konstruksjon re-verifisert av orkestrator):**
|
||||
`VerdictDocument.id` er kun `Field(min_length=1)` (`inbox.py:46`) — ingen grammatikk, i
|
||||
motsetning til `source.id`/`extraction.id` (`_ID_RE`, `ingest.py:63-68,100-105`).
|
||||
`write_verdict` skriver `inbox_dir / f"{verdict.id}.json"` (`inbox.py:96`). Konstruksjon med
|
||||
`id="../../escaped"` aksepteres verbatim (orkestrator-kjørt) → skrivemål utenfor inbox.
|
||||
- **Feilscenario:** i dag ALLTID mintet id (`from_candidate`→`mint_verdict_id`, 16 hex) → ikke
|
||||
nåbar med fiendtlig input nå. Latent hvis en fremtidig sti skriver en verdict med untrusted id.
|
||||
Defensiv asymmetri beviser glippen: `promotion._filename_token` behandler samme id som
|
||||
fiendtlig (saniterer + hash-fallback, `promotion.py:34-40`).
|
||||
- **Fiks:** samme grammatikk/sanering før `write_verdict` eller på `VerdictDocument.id` → foldes
|
||||
inn i **C2.5** (inbox-herding).
|
||||
|
||||
### R-7 [LOW–MODERAT · robusthet] `_read_sql` materialiserer hele resultatsettet før `max_rows` (nytt tilfelle av C-S2)
|
||||
|
||||
- **Belegg (kjørt av sikkerhetsagent):** `cursor.fetchall()` (`ingest.py:244`) FØR
|
||||
`len(data) > max_rows` (`ingest.py:247`); 1000-rads tabell med `max_rows=10` → alle 1000 i
|
||||
minne før cap-en hever feil. Samme feilmodus som C-S2 i `_read_csv`.
|
||||
- **Feilscenario:** robusthet/DoS-mot-seg-selv (begge kilder førstepart-scopet), ikke
|
||||
angriper-drevet i dag. Fail-fast i UTFALL (aldri stille trunkering) — akseptabel MVP-grense.
|
||||
- **Fiks (valgfri):** `LIMIT max_rows+1` / `fetchmany` for SQL, streaming-tell for CSV → **K2.9**
|
||||
eller notér som akseptert MVP-grense.
|
||||
|
||||
### R-8 [LOW · korrekthet, knyttet til C-F5] `seed_store_from_bundle` over-rapporterer antall; seeds uten `verdict_id` kollapser stille
|
||||
|
||||
- **Belegg (kjørt av korrekthetsagent):** alle seedede verdicts deler SAMME features
|
||||
(bundle-IR-projeksjonen), så flere seed-filer UTEN `verdict_id` minter samme id →
|
||||
first-write-wins dropper alle utenom første, men funksjonen returnerer FIL-antallet
|
||||
(`experience.py:132,145-153`). To `type: verdict`-filer, ulik decision/rationale, ingen
|
||||
`verdict_id` → `seeded=2` returnert, `len(store)==1`; det andre læringssignalet tapes.
|
||||
`run_s10.py:86` printer det inflaterte tallet.
|
||||
- **Feilscenario:** konkret manifestasjon av C-F5s feature-halvdel + en count-ærlighetsfeil
|
||||
(rapportert antall ≠ faktisk lagret). Løses av per-verdict-nøkling (C3.2); count-ærligheten
|
||||
bør fikses uansett.
|
||||
- **Fiks:** C3.2 løser roten; legg en count-korreksjon (returner faktisk lagret antall, eller
|
||||
logg drops) i C3.2s scope.
|
||||
|
||||
### R-9 [MERKNAD · sikkerhet — presiserer C-F7/guard-plan, ikke ny defekt] Fold-som-injeksjonsbærer NÅR kjørestien via bundle-seeding
|
||||
|
||||
- **Belegg (kjørt av sikkerhetsagent):** mens inbox-injeksjonen (C-F7) ikke er wiret til noen
|
||||
kommando (C-N2), ER samme injeksjonsbærer wiret via den ANDRE folde-kilden:
|
||||
`run_s10.py:73` → `seed_store_from_bundle` leser `type: verdict`-frontmatter og folder den
|
||||
inn. En forgiftet `promoted-verdict-*.md` i bundelen nådde folded prompt på run-stien
|
||||
(kjørt: `- aaaa [approved]: IGNORE PRIOR INSTRUCTIONS ... INJECT-MARKER-SEED`). Seed-stien er
|
||||
single-line-begrenset (frontmatter-parser), så inbox er strengt verre — men *fold-som-bærer*
|
||||
treffer den faktiske kjørestien.
|
||||
- **Konsekvens for guard-planen:** dette er nøyaktig trust-grensen guard-planens §2 rad 5/6
|
||||
beskriver (mottatt/delt bundle med forgiftet promotert verdict). Bekrefter at G3
|
||||
(`okf.import_bundle` ved delt/mottatt bundle) er riktig plassert, og at promoterings-
|
||||
gaten (§6, fail-closed, kun ekspert-godkjent) er den nåværende beskyttelsen. **Ingen ny
|
||||
kodeendring kreves nå** — men guard-planens markørlinje bør nevne bundle-seed-stien
|
||||
eksplisitt som den wirede fold-bæreren (i dag nevner den inbox). Notert i STATE-oppdatering.
|
||||
|
||||
### R-10 [LOW · testdekning] Run-path-orkestrering og SDK-meldingshåndtering er offline-ubundet
|
||||
|
||||
- **Belegg (testkvalitetsagent, coverage i kopi, 90% total):** `run_s10.py` 0% (`main()`-
|
||||
orkestreringen, inkl. `BudgetExceeded`-stopp-grenen `:99-114` som docstringen selv kaller en
|
||||
tidligere regresjon «stopped here with NO record»); `sdk_client.py` 63% (meldingshåndteringen
|
||||
i `_complete_async` — tekst-aggregering, error-fail-paths, usage/kost-ekstraksjon,
|
||||
`_total_tokens` fail-closed, `max_budget_usd_per_call<=0`-guard — kjøres aldri fordi
|
||||
`test_sdk_isolation`s `fake_query` yield-er tom strøm).
|
||||
- **Feilscenario:** en regresjon i stopp-artefakt-persisteringen eller usage-ekstraksjonen går
|
||||
ubemerket. `run_s10.py` er fasit-sti (skal ikke endres), men logikken KAN bindes offline bak
|
||||
en klient-seam på den NYE kjøresti-inngangen (C2.0) uten å røre fasit-stien.
|
||||
- **Fiks:** budsjett-stopp-binding på C2.0-stien (R-10a); syntetisk-strøm-test for
|
||||
`sdk_client._complete_async` (R-10b) → foldet inn i **C2.0** og **C2.5** (se sesjonsplan).
|
||||
|
||||
### Lavere / kant (korrekthetsagent + spec-agent, kort — hver notert, ikke egen sesjon)
|
||||
|
||||
- **assumptions-bånd uten grense** (`ir.py:37`): negative bånd-verdier godtas → skjev MC
|
||||
(negative p10/p50, kjørt). Løses av samme finitthets-/gyldighets-hardening som R-2 (C2.6).
|
||||
- **tom-streng modell-id passerer `ModelMapContract`** (`contracts.py:43`, ingen `min_length`)
|
||||
→ `resolve_model` kan returnere `""`. PLAUSIBEL, lav. Foldes inn i C2.6/contracts-hardening.
|
||||
- **promotion filnavn-token-kollisjon** (`promotion.py:34-40`): to distinkte usikre id-er →
|
||||
samme token → overskriv/dedup. Kun nåbar med ikke-mintede id-er. PLAUSIBEL, kant.
|
||||
- **anker/query-krysslenker droppes stille** (`okf.py:24` `_CROSSLINK_PATTERN` krever `.md)`
|
||||
umiddelbart) → `(x.md#sec)` navigeres aldri. LAV, spec-tro (regelen er `\]\(([^)]+\.md)\)`).
|
||||
- **ikke-SELECT SQL → `cursor.description is None` → TypeError** (`ingest.py:243`). Konfig-feil,
|
||||
kryptisk melding. PLAUSIBEL, lav.
|
||||
- **`check_turn_safety_net` er en død vokter** (`loop.py:111`): turns ≤ 2·max_rounds <
|
||||
2·max_rounds+2, så den kan aldri utløses gitt løkkegrensene. Ikke en defekt — men §8s
|
||||
«turn-count termination safety net above [the round cap]» er dermed en no-op i praksis;
|
||||
notér i C2.6 eller egen liten opprydding.
|
||||
- **OBS-2 (spec-agent):** `DataSourceContract.docs_dir` valideres (`contracts.py:36`) men
|
||||
`run_s10` navigerer `args.bundle` direkte (`run_s10.py:63,69`) — konsistent i dag, men et
|
||||
fremtidig avvik passerer stille. LAV.
|
||||
|
||||
---
|
||||
|
||||
## 3. Testkvalitet + §11 load-bearing (detach-stikkprøver)
|
||||
|
||||
**4/4 detach-eksperimenter RØDE i throwaway-kopi** (testkvalitetsagent), hver revert→grønn,
|
||||
arbeidstre urørt (`git status` = kun `?? .claude/`, HEAD `b46f32c`):
|
||||
|
||||
| # | Detach (i kopi) | Forventet | Faktisk |
|
||||
|---|---|---|---|
|
||||
| A | checker-override kortsluttet (`loop.py apply_checker_gate`) | `test_checker_gate_loadbearing` rød | **RØD, 3 failed** |
|
||||
| B | inbox-merge → `pass` (`inbox.py`) | `test_step7_async_loop_loadbearing` rød | **RØD, 2 failed** |
|
||||
| C | verbatim-id re-mintet (`experience.py seed`) | `test_step8_promotion_loadbearing` rød | **RØD, 2 failed** |
|
||||
| D | `okf_type` fjernet fra ingest-spec-KOPI | `test_ingest_spec_loadbearing` rød | **RØD, 1 failed** |
|
||||
|
||||
Baseline i kopi 265 passed; etter alle reverts 265 passed re-bekreftet. Metoden holder på de
|
||||
stikkprøvde sømmene (paritet med 2026-07-10s 11/11 på disse fire).
|
||||
|
||||
**Presisjons-lærdom (detach D):** ingest-spec-vaktens assertion er substring-hvor-som-helst,
|
||||
ikke tabellspesifikk — å fjerne KUN §12-tabellraden ville ikke detache (feltet står også i
|
||||
felt-definisjonen). Dette må C1.1s method-spec-vakt ta høyde for (dokumentér begrensningen
|
||||
eller scope assertion til §12-blokken).
|
||||
|
||||
**Testkvalitetssveip:** ingen vakuøse assertions (ingen `assert True`/`xfail`/`skip`/TODO);
|
||||
ScriptedClient (`tests/_scripted.py`) bekreftet SDK-import-ren (importerer kun
|
||||
`typing.Callable` + `loop.ModelReply`; `loop.py` drar ingen SDK); suiten deterministisk uten
|
||||
nøkkel/nett (ingen ambient `os.environ`/socket/api_key; eneste `setenv` er lokal
|
||||
sqlite-fixture-sti). Dekningshull: **R-10** (run_s10 0%, sdk_client 63%).
|
||||
|
||||
---
|
||||
|
||||
## 4. SDK-bruk + modell-map-gyldighet (SDK-agent, med kilder)
|
||||
|
||||
- **Alle SDK-attributt-premisser i `sdk_client.py` holder mot installert 0.2.110** — verifisert
|
||||
mot pakkekilden (`.venv/.../claude_agent_sdk/types.py`): `AssistantMessage.error/.model`,
|
||||
`ResultMessage.usage/.total_cost_usd/.is_error/.subtype/.errors`,
|
||||
`ClaudeAgentOptions.max_budget_usd/.setting_sources/.system_prompt/.max_turns/.model/.tools`,
|
||||
`TextBlock.text`, `query`. `setting_sources=[]`-isolasjonspåstanden og
|
||||
`system_prompt=None`→`--system-prompt ""`-serialiseringen er ordrett dokumentert/verifisert
|
||||
ned til CLI-argumentet (`subprocess_cli.py:227-228`).
|
||||
- **Nyeste SDK: 0.2.120 (15. juli 2026)**; installert 0.2.110. **Ingen breaking changes** på de
|
||||
brukte attributtene 0.2.110→0.2.120 (hovedsakelig bundlede CLI-bumps). **0.2.111 (6. juli)
|
||||
fikser feil som treffer nettopp denne klientens leseløkke** (NDJSON-parser mistet whitespace
|
||||
på linjer >64 KiB; TypeError-krasj når `content` er ren streng; zombie-subprosess ved
|
||||
cancellation). Kilder: [pypi.org/project/claude-agent-sdk](https://pypi.org/project/claude-agent-sdk/),
|
||||
[GitHub releases](https://github.com/anthropics/claude-agent-sdk-python/releases), hentet
|
||||
2026-07-16.
|
||||
- **Anbefalt pin: `claude-agent-sdk>=0.2.111,<0.3`** (C-N3) + versjonsvakt-test (C2.5).
|
||||
- **Modell-map:** `claude-haiku-4-5-20251001` (default/proposer/checker) er **gjeldende** i
|
||||
offisiell modell-oversikt, IKKE deprecated, og **fortsatt billigst egnet** ($1/$5 MTok;
|
||||
eneste rimeligere er retired Haiku 3.5; ingen Haiku nyere enn 4.5). Kostnadsdisiplinen
|
||||
(Haiku 4.5 for en eventuell live-kjøring) holder. Kilder: [platform.claude.com models](https://platform.claude.com/docs/en/about-claude/models/overview),
|
||||
[pricing](https://platform.claude.com/docs/en/about-claude/pricing), hentet 2026-07-16.
|
||||
`ModelMapContract` matcher fil-strukturen; ingen manglende/ubrukte roller.
|
||||
- **Presisjonsnoter:** `test_sdk_isolation.test_the_system_prompt_is_empty` hevder i
|
||||
docstringen `--system-prompt ""`-serialisering men asserterer bare `system_prompt is None`
|
||||
(grønn-men-død for akkurat den claimen — påstanden er korrekt, testen dekker den ikke);
|
||||
runtime-feltnavnene i `usage`-dicten (`input_tokens` etc.) kan ikke bekreftes uten et
|
||||
forbudt `query()`-kall, men koden degraderer fail-closed til `None` ved avvik.
|
||||
|
||||
---
|
||||
|
||||
## 5. Spec-konformitet (spec-agent)
|
||||
|
||||
- **~70 normative krav KONFORME** (implementert + bundet av test). Nøkkelbelegg: §3 Steg 1
|
||||
navigasjon `okf.py:93-119` + verdict-eksklusjon `:131`; fold/seeding `experience.py:60-171`;
|
||||
Steg 4 validator `validator.py:50-83` + checker-gate `loop.py:186-212`; §6 promotion
|
||||
`promotion.py:48-103`; §8 budsjett `budget.py:35-57`; §10 startup `contracts.py:98-116`;
|
||||
ingest verdict-reservasjon `ingest.py:114-122`, provenance-lag `:279-297`.
|
||||
- **Konformitetsgap:** §1 konformans-pkt 3 (hver load-bearing søm har detach-test) er 9/11 —
|
||||
C-N1 (spec-integritet) + R-1 (closed loop) mangler; §12-kompletthet er derfor ikke håndhevet
|
||||
(spec §12 lover at spec-integritetstesten gjør det).
|
||||
- **Konformt-men-uvoktet (folder inn i C-N1):** §1 ærlighetsregelen, §4.3 persona-prosa-
|
||||
nøytralitet og §11 spec-integritet er alle konforme NÅ, men uten automatisk vakt — drift
|
||||
ville være usynlig. Nettopp lasten C-N1 skal bære.
|
||||
- **ingest §8 Network gate:** N/A i D7-scope (http uimplementert/nektet ved manifest-validering;
|
||||
file+sql lokale → ingen egress-sti). Bekreftet av sikkerhetsagentens egress-grep (0 treff).
|
||||
|
||||
**§12-felt konsumert av src-logikk** (for C1.1s vaktdesign): `decision`, `rationale`,
|
||||
`id`/`verdict_id`, `proposal_features`, `affected_codes`, `measure_type`, `claimed_saving_nok`,
|
||||
`description`, `marker`, `project_id`, `measure`, `affected_items`, `code`, `quantity`,
|
||||
`unit_cost`, `assumptions`, `validates`, `nominal_feasible`, `p10`, `p50`, `p90`,
|
||||
`realization_rate`, `expected_actual_saving_nok`, `type`, `approved`, `rejected`,
|
||||
`approved_with_adjustment`. **Kun golden/test-konsumert (ikke lest av src):** `outcome`,
|
||||
`modelled_saving_nok`, `gap_source`, `context_key`. Anbefaling: vakten dekker ALLE 25 (mirror
|
||||
av ingest-vakten), med bevissthet om at de fire siste er fasit-/test-konsumert.
|
||||
|
||||
---
|
||||
|
||||
## 6. Ærlighetsregel §1 (docs)
|
||||
|
||||
Verifisert av orkestrator mot faktiske artefakter, OG uavhengig bekreftet av ærlighets-agenten
|
||||
(samme konklusjon: én myk overclaim, ingen harde, ingen umerkede stand-ins, ingen utdaterte
|
||||
tall; agenten rekonsilierte S10-tallene byte for byte og la til p10 68 543 / p90 121 057).
|
||||
|
||||
**Ingen OVERCLAIM funnet** (utover den ene myke F1/C-N2 under). Docs er gjennomgående ærlige (§1). Verifiserte claims:
|
||||
|
||||
| Claim | Verifisert mot | Status |
|
||||
|---|---|---|
|
||||
| «265 tests, offline uten API-nøkkel» (`README.md:16-18,153`; `CHANGELOG`) | `uv run pytest` (265 passed uten nøkkel/nett) | ÆRLIG |
|
||||
| S10-tall: «$0.127514 · 36 791/150 000 tokens · 2 of 12 rounds» (`README.md:132-138`) | `runs/s10/usage.json` (`cost_usd 0.127514`, `tokens_used 36791`, `max_tokens 150000`, `rounds_used 2`, `max_rounds 12`) — matcher byte for byte | ÆRLIG |
|
||||
| «everything else is deterministic and offline; nothing here claims more live behaviour than that one documented run» (`README.md:140-141`) | S10 er eneste live-kjøring; resten offline | ÆRLIG (eksplisitt §1-selvbegrensning) |
|
||||
| «http/MCP … D7 does not implement it … no network egress path» (`README.md:118-123`, `extending.md:128-155`) | egress-grep 0 treff (sikkerhetsagent); http avvist fail-fast | ÆRLIG (gjentatt, presist hedget) |
|
||||
| «`create_sdk_mcp_server`/`@tool` … not used anywhere in this repo» (`extending.md:152-155`) | `ingest.py` ren stdlib | ÆRLIG |
|
||||
| ScriptedClient som stand-in | `_scripted.py:1-7` merket §1 | ÆRLIG |
|
||||
| ingest «zero model calls, imports nothing from SDK» (`README.md:100-102`) | `ingest.py:5`; import-grep | ÆRLIG |
|
||||
|
||||
**Én honesty-nær sak (ikke overclaim, men upresis):** README-ens inbox-avsnitt
|
||||
(`README.md:66-68`) «a later run ingests it tolerantly and merges it before the fold» er sant
|
||||
om KONTRAKTEN, men ingen leverbar kjøresti komponerer den i dag (C-N2 — `merge_inbox_into_store`
|
||||
kalles kun fra tester). Formuleringen impliserer en kjørbar «later run» som ikke finnes som
|
||||
kommando. Lukkes av C2.0 (kjøresti-inngangen gjør claimet sant om en skipbar sti). Merk
|
||||
tilliggende nyanse fra R-9: fold-bæreren ER wiret via bundle-seeding på run-stien — så «merges
|
||||
it before the fold» er delvis sant (seed-folden kjører; inbox-folden gjør ikke). **Presis fiks
|
||||
(ærlighets-agentens anbefaling):** ordet «run» i `README.md:67` er det eneste som bærer
|
||||
overclaimet — kvalifisér til f.eks. «the async-loop seam — proven by `test_step7` in a two-run
|
||||
simulation — ingests … before the fold», ELLER (bedre) la C2.0 gjøre setningen bokstavelig sann
|
||||
ved å levere kjøresti-inngangen. C2.0-scopet oppdaterer allerede README-inbox-avsnittet.
|
||||
|
||||
**Ærlighetsregelens egen svakhet (konformitet):** ingen automatisk vakt håndhever §1 på
|
||||
docs/spec (C-N1 mangler) — dagens ærlighet er ekte, men drift ville være usynlig. C1.1 lukker
|
||||
spec-siden; en docs-ærlighets-test (K12s README-claims-mot-CLI-sjekk) lukker README-siden.
|
||||
|
||||
---
|
||||
|
||||
## 7. Verifiseringslogg
|
||||
|
||||
| Påstand | Kilde/kommando |
|
||||
|---|---|
|
||||
| 265 passed / ruff / mypy clean | `uv run pytest -q` (1.68s); `ruff check .`; `ruff format --check .`; `mypy src` (2026-07-16) |
|
||||
| HEAD/remote-sync | `git rev-parse HEAD origin/main open/main commons/main`; `git fetch` alle |
|
||||
| commons-amendment ikke landet / toolkit finnes ikke | subtree-diff `HEAD:shared`↔`commons/main` (docs-only); `ls ~/repos/okf-toolkit` + `git ls-remote` → not found |
|
||||
| R-2 (Infinity) | orkestrator kjørte mot live `ir`+`validator`: `unit_cost:Infinity` → ValidatedProposal(True, inf, p90=inf); `assumptions:[1.0,Infinity]` → True, p90=inf; NaN → ValidationError |
|
||||
| R-3 (tom CSV) | orkestrator: `ingest._render_table([])` → `ValueError: not enough values to unpack`; korrekthetsagent: delvis bundle bekreftet i kopi |
|
||||
| R-4 (BOM) | orkestrator: `ingest.py` har 5× `encoding="utf-8"`, 0× `utf-8-sig`; korrekthetsagent kjørte korrupt header i kopi |
|
||||
| R-6 (id-traversal) | orkestrator: `VerdictDocument(id="../../escaped")` aksepteres verbatim; sikkerhetsagent skrev fil utenfor inbox i kopi |
|
||||
| 4/4 detach røde | testkvalitetsagent, throwaway-kopi, import-isolasjon verifisert, revert→265 passed, arbeidstre urørt |
|
||||
| SDK-premisser + modell-id | SDK-agent mot `.venv/.../types.py` (0.2.110) + PyPI/GitHub/platform.claude.com (2026-07-16) |
|
||||
| C-F7 / R-9 fold-injeksjon | sikkerhetsagent, kjørt i kopi: inbox verbatim; bundle-seed på run-stien (`run_s10.py:73`) verbatim |
|
||||
| Guard-plan §2-tabell rad 1–6 | sikkerhetsagent, kjørt: path-escape avvist, sql read-only, http fail-fast, 0 egress-call-sites |
|
||||
| S10-artefakter urørt | kun lest; ingen re-kjøring |
|
||||
|
||||
---
|
||||
|
||||
## 8. Oppsummering for sesjonsplanen
|
||||
|
||||
Nye ugatede hardening-sesjoner (byggbare nå, injisert i
|
||||
[sesjonsplanen](2026-07-16-sesjonsplan-paritet.md)):
|
||||
|
||||
- **C2.6** — validator/IR finitthets- og gyldighets-hardening (**R-2** primær; +
|
||||
negative bånd, tom-streng modell-id, død turn-safety-net-vokter). Høyest verdi: lukker en
|
||||
faktisk validator-omgåelse på kjørestien. Golden uendret (finite tall).
|
||||
- **K2.9** — ingest-robusthet (**R-3** tom CSV fail-fast før disk-mutasjon; **R-4** `utf-8-sig`;
|
||||
**R-5** malformert-lenket-fil-semantikk med eksplisitt beslutning; **R-7** valgfri max_rows-
|
||||
strømming). Golden uendret.
|
||||
- **R-1/K4** — closed-loop to-kjørings-simulering (§11-raden), allerede i planen.
|
||||
- **R-6** → foldet inn i **C2.5** (id-grammatikk på `VerdictDocument`).
|
||||
- **R-8** → foldet inn i **C3.2** (count-ærlighet ved seeding).
|
||||
- **R-10** → bindinger foldet inn i **C2.0** (budsjett-stopp på ny sti) + **C2.5**
|
||||
(sdk_client syntetisk-strøm-test).
|
||||
751
docs/2026-07-16-sesjonsplan-paritet.md
Normal file
751
docs/2026-07-16-sesjonsplan-paritet.md
Normal file
|
|
@ -0,0 +1,751 @@
|
|||
# Sesjonsplan — full MAF-paritet (K-serien + videreførte C-sesjoner · delt kø D-A–D-E)
|
||||
|
||||
> **Status:** GJELDENDE sesjonsplan for dette repoet. ERSTATTER
|
||||
> [`2026-07-10-sesjonsplan-d7.md`](2026-07-10-sesjonsplan-d7.md) (markert superseded med peker
|
||||
> hit). Forfattet 2026-07-16 (Fable 5, review-/plan-økt) på operatør-mandatet **FULL
|
||||
> MAF-PARITET** (D-G pkt. 2: «Claude-repoet skal være minst like godt som MAF-repoet»,
|
||||
> operatør-besluttet 2026-07-16). Den gamle planens §4-liste «Overføres IKKE hit
|
||||
> (MAF-spesifikt)» er **OPPHEVET som blanko-unntak** — hvert punkt er re-klassifisert i
|
||||
> paritetsmatrisen (§1). Ingen stille kutt.
|
||||
>
|
||||
> Funn-referanser: C-serien peker til [review 2026-07-10](review-2026-07.md); R-serien til
|
||||
> [review-paritet 2026-07-16](2026-07-16-review-paritet.md); MAF-referansene (S2.0–S5.4,
|
||||
> D-A–D-I, M1–M3, T0) til hovedrepoets `docs/plan/2026-07-10-sesjonsplan-fase2-6.md`,
|
||||
> `2026-07-14-revisjonspakke-DF-DI.md`, `2026-07-14-commons-amendment-utkast.md` og
|
||||
> `2026-07-14-toolkit-repo-brief.md` — lest på KAPABILITETS-/PLAN-nivå; MAF-kildekode leses
|
||||
> aldri (D7-regelen står for metode-laget; D-G endrer den bevisst KUN for OKF-formatlaget,
|
||||
> og kun via okf-toolkit når det finnes).
|
||||
>
|
||||
> Prinsipp (uendret): hver bygg-sesjon er én-sesjons-stor, offline, gratis (ScriptedClient),
|
||||
> TDD (Iron Law: failing test først), load-bearing (§11: detach-punkt per søm), og
|
||||
> **Opus 4.8 xhigh-eksekverbar** med «Les STATE.md og følg instruksjonene». Ingen
|
||||
> live-kjøringer: D6 står — S10 var programmets ene; ny spend krever eksplisitt
|
||||
> operatør-godkjenning (M2-analogen §6 er operatør-milepæl, aldri autonom sesjon).
|
||||
> «Suiten kjører uten nøkkel/nett» er invariant i ALLE sesjoner under.
|
||||
|
||||
---
|
||||
|
||||
## 0. Faktisk gate-status ved planleggingstidspunktet (verifisert 2026-07-16)
|
||||
|
||||
| Gate | Status | Belegg |
|
||||
|---|---|---|
|
||||
| D-A–D-E (delt kø) | ÅPNE | MAF-plan §2 + MAF-STATE 2026-07-16 («Operatør-kø uendret») |
|
||||
| D-F–D-I | BESLUTTET 2026-07-14 | revisjonspakka (fasit) |
|
||||
| Commons-amendment (D-F/D-G-utkastet) | **IKKE landet** — utkast venter operatør | subtree-diff `HEAD:shared` ↔ `commons/main`: kun `.gitignore` + guard-adopsjonsdoc, ingen spec-endring |
|
||||
| okf-toolkit-repo (T0) | **Finnes IKKE** | `ls ~/repos/okf-toolkit` + `git ls-remote` mot Forgejo → not found |
|
||||
| MAF-fremdrift | Fase 1 + Fase 2-bolk A (S2.0/S2.1/S2.5) + S3.6 + S4.1 + S4.2 + S5.1 komplett; S5.2 EXECUTE neste; suite 389 | MAF `STATE.md` 2026-07-16 07:40 |
|
||||
| Dette repoet | 265 passed offline · ruff/mypy rene · HEAD `b46f32c` == origin/main; open @ `42f320b` | kjørt i Steg 0 (review-paritet §0) |
|
||||
| `shared/`-subtree | 2 commons-commits bak (docs-only) | samme diff; hentes ved neste koordinerte pull — ingen spec-endring, ufarlig |
|
||||
|
||||
Planen bygger på DENNE statusen. Endres gate-status (amendment lander, toolkit-repo opprettes),
|
||||
gjelder §4-sesjonenes utløser-tekst, ikke antakelsene her.
|
||||
|
||||
## 1. Paritetsmatrise MAF ↔ D7 (kapabilitetsnivå)
|
||||
|
||||
Kilde: MAF-planene/STATE (aldri MAF-src). Klassifisering: **FINNES HER** (kapabiliteten er
|
||||
bygget og testet i dette repoet) / **BYGGBAR NÅ** (ingen beslutnings-gate) / **GATED**
|
||||
(navngitt gate) / **SPEILES IKKE** (etterprøvbar begrunnelse). Alle den gamle planens
|
||||
«Overføres IKKE»-punkter er re-klassifisert her; ingen rad er stille droppet.
|
||||
|
||||
| # | Kapabilitet (MAF-referanse) | MAF-status | D7-status i dag (belegg) | Klassifisering | D7-sesjon |
|
||||
|---|---|---|---|---|---|
|
||||
| 1 | Dimensjons-begrep + katalog (Fase 1 / D-F pkt. 5 / amendment §13.3) | Bygget (Fase 1); katalog spec-es av amendmenten | MANGLER — ingen dimensjons-modell i src (filkatalog) | **GATED: commons-amendment (D-F)** — katalog-kontrakten blir spec (§13.3); bygges fra spec-en når den lander, ikke fra utkast | K13 |
|
||||
| 2 | Mål-kontrakt (absolutt/prosent, hard/soft, stopp ved mål) (Fase 1) | Bygget; prosent-baseline åpen (D-E) | MANGLER | **BYGGBAR NÅ** (absolutt + hard/soft); prosent-baseline-semantikken alene er **GATED: D-E** | K1 |
|
||||
| 3 | Besparelses-hovedbok (typet ledger, fail-closed `realize`-ekspertgate, provenance) (Fase 1) | Bygget | MANGLER | **BYGGBAR NÅ** (stack-lokal — MAF bygde den også uten delt spec) | K1 |
|
||||
| 4 | Portefølje-kjøring (flere prosjekter, referanse-konfig, sekvensiell) (Fase 1) | Bygget | MANGLER — eneste kjøresti er `run_s10.py` (én bundle, fasit-frossen) | **BYGGBAR NÅ** | K2 |
|
||||
| 5 | Portefølje-læringssløyfe — dom på prosjekt k når k+1s prompt (S2.0) | **FERDIG** (bolk A) | MANGLER (ingen portefølje-sti; primitivene finnes: store/fold/inbox) | **BYGGBAR NÅ** (etter K2) | K3 |
|
||||
| 6 | Offline closed-loop-bevis — to-kjørings-simulering m/ markør (method-spec §11-raden «Closed loop»; MAF-original) | Bygget (originalbygget, `test_simulation_loadbearing`-raden) | **MANGLER** — step7/step8-testene beviser hver sin halvdel; ingen test kjører markøren gjennom to komponerte kjøringer (funn **R1**) | **BYGGBAR NÅ** — også et konformitetsgap, ikke bare paritet | K4 |
|
||||
| 7 | Outbox-persistens (S2.1) | **FERDIG** | DELVIS — `artifacts.py` persisterer proposal/result/provenance/usage deterministisk (også stop-artefakter), men uten run_id-navngitt forslag/utfall-par → ingen pending-sporing mulig | **BYGGBAR NÅ** (utvidelse av artifacts-laget) | K5 |
|
||||
| 8 | MCP-ingest-konnektor (S2.2, D-B-gated) | GATED D-B | MANGLER; `extending.md` ærlig «ubygd» | **GATED: D-B + commons-ingest-amendment** — SDK-nativ analog: in-process MCP-fixture via `create_sdk_mcp_server` (SDK-primitiv, verifisert i CLAUDE.md) i stedet for MAFs `mcp`-pakke-klient | K14 |
|
||||
| 9 | Dokument-konnektor PDF (S2.3, D-B-gated) | GATED D-B | MANGLER | **GATED: D-B + commons-ingest-amendment** | K15 |
|
||||
| 10 | Konnektor-herding http (S2.4, D-B-gated) | GATED D-B (MAF HAR http-demo å herde) | MANGLER MER — D7 har ingen http-kilde i det hele tatt (avvist fail-fast, `ingest.py:129`; valgfri per ingest-spec §1) | **GATED: D-B** — sesjonen bygger http-familien + herding + guard-G1-wiring i ett | K16 |
|
||||
| 11 | Inbox-/robusthetsherding (S2.5 ↔ C2.5) | **FERDIG** (bolk A) | MANGLER — vokabular-sjekk/tak finnes ikke (C-F7 kjørt-bevist); SDK-pin løs uten versjonsvakt (C-N3) | **BYGGBAR NÅ** | C2.5 |
|
||||
| 12 | Validator-stramming nominal-gate + band-invariant (S2.7 ↔ C2.7) | GATED D-A | Samme spec-defekt bekreftet her (C-F2, kjørt bevis) | **GATED: D-A pkt. 1 + commons-pull** | C2.7 |
|
||||
| 13 | Semantisk henting (S3.1, D-C) | GATED D-C | MANGLER; OBS delt kollisjon C-P1: D-C som planlagt (cosine over tekst) bryter frossen §3 Steg 1 «structural, never textual» | **GATED: D-C OG C-P1-avklaring i D-A-bolken** (begge må lande) | K17 |
|
||||
| 14 | Multi-kandidat ExpeL-seeding (S3.2 ↔ C3.2) | GATED D-A | Feature-halvdelen bekreftet defekt her (C-F5); id-halvdelen alt løst (verbatim) | **GATED: D-A pkt. 4 + commons-pull** | C3.2 |
|
||||
| 15 | Concurrency/feilmodell (S3.3, D-D) | GATED D-D | Ikke anvendbar i dag (ingen portefølje-sti) — blir reell når K2 lander | **GATED: D-D** (+ K2 som forutsetning) | K18 |
|
||||
| 16 | Kostnadsstyring på tvers av kjøringer (S3.4) | GATED D-D | MANGLER; pre-call-guard-delen er ugatet (C-N4) | **GATED: D-D** for portefølje-delen; pre-call-guard + run-total USD-tak er **BYGGBAR NÅ** | K19 (gated) + C3.5 (nå) |
|
||||
| 17 | Innholdsmodell/bibliotek-materialisering + summary-tier-render (S3.5, D-F) | GATED amendment | MANGLER | **GATED: commons-amendment (D-F/D-G-utkastet)** — inkluderer §13-typene, `library`-ingest-familien (4a/5a), summary-tier (§3 Steg 1-endringen) og dimensjonskatalogen (rad 1) | K13 |
|
||||
| 18 | Kostnadssimulering FØR kjøring (S3.6, D-I pkt. 3 — MÅ-krav) | **FERDIG** | MANGLER | **BYGGBAR NÅ** — D7-analog: what-if over `model_map.json` (Claude-modeller × effort), prisdata som skjema-validert konfig m/ kilde+dato | K6 |
|
||||
| 19 | Kostbaseline-forankring (S4.0 ↔ C4.0) | GATED D-A | Samme spec-defekt bekreftet her (C-F3, 2.9 MNOK-beviset) | **GATED: D-A pkt. 2 + commons-pull** | C4.0 |
|
||||
| 20 | Preflight (S4.1 — Foundry-spesifikk i MAF) | **FERDIG** | MANGLER | **BYGGBAR NÅ** — SDK-nativ analog: Anthropic-API/SDK-preflight, offline (env-kontrakt, model-map-konsistens, placeholder-nekt) — Foundry-auth-delen SPEILES IKKE (sant MAF-spesifikk på kapabilitetsnivå: D7s backend er Anthropic-API) | K7 |
|
||||
| 21 | Live-kjørings-drill + artefakt-fangst (S4.2) | **FERDIG** | MANGLER | **BYGGBAR NÅ** (etter K5+K7) — `--live-dry-run`: bygg alt, STOPP før første modellkall (kall-tellende mock beviser 0 kall) | K8 |
|
||||
| 22 | HITL-verdict-ruting + pending-sporing (S5.1) | **FERDIG** | MANGLER | **BYGGBAR NÅ** (etter K5 — id-join outbox↔inbox) | K9 |
|
||||
| 23 | Varsling/Notifier (S5.2) | Plan klar, EXECUTE neste | MANGLER (D7 har ingen notify-stub engang — bygges rent) | **BYGGBAR NÅ** — kapabilitets-koordinering med MAF S5.2 (protokoll-form, webhook-opt-in, socket-fri suite), aldri kode-titting | K10 |
|
||||
| 24 | CLI-paritet + dokumentsync + D-H-oppskrift (S5.3) | Gjenstår i MAF | MANGLER — ingen leverbar CLI utover fasit-stien | **BYGGBAR NÅ** (sist i ugatet rekke; C2.0 er første skritt) | C2.0 (inngang) + K12 (full paritet) |
|
||||
| 25 | Verdirapport per kjøring (S5.4, D-I pkt. 2) | Gjenstår i MAF | MANGLER | **BYGGBAR NÅ** (etter K5 + K1 + K6) | K11 |
|
||||
| 26 | okf-toolkit-adopsjon inkl. skrive-halvdelen A2 (D-G/T0) | T0 blokkerer også MAF | MANGLER — `okf.py` er kun-les (134 l); skrive-primitivene (promotion har egne) deles ikke | **GATED: T0** (repoet finnes ikke, verifisert 2026-07-16) + operatør (§8-spørsmålene i toolkit-briefen) | K20 |
|
||||
| 27 | llm-ingestion-guard-wiring | MAF: planned (S2.4/S2.5-utvidelse) | Planned her (guard-plan 2026-07-16): G1 http-persist-gate / G2 inbox-depth / G3 import_bundle | G1 **GATED: D-B** (inn i K16) · G2 valgfri depth **vurderes i C2.5** · G3 **GATED: D-E**-retning | K16 / C2.5 / (D-E) |
|
||||
| 28 | Steg-7 kjøresti-inngang (C2.0 — D7-egen) | (MAF har den via run-laget) | MANGLER (C-N2) | **BYGGBAR NÅ** | C2.0 |
|
||||
| 29 | Method-spec-integritetsvakt (C1.1 — §11-raden «Spec integrity») | MAF HAR (`test_method_spec_loadbearing.py`, referert i amendment-utkastet §5.1) | MANGLER (C-N1) | **BYGGBAR NÅ** | C1.1 |
|
||||
| 30 | OKF `/`-lenke-mapping (C2.8 / D-A pkt. 3 / D-G pkt. 1) | GATED D-A (MAF mangler også bygg-sesjon — flagget) | Spec-tro skip i dag (`okf.py:112`) | **GATED: D-A pkt. 3 + commons-pull** | C2.8 |
|
||||
| 31 | Budsjett-guard pre-call + run-total USD (C3.5) | Del av S3.4 i MAF | MANGLER (C-N4; per-kall-USD-tak finnes alt — bedre enn MAF) | **BYGGBAR NÅ** | C3.5 |
|
||||
| 32 | Operatør-milepæler M1–M3 | Definert i MAF-planen | Ingen definert her | **SPEILES som milepæl-definisjoner** (§6) — aldri autonome sesjoner. M1-analogen (tenant+smoke) er Foundry-spesifikk; D7-ekvivalenten (nøkkel + preflight grønn) foldes inn i M2-analogens forutsetninger | §6 |
|
||||
| 33 | Validator robust mot ikke-finite tall (review-paritet R-2 — D7-EGEN korrekthet) | (egen implementasjons-defekt) | **DEFEKT** — `Infinity` gir `validates=True` (kjørt-bevist) | **BYGGBAR NÅ** | C2.6 |
|
||||
| 34 | Ingest robust mot tom/BOM/malformert kilde (R-3/R-4/R-5/R-7 — D7-EGEN) | (egen implementasjons-defekt) | **DEFEKT** — tom CSV krasjer midt i materialisering → delvis bundle (kjørt-bevist) | **BYGGBAR NÅ** | K2.9 |
|
||||
| 35 | Closed-loop to-kjørings-vakt (R-1 — §11-raden «Closed loop») | MAF HAR (`test_simulation_loadbearing`) | MANGLER — §11 rad 8 ubundet | **BYGGBAR NÅ** | K4 |
|
||||
|
||||
**Re-klassifisering av den opphevede «Overføres IKKE»-listen** (gammel plan §4): S2.0-portefølje
|
||||
→ rad 4–5 (BYGGBAR NÅ); S2.1-outbox → rad 7 (BYGGBAR NÅ — «output-laget finnes her» var bare
|
||||
delvis sant); S2.2 MCP → rad 8 (GATED D-B, SDK-nativ analog); S2.3 doc → rad 9 (GATED D-B);
|
||||
S2.4 http-herding → rad 10 (GATED D-B); S3.1 → rad 13 (GATED D-C+C-P1); S3.3 → rad 15 (GATED
|
||||
D-D); S3.4 → rad 16 (delt: C3.5 nå, K19 gated); S4.1/S4.2-Foundry → rad 20–21 (SDK-nativ
|
||||
analog, BYGGBAR NÅ; kun Foundry-*auth* speiles ikke); S5.x → rad 22–25 (BYGGBAR NÅ-kjede);
|
||||
M1–M3 → rad 32. Setningen «`extending.md` står: ingen D7-HTTP/MCP-økt planlagt» er ikke
|
||||
lenger dekkende — K14–K16 planlegges nå, gated D-B; `extending.md` oppdateres i K16
|
||||
(docs-ærlighet, §1).
|
||||
|
||||
## 2. Den delte beslutnings-køen (uendret — bor i HOVEDREPOET)
|
||||
|
||||
D-A–D-E ligger i MAF-planens §2 og besluttes der; dette repoet planlegger ingen egen variant —
|
||||
kun sesjoner gated på den. Det som gater arbeid HER, med anbefaling i klarspråk, står i
|
||||
[beslutningsbriefen](2026-07-16-beslutningsbrief.md). Koblings-flagget **C-P1** (D-C ↔ frossen
|
||||
§3 Steg 1) står uendret og MÅ inn i D-A-bolken. Ett NYTT beslutnings-kandidat-punkt foreslås
|
||||
inn i den delte køen via briefen (delbarhet av ledger-/outbox-format) — det besluttes ALDRI
|
||||
ensidig her.
|
||||
|
||||
**Commons-regel (uendret):** amendments skrives i commons, pulles med
|
||||
`git subtree pull --prefix=shared commons main --squash`. ALDRI subtree push. Etter hver
|
||||
amendment-bølge re-pinner/puller BEGGE repo og BEGGE suiter kjøres (sammenligningsprotokollen);
|
||||
golden re-fryses kun koordinert i commons.
|
||||
|
||||
## 3. Byggbare NÅ (ingen beslutnings-gate) — anbefalt rekkefølge
|
||||
|
||||
> Felles verifisering for ALLE sesjoner (gjentas ikke per sesjon): full gate
|
||||
> (`uv run pytest` + `uv run ruff check .` + `uv run ruff format --check .` +
|
||||
> `uv run mypy src`) grønn; golden-regresjonen (`test_bygg_energi_mikro.py` +
|
||||
> ingest-goldens) uendret grønn; suiten kjører uten nøkkel/nett; `runs/s10/` urørt;
|
||||
> `run_s10.py` byte-urørt (fasit-sti). Nye moduler holdes SDK-frie (ren stdlib+pydantic)
|
||||
> med mindre sesjonen eksplisitt sier noe annet, og SDK-frihet bindes med import-vakt etter
|
||||
> `test_okf`-purity-mønsteret.
|
||||
|
||||
### C1.1 Method-spec-integritetsvakt (C-N1) — UENDRET fra gammel plan, ÅPNING
|
||||
- **Mål:** §11-raden «Spec integrity» håndheves lokalt — spec-drift i subtree-synken fanges her.
|
||||
- **Scope (filliste):** ny `tests/test_method_spec_loadbearing.py` (KUN testkode).
|
||||
- **IKKE-scope:** ingen src-endring, ingen spec-endring, ingen endring i ingest-spec-vakten.
|
||||
- **Gate:** ingen.
|
||||
- **TDD-plan:** testen er selv vakten; RØD-bevis via mutert spec-KOPI i `tmp_path`
|
||||
(parametrisert mot kopien, aldri mot `shared/`): (a) slett fila → rød; (b) injiser
|
||||
rammeverksnavn (MAF/Claude/Anthropic/Azure/…, samme navneliste som ingest-vakten) → rød;
|
||||
(c) fjern et konsumert §12-felt → rød. Innhold: (1) fil-eksistens + struktur-markører
|
||||
(`## 1.`–`## 12.`, `### Step 1`–`### Step 8`, «MUST»); (2) framework-nøytralitet;
|
||||
(3) §12-dekning for feltene DENNE koden konsumerer (`decision`, `rationale`, `id`,
|
||||
`proposal_features`, `affected_codes`, `measure_type`, `claimed_saving_nok`, `description`,
|
||||
IR-feltene `project_id`/`measure`/`affected_items`/`code`/`quantity`/`unit_cost`/`assumptions`,
|
||||
golden-feltene `outcome`/`validates`/`nominal_feasible`/`p10`/`p50`/`p90`,
|
||||
learning-surface-feltene, `type`, vokabular-verdiene `approved`/`rejected`/
|
||||
`approved_with_adjustment`). Feltlisten valideres mot review-paritet §-vedlegget
|
||||
(spec-konformitetsagentens konsumliste) i sesjonen. Presisjons-lærdom fra
|
||||
detach-stikkprøven av ingest-vakten (review-paritet §3): substring-hvor-som-helst-assertion
|
||||
gjør at et felt som også nevnes i løpeteksten ikke detacher ved ren tabell-fjerning —
|
||||
dokumentér samme begrensning i method-spec-vakten, eller scope assertion til
|
||||
§12-tabellblokken der det er praktisk.
|
||||
- **Nøkkelantakelse (+test):** markørene i dagens method-spec matcher listen — testes FØRST
|
||||
ved å kjøre vakten grønn mot uendret `shared/method-spec.md` før mutasjons-parametrene.
|
||||
- **Verifisering:** `uv run pytest tests/test_method_spec_loadbearing.py` grønn; mutasjons-
|
||||
parametrene røde mot kopi; full gate. **VIKTIG koordinering:** amendment-utkastet (§5.1) er
|
||||
konstruert mot MAFs vakt-design (presence-asserts, ikke forbud mot nye seksjoner) — bygg
|
||||
vakten HER med samme presence-semantikk, så en senere amendment-pull ikke gjør den rød.
|
||||
|
||||
### C2.5 Inbox-herding + SDK-versjonsvakt (C-F7, C-N3) — UENDRET + guard-G2-vurdering
|
||||
- **Mål:** inboxen slutter å være en uvalidert injeksjonsflate; SDK-attributt-premissene får
|
||||
en vakt som tvinger bevisst re-verifisering ved oppgradering.
|
||||
- **Scope (filliste):** `src/portfolio_optimiser_claude/inbox.py`, `pyproject.toml`,
|
||||
`tests/test_step7_async_loop_loadbearing.py` (utvidelse), ny `tests/test_sdk_version_guard.py`.
|
||||
- **IKKE-scope:** guard-*wiring* (kun vurderingsnotat, se under); endring i tolerant-lasting-
|
||||
semantikken for øvrige felter; `experience.py`.
|
||||
- **Gate:** ingen.
|
||||
- **TDD-plan:** RØD: inbox-fil med `decision: "hva-som-helst"` når ALDRI storen — reviewens
|
||||
kjørte C-F7-bevis blir fixturen (detach-punkt: fjern vokabular-sjekken → den entrer → rød).
|
||||
Vokabular på fil-laget = §4.2-settet {approved, rejected, approved_with_adjustment}; ukjent
|
||||
→ SKIP, aldri raise (tolerant-regelen består). RØD: rationale > konfigurerbart tak →
|
||||
fail-fast med presis feil (aldri stille kutt); RØD: antall filer > tak → fail-fast. RØD
|
||||
(R-6): `VerdictDocument.id` med path-traversal (`../../escaped`) → avvist/sanert FØR
|
||||
`write_verdict` skriver (detach id-grammatikken → fil skrives utenfor inbox → rød;
|
||||
sikkerhetsagentens kjørte bevis blir fixturen; speil `_ID_RE` fra `ingest.py` eller
|
||||
`promotion._filename_token`-saneringen). RØD:
|
||||
versjonsvakt mot fake-versjon (monkeypatch `importlib.metadata.version`) — melding skal
|
||||
navngi `sdk_client.py`-premissene som må re-verifiseres. Pin: **`claude-agent-sdk>=0.2.111,<0.3`**
|
||||
(sdk-review 2026-07-16: alle attributt-premisser verifisert mot installert 0.2.110 OG mot
|
||||
releases t.o.m. nyeste 0.2.120 — ingen brudd; 0.2.111 bærer NDJSON-/content-parsing-fikser
|
||||
som treffer nettopp denne klientens leseløkke, se review-paritet §2). Sesjonen re-kjører
|
||||
attributt-verifiseringen mot versjonen `uv sync` faktisk resolver.
|
||||
I tillegg (fra R4/R5, test-detach + sdk-review): (5) bind `sdk_client._complete_async`-
|
||||
meldingshåndteringen offline med en syntetisk strøm (fake_query som yield-er
|
||||
AssistantMessage/ResultMessage-verdier: tekst-aggregering, error-fail-paths,
|
||||
usage/kost-ekstraksjon, `_total_tokens`-fail-closed, `max_budget_usd_per_call<=0`-guarden
|
||||
— i dag kjøres ingenting av dette i suiten); (6) rett `test_sdk_isolation`-docstringen som
|
||||
hevder `--system-prompt ""`-serialisering testkroppen ikke beviser (grønn-men-død for
|
||||
akkurat den claimen — ærligst å omformulere docstringen; å binde transport-serialisering
|
||||
ville lese SDK-privat API og gjeninnføre F11-skjørhet).
|
||||
- **Guard-G2-vurdering (leveranse i sesjonen, ikke wiring):** kort avsnitt i commit-meldingen/
|
||||
STATE om `scan_output`-depth over `rationale` er verdt en senere additiv økt —
|
||||
C2.5-allowlisten er den nødvendige delen (guard-planen §4 G2). Markørlinjen i STATE
|
||||
oppdateres hvis vurderingen endrer trigger-bildet.
|
||||
- **Nøkkelantakelse (+test):** step7-suitens tolerant-lasting består uendret — kontrolltest:
|
||||
eksisterende `test_non_json_broken_and_incomplete_files_are_skipped` forblir grønn.
|
||||
- **Verifisering:** nye tester grønne + detach → rød; step7-suiten uendret grønn; full gate.
|
||||
|
||||
### C2.0 Steg-7 kjøresti-inngang (C-N2) — UENDRET
|
||||
- **Mål:** en skipbar inngang komponerer §5-sekvensen (merge inbox → seed → fold → run), så
|
||||
README-ens inbox-avsnitt er sant om en leverbar sti.
|
||||
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/run.py` (offline-testbar
|
||||
komposisjonsfunksjon `compose_run_context(bundle_dir, inbox_dir=None, k=...)` + tynn CLI
|
||||
`python -m portfolio_optimiser_claude.run --bundle/--inbox/--out` som gjenbruker
|
||||
contracts/meter/artifacts), ny `tests/test_run_entrance_loadbearing.py`, README-avsnittet
|
||||
om inboxen (peker på ny inngang).
|
||||
- **IKKE-scope:** `run_s10.py` (byte-urørt fasit); ny live-kjøring (CLI testes kun med
|
||||
ScriptedClient; SDK-klienten wires men eksekveres ikke i suiten); portefølje (K2).
|
||||
- **Gate:** ingen.
|
||||
- **TDD-plan:** RØD: dom droppet i inbox-mappe → inngangens komponerte kontekst bærer dommens
|
||||
markør (detach-punkt: fjern merge-kallet i komposisjonen → rød); kontroll: tom/manglende
|
||||
inbox → base-kontekst uendret; RØD: inngangen skriver ALDRI til inboxen (byte-sammenligning
|
||||
før/etter, §5-rolledelingen); RØD (fra R3, test-detach-coverage): budsjett-stopp under
|
||||
kjøring via den NYE inngangen → stopp-artefaktene persisteres + strukturert exit
|
||||
(ScriptedClient + lavt tak — binder orkestrerings-grenen `run_s10.py:99-114` aldri fikk
|
||||
bundet; fasit-stien forblir byte-urørt, bindingen skjer på den nye stien).
|
||||
- **Nøkkelantakelse (+test):** komposisjonen gjenbruker `fold_experience`/
|
||||
`merge_inbox_into_store`/`seed_store_from_bundle` uendret — ingen ny søm, kun wiring;
|
||||
testes ved at ingen eksisterende testfil endres.
|
||||
- **Verifisering:** ny testfil grønn + detach → rød; `grep -n "inbox" README.md` viser claim
|
||||
som matcher en skipbar sti; full gate.
|
||||
|
||||
### C2.6 Validator/IR finitthets- og gyldighets-hardening (R-2 primær) — NY, BYGGBAR NÅ, HØY VERDI
|
||||
- **Mål:** den obligatoriske validatoren kan ikke lenger settes ut av spill av ikke-finite
|
||||
eller ugyldige tall — `Infinity` klarerer ikke porten vakuøst lenger.
|
||||
- **Scope (filliste):** `ir.py` (`allow_inf_nan=False` på de numeriske feltene, eller eksplisitt
|
||||
finitthetssjekk av `quantity`/`unit_cost`/`claimed_saving_nok` + bånd-endepunkter; forby
|
||||
negative bånd-verdier), `contracts.py` (`min_length` på modell-id-verdier — tom-streng-
|
||||
bug), `loop.py` (fjern/dokumentér den døde `check_turn_safety_net`-vokteren `:111` — eller
|
||||
gjør §8s turn-safety-net faktisk nåbar), `tests/test_ir.py`, `tests/test_validator.py`,
|
||||
`tests/test_contracts.py`.
|
||||
- **IKKE-scope:** kostbaseline (C4.0); nominal-gate (C2.7, D-A-gated) — dette er ren
|
||||
finitthets-/gyldighets-hardening, ikke spec-strammingen.
|
||||
- **Gate:** ingen. **Golden uendret** (golden-tallene er finite).
|
||||
- **TDD-plan:** RØD: `unit_cost: Infinity` → IR-konstruksjon eller validering avvises (i dag
|
||||
`ValidatedProposal(validates=True, p90=inf)` — reviewens kjørte R-2-bevis blir fixturen;
|
||||
detach-punkt: gjeninnfør `allow_inf_nan=True` → inf validerer → rød); RØD: `assumptions`-bånd
|
||||
med `Infinity`/negativ endepunkt → avvist; kontroll: NaN avvises fortsatt (regresjon);
|
||||
kontroll: golden-bundelens finite tall validerer uendret; RØD: tom-streng modell-id →
|
||||
ModelMapContract avviser.
|
||||
- **Nøkkelantakelse (+test):** ingen golden-/fixture-tall er ikke-finite — VERIFISERT
|
||||
(golden.json + alle fixtures er finite); bindes ved at `test_bygg_energi_mikro` forblir grønn.
|
||||
- **Verifisering:** nye tester grønne + detach → rød; golden uendret; full gate.
|
||||
|
||||
### K2.9 Ingest-robusthet (R-3/R-4/R-5/R-7) — NY, BYGGBAR NÅ
|
||||
- **Mål:** ingest krasjer ikke midt i materialisering på tomme/BOM-/malformerte kilder, og
|
||||
etterlater aldri en delvis bundle.
|
||||
- **Scope (filliste):** `ingest.py` (R-3: vokt tom `rows` med fail-fast FØR disk-mutasjon —
|
||||
aldri delvis bundle; R-4: les CSV med `utf-8-sig`; R-7 valgfritt: `LIMIT max_rows+1`/
|
||||
`fetchmany` for SQL + streaming-tell for CSV), `okf.py` (R-5: eksplisitt beslutning for
|
||||
malformert-men-eksisterende lenket concept-fil — tolerér-og-hopp ELLER dokumentert fail-fast,
|
||||
ikke stille asymmetri), nye tester + evt. golden-fixture-tillegg (repo-lokalt, ikke `shared/`).
|
||||
- **IKKE-scope:** ny kildefamilie (K14–K16, D-B-gated); endring i eksisterende ingest-goldens
|
||||
(byte-fasit).
|
||||
- **Gate:** ingen.
|
||||
- **TDD-plan:** RØD: tom CSV-ekstraksjon → fail-fast MED bundle uendret (detach fail-fast-
|
||||
vakten → delvis bundle + krasj → rød; kontroll: byte-sjekk at ingen fil ble skrevet ved feil);
|
||||
RØD: BOM-CSV → header `code` ikke `code` (detach `utf-8-sig` → korrupt header → rød); RØD:
|
||||
malformert lenket fil → valgt semantikk bevist (hopp-og-fortsett: resten av bundelen
|
||||
navigeres; ELLER fail-fast: presis feil) — detach → motsatt oppførsel → rød.
|
||||
- **Nøkkelantakelse (+test):** eksisterende ingest-goldens er upåvirket (ingen tom/BOM/
|
||||
malformert fixture i dem) — bindes ved at begge ingest-golden-suiter forblir grønne.
|
||||
- **Verifisering:** nye tester grønne + detach → rød; ingest-goldens uendret; full gate.
|
||||
|
||||
### K4 Closed-loop to-kjørings-simulering (R-1 — §11-raden «Closed loop»; MAF-paritet rad 6)
|
||||
- **Mål:** §11s siste udekkede rad (utover C1.1) lukkes: en skriptet to-kjørings-simulering
|
||||
beviser at persona-markøren krysser kjøringer VIA promotering — og IKKE krysser uten.
|
||||
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/simulation.py` (deterministisk
|
||||
to-run-driver over `run.py`-komposisjonen + persona-artefakten + promotion; ScriptedClient;
|
||||
null modellkall), ny `tests/test_simulation_loadbearing.py`.
|
||||
- **IKKE-scope:** endring i loop/promotion/persona-primitivene; live-kjøring; portefølje.
|
||||
- **Gate:** ingen (forutsetter C2.0 — komposisjonsinngangen er kjøretøyet).
|
||||
- **TDD-plan:** RØD: kjøring A → persona-dom (markør fra `shared/skills/expert-reviewer/`-
|
||||
artefakten) → promotering → kjøring B med FERSK store: markøren MÅ nå Bs hypotese-prompt
|
||||
(detach-punkt 1: fjern promoterings-steget → markøren uteblir → rød). RØD (symmetrisk
|
||||
kontroll): UTEN promotering krysser markøren ALDRI (detach-punkt 2: la konteksten rendre
|
||||
verdict-laget → markøren lekker → rød — gjenbruker verdict-eksklusjonens invariant på
|
||||
simulerings-nivå). Honesty-krav: modulen docstring-merkes som skriptet stand-in (§1).
|
||||
- **Nøkkelantakelse (+test):** persona-artefaktens `marker` er substring av `rationale`
|
||||
(spec §4.3) — allerede bundet av `test_persona_skill_loadbearing.py`; simuleringen
|
||||
gjenbruker den, ingen ny persona-kilde.
|
||||
- **Verifisering:** ny testfil grønn + begge detach-punkter røde; full gate.
|
||||
|
||||
### K1 Besparelses-hovedbok + mål-kontrakt (paritetsrad 2–3; Fase-1-analog)
|
||||
- **Mål:** D7 får en typet hovedbok over realiserte besparelser (fail-closed ekspert-gate,
|
||||
provenance-stemplet) og en mål-kontrakt (absolutt beløp, hard/soft) med «stopp når mål
|
||||
nådd»-logikk — distinkt fra token-budsjettet.
|
||||
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/ledger.py` (typet `SavingsLedger`;
|
||||
`realize` KUN med eksplisitt ekspert-argument + eksplisitt timestamp — samme
|
||||
determinisme-regel som promotion §6; deterministisk JSON-persistens sort_keys/indent 2/LF),
|
||||
ny `goals.py` (`GoalContract`: absolutt mål, hard/soft; fail-fast konstruksjon §10-stil),
|
||||
nye `tests/test_ledger_loadbearing.py` + `tests/test_goals.py`.
|
||||
- **IKKE-scope:** prosent-mål-baseline (D-E-gated — kontrakten reserverer feltet med
|
||||
eksplisitt `NotImplementedError`-nekt + TODO-peker til D-E, aldri stille semantikk);
|
||||
portefølje-wiring (K2); verdirapport (K11).
|
||||
- **Gate:** ingen for absolutt-delen. **Prosent-delen: D-E.**
|
||||
- **TDD-plan:** RØD: `realize` uten ekspert-stempel → nekt (detach-punkt: fjern gate-sjekken
|
||||
→ uekspederte «realiserte» tall entrer boken → rød); RØD: hovedboken akkumulerer og
|
||||
persisterer deterministisk (to identiske sekvenser → byte-identisk fil); RØD: hardt mål
|
||||
nådd → strukturert stopp-signal (typet event, aldri stille); soft mål → flagg uten stopp;
|
||||
RØD: prosent-mål forsøkt konstruert → eksplisitt nekt med D-E-melding.
|
||||
- **Nøkkelantakelse (+test):** ledger-semantikk kan speiles på kapabilitetsnivå fra
|
||||
MAF-planens beskrivelse (typet store, fail-closed realize, dimensjonsfri sum-nøkkel mot
|
||||
dobbelttelling) uten MAF-kode — RISIKO: detaljsemantikk kan divergere fra MAF; markeres i
|
||||
docstring som stack-lokal kontrakt (delbarhet er foreslått beslutningspunkt i briefen).
|
||||
Test på antakelsen: dimensjonsfri sum-nøkkel bindes med en to-dimensjoner-samme-prosjekt-
|
||||
fixture der summen IKKE dobbelttelles.
|
||||
- **Verifisering:** nye tester grønne + detach → rød; full gate.
|
||||
|
||||
### K2 Portefølje-kjøring (paritetsrad 4; Fase-1-analog)
|
||||
- **Mål:** `run_portfolio` kjører N prosjekter sekvensielt fra en skjema-validert
|
||||
referanse-konfig (per-prosjekt bundle-sti), med collect-per-prosjekt-resultater — den
|
||||
kjørestien MAF fikk i Fase 1 og D7 aldri har hatt.
|
||||
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/portfolio.py`
|
||||
(`run_portfolio(projects, client, meter, ...)` + `PortfolioResult`), ny
|
||||
`data/reference_projects.json` (eksempel-konfig; skjema-validert fail-fast i
|
||||
`contracts.py`-stil), `contracts.py` (konfig-modell), mini-bundle-fixture repo-lokalt under
|
||||
`tests/data/` (ALDRI i `shared/`), ny `tests/test_portfolio.py`.
|
||||
- **IKKE-scope:** læringstreing på tvers (K3); concurrency (K18/D-D); goals/ledger-wiring
|
||||
utover å ta imot dem som valgfrie argumenter; endring i `loop.py`-kjernen.
|
||||
- **Gate:** ingen.
|
||||
- **TDD-plan:** RØD: to-prosjekt-konfig → begge kjøres, resultatliste i konfig-rekkefølge
|
||||
(deterministisk); RØD: malformet konfig (manglende bundle-sti) → fail-fast FØR første
|
||||
kjøring (§10-disiplin; detach-punkt: fjern skjema-valideringen → kjøring starter på
|
||||
ugyldig konfig → rød); RØD: feil i prosjekt 1 propagerer som typet feil — feilpolicyen
|
||||
(collect-and-continue vs raise) dokumenteres eksplisitt som stack-lokalt valg inntil D-D
|
||||
(default: raise, som «i dag kastes alt» — endres bevisst av K18 når D-D lander).
|
||||
- **Nøkkelantakelse (+test):** loop-kjernen er re-entrant per prosjekt (fresh debate-state
|
||||
per run — spec §3 Steg 3) — bindes med test: to sekvensielle kjøringer deler ingen
|
||||
muterbar tilstand utover eksplisitt delt store.
|
||||
- **Verifisering:** nye tester grønne + detach → rød; full gate.
|
||||
|
||||
### K3 Portefølje-læringssløyfe (S2.0-analog; paritetsrad 5)
|
||||
- **Mål:** en dom på prosjekt k når prosjekt k+1s hypotese-prompt i samme porteføljepass —
|
||||
delt store + verdict_dir tres gjennom `run_portfolio`.
|
||||
- **Scope (filliste):** `portfolio.py` (delt store + `verdict_dir`-parameter tres gjennom;
|
||||
inbox-merge FØR hver kjørings fold — gjenbruker C2.0-komposisjonen),
|
||||
`tests/test_portfolio_learning_loadbearing.py`.
|
||||
- **IKKE-scope:** semantisk henting (K17); multi-kandidat-nøkling (C3.2 — dagens
|
||||
feature-nøkling brukes som den er, med kjent C-F5-begrensning notert).
|
||||
- **Gate:** ingen (forutsetter K2 + C2.0).
|
||||
- **TDD-plan:** RØD: dom om prosjekt k (droppet i verdict_dir mellom kjøringene / promotert
|
||||
i ks bundle) → k+1s genererings-prompt bærer dommens id+markør (detach-punkt: fjern
|
||||
store-/verdict_dir-trådingen gjennom porteføljen → rød); kontroll: tom store/inbox → k+1
|
||||
uendret base-prompt.
|
||||
- **Nøkkelantakelse (+test):** first-write-wins-merge (§4.2) gjør gjentatte merges over
|
||||
porteføljepasset idempotente — bindes med dobbel-merge-test på porteføljenivå.
|
||||
- **Verifisering:** ny testfil grønn + detach → rød; full gate.
|
||||
|
||||
### K5 Outbox-persistens (S2.1-analog; paritetsrad 7)
|
||||
- **Mål:** hver kjørings forslag/utfall persisteres run_id-navngitt i en outbox-mappe, så
|
||||
utestående dommer kan spores (K9) og live-artefakter fanges (K8) — sammenligningsprotokoll
|
||||
§4.2-formen.
|
||||
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/outbox.py` (gjenbruker
|
||||
`artifacts.py`-serialisering; skriver `{run_id}-proposal.json` + `{run_id}-outcome.json`
|
||||
med outcome-type, reason/percentiler, checker_verdict, provenance-referanse, verdict-id;
|
||||
`run_id` PÅKREVD når outbox er satt — ingen wall-clock-default), `run.py` (valgfritt
|
||||
`outbox_dir`/`run_id`), ny `tests/test_outbox_loadbearing.py`.
|
||||
- **IKKE-scope:** ruting/pending (K9); varsling (K10); endring i `artifacts.py`-formatene
|
||||
(S10-fasiten leses av dem).
|
||||
- **Gate:** ingen.
|
||||
- **TDD-plan:** RØD: kjøring med outbox_dir → filparet finnes, byte-deterministisk
|
||||
(sort_keys/indent 2/LF; to kjøringer samme input+run_id → `diff` tom) (detach-punkt: fjern
|
||||
outbox-skrivingen → rød); kontroll: uten outbox_dir skrives ingenting; RØD: outbox satt
|
||||
uten run_id → fail-fast. Docstring siterer method-spec §2: systemet EIER output-laget
|
||||
(rolledelingen §5 gjelder inbox/wiki, ikke systemets eget output-lag).
|
||||
- **Nøkkelantakelse (+test):** `ValidatedProposal`/`Rejection` er JSON-serialiserbare via
|
||||
eksplisitt mapping — testes FØRST med begge utfallstyper (artifacts.py gjør alt dette i
|
||||
dag for run-artefaktene; antakelsen er at samme mapping bærer outcome-formen).
|
||||
- **Verifisering:** ny testfil grønn + detach → rød; full gate.
|
||||
|
||||
### C3.5 Budsjett-guard (C-N4) — VIDEREFØRT, løftet fra «valgfri» til paritetskrav (rad 16/31)
|
||||
- **Mål:** pre-call-guard (nekt kall når rest-tak < 0) + eksplisitt run-total USD-grense over
|
||||
SDK-klientens akkumulerte kost — på plass FØR enhver fremtidig live-kjøring.
|
||||
- **Scope (filliste):** `budget.py` (pre-call-sjekk-primitiv + run-total USD-tak i meteren),
|
||||
`loop.py` (guard-kall FØR `client.complete`), `sdk_client.py` (eksponer akkumulert
|
||||
`total_cost_usd` — leses allerede fra ResultMessage), `tests/test_budget.py` (+utvidelse).
|
||||
- **IKKE-scope:** portefølje-nivå-tak (K19, D-D-gated); endring i post-charge-semantikken
|
||||
(består som belte-og-seler).
|
||||
- **Gate:** ingen.
|
||||
- **TDD-plan:** RØD: mock-klient som teller kall — når rest < neste kall er kallet ALDRI
|
||||
gjort (detach-punkt: fjern pre-call-guarden → kallet skjer → rød); RØD: run-total USD-tak
|
||||
krysset → strukturert stopp (samme event-form som token-stoppen, §8); kontroll:
|
||||
usage-fail-closed-testen (`test_budget`) uendret grønn.
|
||||
- **Nøkkelantakelse (+test):** `ResultMessage.total_cost_usd` akkumuleres pålitelig per kall
|
||||
på 0.2.110 (verifisert i sdk-review 2026-07-16, review-paritet §2) — versjonsvakten fra
|
||||
C2.5 dekker drift.
|
||||
- **Verifisering:** nye tester grønne + detach → rød; full gate.
|
||||
|
||||
### K6 Kostnadssimulering før kjøring (S3.6-analog; D-I pkt. 3 MÅ-krav; paritetsrad 18)
|
||||
- **Mål:** operatøren ser estimert kost for en (portefølje-)kjøring FØR start — what-if over
|
||||
model_map (Claude-modeller × effortnivåer), prisdata som skjema-validert konfig.
|
||||
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/costsim.py` (funksjons-API +
|
||||
`python -m portfolio_optimiser_claude.costsim`; deterministisk øvre-grense-estimat fra
|
||||
portefølje-form × tak — merket ESTIMAT i output), ny `data/pricing.example.json` (skjema:
|
||||
kr-eller-USD/Mtok per modell-id, PÅKREVD kilde+dato-felt; fail-fast ved manglende/ugyldig
|
||||
pris — aldri hardkodet), `contracts.py` (pris-skjema), nye tester.
|
||||
- **IKKE-scope:** live prisoppslag (nett); faktisk modellkall; kvalitets-benchmarking
|
||||
(kvalitetsutsagn kun som veiledning-med-kilde, D-I-regelen).
|
||||
- **Gate:** ingen.
|
||||
- **TDD-plan:** RØD: konfig uten pris for en modell i model_map → fail-fast «missing price
|
||||
for <modell-id>» (detach-punkt: fjern pris-valideringen → estimat gjettes → rød); RØD:
|
||||
deterministisk og skalerer med modell × effort (to modeller, samme portefølje →
|
||||
forskjellig, reproduserbart estimat; detach effort-faktoren → identisk → rød); RØD:
|
||||
grep-guard: ingen pris-literal i `costsim.py`-kildekode (pris MÅ komme fra konfig).
|
||||
- **Nøkkelantakelse (+test):** eksempel-prisene kan kildeføres mot offisiell Anthropic-
|
||||
prisside med dato (sdk-modelmap-reviewens kilder gjenbrukes); IKKE VERIFISERT utover
|
||||
review-datoen — derfor kilde+dato-felt i skjemaet, så stale priser er synlige, aldri stille.
|
||||
- **Verifisering:** nye tester grønne + detach → rød; `uv run python -m
|
||||
portfolio_optimiser_claude.costsim` gir estimat-tabell uten nettverk; full gate.
|
||||
|
||||
### K7 SDK-/API-preflight (S4.1-analog, SDK-nativ; paritetsrad 20)
|
||||
- **Mål:** alt som KAN valideres uten et modellkall valideres før operatøren betaler for ett.
|
||||
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/preflight.py`
|
||||
(`python -m portfolio_optimiser_claude.preflight --profile anthropic`): env-kontrakt
|
||||
(`ANTHROPIC_API_KEY` satt + ikke-placeholder-form — nøkkelVERDIEN valideres aldri online),
|
||||
model_map-konsistens (profil finnes, `default` finnes, modell-id-form), placeholder-nekt
|
||||
også i `resolve_model`-stien, SDK-importerbarhet + bundlet CLI til stede
|
||||
(claude-agent-sdk-premisset), budsjett-/stoppkontrakt satt. Nekt-liste med aksjonérbar
|
||||
melding per mangel. Tester.
|
||||
- **IKKE-scope:** faktisk API-kall (aldri — preflighten er selve grensen); Foundry/Azure
|
||||
(SPEILES IKKE, rad 20-begrunnelsen).
|
||||
- **Gate:** ingen.
|
||||
- **TDD-plan:** RØD: manglende env-nøkkel → strukturert nekt med aksjonérbar melding
|
||||
(detach-punkt: fjern env-sjekken → preflight «grønn» uten nøkkel → rød); RØD:
|
||||
placeholder-modell-id i map → nekt; RØD: grep-guard ingen socket-/httpx-sti i modulen.
|
||||
- **Nøkkelantakelse (+test):** «bundlet CLI til stede» kan sjekkes offline via SDK-pakkens
|
||||
egne filer (verifiseres i sesjonen mot installert 0.2.110; hvis ikke mulig offline —
|
||||
droppes sjekken eksplisitt med begrunnelse i docstring, aldri en nett-sjekk).
|
||||
- **Verifisering:** nye tester grønne + detach → rød; `uv run python -m
|
||||
portfolio_optimiser_claude.preflight` korrekt nekt/OK uten nettverk; full gate.
|
||||
|
||||
### K8 Live-kjørings-drill + artefakt-fangst (S4.2-analog; paritetsrad 21)
|
||||
- **Mål:** en eventuell fremtidig live-kjøring (M2-analogen, operatør-gated) er ferdig-rigget:
|
||||
alt bygges, artefakter fanges, drillen er øvd offline — uten ett modellkall.
|
||||
- **Scope (filliste):** `run.py` (`--live-dry-run`: last kontrakter, kjør preflight, bygg
|
||||
klient-konfig, valider budsjett, skriv kjøringskonfig-logg (modell-id, parametre, tak —
|
||||
sammenligningsprotokoll §4.3-form) til outbox, STOPP før første modellkall), tester med
|
||||
kall-tellende mock.
|
||||
- **IKKE-scope:** selve live-kjøringen (M2-analog, operatør); endring i preflight/outbox.
|
||||
- **Gate:** ingen (forutsetter K5 + K7).
|
||||
- **TDD-plan:** RØD: dry-run mot kall-tellende mock-klient → NULL kall skjedde (detach-punkt:
|
||||
fjern stopp-punktet → kall telles → rød); RØD: artefakt-settet (konfig-logg + preflight-
|
||||
resultat) komplett og deterministisk i outbox.
|
||||
- **Nøkkelantakelse (+test):** klient-konstruksjon uten kall er gratis og nøkkel-fri
|
||||
(CLAUDE.md-verifisert SDK-premiss: import og konstruksjon fungerer uten API-nøkkel) —
|
||||
bindes med test som konstruerer klienten i suiten (uten nøkkel).
|
||||
- **Verifisering:** nye tester grønne + detach → rød; full gate.
|
||||
|
||||
### K9 HITL verdict-ruting + pending-sporing (S5.1-analog; paritetsrad 22)
|
||||
- **Mål:** operatøren ser hvilke forslag som venter på dom og hvem som skal dømme — ren
|
||||
fil-basert id-join outbox↔inbox.
|
||||
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/hitl.py` (pending-registry =
|
||||
outbox-forslag uten matchende inbox-/promotert dom, id-join på verdict-id; ruting-konfig
|
||||
`nøkkel → ekspert` skjema-validert fail-fast — nøkkelen er en konfig-streng nå,
|
||||
dimensjonskatalog-integrasjon kommer med K13), CLI `python -m portfolio_optimiser_claude.hitl
|
||||
pending|route`, tester.
|
||||
- **IKKE-scope:** varsling (K10); web-UI; skriving til inbox (rolledelingen §5 — hitl LESER
|
||||
begge lag).
|
||||
- **Gate:** ingen (forutsetter K5).
|
||||
- **TDD-plan:** RØD: forslag i outbox uten dom → listes utestående; dom lander i inbox →
|
||||
forsvinner fra pending (detach-punkt: fjern id-joinen → dømt forslag listes fortsatt →
|
||||
rød); RØD: malformet ruting-konfig → fail-fast; RØD: hitl skriver aldri (byte-sammenligning
|
||||
av outbox+inbox før/etter).
|
||||
- **Nøkkelantakelse (+test):** outbox-outcome bærer verdict-id-en å joine på (K5-formen) —
|
||||
bindes i K5s testfil og gjenbrukes her.
|
||||
- **Verifisering:** nye tester grønne + detach → rød; full gate.
|
||||
|
||||
### K10 Varsling/Notifier (S5.2-analog; paritetsrad 23)
|
||||
- **Mål:** leverbare varslings-implementasjoner uten å bryte ingen-stille-egress.
|
||||
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/notify.py` (`Notifier`-protokoll +
|
||||
`console`/`file`/`webhook`; webhook krever eksplisitt per-kjøring opt-in-flagg — mirror av
|
||||
ingest-spec §8-mønsteret («flagget er et run-argument, aldri konfig-felt») — + injiserbar
|
||||
transport, canned i tester, null socket i suiten), `run.py`/`hitl.py` (opt-in seam), tester.
|
||||
- **IKKE-scope:** e-post/Teams-adaptere; retry-politikk; kø.
|
||||
- **Gate:** ingen. **Koordineringspunkt (kapabilitetsnivå):** MAF S5.2 eksekveres nå — les
|
||||
MAF-STATE/plan-oppsummeringen (aldri koden) før sesjonen og speil kapabilitetsvalgene
|
||||
(protokoll-form, webhook-opt-in, socket-fri suite) der de er beskrevet på plan-nivå.
|
||||
- **TDD-plan:** RØD: webhook uten opt-in → nekt fail-fast (detach-punkt: fjern opt-in-sjekken
|
||||
→ transporten kalles → rød); RØD: canned transport mottar korrekt payload (struktur, ikke
|
||||
prosa); RØD: grep-guard ingen socket-sti utenfor den injiserbare seamen.
|
||||
- **Nøkkelantakelse (+test):** payload-formen kan holdes stack-lokal (ingen delt spec for
|
||||
varsling) — divergens mot MAF er akseptert og dokumentert i docstring.
|
||||
- **Verifisering:** nye tester grønne + detach → rød; full gate.
|
||||
|
||||
### K11 Verdirapport per kjøring (S5.4-analog; D-I pkt. 2; paritetsrad 25)
|
||||
- **Mål:** hver kjøring/porteføljepass produserer en deterministisk verdirapport — modellert →
|
||||
ekspert-korrigert → realisert, målprogresjon, tallfestet læringseffekt, kost-mot-verdi —
|
||||
uten ett modellkall.
|
||||
- **Scope (filliste):** ny `src/portfolio_optimiser_claude/valuereport.py` (ren projeksjon
|
||||
over ledger (K1) + outbox (K5) + costsim-estimat (K6); JSON + markdown-render, byte-stabil
|
||||
sort_keys/indent/LF), `run.py`/`portfolio.py` (opt-in `--value-report`), tester + committede
|
||||
fixtures.
|
||||
- **IKKE-scope:** dashboard; live-oppdatering; modellkall; nivå-2-README-påstander (kommer
|
||||
FØRST når beviset finnes — D-I pkt. 1).
|
||||
- **Gate:** ingen (forutsetter K1 + K5 + K6).
|
||||
- **TDD-plan:** RØD: to kjøringer med økende godkjenningsandel → læringseffekt-metrikk stiger
|
||||
og gap-krymping rapporteres (detach-punkt: fjern gap-beregningen → flat/feil → rød); RØD:
|
||||
prosjekt uten dom → «realisert» tomt/umerket, ALDRI lik modellert (detach ærlighets-grensen
|
||||
→ realisert=modellert → rød); RØD: byte-determinisme (samme ledger+outbox → identisk
|
||||
rapport, `diff`).
|
||||
- **Nøkkelantakelse (+test):** ledger+outbox bærer alt rapporten trenger — rapporten er ren
|
||||
projeksjon, ingen ny tilstand; testes ved å bygge rapport fra committede fixtures uten
|
||||
kjøring.
|
||||
- **Verifisering:** nye tester grønne + detach → rød; full gate.
|
||||
|
||||
### K12 CLI-paritet + dokumentsync + D-H-oppskrift (S5.3-analog; paritetsrad 24) — SISTE ugatede
|
||||
- **Mål:** operatøren driver ALT bygget (kjøring, portefølje, inbox, outbox, ledger, goals,
|
||||
pending, costsim, preflight, verdirapport) fra kommandolinja; README/extending.md/CHANGELOG
|
||||
påstår nøyaktig det koden gjør (§1); D-H-oppskriften leveres som dokument.
|
||||
- **Scope (filliste):** `run.py` (samlende CLI-flater: `--bundle/--inbox/--outbox/--verdict-dir/
|
||||
--goals/--ledger/--portfolio/--value-report`), `README.md`, `docs/extending.md`,
|
||||
`CHANGELOG.md`, nytt `docs/oppskrift-kunnskapsbase.md` (D-H pkt. 1: dokumentert team-prosess,
|
||||
ærlig 1–2-ukers-forventning; IKKE veiviser — B9 er FORKASTET i D-H), CLI-tester.
|
||||
- **IKKE-scope:** nye kapabiliteter; fabrikk-/demo-sti (T0-gated — oppskriften peker på den
|
||||
som fremtidig, merket ubygd).
|
||||
- **Gate:** ingen (forutsetter at K1–K11-kjeden er landet — ellers krymper scope ærlig).
|
||||
- **TDD-plan:** RØD: CLI-kjøring med goals+ledger på fixtures → mål-stopp observerbar i
|
||||
output (detach-punkt: koble goals fra CLI-stien → stopp uteblir → rød); RØD:
|
||||
ærlighets-grep i testform: README-claims-listen (inbox, portefølje, CLI) matcher skipbare
|
||||
stier (testen leser README og asserter at hver dokumentert kommando finnes i CLI-hjelpen).
|
||||
- **Nøkkelantakelse (+test):** ingen — ren wiring + docs.
|
||||
- **Verifisering:** CLI-tester grønne; manuell `uv run python -m portfolio_optimiser_claude.run
|
||||
--help`-røyk dokumentert i STATE; full gate.
|
||||
|
||||
## 4. Gatede sesjoner (startes IKKE før gaten er utløst — eksakt utløser per sesjon)
|
||||
|
||||
> Felles mal for D-A-bølgen (uendret fra gammel plan): amendment lander i commons →
|
||||
> koordinert subtree-pull i BEGGE repo → BEGGE suiter kjøres → failing test først
|
||||
> (review-moteksemplene ER fixturene) → impl → detach-bevis → full gate → golden uendret
|
||||
> (eller koordinert re-frosset i commons FØRST).
|
||||
|
||||
### C2.7 Validator-stramming (C-F2) — **Gate: D-A pkt. 1 godkjent + commons-pull utført**
|
||||
Uendret fra gammel plan §3: (a) strukturell blokk `claimed > nominal_feasible` → `Rejection`;
|
||||
(b) IR-invariant `low ≤ unit_cost ≤ high` (Pydantic `model_validator`). Premiss VERIFISERT
|
||||
2026-07-10 (golden- og fixture-kompatibel: alle ikke-tomme bands omslutter unit_cost;
|
||||
golden-claim 30 000 ≤ 90 000). TDD: moteksempel #1 (claim 100k/nominal 90k/band [0.70,1.40])
|
||||
→ MÅ bli Rejection; band [1.8,2.2] om unit_cost 1.0 → ValidationError; detach nominal-blokken
|
||||
→ rød. Filer: `validator.py`, `ir.py`, `tests/test_validator.py`, `tests/test_ir.py`;
|
||||
`test_bygg_energi_mikro.py` uendret grønn.
|
||||
|
||||
### C2.8 OKF `/`-lenke-mapping (C-F4) — **Gate: D-A pkt. 3 godkjent + commons-pull utført**
|
||||
Uendret fra gammel plan §3: ledende `/` mappes til bundle-rot i `navigate_bundle`;
|
||||
boundary-sjekken består fail-closed. TDD: `](/tiltak.md)` → navigeres (detach → rød);
|
||||
`](/../escape.md)` → fortsatt skippet. Filer: `okf.py`, `tests/test_okf.py`. Merk: MAF-siden
|
||||
mangler fortsatt egen F4-byggsesjon — flagget står (operatøren legger den til der).
|
||||
**Toolkit-kobling:** lander T0/K20 FØR D-A pkt. 3, flyttes `/`-mappingen inn i okf-core og
|
||||
C2.8 blir en konsum-oppgradering — sesjonene merges da eksplisitt.
|
||||
|
||||
### C3.2 Per-verdict seeding (C-F5) — **Gate: D-A pkt. 4 godkjent + commons-pull utført**
|
||||
Uendret fra gammel plan §3: seed leser features fra verdict-filas egen frontmatter (nye
|
||||
valgfrie felt `affected_codes`/`measure_type`/`claimed_saving_nok`; fallback = dagens
|
||||
nøkling); `promote` skriver feltene; multi-kandidat-fixture repo-lokal. TDD: to kandidater i
|
||||
én bundle → dom om B når ALDRI As prompt via retrieval på As features (detach → rød);
|
||||
eksisterende step1/step7/step8 uendret grønne (fallback). **R-8 (count-ærlighet, foldet inn):**
|
||||
`seed_store_from_bundle` skal returnere FAKTISK lagret antall (eller logge drops), ikke
|
||||
fil-antallet — RØD: to seed-filer uten `verdict_id`, ulik decision → i dag `seeded=2` men
|
||||
`len(store)==1`; med per-verdict-nøkling blir de distinkte, og count matcher (detach nøklingen
|
||||
→ count/antall divergerer igjen → rød). Filer: `experience.py`, `promotion.py`,
|
||||
loadbearing-testene, ny fixture.
|
||||
|
||||
### C4.0 Kostbaseline-forankring (C-F3) — **Gate: D-A pkt. 2 godkjent + commons-pull utført**
|
||||
Uendret fra gammel plan §3: baseline-projeksjon i bundle (`cost-baseline.json`,
|
||||
commons-format) + fail-closed avstemmings-stage i `validate_proposal` (ukjent kode →
|
||||
Rejection; utenfor toleranse → Rejection; toleranse konfig; baseline-argument VALGFRITT =
|
||||
dagens oppførsel, men kjøresti-inngangen (C2.0/`run.py`) SETTER den når fila finnes). TDD:
|
||||
F3-moteksemplet (diktet kode, 10 MNOK) → Rejection «unknown cost code» (detach → validated →
|
||||
rød); golden-bundelen (uten baseline-fil) validerer uendret. Filer: `validator.py`,
|
||||
`okf.py`/`ir.py` (loader), commons-fixture, nye tester. **MÅ være grønn før M2-analogen.**
|
||||
|
||||
### K13 Innholdsmodell + bibliotek + dimensjonskatalog + summary-tier (S3.5-analog) —
|
||||
**Gate: commons-amendmenten (D-F/D-G-utkastet 2026-07-14) operatør-godkjent, committet i
|
||||
commons OG pullet hit (koordinert med MAF; begge suiter grønne etter pull)**
|
||||
- **Scope:** bygg fra den nye spec-teksten (aldri fra utkastet før det er landet):
|
||||
(1) `dimension_catalog.py` — §13.3-katalogen, skjema-validert fail-fast (id, label,
|
||||
allowed_measure_types, allowed_code_prefixes) + scoping-gate; eksempel-katalog under
|
||||
`data/`; (2) `ingest.py` — `library`-kildefamilien (4a/5a: `library-{id}.md`, kuratert
|
||||
frontmatter + additivt provenance-lag, kildebelegg-håndheving fail-fast ved tom/manglende
|
||||
`sources`); (3) `okf.py` — summary-tier-render for bibliotek-typene (description-linje
|
||||
default; full body kun for deterministisk pre-run-utvalg — kandidatens dimensjon); (4) ny
|
||||
golden-case `examples/ingest-golden-library/` KUN hvis commons shipper den (fasit eies der).
|
||||
- **TDD:** RØD per amendmentens fire detach-punkter (S3.5-malen): ugyldig katalog → fail-fast;
|
||||
materialisert bibliotek-fil når prompten via `bundle_context` (detach → markør borte → rød);
|
||||
summary-tier gir én linje, ikke fulltekst (detach → fulltekst-stuffing → rød);
|
||||
separasjons-kontroll: bibliotek-fil når ALDRI prompten via dom-kanalen (folden).
|
||||
- **Nøkkelantakelse (+test):** default uten bibliotek-filer er byte-identisk med dagens
|
||||
render (amendment §3.2s garanti) — bindes med regresjonstest på eksisterende bundle FØR ny
|
||||
funksjonalitet skrives. C1.1-vakten skal forbli GRØNN gjennom pullen (amendment §5.1 er
|
||||
konstruert for det — verifiseres som pull-ens første sjekk).
|
||||
- **Verifisering:** nye tester grønne + detach → rød; `test_bygg_energi_mikro` + begge
|
||||
ingest-goldens uendret; full gate; sammenligningsprotokoll-kjøring i BEGGE repo.
|
||||
|
||||
### K14 MCP-ingest-konnektor (S2.2-analog) — **Gate: D-B besluttet + ingest-spec-amendment
|
||||
(mcp-familien) landet i commons + pullet hit**
|
||||
SDK-nativ analog: kildefamilie `mcp` i manifestet; test-fixture = in-process MCP-server via
|
||||
SDK-primitivet `create_sdk_mcp_server`/`@tool` (av-demoer extension-pointet uten socket).
|
||||
Per-run-grant: eksplisitt flagg (ingest-spec §8-mønsteret — run-argument, aldri manifest-felt).
|
||||
TDD: manifest med `type: mcp` uten grant → `IngestError` (detach → rød); golden-materialisering
|
||||
mot fixture-server byte-deterministisk; verdict-reservasjonen gjelder også mcp-familien.
|
||||
Nøkkelantakelse (testes FØRST i sesjonen): SDK-MCP-serveren kan drives i-prosess uten socket —
|
||||
hvis ikke, subprosess-fixture med eksplisitt merking. OBS: `ingest.py` er i dag SDK-fri —
|
||||
mcp-konnektoren legges i EGEN modul (f.eks. `ingest_mcp.py`) så ingest-kjernens renhet består
|
||||
(detach-vaktene i `test_ingest_loadbearing` urørte).
|
||||
|
||||
### K15 Dokument-konnektor PDF (S2.3-analog) — **Gate: D-B besluttet (inkl. pypdf-dep-valget)
|
||||
+ ingest-spec-amendment (doc-familien) landet + pullet**
|
||||
Tekst-ekstraksjon per side, fenced-verbatim-render (gjenbruk http-regelen fra spec §5),
|
||||
`max_rows`-cap, fail-fast på ikke-tekst-PDF; DOCX utsatt (D-B). TDD: golden byte-determinisme;
|
||||
cap-overskridelse → feil, aldri trunkering; pin pypdf-versjon (golden fanger drift).
|
||||
|
||||
### K16 http-kilde + konnektor-herding + guard-G1 (S2.4-analog) — **Gate: D-B besluttet MED
|
||||
http/live-kilde i scope (i dag eksplisitt utenfor D7-roadmap)**
|
||||
Bygger http-familien (i dag avvist fail-fast — det er selve utløseren som endrer det):
|
||||
`base_url`/`credential_ref` per ingest-spec §4, nettverks-opt-in per §8 (fail-fast uten flagg
|
||||
— load-bearing §11-raden «Network gate»), timeout + feilkategorisering mot injisert transport
|
||||
(aldri live), OG guard-planens G1-wiring i samme økt: `prepare_input` → deterministisk render
|
||||
→ `screen_output` FØR skriving av konseptfila; FAIL_SECURE → ikke skriv, alert med gate-kode
|
||||
uten innhold. Guard-dep pinnes + versjonsvakt (samme disiplin som C2.5). TDD: per feilmodus
|
||||
canned transport → presis IngestError; uten opt-in → nekt (detach → rød); injeksjons-fixture →
|
||||
fila skrives ALDRI (detach guard-gaten → payload lander i bundelen → rød — guard-planens §7).
|
||||
STATE-markørlinjen oppdateres `planned` → `integrated` med detach-bevis.
|
||||
|
||||
### K17 Semantisk henting (S3.1-analog) — **Gate: D-C besluttet OG C-P1 avklart i D-A-bolken
|
||||
(amendment av ranking-regelen ELLER re-scoping til strukturelle features) + evt. commons-pull**
|
||||
Scope avhenger av C-P1-utfallet: (a) amendment-varianten: `Retriever`-seam +
|
||||
`HybridRanker` (strukturell + cosine over lagrede vektorer, delt format .npy+jsonl per D-C),
|
||||
deterministisk fake-embedder i tester; (b) re-scoping-varianten: embeddings over strukturelle
|
||||
features alene. Uansett: ny `semretrieval.py` SDK-fri, opt-in seam i `experience.py`, ingen
|
||||
endring i `shared/`. TDD: syntetisk base der KUN den nye komponenten kan rangere riktig dom
|
||||
øverst (detach → rød); determinisme ×2 kjøringer; fake-embedder bit-stabil.
|
||||
`test_surface_text_never_contributes` består i variant (b); i variant (a) endres den KUN slik
|
||||
amendmenten krever.
|
||||
|
||||
### K18 Concurrency/feilmodell (S3.3-analog) — **Gate: D-D besluttet (+ K2 landet)**
|
||||
Bølge-modellen fra D-D-fasiten når den kommer: `run_portfolio(concurrency=k)`, snapshot per
|
||||
bølge, deterministisk merge-barriere, collect-and-continue-feilpolicy (erstatter K2s
|
||||
raise-default bevisst). TDD: concurrency=3 byte-identisk med concurrency=1 på 3-prosjekt-
|
||||
fixturen (detach barrieren → rød over repetisjoner); injisert feil i prosjekt 2 → 1+3 bevart.
|
||||
Nøkkelantakelse å teste FØRST: asyncio-samtidighet i én event-loop med ScriptedClient
|
||||
(SDK-klienten er async — anyio-premisset verifiseres i sesjonen).
|
||||
|
||||
### K19 Kostnadsstyring på tvers (S3.4-analog) — **Gate: D-D besluttet (deler feilpolicy)**
|
||||
`PortfolioBudget` (globalt tak + per-run-tak) over C3.5-primitivene; spend-persistens
|
||||
(deterministisk JSON, eksplisitt stamp); oppstartsnekt når rest < minimum per kjøring. TDD:
|
||||
globalt tak krysses midt i passet → strukturert stopp med fullførte runs bevart (detach → rød);
|
||||
pre-call-guard nekter kallet (kall-tellende mock).
|
||||
|
||||
### K20 okf-toolkit-adopsjon inkl. skrive-halvdelen (D-G/T0) — **Gate: okf-toolkit-repoet
|
||||
finnes, T1 (okf-core + formatprøve) er publisert/installerbar, OG operatøren har godkjent
|
||||
koordinert A1+A2-migrering (toolkit-briefens §7: migreringene er koblet, ikke uavhengige)**
|
||||
- **Scope:** importér `okf-core`; `okf.py`-lesekjernen delegerer/erstattes; skrive-halvdelen
|
||||
(render_frontmatter/write_concept_file/link_in_index-ekvivalentene) blir tilgjengelig her —
|
||||
D-Gs «minst like godt»-hovedgevinst; kjør formatprøven (conformance-testsettet) mot egne
|
||||
bundler i suiten; `pyproject.toml` (+dep, pin + versjonsvakt samme disiplin som C2.5).
|
||||
- **TDD:** RØD: formatprøven kjører i suiten og en bevisst malformert fixture-bundle feiler
|
||||
minst én conformance-test; RØD: skrive-primitivene importérbare og brukt av promotion-stien
|
||||
(detach → promotion faller tilbake/feiler → rød); eksisterende okf-purity-vakt beholdes
|
||||
(okf-core er stdlib-only per toolkit-briefen §2 — verifiseres, ikke antas).
|
||||
- **Bevisst avvik:** dette endrer «from spec alone» for formatlaget — operatør-besluttet
|
||||
(D-G pkt. 2, revisjonspakke §0.2); dokumenteres i README/CLAUDE.md i samme sesjon.
|
||||
- **Verifisering:** full gate; golden uendret; sammenligningsprotokoll-kjøring i BEGGE repo
|
||||
(A1-migreringen skjer koordinert på MAF-siden).
|
||||
|
||||
### Guard G3 (`okf.import_bundle`) — **Gate: delt D-E-retning åpner bundle-utveksling**
|
||||
Ingen egen sesjon planlegges før gaten: wiring-formen står i guard-planen §4 G3.
|
||||
|
||||
## 5. Avhengighetsgraf + anbefalt sekvens
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph OPER["Operatør-gater (delt kø i HOVEDREPOET + amendment/toolkit)"]
|
||||
DA["D-A (+C-P1)"]; DB["D-B"]; DC["D-C"]; DD["D-D"]; DE["D-E"]
|
||||
AMD["commons-amendment D-F/D-G"]; T0[["T0 okf-toolkit (finnes ikke)"]]
|
||||
end
|
||||
C11["C1.1 spec-vakt"] --> C25["C2.5 inbox+SDK-vakt+R6"] --> C20["C2.0 kjøresti-inngang"]
|
||||
C26["C2.6 validator-finitthet (R2)"]; K29["K2.9 ingest-robusthet (R3-R7)"]
|
||||
C20 --> K4["K4 closed-loop-sim (R1)"]
|
||||
C20 --> K2["K2 portefølje-kjøring"]
|
||||
K1["K1 ledger+goals"] --> K2 --> K3["K3 portefølje-læring"]
|
||||
K5["K5 outbox"] --> K8["K8 live-drill"]; K7["K7 preflight"] --> K8
|
||||
K5 --> K9["K9 HITL-ruting"] --> K10["K10 notifier"]
|
||||
K1 --> K11["K11 verdirapport"]; K5 --> K11; K6["K6 costsim"] --> K11
|
||||
C35["C3.5 budsjett-guard"] --> K8
|
||||
K3 --> K12["K12 CLI-paritet+oppskrift"]; K9 --> K12; K11 --> K12
|
||||
DA --> C27["C2.7 validator"]; DA --> C28["C2.8 /-lenker"]; DA --> C32["C3.2 seeding"]; DA --> C40["C4.0 kostbaseline"]
|
||||
AMD --> K13["K13 bibliotek+katalog+summary-tier"]
|
||||
DB --> K14["K14 MCP-ingest"]; DB --> K15["K15 doc-PDF"]; DB --> K16["K16 http+guard-G1"]
|
||||
DC --> K17["K17 semantisk henting"]; DA -. C-P1-avklaring .-> K17
|
||||
DD --> K18["K18 concurrency"]; DD --> K19["K19 kost på tvers"]; K2 --> K18; C35 --> K19
|
||||
T0 --> K20["K20 okf-core-adopsjon"]
|
||||
C40 --> M2A{{"M2-analog: evt. ny live-kjøring (operatør + D-E + D6-ny-godkjenning)"}}
|
||||
K8 --> M2A; DE --> M2A
|
||||
```
|
||||
|
||||
**Anbefalt sekvens (ugatet først — åpningen C1.1 → C2.5 → C2.0 står, med review-begrunnelse
|
||||
uendret):**
|
||||
|
||||
1. **C1.1 → C2.5 → C2.0** (vakt → herding → inngang)
|
||||
2. **C2.6 → K2.9** (korrekthets-hardening — R-2 validator-omgåelsen har høyest verdi av alt
|
||||
ugatet; kan tas rett etter C1.1 hvis ønskelig, uavhengig av C2.5/C2.0)
|
||||
3. **K4** (closed-loop-sim — lukker §11-gapet R-1 tidlig)
|
||||
4. **K1 → K2 → K3** (portefølje-fundamentet)
|
||||
4. **K5 → C3.5 → K6 → K7 → K8** (outbox/kost/preflight/drill)
|
||||
5. **K9 → K10 → K11 → K12** (HITL/varsling/verdirapport/CLI-sluttsync)
|
||||
6. Ved D-A (når som helst, uavhengig av 1–5): **C2.7 → C2.8 → C3.2 → C4.0** etter koordinert
|
||||
pull; ved amendment: **K13**; ved D-B: **K14 → K15 → K16**; ved D-C+C-P1: **K17**; ved
|
||||
D-D: **K18 → K19**; ved T0: **K20**.
|
||||
7. Vedlikehold når som helst: koordinert subtree-pull av de to docs-only commons-commitene
|
||||
(ingen spec-endring — men kjør begge suiter etter pull likevel, protokoll-regelen).
|
||||
|
||||
**Koordineringspunkter med MAF (absolutte):** (a) etter HVER amendment-bølge: begge repo
|
||||
puller subtree og BEGGE suiter kjøres — aldri én side alene; (b) golden re-fryses kun
|
||||
koordinert i commons; (c) K10 speiler MAF S5.2 på kapabilitetsnivå (plan-lesing, aldri kode);
|
||||
(d) K20/A1-migreringen er koblet på tvers av repoene (toolkit-brief §7); (e) C2.8-flagget om
|
||||
manglende MAF-F4-byggsesjon står til operatøren har lagt den til der.
|
||||
|
||||
## 6. Operatør-milepæler (aldri autonome sesjoner)
|
||||
|
||||
- **M2-analog — eventuell ny live-kjøring:** krever ALT av: eksplisitt operatør-godkjenning
|
||||
(D6: ny spend), D-E (stack-paritet for ekte kjøring — avgjør om D7 i det hele tatt skal
|
||||
kjøre live igjen), C4.0 grønn (kostbaseline FØR ekte modell), C3.5 + K6 + K7 + K8 grønne
|
||||
(guard, estimat, preflight, drill), harde tak satt. Forutsetningen «nøkkel satt + preflight
|
||||
grønn» er D7-ekvivalenten av MAFs M1. Utfall re-rulles ikke (protokoll §4.5).
|
||||
- **M3-analog (pilot):** følger MAF-planens M3 — ikke planlagt her før D-B/D-E/toolkit-
|
||||
fabrikken foreligger; D7-deltakelse avgjøres av D-E.
|
||||
|
||||
## 7. Leveringsklar-definisjon (binær sjekkliste)
|
||||
|
||||
«Leveringsklart» er nådd når ALLE punkter under er sanne (hver enkelt er kommando-verifiserbar):
|
||||
|
||||
- [ ] Alle paritetsmatrise-rader (§1) er enten **FINNES HER** (bygget + load-bearing-testet)
|
||||
eller **SPEILES IKKE** med begrunnelse operatøren har sett — ingen rad står i BYGGBAR
|
||||
NÅ; GATED-rader er enten utløst+bygget eller eksplisitt operatør-akseptert som
|
||||
utestående (beslutnings-køens ansvar, dokumentert i STATE).
|
||||
- [ ] Full gate grønn: `uv run pytest` (alle tester, offline uten nøkkel/nett) +
|
||||
`uv run ruff check .` + `uv run ruff format --check .` + `uv run mypy src`.
|
||||
- [ ] §11-tabellen komplett: hver rad (inkl. «Spec integrity» C1.1 og «Closed loop» K4) har
|
||||
en navngitt test som er detach-bevist rød (bevis i testfil eller sesjonslogg).
|
||||
- [ ] README/docs ærlige (§1): hver kapabilitets-påstand matcher en skipbar sti (K12s
|
||||
ærlighets-test grønn); skriptede stand-ins merket; ingen nivå-2-verdipåstand uten
|
||||
D-I-belegget.
|
||||
- [ ] Guard-markørlinjen i STATE.md er korrekt (planned/integrated per faktisk wiring-status,
|
||||
med detach-bevis hvis integrated).
|
||||
- [ ] Golden-bytene uendret mot commons (eller re-frosset KOORDINERT i commons med begge
|
||||
suiter grønne).
|
||||
- [ ] `runs/s10/` byte-urørt; `run_s10.py` byte-urørt.
|
||||
- [ ] Subtree i synk med commons (ingen utestående spec-commits; verifisert med subtree-diff).
|
||||
- [ ] STATE.md oppdatert etter konvensjonen; CHANGELOG dekker alle landede sesjoner.
|
||||
- [ ] **`open`-speiling som EGEN operatør-gated sluttpost:** push til `open` skjer ALDRI
|
||||
automatisk — operatøren godkjenner eksplisitt hvilke commits som speiles, som siste
|
||||
handling etter alt over.
|
||||
|
||||
## 8. Endringer mot 2026-07-10-planen
|
||||
|
||||
| Gammel plan | Endring |
|
||||
|---|---|
|
||||
| §4 «Overføres IKKE hit (MAF-spesifikt)» | **OPPHEVET** — re-klassifisert rad for rad i §1 (operatør-mandat 2026-07-16) |
|
||||
| C1.1/C2.0/C2.5/C2.7/C2.8/C3.2/C3.5/C4.0 | Videreført uendret i substans (C3.5 løftet fra «valgfri» til paritetskrav; C2.5 utvidet med guard-G2-vurdering) |
|
||||
| «ingen D7-HTTP/MCP-økt planlagt» | Erstattet av K14–K16, gated D-B |
|
||||
| (fantes ikke) | K-serien: K1–K20 (paritetssesjoner) + M2-/M3-analoger + leveringsklar-definisjon (§7) |
|
||||
| (fantes ikke) | Review-paritet R-serien (2026-07-16): C2.6 (R-2 validator-finitthet), K2.9 (R-3/R-4/R-5/R-7 ingest-robusthet), K4 (R-1 closed-loop); R-6→C2.5, R-8→C3.2, R-10→C2.0/C2.5 |
|
||||
Loading…
Add table
Add a link
Reference in a new issue