Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 33 additions & 7 deletions ralph_loop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,8 @@ execute_claude_code() {
log_status "WARN" "Could not find result message in stream output"
# Keep stream output as-is for debugging
fi
# Clean up temporary stream log after extraction
rm -f "$stream_output_file"
fi
else
# BACKGROUND MODE: Original behavior with progress monitoring
Expand Down Expand Up @@ -1314,6 +1316,7 @@ execute_claude_code() {

# Get PID and monitor progress
local claude_pid=$!
_CLAUDE_PID=$claude_pid
local progress_counter=0

# Early failure detection: if the command doesn't exist or fails immediately,
Expand Down Expand Up @@ -1389,6 +1392,7 @@ EOF
# Wait for the process to finish and get exit code
wait $claude_pid
exit_code=$?
_CLAUDE_PID=""
fi

if [ $exit_code -eq 0 ]; then
Expand Down Expand Up @@ -1518,17 +1522,35 @@ EOF

# Cleanup function
cleanup() {
log_status "INFO" "Ralph loop interrupted. Cleaning up..."
reset_session "manual_interrupt"
update_status "$loop_count" "$(cat "$CALL_COUNT_FILE" 2>/dev/null || echo "0")" "interrupted" "stopped"
exit 0
local trap_exit_code=${1:-$?}
# Reentrancy guard — prevent double execution from EXIT + signal combination
if [[ "$_CLEANUP_DONE" == "true" ]]; then return; fi
_CLEANUP_DONE=true

# Kill background Claude process if still running
if [[ -n "$_CLAUDE_PID" ]] && kill -0 "$_CLAUDE_PID" 2>/dev/null; then
kill "$_CLAUDE_PID" 2>/dev/null || true
wait "$_CLAUDE_PID" 2>/dev/null || true
fi
_CLAUDE_PID=""

# Only record "interrupted" status for abnormal exits (non-zero exit code)
# Normal exit (code 0) preserves the status already written by the main loop
if [[ $loop_count -gt 0 && $trap_exit_code -ne 0 ]]; then
log_status "INFO" "Ralph loop interrupted. Cleaning up..."
reset_session "manual_interrupt"
update_status "$loop_count" "$(cat "$CALL_COUNT_FILE" 2>/dev/null || echo "0")" "interrupted" "stopped"
fi
# No exit here — EXIT trap handles natural termination
}

# Set up signal handlers
trap cleanup SIGINT SIGTERM
# Set up signal handlers — EXIT covers SIGINT, SIGTERM, set -e errors, and normal exit
trap 'cleanup $?' EXIT

# Global variable for loop count (needed by cleanup function)
# Global variables for cleanup
loop_count=0
_CLAUDE_PID=""
_CLEANUP_DONE=false

# Main loop
main() {
Expand Down Expand Up @@ -1600,6 +1622,10 @@ main() {
# Initialize session tracking before entering the loop
init_session_tracking

# Reset stale exit signals from previous session (SIGKILL/OOM recovery)
echo '{"test_only_loops": [], "done_signals": [], "completion_indicators": []}' > "$EXIT_SIGNALS_FILE"
rm -f "$RALPH_DIR/.response_analysis"

log_status "INFO" "Starting main loop..."

while true; do
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_session_continuity.bats
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ function_exists_in_ralph() {

@test "cleanup function includes session reset" {
# Check if cleanup function includes reset_session
run grep -A5 'cleanup()' "${BATS_TEST_DIRNAME}/../../ralph_loop.sh"
run grep -A20 'cleanup()' "${BATS_TEST_DIRNAME}/../../ralph_loop.sh"

[[ "$output" == *"reset_session"* ]] || skip "Cleanup session reset not yet implemented"
}
Expand Down
Loading