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>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-23 15:04:21 +02:00
commit 37547fe292
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
1147 changed files with 24138 additions and 9503 deletions

View file

@ -11,7 +11,7 @@ exactly — nothing wider is needed, and nothing narrower suffices.
**The plan said "sort each wave's new verdicts on ``project_id``"; that was measured wrong and the
correction is load-bearing, so it is recorded here rather than only in git.** Lexicographic order
is BRU/FV42/RV13 while the sequential pass yields FV42/RV13/BRU — a ``project_id`` sort is
is ARKIV/KONTOR/NETT while the sequential pass yields KONTOR/NETT/ARKIV — a ``project_id`` sort is
deterministic yet NOT identical to ``concurrency=1``, and the second is the actual contract. The
plan also named that sort as the detach point; it is not. With per-project snapshots the wave list
is never reordered by completion, so a ``sorted(...)`` in the barrier would re-sort an already
@ -60,7 +60,7 @@ from portfolio_optimiser.verdicts import VerdictStore
# The shipped 3-project fixture, in submission order (mirrors tests/test_portfolio.py:57).
# ``REPLIES`` is reused from there deliberately: its three proposals are already verified to
# validate AND to mint three DISTINCT verdict ids, which is the precondition self-check 3 asserts.
_PORTFOLIO_IDS = ["FV42-GSV-E1", "RV13-RAS-TP", "BRU-LAKS-REHAB"]
_PORTFOLIO_IDS = ["KONTOR-IT-E1", "NETT-SIKR-TP", "ARKIV-LAGR-MIGR"]
# Scheduler yields per project, DESCENDING by submission index: the FIRST-submitted project yields
# most and therefore tends to finish LAST. This is what makes completion order depart from
@ -378,7 +378,7 @@ async def test_runs_follow_project_ids_not_completion_order() -> None:
"completion order matched submission order, so this assertion would hold trivially"
)
# ``claimed_saving_nok`` is the per-project discriminator in REPLIES (200k / 130k / 210k) —
# ``measure_type`` is NOT, since FV42 and BRU deliberately share "Reduce scope".
# ``measure_type`` is NOT, since KONTOR and ARKIV deliberately share "Reduce scope".
assert [r.verdict.proposal_features.claimed_saving_nok for r in result.runs] == [
200_000.0,
130_000.0,
@ -397,7 +397,7 @@ async def test_runs_follow_project_ids_not_completion_order() -> None:
# The MIDDLE project of the wave. Middle is deliberate: a failure at either end can be dropped by
# a truncation bug and still leave the survivors in the right relative order, so an end position
# would let the ordering assertion below pass for the wrong reason.
_FAILING_PID = "RV13-RAS-TP"
_FAILING_PID = "NETT-SIKR-TP"
class _FailingProbeClient(_OrderProbeClient):
@ -511,9 +511,9 @@ async def test_one_project_failure_does_not_cancel_its_siblings() -> None:
assert failure.error_type == "RuntimeError"
assert "synthetic backend failure" in failure.error
# The survivors are the two healthy projects, in SUBMISSION order — 200k is FV42 (submitted
# first), 210k is BRU (submitted last). ``measure_type`` is not a discriminator here: FV42 and
# BRU deliberately share "Reduce scope".
# The survivors are the two healthy projects, in SUBMISSION order — 200k is KONTOR (submitted
# first), 210k is ARKIV (submitted last). ``measure_type`` is not a discriminator here: KONTOR and
# ARKIV deliberately share "Reduce scope".
assert [r.verdict.proposal_features.claimed_saving_nok for r in result.runs] == [
200_000.0,
210_000.0,
@ -638,20 +638,20 @@ async def test_goal_stop_membership_is_identical_across_concurrency() -> None:
empty ``runs`` and the equality is nearly free. It is asserted anyway because a regression that
let a hard stop leak one wave's worth of runs would show up here first."""
# Strong half — a per-project HARD goal skips exactly that pid, at every k.
per_project = GoalConfig(per_project={"RV13-RAS-TP": GoalContract(absolute_ore=1000)})
per_project = GoalConfig(per_project={"NETT-SIKR-TP": GoalContract(absolute_ore=1000)})
probe = _Recorder()
concurrent = await _goal_pass(
3, ledger=_prefilled("RV13-RAS-TP", 1000), goals=per_project, recorder=probe
3, ledger=_prefilled("NETT-SIKR-TP", 1000), goals=per_project, recorder=probe
)
sequential = await _goal_pass(
1, ledger=_prefilled("RV13-RAS-TP", 1000), goals=per_project, recorder=_Recorder()
1, ledger=_prefilled("NETT-SIKR-TP", 1000), goals=per_project, recorder=_Recorder()
)
assert probe.max_in_flight > 1, (
f"max in-flight was {probe.max_in_flight}: the surviving two projects never overlapped, so "
"membership under concurrency is untested here"
)
assert _ran(concurrent) == _ran(sequential) == ["FV42-GSV-E1", "BRU-LAKS-REHAB"], (
assert _ran(concurrent) == _ran(sequential) == ["KONTOR-IT-E1", "ARKIV-LAGR-MIGR"], (
f"membership diverged with k: k=3 ran {_ran(concurrent)}, k=1 ran {_ran(sequential)}"
)
assert concurrent.stopped_early is False and sequential.stopped_early is False, (
@ -661,10 +661,10 @@ async def test_goal_stop_membership_is_identical_across_concurrency() -> None:
# Weak half — a HARD portfolio goal already reached stops the pass identically at every k.
portfolio = GoalConfig(portfolio=GoalContract(absolute_ore=100))
stopped_concurrent = await _goal_pass(
3, ledger=_prefilled("FV42-GSV-E1", 100), goals=portfolio, recorder=_Recorder()
3, ledger=_prefilled("KONTOR-IT-E1", 100), goals=portfolio, recorder=_Recorder()
)
stopped_sequential = await _goal_pass(
1, ledger=_prefilled("FV42-GSV-E1", 100), goals=portfolio, recorder=_Recorder()
1, ledger=_prefilled("KONTOR-IT-E1", 100), goals=portfolio, recorder=_Recorder()
)
assert _ran(stopped_concurrent) == _ran(stopped_sequential) == []
assert stopped_concurrent.stopped_early is stopped_sequential.stopped_early is True
@ -773,7 +773,7 @@ async def test_intra_wave_visibility_is_the_documented_semantic_difference(
**Why the shipped fixture cannot show it, and why this test needs its own.** The Step-1 ExpeL
fold is ``bundle_dir``-gated, and no project in ``reference_projects.json`` sets ``bundle_dir``,
so on that fixture the cross-project chain is live for store CONTENT but inert for OUTCOMES —
the difference exists and is unobservable. The road-*k* + bundle-*(k+1)* pair from
the difference exists and is unobservable. The ref-*k* + bundle-*(k+1)* pair from
``test_portfolio_learning_loadbearing.py`` is the fixture where the fold actually fires, injected
through the SAME ``load_reference_projects`` monkeypatch seam that file uses (``:163``). No
``projects=`` parameter is added to production code for this: that would be a new public seam