diff options
Diffstat (limited to 'hooks/ai-wrap-teardown.sh')
| -rwxr-xr-x | hooks/ai-wrap-teardown.sh | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/hooks/ai-wrap-teardown.sh b/hooks/ai-wrap-teardown.sh index 6133075..ca73ae6 100755 --- a/hooks/ai-wrap-teardown.sh +++ b/hooks/ai-wrap-teardown.sh @@ -39,8 +39,10 @@ # "command": "~/.claude/hooks/ai-wrap-teardown.sh" } ] } ] set -u +payload="$(cat)" + # Stop-hook stdin JSON carries cwd; basename it to the project / aiv- session. -cwd="$(jq -r '.cwd // empty' 2>/dev/null)" +cwd="$(printf '%s' "$payload" | jq -r '.cwd // empty' 2>/dev/null)" [ -z "$cwd" ] && cwd="$PWD" proj="$(basename "$cwd")" @@ -53,15 +55,54 @@ fire() { emacsclient -e "$1" >/dev/null 2>&1 || true } +# A sentinel means wrap-up claimed completion. Re-prove that claim immediately +# before consuming it: the certificate binds a prior strict check to HEAD, and +# verify also performs a fresh strict check to catch late writes. +verify_wrap() { + local gate="${GIT_WORKTREE_GATE:-}" detail + if [ -z "$gate" ]; then + gate="$(command -v git-worktree-gate 2>/dev/null || true)" + fi + if [ -z "$gate" ] || [ ! -x "$gate" ]; then + gate="$HOME/code/rulesets/claude-templates/bin/git-worktree-gate" + fi + if [ ! -x "$gate" ]; then + detail="wrap blocked: git-worktree-gate is unavailable; install rulesets tooling and retry" + else + detail="$("$gate" verify "$cwd" 2>&1)" && return 0 + fi + + # Codex and Claude consume different Stop-hook response fields. Codex + # command-hook payloads always include model; Claude's do not. + if printf '%s' "$payload" | jq -e '.model? != null' >/dev/null 2>&1; then + jq -n --arg reason "$detail" \ + '{continue:false, stopReason:$reason, systemMessage:$reason}' + else + jq -n --arg reason "$detail" \ + '{decision:"block", reason:$reason}' + fi + return 1 +} + +consume_certificate() { + local dir + dir="$(git -C "$cwd" rev-parse --absolute-git-dir 2>/dev/null)" || return 0 + rm -f "$dir/ai-wrap-clean" +} + # Shutdown supersedes teardown when both are somehow present. if [ -f "$shutdown_sentinel" ]; then + verify_wrap || exit 0 rm -f "$shutdown_sentinel" "$teardown_sentinel" + consume_certificate fire '(cj/ai-term-shutdown-countdown)' exit 0 fi if [ -f "$teardown_sentinel" ]; then + verify_wrap || exit 0 rm -f "$teardown_sentinel" + consume_certificate fire "(cj/ai-term-quit \"${proj}\")" exit 0 fi |
