portfolio-optimiser/tests
Kjell Tore Guttormsen 8e9f385d17 test(spec): make the pulled method spec load-bearing at rule level, not just section level
The spec arrives by subtree pull from commons, so drift is something we RECEIVE
rather than author. The existing guard only asserted the section HEADINGS were
present: a pull could empty a section of its normative content and stay green.
Measured, not assumed — with `escape, not depth` deleted from Step 1, the old
skeleton test still passes (M5 below).

Two new guards, one file:

- Rule level (test 6): 25 normative rules, each bound to the section that OWNS
  it, so a phrase surviving elsewhere in the document does not count as the spec
  still stating the rule. Selection is principled rather than taste — every entry
  anchors a §11 conformance seam or a CLAUDE.md invariant. Matching is
  whitespace- and emphasis-insensitive: re-wrapping a paragraph upstream is an
  editorial change, not a rule change, and must not cost a false red.
- §11 table (test 7): the conformance table still names the seams this suite
  implements, and every test it cites exists here. One-directional by design —
  the repo carries 26 load-bearing tests, the spec anchors 10, because the spec
  governs the METHOD, not this repo.

Five measurements, all as expected: M1 delete a rule → RED · M2 RELOCATE a rule
out of its section while leaving it in the document → RED (this is what the
section binding buys) · M3 drop a seam row from §11 → RED · M4 harmless re-wrap
+ de-bolding → GREEN · M5 the old skeleton test does NOT catch M1 → GREEN.
Spec restored from a byte copy after each mutation, shasum verified.

Known gap, deliberately not patched here: §11 has no row for the portfolio-wide
budget seam (S3.4/F10) — the pulled spec predates it. That is a commons
amendment; a consumer editing shared/ is exactly the drift this guards against.

553 → 555 tests, ruff + mypy green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Aw9TECznT5b5H6374CBTvV
2026-08-01 19:57:33 +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_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_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 docs(s33): document the wave snapshot's deliberate intra-wave semantics, pinned by test 2026-07-31 17:40:05 +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 feat(s33): wave executor with per-project snapshot and deterministic merge barrier 2026-07-31 15:56:13 +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(fase6): gate-promote approved verdicts back into the OKF wiki (Steg 8) 2026-06-30 11:06:28 +02:00
test_validator.py feat(fase2): promote blocking validator + IR to src 2026-06-24 13:24:03 +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