#!/usr/bin/env python3 """ Positive control for the degraded-run guard. An absence is not evidence until the instrument is shown capable of detecting presence. The old guard PASSED trial 03 — 2,944 words of untagged deliberation, truncated at the token ceiling, recorded as `degraded: null`. So the test is not "does the new guard run"; it is "does the new guard catch THE ACTUAL OUTPUT that defeated the old one", and does it stay quiet on output that is genuinely fine. Runs anywhere — imports no mlx. Usage: ./test_degraded_guard.py """ from __future__ import annotations import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent)) from run_trial import UNTAGGED_SCRATCHPAD_RE, split_reasoning # noqa: E402 HERE = Path(__file__).resolve().parent TRIAL_03 = HERE / "runs" / "trial-03-20260802T144136Z.answer.md" # A real answer to this prompt. Must NOT trip the guard — a guard that fires on # everything detects nothing. CLEAN_ANSWER = """**Assumption:** The separation-of-powers analogy maps validly. **Where relied upon:** Part III asserts it as a historical premise. **What must be true:** That the conditions enabling checks in human political systems are present in this configuration.""" # The failure mode in miniature, for when the trial-03 artefact is not present. SYNTHETIC_SCRATCHPAD = """Here's a thinking process: 1. **Analyze User Input:** The task is to identify claims the document relies on.""" # Near-misses that must stay quiet: deliberation words appearing in a real answer. NEAR_MISSES = [ "The document's reasoning about correlated misses is never demonstrated.", # Caught a real false positive in the first version of the guard: a bare # `okay` plus any deliberation word within 80 characters. "Okay is not a word this document uses, but its approach to falsification is.", "**Assumption 1:** the author's thinking process is treated as transparent.", "I will not restate what Part VII already names as its own limitation.", "Here's the assumption the argument needs: that the analogy holds.", ] failures: list[str] = [] def check(name: str, got: bool, want: bool, detail: str = "") -> None: if got != want: failures.append(f"{name}: expected {want}, got {got}. {detail}") print(f" FAIL {name}") else: print(f" ok {name}") print("Positive control — the artefact that defeated the old guard:") if TRIAL_03.is_file(): text = TRIAL_03.read_text(encoding="utf-8") reasoning, answer = split_reasoning(text) check("trial-03: no tag found", reasoning is None, True) check( "trial-03: untagged scratchpad DETECTED", bool(UNTAGGED_SCRATCHPAD_RE.match(answer)), True, "This is the exact output the old guard passed as degraded:null.", ) else: print(f" SKIP {TRIAL_03.name} not present — running synthetic only") failures.append( "trial-03 artefact absent: the positive control did not run against real " "output. Treat the guard as UNVERIFIED against the case it was built for." ) print("\nSynthetic scratchpad:") check( "synthetic scratchpad detected", bool(UNTAGGED_SCRATCHPAD_RE.match(SYNTHETIC_SCRATCHPAD)), True, ) print("\nNegative controls — must stay quiet:") check("clean answer not flagged", bool(UNTAGGED_SCRATCHPAD_RE.match(CLEAN_ANSWER)), False) for i, text in enumerate(NEAR_MISSES): check(f"near-miss {i}", bool(UNTAGGED_SCRATCHPAD_RE.match(text)), False, repr(text[:50])) print("\nTagged output still splits correctly:") r, a = split_reasoning("deliberating\nThe answer.") check("reasoning extracted", r == "deliberating", True) check("answer extracted", a == "The answer.", True) if failures: print(f"\nINSTRUMENT NOT VERIFIED — {len(failures)} failure(s):") for f in failures: print(f" - {f}") sys.exit(1) print("\nAll checks passed. The guard catches the case that defeated its predecessor.")