portfolio-optimiser/docs/review-2026-07.md
Kjell Tore Guttormsen 37547fe292
refactor(examples): replace sector-specific example material with generic, fictitious examples
The context sets, the packaged knowledge bases and the example bundles are
replaced by one fictitious example set about IT operations in an invented
organisation: three context sets (serverrom-2027, driftsavtale-2027 and the
two-base drift-og-avtale-2027), two synthetic knowledge bases under
src/portfolio_optimiser/data/kunnskapsbaser and two example bundles under
src/portfolio_optimiser/data/bundles. Numbers, codes and structural values in
tests and fixtures are kept; names, ids and wording change. Dated measurement
documents that only recorded runs on the replaced material are deleted.

Gate figures measured on the new set are not comparable with earlier ones.
The exclusion gate from the previous commit is green: 0 tracked files hit
outside the shared/ subtree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 15:04:21 +02:00

24 KiB
Raw Blame History

Uavhengig kryssmodell-review — portfolio-optimiser (2026-07-09)

Reviewer: Fable 5 (xhigh), uavhengig av Opus 4.8 som skrev koden. Mandat: adversarisk fire-akse-review + re-plan — se sesjonsplanen (opprinnelig levert som replan-proposed.md; promotert 2026-07-10 på operatør-instruks, samtidig som roadmap + STATE.md ble oppdatert). Under selve reviewen ble ingen live-filer endret.

Metode: all kode lest (21 moduler, 3 754 linjer), alle nøkkel-tester lest, full lokal suite

  • ruff + mypy kjørt, OKF-spec hentet (WebFetch), og 5 detach-eksperimenter utført i en throwaway-kopi (scratchpad — live-repoet urørt). Hver påstand under har fil:linje eller kommando-belegg; verifiseringslogg nederst.

0. Baseline (verifisert, ikke sitert fra STATE)

Påstand Resultat Belegg
Testsuite 279 passed / 4 skipped (25.5s) — STATEs tall stemmer uv run pytest -q
Lint / typer ruff clean; mypy clean (21 filer) uv run ruff check .; uv run mypy src
Push-status HEAD 847ed90 == origin/main — STATEs push-påstand stemmer git rev-parse begge
Testomfang 244 test-funksjoner / 46 filer (283 collected = 279+4; orienteringens «~278/~54» var upresis) grep -c "def test"
De 4 skip env-gatede live-tester (Foundry/Ollama) — ingen ble trigget test_foundry_profile_live.py:19-22
STATEs 3 plan-avvik Alle tre bekreftet reelle og ærlig dokumentert; ingen skjuler en defekt progress.json steg 3/6-noter; run.py:517-537 (main uten ledger/goals)

Detach-bevis (load-bearing-stikkprøver, ALLE 11 RØDE i kopien): (1) Steg-1-fold detached → test_step1 rød; (2) checker-override detached → test_checker_gate rød; (3) link_in_index detached fra promote_verdict → test_step8 ×2 + test_simulation_loadbearing røde; (4) import agent_framework injisert i okf.py → test_okf_is_maf_free rød; (5) verdict-eksklusjon fjernet fra context_files → test_okf ×2 røde; (6) Steg-5 reason-injeksjon detached → test_step5 rød; (7) dimension admits-gate detached → test_dimension_loadbearing rød; (8) ledgerens dimensjonsfrie dedup detached → test_ledger rød (sum dobles); (9) fail-closed realize-gate detached → rød; (10) Steg-7 inbox-ingest detached → test_step7 rød; (11) portefølje-goal-stop detached → test_goal_stop_is_load_bearing rød. Detach 6–11 bekrefter uavhengig STATEs Fase-1-detach-påstander (som ellers kun sto i progress.json). Metoden holder på alle stikkprøvde sømmer. I tillegg: simuleringskonsollen (uv run python -m portfolio_optimiser.simulation) kjørt ende-til-ende i kopien — EXIT 0, sløyfe lukket, ærlig merking i output. Én nyanse: under detach 5 forble Steg-1s empty-store-kontroll grønn — verdict-BODYen bruker desimalkomma («0,82»), dot-formen bor kun i frontmatter (som ikke rendres i bundle_context), så dekningen for den detachen bæres av okf-nivå-testene, ikke run-nivå-kontrollen.


