curatare
This commit is contained in:
@@ -1,203 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Ralph - Autonomous Loop for PRD Implementation
|
||||
# Usage: ./ralph.sh [max_iterations]
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
PRD_FILE="$SCRIPT_DIR/prd.json"
|
||||
PROGRESS_FILE="$SCRIPT_DIR/progress.txt"
|
||||
PROMPT_FILE="$SCRIPT_DIR/prompt.md"
|
||||
LOG_DIR="$SCRIPT_DIR/logs"
|
||||
|
||||
MAX_ITERATIONS=${1:-50}
|
||||
ITERATION=0
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
log() {
|
||||
echo -e "${BLUE}[Ralph]${NC} $1"
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$PROGRESS_FILE"
|
||||
}
|
||||
|
||||
error() {
|
||||
echo -e "${RED}[Ralph ERROR]${NC} $1"
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >> "$PROGRESS_FILE"
|
||||
}
|
||||
|
||||
success() {
|
||||
echo -e "${GREEN}[Ralph]${NC} $1"
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS: $1" >> "$PROGRESS_FILE"
|
||||
}
|
||||
|
||||
# Check prerequisites
|
||||
if [ ! -f "$PRD_FILE" ]; then
|
||||
error "prd.json not found at $PRD_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v claude &> /dev/null; then
|
||||
error "claude CLI not found. Install with: npm install -g @anthropic-ai/claude-code"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v jq &> /dev/null; then
|
||||
error "jq not found. Install with: apt install jq"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create log directory
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Get project info
|
||||
PROJECT_NAME=$(jq -r '.projectName' "$PRD_FILE")
|
||||
BRANCH_NAME=$(jq -r '.branchName' "$PRD_FILE")
|
||||
|
||||
log "Starting Ralph for project: $PROJECT_NAME"
|
||||
log "Max iterations: $MAX_ITERATIONS"
|
||||
|
||||
# Create branch if not exists
|
||||
cd "$PROJECT_ROOT"
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
if [ "$CURRENT_BRANCH" != "$BRANCH_NAME" ]; then
|
||||
if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then
|
||||
log "Switching to existing branch: $BRANCH_NAME"
|
||||
git checkout "$BRANCH_NAME"
|
||||
else
|
||||
log "Creating new branch: $BRANCH_NAME"
|
||||
git checkout -b "$BRANCH_NAME"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Function to get next pending story
|
||||
get_next_story() {
|
||||
jq -r '.userStories | map(select(.passes == false)) | sort_by(.priority) | .[0] | .id // empty' "$PRD_FILE"
|
||||
}
|
||||
|
||||
# Function to get story details
|
||||
get_story_details() {
|
||||
local story_id=$1
|
||||
jq -r --arg id "$story_id" '.userStories[] | select(.id == $id)' "$PRD_FILE"
|
||||
}
|
||||
|
||||
# Function to mark story as passed
|
||||
mark_story_passed() {
|
||||
local story_id=$1
|
||||
local notes=$2
|
||||
local tmp_file=$(mktemp)
|
||||
jq --arg id "$story_id" --arg notes "$notes" \
|
||||
'(.userStories[] | select(.id == $id)) |= (.passes = true | .notes = $notes)' \
|
||||
"$PRD_FILE" > "$tmp_file" && mv "$tmp_file" "$PRD_FILE"
|
||||
}
|
||||
|
||||
# Function to count stories
|
||||
count_stories() {
|
||||
local total=$(jq '.userStories | length' "$PRD_FILE")
|
||||
local passed=$(jq '[.userStories[] | select(.passes == true)] | length' "$PRD_FILE")
|
||||
echo "$passed/$total"
|
||||
}
|
||||
|
||||
# Main loop
|
||||
while [ $ITERATION -lt $MAX_ITERATIONS ]; do
|
||||
ITERATION=$((ITERATION + 1))
|
||||
|
||||
log "=== Iteration $ITERATION/$MAX_ITERATIONS ==="
|
||||
|
||||
# Get next story
|
||||
NEXT_STORY=$(get_next_story)
|
||||
|
||||
if [ -z "$NEXT_STORY" ]; then
|
||||
success "All stories completed! 🎉"
|
||||
break
|
||||
fi
|
||||
|
||||
log "Working on story: $NEXT_STORY"
|
||||
|
||||
# Get story details for prompt
|
||||
STORY_JSON=$(get_story_details "$NEXT_STORY")
|
||||
STORY_TITLE=$(echo "$STORY_JSON" | jq -r '.title')
|
||||
|
||||
# Create iteration prompt
|
||||
ITERATION_PROMPT="You are implementing user story $NEXT_STORY: $STORY_TITLE
|
||||
|
||||
Read the full PRD at scripts/ralph/prd.json for context and CSS rules.
|
||||
|
||||
Story details:
|
||||
$STORY_JSON
|
||||
|
||||
IMPORTANT CSS RULES (from PRD):
|
||||
- NEVER use hardcoded values - always use design tokens
|
||||
- Check docs/DESIGN_TOKENS.md and docs/CSS_PATTERNS.md before writing CSS
|
||||
- Test in BOTH light and dark mode
|
||||
- NEVER use :deep() in components
|
||||
|
||||
Your task:
|
||||
1. Implement this story following all acceptance criteria
|
||||
2. Run tests/typecheck to verify
|
||||
3. If ALL criteria pass, respond with: STORY_PASSED
|
||||
4. If blocked or need clarification, respond with: STORY_BLOCKED: <reason>
|
||||
|
||||
Do NOT move to other stories. Focus only on $NEXT_STORY."
|
||||
|
||||
# Run Claude
|
||||
LOG_FILE="$LOG_DIR/iteration_${ITERATION}_${NEXT_STORY}.log"
|
||||
log "Running Claude... (log: $LOG_FILE)"
|
||||
|
||||
# Run claude with the prompt (--output-format json avoids streaming mode issues)
|
||||
CLAUDE_OUTPUT=$(cd "$PROJECT_ROOT" && claude -p "$ITERATION_PROMPT" --output-format json 2>&1 | tee "$LOG_FILE")
|
||||
|
||||
# Check result
|
||||
if echo "$CLAUDE_OUTPUT" | grep -q "STORY_PASSED"; then
|
||||
success "Story $NEXT_STORY passed!"
|
||||
mark_story_passed "$NEXT_STORY" "Completed in iteration $ITERATION"
|
||||
|
||||
# Commit changes
|
||||
cd "$PROJECT_ROOT"
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
git add -A
|
||||
git commit -m "feat($PROJECT_NAME): Complete $NEXT_STORY - $STORY_TITLE
|
||||
|
||||
Implemented by Ralph autonomous loop.
|
||||
Iteration: $ITERATION
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||
log "Changes committed"
|
||||
fi
|
||||
|
||||
elif echo "$CLAUDE_OUTPUT" | grep -q "STORY_BLOCKED"; then
|
||||
BLOCK_REASON=$(echo "$CLAUDE_OUTPUT" | grep "STORY_BLOCKED" | sed 's/STORY_BLOCKED://')
|
||||
error "Story $NEXT_STORY blocked: $BLOCK_REASON"
|
||||
log "Stopping loop due to blocked story"
|
||||
break
|
||||
else
|
||||
log "Story $NEXT_STORY not yet complete, continuing..."
|
||||
fi
|
||||
|
||||
# Progress update
|
||||
PROGRESS=$(count_stories)
|
||||
log "Progress: $PROGRESS stories completed"
|
||||
|
||||
# Small delay between iterations
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Final summary
|
||||
echo ""
|
||||
log "=== Ralph Session Complete ==="
|
||||
PROGRESS=$(count_stories)
|
||||
log "Final progress: $PROGRESS stories completed"
|
||||
log "Branch: $BRANCH_NAME"
|
||||
log "Logs: $LOG_DIR"
|
||||
|
||||
# Show remaining stories
|
||||
REMAINING=$(jq -r '[.userStories[] | select(.passes == false)] | length' "$PRD_FILE")
|
||||
if [ "$REMAINING" -gt 0 ]; then
|
||||
echo -e "\n${YELLOW}Remaining stories:${NC}"
|
||||
jq -r '.userStories[] | select(.passes == false) | " - \(.id): \(.title)"' "$PRD_FILE"
|
||||
fi
|
||||
Reference in New Issue
Block a user