portfolio-optimiser/tests/test_golden_transcript_loadbearing.py
Kjell Tore Guttormsen 50232fb88d feat(simulation): P4 pkt. 3+4 — demo-transkriptet pinnet, frø-setningen avledet [skip-docs]
Kriterium 6 er selv-identitet: to kjøringer av en regredert demo er like enige som
to av en riktig. Fasiten forlater derfor prosessen. stdout pinnes ORDRETT (og er
dermed demoens abortsti); stderr normaliseres på nøyaktig to MÅLTE miljø-spann —
site-packages-prefikset og temp-katalogen — med po-sim- holdt synlig, fordi det er
en egenskap ved programmet og ikke ved miljøet. Pinnet stderr = fire linjer.
Kontrollen som forbyr at masken vokser er load-bearing: en droppende normaliserer
med fasiten regenerert under seg holder BEGGE likhets-testene grønne.

Pkt. 4: planens forhåndsskrevne frø-setning sa «én av de TO tidligere dommene».
Målt mot levert VEGLYS-bundle henter Kjøring B TRE — én fulgte med kunnskapsbasen,
to er demoens egne, én per tidsskala. Splitten avledes derfor fra kjøringen; en
håndskrevet «én av tre» ville vært den andre kopien som drifter.

Fem mutasjoner alle røde + grønn kontroll (hele suiten hver gang): ett byte i en
stdout-linje · detach dempingen · over-normaliser stderr · literal splitt · detach
frø-setningens print. Byte- og detach-mutasjonene ble fanget av KUN golden-testen;
den literale splitten av KUN skille-testen.

793 -> 801 passed / 4 skipped.
2026-08-09 22:12:25 +02:00

142 lines
7 KiB
Python