1. Funn (rangert, mest alvorlig først)

Ingen BLOCKER i dagens påstands-omfang (single-run-claims er sanne og detach-beviste). Funn 1–3 er MAJOR fordi de gjør neste fasers premisser falske eller farlige hvis de ikke fikses først.

F1 [MAJOR · Akse 1 + ærlighet] Læringssløyfa er DØD på portefølje-stien — docstring påstår den lever

  • Belegg: run_portfolio (run.py:429-514) har ingen bundle_dir/verdict_dir-parametre og kaller run_project uten dem (run.py:496-508). Steg-1-folden er gated på bundle_dir is not None (run.py:312). Dermed når ingen tidligere dom noensinne noen hypotese-prompt i en portefølje-kjøring. Docstringen påstår likevel «a verdict on project k informs the ExpeL retrieval of project k+1 (the cross-project learning loop)» (run.py:100-104, run.py:445-448). Det som faktisk skjer er kun post-generering-retrieved (run.py:367-377) — som koden selv innrømmer «is NOT what reaches the prompt». test_portfolio.py:131-151 asserter kun retrieved, aldri prompten — grønn-men-død på akkurat den sløyfa målbildets §5-diagnose handlet om.
  • Feilscenario: operatør kjører run_portfolio med seeded store og forventer (per docstring) at prosjekt 2 lærer av prosjekt 1s dom. Ingen prompt endres; alle hypoteser er uinformerte; rapporter bygget på «cross-project learning» er usanne (målbilde §1 kardinalregel).
  • Konsekvens for planen: Fase 3 (concurrent fan-out) skalerer i dag en portefølje-sti uten læring — premissfeil som blir BLOCKER hvis den ikke fikses FØR Fase 3.
  • Fiks: per-prosjekt bundle_dir + verdict_dir i konfig, tred gjennom run_portfolio; load-bearing test: dom på prosjekt k MÅ nå prosjekt k+1s prompt (ikke bare retrieved). → Re-plan sesjon S2.0.

F2 [MAJOR · Akse 1] Validator: CBC-nominalen gater aldri — selv-forfattede assumptions blåser P90 over «maximum feasible»

  • Belegg: eneste numeriske blokker er P90 + metode-cap (validator.py:133-152); nominal_feasible beregnes (validator.py:129) men brukes aldri som gate. assumptions forfattes av modellen selv (generate.py:71-78; ir.py:35 har ingen invariant om at bandet omslutter unit_cost). Kjørt bevis (i kopien): golden-bundelens egne tall — total 300 000, nominal 90 000, band [0.70, 1.40] — validerer claim 100 000 > 90 000 (p90=121 057). Med band helt over unit_cost ([1.8, 2.2]) validerer claim 55 000 mot nominal 30 000 (p90=65 058).
  • Feilscenario (live, Fase 4/6): proposer setter et optimistisk band → claim over den deterministiske feasibility-grensen stemples validated og når eksperten som «validator-godkjent». Modul-docstringens «a real CBC solve bounds the maximum feasible saving» (validator.py:7-8) er usann som gate-påstand; method-spec §3 Steg 4 pkt. 2 («capped at a policy fraction») håndheves ikke.
  • Fiks (golden-kompatibel — golden claim 30 000 ≤ 90 000 påvirkes ikke): (a) strukturell blokk også på claimed > nominal_feasible; (b) IR-invariant low ≤ unit_cost ≤ high per assumption-band (golden-bandet [0.70,1.40] omslutter 1.0 → OK). Krever spec-amendment i commons FØRST (method-spec §3/§7 er frossen; PULL-ONLY) + speiling i D7-søskenet (utenfor dette repoets scope, flagges). → Beslutnings-sesjon D-A, bygg-sesjon S2.7.

