portfolio-optimiser-claude/docs/review-2026-07.md
Kjell Tore Guttormsen 3f106fcfd1 docs(review): kryssmodell-review + sesjonsplan-synk mot delt beslutnings-kø D-A–D-E
Fable 5-review av D7-søskenet, speil av MAF-reviewen 2026-07-09: baseline
re-verifisert (265/ruff/mypy), F2/F3/F5/F7-analoger kjørt-bevist, F1/F11
avkreftet i MAF-form, egne funn (method-spec-vakt mangler, Steg-7-inngang,
SDK-versjonsvakt, D-C↔spec-kollisjon), 11/11 detach-eksperimenter røde i
throwaway-kopi. Sesjonsplan: byggbare-nå C1.1/C2.5/C2.0 + D-A-gatede speil
C2.7/C2.8/C3.2/C4.0.
2026-07-10 07:29:35 +02:00

267 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Uavhengig kryssmodell-review — portfolio-optimiser-claude (2026-07-10)
> **Reviewer:** Fable 5 (xhigh), uavhengig av Opus 4.8 som skrev koden. **Mandat:** speil av
> MAF-søskenets kryssmodell-review (2026-07-09) — verifiser hvert MAF-funn mot DENNE kodebasen
> (premisser, ikke fakta) + uavhengig sveip etter D7-egne blindsoner. Ingen live-filer ble
> endret under selve reviewen; fletting (dette dokumentet + sesjonsplan + STATE) er
> operatør-forhåndsgodkjent.
>
> **Metode:** all kildekode lest (16 moduler), alle nøkkel-tester lest, full lokal suite +
> ruff + mypy kjørt, F2/F3/F5/F7-moteksempler KJØRT mot live-modulene (read-only), og
> **11 detach-eksperimenter utført i en throwaway-kopi** (scratchpad — live-repoet urørt).
> Hver påstand har `fil:linje`- eller kommando-belegg; verifiseringslogg nederst.
## 0. Baseline (verifisert, ikke sitert fra STATE)
| Påstand | Resultat | Belegg |
|---|---|---|
| Testsuite | **265 passed** (1.6s) — STATE/CHANGELOG-tallet stemmer | `uv run pytest -q` |
| Lint / typer | ruff clean (40 filer formatert); mypy clean (16 filer, strict) | `uv run ruff check .`; `uv run mypy src` |
| Push-status | HEAD `42f320b` == `origin/main` == `open/main` — STATEs påstand stemmer | `git rev-parse` alle tre |
| Offline-invariant | Suiten kjører uten nøkkel/nettverk; ingen egress-stier i `src/` utenfor SDK-klienten | suite-kjøring + grep `urllib\|socket\|requests` |
| S10-artefakter | `runs/s10/` urørt (fasit, protokoll §4.2/§4.5) — IKKE re-kjørt | kun lest |
**Detach-bevis (load-bearing-stikkprøver, ALLE 11 RØDE i kopien — MAF-paritet 11/11):**
(1) Steg-1-fold detached → `test_step1` + `test_step7` røde (4 failed); (2) checker-override
detached → `test_checker_gate` rød (3); (3) inbox-merge detached → `test_step7` rød (2);
(4) promotion-index-lenke detached → `test_step8` rød (5); (5) verdict-eksklusjon fjernet fra
`bundle_context``test_okf` + `test_step8` røde (2); (6) `setting_sources=[]``None`
`test_sdk_isolation` rød (2); (7) informert refinement detached → `test_step5` rød (2);
(8) verbatim-id-seeding re-mintet → `test_step8` rød (2); (9) re-ingest-lagsikkerhet detached
(alle .md «stamped») → `test_ingest_loadbearing` rød (1); (10) `import claude_agent_sdk` i
`okf.py` → purity-testene røde (2); (11) usage-fail-closed detached → `test_budget` rød (1).
Kopien verifisert isolert (pakken importerte fra kopiens `src/`) og revertert ren etterpå.
**Metoden holder på alle stikkprøvde sømmer.**
---
## 1. Funn (rangert, mest alvorlig først)
Ingen BLOCKER i dagens påstands-omfang: single-run-claims er sanne, detach-beviste, og
README/extending.md er gjennomgående ærlige (§1). Funn 12 og 45 er spec-nivå-defekter som
finnes her *by construction* (samme frosne spec) og deler beslutning D-A med MAF-siden.
### C-F2 [MAJOR · spec-nivå] Validator: nominal-grensen gater aldri — selv-forfattede bands blåser P90 forbi «maximum feasible» (F2-analog: BEKREFTET)
- **Belegg:** eneste numeriske blokk er P90 (`validator.py:68`); `nominal_feasible` beregnes
(`validator.py:53`) men brukes aldri som gate. `assumptions` forfattes av modellen selv
(`loop.py:66-73` parser fritt; `ir.py:30-49` har ingen invariant om at bandet omslutter
`unit_cost`). **Kjørt bevis (live-modul, read-only):** golden-bundelens egne tall — total
300 000, nominal 90 000, band [0.70, 1.40] — validerer claim **100 000 > 90 000**
(p90=121 057.09). Band helt over unit_cost ([1.8, 2.2]) validerer claim **55 000 mot
nominal 30 000** (p90=65 058.49). Nøyaktig samme tall som MAF-moteksemplene — bekrefter
at defekten er spec-båren, ikke implementasjonsbåren.
- **Feilscenario:** en ekte proposer setter et optimistisk band → claim over den
deterministiske feasibility-grensen stemples `validated` og persisteres som
«validator-godkjent» i run-artefaktene.
- **Fiks:** speiling av MAF S2.7 — (a) strukturell blokk `claimed > nominal_feasible`;
(b) IR-invariant `low ≤ unit_cost ≤ high`. **Golden- OG fixture-kompatibel her, verifisert:**
golden-claim 30 000 ≤ 90 000; alle ikke-tomme bands i dette repoets fixtures omslutter
unit_cost ([0.8,1.2]∋1.0 `test_ir.py:26`; [0.70,1.40]∋1.0 golden; (0.70,1.50)∋1.0
`test_bygg_energi_mikro.py:83`; resten tomme). Gated på **D-A pkt. 1 + commons-pull**
→ sesjon **C2.7**.
### C-F3 [MAJOR · spec-nivå] `affected_items` forankres ikke mot noen kostbaseline (F3-analog: BEKREFTET)
- **Belegg:** `_parse_candidate` aksepterer vilkårlige modell-forfattede kostlinjer
(`loop.py:66-73`); ingenting i bundle-formatet bærer en kostbaseline å avstemme mot.
**Kjørt bevis:** diktet linje `{code:"XX-DIKTET", quantity:1e6, unit_cost:10}` → total
10 MNOK → claim **2 900 000 stemples `validated`** (degenererte percentiler 3.0 MNOK uten
band). IR-invarianten (claim ≤ items-total, `ir.py:39-49`) regner kun på selv-deklarerte tall.
- **Feilscenario:** mot en ekte modell er «validatoren avgjør tallene» tom mot hallusinerte
kostlinjer; kun checker-LLM-en (fail-open, `loop.py:200-212`) står imellom.
- **Fiks:** speiling av MAF S4.0 — fail-closed avstemmings-stage mot en baseline-projeksjon
i bundelen (commons-amendment for `cost-baseline.json`). Gated på **D-A pkt. 2** → sesjon
**C4.0**. MÅ være grønn før enhver eventuell fremtidig live-kjøring i dette repoet (D6:
ny spend krever uansett ny operatør-godkjenning).
### C-N1 [MAJOR · konformitet · D7-EGEN] Method-spec-integritetsvakten mangler — §11-raden «Spec integrity» er uimplementert
- **Belegg:** ingen test i repoet refererer `method-spec.md`
(`grep -rn "method-spec\|method_spec" tests/` → null treff i testkode). Spec §11 krever:
«this spec goes missing, names a framework, or stops documenting a consumed contract
field» → rød (referansetest `test_method_spec_loadbearing.py`); §1 pkt. 3 gjør §11-tabellen
til konformitetskrav. Ingest-spec-en HAR sin analog (`test_ingest_spec_loadbearing.py`
forbidden-toolkits + kontraktsfelt-dekning), så mønsteret finnes i repoet; method-spec-vakten
ble aldri speilet. Spec-intro-ens «a guard test keeps it that way» er dermed sann kun via
MAF-søskenets test — dette repoet håndhever den ikke selv.
- **Feilscenario:** en commons-pull som (utilsiktet) endrer method-spec-en — fjerner et
kontraktsfelt fra §12-tabellen eller introduserer rammeverksnavn — passerer denne suiten
grønt; D7 mister sin eneste lokale detektor for spec-drift i subtree-synken.
- **Fiks:** ny `tests/test_method_spec_loadbearing.py` etter ingest-spec-mønsteret
(fil-eksistens, forbidden-toolkits, §12-kontraktsfelt-dekning for feltene DENNE
implementasjonen konsumerer). Ingen beslutnings-avhengighet → sesjon **C1.1** (byggbar NÅ).
### C-F5 [MAJOR · spec-nivå] ExpeL-seeding feilnøkler features på bundelens ENE kandidat (F5-analog: BEKREFTET, med nyanse — id-halvdelen er allerede løst her)
- **Belegg:** `seed_store_from_bundle` leser features fra `load_validator_input(bundle_dir)`
— bundelens ENE IR-projeksjon — og gir ALLE `type: verdict`-filer de samme features
(`experience.py:132`, `experience.py:145-152`). **Nyansen:** `verdict_id` leses VERBATIM
fra frontmatter (`experience.py:147`), så id-kollisjonen MAF-funnet beskrev er avverget
for promoterte filer — load-bearing-bevist (`test_step8:test_two_promoted_candidates_both_seed_verbatim_ids`).
**Kjørt bevis for rest-defekten:** to promoterte dommer om ulike kandidater (E01/led-retrofit
vs E99/ventilation) seedes begge med bundle-features (ENERGI-TOTAL-EL/LED) — retrieval kan
ikke skille dem; en spørring med kandidat Bs egne features rangerer på feil grunnlag.
- **Feilscenario:** flerkandidat-bundle: dom om tiltak B foldes inn i hypoteser om tiltak A —
feil læringssignal, presist det klynge C-skalering forutsetter at ikke skjer.
- **Fiks:** speiling av MAF S3.2 — seed leser features fra verdict-filas egen frontmatter
(promote skriver dem), fallback dagens nøkling. Gated på **D-A pkt. 4** → sesjon **C3.2**.
### C-F4 [MAJOR · frossen-ramme-utfordring] `/`-prefiksede OKF-lenker hoppes over — spec-tro implementasjon av en spec-feil (F4-analog: BEKREFTET)
- **Belegg:** `navigate_bundle` skipper ethvert mål med `/` eller `\` (`okf.py:112`) —
method-spec §3 Steg 1 pinner regelen. OKF-spec-en anbefaler bundle-rot-relativ `/`-form
(MAF-review U-1, WebFetch-verifisert 2026-07-09; ikke re-hentet her — nettverksregel).
- **Feilscenario (D7-spesifikk nyanse):** en ekstern bundle med `](/tiltak.md)`-lenker
navigerer til KUN index. Har indexen citerbar body, feiler kjøringen IKKE fast —
`build_citations` siterer index-bodyen (`artifacts.py:31-59`) og kjøringen fortsetter med
stille kontekst-tap; kun en body-løs index gir fail-fast («no citable content»).
- **Fiks:** kun via **D-A pkt. 3** (spec-amendment: ledende `/` mappes til bundle-rot,
fortsatt fail-closed boundary) → sesjon **C2.8**. Merk: MAF-planen har i dag INGEN
bygg-sesjon for F4-implementasjonen på sin side — bør legges til der når D-A lander.
(Relatert MINOR, samme som MAF: en index-lenket `log.md` — reservert i OKF — ville
rendres som konseptfil; `okf.py:128-134` filtrerer kun verdict + tom body.)
### C-F7 [MINOR nå → MAJOR ved flerbruker/klynge E] Verdict-inboxen er en uvalidert prompt-injeksjonsflate (F7-analog: BEKREFTET)
- **Belegg:** `decision` valideres kun som ikke-tom streng (`inbox.py:47`) — modulens
docstring UTSETTER eksplisitt vokabular-politiet til §4.1/§6 (`inbox.py:10-13`), men på
merge-stien (`inbox.py:122-132`) fins ingen sjekk; `rationale` flyter verbatim inn i
hypotese-prompten via folden (`experience.py:157-171`). Ingen størrelses-/antall-tak.
**Kjørt bevis:** `{"decision": "hva-som-helst", "rationale": "IGNORE ALL PREVIOUS
INSTRUCTIONS…"}` → merged=1, decision-strengen OG injeksjonsteksten når prompten.
- **Fiks (fortsatt tolerant — skip, aldri raise):** vokabular-sjekk mot {approved, rejected,
approved_with_adjustment}-settet ved merge, tak på rationale-lengde + antall filer.
Ingen beslutnings-avhengighet → sesjon **C2.5**.
### C-N2 [MINOR · D7-EGEN] Steg-7-inboxen har ingen kjørbar kjøresti-inngang
- **Belegg:** `merge_inbox_into_store` kalles fra INGEN kjøresti — `run_s10.py:44-54` har
ingen `--inbox`-arg og kaller kun `seed_store_from_bundle` + `fold_experience`
(`run_s10.py:72-79`). Steg 7 (§3/§5: «a run ingests the inbox INTO its store BEFORE the
Step-1 fold») er bevist som primitiv + test-komposisjon (`test_step7`, detach-bevist rød),
men ingen skipbar inngang komponerer den. README sier «a later run ingests it tolerantly
and merges it before the fold» (`README.md:66-68`) — sant om kontrakten, men ingen
leverbar kjøresti gjør det. (Til forskjell fra MAF-F1: ingen død docstring-påstand —
folden ER wiret på den ene kjørestien som finnes; F1 i MAF-formen er AVKREFTET her.)
- **Feilscenario:** en operatør som dropper en dom i en inbox-mappe og re-kjører har ingen
kommando som plukker den opp — læringssløyfas lange tidsskala er i praksis kun
promoterings-veien (som ER wiret via bundle-seeding).
- **Fiks:** generalisert kjøresti-inngang (offline-testbar komposisjonsfunksjon +
`--inbox`/`--verdict-dir`-arg; `run_s10.py` forblir urørt fasit-sti). Ingen
beslutnings-avhengighet → sesjon **C2.0**.
### C-N3 [MINOR · D7-EGEN] SDK-avhengigheten er løst pinnet og run-stien leser 0.2.110-attributter uten versjonsvakt (F11-analog: AVKREFTET for testdobbelen, rest-risiko på run-stien)
- **Belegg:** testdobbelen er REN — `ScriptedClient` implementerer repoets egen
`ModelClient`-protokoll og importerer ingenting fra SDK-en (`tests/_scripted.py`), så
MAF-F11s privat-API-skjørhet i suiten er AVKREFTET her. Men run-stien leser
`AssistantMessage.error/.model`, `ResultMessage.usage/.total_cost_usd/.is_error/.subtype/.errors`
(«verifisert mot 0.2.110», `sdk_client.py:12-17,108-121`) med pin `claude-agent-sdk>=0.2`
(`pyproject.toml:8`) — enhver 0.x-oppgradering kan endre attributt-semantikken stille,
og `_total_tokens` summerer da et KRYMPET felt-subsett uten feil (`sdk_client.py:66-71`).
- **Fiks:** pin `>=0.2,<0.3` + versjonsvakt-test med handlingsrettet melding (tvinger bevisst
re-verifisering av attributt-premissene ved oppgradering) → inn i sesjon **C2.5**.
### C-N4 [MINOR] Token-taket lades ETTER fullført kall; USD-taket er kun per-kall (F10-analog: DELVIS BEKREFTET)
- **Belegg:** `meter.charge_tokens` kalles etter `client.complete` returnerer
(`loop.py:91`, `budget.py:43-51`) — kallet som krysser taket fullføres (og koster) før
raise, som i MAF. USD: per-kall-tak finnes førsteklasses (`sdk_client.py:87`,
`ClaudeAgentOptions.max_budget_usd` — bedre enn MAF), men ingen run-total USD-grense;
totalen er kun indirekte bundet (antall kall × per-kall-tak, antall kall bundet av
meteren). **Ærlighets-nyansen fra MAF-F10 er AVKREFTET her:** ingen docstring lover
«short-circuits» — `budget.py:1-9` beskriver mekanikken presist.
- **Fiks (lav prioritet):** pre-call-guard + eksplisitt run-total USD-tak → valgfri sesjon
**C3.5** (uavhengig; mest verd før en eventuell ny live-kjøring).
### C-S1 [SUGGESTION] Checker-parse: `VERDICT: REJECT`-substring-presedens hvor som helst (F13-analog, spec-pinnet)
- `_REJECT_PATTERN.search` over hele teksten (`loop.py:42,186-194`): en checker som SITERER
formatet feiltolkes som reject. Spec-konformt (§3 Steg 4 pinner presedensen) — flagges som
robusthet; evt. siste-linje-parse er en D-A-nyansering (allerede i MAF-planens D-A pkt. 5-nabolag).
### C-S2 [SUGGESTION] `max_rows`-cap håndheves etter full innlesing
- `_read_csv` leser hele fila før cap-sjekk (`ingest.py:190-197`); `_read_sql` gjør
`fetchall()` før sjekk (`ingest.py:244-247`). Fail-fast i UTFALL (aldri stille trunkering,
§8-konformt), men en enorm lokal kilde leses helt inn i minnet først. Akseptabel MVP-grense
for lokale kilder; noteres for en evt. streaming-variant.
### C-S3 [SUGGESTION] Døde/små ting
- `promotion._link_from_index` er ikke-atomisk RMW — dokumentert MVP-grense
(`promotion.py:92-95`), samme som MAF-F6s index-del; blir først reell ved concurrency
(D-D), som D7 ikke har noen sti for i dag.
- `model_map.json` har kun `anthropic`-profil (Bedrock/Vertex/Foundry er env-switch-konfig
per design) — ingen placeholder-problem à la MAF-P6 her.
### C-P1 [MAJOR · plan-nivå · DELT — flagges til hovedrepoet] MAF-planens S3.1 (semantisk henting) kolliderer med frossen method-spec §3 Steg 1
- **Belegg:** method-spec §3 Steg 1 (frossen): «Ranking is **structural, never textual**
surface text MUST NOT contribute to similarity.» MAF-planens S3.1 bygger «HybridRanker =
dagens strukturelle score + cosine over lagrede vektorer» gated KUN på D-C — men cosine
over embeddings av rationale-/overflatetekst ER tekstlig similarity og bryter spec-en
uten amendment. D7 håndhever regelen i dag (`experience.py:83-95` + load-bearing
`test_surface_text_never_contributes`).
- **Konsekvens:** D-C-beslutningen må enten (a) kobles til et D-A-punkt som amender
ranking-regelen bevisst, eller (b) scope S3.1 til embeddings over strukturelle features.
Gjelder BEGGE repo — dette er en delt beslutnings-forutsetning MAF-reviewen ikke fanget.
---
## 2. MAF-funnene — status i dette repoet
| MAF-funn | Status her | Belegg / hvor |
|---|---|---|
| F1 (portefølje-læringssløyfe død) | **Avkreftet i MAF-formen** — ingen portefølje-sti finnes; folden ER wiret på eneste kjøresti (`run_s10.py:72-79`); ingen død docstring. Rest-analog: C-N2 (ingen kjørbar Steg-7-inngang) | §1 C-N2 |
| F2 (nominal gater aldri) | **Bekreftet** (kjørt bevis, identiske moteksempel-tall) | §1 C-F2 |
| F3 (ingen kostbaseline) | **Bekreftet** (kjørt bevis, 2.9 MNOK validert) | §1 C-F3 |
| F4 (`/`-lenker skippes) | **Bekreftet** (`okf.py:112`; spec-tro; stille-tap-nyanse) | §1 C-F4 |
| F5 (én-kandidat-seeding) | **Bekreftet med nyanse** — id-halvdelen ALLEREDE løst (verbatim `verdict_id` + load-bearing test); feature-halvdelen kjørt-bevist | §1 C-F5 |
| F6 (concurrency/RMW) | **Ikke anvendbar** — ingen portefølje-/concurrent-sti; RMW-grensen dokumentert (`promotion.py:95`). Relevant først ved D-D-speiling | §1 C-S3 |
| F7 (inbox-injeksjon) | **Bekreftet** (kjørt bevis) | §1 C-F7 |
| F8 (metode-cap fail-open) | **Ikke anvendbar** — D7-validatoren har ingen metoderegler (kun §3-Steg-4-kjernen); golden krever dem ikke | `validator.py` (hele) |
| F9 (prosent-mål/baseline) | **Ikke anvendbar** — ingen goals/ledger-lag i D7 | filkatalog |
| F10 (budsjett post-charge) | **Delvis bekreftet** — post-charge ja; docstring ærlig; per-kall-USD-tak finnes (bedre enn MAF); run-total USD-tak mangler | §1 C-N4 |
| F11 (privat-API i doubles) | **Avkreftet for testdobbelen** (egen protokoll); **rest-risiko på run-stien** (løs pin, ingen versjonsvakt) | §1 C-N3 |
| F12 (CHANGELOG stale) | **Avkreftet**`CHANGELOG.md:16` sier 265 == suiten | baseline |
| F13 (småting) | **Delvis** — checker-parse-presedensen gjelder (C-S1); `_authored_texts`-dødkoden og retrieval-substring er MAF-spesifikke (D7-similarity er ren strukturell) | §1 C-S1 |
| F14 (Magentic-begrunnelse) | **Ikke anvendbar** — ingen MAF/Magentic-referanser i D7 | grep |
| P1/P2 (roadmap vs ingest-målbilde / MCP-wiring) | **Ikke anvendbar** — D7 har ingen Fase-2-roadmap; `extending.md` er ærlig om HTTP/MCP ubygd (peker-only) | `docs/extending.md:128-160` |
| P4 (output-lag ubygget) | **I hovedsak avkreftet her**`artifacts.py` persisterer proposal/result/provenance/usage + stop-artefakter deterministisk (`runs/s10/`). Rest: run_id-basert outbox + pending-sporing KUN hvis D7 skal speile Fase 5 (ikke planlagt) | `artifacts.py:83-152` |
| P5 (verdict_dir i portefølje) | **Ikke anvendbar** (ingen `run_portfolio`) | filkatalog |
| P6 (stubs: notify/MCP-demo/Azure-placeholders/main-paritet) | **Ikke anvendbar** i MAF-formen — ingen slike stubs her; CLI-paritets-resten dekkes av C-N2/C2.0 | §1 C-N2 |
| U-1U-4 (frossen-ramme-utfordringer) | Samme status som F4/F2+F3/P1/F5 over — D7 slutter seg til U-1/U-2/U-4; U-3 ikke anvendbar | §1 |
## 3. Utfordringer mot frosne beslutninger (KLART MERKET — kun operatøren kan endre)
D7-siden SLUTTER SEG TIL MAF-reviewens U-1 (`/`-lenker), U-2 (validator-semantikk) og U-4
(seeding-regelen) med egne kjørte bevis (§1), og legger til:
| # | Frossen ramme | Utfordring | Belegg |
|---|---|---|---|
| U-5 (ny) | method-spec §3 Steg 1 («structural, never textual») | Delt D-C-plan (semantisk henting) er uimplementerbar uten amendment eller re-scoping — koblingen D-C↔D-A mangler i den delte køen | §1 C-P1 |
Ingen utfordring rettes mot: golden-suiten (reprodusert eksakt), maker-checker-gaten
(detach-bevist), fail-closed promotering (detach-bevist), verdict-eksklusjonen
(detach-bevist), SDK-isolasjonsvalget `setting_sources=[]` (detach-bevist; S10-post-mortem-
begrunnelsen står), eller load-bearing-regelen (11/11 stikkprøver røde).
## 4. Verifiseringslogg
| Påstand | Kilde/kommando |
|---|---|
| 265 passed / ruff clean / mypy clean (16 filer) | `uv run pytest -q` (1.60s); `uv run ruff check .`; `uv run ruff format --check .`; `uv run mypy src` (2026-07-10) |
| HEAD == origin/main == open/main | `git rev-parse HEAD origin/main open/main` → alle `42f320b` |
| 11 detach-eksperimenter røde | throwaway-kopi i scratchpad; driver-script med kirurgisk patch + `uv run pytest <målfil>` per søm + git-revert; kopi-isolasjon verifisert (`portfolio_optimiser_claude.__file__` peker i kopien); 11/11 RED, 0 anomalier |
| F2-moteksempler validerer | `uv run python` mot live-modul (read-only): claim 100k>nominal 90k → ValidatedProposal p90=121 057.09; claim 55k>nominal 30k (band [1.8,2.2]) → ValidatedProposal p90=65 058.49 |
| F3-moteksempel validerer | samme script: diktet linje 1e6×10 → claim 2.9 MNOK → ValidatedProposal (percentiler 3.0 MNOK) |
| F5-feilnøkling | kjørt i kopien: to promoterte dommer (E01 vs E99) → begge store-records bærer bundle-features (ENERGI-TOTAL-EL/LED); distinkte ids (verbatim) |
| F7-injeksjon | kjørt i kopien: `decision:"hva-som-helst"` + injeksjons-rationale → merged=1, begge når prompten via folden |
| Method-spec-vakt mangler | `grep -rn "method-spec\|method_spec" tests/` → 0 treff; `test_ingest_spec_loadbearing.py` finnes (mønsteret) |
| C2.7-antakelsen (alle bands omslutter unit_cost) | grep over tests/ + examples/ + shared/examples/: eneste ikke-tomme bands [0.8,1.2]∋1.0, [0.70,1.40]∋1.0, (0.70,1.50)∋1.0 — null brudd |
| Ingen egress i src utenfor SDK-klient | `grep -rn "urllib\|socket\|requests\.\|http" src/…/*.py` → kun docstring-treff i ingest.py |
| S10-artefakter urørt | kun lest; ingen re-kjøring (protokoll §4.2/§4.5) |
| OKF-spec-ens `/`-anbefaling | IKKE re-verifisert her (nettverksregel denne sesjonen) — arvet fra MAF-review §6 (WebFetch 2026-07-09), merket som arvet premiss |
| SDK-attributt-premisser («verifisert mot 0.2.110») | arvet fra kodens egne verifikasjonsnotater (`sdk_client.py:12-17`, CLAUDE.md) — ikke re-verifisert mot nyere SDK; nettopp derfor C-N3 krever versjonsvakt |