Repository navigation
chore(lint): refuse cargo test, rg counts, loose nextest in plan gates - #226
Conversation
The plan lint now splits each command in an <automated> block into words and refuses shapes that shipped false greens or gates that failed correct work: cargo test (a filter matching nothing exits 0); nextest without --no-tests=fail, with a positional filter, more than one filter, or a filter other than exactly test(=path); rg -c and --count; and -p devflow-cli. It reads inside bash -c regions and handles escaped quotes. Three narrower rules it subsumes are removed; their blocked cases stay as tests. CLAUDE.md gains a Repo Traps list. Probed under gawk and under mawk 1.3.4 (the CI image's awk). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0182ocSM2E4fb2zu52jxGLzi
There was a problem hiding this comment.
Graphify reviewed this change.
Code graph out of date: Health delta baseline: last indexed commit 71a5192 (diverged from this PR's base — delta is approximate). Health delta baseline was built by an older engine whose node ids do not match this review's — delta is approximate. Impact and hotspot numbers below may be wrong.
Worth a look — the grounded gate found no coupling regressions or blocking issues, but 2 advisory finding(s) below merit a look before merge.
Not checked: tests were not run; no formal proof of the changed code.
Graphify review — findings
Tightens the plan-bashism scanner so verify gates can no longer ship commands that exit 0 without proving anything: cargo test is refused outright, and cargo nextest run must pass --no-tests=fail with exactly one -E 'test(=module::path::name)' filter and no positional filters. It also refuses any rg count flag (-c, -nc, --count, --count-matches), -p devflow-cli, and a command whose quote never closes. Because the check is a word-level parse that also reads inside bash -c '...' regions, bypasses like global flags before the subcommand, the cargo t alias, and path-qualified invocations are the ways it could still miss a bad command. The test suite now covers each rule with matching accepted forms, and the legit fixture swaps cargo test for cargo build so the negative control still passes.
Worth a look
- Cargo global flags before the subcommand bypass all cargo rules —
scripts/lint-plan-bashisms.sh· Escalate · medium- NOT verified (no proof, no reproducing execution) — needs human review
- Built-in
cargo talias bypasses the cargo-test refusal —scripts/lint-plan-bashisms.sh· Escalate · medium- NOT verified (no proof, no reproducing execution) — needs human review
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 61 functions depend on the 61 functions this change touches.
Health — this change adds coupling hotspots:
- new:
assert_inline_blocked()— 13 callers, 3 callees - new:
assert_blocked()— 7 callers, 3 callees - new:
assert_inline_accepted()— 6 callers, 3 callees - new:
staged_bad_working_tree_clean_is_blocked()— 0 callers, 6 callees - new:
staged_clean_working_tree_bad_is_accepted()— 0 callers, 6 callees - new:
staged_deleted_plan_is_skipped()— 0 callers, 6 callees - new:
staged_renamed_bad_plan_is_blocked()— 0 callers, 6 callees
Verification — 61 functions in the blast radius were not formally verified this run (proofs are advisory here).
Health delta baseline: last indexed commit 71a5192 (diverged from this PR's base — delta is approximate).
Health delta baseline was built by an older engine whose node ids do not match this review's — delta is approximate.
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 61 function(s) in the blast radius were not formally verified this run
Docs that may be stale (advisory)
ARCHITECTURE.md§ The Stage machine (lines 23-54): references changed symbolsgateARCHITECTURE.md§ Hooks (lines 55-86): references changed symbolsgateARCHITECTURE.md§ Completion evaluation (lines 131-160): references changed symbolsgateARCHITECTURE.md§ Gate protocol (lines 206-251): references changed symbolsgateARCHITECTURE.md§ Git and ship model (lines 317-351): references changed symbolsgateCHANGELOG.md§ What's new (lines 223-271): references changed symbolsgateCHANGELOG.md§ 2.2.0 — 2026-07-31 (lines 497-507): references changed symbolsgateCHANGELOG.md§ Behavior change: human-blocking checkpoints are now resolved by the agent (lines 508-532): references changed symbolsgateCHANGELOG.md§ Fixed (lines 558-565): references changed symbolsgateCHANGELOG.md§ Added (lines 566-569): references changed symbolsgate
…and 10 more.
· 7 more finding(s) on lines outside this diff (see the check run).
Extends
scripts/lint-plan-bashisms.sh(the pre-commit scan of staged*PLAN.mdfiles) beyond zsh-unsafe bashisms. Inside<automated>verify blocks it now also refuses command shapes that have shipped a false green, or a gate that fails correct work, in this repo:cargo test: a name filter that matches nothing still exits 0.cargo nextest runwithout--no-tests=fail, with a positional or--filter, with more than one-E/--skip, or with a filter that is not exactlytest(=...). For example,-E 'test(=real) | test(=wrong)'runs one test and exits 0.rg -c/--count/--count-matches: zero matches print nothing, not0.-p devflow-cli: no such package; the CLI package isdevflow.A command whose quote never closes is refused as unparsable (fail closed). Each refusal names its fix.
plan_bashism_scanner.rsgains cases for each shape. Thelegit-PLAN.mdnegative control switches its wrapped command fromcargo testtocargo build, so it stays accepted under the new rule.This content has lived on a personal workspace branch since 2026-10-16 (the patch-id is identical on these three files). It is contributor tooling, so it belongs on
develop.Known and separate: the report cuts each line at 200 characters, path included, so a very long checkout path hides the offending text. That has been the case since 2026-09-06 and is not changed here. It is tracked as a backlog item.
🤖 Generated with Claude Code
https://claude.ai/code/session_01RGzZZbfn3r9638yptqPL47