F3 [MAJOR · Akse 1/4] Ingen forankring av affected_items mot prosjektets faktiske kostbaseline

  • Belegg: _parse_ir aksepterer vilkårlige modell-forfattede kostlinjer (generate.py:71-78). Referanse-stien har project.cost_items (reference_domain.py:39-52) men avstemmer aldri; bundle-stien bygger Project med cost_items=() (run.py:168-195). Både IR-invarianten (claim ≤ items-total, ir.py:37-44) og hele validatoren regner på selv-deklarerte tall.
  • Feilscenario: proposer dikter {code:"XX", quantity:1e6, unit_cost:10} → total 10 MNOK → P90 3 MNOK → claim 2,9 MNOK stemples validated. Mot en ekte modell (Fase 4/6) er «validatoren avgjør tallene» tom mot hallusinerte kostlinjer; kun checker-LLM-en (fail-open) står imellom.
  • Fiks: ny fail-closed avstemmings-stage: hver affected_items.code MÅ finnes i prosjektets kostbaseline, quantity/unit_cost innenfor toleranse mot baseline. Bundle-stien trenger en kostbaseline-projeksjon (naturlig produsert av ingest-laget). Spec-amendment i commons. → D-A + sesjon S4.0 (må være grønn FØR første live-kjøring M2).

F4 [MAJOR · Akse 2 · UTFORDRING MOT FROSSEN RAMME] OKF-navigasjonen avviser spec-ens ANBEFALTE lenkeform

  • Belegg: navigate_bundle hopper over ethvert mål som inneholder / (okf.py:124-125) — og method-spec §3 Steg 1 pinner dette («Targets containing a path separator are out-of-bundle and MUST be skipped»). Men OKF-spec-en (hentet 2026-07-09) sier absolutt/bundle-relativ form («Begin with /, interpreted relative to the bundle root») er den anbefalte formen. Målbildet §4 beskriver selv cross-links som «bundle-relative /…».
  • Feilscenario: en bundle forfattet etter OKF-anbefalingen (](/tiltak.md)) navigerer til KUN index → bundle_citations tom → run_project raiser «no citable content» (run.py:278-279). Enhver ekstern OKF-bundle (f.eks. generert av Googles referanse-tooling) kan være ukonsumerbar.
  • Vurdering: dette er en feil i den frosne method-spec-en, ikke i okf.py (som implementerer spec-en trofast). Kun operatøren kan endre den. Anbefalt amendment: ledende / mappes til bundle-rot (fortsatt fail-closed boundary-sjekk; subkataloger kan fortsatt avvises om ønsket). → D-A. (Relatert MINOR: log.md er reservert i OKF-spec, men en index-lenke til den ville rendre den som konseptfil i bundle_context — okf.py:88-92 filtrerer kun index.md + verdict.)

F5 [MAJOR · Akse 2/3] ExpeL-substratet er én-kandidat-per-bundle — skalerer ikke til klynge C

  • Belegg: seed_store_from_bundle nøkler alle type: verdict-filer på bundelens ENE kandidat fra validator-input.json (verdicts.py:415-430; okf.py:26 — én projeksjon per bundle). To dommer om samme kandidat re-mintes til samme id; en dom om en ANNEN kandidat feil-nøkles til denne kandidatens features.
  • Feilscenario: et reelt prosjekt med ~10 dimensjoner × flere tiltak: promotert dom om tiltak B foldes inn i hypoteser om tiltak A (feil læringssignal), eller kolliderer på id og droppes. Roadmap C («all faglig kunnskap + alle tidligere dommer») forutsetter multi-kandidat.
  • Fiks: per-verdict features (les fra verdict-filas egen frontmatter/IR-referanse) + bundle- layout for flere kandidater. Spec-amendment (seeding-regelen §3 Steg 1 er normativ). → D-A + sesjon S3.2.

F6 [MAJOR · Akse 4] Concurrency-forutsetningene finnes ikke — og determinisme-kriteriet er selvmotsigende i dag

  • Belegg: link_in_index/index-RMW er ikke-atomisk (okf.py:183-190, dokumentert MVP-grense; også ingest.py:587-598); ledgeren er hel-fil skriv/les uten låsing (ledger.py:141-162); VerdictStore er in-memory first-wins (verdicts.py:225-236). Videre: Fase 3-kriteriet «concurrent == sekvensiell» kolliderer med dagens semantikk der én delt store tres gjennom kjøringene i rekkefølge — k+1 ser k (run.py:443-448); concurrent gjør ankomstrekkefølgen udeterministisk.
  • Feilscenario: to samtidige kjøringer promoterer mot samme bundle → tapt index-lenke (last-write-wins på RMW) → dommen blir unavigerbar og læringen stille borte.
  • Fiks: eksplisitt concurrency-modell FØR bygging (per-prosjekt-isolasjon under kjøring + deterministisk merge-barriere mellom bølger; én-skriver-regel eller fil-lås for index/ledger). → Beslutnings-sesjon D-D, bygg S3.4/S3.5.

