harb/onchain/.claude/hooks/supervisor/on-stop.sh
openhands b7260b2eaf chore: analysis tooling, research artifacts, and code quality
- Analysis: parameter sweep scripts, adversarial testing, 2D frontier maps
- Research: KRAIKEN_RESEARCH_REPORT, SECURITY_REVIEW, STORAGE_LAYOUT
- FuzzingBase: consolidated fuzzing helper, BackgroundLP simulation
- Sweep results: CSV data for full 4D sweep (1050 combos), bull-bear,
  AS sweep, VWAP fix validation
- Code quality: .gitignore for fuzz CSVs, gas snapshot, updated docs
- Remove dead analysis helpers (CSVHelper, CSVManager, ScenarioRecorder)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:22:03 +00:00

71 lines
2.4 KiB
Bash
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# Claude Code Stop hook — fires when the agent finishes responding.
#
# Option D: bash pre-filter first, LLM triage only for ambiguous cases.
#
# Known Stop event fields:
# session_id, transcript_path, cwd, permission_mode,
# hook_event_name ("Stop"), stop_hook_active
#
# Note: stop_reason is NOT provided in the Stop event JSON.
# We detect state by inspecting the tmux pane instead.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SUPERVISOR_DIR="${SCRIPT_DIR%/hooks}"
INPUT=$(cat)
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"')
CWD=$(echo "$INPUT" | jq -r '.cwd // "unknown"')
# Find matching supervised session
STATE_FILE="${CCS_STATE_FILE:-${HOME}/.openclaw/workspace/supervisor-state.json}"
if [ ! -f "$STATE_FILE" ]; then
exit 0 # No supervised sessions
fi
SOCKET=$(jq -r --arg cwd "$CWD" '
.sessions | to_entries[] | select(.value.projectDir == $cwd and .value.status == "running") | .value.socket
' "$STATE_FILE" 2>/dev/null || echo "")
TMUX_SESSION=$(jq -r --arg cwd "$CWD" '
.sessions | to_entries[] | select(.value.projectDir == $cwd and .value.status == "running") | .value.tmuxSession
' "$STATE_FILE" 2>/dev/null || echo "")
# No matching supervised session for this project
if [ -z "$SOCKET" ] || [ -z "$TMUX_SESSION" ]; then
exit 0
fi
# Can we reach the tmux session?
if [ ! -S "$SOCKET" ] || ! tmux -S "$SOCKET" has-session -t "$TMUX_SESSION" 2>/dev/null; then
exit 0
fi
PANE_OUTPUT=$(tmux -S "$SOCKET" capture-pane -p -J -t "$TMUX_SESSION" -S -30 2>/dev/null || echo "")
# Bash pre-filter: check the last few lines for patterns
# Check for API errors (transient — always triage)
if echo "$PANE_OUTPUT" | tail -10 | grep -qiE "API Error: 5[0-9][0-9]|internal.server.error|api_error"; then
"$SUPERVISOR_DIR/triage.sh" "stopped:api_error" "$CWD" "$PANE_OUTPUT" &
exit 0
fi
# Check for rate limiting
if echo "$PANE_OUTPUT" | tail -10 | grep -qiE "429|rate.limit"; then
echo "[$(date -u +%FT%TZ)] RATE_LIMITED | stop | $CWD" >> "${CCS_LOG_FILE:-/tmp/ccs-triage.log}"
exit 0
fi
# Check if shell prompt is back (Claude Code exited)
if echo "$PANE_OUTPUT" | tail -5 | grep -qE '^\$ |^ [^/]|^% |^[a-z]+@.*\$ '; then
# Prompt returned — agent might be done or crashed. Triage it.
"$SUPERVISOR_DIR/triage.sh" "stopped:prompt_back" "$CWD" "$PANE_OUTPUT" &
exit 0
fi
# No prompt back, no errors — agent is likely mid-conversation. Skip silently.
exit 0