"""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