With "reasoning" escalation.
#!/bin/bash
set -o pipefail # catch CLI failures
# Using Claude
# --- Config ---
PROMPT_FILE="PROMPT.md"
PRD_FILE="specs/prd.json"
LOG_FILE="progress.log"
MAX_ITERATIONS=${1:-10}
ITERATION=0
STALLED_COUNT=0
# --- UI Colors ---
BLUE='\033[1;34m'; YELLOW='\033[1;33m'; GREEN='\033[1;32m'; MAGENTA='\033[1;35m'; NC='\033[0m'
log_info() { echo -e "${BLUE}ℹ️ $1${NC}"; }
log_step() { echo -e "${YELLOW}➔ $1${NC}"; }
log_success() { echo -e "${GREEN}✅ $1${NC}"; }
log_warn() { echo -e "${MAGENTA}⚠️ $1${NC}"; }
# Exit the entire script if Ctrl+C is pressed
trap "echo -e '\n${MAGENTA}Stopping Ralph Loop...${NC}'; exit 1" SIGINT
while [ $ITERATION -lt $MAX_ITERATIONS ]; do
ITERATION=$((ITERATION + 1))
# 1. Adjust Reasoning Level
REASONING_LEVEL="low"
[ "$STALLED_COUNT" -eq 1 ] && REASONING_LEVEL="medium"
[ "$STALLED_COUNT" -ge 2 ] && REASONING_LEVEL="high"
# If we've stalled twice, wipe the local wrangler state to ensure
# stale D1/KV data isn't causing the friction.
if [ "$STALLED_COUNT" -eq 2 ]; then
log_warn "Friction detected. Clearing .wrangler local state..."
rm -rf .wrangler/state/v3
fi
# 2. Get Task Context
PENDING_TASKS=$(jq -r '.userStories[] | select(.passes == false or .passes == null) | "[\(.id)] \(.title)"' "$PRD_FILE")
CURRENT_TASK=$(echo "$PENDING_TASKS" | head -n 1)
if [ -z "$CURRENT_TASK" ]; then
log_success "No incomplete tasks found."
exit 0
fi
echo -e "${BLUE}------------------------------------------------------------${NC}"
log_info "ITERATION $ITERATION/$MAX_ITERATIONS | LEVEL: $REASONING_LEVEL"
log_step "TARGET: $CURRENT_TASK"
echo -e "${BLUE}------------------------------------------------------------${NC}"
# 3. Build Dynamic Context for the CLI
TMP_CONTEXT=$(mktemp)
{
cat "$PROMPT_FILE"
echo -e "\n# CURRENT STATE"
echo "PENDING_TASKS: $PENDING_TASKS"
echo "LAST_LOG_ENTRY: $(tail -n 5 "$LOG_FILE" 2>/dev/null)"
} > "$TMP_CONTEXT"
# 4. Execute
TMP_CAPTURE=$(mktemp)
cat "$TMP_CONTEXT" | claude -p --effort "$REASONING_LEVEL" --dangerously-skip-permissions | tee "$TMP_CAPTURE"
RESPONSE=$(cat "$TMP_CAPTURE")
# 5. Progress Detection (Commit OR File Changes)
HAS_CHANGES=$(git status --porcelain)
if [ -n "$HAS_CHANGES" ]; then
log_success "Activity detected."
STALLED_COUNT=0
else
log_warn "No changes detected."
STALLED_COUNT=$((STALLED_COUNT + 1))
fi
# Cleanup temp files
rm "$TMP_CONTEXT" "$TMP_CAPTURE"
if [[ "$RESPONSE" == *"<promise>COMPLETE</promise>"* ]]; then
log_success "MISSION ACCOMPLISHED."
exit 0
fi
donestudy NOTES/architecture.md
study NOTES/product.md
# MISSION
Write some tests for this serverside rendered app template.
## Important
- Commit frequently
- Read the Codebase Patterns section in progress.log before starting
## EXECUTION RULES
1. READ: Always check `specs/prd.json` and `progress.log` at the start of
every session.
2. SCOPE: Pick the highest priority task where `passes: false`. Work ONLY on
that task.
3. WRITE TESTS: Before implementing, write failing tests for the feature/bug,
then make the tests pass
4. TARGETED TESTING:
- DO NOT run the full test suite (`npm test`) for every minor change.
- DO run only the tests relevant to the current file
(e.g., `npx vitest path/to/file.spec.ts`).
- Run the FULL test suite (`npm test`) ONLY when you believe the task is
100% complete.
5. VERIFY: You must run `npm run lint` and `npm test` after any code change.
6. DOCUMENT: Update `progress.log` with what was changed and any new
patterns discovered.
7. UPDATE: Update the PRD, `specs/prd.json` to set `passes: true` for the completed story
8. COMMIT: If tests pass, commit with a descriptive message
like `FEATURE: [TaskID] - [Description]`.
9. ATOMICITY: Aim to complete exactly one task per iteration.
## Progress Report Format
APPEND to progress.log (never replace, always append):
\`\`\`
## [Date/Time] - [Story ID]
Thread: https://ampcode.com/threads/$AMP_CURRENT_THREAD_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.log (create it if it doesn't exist). This section should consolidate the most important learnings:
Only add patterns that are **general and reusable**, not story-specific details.
## Update AGENTS.md Files
Before committing, check if any edited files have learnings worth preserving in nearby AGENTS.md files:
1. **Identify directories with edited files** - Look at which directories you modified
2. **Check for existing AGENTS.md** - Look for AGENTS.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 AGENTS.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.log
Only update AGENTS.md if you have **genuinely reusable knowledge** that would help future work in that directory.
## STOP CONDITION
Once ALL tasks in `specs/prd.json` have `passes: true`, you must output the
exact string: <promise>COMPLETE</promise>
Do not perform any further work after all tasks are verified.