"""P4 pkt. 3 — the demo transcript is pinned as a checked-in fasit, and the pin is also the
demo's abort path.
**What this adds over criterion 6.** Criterion 6 is self-identity: run the demo twice, diff the two
outputs. It catches non-determinism, and nothing else — two runs of a *regressed* demo agree with
each other just as happily as two runs of a correct one. Between the Wednesday freeze and the
Thursday stage there is no second run to compare against, so the fasit has to leave the process:
the transcript is checked in, and the demo is diffed against the file.
**Why stdout is literal and stderr is not.** stdout was measured byte-identical across runs AND
across a fresh clone (P4 pkt. 1), so it is pinned verbatim — the file under ``golden/`` is exactly
what the operator sees, which is what makes it usable as the abort path: if the live run fails on
stage, that file IS the transcript. stderr carries two spans that are environment state rather than
program output, and both were measured to differ between a fresh clone and the working copy:
1. the absolute ``.../site-packages/`` prefix in the two ``ExperimentalWarning`` lines, and
2. the temp directory behind ``(arbeidskopi: ...)`` — a fresh ``mkdtemp`` suffix every run, under a
``TMPDIR`` that is per-user.
Both are masked; everything else is compared byte for byte. Pinned stderr is four lines: the two
warnings, a blank line, and the ``arbeidskopi:`` line.
**The narrowness is the point, and it is under test.** P4 pkt. 2 damped the round-cap notices with a
filter keyed on the MESSAGE precisely so that a NEW warning — from a MAF bump, or a subtree pull —
would still reach stderr and trip this pin. A normalisation that masked whole lines would undo that
in one step and leave a pin that can no longer fail for the reason it exists. So the masking is
measured, not asserted: ``test_normalisation_does_not_mask_a_new_warning`` feeds a stderr with one
extra line through the same normaliser and requires it to STOP matching the fasit.
**Honesty about what a golden proves.** The fasit was generated from a run, so it cannot by itself
prove that run was right — it pins the output the P3 criteria were measured against (eight step
lines; hypothesis #1 REJECTED on the P90 stage and the corrected one VALIDATED for the same
candidate; both learning paths reaching Run B). Regenerating it is therefore a decision, never
housekeeping: whoever regenerates re-takes those measurements.
"""
from __future__ import annotations
import os
import re
import subprocess
import sys
from pathlib import Path
import pytest
_GOLDEN_DIR = Path(__file__).resolve().parent / "golden"
_STDOUT_FASIT = _GOLDEN_DIR / "demo-transcript.stdout"
_STDERR_FASIT = _GOLDEN_DIR / "demo-transcript.stderr"
# Span 1: the interpreter's site-packages prefix, up to and including the separator. Anchored on
# the literal ``/site-packages/`` rather than on a home directory, so a checkout anywhere (or a
# different Python minor version) normalises to the same text.
_SITE_PACKAGES = re.compile(r"\S*/site-packages/")
# Span 2: the throwaway working copy. The ``po-sim-`` prefix is kept VISIBLE — it is a property of
# the program (``tempfile.mkdtemp(prefix="po-sim-")``), not of the environment — while the TMPDIR
# root and the random suffix, which are both, are masked.
_WORKING_COPY = re.compile(r"\(arbeidskopi: \S*/po-sim-\w+\)")
def normalise_stderr(text: str) -> str:
"""Mask the two measured environment-dependent spans, and nothing else."""
text = _SITE_PACKAGES.sub("<SITE-PACKAGES>/", text)
return _WORKING_COPY.sub("(arbeidskopi: <TMPDIR>/po-sim-<SUFFIKS>)", text)
@pytest.fixture(scope="module")
def demo() -> subprocess.CompletedProcess[str]:
"""Run the real demo once for this module.
Runs the ``-m`` form rather than the console script: it needs no assumption about PATH, and the
two forms were measured to write identical stdout when the entry point was added (P4 pkt. 5).
``PYTHONIOENCODING`` is pinned because the fasit is a file of UTF-8 bytes — without it the
comparison would measure the operator's locale instead of the program.
"""
proc = subprocess.run(
[sys.executable, "-m", "portfolio_optimiser.simulation"],
capture_output=True,
text=True,
encoding="utf-8",
env={**os.environ, "PYTHONIOENCODING": "utf-8"},
check=False,
)
assert proc.returncode == 0, proc.stderr
return proc
def test_demo_stdout_matches_the_checked_in_transcript(
demo: subprocess.CompletedProcess[str],
) -> None:
"""T-P4.3a: stdout is byte-identical to the fasit — no normalisation, no tolerance.
RED on any change to a step line, a number, a label or the ordering. That is the whole point:
on demo day the operator has already read this file, and anything the program says that the
file does not is a surprise on stage.
"""
assert _STDOUT_FASIT.exists(), (
f"the pinned transcript is missing: {_STDOUT_FASIT}. It is generated by re-taking the P3 "
"measurements, not by copying whatever the demo currently prints."
)
assert demo.stdout == _STDOUT_FASIT.read_text(encoding="utf-8")
def test_demo_stderr_matches_the_normalised_transcript(
demo: subprocess.CompletedProcess[str],
) -> None:
"""T-P4.3b: stderr, with the two environment spans masked, is identical to the fasit.
RED when a new warning appears (a MAF bump, a subtree pull) and RED when the round-cap damping
is detached — the two lines it drops would land right back in this comparison.
"""
assert _STDERR_FASIT.exists(), f"the pinned stderr is missing: {_STDERR_FASIT}"
assert normalise_stderr(demo.stderr) == _STDERR_FASIT.read_text(encoding="utf-8")
def test_normalisation_is_not_a_no_op(demo: subprocess.CompletedProcess[str]) -> None:
"""T-P4.3c (RED-proof for the test above): the raw stderr really does differ from the fasit.
Without this, T-P4.3b would be indistinguishable from a run where the environment spans happened
to be stable and the normaliser did nothing at all — and a masking that never fires cannot be
said to be narrow.
"""
fasit = _STDERR_FASIT.read_text(encoding="utf-8")
assert demo.stderr != fasit
assert normalise_stderr(demo.stderr) == fasit
def test_normalisation_does_not_mask_a_new_warning(
demo: subprocess.CompletedProcess[str],
) -> None:
"""T-P4.3d (control): the masking is span-scoped, so an EXTRA stderr line still trips the pin.
This is the property P4 pkt. 2 paid for by keying the damping on the message rather than on the
logger. Measured here on a synthetic stderr rather than by provoking a real warning, because the
thing under test is the normaliser's reach — the real-warning path is what T-P4.3b covers.
"""
intruder = (
"/somewhere/lib/python3.12/site-packages/agent_framework/_new.py:1: DeprecationWarning: "
"something changed under us.\n"
)
polluted = intruder + demo.stderr
assert normalise_stderr(polluted) != _STDERR_FASIT.read_text(encoding="utf-8")