100 lines
3.2 KiB
Bash
Executable File
100 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# session-start.sh - SessionStart hook for claude-handoff plugin
|
|
#
|
|
# PURPOSE:
|
|
# Injects pre-generated handoff content after `/compact handoff:<goal>`
|
|
# completes. Content was generated by PreCompact hook using --fork-session.
|
|
#
|
|
# HOOK EVENT: SessionStart (matcher: "compact")
|
|
# - Fires when sessions continue after compact operations (NOT new sessions!)
|
|
# - Receives: session_id, transcript_path, cwd, source ("compact")
|
|
#
|
|
# BEHAVIOR:
|
|
# - Checks for handoff content saved by pre-compact.sh
|
|
# - Injects handoff_content as systemMessage
|
|
# - Cleans up state file after successful injection
|
|
#
|
|
# TESTING:
|
|
# 1. Enable debug logging in hooks/lib/logging.sh (set LOGGING_ENABLED=true)
|
|
# 2. Run: /compact handoff:implement feature X
|
|
# 3. Compact completes, session continues
|
|
# 4. Check logs:
|
|
# tail -f /tmp/handoff-sessionstart.log
|
|
# 5. Verify handoff appears as system message in continuing session
|
|
# 6. Check state file cleaned up on success:
|
|
# ls -la .git/handoff-pending/ # should not exist after successful handoff
|
|
#
|
|
# MANUAL TESTING WITH FAKE STATE:
|
|
# # Create fake state with pre-generated content
|
|
# mkdir -p .git/handoff-pending
|
|
# echo '{"handoff_content":"## Goal\nTest\n## Context\n- Item 1","goal":"test","trigger":"manual","type":"compact"}' > .git/handoff-pending/handoff-context.json
|
|
#
|
|
# # Run hook
|
|
# echo '{"session_id":"test-123","cwd":"'$(pwd)'","source":"compact"}' | bash session-start.sh
|
|
#
|
|
# # Check output contains systemMessage with handoff content
|
|
# # Cleanup
|
|
# rm -rf .git/handoff-pending
|
|
#
|
|
# EXIT BEHAVIOR:
|
|
# - Returns JSON with systemMessage if handoff content exists
|
|
# - Exits silently (exit 0, no output) if no handoff state found
|
|
#
|
|
set -euo pipefail
|
|
|
|
# Load logging module
|
|
source "${BASH_SOURCE%/*}/../lib/logging.sh"
|
|
init_logging "sessionstart"
|
|
|
|
# Read hook input
|
|
input=$(cat)
|
|
session_id=$(echo "$input" | jq -r '.session_id // ""')
|
|
cwd=$(echo "$input" | jq -r '.cwd // "."')
|
|
source=$(echo "$input" | jq -r '.source // "unknown"')
|
|
|
|
log "Received input: session_id=$session_id cwd=$cwd source=$source"
|
|
|
|
# Only proceed if this is a compact-triggered session continuation
|
|
if [[ "$source" != "compact" ]]; then
|
|
log "Source is '$source', not 'compact'. Exiting."
|
|
exit 0
|
|
fi
|
|
|
|
# Change to project directory
|
|
cd "$cwd" || exit 0
|
|
|
|
# Check for pending handoff state
|
|
state_file=".git/handoff-pending/handoff-context.json"
|
|
|
|
if [[ ! -f "$state_file" ]]; then
|
|
log "No state file found, exiting"
|
|
exit 0
|
|
fi
|
|
|
|
log "Found state file: $state_file"
|
|
|
|
# Read pre-generated handoff content
|
|
handoff_content=$(cat "$state_file" | jq -r '.handoff_content // ""')
|
|
goal=$(cat "$state_file" | jq -r '.goal // ""')
|
|
|
|
log "State: goal='$goal' content_length=${#handoff_content} chars"
|
|
|
|
# If no handoff content, exit without cleanup (might be old state format)
|
|
if [[ -z "$handoff_content" ]]; then
|
|
log "No handoff_content in state file, exiting"
|
|
exit 0
|
|
fi
|
|
|
|
# Cleanup: remove both file and directory
|
|
rm -f "$state_file"
|
|
rmdir .git/handoff-pending 2>/dev/null || true
|
|
|
|
log "Injecting handoff content as systemMessage"
|
|
|
|
# Return JSON with systemMessage to inject into session
|
|
jq -n --arg context "$handoff_content" '{
|
|
systemMessage: $context
|
|
}'
|
|
|
|
exit 0
|