The command line has joints
A shell command is not one flat string. Bash identifies assignments and redirections before expansion. It can join commands with operators, put them in groups, and pass them through wrappers. A permission matcher has to preserve the command that matters while it reads that structure.
Claude Code's permission documentation says compound commands are split into separate commands for matching. The same page warns that wrappers can hide the command behind them. Release 2.1.289 fixed cases involving an expanded environment-variable prefix, a bare assignment before a command, and a nested part of a compound command.
Do not test the rule with the clean command. Test every place the command can hide.
This is not a reason to abandon shell permissions. It is a reason to treat the rule set like code. Pin the agent version. Keep a small pack of commands that must ask or stop. Run it after upgrades, settings changes, and sandbox changes.
If policy should block rm -rf build, test that exact action alone, after an assignment, after an allowed command, inside a group, and behind each wrapper your team permits. Add the observed prompt or refusal to the receipt.