From fd82e35505f01df3281440a882e020fd70b7c9a9 Mon Sep 17 00:00:00 2001 From: Jonathan Borduas Date: Sun, 6 Sep 2026 10:14:41 +0100 Subject: [PATCH 1/2] #598: the short-circuit names its own remedy, and says it is a SKIP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `--force` exists and is documented in --help — "run the subject even if main has not moved" — and the ONLY output a reader sees when the legs did not run never mentioned it. Measured: 0 occurrences of "--force" in a short-circuit run. ⚠ WHAT THAT COST, from the field. A pane probing whether index-watch invokes verdict-census planted a recording stub and watched it fire on run 1 and NOT on runs 2-4. It nearly reported a FALSE NEGATIVE — "this caller does not exist" — because nothing here said the legs could be MADE to run. ⇒ The prose was true and complete about what HAPPENED, and silent about what to DO. That is #73's shape: an absence report that does not name its remedy converts a gap into a wall. Two-poled on an unchanged tree: run 2 (short-circuit) exit 0, now names --force and declares itself a SKIP --force, same tree exit 1, legs actually run ⛔ EXIT 0 IS DELIBERATELY UNCHANGED, and this is a ruling, not a deferral. This file's contract already reads "0 main unchanged, OR checked and the subject reported clean" — two-valued BY DECLARATION, not by accident — and twelve files reference this tool. #598 argues that declaring it does not make it safe; that argument stands and is recorded there. What is settled here: a reader who sees this line now knows the next move, which is the harm the issue actually recorded. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01DTMf4EvaTEnDKXY47efRZZ --- tools/index-watch.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tools/index-watch.py b/tools/index-watch.py index 1f69494..821d66e 100755 --- a/tools/index-watch.py +++ b/tools/index-watch.py @@ -245,8 +245,29 @@ def check_once(state_path, force=False, subject=None, repo=None, legs=None, sha= prev, base = load_state(state_path) if prev == sha and not force: # The only silent-ish path, and it is silent about the SUBJECTS, not about itself. + # + # ⛔ #598: THIS LINE NAMES ITS OWN REMEDY NOW, and the omission was the whole cost. + # `--force` exists and is documented in --help ("run the subject even if main has not + # moved"), and this output — the ONLY output a reader sees when the legs did not run — + # never mentioned it. Measured 2026-09-06: 0 occurrences of "--force" in a + # short-circuit run. + # + # ⚠ WHAT THAT COST, from the field: a pane probing whether index-watch invokes + # verdict-census planted a recording stub and watched it fire on run 1 and NOT on runs + # 2-4. It nearly reported a FALSE NEGATIVE — "this caller does not exist" — because + # nothing here said the legs could be MADE to run. ⇒ The prose was true and complete + # about what happened, and silent about what to do, which is the shape #73 records: + # an absence report that does not name its remedy converts a gap into a wall. + # + # ⚠ EXIT 0 IS DELIBERATELY UNCHANGED. This file's contract already reads "0 main + # unchanged, OR checked and the subject reported clean" — two-valued by declaration, + # not by accident — and twelve files reference this tool. #598 argues that declaring + # it does not make it safe, and that argument stands; it is recorded there, not + # settled here. What is settled: a reader who sees this line now knows the next move. return 0, [f" ok main unchanged at {sha[:8]} — {len(legs)} leg(s) not run" - f" (nothing to re-check)"] + f" (nothing to re-check; --force runs them anyway)", + f" ⚠ this is a SKIP, not a verdict: exit 0 here means the legs did NOT" + f" run. See #598."] codes, all_lines, all_found = [], [], [] for leg in legs: From 03278ee0833adef679b43bf859374e0abc3c0b96 Mon Sep 17 00:00:00 2001 From: Jonathan Borduas Date: Sun, 6 Sep 2026 10:14:41 +0100 Subject: [PATCH 2/2] #607 was half a fix: the gate probes garbage BARE too, and both tools ignored it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⛔ I FOUND THIS BY MY OWN CHANGE APPEARING TO REGRESS SOMETHING IT DID NOT. pane-census read UNVERIFIABLE on my branch; the CONTROL — three runs at origin/main, my change absent — read IDENTICALLY. ⇒ Not a regression. The state had FLIPPED under both. ★ AND THE MECHANISM IS THE FINDING. #607 refused an unknown flag only ALONGSIDE `--self-test`. The gate also runs `--zzz-not-a-flag` BARE, and a bare unknown flag fell straight through to the main path — so each tool returned its own CENSUS/SCAN verdict, and the gate read that as "it accepts garbage". ⇒ That verdict depends on LIVE STATE, so the gate's reading of an UNCHANGED FILE moved on its own. Measured, same tree, one hour apart: pane-census --zzz-not-a-flag -> 1 (a divergence was live) gate satisfied pane-census --zzz-not-a-flag -> 0 (sources agreed) gate UNVERIFIABLE ⛔ SO #607 PASSED CI ONLY BECAUSE THE FLEET HAPPENED TO DIVERGE THAT HOUR. A control that holds for an environmental reason is not a control — which is the proposition the gate exists to enforce, and my fix was an instance of violating it. ⚠ pipe-exit-scan had the SAME latent hole and was passing for the SAME kind of accident: bare and garbage both exited 1 because it happens to have findings. If those ever cleared it would exit 0 and go UNVERIFIABLE with nothing changed. ⇒ Both now refuse ANY unrecognised argument. Known flags derived, not assumed: pane-census --self-test/--selftest pipe-exit-scan --self-test/--selftest, --transcripts, --project ⚠ `--project` consumes the NEXT token as its value; the guard skips it, and `--transcripts` is re-run above and still reaches the main path. ⚠ Exit 2 is each file's own documented "established nothing". pane-census bare=0 garbage=2 self=0 self+garbage=2 pipe-exit-scan bare=1 garbage=2 self=0 self+garbage=2 MEASURED, three consecutive runs, now STABLE for a structural reason: 44 control(s) passed · 0 FAILED · 0 UNESTABLISHED · 1 UNVERIFIABLE test_pane_census 0 · test_pipe_exit_scan 0 · test_index_watch 0 · exit-code-gate 0 · check-tools-index 0. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01DTMf4EvaTEnDKXY47efRZZ --- tools/pane-census.py | 21 +++++++++++++++++++++ tools/pipe-exit-scan.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/tools/pane-census.py b/tools/pane-census.py index bd356f4..db88b6d 100644 --- a/tools/pane-census.py +++ b/tools/pane-census.py @@ -324,6 +324,27 @@ def main(): # have happened is not a control. Measured 2026-09-06. # ⚠ Exit 2 is correct and unambiguous here: this file's contract already reads # `2 established nothing`, and a half-read invocation establishes nothing. + # ⛔ ANY unrecognised argument, not just one alongside `--self-test`. #607 refused only + # the second, and that was HALF THE PROBE: the gate runs `--zzz-not-a-flag` BARE too, and + # a bare unknown flag fell straight through to the main path — so the tool returned its + # CENSUS VERDICT and the gate read that as "it accepts garbage". + # + # ⚠ HOW THE HOLE HID, and it is the reason this is worth the words: the verdict returned + # depends on LIVE STATE, so the gate's reading of THIS FILE moved without the file + # changing. Measured 2026-09-06, same tree, one hour apart: + # `--zzz-not-a-flag` -> 1 (a divergence was live) ⇒ gate satisfied + # `--zzz-not-a-flag` -> 0 (sources agreed) ⇒ gate: UNVERIFIABLE + # ⇒ #607's fix passed CI only because the fleet happened to diverge that hour. A control + # that holds for an environmental reason is not a control. + # ⚠ Exit 2 is this file's documented "established nothing"; a refusal collides with + # neither 0 nor 1. + _KNOWN = {"--self-test", "--selftest"} + _unknown = [a for a in sys.argv[1:] if a not in _KNOWN] + if _unknown and not ({"--self-test", "--selftest"} & set(sys.argv[1:])): + print(f"\u26d4 VOID \u2014 unrecognised argument(s): {_unknown}. This instrument takes\n" + f" none but --self-test; it reads the pane census and nothing else.\n" + f" NO REMEDY \u2014 there is no flag to pass. Run it bare.", file=sys.stderr) + return 2 if "--self-test" in sys.argv or "--selftest" in sys.argv: _extra = [a for a in sys.argv[1:] if a not in ("--self-test", "--selftest")] if _extra: diff --git a/tools/pipe-exit-scan.py b/tools/pipe-exit-scan.py index d53fdde..56dec00 100755 --- a/tools/pipe-exit-scan.py +++ b/tools/pipe-exit-scan.py @@ -467,6 +467,35 @@ def main(): # have happened is not a control. Measured 2026-09-06. # ⚠ Exit 2 is correct and unambiguous here: this file's contract already reads # `2 established nothing`, and a half-read invocation establishes nothing. + # ⛔ ANY unrecognised argument, not just one alongside `--self-test`. #607 refused only + # the second, and that was HALF THE PROBE: the gate runs `--zzz-not-a-flag` BARE too, and + # a bare unknown flag fell straight through to the main path — so the tool returned its + # CENSUS VERDICT and the gate read that as "it accepts garbage". + # + # ⚠ HOW THE HOLE HID, and it is the reason this is worth the words: the verdict returned + # depends on LIVE STATE, so the gate's reading of THIS FILE moved without the file + # changing. Measured 2026-09-06, same tree, one hour apart: + # `--zzz-not-a-flag` -> 1 (a divergence was live) ⇒ gate satisfied + # `--zzz-not-a-flag` -> 0 (sources agreed) ⇒ gate: UNVERIFIABLE + # ⇒ #607's fix passed CI only because the fleet happened to diverge that hour. A control + # that holds for an environmental reason is not a control. + # ⚠ Exit 2 is this file's documented "established nothing"; a refusal collides with + # neither 0 nor 1. + _KNOWN = {"--self-test", "--selftest", "--transcripts", "--project"} + _av = sys.argv[1:] + _unknown, _skip = [], False + for _i, _a in enumerate(_av): + if _skip: # --project consumes the next token as its VALUE + _skip = False; continue + if _a == "--project": + _skip = True; continue + if _a not in _KNOWN: + _unknown.append(_a) + if _unknown and not ({"--self-test", "--selftest"} & set(_av)): + print(f"\u26d4 VOID \u2014 unrecognised argument(s): {_unknown}. This instrument takes\n" + f" {sorted(_KNOWN)} and nothing else.\n" + f" NO REMEDY \u2014 drop it and run again.", file=sys.stderr) + return 2 if "--self-test" in sys.argv or "--selftest" in sys.argv: _extra = [a for a in sys.argv[1:] if a not in ("--self-test", "--selftest")] if _extra: