2026-03-17 19:58:30 +08:00
#!/bin/bash
# stop hook: run required repo verification commands for agent-driven changes
set -u
mode = " ${ AGENT_VERIFY_MODE :- strict } "
if [ " ${ 1 :- } " = "--advisory" ] ; then
mode = "advisory"
shift
fi
2026-07-03 13:58:36 +07:00
input = " $( cat) "
# Avoid infinite stop loops: when a previous blocking verify already forced the
# agent to continue, Claude Code/Codex set stop_hook_active on the next Stop.
if command -v jq >/dev/null 2>& 1; then
if [ " $( printf '%s' " $input " | jq -r '.stop_hook_active // false' 2>/dev/null) " = "true" ] ; then
exit 0
fi
fi
2026-03-17 19:58:30 +08:00
cd " $( git rev-parse --show-toplevel 2>/dev/null || pwd ) " || exit 0
2026-07-03 13:58:36 +07:00
# Read-only sessions change nothing; skip the expensive full verification.
if git rev-parse --is-inside-work-tree >/dev/null 2>& 1 && [ -z " $( git status --porcelain 2>/dev/null) " ] ; then
echo "Working tree clean; skipping verification."
exit 0
fi
2026-03-17 19:58:30 +08:00
cleanup_generated_dir() {
local path = " $1 "
if ! git rev-parse --is-inside-work-tree >/dev/null 2>& 1; then
return
fi
if git ls-files --error-unmatch " $path " >/dev/null 2>& 1; then
if git diff --quiet -- " $path " ; then
return
fi
echo "=== git restore --worktree $path ==="
git restore --worktree -- " $path " 2>& 1 || true
echo ""
return
fi
if [ -e " $path " ] ; then
echo "=== rm -rf $path ==="
rm -rf " $path " 2>& 1 || true
echo ""
fi
}
run_required_check() {
local label = " $1 "
shift
echo "=== $label ==="
if " $@ " 2>& 1; then
echo ""
return 0
fi
echo ""
return 1
}
echo "Running build, lint, type-check, and security audit..."
echo ""
failures = 0
2026-03-19 13:41:03 +08:00
run_required_check "corepack yarn build" corepack yarn build || failures = 1
run_required_check "corepack yarn lint" corepack yarn lint || failures = 1
run_required_check "corepack yarn type-check" corepack yarn type-check || failures = 1
2026-03-17 19:58:30 +08:00
2026-03-19 13:41:03 +08:00
echo "=== corepack yarn npm audit ==="
corepack yarn npm audit 2>& 1 || true
2026-03-17 19:58:30 +08:00
echo ""
cleanup_generated_dir build
cleanup_generated_dir dist
if [ " $failures " -ne 0 ] ; then
if [ " $mode " = "advisory" ] ; then
echo "Verification failed, but AGENT_VERIFY_MODE=advisory so the hook is exiting 0."
exit 0
fi
2026-07-03 13:58:36 +07:00
# Exit 2 is the only exit code that blocks the stop and feeds the reason back
# to the agent in Claude Code and Codex; exit 1 would be a silent, non-blocking
# error. The full logs are on stdout above; keep the stderr reason short.
echo "Verification failed: build, lint, or type-check reported errors (see hook output). Fix them before finishing, or rerun with AGENT_VERIFY_MODE=advisory to intentionally stop on a broken tree." >& 2
exit 2
2026-03-17 19:58:30 +08:00
fi
echo "Verification complete."
exit 0