F7 [MINOR nå → MAJOR ved Fase 2/6 · Akse 4] Verdict-inboxen er en uvalidert prompt-injeksjonsflate

  • Belegg: tolerant last validerer kun nøkkel-tilstedeværelse (verdicts.py:174-196); decision valideres ALDRI mot vokabularet (§4.2-kravet) — {"decision": "hva-som-helst"} entrer storen; rationale flyter verbatim inn i hypotese-prompten (verdicts.py:249-252 → run.py:312-315). Ingen størrelses-tak per fil.
  • Feilscenario: en fremmed/fiendtlig JSON i inbox-mappa («Ignore all previous instructions…» som rationale) injiseres i prompten på neste kjøring. Med flere brukere/eksperter (klynge E) er mappa en delt angrepsflate.
  • Fiks (fortsatt tolerant — skip, aldri raise): vokabular-sjekk på decision, tak på fil-/rationale-størrelse, antall-tak per merge. → sesjon S2.5.

F8 [MINOR · Akse 1] Metode-cap er fail-open på fri-tekst measure — asymmetrisk med dimension-gaten

  • Belegg: energiregelen keyer på eksakt streng energy_efficiency (validator.py:40-47,141-152) — modell-forfattet fri-tekst; «energy efficiency retrofit» omgår den strengere capen. dimension.admits er motsatt fail-closed allowlist (dimension.py:38-44) — i en dimensjon-scopet kjøring med allowed_measure_types={"energy_efficiency"} tvinges eksakt streng, så gapet gjelder primært u-scopede kjøringer.
  • Fiks: metode-regler bør keyes via dimensjons-/metode-registeret (konfig), ikke strenglikhet i validatoren. Kan tas sammen med S4.0.

F9 [MINOR · Akse 1] Prosent-mål: float-trunkering + subset-avhengig baseline + latent null-baseline

  • Belegg: int(goal.percent / 100 * baseline_ore) trunkerer med float-matte (run.py:423) — bryter Decimal/ROUND_HALF_UP-disiplinen (run.py:411-413, ledger.py:198-201). Baseline = sum av kun de prosjektene som er MED i passet (run.py:465) — samme mål-% gir ulik terskel avhengig av subsettet. Bundle-deriverte prosjekter har total_cost=0 (run.py:192 cost_items=()) → terskel 0 → øyeblikkelig stopp (latent; unåelig i dag siden run_portfolio kun tar referanse-prosjekter — blir reell ved S2.0).
  • Fiks: Decimal-konvertering; baseline-semantikk avklares i D-E (del av §4.3-resten); guard i S2.0.

F10 [MINOR · Akse 1 + ærlighet] BudgetMiddleware «short-circuits» først ETTER at kallet er fullført

  • Belegg: await call_next() kjøres før charge (budget.py:89-100) — kallet som krysser taket fullføres (og koster) før raise. For Fase 3-kostnadsstyring på tvers trengs pre-call-sjekk (nekter å starte kall når resttaket er brukt). Docstring-ordet «short-circuits the moment the cap is crossed» lover hakket mer enn mekanikken.
  • Fiks: pre-call guard i tillegg; tas i S3.5.

F11 [MINOR · Akse 1] Offline-bevisstrategien hviler på MAF-private API-er

  • Belegg: alle syntetiske klienter overrider _inner_get_response/_build_response_stream (simulation.py:86-114, conftest.py:59-80,118-141,175-181 — fire duplikater av mønsteret); suiten emitter allerede ExperimentalWarning fra agent_framework (skills/harness). En MAF-minor-oppgradering kan stille knekke HELE det offline ende-til-ende-beviset.
  • Fiks: pin agent-framework-core strammere (>=1.9,<2 e.l.) + én delt scripted-klient (redusér 4→1 implementasjoner) + en vakt-test som feiler ved MAF-versjonsskifte med beskjed om bevisst re-verifisering. Kan tas i S2.5 eller egen liten sesjon.

