Repository navigation
fix(hooks): the decision gate judges every language, test file and header (ADR-1060 revision, no exception) - #555
Conversation
…ader Owner ruling of 2026-09-10 on ADR-1060: no exception. Six lines of /// rationale in a tests/*.rs file passed the gate because the language was deferred "until measured", the path was a test root and the run sat before anything executable. Each exemption sufficed alone. - _decision_gate_lex.py: one character-level scanner for the //, /* */, -- and ; families (string literals, Rust raw strings, backtick strings and block comments tracked), covering .rs .js .jsx .ts .tsx .go .java .c .h .cpp .hpp .cc .swift .kt .kts .cs .scala .m .mm .dart .php .sql .lua .hs .el .clj .lisp, plus the full # family (.py via tokenize, the shell family via the heredoc skip, .pl .r .toml .yaml .yml .cfg .ini). The suffix table and the scanner table are one table (LANGUAGES). - decision_gate.py: is_test_path, _TEST_DIRS, _TEST_FILE_RE, _is_header_run and the header boundary are deleted; the refusal states that no header, test file or language is exempt. PROSE_RUN_LIMIT, grandfathering, the source: pointer, fail-open and CORTEX_DECISION_GATE=off stay. - Python: a comment token after code on the same line no longer counts as a comment line, as the scanner's docstring already claimed. - ADR-1060 wiki page: revision section with the leak, what is removed, what stays and the tracked-tree measurement at 8d71210 (1479 files in judged suffixes, 10 with a header run of 8+, all grandfathered); mirror regenerated with scripts/check_project_wiki.py --write. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01LSTGMnuSuUXWs7ZBofW1AW
…ision gate (#555) Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01LSTGMnuSuUXWs7ZBofW1AW
|
ZETETIC-REVIEW: APPROVE Owner ruling implemented: ADR-1060 without exception. mcp_server/hooks/_decision_gate_lex.py lexes the // and /* / family (.rs .js .jsx .ts .tsx .go .java .c .h .cpp .hpp .cc .swift .kt .kts .cs .scala .m .mm .dart .php), -- (.sql .lua .hs), ; (.el .clj .lisp) and the # family, with string literals, raw and backtick strings, char literals and block comments tracked; decision_gate.py drops the test-path and header exemptions and their dead code, keeps PROSE_RUN_LIMIT 8, grandfathering, the source: pointer, fail-open and the explicit CORTEX_DECISION_GATE=off. The canonical page wiki/adr/cortex/1060-.md carries the revision (leak, three reasons, removed, kept, measurement) and the docs/adr mirror is regenerated through scripts/check_project_wiki.py --write. CHANGELOG cites #555. Evidence on head 07059ab: all 24 CI checks green. The owner's own simulation (ten /// lines into tests/rust_local_receiver_static_resolution.rs through scripts/launcher.py) exits 0 on origin/main and exits 2 with the refusal on the branch; new tests 12 failed on origin/main, 78 passed on the branch across both gate files; ruff, craftsmanship, pyright (0 errors), doc-claims, project-wiki, no-deps and marketplace-pins gates all exit 0. Measurement: 10 tracked files carry a header run of 8+ lines, all grandfathered, nothing in the tree is blocked. One narrowing recorded in the ADR: a Python comment after code on the same line no longer counts as a comment line, consistent with every other scanner. Merging; release 4.21.0 follows so installs receive the gate. |
The decision gate judges every language, test file and header (ADR-1060 revision 2026-09-10, no exception, #555): // and /* */, --, ; and # comment families, no test-path or header exemption, PROSE_RUN_LIMIT unchanged at 8, grandfathering and the explicit override kept. Every version surface moves to 4.21.0 (pyproject, plugin and marketplace manifests, server.json, manifest.json, package.json and lock, gemini and codex manifests, badge, uv.lock, README alt text) and the hypermnesia-mcp-viz pin moves to v3.2.0 (2482563172c0f02a1c022b82cb4e38299b7748b4, cortex-viz #156: the Wiki view lists project wikis, where project_root ADRs actually live). Claude-Session: https://claude.ai/code/session_01LSTGMnuSuUXWs7ZBofW1AW Co-authored-by: Claude Fable 5.1 <[email protected]>
Summary
Implements the owner ruling of 2026-09-10 on ADR-1060 ("Révision de l'ADR-1060, pas d'exception"). On 2026-09-10 six lines of
///rationale were written intoai-architect-mcp-codebase/tests/rust_local_receiver_static_resolution.rsandmcp_server/hooks/decision_gate.pylet them through, because each of its three exemptions sufficed alone://languages were deferred "until measured", the path was under a test root, and the run sat before anything executable. All three exemptions are removed. The gate now judges every comment-marker language (#,//and/* */,--,;), test files and header blocks alike.PROSE_RUN_LIMIT(8), grandfathering of blocks already in the file, thesource:pointer line, fail-open on unreadable input and the explicitCORTEX_DECISION_GATE=offoverride are unchanged.No issue is linked: the owner ruling is recorded in the canonical wiki page
wiki/adr/cortex/1060-*.md(section "Revision 2026-09-10 — no exception"), with the read-only mirrordocs/adr/ADR-1060-*.mdregenerated throughscripts/check_project_wiki.py --write.Closes #N/A (owner ruling, no issue)
Type of change
What changed
mcp_server/hooks/_decision_gate_lex.py: one character-level scanner (_Scanner) for the//,--and;families that tracks quoted strings (single-line unless the language lets them span lines; backtick and Rustr#"..."#raw strings always), character literals (so a Rust lifetime'adoes not open a string) and block comments; every line a block comment crosses is a comment line, a line holding code is never one. Python stays ontokenize, the shell family keeps its heredoc skip.LANGUAGESis the single table of suffix, refusal marker and scanner, covering.py .sh .bash .zsh .rb .pl .r .toml .yaml .yml .cfg .ini .rs .js .jsx .ts .tsx .go .java .c .h .cpp .hpp .cc .swift .kt .kts .cs .scala .m .mm .dart .php .sql .lua .hs .el .clj .lisp.mcp_server/hooks/decision_gate.py:is_test_path,_TEST_DIRS,_TEST_FILE_RE,_is_header_runand the header boundary are deleted; suffix lookup is case-insensitive; the refusal states that no header, test file or language is exempt. One narrowing on Python: a comment token after code on the same line (x = 1 # note) no longer counts as a comment line, which is what the scanner's docstring already claimed.tests_py/hooks/test_decision_gate.pyflips the former exemption tests to refusals and adds the grandfathered-header case;tests_py/hooks/test_decision_gate_languages.pypins the Rusttests/*.rs///case (direct and through the process entry point),//in.ts/.go,/* */in.java, a 10-line header on a new.py,//text and a block comment inside Rust string literals (not comments), the 7-line run, grandfathering in.go,source:lines, the override, every declared suffix, lifetimes, unterminated block comments and trailing comments.Gate
The owner's simulation (a PreToolUse Edit event on stdin adding ten
///lines totests/rust_local_receiver_static_resolution.rs, throughpython3 scripts/launcher.py mcp_server.hooks.decision_gate):8d71210f:exit=0(allowed)[decision-gate] BLOCKED: .../tests/rust_local_receiver_static_resolution.rs:3 would add 10 consecutive comment lines. ... No header, test file or language is exempt (ADR-1060, revision 2026-09-10).then... leave only// source: ADR-NNNNhere ...,exit=2tests_py/hooks/test_decision_gate_languages.pyon origin/main (detached worktree at8d71210f, the module-level parametrize overlex.LANGUAGESstripped because it cannot collect there):12 failed, 5 passed; the 5 that pass are the ALLOW-shaped invariants (string literals, the 7-line run, grandfathering, pointer lines). On the branch:78 passedacross both gate test files.Measurement (header exemption removal)
Tracked tree at
8d71210f, every file whose suffix the gate now judges, scanned with the revised lexer. A header run is a run of 8+ comment lines preceded only by blank lines, comment lines, a shebang, a shellsetline or the Python module docstring..py.sh.yml.sql.yaml.toml.jsTen files carry a header run at or over the threshold (for example
benchmarks/reproduce.sh,scripts/install-plugin.sh,scripts/phase_0_4_5_backfill.sql,tests_js/spatial_hash.test.js). All are grandfathered: editing them elsewhere is allowed. Nothing in the tree is blocked by the ruling; the number is recorded in the ADR for the owner to decide on.Test plan
pytest tests_py/hooks/= 465 passed (13 subtests).test_decision_gate_languages.pyplus the flipped and added cases intest_decision_gate.py(78 total across the two files).LANGUAGESfailstest_every_declared_suffix_is_enforced; re-adding a test-path or header exemption fails the flipped tests; treating a string body as a comment fails the two Rust string tests; dropping the char-literal rule fails the lifetime test; counting trailing comments fails the trailing-comment test. Not caught: a scanner that mis-lexes a literal form no test uses (a C++R"(...)"raw string, for instance); that fails open, never closed, and the ADR records it as a risk accepted.python -m mcp_server.hooks.decision_gaterather thanscripts/launcher.py, because the launcher runsensure_deps(<repo>/deps)first and pip-installs the base packages over the network when that directory is empty (which it is in CI); a unit test must not perform that install.Gates as CI runs them (final state)
ruff check .andruff format --check .(ruff 0.16.6 fromrequirements/lint.txt): cleanpython scripts/check_craftsmanship.py: OKpython scripts/check_project_wiki.py: mirrors matchpython scripts/check_doc_claims.py: OKpython scripts/check_no_deps_invariant.py: cleanpython3 scripts/check_marketplace_pins.py: all pins current (untouched)uv sync ... --group typecheck,.venv/bin/python -m pyright mcp_server/): exit 0Audit notes
Coding-standards compliance
anyin production code._decision_gate_lex.py257,decision_gate.py177).# source:annotation (PROSE_RUN_LIMIT, unchanged).🤖 Generated with Claude Code
https://claude.ai/code/session_01LSTGMnuSuUXWs7ZBofW1AW