feat(simulation): GO — demoen kjører levert VEGLYS-bundle, forankret på deres tall [skip-docs]
P3 a-c lukket. Pullen hentet commons 002f000+27cdce9: kriterium 8 grønt (nav-goldens byte-uendret, målt både med git diff og shasum) og suiten uendret 785 — ingen abort. Retningen på tallene er SNUDD (P3 b): manus-registerets kostlinjer er skrevet FRA shared/examples/veglys-fv-soer/cost-baseline.json, ikke ved siden av den, og baseline_from_scripted_candidate brukes ikke på denne stien — main() leser levert fil. Overdrivelsen 2100000 er valgt utenfor commons' tall-inventar: målt fraværende fra bundelen og over målt P90 1769915 (deres anslag var ~1770000). 600000/900000 ville klarert gaten og aldri utløst Steg 5. Målingen felte en defekt reserven skjulte: :g slår over i eksponentform ved 7. signifikante siffer, så levert baseline printet 4.38615e+06. Reservens 300000 har seks siffer og nådde aldri overgangen. _num erstatter :g begge steder. Load-bearing MÅLT mot hele suiten, fem mutasjoner alle røde + grønn kontroll: detach main-wiringen · reverter _num til :g · drift registeret ETT siffer (4386151 — innenfor 5 %-toleransen, fanget av ingenting i 792 tester bortsett fra den nye) · sett flip_key til et token som finnes i bundelen · detach forankringen på bundle-stien. 785 -> 793 passed / 4 skipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BUjfw4eJdwwnqHSXhfcY6i
This commit is contained in:
parent
ce892be855
commit
02ddc6735f
3 changed files with 306 additions and 15 deletions
|
|
@ -54,6 +54,9 @@ from portfolio_optimiser.verdicts import (
|
|||
)
|
||||
|
||||
_PROJECT_ID = "BYGG-KONTOR-NORD"
|
||||
# The delivered domain bundle (commons `002f000`) — the project the demo runs on stage. Kept beside
|
||||
# the reserve's id rather than replacing it: the reserve stays reachable as the abort path.
|
||||
_VEGLYS_PROJECT_ID = "VEGLYS-FV-SOER"
|
||||
|
||||
# --- P4 pkt. 2: demo stderr discipline -----------------------------------------------------------
|
||||
# Measured 2026-08-09, the demo wrote six stderr lines: two ``ExperimentalWarning``s from
|
||||
|
|
@ -216,6 +219,38 @@ _CANDIDATES: tuple[ScriptedCandidate, ...] = (
|
|||
),
|
||||
flip_key="250000",
|
||||
),
|
||||
# VEGLYS-FV-SOER — the DELIVERED bundle (commons `002f000`), and the one on stage. Every number
|
||||
# below is written FROM `shared/examples/veglys-fv-soer/validator-input.json`, never beside it
|
||||
# (plan P3 b): this is `baseline_from_scripted_candidate`'s direction REVERSED — the domain team
|
||||
# shipped the cost lines, so the register copies them, and the derivation helper is not used on
|
||||
# this path (`main` reads the delivered `cost-baseline.json` off the bundle instead).
|
||||
#
|
||||
# The corrected reply IS the delivered IR projection verbatim: affected_items = the WHOLE
|
||||
# portfolio's annual energy cost (their decision — scoping it to the 2 500 touched points would
|
||||
# make the RIGHT proposal 38,6 % of its own baseline and the 30 % cap would fell it on stage),
|
||||
# claimed_saving_nok = 445500, assumptions = the declared energy-price band. The overclaimed one
|
||||
# differs in exactly ONE field.
|
||||
#
|
||||
# 2100000 is chosen OUTSIDE commons' number inventory and above BOTH thresholds: measured absent
|
||||
# from the bundle (so the correction is caused by the falsification travelling back), and above
|
||||
# the degenerate cap 0.30 x 4386150 = 1315845 as well as the banded P90. 600000/900000 would have
|
||||
# CLEARED the gate — the REJECTED line would never appear and demo-criterion 2 would fail quietly.
|
||||
ScriptedCandidate(
|
||||
project_id=_VEGLYS_PROJECT_ID,
|
||||
overclaimed=(
|
||||
'{"measure":"LED-utskifting av 2 500 eldre HPS-armaturer (114 W -> 70 W)",'
|
||||
'"affected_items":[{"code":"ENERGI-VEGLYS-EL","quantity":4386150,"unit_cost":1.0}],'
|
||||
'"claimed_saving_nok":2100000,'
|
||||
'"assumptions":{"ENERGI-VEGLYS-EL":[0.70,1.40]}}'
|
||||
),
|
||||
corrected=(
|
||||
'{"measure":"LED-utskifting av 2 500 eldre HPS-armaturer (114 W -> 70 W)",'
|
||||
'"affected_items":[{"code":"ENERGI-VEGLYS-EL","quantity":4386150,"unit_cost":1.0}],'
|
||||
'"claimed_saving_nok":445500,'
|
||||
'"assumptions":{"ENERGI-VEGLYS-EL":[0.70,1.40]}}'
|
||||
),
|
||||
flip_key="2100000",
|
||||
),
|
||||
)
|
||||
|
||||
_proposer_reply = scripted_proposer(_CANDIDATES)
|
||||
|
|
@ -226,6 +261,21 @@ _proposer_reply = scripted_proposer(_CANDIDATES)
|
|||
_COST_BASELINE_FILE = "cost-baseline.json"
|
||||
_ANCHORED_DIR_NAME = "forankret-reserve"
|
||||
_RESERVE_PROVENANCE = "tallene er syntetiske — avledet av demo-manuset, ikke levert av et fagmiljø"
|
||||
# The GO-day honesty sentence (plan P4 pkt. 4). It claims exactly what the bundle's own `_note`
|
||||
# documents — the cost line is derived from published sources — and nothing about the realization
|
||||
# rate, which the seed verdict itself marks as BORROWED from lighting-programme literature.
|
||||
_VEGLYS_PROVENANCE = (
|
||||
"tallene er levert i kunnskapsbasen — utledet av fagkilder (Håndbok V124, NMFV), "
|
||||
"ikke av demo-manuset"
|
||||
)
|
||||
|
||||
|
||||
def _delivered_bundle_dir() -> Path:
|
||||
"""The delivered VEGLYS bundle, resolved at CALL time via ``shared_root()`` (same seam as
|
||||
``_default_bundle_dir``). It ships its own ``cost-baseline.json``, so the demo is anchored
|
||||
WITHOUT ``materialize_anchored_bundle`` — that helper exists for the reserve, whose numbers
|
||||
cannot be given a baseline in place (pull-only subtree + byte-unchanged goldens)."""
|
||||
return shared_root() / "examples" / "veglys-fv-soer"
|
||||
|
||||
|
||||
def baseline_from_scripted_candidate(candidate: ScriptedCandidate) -> CostBaseline:
|
||||
|
|
@ -598,8 +648,24 @@ def _clip(text: str, limit: int = 92) -> str:
|
|||
return flat if len(flat) <= limit else flat[: limit - 1] + "…"
|
||||
|
||||
|
||||
def _num(value: float) -> str:
|
||||
"""Render a cost magnitude without exponent notation.
|
||||
|
||||
``:g`` — what these lines used while the demo ran the reserve — switches to scientific notation
|
||||
at the 7th significant digit, so the DELIVERED baseline printed as ``4.38615e+06``. The reserve's
|
||||
``300000`` has six digits and never reached the switch: a formatting defect the synthetic numbers
|
||||
hid and delivered content exposed on the first run. A demo whose headline cost line is unreadable
|
||||
cannot claim the gate is anchored in real cost lines.
|
||||
"""
|
||||
if value == int(value):
|
||||
return str(int(value))
|
||||
return f"{value:f}".rstrip("0").rstrip(".")
|
||||
|
||||
|
||||
def _items_line(proposal: SavingsProposal) -> str:
|
||||
return ", ".join(f"{i.code} {i.quantity:g} x {i.unit_cost:g}" for i in proposal.affected_items)
|
||||
return ", ".join(
|
||||
f"{i.code} {_num(i.quantity)} x {_num(i.unit_cost)}" for i in proposal.affected_items
|
||||
)
|
||||
|
||||
|
||||
def _first_hypothesis(result: RunResult) -> SavingsProposal:
|
||||
|
|
@ -707,7 +773,7 @@ def _baseline_lines(bundle_dir: Path, provenance: str) -> list[str]:
|
|||
" validatoren regner kun på tallene forslaget selv oppgir",
|
||||
]
|
||||
items = ", ".join(
|
||||
f"{code} {line.quantity:g} x {line.unit_cost:g}"
|
||||
f"{code} {_num(line.quantity)} x {_num(line.unit_cost)}"
|
||||
for code, line in sorted(baseline.items.items())
|
||||
)
|
||||
return [
|
||||
|
|
@ -730,12 +796,15 @@ def main(argv: list[str] | None = None) -> int: # pragma: no cover - console tr
|
|||
quiet_expected_round_cap_notice()
|
||||
|
||||
work = tempfile.mkdtemp(prefix="po-sim-")
|
||||
# THE call site (P4 pkt. 0): the demo runs the ANCHORED reserve — the shared bundle plus the
|
||||
# cost baseline it cannot be given in place. On GO day these two lines point at the delivered
|
||||
# bundle and state ITS provenance instead; the run path's seam is the same either way.
|
||||
bundle = materialize_anchored_bundle(Path(work) / _ANCHORED_DIR_NAME)
|
||||
provenance = _RESERVE_PROVENANCE
|
||||
result = asyncio.run(simulate_learning_loop(str(bundle), work))
|
||||
# THE call site (P3, GO): the demo runs the DELIVERED bundle, which ships its own
|
||||
# `cost-baseline.json` — so the gate is anchored on numbers a domain team wrote, not on numbers
|
||||
# the script derived. The abort path is these three lines reverted to the anchored reserve
|
||||
# (`materialize_anchored_bundle` + `_RESERVE_PROVENANCE` + `_PROJECT_ID`); the run path's seam
|
||||
# is identical either way, which is what made pointing at delivered content a call-site change.
|
||||
bundle = _delivered_bundle_dir()
|
||||
provenance = _VEGLYS_PROVENANCE
|
||||
project_id = _VEGLYS_PROJECT_ID
|
||||
result = asyncio.run(simulate_learning_loop(str(bundle), work, project_id=project_id))
|
||||
|
||||
print("=" * 78)
|
||||
print("OFFLINE SIMULERING — skriptede agent-svar, INGEN ekte modell.")
|
||||
|
|
@ -750,7 +819,7 @@ def main(argv: list[str] | None = None) -> int: # pragma: no cover - console tr
|
|||
# Run A walks steps 1-7 of the method; the promotion between the runs IS step 8. Run B is not
|
||||
# re-numbered — it re-runs the same eight steps, and what the demo needs from it is the ONE
|
||||
# thing that changed: the marker now reaches the hypothesis prompt.
|
||||
print(f"\nKJØRING A ({_PROJECT_ID} — fersk kunnskapsbase, ingen tidligere dommer)")
|
||||
print(f"\nKJØRING A ({project_id} — fersk kunnskapsbase, ingen tidligere dommer)")
|
||||
for line in _run_trace_lines(
|
||||
result.run_a, marker=result.marker, marker_in_prompt=result.marker_in_run_a_prompt
|
||||
):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue