|
1 | 1 | #!/usr/bin/env bash |
2 | 2 | # check-freeze.sh — PreToolUse hook for /freeze skill |
3 | 3 | # Reads JSON from stdin, checks if file_path is within the freeze boundary. |
4 | | -# Returns {"permissionDecision":"deny","message":"..."} to block, or {} to allow. |
| 4 | +# Returns hookSpecificOutput with permissionDecision "deny" to block, or {} to allow. |
5 | 5 | set -euo pipefail |
6 | 6 |
|
7 | 7 | # Read stdin |
8 | 8 | INPUT=$(cat) |
9 | 9 |
|
10 | | -# Locate the freeze directory state file |
11 | | -STATE_DIR="${CLAUDE_PLUGIN_DATA:-$HOME/.gstack}" |
| 10 | +# Locate the freeze directory state file via gstack-paths for consistent resolution |
| 11 | +# across GSTACK_HOME / CLAUDE_PLUGIN_DATA / $HOME/.gstack fallback chain. |
| 12 | +_PATHS_BIN="" |
| 13 | +for _p in \ |
| 14 | + "${CLAUDE_SKILL_DIR:-}/../gstack/bin/gstack-paths" \ |
| 15 | + "$HOME/.claude/skills/gstack/bin/gstack-paths"; do |
| 16 | + [ -x "$_p" ] && { _PATHS_BIN="$_p"; break; } |
| 17 | +done |
| 18 | + |
| 19 | +if [ -n "$_PATHS_BIN" ]; then |
| 20 | + eval "$("$_PATHS_BIN" 2>/dev/null)" 2>/dev/null || true |
| 21 | + STATE_DIR="${GSTACK_STATE_ROOT:-${CLAUDE_PLUGIN_DATA:-$HOME/.gstack}}" |
| 22 | +else |
| 23 | + STATE_DIR="${CLAUDE_PLUGIN_DATA:-$HOME/.gstack}" |
| 24 | +fi |
| 25 | + |
12 | 26 | FREEZE_FILE="$STATE_DIR/freeze-dir.txt" |
13 | 27 |
|
14 | 28 | # If no freeze file exists, allow everything (not yet configured) |
@@ -74,6 +88,7 @@ case "$FILE_PATH" in |
74 | 88 | mkdir -p ~/.gstack/analytics 2>/dev/null || true |
75 | 89 | echo '{"event":"hook_fire","skill":"freeze","pattern":"boundary_deny","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || echo "unknown")'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true |
76 | 90 |
|
77 | | - printf '{"permissionDecision":"deny","message":"[freeze] Blocked: %s is outside the freeze boundary (%s). Only edits within the frozen directory are allowed."}\n' "$FILE_PATH" "$FREEZE_DIR" |
| 91 | + _REASON=$(printf '[freeze] Blocked: %s is outside the freeze boundary (%s). Only edits within the frozen directory are allowed.' "$FILE_PATH" "$FREEZE_DIR" | sed 's/"/\\"/g') |
| 92 | + printf '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"%s"}}\n' "$_REASON" |
78 | 93 | ;; |
79 | 94 | esac |
0 commit comments