portfolio-optimiser/src/portfolio_optimiser/data/bundles/multi-kandidat-mikro/index.md
Kjell Tore Guttormsen 012adc0a3c feat(verdicts): key each verdict on its own candidate, not the bundle's one IR projection (S3.2)
seed_store_from_bundle keyed EVERY `type: verdict` file on bundle_candidate_features — the single
candidate the bundle's validator-input.json describes. A bundle carrying verdicts about several
candidates collapsed them onto one key, so a verdict about candidate B scored a perfect structural
match against candidate A's query and could be folded into A's hypothesis prompt. The ExpeL
substrate was single-candidate by construction.

A verdict file may now carry its own structural key in frontmatter (affected_codes / measure_type /
claimed_saving_nok); absent, keying falls back to the bundle candidate, so every pre-S3.2 seed keeps
working unchanged. promote_verdict writes the three fields, so a promoted verdict — frequently about
a different candidate than the target bundle's projection — does not impersonate that candidate.

Semantics decided HERE, not pulled: commons' seeding rule (method-spec §3 Steg 1 + bundle example)
has not arrived; we said we would build locally first. D7 mirroring stays open.

- ALL THREE fields or none. A partial declaration raises VerdictFrontmatterError rather than merging
  with the bundle candidate, which would mint a key belonging to NEITHER candidate. Validation,
  never repair (mirrors write_concept_file); the tolerant-skip rule belongs to the RAW inbox layer.
- claimed_saving_nok parses via json.loads — the SAME literal rule the IR projection went through —
  and is written back with str() of the raw value. _mint_id hashes that value, so 30000 and 30000.0
  are different keys; a normalising writer would split one candidate's signal across two ids.
- The structural key is signal-free, so it does not weaken the Step-8 no-leak property (Test C green).

Load-bearing MEASURED, five mutations all red: detach per-verdict keying · detach the fields
promote_verdict writes · make a partial/unparseable key tolerant · normalise the magnitude on write ·
remove the fallback (control — breaks the step1 suite at collection, proving the fallback bears load).

589 -> 597 tests. Full gate green (pytest, ruff, mypy).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkjvTTxrg9LTrmghebfiij
2026-08-03 16:44:58 +02:00

1.9 KiB

type okf_version title description tags timestamp
index 0.1 Multi-kandidat mikro — repo-lokal fixture (S3.2 per-dom-noekling) Minimal repo-lokal OKF-bundle under data/ med dommer om TO ULIKE kandidater, mens IR-projeksjonen beskriver kandidat A alene. Fixturen gjoer forskjellen mellom per-dom-noekling og bundle-noekling maalbar.
fixture
S3.2
multi-kandidat
2026-08-03

Multi-kandidat mikro (repo-lokal test-fixture)

En repo-lokal mini OKF-bundle under pakkens data/ (ALDRI shared/ — subtree er PULL-ONLY). Den finnes for ett formaal: bundelen bærer dommer om to ulike kandidater, mens validator-input.json (ExpeL-query-noekkelen) beskriver kandidat A alene.

Foer S3.2 noeklet seed_store_from_bundle HVER dom paa bundelens ene IR-projeksjon, saa dommen om kandidat B ble uskillelig fra dommen om kandidat A og kunne naa kandidat As hypotese-prompt. Med per-dom-noekling leser hver dom sine EGNE strukturelle felt fra frontmatter.

Rekkefoelgen under er bevisst: kandidat B er lenket foerst, saa en detachet per-dom-noekling (begge dommer faar kandidat As noekkel → uavgjort likhet, uavgjort id) rangerer B-dommen oeverst.

Innhold (progressiv disclosure)

  • verdict-b-asfalt.mdtype: verdict — dom om kandidat B (asfalttykkelse, kode 05.2). Bærer sine egne affected_codes/measure_type/ claimed_saving_nok. Skal ALDRI naa kandidat As hypotese-prompt.
  • verdict-a-led.mdtype: verdict — dom om kandidat A (LED-retrofit, kode ENERGI-TOTAL-EL). Dette er dommen kandidat As query skal hente.
  • prosjekt-multi.mdtype: project — bygget/strekningen begge kandidatene hoerer til. Concept-filen OKF-navigasjonen leser inn som lese-kontekst.

validator-input.json er IR-projeksjonen den deterministiske validatoren konsumerer, og kilden for ExpeL-query-noekkelen (bundle_candidate_features) — kandidat A.