fix(analyzer,monitor): EXIT_SIGNAL detection and monitor paths (v0.10.1)

Fixes #113 - EXIT_SIGNAL not detected in JSON output format
Fixes #117 - ralph_monitor.sh uses wrong paths after v0.10.0 migration

Bug fixes:
- Parse EXIT_SIGNAL from .result field when Claude CLI returns JSON format
- Add safety circuit breaker: force exit after 5 consecutive completion indicators
- Fix checkbox parsing for indented markdown with POSIX [[:space:]]* pattern
- Update ralph_monitor.sh paths: status.json, logs/ralph.log, progress.json

Files changed:
- lib/response_analyzer.sh: Extract RALPH_STATUS from embedded .result text
- ralph_loop.sh: Safety circuit breaker + indented checkbox patterns
- ralph_monitor.sh: All paths updated for .ralph/ subfolder
- create_files.sh: Indented checkbox pattern consistency
- README.md: v0.10.1 changelog, version bump, test count update
- CLAUDE.md: Version bump to v0.10.1

All 310 tests pass.
This commit is contained in:
Test User 2026-01-21 21:31:50 -07:00
parent 9b19d70e35
commit da1aed34c6
6 changed files with 68 additions and 18 deletions

View file

@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
This is the Ralph for Claude Code repository - an autonomous AI development loop system that enables continuous development cycles with intelligent exit detection and rate limiting.
**Version**: v0.10.0 | **Tests**: 310 passing (100% pass rate) | **CI/CD**: GitHub Actions
**Version**: v0.10.1 | **Tests**: 310 passing (100% pass rate) | **CI/CD**: GitHub Actions
## Core Architecture

View file