F12 [MINOR · ærlighet] CHANGELOG er utdatert etter Fase 1

  • Belegg: CHANGELOG.md:22 sier «237 passing tests» (nå 279); ingen Fase-1-oppføring (dimension/ledger/goals/metode-regel mangler). Versjonssync-regelen krever konsistens.
  • Fiks: oppdatér i S2.0 (samme sesjon som docstring-fiksen for F1).

F13 [SUGGESTION · Akse 1] Småting

  • _authored_texts: isinstance(out, str)-grenen er død kode — en str har ingen messages, så den filtreres bort på linja over (run.py:127-131).
  • _checker_verdict matcher VERDICT: REJECT hvor som helst i teksten (run.py:153); en checker som SITERER formatet («enten 'VERDICT: APPROVE' eller 'VERDICT: REJECT'») feiltolkes som reject (spec-en pinner reject-presedens, så dette er spec-konformt — men en siste-linje-parse ville vært robustere; evt. spec-nyansering i D-A).
  • retrieval._score bruker substring-match per token (retrieval.py:97) — «as» matcher «assets»; greit for MVP, erstattes uansett i S3.3.
  • Referanse-stiens retrieval-query er hardkodet «cost saving measure» (run.py:274).

F14 [MINOR · ærlighet] «Magentic er eksperimentell» er utdatert som begrunnelse (Python)

  • Belegg (delegert research, kildeført): orkestreringene (GroupChatBuilder/MagenticBuilder) leveres i agent-framework-orchestrations 1.0.0, «Production/Stable» (PyPI, 18. juni 2026); MAF-Python-doc-sidene bærer ingen experimental-banner (banneret gjelder Semantic Kernel og .NET). CLAUDE.md/målbildets «IKKE Magentic, som er eksperimentell» er dermed utdatert for Python.
  • Vurdering: Group Chat-VALGET står seg — Magentic-doc-en sier selv «untested … outside of the original Magentic-One design» og anbefaler Group Chat for enklere koordinering. Kun BEGRUNNELSEN bør omformuleres (operatør-beslutning; CLAUDE.md/målbildet er frosne).
  • Motverifisering utført: research-agentens andre utfordring — at middleware skal virke på bar BaseChatClient per docs — ble empirisk tilbakevist mot installert 1.9.0: agent-nivå ChatMiddleware på en bar BaseChatClient-subklasse fyrer ALDRI (calls=0, kjørt i kopien). Repoets «(verified)»-premiss (simulation.py:74-76, conftest.py:31-35) er korrekt; docs divergerer fra 1.9.0-implementasjonen — enda en grunn til versjonsvakten i F11.

