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.
This commit is contained in:
parent
7aef1feaa4
commit
50232fb88d
7 changed files with 422 additions and 2 deletions
124
tests/test_p4_honesty_sentences_loadbearing.py
Normal file
124
tests/test_p4_honesty_sentences_loadbearing.py
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
"""P4 pkt. 4 — the two honesty sentences the demo says out loud, and why one of them is DERIVED.
|
||||
|
||||
The plan pre-wrote two sentences for the stage. The first is the provenance claim about the cost
|
||||
numbers, already live as ``_VEGLYS_PROVENANCE`` since the GO (P3): the baseline the validator's
|
||||
stage 0 reconciles against was written by a domain team, not by the demo script.
|
||||
|
||||
The second is the seed sentence, about where Run B's "previous verdicts" come from. **Its pre-written
|
||||
wording is wrong against the delivered content and was corrected against measurement.** The plan said
|
||||
"one of the TWO previous verdicts in Run B came with the example — the other is the one the demo
|
||||
learned"; measured against the delivered VEGLYS bundle, Run B retrieves THREE: one seeded
|
||||
(``verdict-veglys-fro.md``), and TWO the demo produced itself — one per time scale (the Step-8
|
||||
promotion and the Step-7 inbox note). A sentence that says "two" would be a false claim made on
|
||||
stage about a number printed one line above it.
|
||||
|
||||
**Why the split is computed and not written down.** The line right above already prints the retrieved
|
||||
count. A hand-written "one of three" would be a second copy of that number in a different place —
|
||||
the exact drift the anchored-baseline discipline (P4 pkt. 0) refuses — and it would go on being said
|
||||
after a future bundle ships a second seeded verdict, silently. So the split is derived from the run,
|
||||
and the classifier is the two markers the demo has been tracing all along: a retrieved verdict that
|
||||
carries one of them is one the demo learned in this session; anything else came with the knowledge
|
||||
base.
|
||||
|
||||
That classifier rests on a property of the delivered content — the seeded verdict must carry NEITHER
|
||||
marker — so that property is measured here too, and not assumed.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from portfolio_optimiser.persona import load_persona_example
|
||||
from portfolio_optimiser.simulation import (
|
||||
_INBOX_MARKER,
|
||||
_VEGLYS_PROVENANCE,
|
||||
_delivered_bundle_dir,
|
||||
_verdict_origin_line,
|
||||
)
|
||||
from portfolio_optimiser.verdicts import ProposalFeatures, Verdict, seed_store_from_bundle
|
||||
|
||||
# The Step-8 marker is the shared expert-reviewer skill's own, read at call time — the simulation
|
||||
# takes it from the artifact rather than from a module constant, and so does this test.
|
||||
_MARKER = load_persona_example().marker
|
||||
|
||||
|
||||
def _verdict(vid: str, rationale: str) -> Verdict:
|
||||
return Verdict(
|
||||
id=vid,
|
||||
proposal_features=ProposalFeatures(
|
||||
affected_codes=frozenset({"ENERGI-VEGLYS-EL"}),
|
||||
measure_type="LED-utskifting",
|
||||
claimed_saving_nok=445500.0,
|
||||
description="LED-utskifting",
|
||||
),
|
||||
decision="approved",
|
||||
rationale=rationale,
|
||||
)
|
||||
|
||||
|
||||
def test_the_origin_line_reports_the_delivered_bundles_actual_split() -> None:
|
||||
"""T-P4.4a: three retrieved, two carrying markers -> one came with the knowledge base.
|
||||
|
||||
This is the shape the demo prints today. RED if the classification is inverted or dropped.
|
||||
"""
|
||||
retrieved = [
|
||||
_verdict("seeded", "frøsatt dom uten markør"),
|
||||
_verdict("promoted", f"persona-dom ({_MARKER})"),
|
||||
_verdict("inbox", f"driftsnotat ({_INBOX_MARKER})"),
|
||||
]
|
||||
line = _verdict_origin_line(retrieved, marker=_MARKER, inbox_marker=_INBOX_MARKER)
|
||||
assert "1" in line and "2" in line
|
||||
assert "kunnskapsbasen" in line
|
||||
|
||||
|
||||
def test_the_split_is_computed_and_not_a_written_down_constant() -> None:
|
||||
"""T-P4.4b (the distinguishing test): a bundle with a SECOND seeded verdict must move the
|
||||
number.
|
||||
|
||||
An implementation that writes "1 of 3" into the string passes T-P4.4a and fails here — which is
|
||||
the whole reason this test exists. A test that only ever sees the delivered bundle's own split
|
||||
cannot tell the two implementations apart, and would prove nothing.
|
||||
"""
|
||||
retrieved = [
|
||||
_verdict("seeded-a", "frøsatt dom uten markør"),
|
||||
_verdict("seeded-b", "en annen frøsatt dom uten markør"),
|
||||
_verdict("promoted", f"persona-dom ({_MARKER})"),
|
||||
_verdict("inbox", f"driftsnotat ({_INBOX_MARKER})"),
|
||||
]
|
||||
line = _verdict_origin_line(retrieved, marker=_MARKER, inbox_marker=_INBOX_MARKER)
|
||||
assert "2 av 4" in line, line
|
||||
|
||||
|
||||
def test_both_sentences_are_in_the_pinned_transcript() -> None:
|
||||
"""T-P4.4d: the two sentences are on the screen the operator has already read.
|
||||
|
||||
Checked against the checked-in fasit rather than by starting a fourth demo subprocess — the
|
||||
fasit is byte-compared to a live run in ``test_golden_transcript_loadbearing``, so a sentence
|
||||
that is in the file but no longer printed fails there, and a sentence dropped from BOTH fails
|
||||
here. The provenance half needs this: the anchored-reserve test only rules the reserve's
|
||||
sentence OUT, so emptying ``_VEGLYS_PROVENANCE`` would leave it green.
|
||||
"""
|
||||
fasit = (Path(__file__).resolve().parent / "golden" / "demo-transcript.stdout").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
assert _VEGLYS_PROVENANCE in fasit
|
||||
assert "med kunnskapsbasen; de øvrige" in fasit
|
||||
|
||||
|
||||
def test_the_delivered_seed_verdict_carries_neither_marker() -> None:
|
||||
"""T-P4.4c (RED-proof for the classifier): the property the split rests on, measured on the
|
||||
delivered bundle rather than assumed.
|
||||
|
||||
If the seeded verdict's rationale ever contained one of the two markers, it would be counted as
|
||||
something the demo learned, and the sentence on stage would overstate the loop by one. It would
|
||||
also mean the marker was present in the knowledge base from the start — which the Step-7 and
|
||||
Step-8 load-bearing tests already forbid for their own reasons, but this line depends on it too.
|
||||
"""
|
||||
store = seed_store_from_bundle(str(_delivered_bundle_dir()))
|
||||
seeded = [v for v in store.verdicts]
|
||||
assert seeded, (
|
||||
"the delivered bundle ships no seeded verdict — the classifier has nothing to see"
|
||||
)
|
||||
for verdict in seeded:
|
||||
assert _MARKER not in verdict.rationale
|
||||
assert _INBOX_MARKER not in verdict.rationale
|
||||
Loading…
Add table
Add a link
Reference in a new issue