@ -2,8 +2,8 @@
[![CI](https://github.com/frankbria/ralph-claude-code/actions/workflows/test.yml/badge.svg)](https://github.com/frankbria/ralph-claude-code/actions/workflows/test.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
![Version](https://img.shields.io/badge/version-0.10.0-blue)
![Tests](https://img.shields.io/badge/tests-308%20passing-green)
![Version](https://img.shields.io/badge/version-0.10.1-blue)
![Tests](https://img.shields.io/badge/tests-310%20passing-green)
[![GitHub Issues](https://img.shields.io/github/issues/frankbria/ralph-claude-code)](https://github.com/frankbria/ralph-claude-code/issues)
[![Mentioned in Awesome Claude Code](https://awesome.re/mentioned-badge.svg)](https://github.com/hesreallyhim/awesome-claude-code)
[![Follow on X](https://img.shields.io/twitter/follow/FrankBria18044?style=social)](https://x.com/FrankBria18044)
@ -16,9 +16,9 @@ Ralph is an implementation of the Geoffrey Huntley's technique for Claude Code t
## Project Status
**Version**: v0.10.0 - Active Development
**Version**: v0.10.1 - Active Development
**Core Features**: Working and tested
**Test Coverage**: 308 tests, 100% pass rate
**Test Coverage**: 310 tests, 100% pass rate
### What's Working Now
- Autonomous development loops with intelligent exit detection
@ -36,10 +36,26 @@ Ralph is an implementation of the Geoffrey Huntley's technique for Claude Code t
- PRD import functionality
- **CI/CD pipeline with GitHub Actions**
- **Dedicated uninstall script for clean removal**
- 308 passing tests across 11 test files
- 310 passing tests across 11 test files
### Recent Improvements
**v0.10.1 - Bug Fixes & Monitor Path Corrections**
- Fixed `ralph_monitor.sh` hardcoded paths for v0.10.0 compatibility:
- `STATUS_FILE`: `status.json``.ralph/status.json`
- `LOG_FILE`: `logs/ralph.log``.ralph/logs/ralph.log`
- `progress.json``.ralph/progress.json`
- Fixed EXIT_SIGNAL parsing in JSON format (Bug #1):
- Now extracts `EXIT_SIGNAL` from `.result` field when Claude CLI returns JSON
- Properly detects RALPH_STATUS blocks embedded in JSON response text
- Added safety circuit breaker (Bug #2):
- Force exit after 5 consecutive completion indicators (prevents infinite loops)
- Higher threshold than normal (2) to avoid false positives while preventing API waste
- Fixed checkbox parsing for indented markdown (Bug #3):
- Changed patterns from `^- \[` to `^[[:space:]]*- \[` (POSIX-compliant)
- Supports indented checkboxes in `@fix_plan.md`
- Updated README.md documentation example for new log path
**v0.10.0 - .ralph/ Subfolder Structure (BREAKING CHANGE)**
- **Breaking**: Moved all Ralph-specific files to `.ralph/` subfolder
- Project root stays clean: only `src/`, `README.md`, and user files remain
@ -584,7 +600,7 @@ Shows real-time:
ralph --status
# Manual log inspection
tail -f logs/ralph.log
tail -f .ralph/logs/ralph.log
```
### Common Issues

View file

@ -204,9 +204,10 @@ should_exit_gracefully() {
fi
# 4. Check fix_plan.md for completion
# Bug #3 Fix: Support indented markdown checkboxes with [[:space:]]* pattern
if [[ -f "$RALPH_DIR/@fix_plan.md" ]]; then
local total_items=$(grep -c "^- \[" "$RALPH_DIR/@fix_plan.md" 2>/dev/null || echo "0")
local completed_items=$(grep -c "^- \[x\]" "$RALPH_DIR/@fix_plan.md" 2>/dev/null || echo "0")
local total_items=$(grep -cE "^[[:space:]]*- \[" "$RALPH_DIR/@fix_plan.md" 2>/dev/null || echo "0")
local completed_items=$(grep -cE "^[[:space:]]*- \[x\]" "$RALPH_DIR/@fix_plan.md" 2>/dev/null || echo "0")
if [[ $total_items -gt 0 ]] && [[ $completed_items -eq $total_items ]]; then
log_status "WARN" "Exit condition: All fix_plan.md items completed ($completed_items/$total_items)"

View file

@ -89,6 +89,27 @@ parse_json_response() {
# Exit signal: from flat format OR derived from completion_status
local exit_signal=$(jq -r '.exit_signal // false' "$output_file" 2>/dev/null)
# Bug #1 Fix: If exit_signal is still false, check for RALPH_STATUS block in .result field
# Claude CLI JSON format embeds the RALPH_STATUS block within the .result text field
if [[ "$exit_signal" == "false" && "$has_result_field" == "true" ]]; then
local result_text=$(jq -r '.result // ""' "$output_file" 2>/dev/null)
if [[ -n "$result_text" ]] && echo "$result_text" | grep -q -- "---RALPH_STATUS---"; then
# Extract EXIT_SIGNAL value from RALPH_STATUS block within result text
local embedded_exit_sig=$(echo "$result_text" | grep "EXIT_SIGNAL:" | cut -d: -f2 | xargs)
if [[ "$embedded_exit_sig" == "true" ]]; then
exit_signal="true"
[[ "${VERBOSE_PROGRESS:-}" == "true" ]] && echo "DEBUG: Extracted EXIT_SIGNAL=true from .result RALPH_STATUS block" >&2
fi
# Also check STATUS field as fallback
local embedded_status=$(echo "$result_text" | grep "STATUS:" | cut -d: -f2 | xargs)
if [[ "$embedded_status" == "COMPLETE" && "$exit_signal" != "true" ]]; then
# STATUS: COMPLETE without explicit EXIT_SIGNAL implies completion
exit_signal="true"
[[ "${VERBOSE_PROGRESS:-}" == "true" ]] && echo "DEBUG: Inferred EXIT_SIGNAL=true from .result STATUS=COMPLETE" >&2
fi
fi
fi
# Work type: from flat format
local work_type=$(jq -r '.work_type // "UNKNOWN"' "$output_file" 2>/dev/null)

View file

@ -313,7 +313,17 @@ should_exit_gracefully() {
return 0
fi
# 3. Strong completion indicators (only if Claude's EXIT_SIGNAL is true)
# 3. Safety circuit breaker - force exit after 5 consecutive completion indicators
# Bug #2 Fix: Prevents infinite loops when EXIT_SIGNAL is not explicitly set
# but completion patterns clearly indicate work is done. Threshold of 5 is higher
# than normal threshold (2) to avoid false positives while preventing API waste.
if [[ $recent_completion_indicators -ge 5 ]]; then
log_status "WARN" "🚨 SAFETY CIRCUIT BREAKER: Force exit after 5 consecutive completion indicators ($recent_completion_indicators)" >&2
echo "safety_circuit_breaker"
return 0
fi
# 4. Strong completion indicators (only if Claude's EXIT_SIGNAL is true)
# This prevents premature exits when heuristics detect completion patterns
# but Claude explicitly indicates work is still in progress via RALPH_STATUS block.
# The exit_signal in .response_analysis represents Claude's explicit intent.
@ -330,10 +340,11 @@ should_exit_gracefully() {
log_status "INFO" "DEBUG: Completion indicators ($recent_completion_indicators) present but EXIT_SIGNAL=false, continuing..." >&2
fi
# 4. Check fix_plan.md for completion
# 5. Check fix_plan.md for completion
# Bug #3 Fix: Support indented markdown checkboxes with [[:space:]]* pattern
if [[ -f "$RALPH_DIR/@fix_plan.md" ]]; then
local total_items=$(grep -c "^- \[" "$RALPH_DIR/@fix_plan.md" 2>/dev/null)
local completed_items=$(grep -c "^- \[x\]" "$RALPH_DIR/@fix_plan.md" 2>/dev/null)
local total_items=$(grep -cE "^[[:space:]]*- \[" "$RALPH_DIR/@fix_plan.md" 2>/dev/null)
local completed_items=$(grep -cE "^[[:space:]]*- \[x\]" "$RALPH_DIR/@fix_plan.md" 2>/dev/null)
# Handle case where grep returns no matches (exit code 1)
[[ -z "$total_items" ]] && total_items=0
@ -445,8 +456,9 @@ build_loop_context() {
context="Loop #${loop_count}. "
# Extract incomplete tasks from @fix_plan.md
# Bug #3 Fix: Support indented markdown checkboxes with [[:space:]]* pattern
if [[ -f "$RALPH_DIR/@fix_plan.md" ]]; then
local incomplete_tasks=$(grep -c "^- \[ \]" "$RALPH_DIR/@fix_plan.md" 2>/dev/null || echo "0")
local incomplete_tasks=$(grep -cE "^[[:space:]]*- \[ \]" "$RALPH_DIR/@fix_plan.md" 2>/dev/null || echo "0")
context+="Remaining tasks: ${incomplete_tasks}. "
fi

View file

@ -3,8 +3,8 @@
# Ralph Status Monitor - Live terminal dashboard for the Ralph loop
set -e
STATUS_FILE="status.json"
LOG_FILE="logs/ralph.log"
STATUS_FILE=".ralph/status.json"
LOG_FILE=".ralph/logs/ralph.log"
REFRESH_INTERVAL=2
# Colors
@ -74,8 +74,8 @@ display_status() {
fi
# Claude Code Progress section
if [[ -f "progress.json" ]]; then
local progress_data=$(cat "progress.json" 2>/dev/null)
if [[ -f ".ralph/progress.json" ]]; then
local progress_data=$(cat ".ralph/progress.json" 2>/dev/null)
local progress_status=$(echo "$progress_data" | jq -r '.status // "idle"' 2>/dev/null || echo "idle")
if [[ "$progress_status" == "executing" ]]; then