portfolio-optimiser-claude/docs/2026-07-16-review-paritet.md
Kjell Tore Guttormsen d746891f06 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>
2026-07-16 08:36:07 +02:00

27 KiB
Raw Blame History

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). Paritetsmatrisen + sesjonsplanen ligger i 2026-07-16-sesjonsplan-paritet.md; operatør-køen i 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:sharedcommons/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: InfinitySavingsProposal konstrueres, validate_proposalValidatedProposal(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 materializes 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 [LOWMEDIUM · 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 [LOWMEDIUM · 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_candidatemint_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 [LOWMODERAT · 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_idseeded=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:73seed_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_isolations 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, GitHub 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, 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:sharedcommons/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 16 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):

  • 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).