[Bug] Auto-mode classifier judges command form, not effect: dry-runs blocked while allowlisted equivalents with larger blast radius pass; denials stack into the 5-consecutive lockout
Summary
The auto-mode permission classifier judges Bash commands by their surface form, not their effect, which produces repeated false-positive denials on benign commands — including read-only dry-runs — while the identical effect passes instantly when phrased through an allowlisted command. In longer autonomous runs the denials stack into the "N consecutive actions were blocked" lockout banner, derailing plan-mode/auto-mode sessions (in our case, mid-way through authoring a new agent skill).
Related: #78192 (over-triggering, general), #78344 (5-denials-one-task shape). This report adds the form-vs-effect inconsistency and dry-run evidence.
Environment
- Claude Code CLI, auto mode (default permission mode), Linux (Ubuntu, kernel 6.17)
- Observed across 7+ sessions, 2026-07-16 → 2026-07-19, same machine
Reproduction (representative, from real transcripts)
- In auto mode, have the agent clean up retired directories that contain only git-ignored
__pycache__artifacts:
rm -rf skills/a skills/b skills/c …→ BLOCKED (bulk-deletion shape)git clean -ndX skills/→ BLOCKED — note-n: this is a dry run, a pure read-only listing of ignored filesfind skills -type d -name __pycache__ -prune -exec rm -rf {} +→ ALLOWED instantly (the project hadBash(find:*)inpermissions.allow, which skips the classifier)
The third command deletes strictly more than the first two would have shown/removed. Same effect, opposite verdicts, decided by phrasing.
- Other benign-intent denials from the same period:
pip install --user --break-system-packages <pkg>(flagged for the flag's name during a version-validation task), asedcleanup of merge-conflict markers in a lockfile (flagged as irreversible destruction —git checkout --of the same file would have been equally destructive and likely unflagged). - After several denials in a row the session surfaces: "Auto mode classifier requires confirmation for this command. 5 consecutive actions were blocked. Please review the transcript before continuing." — at which point an autonomous run (ours was creating a plan for a new skill) is effectively dead until a human intervenes.
What went wrong
- Effect-blind form matching: a dry-run (
git clean -n…) cannot be destructive, yet is blocked; a narrowfind -exec rmwith larger blast radius passes because a broad allowlist rule (find:*) bypasses classification entirely. - Denials compound instead of converging: the denial text tells the agent to try "other tools that might naturally accomplish this goal", but each rephrasing risks another denial → the N-consecutive lockout. There is no "confirm once for this narrow goal" path in-band.
- Asymmetric incentives: the practical fix users discover is adding broad
permissions.allowrules (e.g.find:*,bash:*), which removes the classifier from exactly the commands it was judging — the safety outcome is worse than a well-targeted confirmation would have been.
Expected
- Dry-run / list-only flags (
-n,--dry-run,--check) on otherwise-destructive commands should classify as reads. - Consider effect-level classification for common deletion shapes (paths under
/tmp/session scratch vs repo paths; git-ignored artifacts vs tracked files). - After a denial, offer a one-shot in-band confirmation ("allow this specific command once") instead of pushing agents toward rephrasing-roulette and users toward broad allowlists.
Impact
Autonomous/plan-mode runs stall mid-task; users respond by adding broad allowlist rules that bypass the classifier wholesale, reducing net safety.