From 5e819673d9b4dd58b9c3e734d68175ea727f2d88 Mon Sep 17 00:00:00 2001 From: Jonathan Borduas Date: Sun, 6 Sep 2026 02:22:51 +0100 Subject: [PATCH 1/2] =?UTF-8?q?declare=20where=20three=20instruments'=20co?= =?UTF-8?q?ntrols=20live=20=E2=80=94=20and=20prove=20one=20declaration=20i?= =?UTF-8?q?s=20ignored?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gate reported 4 UNESTABLISHED. Three of them are not uncontrolled: check-freshness test_check_freshness.py 28 controls PASSES gh-complete test_gh_complete.py 18 controls PASSES job-log test_job_log.py 46 controls PASSES All three suites run in the gating job (56/56 passing). Nothing told the gate where to look. ⇒ Each now carries the repo's existing anchored form, with the reason it has no `--self-test` argv surface stated rather than implied: check-freshness a completedAt boundary is pure arithmetic gh-complete it FORWARDS flags to `gh`, so --self-test becomes a gh flag job-log its subject is a log BODY, fed captured bytes ⇒ MEASURED EFFECT: 4 UNESTABLISHED -> 3. Only gh-complete moved. ⛔ AND THAT IS THE FINDING. check-freshness and job-log take REQUIRED arguments, so they hit the gate's cannot-invoke-bare branch at :272, which returns unest WITHOUT consulting the declaration — first consulted at :340, sixty-eight lines later. Its message says: "it needs a `# NO-SELF-TEST:` line or an invocation this gate can derive." ★ TWO-POLE PROOF, not inference — same tree, declaration present then renamed: POLE A with `# NO-SELF-TEST:` -> "CANNOT BE INVOKED BARE ... UNESTABLISHED" POLE B declaration removed -> IDENTICAL BYTES ⇒ The gate names a remedy it does not honour on the path that prints it. That is #73's own doctrine — an absence report must name a remedy that WORKS — failing in the gate. Filed separately; I am not changing gate semantics unilaterally. ⚠ SO WHAT THESE TWO DECLARATIONS BUY, stated honestly: nothing today. They are true, they record where the control lives for a reader, and they take effect if the gate is fixed. I am not claiming they change the gate's reading, because I measured that they do not. ⚠ AND THE ERROR THAT MADE THIS WORTH DOING WAS MINE. Earlier today I published that 8 instruments "told the gate they HAVE no control". The declaration's own text says the opposite four words in: "⛔ This is a DECLARATION of where the control lives, not a claim that none exists." I read a label and inferred a state. These three now carry that same declaration for the same reason. ⚠ Also caught here: my AST probe scored test_check_freshness and test_job_log at 0 tests / 0 asserts. Both use a module-level `check(name, got, want)` helper — no `def test_*`, no `assert` — so a well-formed 0 for suites of 163 and 229 lines carrying 28 and 46 controls. Caught only because 0 was implausible. check-tools-index 0 · three suites 0 · all three compile. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01DTMf4EvaTEnDKXY47efRZZ --- tools/check-freshness.py | 10 ++++++++++ tools/gh-complete.py | 10 ++++++++++ tools/job-log.py | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/tools/check-freshness.py b/tools/check-freshness.py index 8291ea7..690d1a3 100644 --- a/tools/check-freshness.py +++ b/tools/check-freshness.py @@ -45,6 +45,16 @@ change and cannot speak to now. Re-running is what produces current evidence; this only refuses to let old evidence pose as it. """ + +# NO-SELF-TEST: controlled by tools/test_check_freshness.py, which the CI glob gates and which +# passes on main (28 controls). ⛔ This is a DECLARATION of where the control lives, +# not a claim that none exists — tools/README.md records two control conventions in +# one directory (`--self-test` and `test_*.py`). +# +# ⚠ WHY THIS TOOL HAS NO `--self-test`: a completedAt boundary is pure arithmetic, so the controls drive classify() with +# synthetic instants and need no forge. +# ⇒ Before this line existed the gate reported it UNESTABLISHED — correctly, because +# nothing told the gate where to look. The control was there the whole time. import argparse, json, subprocess, sys from datetime import datetime, timezone diff --git a/tools/gh-complete.py b/tools/gh-complete.py index e8b8b51..0acc2cf 100644 --- a/tools/gh-complete.py +++ b/tools/gh-complete.py @@ -32,6 +32,16 @@ Exit: 0 complete, JSON on stdout · 1 TRUNCATED — the reading is a prefix 2 established nothing (call failed, or the shape is not a counted list) """ + +# NO-SELF-TEST: controlled by tools/test_gh_complete.py, which the CI glob gates and which +# passes on main (18 controls). ⛔ This is a DECLARATION of where the control lives, +# not a claim that none exists — tools/README.md records two control conventions in +# one directory (`--self-test` and `test_*.py`). +# +# ⚠ WHY THIS TOOL HAS NO `--self-test`: it FORWARDS its flags to `gh`, so a `--self-test` argv would be handed to gh and +# come back as gh's usage block — an argv surface it cannot own. +# ⇒ Before this line existed the gate reported it UNESTABLISHED — correctly, because +# nothing told the gate where to look. The control was there the whole time. import json import re import subprocess diff --git a/tools/job-log.py b/tools/job-log.py index 4796ff4..c590a6d 100644 --- a/tools/job-log.py +++ b/tools/job-log.py @@ -47,6 +47,16 @@ so is a genuinely short job log, and picking a threshold invents a boundary the data does not have. The timestamp is a property of the format, not of the length. """ + +# NO-SELF-TEST: controlled by tools/test_job_log.py, which the CI glob gates and which +# passes on main (46 controls). ⛔ This is a DECLARATION of where the control lives, +# not a claim that none exists — tools/README.md records two control conventions in +# one directory (`--self-test` and `test_*.py`). +# +# ⚠ WHY THIS TOOL HAS NO `--self-test`: its subject is a log BODY, so the controls feed it real captured bytes rather than +# reaching a runner. +# ⇒ Before this line existed the gate reported it UNESTABLISHED — correctly, because +# nothing told the gate where to look. The control was there the whole time. import argparse, json, os, re, subprocess, sys, types _here = os.path.dirname(os.path.abspath(__file__)) From f8faf5f49cfad7fa9634e563f9a039b7e81f5547 Mon Sep 17 00:00:00 2001 From: Jonathan Borduas Date: Sun, 6 Sep 2026 02:51:09 +0100 Subject: [PATCH 2/2] review: date the control counts, and stop implying an inert declaration worked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two findings from CodeRabbit on #602, both correct, both verified before adopting. 1 ⛔ MAJOR — the comment implied the declaration fixed the gate. It does not. The tail I shipped read: ⇒ Before this line existed the gate reported it UNESTABLISHED — correctly, because nothing told the gate where to look. The control was there the whole time. True of gh-complete. FALSE of check-freshness and job-log, which take required arguments and reach the cannot-invoke-bare branch at gate-selftests.sh:272 — which returns before DECLARES_NONE is consulted at :340. Two-poled: with the line present and with it renamed, the gate emits IDENTICAL BYTES. ⇒ Those two now say so outright: an external control EXISTS and is gated; the gate cannot SEE it; those are two different facts and a reader must not infer the second from the first. #603 carries the mismatch. ⚠ This is the exact defect class I spent today cataloguing, committed by me in a comment ABOUT a label that gets misread: a true-sounding sentence a reader infers a false state from. The reviewer caught in one pass what I had just written three issue comments about. 2 ⚠ MINOR — "28 controls" carried no measurement date. CLAUDE.md's own rule: a number without a date is a rumour. All three counts now carry the date, the method (AST — ast.Call to `check`, because a line-anchored grep scored these same suites at ZERO), and the validator. ⇒ gh-complete's tail states its MEASURED EFFECT (UNESTABLISHED -> declared) rather than the generic claim, since for it the declaration is honoured. Gate reading unchanged by this edit: 60 subjects, 3 UNESTABLISHED. check-tools-index 0 · three suites 0 · all three compile. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01DTMf4EvaTEnDKXY47efRZZ --- tools/check-freshness.py | 14 +++++++++++--- tools/gh-complete.py | 8 +++++--- tools/job-log.py | 14 +++++++++++--- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/tools/check-freshness.py b/tools/check-freshness.py index 690d1a3..98b5428 100644 --- a/tools/check-freshness.py +++ b/tools/check-freshness.py @@ -47,14 +47,22 @@ """ # NO-SELF-TEST: controlled by tools/test_check_freshness.py, which the CI glob gates and which -# passes on main (28 controls). ⛔ This is a DECLARATION of where the control lives, +# passes on main — 28 controls, counted by AST (ast.Call to `check`), measured +# 2026-09-06 at origin/main by `python3 tools/test_check_freshness.py` exit 0 in the gating job. ⛔ This is a DECLARATION of where the control lives, # not a claim that none exists — tools/README.md records two control conventions in # one directory (`--self-test` and `test_*.py`). # # ⚠ WHY THIS TOOL HAS NO `--self-test`: a completedAt boundary is pure arithmetic, so the controls drive classify() with # synthetic instants and need no forge. -# ⇒ Before this line existed the gate reported it UNESTABLISHED — correctly, because -# nothing told the gate where to look. The control was there the whole time. +# ⛔ THIS DECLARATION DOES NOT CHANGE THE GATE'S VERDICT, AND SAYING SO IS THE POINT. +# This tool takes REQUIRED ARGUMENTS, so it reaches the cannot-invoke-bare branch at +# gate-selftests.sh:272, which returns before `DECLARES_NONE` is consulted at :340. +# Measured 2026-09-06, two-poled: with this line present and with it renamed, the gate +# emits IDENTICAL BYTES and this tool REMAINS UNESTABLISHED. +# ⇒ So: an external control EXISTS and is gated; the gate cannot SEE it. Those are +# two different facts and a reader must not infer the second from the first. +# The mismatch — the gate names this line as the remedy on a path that ignores it — +# is nForma-AI/nForma-NEXT#603, not this file's to fix. import argparse, json, subprocess, sys from datetime import datetime, timezone diff --git a/tools/gh-complete.py b/tools/gh-complete.py index 0acc2cf..4bfc1f6 100644 --- a/tools/gh-complete.py +++ b/tools/gh-complete.py @@ -34,14 +34,16 @@ """ # NO-SELF-TEST: controlled by tools/test_gh_complete.py, which the CI glob gates and which -# passes on main (18 controls). ⛔ This is a DECLARATION of where the control lives, +# passes on main — 18 controls, counted by AST (ast.Call to `check`), measured +# 2026-09-06 at origin/main by `python3 tools/test_gh_complete.py` exit 0 in the gating job. ⛔ This is a DECLARATION of where the control lives, # not a claim that none exists — tools/README.md records two control conventions in # one directory (`--self-test` and `test_*.py`). # # ⚠ WHY THIS TOOL HAS NO `--self-test`: it FORWARDS its flags to `gh`, so a `--self-test` argv would be handed to gh and # come back as gh's usage block — an argv surface it cannot own. -# ⇒ Before this line existed the gate reported it UNESTABLISHED — correctly, because -# nothing told the gate where to look. The control was there the whole time. +# ⇒ MEASURED EFFECT: before this line the gate reported UNESTABLISHED; with it the +# gate reports `declared NO self-test`. This tool reaches the flag-REJECTED branch, +# where the declaration IS consulted (gate-selftests.sh:340). Measured 2026-09-06. import json import re import subprocess diff --git a/tools/job-log.py b/tools/job-log.py index c590a6d..c025f56 100644 --- a/tools/job-log.py +++ b/tools/job-log.py @@ -49,14 +49,22 @@ """ # NO-SELF-TEST: controlled by tools/test_job_log.py, which the CI glob gates and which -# passes on main (46 controls). ⛔ This is a DECLARATION of where the control lives, +# passes on main — 46 controls, counted by AST (ast.Call to `check`), measured +# 2026-09-06 at origin/main by `python3 tools/test_job_log.py` exit 0 in the gating job. ⛔ This is a DECLARATION of where the control lives, # not a claim that none exists — tools/README.md records two control conventions in # one directory (`--self-test` and `test_*.py`). # # ⚠ WHY THIS TOOL HAS NO `--self-test`: its subject is a log BODY, so the controls feed it real captured bytes rather than # reaching a runner. -# ⇒ Before this line existed the gate reported it UNESTABLISHED — correctly, because -# nothing told the gate where to look. The control was there the whole time. +# ⛔ THIS DECLARATION DOES NOT CHANGE THE GATE'S VERDICT, AND SAYING SO IS THE POINT. +# This tool takes REQUIRED ARGUMENTS, so it reaches the cannot-invoke-bare branch at +# gate-selftests.sh:272, which returns before `DECLARES_NONE` is consulted at :340. +# Measured 2026-09-06, two-poled: with this line present and with it renamed, the gate +# emits IDENTICAL BYTES and this tool REMAINS UNESTABLISHED. +# ⇒ So: an external control EXISTS and is gated; the gate cannot SEE it. Those are +# two different facts and a reader must not infer the second from the first. +# The mismatch — the gate names this line as the remedy on a path that ignores it — +# is nForma-AI/nForma-NEXT#603, not this file's to fix. import argparse, json, os, re, subprocess, sys, types _here = os.path.dirname(os.path.abspath(__file__))