9 new cases locking in the behavior added by the previous two
commits. Each was verified to fail before the fix and pass after.
Greptile — quote-aware depth counting:
- blocks $(echo ")"; (npm run dev))
- blocks (echo ")"; npm run dev)
- allows $(echo "(npm run dev)") — () inside double-quoted body is literal
Greptile — brace groups:
- blocks { npm run dev; }
- blocks echo hi && { npm run dev; }
- allows {npm run dev} — bash brace-group syntax requires a space after {
CodeRabbit — missing package-manager variants:
- blocks yarn run dev (yarn 1.x convention)
- blocks bun dev (bun bare form)
CodeRabbit nitpick — symmetric quote test:
- blocks echo "$(npm run dev)" — double-quoted substitution still substitutes
The `{npm run dev}` allow case is intentional: bash treats `{` as
a reserved word only when followed by whitespace. The pre-fix code
already passed this through, but until now we never asserted it,
so a future change to brace handling could silently start blocking
literal `{npm` tokens.
Lock in the behavior added by the previous commit. Each new case was
verified to fail before the fix and pass after.
Bypasses now blocked (exit 2):
- \$(npm run dev) command substitution
- \`npm run dev\` backtick substitution
- echo \$(npm run dev) substitution inside an argument
- (npm run dev) plain subshell group
- \$(echo a; npm run dev) substitution containing a sequenced segment
- (pnpm dev) plain subshell group, alt package manager
Allow cases — explicitly proven NOT to regress so the fix doesn't
over-block legitimate uses:
- (tmux new-session -d -s dev "npm run dev") tmux launcher inside ()
- git commit -m '(npm run dev)' literal in single quotes
- echo "(npm run dev)" literal in double quotes
(bash does NOT subshell () inside double quotes)
- git commit -m '\$(npm run dev) fix' literal in single quotes
Single- and double-quote allow cases are important: they distinguish a
real subshell construct from one that's just text inside a string,
which is what `extractSubshellGroups` / `extractCommandSubstitutions`
quote-awareness is for.