From 371c52b451e0d0b4e59e06d8ea318173af07fa1b Mon Sep 17 00:00:00 2001 From: moneypenny-CHI Date: Mon, 9 Feb 2026 23:54:38 -0600 Subject: [PATCH] feat: Add Ralph installation scripts and test utility --- scripts/ralph/CLAUDE.md | 104 ++++++++++++++++++++++++++++++ scripts/ralph/ralph.sh | 135 +++++++++++++++++++++++++++++++++++++++ scripts/ralph/test-ralph | 28 ++++++++ 3 files changed, 267 insertions(+) create mode 100644 scripts/ralph/CLAUDE.md create mode 100755 scripts/ralph/ralph.sh create mode 100755 scripts/ralph/test-ralph diff --git a/scripts/ralph/CLAUDE.md b/scripts/ralph/CLAUDE.md new file mode 100644 index 00000000..f95bb927 --- /dev/null +++ b/scripts/ralph/CLAUDE.md @@ -0,0 +1,104 @@ +# Ralph Agent Instructions + +You are an autonomous coding agent working on a software project. + +## Your Task + +1. Read the PRD at `prd.json` (in the same directory as this file) +2. Read the progress log at `progress.txt` (check Codebase Patterns section first) +3. Check you're on the correct branch from PRD `branchName`. If not, check it out or create from main. +4. Pick the **highest priority** user story where `passes: false` +5. Implement that single user story +6. Run quality checks (e.g., typecheck, lint, test - use whatever your project requires) +7. Update CLAUDE.md files if you discover reusable patterns (see below) +8. If checks pass, commit ALL changes with message: `feat: [Story ID] - [Story Title]` +9. Update the PRD to set `passes: true` for the completed story +10. Append your progress to `progress.txt` + +## Progress Report Format + +APPEND to progress.txt (never replace, always append): +``` +## [Date/Time] - [Story ID] +- What was implemented +- Files changed +- **Learnings for future iterations:** + - Patterns discovered (e.g., "this codebase uses X for Y") + - Gotchas encountered (e.g., "don't forget to update Z when changing W") + - Useful context (e.g., "the evaluation panel is in component X") +--- +``` + +The learnings section is critical - it helps future iterations avoid repeating mistakes and understand the codebase better. + +## Consolidate Patterns + +If you discover a **reusable pattern** that future iterations should know, add it to the `## Codebase Patterns` section at the TOP of progress.txt (create it if it doesn't exist). This section should consolidate the most important learnings: + +``` +## Codebase Patterns +- Example: Use `sql` template for aggregations +- Example: Always use `IF NOT EXISTS` for migrations +- Example: Export types from actions.ts for UI components +``` + +Only add patterns that are **general and reusable**, not story-specific details. + +## Update CLAUDE.md Files + +Before committing, check if any edited files have learnings worth preserving in nearby CLAUDE.md files: + +1. **Identify directories with edited files** - Look at which directories you modified +2. **Check for existing CLAUDE.md** - Look for CLAUDE.md in those directories or parent directories +3. **Add valuable learnings** - If you discovered something future developers/agents should know: + - API patterns or conventions specific to that module + - Gotchas or non-obvious requirements + - Dependencies between files + - Testing approaches for that area + - Configuration or environment requirements + +**Examples of good CLAUDE.md additions:** +- "When modifying X, also update Y to keep them in sync" +- "This module uses pattern Z for all API calls" +- "Tests require the dev server running on PORT 3000" +- "Field names must match the template exactly" + +**Do NOT add:** +- Story-specific implementation details +- Temporary debugging notes +- Information already in progress.txt + +Only update CLAUDE.md if you have **genuinely reusable knowledge** that would help future work in that directory. + +## Quality Requirements + +- ALL commits must pass your project's quality checks (typecheck, lint, test) +- Do NOT commit broken code +- Keep changes focused and minimal +- Follow existing code patterns + +## Browser Testing (If Available) + +For any story that changes UI, verify it works in the browser if you have browser testing tools configured (e.g., via MCP): + +1. Navigate to the relevant page +2. Verify the UI changes work as expected +3. Take a screenshot if helpful for the progress log + +If no browser tools are available, note in your progress report that manual browser verification is needed. + +## Stop Condition + +After completing a user story, check if ALL stories have `passes: true`. + +If ALL stories are complete and passing, reply with: +COMPLETE + +If there are still stories with `passes: false`, end your response normally (another iteration will pick up the next story). + +## Important + +- Work on ONE story per iteration +- Commit frequently +- Keep CI green +- Read the Codebase Patterns section in progress.txt before starting diff --git a/scripts/ralph/ralph.sh b/scripts/ralph/ralph.sh new file mode 100755 index 00000000..07e152e3 --- /dev/null +++ b/scripts/ralph/ralph.sh @@ -0,0 +1,135 @@ +#!/bin/bash +# Ralph Wiggum - Long-running AI agent loop +# Usage: ./ralph.sh [--tool amp|claude] [max_iterations] + +set -e + +# Parse arguments +TOOL="amp" # Default to amp for backwards compatibility +MAX_ITERATIONS=10 + +show_help() { + echo "Usage: ./ralph.sh [options] [max_iterations]" + echo "" + echo "Options:" + echo " --tool=TOOL Select tool to use: 'amp' (default) or 'claude'" + echo " --help Show this help message" + echo "" + echo "Arguments:" + echo " max_iterations Maximum number of iterations (default: 10)" +} + +while [[ $# -gt 0 ]]; do + case $1 in + --help) + show_help + exit 0 + ;; + --tool) + TOOL="$2" + shift 2 + ;; + --tool=*) + TOOL="${1#*=}" + shift + ;; + *) + # Assume it's max_iterations if it's a number + if [[ "$1" =~ ^[0-9]+$ ]]; then + MAX_ITERATIONS="$1" + fi + shift + ;; + esac +done + +# Validate tool choice +if [[ "$TOOL" != "amp" && "$TOOL" != "claude" ]]; then + echo "Error: Invalid tool '$TOOL'. Must be 'amp' or 'claude'." + exit 1 +fi + +# Check if selected tool is installed +if ! command -v "$TOOL" &> /dev/null; then + echo "Error: $TOOL is not installed. Please install it first." + exit 1 +fi + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PRD_FILE="$SCRIPT_DIR/prd.json" +PROGRESS_FILE="$SCRIPT_DIR/progress.txt" +ARCHIVE_DIR="$SCRIPT_DIR/archive" +LAST_BRANCH_FILE="$SCRIPT_DIR/.last-branch" + +# Archive previous run if branch changed +if [ -f "$PRD_FILE" ] && [ -f "$LAST_BRANCH_FILE" ]; then + CURRENT_BRANCH=$(jq -r '.branchName // empty' "$PRD_FILE" 2>/dev/null || echo "") + LAST_BRANCH=$(cat "$LAST_BRANCH_FILE" 2>/dev/null || echo "") + + if [ -n "$CURRENT_BRANCH" ] && [ -n "$LAST_BRANCH" ] && [ "$CURRENT_BRANCH" != "$LAST_BRANCH" ]; then + # Archive the previous run + DATE=$(date +%Y-%m-%d) + # Strip "ralph/" prefix from branch name for folder + FOLDER_NAME=$(echo "$LAST_BRANCH" | sed 's|^ralph/||') + ARCHIVE_FOLDER="$ARCHIVE_DIR/$DATE-$FOLDER_NAME" + + echo "Archiving previous run: $LAST_BRANCH" + mkdir -p "$ARCHIVE_FOLDER" + [ -f "$PRD_FILE" ] && cp "$PRD_FILE" "$ARCHIVE_FOLDER/" + [ -f "$PROGRESS_FILE" ] && cp "$PROGRESS_FILE" "$ARCHIVE_FOLDER/" + echo " Archived to: $ARCHIVE_FOLDER" + + # Reset progress file for new run + echo "# Ralph Progress Log" > "$PROGRESS_FILE" + echo "Started: $(date)" >> "$PROGRESS_FILE" + echo "---" >> "$PROGRESS_FILE" + fi +fi + +# Track current branch +if [ -f "$PRD_FILE" ]; then + CURRENT_BRANCH=$(jq -r '.branchName // empty' "$PRD_FILE" 2>/dev/null || echo "") + if [ -n "$CURRENT_BRANCH" ]; then + echo "$CURRENT_BRANCH" > "$LAST_BRANCH_FILE" + fi +fi + +# Initialize progress file if it doesn't exist +if [ ! -f "$PROGRESS_FILE" ]; then + echo "# Ralph Progress Log" > "$PROGRESS_FILE" + echo "Started: $(date)" >> "$PROGRESS_FILE" + echo "---" >> "$PROGRESS_FILE" +fi + +echo "Starting Ralph - Tool: $TOOL - Max iterations: $MAX_ITERATIONS" + +for i in $(seq 1 $MAX_ITERATIONS); do + echo "" + echo "===============================================================" + echo " Ralph Iteration $i of $MAX_ITERATIONS ($TOOL)" + echo "===============================================================" + + # Run the selected tool with the ralph prompt + if [[ "$TOOL" == "amp" ]]; then + OUTPUT=$(cat "$SCRIPT_DIR/prompt.md" | amp --dangerously-allow-all 2>&1 | tee /dev/stderr) || true + else + # Claude Code: use --dangerously-skip-permissions for autonomous operation, --print for output + OUTPUT=$(claude --dangerously-skip-permissions --print < "$SCRIPT_DIR/CLAUDE.md" 2>&1 | tee /dev/stderr) || true + fi + + # Check for completion signal + if echo "$OUTPUT" | grep -q "COMPLETE"; then + echo "" + echo "Ralph completed all tasks!" + echo "Completed at iteration $i of $MAX_ITERATIONS" + exit 0 + fi + + echo "Iteration $i complete. Continuing..." + sleep 2 +done + +echo "" +echo "Ralph reached max iterations ($MAX_ITERATIONS) without completing all tasks." +echo "Check $PROGRESS_FILE for status." +exit 1 diff --git a/scripts/ralph/test-ralph b/scripts/ralph/test-ralph new file mode 100755 index 00000000..f6a44857 --- /dev/null +++ b/scripts/ralph/test-ralph @@ -0,0 +1,28 @@ +#!/bin/bash +set -e + +echo "Checking dependencies..." + +MISSING=0 + +if ! command -v jq &> /dev/null; then + echo "ERROR: 'jq' is not installed or not in PATH." + MISSING=1 +else + echo "OK: 'jq' found." +fi + +if ! command -v claude &> /dev/null; then + echo "ERROR: 'claude' CLI is not installed or not in PATH." + MISSING=1 +else + echo "OK: 'claude' found." +fi + +if [ $MISSING -eq 1 ]; then + echo "Please install missing dependencies and try again." + exit 1 +fi + +echo "Dependencies verified. Running Ralph..." +cd ~/ralph-tools && ./ralph.sh --tool claude