2. Akse 3 — plan-fullstendighet (funn som endrer re-planen)

  • P1 [MAJOR]: Roadmap Fase 2 («live-kilde-herding», «inkrementell re-ingest») motsier det frosne ingest-målbildet: §8 «Inkrementell re-ingest er et extension point, ikke MVP», §11 «Ingen live-kilde forekommer noensinne i programmet», §12 «Ingen scheduler». Frossen-dokument- regimet krever en bevisst amendment før Fase 2 kan bygge dette. → D-B (operatør).
  • P2 [MINOR]: Roadmap B-overskriften «MCP wiret i kjørestien» motsier sin egen brødtekst («MCP som en ekte ingest-kilde») og CLAUDE.md-invarianten (FunctionTool er kjøresti-sømmen; method-spec §3 forbyr query-time retrieval). Re-planen løser det som MCP-ingest-konnektor (ny kildefamilie i manifestet), aldri kjøresti-wiring.
  • P3 — status på de seks §4-beslutningene: §4.1 dimensjonsmodell: avklart av Fase 1 (både kontekst-subsett OG kandidat-constraint; dobbelttelling løst av ledgerens dimensjonsfrie sum-nøkkel). §4.2 hovedbok-sannhet: i hovedsak avklart (typet store + fail-closed ekspert-gate realize); driftskonvensjon (hvor fila bor, hvem kjører realize) gjenstår. §4.3 mål-semantikk: delvis (absolutt+prosent+hard/soft bygget; prosent-BASELINE uavklart — F9). §4.4 første live-kilde: åpen (blokkert av P1). §4.5 vektor-store: åpen. §4.6 stack-paritet: åpen (operatør). → beslutnings-sesjoner D-B/D-C/D-E i re-planen.
  • P4 [MAJOR]: Output-laget (målbilde §3) er ikke bygget: ingenting persisterer forslag/ avvisninger/provenance til disk — run_project returnerer bare objekter; output-laget består i dag KUN av verdict-inboxen. Klynge E («sporing av utestående dommer») og sammenligningsprotokollens §4.2 («artefakter er fasit») forutsetter en outbox. → sesjon S2.1.
  • P5: run_portfolio mangler også verdict_dir — klynge E-ruting forutsetter den (dekkes av S2.0).
  • P6: Stubs/gap med sesjons-hjem: notify=-stub (run.py:229,382-383) → S5.2; build_mcp_server uwiret demo (datasource.py:79-92) → S2.2 gjenbruker kjernen; Azure-blokk = placeholders (data/model_map.json) → S4.1 + M1; main() kan ikke drive Fase-1-featurene (ingen dimension/ledger/goals/bundle-args, run.py:517-537) → S5.3.

3. Akse 4 — skala/drift/HITL (oppsummert; detaljer i re-planen)

  • Klynge C: concurrent==sekvensiell-kriteriet krever bølge-barriere-design (F6/D-D); kostnadstak finnes kun per kjøring (run.py:284-287) — på tvers-styring mangler (S3.5).
  • Klynge D: Azure-profilen er reell kode (FoundryChatClient, backends.py:68-78) men u-eksersert: placeholders i model_map, ingen preflight-validering av env/deployment før klient-bygging, ingen dokumentert auth-oppskrift. Offline-byggbart: preflight + env-kontrakt + artefakt-fangst (S4.1/S4.2); selve kjøringen er operatør-milepæl (M1/M2).
  • Klynge E: ruting/sporing forutsetter outbox (P4) + per-ekspert-konfig; varsling må følge ingen-stille-egress (opt-in-flagg, injiserbar transport — samme mønster som ingest.py:297-314).
  • Delvis feil midt i portefølje: en exception i prosjekt k (f.eks. BudgetExceeded i run_project) propagerer ut av run_portfolio (run.py:496-509 — ingen try) og KASTER hele passets resultater (runs 1..k-1 tapes). Akseptabelt for MVP, men må avklares før N×10 (S3.4).

4. Ambisiøse utvidelser (FORSLAG — utenfor godkjent A–E-scope, krever operatør-godkjenning)

  1. Lærings-dashboard (statisk HTML): generator over ledger + verdicts + runs — realisert vs modellert per prosjekt/dimensjon, mål-progresjon, ExpeL-treff. Ren offline-artefakt av eksisterende data. Kostnad: 1–2 sesjoner.
  2. Wiki-query-CLI: python -m portfolio_optimiser.ask "…"— naviger bundle + store og svar «hva vet wikien om kandidat X» (strukturert, ikke LLM). Gir ekspertene innsyn i læringsgrunnlaget. Kostnad: 1 sesjon.
  3. Verdict-provenance-graf: eksportér kjeden dom → promotering → fold → forslag som mermaid/DOT fra provenance-stemplene — «hvorfor foreslo systemet dette»-sporbarhet. Kostnad: 1 sesjon.
  4. Konsept-kvalitetsscore: per bundle-fil: staleness (timestamp), lenketetthet, siterings-dekning fra kjøringer — flagger råtnende wiki-innhold for kurator. Kostnad: 1–2 sesjoner.
  5. Kjørings-diff: sammenlign to output-lag-artefakter (prompter/utfall/percentiler) — regresjonsverktøy på metodenivå når spec/valider endres. Kostnad: 1 sesjon.

