Skip to content

chore(lint): refuse cargo test, rg counts, loose nextest in plan gates - #226

Merged
denniyahh merged 1 commit into
developfrom
feature/plan-lint-gate-shapes
Oct 23, 2026
Merged

denniyahh merged 1 commit into
developfrom
feature/plan-lint-gate-shapes

Conversation

@denniyahh

@denniyahh denniyahh commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

Extends scripts/lint-plan-bashisms.sh (the pre-commit scan of staged *PLAN.md files) 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 run without --no-tests=fail, with a positional or -- filter, with more than one -E/--skip, or with a filter that is not exactly test(=...). For example, -E 'test(=real) | test(=wrong)' runs one test and exits 0.
  • rg -c / --count / --count-matches: zero matches print nothing, not 0.
  • -p devflow-cli: no such package; the CLI package is devflow.

A command whose quote never closes is refused as unparsable (fail closed). Each refusal names its fix. plan_bashism_scanner.rs gains cases for each shape. The legit-PLAN.md negative control switches its wrapped command from cargo test to cargo 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

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
@denniyahh
denniyahh merged commit 78fa1bb into develop Oct 23, 2026
13 checks passed
@denniyahh
denniyahh deleted the feature/plan-lint-gate-shapes branch October 23, 2026 00:59

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 t alias 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)

…and 10 more.

· 7 more finding(s) on lines outside this diff (see the check run).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant