Merge pull request #166 from frankbria/fix/live-mode-text-format-164
fix(live-mode): crash with text output format (#164)
This commit is contained in:
commit
57deaaaf55
3 changed files with 124 additions and 16 deletions
|
|
@ -169,7 +169,7 @@ tmux attach -t <session-name>
|
|||
|
||||
### Running Tests
|
||||
```bash
|
||||
# Run all tests (484 tests)
|
||||
# Run all tests (490 tests)
|
||||
npm test
|
||||
|
||||
# Run specific test suites
|
||||
|
|
@ -214,7 +214,7 @@ CLAUDE_MIN_VERSION="2.0.76" # Minimum Claude CLI version
|
|||
```
|
||||
|
||||
**CLI Options:**
|
||||
- `--output-format json|text` - Set Claude output format (default: json)
|
||||
- `--output-format json|text` - Set Claude output format (default: json). Note: `--live` mode requires JSON and will auto-switch from text to json.
|
||||
- `--allowed-tools "Write,Read,Bash(git *)"` - Restrict allowed tools
|
||||
- `--no-continue` - Disable session continuity, start fresh each loop
|
||||
|
||||
|
|
@ -445,13 +445,13 @@ Ralph uses advanced error detection with two-stage filtering to eliminate false
|
|||
|
||||
## Test Suite
|
||||
|
||||
### Test Files (484 tests total)
|
||||
### Test Files (490 tests total)
|
||||
|
||||
| File | Tests | Description |
|
||||
|------|-------|-------------|
|
||||
| `test_circuit_breaker_recovery.bats` | 19 | Cooldown timer, auto-reset, parse_iso_to_epoch, CLI flag (Issue #160) |
|
||||
| `test_cli_parsing.bats` | 35 | CLI argument parsing for all flags + monitor parameter forwarding |
|
||||
| `test_cli_modern.bats` | 33 | Modern CLI commands (Phase 1.1) + build_claude_command fix |
|
||||
| `test_cli_modern.bats` | 39 | Modern CLI commands (Phase 1.1) + build_claude_command fix + live mode text format fix (#164) |
|
||||
| `test_json_parsing.bats` | 52 | JSON output format parsing + Claude CLI format + session management + array format |
|
||||
| `test_session_continuity.bats` | 44 | Session lifecycle management + expiration + circuit breaker integration + issue #91 fix |
|
||||
| `test_exit_detection.bats` | 53 | Exit signal detection + EXIT_SIGNAL-based completion indicators + progress detection |
|
||||
|
|
|
|||
|
|
@ -1048,21 +1048,24 @@ execute_claude_code() {
|
|||
session_id=$(init_claude_session)
|
||||
fi
|
||||
|
||||
# Live mode requires JSON output (stream-json) — override text format
|
||||
if [[ "$LIVE_OUTPUT" == "true" && "$CLAUDE_OUTPUT_FORMAT" == "text" ]]; then
|
||||
log_status "WARN" "Live mode requires JSON output format. Overriding text → json for this session."
|
||||
CLAUDE_OUTPUT_FORMAT="json"
|
||||
fi
|
||||
|
||||
# Build the Claude CLI command with modern flags
|
||||
# Note: We use the modern CLI with -p flag when CLAUDE_OUTPUT_FORMAT is "json"
|
||||
# For backward compatibility, fall back to stdin piping for text mode
|
||||
local use_modern_cli=false
|
||||
|
||||
if [[ "$CLAUDE_OUTPUT_FORMAT" == "json" ]]; then
|
||||
# Modern approach: use CLI flags (builds CLAUDE_CMD_ARGS array)
|
||||
if build_claude_command "$PROMPT_FILE" "$loop_context" "$session_id"; then
|
||||
use_modern_cli=true
|
||||
log_status "INFO" "Using modern CLI mode (JSON output)"
|
||||
else
|
||||
log_status "WARN" "Failed to build modern CLI command, falling back to legacy mode"
|
||||
fi
|
||||
if build_claude_command "$PROMPT_FILE" "$loop_context" "$session_id"; then
|
||||
use_modern_cli=true
|
||||
log_status "INFO" "Using modern CLI mode (${CLAUDE_OUTPUT_FORMAT} output)"
|
||||
else
|
||||
log_status "INFO" "Using legacy CLI mode (text output)"
|
||||
log_status "WARN" "Failed to build modern CLI command, falling back to legacy mode"
|
||||
if [[ "$LIVE_OUTPUT" == "true" ]]; then
|
||||
log_status "ERROR" "Live mode requires a built Claude command. Falling back to background mode."
|
||||
LIVE_OUTPUT=false
|
||||
fi
|
||||
fi
|
||||
|
||||
# Execute Claude Code
|
||||
|
|
@ -1091,6 +1094,14 @@ execute_claude_code() {
|
|||
fi
|
||||
fi
|
||||
|
||||
if [[ "$LIVE_OUTPUT" == "true" ]]; then
|
||||
# Safety check: live mode requires a successfully built modern command
|
||||
if [[ "$use_modern_cli" != "true" || ${#CLAUDE_CMD_ARGS[@]} -eq 0 ]]; then
|
||||
log_status "ERROR" "Live mode requires a built Claude command. Falling back to background mode."
|
||||
LIVE_OUTPUT=false
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$LIVE_OUTPUT" == "true" ]]; then
|
||||
log_status "INFO" "📺 Live output mode enabled - showing Claude Code streaming..."
|
||||
echo -e "${PURPLE}━━━━━━━━━━━━━━━━ Claude Code Output ━━━━━━━━━━━━━━━━${NC}"
|
||||
|
|
@ -1613,7 +1624,7 @@ Options:
|
|||
-s, --status Show current status and exit
|
||||
-m, --monitor Start with tmux session and live monitor (requires tmux)
|
||||
-v, --verbose Show detailed progress updates during execution
|
||||
-l, --live Show Claude Code output in real-time (streaming mode)
|
||||
-l, --live Show Claude Code output in real-time (auto-switches to JSON output)
|
||||
-t, --timeout MIN Set Claude Code execution timeout in minutes (default: $CLAUDE_TIMEOUT_MINUTES)
|
||||
--reset-circuit Reset circuit breaker to CLOSED state
|
||||
--circuit-status Show circuit breaker status and exit
|
||||
|
|
@ -1622,6 +1633,7 @@ Options:
|
|||
|
||||
Modern CLI Options (Phase 1.1):
|
||||
--output-format FORMAT Set Claude output format: json or text (default: $CLAUDE_OUTPUT_FORMAT)
|
||||
Note: --live mode requires JSON and will auto-switch
|
||||
--allowed-tools TOOLS Comma-separated list of allowed tools (default: $CLAUDE_ALLOWED_TOOLS)
|
||||
--no-continue Disable session continuity across loops
|
||||
--session-expiry HOURS Set session expiration time in hours (default: $CLAUDE_SESSION_EXPIRY_HOURS)
|
||||
|
|
|
|||
|
|
@ -667,3 +667,99 @@ EOF
|
|||
[[ "$output" == *'_env_MAX_CALLS_PER_HOUR'* ]]
|
||||
[[ "$output" == *'_env_CLAUDE_TIMEOUT_MINUTES'* ]]
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# LIVE MODE + TEXT FORMAT FIX TESTS (Issue #164)
|
||||
# Tests for: live mode format override, always-call build_claude_command,
|
||||
# and safety check for empty CLAUDE_CMD_ARGS
|
||||
# =============================================================================
|
||||
|
||||
@test "build_claude_command works for text format (populates CLAUDE_CMD_ARGS)" {
|
||||
export CLAUDE_CODE_CMD="claude"
|
||||
export CLAUDE_OUTPUT_FORMAT="text"
|
||||
export CLAUDE_ALLOWED_TOOLS="Write,Read"
|
||||
export CLAUDE_USE_CONTINUE="false"
|
||||
|
||||
echo "Test prompt content" > "$PROMPT_FILE"
|
||||
|
||||
build_claude_command "$PROMPT_FILE" "" ""
|
||||
|
||||
# CLAUDE_CMD_ARGS should be populated even in text mode
|
||||
[[ ${#CLAUDE_CMD_ARGS[@]} -gt 0 ]]
|
||||
|
||||
local cmd_string="${CLAUDE_CMD_ARGS[*]}"
|
||||
|
||||
# Should contain claude command and -p flag
|
||||
[[ "$cmd_string" == *"claude"* ]]
|
||||
[[ "$cmd_string" == *"-p"* ]]
|
||||
[[ "$cmd_string" == *"Test prompt content"* ]]
|
||||
|
||||
# Should NOT contain --output-format (text mode omits it)
|
||||
[[ "$cmd_string" != *"--output-format"* ]]
|
||||
|
||||
# Should still include allowed tools
|
||||
[[ "$cmd_string" == *"--allowedTools"* ]]
|
||||
[[ "$cmd_string" == *"Write"* ]]
|
||||
}
|
||||
|
||||
@test "build_claude_command works for json format (includes --output-format json)" {
|
||||
export CLAUDE_CODE_CMD="claude"
|
||||
export CLAUDE_OUTPUT_FORMAT="json"
|
||||
export CLAUDE_ALLOWED_TOOLS=""
|
||||
export CLAUDE_USE_CONTINUE="false"
|
||||
|
||||
echo "Test prompt" > "$PROMPT_FILE"
|
||||
|
||||
build_claude_command "$PROMPT_FILE" "" ""
|
||||
|
||||
local cmd_string="${CLAUDE_CMD_ARGS[*]}"
|
||||
|
||||
# Should contain --output-format json
|
||||
[[ "$cmd_string" == *"--output-format"* ]]
|
||||
[[ "$cmd_string" == *"json"* ]]
|
||||
[[ "$cmd_string" == *"-p"* ]]
|
||||
}
|
||||
|
||||
@test "live mode overrides text to json format in ralph_loop.sh" {
|
||||
# Verify ralph_loop.sh contains the live mode format override logic
|
||||
run grep -A3 'LIVE_OUTPUT.*true.*CLAUDE_OUTPUT_FORMAT.*text' "${BATS_TEST_DIRNAME}/../../ralph_loop.sh"
|
||||
|
||||
# Should find the override block
|
||||
[[ "$output" == *"CLAUDE_OUTPUT_FORMAT"* ]]
|
||||
[[ "$output" == *"json"* ]]
|
||||
}
|
||||
|
||||
@test "live mode format override preserves json format unchanged" {
|
||||
# The override should only trigger when format is "text", not "json"
|
||||
# Verify the condition checks for text specifically
|
||||
run grep 'CLAUDE_OUTPUT_FORMAT.*text' "${BATS_TEST_DIRNAME}/../../ralph_loop.sh"
|
||||
|
||||
# Should check specifically for "text" (not a blanket override)
|
||||
[[ "$output" == *'"text"'* ]]
|
||||
}
|
||||
|
||||
@test "safety check prevents live mode with empty CLAUDE_CMD_ARGS" {
|
||||
# Verify ralph_loop.sh has the safety check for empty CLAUDE_CMD_ARGS
|
||||
# The check also verifies use_modern_cli is true (not just non-empty array)
|
||||
run grep -A3 'use_modern_cli.*CLAUDE_CMD_ARGS.*-eq 0' "${BATS_TEST_DIRNAME}/../../ralph_loop.sh"
|
||||
|
||||
# Should find safety check that falls back to background mode
|
||||
[[ "$output" == *"LIVE_OUTPUT"* ]] || [[ "$output" == *"background"* ]]
|
||||
}
|
||||
|
||||
@test "build_claude_command is called regardless of output format in ralph_loop.sh" {
|
||||
# Verify that build_claude_command is NOT gated behind JSON-only check
|
||||
# The old pattern was: if [[ "$CLAUDE_OUTPUT_FORMAT" == "json" ]]; then build_claude_command...
|
||||
# The new pattern should call build_claude_command unconditionally
|
||||
|
||||
# Check that build_claude_command call is NOT inside a JSON-only conditional
|
||||
# Look for the actual call site (not the function definition or comments)
|
||||
local script="${BATS_TEST_DIRNAME}/../../ralph_loop.sh"
|
||||
|
||||
# The old pattern: "json" check immediately followed by build_claude_command
|
||||
# should no longer exist as a gate
|
||||
run bash -c "sed -n '/# Build the Claude CLI command/,/# Execute Claude Code/p' '$script' | grep -c 'CLAUDE_OUTPUT_FORMAT.*json.*build_claude_command'"
|
||||
|
||||
# Should find 0 matches (the gate has been removed)
|
||||
[[ "$output" == "0" ]]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue