portfolio-optimiser/tests
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
..
spikes fix(fase3): relax hardcoded project-count assert in spike test (SC1 4th-project follow-up) 2026-06-26 12:14:34 +02:00
conftest.py refactor(fase2a): konsolider fire skriptede klienter til én kanonisk (S2.5) 2026-07-15 07:37:43 +02:00
test_assessment_method_loadbearing.py feat(fase1): assessment-method encoding — persisted dimension-scoped example + validator rule (F1) 2026-07-07 08:15:44 +02:00
test_backends.py fix(s41): pass required credential in AzureFoundryBackend.create_chat_client 2026-07-15 11:18:40 +02:00
test_budget.py feat(budget): enforce a global portfolio token cap before the call, not after it (S3.4/F10) 2026-07-31 21:34:48 +02:00
test_bygg_energi_mikro.py docs(shared): bygg-energi mikro-eksempel — OKF-bundle + golden + load-bearing test 2026-06-29 09:42:13 +02:00
test_checker_gate_loadbearing.py feat(fase3): make the maker-checker checker actually gate the reasoning 2026-06-30 07:24:30 +02:00
test_contracts.py feat(fase1): GoalContract + GoalConfig standalone fail-fast loader (F1) 2026-07-07 08:01:53 +02:00
test_costsim.py test(s36): value-level guard for _ore_to_kr_str money formatter 2026-07-15 10:25:05 +02:00
test_costsim_loadbearing.py feat(s36): costsim CLI + no-network + no-hardcoded-price guards 2026-07-15 10:05:29 +02:00
test_datasource.py feat(fase2): expose retriever as citation-bearing data source 2026-06-24 13:34:53 +02:00
test_dimension.py feat(s53): load_dimension fail-fast loader (MAF-free, mirrors load_goal_config) 2026-07-23 21:31:32 +02:00
test_dimension_loadbearing.py feat(fase1): dimension in run_project — context scope + candidate constraint (F1) 2026-07-07 07:50:26 +02:00
test_foundry_profile_live.py test(fase2): gated live local + Foundry profile checks 2026-06-24 14:02:44 +02:00
test_generate.py feat(fase2): LLM->IR generation with validator-as-retry 2026-06-24 13:48:54 +02:00
test_hitl.py fix(s51): close 2 review MINORs — non-UTF-8 skip + affected_codes parity 2026-07-15 20:59:01 +02:00
test_hitl_loadbearing.py fix(s51): close 2 review MINORs — non-UTF-8 skip + affected_codes parity 2026-07-15 20:59:01 +02:00
test_imports_core.py feat(fase1): export domain-model public API + green full suite (F1) 2026-07-07 08:17:10 +02:00
test_ingest_golden.py test(ingest): golden extraction case examples/ingest-golden-file, byte-frozen (I2) 2026-07-03 18:40:53 +02:00
test_ingest_golden_http.py test(ingest): http golden extraction, byte-deterministic (I6) 2026-07-04 17:12:34 +02:00
test_ingest_golden_sql.py test(ingest): SQL connector + load-bearing + golden, detach-proven (I4) 2026-07-04 06:56:02 +02:00
test_ingest_http.py feat(ingest): http read_http connector + injectable transport seam (I6) 2026-07-04 16:57:29 +02:00
test_ingest_http_loadbearing.py feat(ingest): gate http behind allow_network run-flag + dispatch (I6) 2026-07-04 17:04:05 +02:00
test_ingest_http_timeout_loadbearing.py feat(ingest): bound the default http transport in time, in front of the pinned library (S2.4) 2026-08-03 14:54:04 +02:00
test_ingest_library_seam.py refactor(ingest): adopt shared llm-ingestion-okf v0.3.1 behind a thin adapter 2026-07-20 07:47:55 +02:00
test_ingest_loadbearing.py refactor(ingest): adopt shared llm-ingestion-okf v0.3.1 behind a thin adapter 2026-07-20 07:47:55 +02:00
test_ingest_manifest.py refactor(ingest): adopt shared llm-ingestion-okf v0.3.1 behind a thin adapter 2026-07-20 07:47:55 +02:00
test_ingest_materialize.py refactor(ingest): adopt shared llm-ingestion-okf v0.3.1 behind a thin adapter 2026-07-20 07:47:55 +02:00
test_ingest_mcp.py feat(ingest): add the MCP connector as a transport inside the http family (S2.2) 2026-08-02 21:14:57 +02:00
test_ingest_mcp_loadbearing.py feat(ingest): add the MCP connector as a transport inside the http family (S2.2) 2026-08-02 21:14:57 +02:00
test_ingest_sql.py test(ingest): SQL connector + load-bearing + golden, detach-proven (I4) 2026-07-04 06:56:02 +02:00
test_ingest_sql_loadbearing.py test(ingest): SQL connector + load-bearing + golden, detach-proven (I4) 2026-07-04 06:56:02 +02:00
test_ledger.py fix(s54): reject non-array/non-object ledger JSON in SavingsLedger.load 2026-07-24 19:52:52 +02:00
test_ledger_loadbearing.py feat(fase1): hard/soft goal-stop in run_portfolio on accumulated ledger (F1) 2026-07-07 08:11:43 +02:00
test_live_dry_run.py fix(s42): close review WARN — hermetic dry-run env + scoped azure hint 2026-07-15 18:30:30 +02:00
test_live_dry_run_loadbearing.py feat(s42): live_dry_run cut in run_project + DryRunReport 2026-07-15 18:05:16 +02:00
test_local_profile_live.py test(fase2): gated live local + Foundry profile checks 2026-06-24 14:02:44 +02:00
test_maf_version_guard.py feat(fase2a): MAF version-guard (test-tidsvakt, dist-metadata) + pin agent-framework-core<2 (S2.5) 2026-07-15 07:28:40 +02:00
test_method_spec_loadbearing.py test(spec): make the pulled method spec load-bearing at rule level, not just section level 2026-08-01 19:57:33 +02:00
test_notify.py test(s52): cover build_notifier console/file dispatch + file-without-path fail-fast 2026-07-17 03:16:25 +02:00
test_notify_loadbearing.py fix(s52): resolve ConsoleNotifier default stream at call time 2026-07-17 03:18:00 +02:00
test_okf.py feat(okf): conform the context seam to the pulled navigation + stamp-integrity contracts 2026-07-31 21:07:29 +02:00
test_outbox_loadbearing.py feat(s42): byte-deterministic write_run_config outbox writer 2026-07-15 12:39:42 +02:00
test_persona_skill_loadbearing.py feat(persona): build the shared expert-reviewer persona as a framework-neutral Agent Skill 2026-06-30 13:59:42 +02:00
test_portfolio.py feat(s41): PORTFOLIO_MODEL_MAP override + placeholder fail-fast in resolve_model 2026-07-15 11:17:06 +02:00
test_portfolio_budget_loadbearing.py feat(budget): enforce a global portfolio token cap before the call, not after it (S3.4/F10) 2026-07-31 21:34:48 +02:00
test_portfolio_concurrent_loadbearing.py test(portfolio): gate the wave handler's catch width and the failed-project ledger (v/t/s) 2026-08-03 16:09:12 +02:00
test_portfolio_failure_accounting_loadbearing.py test(portfolio): gate the wave handler's catch width and the failed-project ledger (v/t/s) 2026-08-03 16:09:12 +02:00
test_portfolio_learning_loadbearing.py feat(fase2a): percent-mål mot baseline 0 reiser ValueError (S2.0) 2026-07-15 07:14:29 +02:00
test_portfolio_live.py test(fase3): SC7 both profiles offline + gated Azure portfolio arm 2026-06-26 12:10:04 +02:00
test_preflight.py fix(s41): close review WARN — OSError refusal + scheme/profile branch coverage 2026-07-15 11:58:10 +02:00
test_preflight_loadbearing.py style(s41): ruff format preflight test files 2026-07-15 11:25:26 +02:00
test_provenance.py feat(fase2): first-class Pydantic provenance stamp 2026-06-24 13:26:55 +02:00
test_reference_domain.py test(fase2a): commit Step 2 optional bundle_dir/verdict_dir tests (S2.0, omitted from 9659045) 2026-07-15 07:29:19 +02:00
test_retrieval.py fix(retrieval): fail-closed on uncanonicalisable paths (embedded null byte) 2026-07-21 08:00:11 +02:00
test_run_cli.py fix(s31): close 1 review BLOCKER — EmbedderConfig registry + --embedder-config, never an import path 2026-07-25 12:50:19 +02:00
test_run_cli_loadbearing.py test(s31): close 1 review MAJOR — main()-level load-bearing proof of the --semantic-retrieval wiring 2026-07-25 12:44:03 +02:00
test_run_smoke.py feat(fase2): vertical-slice orchestrator + two-layer HITL wiring 2026-06-24 13:54:54 +02:00
test_scripted_client_consolidation.py test(portfolio): gate the wave handler's catch width and the failed-project ledger (v/t/s) 2026-08-03 16:09:12 +02:00
test_semretrieval.py fix(s31): close 1 review BLOCKER — EmbedderConfig registry + --embedder-config, never an import path 2026-07-25 12:50:19 +02:00
test_semretrieval_loadbearing.py test(s31): pin the structural-order-preservation contract — RED at the shipped weight 2026-07-25 20:01:32 +02:00
test_shared_root_loadbearing.py feat(shared-root): S3 — configurable shared-root resolver with load-bearing override test 2026-07-03 01:10:05 +02:00
test_simulation_loadbearing.py feat(sim): offline end-to-end simulation proving the learning loop closes 2026-06-30 12:55:15 +02:00
test_smoke.py feat: initial scaffold (Python framework on Microsoft Agent Framework) 2026-06-23 22:01:22 +02:00
test_step1_expel_loadbearing.py feat(fase2b): OKF-navigated bundle context replaces chunk-stuffing 2026-06-30 06:42:19 +02:00
test_step5_refine_loadbearing.py feat(fase4): route the validator falsification into the next hypothesis (informed refinement) 2026-06-30 09:08:02 +02:00
test_step7_async_loop_loadbearing.py feat(fase5): add the long/async verdict file inbox (Steg 7 resumable feedback) 2026-06-30 09:54:23 +02:00
test_step8_promotion_loadbearing.py feat(verdicts): key each verdict on its own candidate, not the bundle's one IR projection (S3.2) 2026-08-03 16:44:58 +02:00
test_step32_multicandidate_loadbearing.py feat(verdicts): key each verdict on its own candidate, not the bundle's one IR projection (S3.2) 2026-08-03 16:44:58 +02:00
test_validator.py feat(validator): enforce the deterministic stage-2 bound and band enclosure (S2.7) 2026-08-03 16:22:54 +02:00
test_value_report.py feat(s54): value_report text + deterministic JSON formatters 2026-07-24 01:29:31 +02:00
test_value_report_loadbearing.py test(s54): value_report overlap-flag load-bearing seam 2026-07-24 01:30:55 +02:00
test_verdicts.py fix(s51): close 2 review MINORs — non-UTF-8 skip + affected_codes parity 2026-07-15 20:59:01 +02:00
test_vertical_slice_e2e.py fix(fase3): stamp real proposer model into provenance, kill fake-model leak (F1) 2026-06-26 15:03:45 +02:00
test_workflow.py feat(fase2): thread tools + budget middleware through fresh_workflow onto agents 2026-06-26 00:36:06 +02:00