5. Utfordringer mot frosne beslutninger (KLART MERKET — kun operatøren kan endre)

# Frossen ramme Utfordring Belegg
U-1 method-spec §3 Steg 1 («path separator MUST be skipped») Avviser OKF-spec-ens anbefalte /-lenkeform → eksterne bundles ukonsumerbare (F4) okf.py:124-125; OKF-spec (WebFetch 2026-07-09)
U-2 method-spec §3 Steg 4 / §7.2 (validator-semantikk frossen) Stage-2-«cap» håndheves ikke; selv-forfattede bands omgår den (F2); kostbaseline-forankring mangler (F3) Kjørte moteksempler, validator.py:125-153
U-3 Ingest-målbilde §8/§11/§12 (frossen) Roadmap Fase 2 planlegger eksplisitt det målbildet forbyr (P1) — én av dem må vike, bevisst Begge dokumenter sitert over
U-4 method-spec §3 Steg 1 seeding-regel Én-kandidat-nøkling skalerer ikke til klynge C (F5) verdicts.py:415-430

Ingen utfordring rettes mot: deterministisk validator som obligatorisk/blokkerende (bekreftet riktig og reelt blokkerende på sitt input-domene), maker-checker-gaten (reelt gatende, detach-bevist), fail-closed promotering/realisering (detach-bevist), load-bearing-regelen (den fanget reelt), eller 90 %-prinsippet.

6. Verifiseringslogg

Påstand Kilde/kommando
279 passed / 4 skipped uv run pytest -q (25.5s, 2026-07-09)
ruff clean / mypy clean uv run ruff check .; uv run mypy src (21 filer)
HEAD pushet git rev-parse HEAD == git rev-parse origin/main == 847ed901
11 detach-eksperimenter røde scratchpad-kopi: kirurgisk detach + uv run pytest <fil> per søm (se §0)
Simuleringskonsollen virker uv run python -m portfolio_optimiser.simulation i kopien → EXIT 0, «LEARNING LOOP CLOSED»
S2.7-antakelsen (bands omslutter unit_cost i alle fixtures) skann av alle JSON-fixtures + inline-band-grep → NULL brudd (eneste inline-treff laster den sjekkede JSON-en)
Re-planens avhengighetsgraf er gyldig mermaid validert + rendret via Mermaid-verktøyet (kun sesjonsnavn sendt)
OKF-krav (type/reserverte/lenker/toleranse) WebFetch raw.githubusercontent.com/GoogleCloudPlatform/knowledge-catalog/main/okf/SPEC.md
F2-moteksempler validerer uv run python i kopien: claim 100k>nominal 90k → ValidatedProposal p90=121057; claim 55k>nominal 30k → ValidatedProposal p90=65058
F1: fold gated på bundle_dir; run_portfolio uten bundle_dir run.py:312, run.py:429-514 (lest)
P1-konflikten docs/plan/2026-07-06-reell-kjoring-analyse-plan.md:50-57 vs docs/plan/2026-07-03-maalbilde-ingest-lag.md:161-166,199-204,207-215
CHANGELOG stale CHANGELOG.md:22 («237 passing tests»)
Live-tester ikke trigget 4 skips = env-gatede (test_foundry_profile_live.py:19, test_local_profile_live.py, test_portfolio_live.py); ingen endpoints satt
STATEs 3 avvik progress.json steg-noter + run.py:517-537 + ledger.py:165-192
Magentic GA i Python Delegert research: PyPI agent-framework-orchestrations 1.0.0 «Production/Stable»; MS Learn orchestration-sider uten experimental-banner
Middleware fyrer IKKE på bar BaseChatClient (1.9.0) Empirisk: minimal BaseChatClient-subklasse + Agent(middleware=[mw]) → calls=0 (kjørt i kopien)
Vektor-store-fakta (numpy/sqlite-vec/faiss/LanceDB-wheels) Delegert research m/ PyPI-files-kilder; brukes i D-C (replan); ikke-kryssjekkede punkter der er merket «Ikke verifisert»
Foundry-config (FoundryChatClient: project_endpoint+model+credential; Entra) Delegert research mot MS Learn provider-sider; brukes i S4.1