claude-harness/hooks/require-plan.sh

25 lines
1.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# PreToolUse hook: edits under src/ require a plan for this branch or a .bounded marker.
set -euo pipefail
input=$(cat)
read -r cwd fpath < <(printf '%s' "$input" | python3 -c '
import sys,json
d=json.load(sys.stdin); ti=d.get("tool_input",{}) or {}
print(d.get("cwd",""), ti.get("file_path") or ti.get("path") or "")' 2>/dev/null || echo " ")
[ -n "$cwd" ] && [ -n "$fpath" ] || exit 0
root=$(git -C "$cwd" rev-parse --show-toplevel 2>/dev/null || true)
[ -n "$root" ] || exit 0
case "$fpath" in
"$root"/src/*|src/*) ;;
*) exit 0 ;;
esac
[ -f "$root/.bounded" ] && exit 0
branch=$(git -C "$cwd" branch --show-current 2>/dev/null || true)
if ls "$root"/docs/superpowers/plans/*.md >/dev/null 2>&1; then
if [ -z "$branch" ] || grep -lq -- "$branch" "$root"/docs/superpowers/plans/*.md 2>/dev/null; then exit 0; fi
# any plan exists but none names this branch: still allow if only one plan (single-feature repo)
[ "$(ls "$root"/docs/superpowers/plans/*.md | wc -l)" -eq 1 ] && exit 0
fi
echo "BLOCKED: editing $fpath without a plan. Run superpowers:brainstorming; for a bounded change create '$root/.bounded' first." >&2
exit 2