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>
223 lines
11 KiB
Python
223 lines
11 KiB
Python
"""P3 (GO) — the demo runs the DELIVERED bundle, and its numbers come FROM that bundle.
|
|
|
|
P4 pkt. 0 anchored the demo against a repo-local reserve whose ``cost-baseline.json`` was DERIVED in
|
|
code from the scripted register (``baseline_from_scripted_candidate``): the reserve's numbers are
|
|
synthetic, so the script was the only ground truth there was. On GO day the direction **reverses** —
|
|
the delivered bundle (today the packaged, fictional ``data/bundles/klientpark-energi/``) ships its
|
|
own ``cost-baseline.json``, so the register is written FROM that file and the derivation helper is
|
|
not used on this path.
|
|
|
|
That reversal is what these tests guard. The risk it models is drift: two copies of the same numbers
|
|
— one in the delivered file, one in our register — that stop agreeing without anyone noticing.
|
|
A drifted register does not crash; it makes the deterministic gate reject the demo's own hypothesis
|
|
at stage 0 instead of at the P90 stage, which on screen is the SAME ``REJECTED`` line telling a
|
|
different story. So the agreement is asserted directly (below), and the 10 % test proves the gate
|
|
would actually catch a disagreement.
|
|
|
|
The 10 % test is repeated here against delivered content on purpose. Its twin in
|
|
``test_anchored_reserve_loadbearing`` proves the MECHANISM; this one measures the CONTENT — the
|
|
mechanism could be perfect while the delivered file and the register disagree.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from portfolio_optimiser import okf
|
|
from portfolio_optimiser.ir import CostBaseline, CostBaselineLine
|
|
from portfolio_optimiser.simulation import (
|
|
_CANDIDATES,
|
|
_INBOX_MARKER,
|
|
_KLIENTPARK_PROJECT_ID,
|
|
ScriptedCandidate,
|
|
_delivered_bundle_dir,
|
|
materialize_anchored_bundle,
|
|
simulate_learning_loop,
|
|
)
|
|
from portfolio_optimiser.persona import load_persona_example
|
|
from portfolio_optimiser.validator import Rejection, ValidatedProposal
|
|
|
|
|
|
def _klientpark() -> ScriptedCandidate:
|
|
"""The registry entry for the delivered project — selected by id, never by index (the registry
|
|
is a set of DATA entries whose order carries no meaning)."""
|
|
(candidate,) = [c for c in _CANDIDATES if c.project_id == _KLIENTPARK_PROJECT_ID]
|
|
return candidate
|
|
|
|
|
|
def _delivered_baseline() -> CostBaseline:
|
|
baseline = okf.load_optional_cost_baseline(str(_delivered_bundle_dir()))
|
|
assert baseline is not None, "the delivered bundle no longer ships a cost-baseline.json"
|
|
return baseline
|
|
|
|
|
|
def test_the_delivered_bundle_ships_its_own_baseline() -> None:
|
|
"""The delivered bundle is anchored WITHOUT ``materialize_anchored_bundle`` — which is exactly
|
|
what let GO day be a call-site change rather than a new seam. RED if the bundle ever drops the
|
|
file: the demo would then run un-anchored while every other line stayed byte-identical."""
|
|
baseline = _delivered_baseline()
|
|
|
|
assert baseline.project_id == _KLIENTPARK_PROJECT_ID
|
|
assert set(baseline.items) == {"ENERGI-KLIENTPARK-EL"}
|
|
|
|
|
|
def test_the_register_states_the_delivered_numbers_verbatim() -> None:
|
|
"""LOAD-BEARING on the DIRECTION of derivation (plan P3 b): the register's cost lines are
|
|
written FROM the delivered ``cost-baseline.json``, so they must equal it exactly — in BOTH
|
|
scripted replies.
|
|
|
|
RED when the two drift: if the bundle re-states the baseline (or someone re-types it here), the
|
|
demo's own hypothesis starts being felled by stage 0's reconciliation instead of by the P90
|
|
stage it narrates. Same ``REJECTED`` line on screen, different mechanism behind it.
|
|
|
|
Both replies are checked, not just the corrected one: the overclaimed hypothesis must differ
|
|
from it in the CLAIM alone, never in the cost lines."""
|
|
candidate = _klientpark()
|
|
delivered = _delivered_baseline().items
|
|
|
|
for reply in (candidate.overclaimed, candidate.corrected):
|
|
items = json.loads(reply)["affected_items"]
|
|
assert {i["code"] for i in items} == set(delivered), (
|
|
"the scripted reply names cost codes the delivered baseline does not declare"
|
|
)
|
|
for item in items:
|
|
line = delivered[item["code"]]
|
|
assert (item["quantity"], item["unit_cost"]) == (line.quantity, line.unit_cost), (
|
|
f"register and delivered cost-baseline.json disagree on {item['code']}: "
|
|
f"script says {(item['quantity'], item['unit_cost'])}, "
|
|
f"delivered says {(line.quantity, line.unit_cost)}"
|
|
)
|
|
|
|
overclaimed = json.loads(candidate.overclaimed)
|
|
corrected = json.loads(candidate.corrected)
|
|
assert overclaimed["claimed_saving_nok"] != corrected["claimed_saving_nok"]
|
|
assert overclaimed["affected_items"] == corrected["affected_items"]
|
|
|
|
|
|
def test_the_overclaim_and_the_markers_are_absent_from_the_delivered_bundle() -> None:
|
|
"""The three tokens the walkthrough traces must not already be IN the content it traces.
|
|
|
|
``flip_key`` absent: otherwise attempt 1's prompt carries it and the proposer 'corrects' before
|
|
anything was falsified — Step 5 would show a correction nothing caused. Both markers absent:
|
|
otherwise Run A's 'markøren er FRAVÆRENDE' line is false, and the promotion / inbox paths would
|
|
each appear to work while carrying nothing.
|
|
|
|
This is a CONTENT check, and delivered content is the reason it exists: the register's figure was
|
|
chosen against the bundle's number inventory, and this is what keeps that choice honest if either
|
|
side changes."""
|
|
text = "\n".join(
|
|
path.read_text(encoding="utf-8")
|
|
for path in sorted(_delivered_bundle_dir().rglob("*"))
|
|
if path.is_file()
|
|
)
|
|
|
|
for token in (_klientpark().flip_key, load_persona_example().marker, _INBOX_MARKER):
|
|
assert token not in text, (
|
|
f"{token!r} already occurs in the delivered bundle — the walkthrough would trace a "
|
|
"token the content supplied, not one the loop carried"
|
|
)
|
|
|
|
|
|
async def test_the_delivered_bundle_runs_the_whole_demo(tmp_path) -> None:
|
|
"""CONTROL, and demo-criterion 2 measured against delivered content: hypothesis #1 is falsified
|
|
by the P90 stage, the corrected one validates, and both runs end FORESLÅTT.
|
|
|
|
A gate that rejects everything proves nothing, so this is what gives the 10 % test below its
|
|
meaning. It also pins WHICH stage rejects #1 — were stage 0 to start rejecting it, the screen
|
|
would still show a REJECTED and a VALIDATED line while demonstrating a different mechanism."""
|
|
result = await simulate_learning_loop(
|
|
str(_delivered_bundle_dir()), str(tmp_path), project_id=_KLIENTPARK_PROJECT_ID
|
|
)
|
|
|
|
assert isinstance(result.run_a.outcome, ValidatedProposal)
|
|
assert isinstance(result.run_b.outcome, ValidatedProposal)
|
|
assert result.run_a.refinements, "no falsification was fed back — Step 5 is not being shown"
|
|
assert "exceeds P90 feasible" in result.run_a.refinements[0].reason, (
|
|
"hypothesis #1 was rejected by some other stage than the P90 one the demo narrates"
|
|
)
|
|
# Both learning paths close on delivered content too (Step 8 wiki + Step 7 inbox).
|
|
assert result.marker_in_run_b_prompt and result.inbox_marker_in_run_b_prompt
|
|
assert not result.marker_in_run_a_prompt
|
|
|
|
|
|
async def test_a_deviating_delivered_baseline_forkaster_the_run_before_the_solver(tmp_path) -> None:
|
|
"""LOAD-BEARING (the 10 % test, on DELIVERED content): when the project's declared cost lines
|
|
deviate 10 % from what the script asserts, the run is FORKASTET at stage 0 — with the
|
|
reconciliation reason, never the P90 one.
|
|
|
|
This is the answer to "the register was copied from the baseline, so of course they agree": the
|
|
agreement is only worth something if a DISagreement would be caught. The script is byte-identical
|
|
to the control above; only the declared baseline moves.
|
|
|
|
The deviated copy is materialized in ``tmp_path`` — criterion 8 requires the delivered bundle
|
|
byte-unchanged."""
|
|
delivered = _delivered_baseline()
|
|
deviated = CostBaseline(
|
|
project_id=delivered.project_id,
|
|
items={
|
|
code: CostBaselineLine(quantity=line.quantity * 1.10, unit_cost=line.unit_cost)
|
|
for code, line in delivered.items.items()
|
|
},
|
|
)
|
|
bundle = materialize_anchored_bundle(
|
|
tmp_path / "avvikende", source=_delivered_bundle_dir(), baseline=deviated
|
|
)
|
|
result = await simulate_learning_loop(
|
|
str(bundle), str(tmp_path), project_id=_KLIENTPARK_PROJECT_ID
|
|
)
|
|
|
|
outcome = result.run_a.outcome
|
|
assert isinstance(outcome, Rejection), (
|
|
"a proposal 10 % away from the project's declared cost lines was NOT rejected — the "
|
|
"deterministic gate is not anchored to the delivered baseline"
|
|
)
|
|
assert "outside the 5.0% tolerance" in outcome.reason
|
|
assert "ENERGI-KLIENTPARK-EL" in outcome.reason
|
|
assert "P90" not in outcome.reason, (
|
|
"rejected by the solver stage, not by the reconciliation stage 0 that must run BEFORE it"
|
|
)
|
|
|
|
|
|
def _snapshot(bundle: Path) -> dict[str, bytes]:
|
|
return {
|
|
path.relative_to(bundle).as_posix(): path.read_bytes()
|
|
for path in sorted(bundle.rglob("*"))
|
|
if path.is_file()
|
|
}
|
|
|
|
|
|
async def test_the_delivered_bundle_is_never_mutated_by_a_run(tmp_path) -> None:
|
|
"""Criterion 8's day-to-day half: the demo copies the bundle, so the delivered files are
|
|
byte-unchanged after a whole two-run walkthrough over them.
|
|
|
|
Measured around a run of its own rather than read off the version-control status: the bundle's
|
|
bytes before and after are compared directly, so the check holds whether or not the bundle is
|
|
committed yet, and it does not depend on which other tests happened to run first."""
|
|
bundle = _delivered_bundle_dir()
|
|
before = _snapshot(bundle)
|
|
assert before, "the delivered bundle has no files -- the comparison below would be vacuous"
|
|
|
|
await simulate_learning_loop(str(bundle), str(tmp_path), project_id=_KLIENTPARK_PROJECT_ID)
|
|
|
|
assert _snapshot(bundle) == before, "the delivered bundle was modified in place by a run"
|
|
|
|
|
|
def test_the_reserve_entry_and_the_delivered_entry_are_both_registered() -> None:
|
|
"""The abort path stays reachable: pointing ``main`` back at the anchored reserve must remain a
|
|
three-line revert, which it only is while the reserve's registry entry still exists."""
|
|
ids = {c.project_id for c in _CANDIDATES}
|
|
|
|
assert {"BYGG-KONTOR-NORD", _KLIENTPARK_PROJECT_ID} <= ids
|
|
|
|
|
|
def test_the_projection_names_the_project_the_register_keys_on() -> None:
|
|
"""The id must stand VERBATIM in the delivered IR projection: ``run._project_from_bundle``
|
|
raises on a mismatch, and ``scripted_proposer`` keys on this exact string. Two files, one
|
|
identifier — so it is asserted, not assumed."""
|
|
projection = json.loads(
|
|
(_delivered_bundle_dir() / "validator-input.json").read_text(encoding="utf-8")
|
|
)
|
|
|
|
assert projection["project_id"] == _KLIENTPARK_PROJECT_ID
|
|
assert _delivered_baseline().project_id == projection["project_id"]
|