fix(import): address code review feedback

- Fix check_claude_version() to use numeric semantic version comparison
- Fix detect_response_format() to read first non-whitespace character
- Wire PARSED_RESULT into success message output
- Wire PARSED_FILES_CREATED into file verification logic
- Add --allowedTools flag to CLI invocation using CLAUDE_ALLOWED_TOOLS
- Separate stderr to avoid corrupting JSON output file
- Clean up stderr file on completion and error
- Update README.md version badges to v0.9.8 and 276 tests
- Update roadmap section with current test coverage breakdown
This commit is contained in:
Test User 2026-01-10 11:24:30 -07:00
parent 4b1ca9bcc7
commit 6dde9cbd26
2 changed files with 89 additions and 35 deletions

View file

@ -1,8 +1,8 @@
# Ralph for Claude Code
![Version](https://img.shields.io/badge/version-0.9.3-blue)
![Version](https://img.shields.io/badge/version-0.9.8-blue)
![Status](https://img.shields.io/badge/status-active%20development-yellow)
![Tests](https://img.shields.io/badge/tests-165%20passing-green)
![Tests](https://img.shields.io/badge/tests-276%20passing-green)
![Coverage](https://img.shields.io/badge/coverage-informational-lightgrey)
[![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)
@ -15,9 +15,9 @@ Ralph is an implementation of the Geoffrey Huntley's technique for Claude Code t
## Project Status
**Version**: v0.9.3 - Active Development
**Version**: v0.9.8 - Active Development
**Core Features**: Working and tested
**Test Coverage**: 165 tests, 100% pass rate
**Test Coverage**: 276 tests, 100% pass rate
### What's Working Now
- Autonomous development loops with intelligent exit detection
@ -609,24 +609,25 @@ tmux attach -t <name> # Reattach to detached session
Ralph is under active development with a clear path to v1.0.0. See [IMPLEMENTATION_PLAN.md](IMPLEMENTATION_PLAN.md) for the complete roadmap.
### Current Status: v0.9.3
### Current Status: v0.9.8
**What's Delivered:**
- Core loop functionality with intelligent exit detection
- Rate limiting (100 calls/hour) and circuit breaker pattern
- Response analyzer with semantic understanding
- 165 comprehensive tests (100% pass rate)
- 276 comprehensive tests (100% pass rate)
- tmux integration and live monitoring
- PRD import functionality
- PRD import functionality with modern CLI JSON parsing
- Installation system and project templates
- Modern CLI commands with JSON output support
- CI/CD pipeline with GitHub Actions
- Comprehensive installation test suite
- Session lifecycle management with auto-reset triggers
**Test Coverage Breakdown:**
- Unit Tests: 111 (CLI parsing, JSON, exit detection, rate limiting)
- Integration Tests: 54 (loop execution, edge cases, installation)
- Test Files: 8
- Unit Tests: 154 (CLI parsing, JSON, exit detection, rate limiting, session continuity)
- Integration Tests: 122 (loop execution, edge cases, installation, project setup, PRD import)
- Test Files: 11
### Path to v1.0.0 (~4 weeks)

View file

@ -54,7 +54,8 @@ detect_response_format() {
fi
# Check if file starts with { or [ (JSON indicators)
local first_char=$(head -c 1 "$output_file" 2>/dev/null | tr -d '[:space:]')
# Use grep to find first non-whitespace character (handles leading whitespace)
local first_char=$(grep -m1 -o '[^[:space:]]' "$output_file" 2>/dev/null)
if [[ "$first_char" != "{" && "$first_char" != "[" ]]; then
echo "text"
@ -125,6 +126,7 @@ parse_conversion_response() {
}
# Check Claude Code CLI version for modern features
# Uses numeric comparison for proper semantic versioning
check_claude_version() {
local version
version=$($CLAUDE_CODE_CMD --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
@ -134,9 +136,32 @@ check_claude_version() {
return 1
fi
# Simple version comparison (assumes semantic versioning)
# For production use, consider a more robust version comparison
if [[ "$version" < "$CLAUDE_MIN_VERSION" ]]; then
# Numeric semantic version comparison
# Split versions into major.minor.patch components
local ver_major ver_minor ver_patch
local min_major min_minor min_patch
IFS='.' read -r ver_major ver_minor ver_patch <<< "$version"
IFS='.' read -r min_major min_minor min_patch <<< "$CLAUDE_MIN_VERSION"
# Compare major version
if [[ $ver_major -lt $min_major ]]; then
log "WARN" "Claude Code CLI version $version is below recommended $CLAUDE_MIN_VERSION"
return 1
elif [[ $ver_major -gt $min_major ]]; then
return 0
fi
# Major equal, compare minor version
if [[ $ver_minor -lt $min_minor ]]; then
log "WARN" "Claude Code CLI version $version is below recommended $CLAUDE_MIN_VERSION"
return 1
elif [[ $ver_minor -gt $min_minor ]]; then
return 0
fi
# Minor equal, compare patch version
if [[ $ver_patch -lt $min_patch ]]; then
log "WARN" "Claude Code CLI version $version is below recommended $CLAUDE_MIN_VERSION"
return 1
fi
@ -314,23 +339,31 @@ PROMPTEOF
# Build and execute Claude Code command
# Modern CLI: Use --output-format json and --allowedTools for structured output
# Fallback: Standard CLI invocation for older versions
# Note: stderr is written to separate file to avoid corrupting JSON output
local stderr_file="${CONVERSION_OUTPUT_FILE}.err"
if [[ "$use_modern_cli" == "true" ]]; then
# Modern CLI invocation with JSON output and controlled tool permissions
# Note: --allowedTools permits file operations without user prompts
if $CLAUDE_CODE_CMD --output-format "$CLAUDE_OUTPUT_FORMAT" < "$CONVERSION_PROMPT_FILE" > "$CONVERSION_OUTPUT_FILE" 2>&1; then
# --allowedTools permits file operations without user prompts
if $CLAUDE_CODE_CMD --output-format "$CLAUDE_OUTPUT_FORMAT" --allowedTools $CLAUDE_ALLOWED_TOOLS < "$CONVERSION_PROMPT_FILE" > "$CONVERSION_OUTPUT_FILE" 2> "$stderr_file"; then
cli_exit_code=0
else
cli_exit_code=$?
fi
else
# Standard CLI invocation (backward compatible)
if $CLAUDE_CODE_CMD < "$CONVERSION_PROMPT_FILE" > "$CONVERSION_OUTPUT_FILE" 2>&1; then
if $CLAUDE_CODE_CMD < "$CONVERSION_PROMPT_FILE" > "$CONVERSION_OUTPUT_FILE" 2> "$stderr_file"; then
cli_exit_code=0
else
cli_exit_code=$?
fi
fi
# Log stderr if there was any (for debugging)
if [[ -s "$stderr_file" ]]; then
log "WARN" "CLI stderr output detected (see $stderr_file)"
fi
# Process the response
local output_format="text"
local json_parsed=false
@ -372,36 +405,56 @@ PROMPTEOF
# Check CLI exit code
if [[ $cli_exit_code -ne 0 ]]; then
log "ERROR" "PRD conversion failed (exit code: $cli_exit_code)"
rm -f "$CONVERSION_PROMPT_FILE" "$CONVERSION_OUTPUT_FILE"
rm -f "$CONVERSION_PROMPT_FILE" "$CONVERSION_OUTPUT_FILE" "$stderr_file"
exit 1
fi
log "SUCCESS" "PRD conversion completed"
# Use PARSED_RESULT for success message if available
if [[ "$json_parsed" == "true" && -n "$PARSED_RESULT" && "$PARSED_RESULT" != "null" ]]; then
log "SUCCESS" "PRD conversion completed: $PARSED_RESULT"
else
log "SUCCESS" "PRD conversion completed"
fi
# Clean up temp files
rm -f "$CONVERSION_PROMPT_FILE" "$CONVERSION_OUTPUT_FILE"
rm -f "$CONVERSION_PROMPT_FILE" "$CONVERSION_OUTPUT_FILE" "$stderr_file"
# Verify files were created
# Use PARSED_FILES_CREATED from JSON if available, otherwise check filesystem
local missing_files=()
local created_files=()
local expected_files=("PROMPT.md" "@fix_plan.md" "specs/requirements.md")
if [[ -f "PROMPT.md" ]]; then
created_files+=("PROMPT.md")
else
missing_files+=("PROMPT.md")
# If JSON provided files_created, use that to inform verification
if [[ "$json_parsed" == "true" && -n "$PARSED_FILES_CREATED" && "$PARSED_FILES_CREATED" != "[]" ]]; then
# Parse JSON array and verify each file exists
local json_files
json_files=$(echo "$PARSED_FILES_CREATED" | jq -r '.[]' 2>/dev/null)
if [[ -n "$json_files" ]]; then
while IFS= read -r file; do
if [[ -f "$file" ]]; then
created_files+=("$file")
else
missing_files+=("$file")
fi
done <<< "$json_files"
fi
fi
if [[ -f "@fix_plan.md" ]]; then
created_files+=("@fix_plan.md")
else
missing_files+=("@fix_plan.md")
fi
if [[ -f "specs/requirements.md" ]]; then
created_files+=("specs/requirements.md")
else
missing_files+=("specs/requirements.md")
fi
# Always verify expected files exist (filesystem is source of truth)
for file in "${expected_files[@]}"; do
if [[ -f "$file" ]]; then
# Add to created_files if not already there
if [[ ! " ${created_files[*]} " =~ " ${file} " ]]; then
created_files+=("$file")
fi
else
# Add to missing_files if not already there
if [[ ! " ${missing_files[*]} " =~ " ${file} " ]]; then
missing_files+=("$file")
fi
fi
done
# Report created files
if [[ ${#created_files[@]} -gt 0 ]]; then