@@ -72,7 +72,6 @@ parse_json_response() {
7272
7373 # Detect JSON format by checking for Claude CLI fields
7474 local has_result_field=$( jq -r ' has("result")' " $output_file " 2> /dev/null)
75- local has_session_id_field=$( jq -r ' has("sessionId")' " $output_file " 2> /dev/null)
7675
7776 # Extract fields - support both flat format and Claude CLI format
7877 # Priority: Claude CLI fields first, then flat format fields
@@ -94,6 +93,10 @@ parse_json_response() {
9493 local files_modified=$( jq -r ' .metadata.files_changed // .files_modified // 0' " $output_file " 2> /dev/null)
9594
9695 # Error count: from flat format OR derived from metadata.has_errors
96+ # Note: When only has_errors=true is present (without explicit error_count),
97+ # we set error_count=1 as a minimum. This is defensive programming since
98+ # the stuck detection threshold is >5 errors, so 1 error won't trigger it.
99+ # Actual error count may be higher, but precise count isn't critical for our logic.
97100 local error_count=$( jq -r ' .error_count // 0' " $output_file " 2> /dev/null)
98101 local has_errors=$( jq -r ' .metadata.has_errors // false' " $output_file " 2> /dev/null)
99102 if [[ " $has_errors " == " true" && " $error_count " == " 0" ]]; then
@@ -232,9 +235,10 @@ analyze_response() {
232235 local json_confidence=$( jq -r ' .confidence' .json_parse_result 2> /dev/null || echo " 0" )
233236 local session_id=$( jq -r ' .session_id' .json_parse_result 2> /dev/null || echo " " )
234237
235- # Persist session ID if present
238+ # Persist session ID if present (for session continuity across loop iterations)
236239 if [[ -n " $session_id " && " $session_id " != " null" ]]; then
237240 store_session_id " $session_id "
241+ [[ " ${VERBOSE_PROGRESS:- } " == " true" ]] && echo " DEBUG: Persisted session ID: $session_id " >&2
238242 fi
239243
240244 # JSON parsing provides high confidence
@@ -567,8 +571,8 @@ detect_stuck_loop() {
567571# SESSION MANAGEMENT FUNCTIONS
568572# =============================================================================
569573
570- # Session file location
571- SESSION_FILE=" .session_id "
574+ # Session file location - standardized across ralph_loop.sh and response_analyzer.sh
575+ SESSION_FILE=" .claude_session_id "
572576# Session expiration time in seconds (24 hours)
573577SESSION_EXPIRATION_SECONDS=86400
574578
@@ -628,16 +632,24 @@ should_resume_session() {
628632 local session_time
629633
630634 # Parse ISO timestamp to epoch - try multiple formats for cross-platform compatibility
635+ # Strip milliseconds if present (e.g., 2026-01-09T10:30:00.123+00:00 → 2026-01-09T10:30:00+00:00)
636+ local clean_timestamp=" ${timestamp} "
637+ if [[ " $timestamp " =~ \. [0-9]+[+-Z] ]]; then
638+ clean_timestamp=$( echo " $timestamp " | sed ' s/\.[0-9]*\([+-Z]\)/\1/' )
639+ fi
640+
631641 if command -v gdate & > /dev/null; then
632642 # macOS with coreutils
633- session_time=$( gdate -d " $timestamp " +%s 2> /dev/null)
643+ session_time=$( gdate -d " $clean_timestamp " +%s 2> /dev/null)
634644 elif date --version 2>&1 | grep -q GNU; then
635645 # GNU date (Linux)
636- session_time=$( date -d " $timestamp " +%s 2> /dev/null)
646+ session_time=$( date -d " $clean_timestamp " +%s 2> /dev/null)
637647 else
638648 # BSD date (macOS without coreutils) - try parsing ISO format
639- # Format: 2026-01-09T10:30:00+00:00 or similar
640- session_time=$( date -j -f " %Y-%m-%dT%H:%M:%S" " ${timestamp% [+-]* } " +%s 2> /dev/null)
649+ # Format: 2026-01-09T10:30:00+00:00 or 2026-01-09T10:30:00Z
650+ # Strip timezone suffix for BSD date parsing
651+ local date_only=" ${clean_timestamp% [+-Z]* } "
652+ session_time=$( date -j -f " %Y-%m-%dT%H:%M:%S" " $date_only " +%s 2> /dev/null)
641653 fi
642654
643655 # If we couldn't parse the timestamp, consider session expired
0 commit comments