Records why the v2.0 classifier taxed the user 22 prompts and what changed.
Root cause: v2.0 conflated "contains a redirect character" with "writes
something". `2>&1` is file-descriptor plumbing and `>/dev/null` is a discard —
neither writes. That single mistake caused 16 of the 22 prompts. It was found
by reading ca_decisions.jsonl, not by inspection: the bug was the classifier's
reasoning, so re-reading the code only reproduced it.
v2.1 changes (all evidence-driven, none speculative):
- _SAFE_REDIRECT_RE strips fd plumbing + /dev/null discards before the
redirect check; a redirect to any REAL path still disqualifies, anchored so
`>/dev/nullx` cannot ride the prefix.
- `cd` added to READONLY_ALLOW (no filesystem effect; every other segment must
independently qualify anyway).
- `ssh <host> '<cmd>'` classifies the inner command under identical rules,
depth-limited to one hop.
Verified: 42/42 self-test, e2e ALL PASS, classify() median 0.011ms.
Tier-1 writes deliberately NOT shipped — widen on evidence, not guesses.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- constrained_autonomy_design_decisions.md: D1-D8 locked (hybrid hook
classifier + Agent-Sudo daemon executor, structural classification with
unknown->sandbox, fail-closed, Hermes recovery ladder) + EXECUTION ORDER
with CA-P1a inserted as zero-dependency item 0
- agent_prompts.md shared block: replace "TIER-2 IS BROKEN" with the
corrected root cause (old primary bridge's NTFY endpoint was unreachable;
tier-2 works when the bridge reaches ntfy + user is attended)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>