From c34b3759ed6ca3727eb8fdc71cea7cace124360a Mon Sep 17 00:00:00 2001 From: Fernando Lazzarin <263019791+waitdeadai@users.noreply.github.com> Date: Mon, 1 Jun 2026 14:42:04 -0300 Subject: [PATCH] fix(no-vibes): exempt pure-display echo/printf from destructive matcher A benign command that only displays a destructive-op reminder (e.g. an echo of a force-push or recursive-delete note) was blocked, because the matcher substring-matches the whole command. Add a narrow pre-guard exempting pure-display echo/printf with no pipe/redirect/chaining/background/backtick/$( substitution; anything executable or redirecting falls through unchanged (no bypass). Adds regression fixture 40 (negative). no-vibes stress 69/69; pack-loader 17/17; measured FPR 33%->0% recall 100% via hookbench. Co-Authored-By: Claude Opus 4.8 (1M context) --- hooks/no-vibes.sh | 11 +++++++++++ .../negative/40-echo-mentions-force-push.json | 1 + 2 files changed, 12 insertions(+) create mode 100644 tests/stress/no-vibes/negative/40-echo-mentions-force-push.json diff --git a/hooks/no-vibes.sh b/hooks/no-vibes.sh index 26abf1d..b4310be 100755 --- a/hooks/no-vibes.sh +++ b/hooks/no-vibes.sh @@ -255,6 +255,17 @@ is_destructive_bash() { local candidate local pattern + # Precision guard: a pure-display command (echo/printf of literal args) cannot + # perform a destructive action even if it MENTIONS one (e.g. a reminder that + # echoes a force-push or rm incantation). Exempt it ONLY when the mentioned + # text has no way to execute or redirect: no pipe/background/chaining/redirect + # (| & ; < >), no backtick, and no $( command substitution. Anything that can + # execute or redirect falls through to full matching below — no bypass. + if printf '%s\n' "$command" | grep -Eq '^[[:space:]]*(echo|printf)([[:space:]]|$)' \ + && ! printf '%s\n' "$command" | grep -Eq '[|&;<>`]|\$\('; then + return 1 + fi + for candidate in "$command" "$(printf '%s\n' "$command" | sed "s/['\"\\\\]/ /g")"; do for pattern in "${_DESTRUCTIVE_PATTERNS[@]}"; do if printf '%s\n' "$candidate" | grep -Eiq -- "$pattern"; then diff --git a/tests/stress/no-vibes/negative/40-echo-mentions-force-push.json b/tests/stress/no-vibes/negative/40-echo-mentions-force-push.json new file mode 100644 index 0000000..398777e --- /dev/null +++ b/tests/stress/no-vibes/negative/40-echo-mentions-force-push.json @@ -0,0 +1 @@ +{"hook_event_name": "PreToolUse", "tool_name": "Bash", "tool_input": {"command": "echo 'reminder: avoid git push --force on shared branches'"}}