diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 00000000..9dc6e77f --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,26 @@ +{ + "hooks": { + "PostToolUse": [ + { + "matcher": "Bash(git commit*)", + "hooks": [ + { + "type": "command", + "command": "node -e \"const fs=require('fs');try{const p=JSON.parse(fs.readFileSync('scripts/ralph/prd.json','utf8'));const s=JSON.parse(fs.readFileSync('scripts/ralph/state.json','utf8'));if(!s.currentStory)process.exit(0);const story=p.userStories.find(u=>u.id===s.currentStory);if(story&&!story.passes){console.log('WARNING: story '+s.currentStory+' not yet marked passes:true in prd.json')}}catch(e){}\"" + } + ] + } + ], + "Stop": [ + { + "matcher": "*", + "hooks": [ + { + "type": "command", + "command": "node -e \"const fs=require('fs');try{const s=JSON.parse(fs.readFileSync('scripts/ralph/state.json','utf8'));const today=new Date().toISOString().slice(0,10);if(s.lastUpdated!==today){console.log('state.json not updated today ('+s.lastUpdated+' vs '+today+')');process.exit(2)}}catch(e){}\"" + } + ] + } + ] + } +} diff --git a/.claudeignore b/.claudeignore new file mode 100644 index 00000000..b87a30db --- /dev/null +++ b/.claudeignore @@ -0,0 +1,28 @@ +# Archives (not relevant to agent work) +archive/ +scripts/ralph/archive/ + +# Flowchart source (visualization, not agent work) +flowchart/ + +# Binary/media files +*.png +*.jpg +*.gif +*.svg +*.ico +*.webp +*.woff +*.woff2 +*.ttf +*.eot + +# Build artifacts +node_modules/ +.next/ +dist/ +build/ +out/ + +# Environment files +.env* diff --git a/.gitignore b/.gitignore index f583b7e5..0705455f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,21 @@ # Ralph working files (generated during runs) -prd.json -progress.txt -.last-branch +scripts/ralph/prd.json +scripts/ralph/progress.md +scripts/ralph/state.json +scripts/ralph/.last-branch # Archive is optional to commit -# archive/ +# scripts/ralph/archive/ # OS files .DS_Store -#Claude -.claude/ +# Claude Code - only exclude local settings (shared settings.json with hooks is tracked) +.claude/settings.local.json + +# Build artifacts +node_modules/ +dist/ +build/ +.next/ +out/ diff --git a/AGENTS.md b/AGENTS.md index 9da9ecd1..789e6851 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,18 +14,18 @@ cd flowchart && npm run dev cd flowchart && npm run build # Run Ralph with Amp (default) -./ralph.sh [max_iterations] +./scripts/ralph/ralph.sh [max_sessions] # Run Ralph with Claude Code -./ralph.sh --tool claude [max_iterations] +./scripts/ralph/ralph.sh --tool claude [max_sessions] ``` ## Key Files -- `ralph.sh` - The bash loop that spawns fresh AI instances (supports `--tool amp` or `--tool claude`) -- `prompt.md` - Instructions given to each AMP instance -- `CLAUDE.md` - Instructions given to each Claude Code instance -- `prd.json.example` - Example PRD format +- `scripts/ralph/ralph.sh` - The bash loop that spawns fresh AI instances (supports `--tool amp` or `--tool claude`) +- `scripts/ralph/prompt.md` - Instructions given to each AMP instance +- `scripts/ralph/CLAUDE.md` - Instructions given to each Claude Code instance +- `scripts/ralph/prd.json.example` - Example PRD format - `flowchart/` - Interactive React Flow diagram explaining how Ralph works ## Flowchart @@ -41,7 +41,7 @@ npm run dev ## Patterns -- Each iteration spawns a fresh AI instance (Amp or Claude Code) with clean context -- Memory persists via git history, `progress.txt`, and `prd.json` +- Each session spawns a fresh AI instance (Amp or Claude Code) with clean context +- Memory persists via git history, `scripts/ralph/progress.md`, `scripts/ralph/prd.json`, and `scripts/ralph/state.json` - Stories should be small enough to complete in one context window -- Always update AGENTS.md with discovered patterns for future iterations +- Always update Institutional Memory in scripts/ralph/CLAUDE.md with discovered patterns for future sessions diff --git a/CLAUDE.md b/CLAUDE.md index f95bb927..39eb98e5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,104 +1,2 @@ -# 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 +## Ralph Agent +When working on Ralph stories, read and follow `scripts/ralph/CLAUDE.md`. diff --git a/README.md b/README.md index d79d8b62..50a0918c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![Ralph](ralph.webp) -Ralph is an autonomous AI agent loop that runs AI coding tools ([Amp](https://ampcode.com) or [Claude Code](https://docs.anthropic.com/en/docs/claude-code)) repeatedly until all PRD items are complete. Each iteration is a fresh instance with clean context. Memory persists via git history, `progress.txt`, and `prd.json`. +Ralph is an autonomous AI agent loop that runs AI coding tools ([Amp](https://ampcode.com) or [Claude Code](https://docs.anthropic.com/en/docs/claude-code)) repeatedly until all PRD items are complete. Each session is a fresh instance with clean context. Memory persists via git history, `state.json`, `progress.md`, and `prd.json`. Based on [Geoffrey Huntley's Ralph pattern](https://ghuntley.com/ralph/). @@ -25,12 +25,17 @@ Copy the ralph files into your project: ```bash # From your project root mkdir -p scripts/ralph -cp /path/to/ralph/ralph.sh scripts/ralph/ +cp /path/to/ralph/scripts/ralph/ralph.sh scripts/ralph/ +cp /path/to/ralph/scripts/ralph/BOOTSTRAP.md scripts/ralph/ +cp /path/to/ralph/scripts/ralph/COMPACTION.md scripts/ralph/ +cp /path/to/ralph/scripts/ralph/PROGRESS-GUIDE.md scripts/ralph/ +cp /path/to/ralph/scripts/ralph/ITERATIVE.md scripts/ralph/ +cp /path/to/ralph/scripts/ralph/prd.json.example scripts/ralph/ # Copy the prompt template for your AI tool of choice: -cp /path/to/ralph/prompt.md scripts/ralph/prompt.md # For Amp +cp /path/to/ralph/scripts/ralph/prompt.md scripts/ralph/prompt.md # For Amp # OR -cp /path/to/ralph/CLAUDE.md scripts/ralph/CLAUDE.md # For Claude Code +cp /path/to/ralph/scripts/ralph/CLAUDE.md scripts/ralph/CLAUDE.md # For Claude Code chmod +x scripts/ralph/ralph.sh ``` @@ -41,13 +46,11 @@ Copy the skills to your Amp or Claude config for use across all projects: For AMP ```bash -cp -r skills/prd ~/.config/amp/skills/ cp -r skills/ralph ~/.config/amp/skills/ ``` For Claude Code (manual) ```bash -cp -r skills/prd ~/.claude/skills/ cp -r skills/ralph ~/.claude/skills/ ``` @@ -66,12 +69,10 @@ Then install the skills: ``` Available skills after installation: -- `/prd` - Generate Product Requirements Documents -- `/ralph` - Convert PRDs to prd.json format +- `/ralph` - Generate PRD markdown + Ralph-compatible `prd.json` in one step Skills are automatically invoked when you ask Claude to: -- "create a prd", "write prd for", "plan this feature" -- "convert this prd", "turn into ralph format", "create prd.json" +- "create a prd", "write prd for", "plan this feature", "spec out" ### Configure Amp auto-handoff (recommended) @@ -85,62 +86,91 @@ Add to `~/.config/amp/settings.json`: This enables automatic handoff when context fills up, allowing Ralph to handle large stories that exceed a single context window. -## Workflow - -### 1. Create a PRD +## Terminology -Use the PRD skill to generate a detailed requirements document: +| Term | Definition | +|------|------------| +| **Session** | One top-level loop cycle in `ralph.sh`. Each session is a fresh context window with no memory of prior sessions except what is persisted in the memory layers below. | +| **Iteration** | Repeating the SAME user story across multiple sessions (ITERATIVE feature). One iteration = one session = one context window. Used for batch/multi-pass work with a predetermined count. | -``` -Load the prd skill and create a PRD for [your feature description] -``` - -Answer the clarifying questions. The skill saves output to `tasks/prd-[feature-name].md`. +## Workflow -### 2. Convert PRD to Ralph format +### 1. Create a PRD -Use the Ralph skill to convert the markdown PRD to JSON: +Use the `/ralph` skill to generate both artifacts in one step: ``` -Load the ralph skill and convert tasks/prd-[feature-name].md to prd.json +Load the ralph skill and create a PRD for [your feature description] ``` -This creates `prd.json` with user stories structured for autonomous execution. +Answer the clarifying questions. The skill produces two outputs: +- `tasks/prd-[feature-name].md` — human-readable requirements document +- `scripts/ralph/prd.json` — machine-readable story list for Ralph -### 3. Run Ralph +### 2. Run Ralph ```bash # Using Amp (default) -./scripts/ralph/ralph.sh [max_iterations] +./scripts/ralph/ralph.sh [max_sessions] # Using Claude Code -./scripts/ralph/ralph.sh --tool claude [max_iterations] +./scripts/ralph/ralph.sh --tool claude [max_sessions] ``` -Default is 10 iterations. Use `--tool amp` or `--tool claude` to select your AI coding tool. +Default is 10 sessions. Use `--tool amp` or `--tool claude` to select your AI coding tool. Ralph will: -1. Create a feature branch (from PRD `branchName`) -2. Pick the highest priority story where `passes: false` -3. Implement that single story -4. Run quality checks (typecheck, tests) -5. Commit if checks pass -6. Update `prd.json` to mark story as `passes: true` -7. Append learnings to `progress.txt` -8. Repeat until all stories pass or max iterations reached +1. Read `state.json` for current story, branch, and next action +2. Create/checkout the feature branch (from `state.json`) +3. Pick the current story (from `state.json`, NOT by scanning prd.json) +4. Implement that single story (or one iteration of an iterative story) +5. Run quality checks (typecheck, tests) +6. Commit if checks pass +7. Append learnings to `progress.md` +8. Update `prd.json` to mark story as `passes: true` +9. Update `state.json` with next story +10. Repeat until all stories pass or max sessions reached + +## Standard vs Iterative Stories + +| Mode | When to Use | Behavior | +|------|-------------|----------| +| **Standard** | Most stories -- single-pass work that fits in one session | Story is implemented and marked `passes: true` in one session | +| **Iterative** | Batch/multi-pass work with a predetermined count | Story has `iterationMode` + `maxIterations` in `prd.json`; one iteration per session; `passes: true` only when `currentIteration >= maxIterations` | + +Iterative mode is for work that is inherently batched (e.g., audit N sections, process N files), **NOT** for stories that are too large. Stories that are too large should be split into smaller stories. + +When a story has `iterationMode`, the agent loads `scripts/ralph/ITERATIVE.md` as a delta-only supplement to `scripts/ralph/CLAUDE.md`. See `scripts/ralph/ITERATIVE.md` for the full rules. + +## Memory Model + +Ralph persists knowledge across sessions via four layers: + +| Layer | File | Purpose | Lifespan | +|-------|------|---------|----------| +| **Operational** | `state.json` | Current story, next action, branch, compaction status | Per-session (updated every session) | +| **Structural** | `prd.json` | Story status, iteration counters, notes | Per-PRD | +| **Experiential** | `progress.md` | Session logs, codebase patterns, learnings | Per-PRD, append-only (auto-compacted) | +| **Institutional** | `scripts/ralph/CLAUDE.md` | Reusable conventions, gotchas, cross-file dependencies | Permanent — survives across PRDs | + +See the "Institutional Memory" section in `scripts/ralph/CLAUDE.md` for details on what goes where. ## Key Files | File | Purpose | |------|---------| -| `ralph.sh` | The bash loop that spawns fresh AI instances (supports `--tool amp` or `--tool claude`) | -| `prompt.md` | Prompt template for Amp | -| `CLAUDE.md` | Prompt template for Claude Code | -| `prd.json` | User stories with `passes` status (the task list) | -| `prd.json.example` | Example PRD format for reference | -| `progress.txt` | Append-only learnings for future iterations | -| `skills/prd/` | Skill for generating PRDs (works with Amp and Claude Code) | -| `skills/ralph/` | Skill for converting PRDs to JSON (works with Amp and Claude Code) | +| `scripts/ralph/ralph.sh` | The bash loop that spawns fresh AI sessions (supports `--tool amp` or `--tool claude`) | +| `scripts/ralph/prompt.md` | Prompt template for Amp | +| `scripts/ralph/CLAUDE.md` | Core agent instructions for Claude Code (includes institutional memory) | +| `scripts/ralph/BOOTSTRAP.md` | State bootstrap for first session (loaded conditionally) | +| `scripts/ralph/COMPACTION.md` | Progress compaction rules (loaded conditionally) | +| `scripts/ralph/PROGRESS-GUIDE.md` | Progress report format and learnings guide (reference) | +| `scripts/ralph/ITERATIVE.md` | Supplemental rules for iterative stories (loaded conditionally) | +| `scripts/ralph/prd.json` | User stories with `passes` status (the task list) | +| `scripts/ralph/prd.json.example` | Example PRD format for reference | +| `scripts/ralph/progress.md` | Append-only learnings for future sessions | +| `scripts/ralph/state.json` | Session orientation file — tells the agent which story, branch, and action to take | +| `skills/ralph/` | Skill for generating PRD markdown + `prd.json` (works with Amp and Claude Code) | | `.claude-plugin/` | Plugin manifest for Claude Code marketplace discovery | | `flowchart/` | Interactive visualization of how Ralph works | @@ -160,11 +190,12 @@ npm run dev ## Critical Concepts -### Each Iteration = Fresh Context +### Each Session = Fresh Context -Each iteration spawns a **new AI instance** (Amp or Claude Code) with clean context. The only memory between iterations is: -- Git history (commits from previous iterations) -- `progress.txt` (learnings and context) +Each session spawns a **new AI instance** (Amp or Claude Code) with clean context. The only memory between sessions is: +- Git history (commits from previous sessions) +- `state.json` (current story orientation and next action) +- `progress.md` (learnings and context) - `prd.json` (which stories are done) ### Small Tasks @@ -182,11 +213,11 @@ Too big (split these): - "Add authentication" - "Refactor the API" -### AGENTS.md Updates Are Critical +### Institutional Memory -After each iteration, Ralph updates the relevant `AGENTS.md` files with learnings. This is key because AI coding tools automatically read these files, so future iterations (and future human developers) benefit from discovered patterns, gotchas, and conventions. +After each session, Ralph updates the institutional memory section in `scripts/ralph/CLAUDE.md` with reusable patterns and gotchas. This is key because AI coding tools automatically read these files, so future sessions (and future human developers) benefit from discovered conventions and gotchas. -Examples of what to add to AGENTS.md: +Examples of what to persist: - Patterns discovered ("this codebase uses X for Y") - Gotchas ("do not forget to update Z when changing W") - Useful context ("the settings panel is in component X") @@ -196,7 +227,7 @@ Examples of what to add to AGENTS.md: Ralph only works if there are feedback loops: - Typecheck catches type errors - Tests verify behavior -- CI must stay green (broken code compounds across iterations) +- CI must stay green (broken code compounds across sessions) ### Browser Verification for UI Stories @@ -204,18 +235,21 @@ Frontend stories must include "Verify in browser using dev-browser skill" in acc ### Stop Condition -When all stories have `passes: true`, Ralph outputs `COMPLETE` and the loop exits. +When all stories have `passes: true`, `ralph.sh` detects completion by checking `prd.json` directly and the loop exits. ## Debugging Check current state: ```bash +# See current state +cat scripts/ralph/state.json | jq . + # See which stories are done -cat prd.json | jq '.userStories[] | {id, title, passes}' +cat scripts/ralph/prd.json | jq '.userStories[] | {id, title, passes}' -# See learnings from previous iterations -cat progress.txt +# See learnings from previous sessions +cat scripts/ralph/progress.md # Check git history git log --oneline -10 @@ -223,14 +257,14 @@ git log --oneline -10 ## Customizing the Prompt -After copying `prompt.md` (for Amp) or `CLAUDE.md` (for Claude Code) to your project, customize it for your project: +After copying `scripts/ralph/prompt.md` (for Amp) or `scripts/ralph/CLAUDE.md` (for Claude Code) to your project, customize it for your project: - Add project-specific quality check commands - Include codebase conventions - Add common gotchas for your stack ## Archiving -Ralph automatically archives previous runs when you start a new feature (different `branchName`). Archives are saved to `archive/YYYY-MM-DD-feature-name/`. +Ralph automatically archives previous runs when you start a new feature (different `branchName`). Archives are saved to `scripts/ralph/archive/YYYY-MM-DD-feature-name/`. ## References diff --git a/prd.json.example b/prd.json.example deleted file mode 100644 index fbc40668..00000000 --- a/prd.json.example +++ /dev/null @@ -1,64 +0,0 @@ -{ - "project": "MyApp", - "branchName": "ralph/task-priority", - "description": "Task Priority System - Add priority levels to tasks", - "userStories": [ - { - "id": "US-001", - "title": "Add priority field to database", - "description": "As a developer, I need to store task priority so it persists across sessions.", - "acceptanceCriteria": [ - "Add priority column to tasks table: 'high' | 'medium' | 'low' (default 'medium')", - "Generate and run migration successfully", - "Typecheck passes" - ], - "priority": 1, - "passes": false, - "notes": "" - }, - { - "id": "US-002", - "title": "Display priority indicator on task cards", - "description": "As a user, I want to see task priority at a glance.", - "acceptanceCriteria": [ - "Each task card shows colored priority badge (red=high, yellow=medium, gray=low)", - "Priority visible without hovering or clicking", - "Typecheck passes", - "Verify in browser using dev-browser skill" - ], - "priority": 2, - "passes": false, - "notes": "" - }, - { - "id": "US-003", - "title": "Add priority selector to task edit", - "description": "As a user, I want to change a task's priority when editing it.", - "acceptanceCriteria": [ - "Priority dropdown in task edit modal", - "Shows current priority as selected", - "Saves immediately on selection change", - "Typecheck passes", - "Verify in browser using dev-browser skill" - ], - "priority": 3, - "passes": false, - "notes": "" - }, - { - "id": "US-004", - "title": "Filter tasks by priority", - "description": "As a user, I want to filter the task list to see only high-priority items.", - "acceptanceCriteria": [ - "Filter dropdown with options: All | High | Medium | Low", - "Filter persists in URL params", - "Empty state message when no tasks match filter", - "Typecheck passes", - "Verify in browser using dev-browser skill" - ], - "priority": 4, - "passes": false, - "notes": "" - } - ] -} diff --git a/prompt.md b/prompt.md deleted file mode 100644 index cdebe901..00000000 --- a/prompt.md +++ /dev/null @@ -1,108 +0,0 @@ -# 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 AGENTS.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] -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") ---- -``` - -Include the thread URL so future iterations can use the `read_thread` tool to reference previous work if needed. - -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 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.txt - -Only update AGENTS.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 (Required for Frontend Stories) - -For any story that changes UI, you MUST verify it works in the browser: - -1. Load the `dev-browser` skill -2. Navigate to the relevant page -3. Verify the UI changes work as expected -4. Take a screenshot if helpful for the progress log - -A frontend story is NOT complete until browser verification passes. - -## 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/ralph.sh b/ralph.sh deleted file mode 100755 index baff052a..00000000 --- a/ralph.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/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 - -while [[ $# -gt 0 ]]; do - case $1 in - --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 -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/BOOTSTRAP.md b/scripts/ralph/BOOTSTRAP.md new file mode 100644 index 00000000..fb6921a6 --- /dev/null +++ b/scripts/ralph/BOOTSTRAP.md @@ -0,0 +1,34 @@ +# State Bootstrap + +> This file is read ONLY when `scripts/ralph/state.json` does not exist (first session or manual invocation). + +## Steps + +1. Read `scripts/ralph/prd.json` +2. Find the first story where `passes: false` (lowest `priority` number) +3. Determine `nextAction`: + - If the story has `iterationMode`: `"iteration 1/N"` (where N = `maxIterations`) + - Otherwise: `"implement"` +4. Write `scripts/ralph/state.json`: +```json +{ + "branch": "", + "currentStory": "", + "storyTitle": "", + "nextAction": "", + "progressTokens": 0, + "compactionNeeded": false, + "compactionThreshold": 10000, + "lastUpdated": "" +} +``` +5. Initialize `scripts/ralph/progress.md` if it doesn't exist: +```markdown +# Ralph Progress Log +Started: [date] +--- + +## Codebase Patterns +> Reusable patterns discovered during implementation. Read this FIRST every session. +``` +6. Return to **Your Task** in `scripts/ralph/CLAUDE.md` diff --git a/scripts/ralph/CLAUDE.md b/scripts/ralph/CLAUDE.md new file mode 100644 index 00000000..1ae62bd0 --- /dev/null +++ b/scripts/ralph/CLAUDE.md @@ -0,0 +1,68 @@ +# Ralph Agent Instructions + +> **Ralph directory: `scripts/ralph/`** — All Ralph files live here. Your working directory is the repo root; always use the `scripts/ralph/` prefix for Ralph file operations. + +## Step 0: Read State (ALWAYS FIRST) + +1. Read `scripts/ralph/state.json`. + - If it exists: orient from `currentStory`, `nextAction`, `branch`, `compactionNeeded`. + - If missing: read `scripts/ralph/BOOTSTRAP.md` and follow it to create `scripts/ralph/state.json`, then continue. +2. If `compactionNeeded` is `true`: read `scripts/ralph/COMPACTION.md` and follow it. Do NOT work on stories. STOP after. +3. Proceed to **Your Task** below. + +## Your Task + +1. Check you're on the correct branch from `state.json`. If not, check it out or create from main. +2. Read `scripts/ralph/progress.md` in two reads: the `## Codebase Patterns` section from the top (~60 lines), then recent sessions from the bottom (last ~80 lines). Never read the entire file. +3. Read `scripts/ralph/prd.json` and locate the story matching `state.json.currentStory` — read its acceptance criteria and description. +4. **If story has `iterationMode` field**: read `scripts/ralph/ITERATIVE.md` BEFORE starting work. +5. Implement that single user story. +6. Run quality checks (typecheck, lint, test; plus `validationCommand` if defined). Fix failures before committing. If unfixable: document in `scripts/ralph/progress.md`, do NOT set `passes: true`, end session. +7. **Frontend verification** (if UI): verify in browser using available tools. If none available, note in `scripts/ralph/progress.md`. +8. Update Institutional Memory (below) if you discover reusable conventions or gotchas. Optionally update project-level `CLAUDE.md` files for directory-scoped knowledge. + - When Institutional Memory approaches budget (35+/40 lines): merge duplicate or overlapping entries into single combined lines. + - Combine entries on the same topic into one comprehensive line. + - Never remove entries unless proven wrong or fully subsumed by another entry. +9. Commit ALL changes: `feat: [Story ID] - [Story Title]` +10. **APPEND** to `scripts/ralph/progress.md`: date, story ID, what was done, files changed, learnings for future sessions. + **PROMOTE (mandatory)**: re-read your learnings — any learning useful beyond the current story MUST go to `## Codebase Patterns` (top of `scripts/ralph/progress.md`). Cross-PRD conventions → Institutional Memory. Format: `scripts/ralph/PROGRESS-GUIDE.md`. +11. Update PRD: set `passes: true` for the completed story in `scripts/ralph/prd.json`. If final iteration, compact notes to max 2 lines (~200 chars). Details in `scripts/ralph/PROGRESS-GUIDE.md`. +12. **Update `scripts/ralph/state.json`** (see State Update Rules below). +13. **STOP** — end response immediately. The shell loop detects completion from `scripts/ralph/prd.json`; a new session handles remaining work. + +## State Update Rules + +At END of every session, update `scripts/ralph/state.json`: + +1. Scan `scripts/ralph/prd.json` for the next incomplete story (first with `passes: false`, ordered by `priority`) +2. `currentStory`: that story's ID (or `null` if all complete) +3. `storyTitle`: that story's title (or `"all stories complete"`) +4. `nextAction`: + - If iterative with `currentIteration > 0`: `"iteration N/M (review pass)"` or `"iteration N/M"` + - If iterative with `currentIteration == 0`: `"iteration 1/M"` + - If standard: `"implement"` + - If all complete: `"all stories complete"` +5. `branch`: keep as-is unless the PRD changes +6. `progressTokens`: estimate current size of `scripts/ralph/progress.md` (~15 tokens/line) +7. `compactionNeeded`: set to `true` if `progressTokens` exceeds `compactionThreshold` +8. `lastUpdated`: current date + +## Critical Rules + +These rules MUST be followed every session, even if earlier context is summarized. + +1. **ALWAYS** read `scripts/ralph/state.json` FIRST, before any other file. +2. **ALWAYS** read `scripts/ralph/progress.md` (Codebase Patterns first) before starting work. +3. **ALWAYS** work on exactly ONE story per session. +4. The story to work on comes from `state.json.currentStory` — NEVER scan `scripts/ralph/prd.json` to find it. +5. **ALWAYS** append to `scripts/ralph/progress.md` before ending a session. NEVER replace its contents (except during compaction — see Step 0.2). +6. **ALWAYS** commit all changes before ending a session. Commits MUST pass quality checks. +7. For iterative stories, all iteration-specific rules are in `scripts/ralph/ITERATIVE.md`. +8. After steps 9-13, **STOP**. End the session. A new session handles remaining work. +9. **ALWAYS** update `scripts/ralph/state.json` at the end of every session. +10. If `compactionNeeded` is true, follow `scripts/ralph/COMPACTION.md` — do NOT work on stories. + +## Institutional Memory + +> Format: `- **Name**: description` | Budget: 40 lines max +> Rules: Never remove unless proven wrong. No story-specific details or timestamps. diff --git a/scripts/ralph/COMPACTION.md b/scripts/ralph/COMPACTION.md new file mode 100644 index 00000000..504d3133 --- /dev/null +++ b/scripts/ralph/COMPACTION.md @@ -0,0 +1,33 @@ +# Compaction Session + +> This file is read ONLY when `scripts/ralph/state.json` has `compactionNeeded: true`. +> This session's ONLY job is compacting `scripts/ralph/progress.md`. Do NOT work on any story. + +## Steps + +1. Read `scripts/ralph/progress.md` in chunks (use offset/limit, ~300 lines per chunk) +2. **Promote before compacting**: scan session entries for learnings NOT already in `## Codebase Patterns`. Add any missing reusable learnings to that section before proceeding. +3. Rewrite it following these rules: + - **Keep header** (title, start date) + - **Keep Codebase Patterns section intact** (including any additions from step 2) + - **Keep the last 3-4 session entries intact** (the most recent entries from the bottom of the file) + - **Compact only INTERMEDIATE sessions** (between Codebase Patterns and the last 3-4 entries) to this format: + ```markdown + ## [Date] - [Story ID] (Iteration X/Y) + - **Implemented**: [1 sentence] + - **Files**: [comma-separated, or "None"] + - **Key learnings**: [only genuinely reusable insights] + --- + ``` + - **Ultra-compact for verification-only sessions**: + ```markdown + ## [Date] - [Story ID] (Iteration X/Y) + - **Implemented**: Verification pass — no changes needed. + - **Files**: None + --- + ``` + - **Remove from intermediate sessions**: line numbers (L42, L103...), verbose audit results, citation counts, excessive verbosity +4. Write the compacted `scripts/ralph/progress.md` +5. Update `scripts/ralph/state.json`: set `compactionNeeded: false`, update `progressTokens` with new estimate +6. Commit: `chore: compact progress.md` +7. STOP — next session resumes story work diff --git a/scripts/ralph/ITERATIVE.md b/scripts/ralph/ITERATIVE.md new file mode 100644 index 00000000..11cc70e1 --- /dev/null +++ b/scripts/ralph/ITERATIVE.md @@ -0,0 +1,117 @@ +# Iterative User Stories Guide + +> This file is read ONLY when the current User Story has an `iterationMode` field. +> For standard (non-iterative) stories, this file is not loaded. + +These rules SUPPLEMENT the standard workflow in `scripts/ralph/CLAUDE.md`. Follow all CLAUDE.md steps as usual, with the overrides below. + +--- + +## When to Use Iterative Mode + +Iterative mode is designed for tasks where **multiple passes improve quality** and **context rot would degrade a single-pass attempt**. Each session gets a fresh context, so later iterations naturally compensate for earlier ones. + +Good candidates: +- Auditing/reviewing N files or components (spread across iterations) +- Complex refactors where a review pass catches mistakes from the implementation pass +- Tasks with high error surface where self-correction across sessions matters + +**NOT** for stories that are simply too large — split those into multiple standard stories instead. + +## Iteration Modes + +The `iterationMode` field determines completion behavior: + +| Mode | Completion Criterion | Use Case | +|---|---|---| +| `fixed` | `currentIteration >= maxIterations` | Predetermined batch work: audit N files, process N items, multi-pass review | + +> Future modes (e.g., `adaptive` — agent decides when done) may be added. Currently only `fixed` is supported. + +--- + +## CRITICAL: One Iteration = One Session + +**This is the most important rule for iterative stories.** + +You MUST: +1. Complete exactly ONE iteration of meaningful progress +2. Follow all CLAUDE.md steps (standard ordering: quality checks → commit → progress.md → update PRD) +3. **STOP and END the session** — a new session handles the next iteration + +NEVER attempt multiple iterations in a single session. A new session will be spawned for the next iteration. + +--- + +## Iteration Strategy + +Before starting work, plan how to distribute effort across `maxIterations`: + +1. **Read the story's `notes` field (in `scripts/ralph/prd.json`) and `scripts/ralph/progress.md`** to understand what previous iterations did +2. **Distribute work logically**: each iteration should focus on a distinct subset or aspect +3. **Reserve later iterations for review**: if `maxIterations` is 3+, the last 1-2 iterations should review and fix issues from earlier ones rather than doing net-new work +4. **Avoid redundancy**: if a previous iteration already handled something, move on + +Example distribution for `maxIterations: 5` on an audit task: +- Iterations 1-3: Audit and fix files in batches +- Iteration 4: Cross-file consistency review, fix regressions +- Iteration 5: Final validation pass, edge cases, documentation + +--- + +## Commit Format + +For iterative stories, append the iteration number to the standard commit format: + +``` +feat: [Story ID] - [Story Title] (iteration N) +``` + +--- + +## Handling No-Change Iterations + +If a review iteration finds no issues to fix: +- This is a **valid outcome** — it means earlier iterations did their job +- Update `notes` with: `"Iteration X/N: Reviewed [scope] — no changes required"` +- Commit only the `scripts/ralph/prd.json` update (the PRD change itself is the meaningful output) +- Do NOT invent unnecessary changes to satisfy "meaningful progress" + +--- + +## Quality Check Failures + +If quality checks fail during an iterative session: +- Attempt to fix the issue within the same session +- If the fix succeeds: proceed normally (commit, update progress, update PRD) +- If you cannot fix it: document the failure in `scripts/ralph/progress.md`, do **NOT** increment `currentIteration`, and end the session. The next session will retry the same iteration with fresh context. + +--- + +## PRD Update Rules (overrides the standard PRD update step in `scripts/ralph/CLAUDE.md`) + +At the END of each session, update `scripts/ralph/prd.json` for the current story: + +1. Increment `currentIteration` (e.g., 0 → 1) +2. Append to `notes` using format: `"Iteration X/N: [what was done]"` — separate entries with ` | ` +3. CRITICAL: Set `passes: true` ONLY when `currentIteration >= maxIterations` + +NEVER set `passes: true` just because tests pass or work appears complete early. The iteration count is the **sole completion criterion** for `fixed` mode. + +**Example (mid-iteration):** +```json +{ + "currentIteration": 2, + "passes": false, + "notes": "Iteration 1/5: Audited files A, B, C | Iteration 2/5: Fixed naming in A, reformatted B" +} +``` + +**Example (final iteration):** +```json +{ + "currentIteration": 5, + "passes": true, + "notes": "Iteration 1/5: Audited files A, B, C | ... | Iteration 5/5: Final review pass — all clean. Complete." +} +``` \ No newline at end of file diff --git a/scripts/ralph/PROGRESS-GUIDE.md b/scripts/ralph/PROGRESS-GUIDE.md new file mode 100644 index 00000000..9787d739 --- /dev/null +++ b/scripts/ralph/PROGRESS-GUIDE.md @@ -0,0 +1,51 @@ +# Progress Guide + +> Reference for writing progress reports and managing the experiential memory layer. +> Read this file when you need the full format details for `scripts/ralph/progress.md` or `scripts/ralph/prd.json` notes. + +## Progress Report Format + +APPEND to `scripts/ralph/progress.md` (NEVER replace, ALWAYS append): +```markdown +## [Date/Time] - [Story ID] +- What was implemented +- Files changed +- **Learnings for future sessions:** + - 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 sessions avoid repeating mistakes. + +## Codebase Patterns Section + +Maintain a `## Codebase Patterns` section at the **TOP** of `scripts/ralph/progress.md` (right after the header). Create it if missing: +```markdown +## Codebase Patterns +> Reusable patterns discovered during implementation. Read this FIRST every session. + +- **Pattern Name**: description +``` + +Budget: **30 lines max**. When approaching the limit, merge related patterns. Never add story-specific details or timestamps. + +## Persist Learnings + +After implementing a story, persist reusable discoveries to two places: + +- **Codebase Patterns** (top of `scripts/ralph/progress.md`): General, reusable patterns +- **Institutional Memory** (bottom of `scripts/ralph/CLAUDE.md`): Conventions, gotchas, cross-file dependencies +- Optionally update project-level `CLAUDE.md` files in relevant directories for directory-scoped knowledge +- NEVER add: story-specific details, temporary debugging notes, or info already elsewhere +- Only add patterns that are **genuinely reusable** across stories + +## Notes Compaction (prd.json) + +When writing the FINAL notes for a story (the one that sets `passes: true`): +- Compact ALL previous notes into a single summary +- Final `notes` field must be **max 2 lines** (~200 chars) +- Keep: what was done, files changed, key ambiguities +- Remove: line numbers, audit scores, citation counts, verification details +- Format: `"[Summary of what was integrated/changed]. [Key ambiguity if any]. Complete."` diff --git a/scripts/ralph/prd.json.example b/scripts/ralph/prd.json.example new file mode 100644 index 00000000..874659be --- /dev/null +++ b/scripts/ralph/prd.json.example @@ -0,0 +1,53 @@ +{ + "project": "MyProject", + "branchName": "ralph/user-preferences", + "description": "User Preferences - Add configurable user preferences with persistence", + "userStories": [ + { + "id": "US-001", + "title": "Add preferences table to database", + "description": "As a developer, I need a preferences table so that user settings persist across sessions.", + "acceptanceCriteria": [ + "Preferences table created with user_id foreign key", + "Default row seeded on user creation via trigger", + "Migration runs without errors", + "Typecheck passes" + ], + "priority": 1, + "passes": false, + "notes": "" + }, + { + "id": "US-002", + "title": "Build preferences UI panel", + "description": "As a user, I want a settings panel so that I can configure my preferences visually.", + "acceptanceCriteria": [ + "Settings panel accessible from user menu", + "All preference fields rendered with correct input types", + "Save button persists changes to backend", + "Verify in browser: panel renders, fields are interactive, save works" + ], + "priority": 2, + "passes": false, + "notes": "" + }, + { + "id": "US-003", + "title": "Audit configuration files for consistency", + "description": "As a developer, I want all configuration files audited so that they follow project conventions.", + "acceptanceCriteria": [ + "Each configuration file checked against project conventions", + "Non-compliant files updated to match conventions", + "All changes documented in progress notes", + "Lint passes after each iteration" + ], + "priority": 3, + "passes": false, + "notes": "", + "iterationMode": "fixed", + "maxIterations": 3, + "currentIteration": 0, + "validationCommand": "npm run lint" + } + ] +} diff --git a/scripts/ralph/prompt.md b/scripts/ralph/prompt.md new file mode 100644 index 00000000..679b6a27 --- /dev/null +++ b/scripts/ralph/prompt.md @@ -0,0 +1,80 @@ +# Ralph Agent Instructions + +> **Ralph directory: `scripts/ralph/`** — All Ralph files live here. Your working directory is the repo root; always use the `scripts/ralph/` prefix for Ralph file operations. + +## Step 0: Read State (ALWAYS FIRST) + +1. Read `scripts/ralph/state.json`. + - If it exists: orient from `currentStory`, `nextAction`, `branch`, `compactionNeeded`. + - If missing: read `scripts/ralph/BOOTSTRAP.md` and follow it to create `scripts/ralph/state.json`, then continue. +2. If `compactionNeeded` is `true`: read `scripts/ralph/COMPACTION.md` and follow it. Do NOT work on stories. STOP after. +3. Proceed to **Your Task** below. + +## Your Task + +1. Check you're on the correct branch from `state.json`. If not, check it out or create from main. +2. Read `scripts/ralph/progress.md` in two reads: the `## Codebase Patterns` section from the top (~60 lines), then recent sessions from the bottom (last ~80 lines). Never read the entire file. +3. Read `scripts/ralph/prd.json` and locate the story matching `state.json.currentStory` — read its acceptance criteria and description. +4. **If story has `iterationMode` field**: read `scripts/ralph/ITERATIVE.md` BEFORE starting work. +5. Implement that single user story. +6. Run quality checks (typecheck, lint, test; plus `validationCommand` if defined). Fix failures before committing. If unfixable: document in `scripts/ralph/progress.md`, do NOT set `passes: true`, end session. +7. **Frontend verification** (if UI): load the `dev-browser` skill, navigate to the relevant page, verify changes work, take a screenshot if helpful. +8. Update AGENTS.md files if you discover reusable conventions or gotchas in directories you modified. Optionally update directory-scoped AGENTS.md files for module-specific knowledge. + - When AGENTS.md files grow large: merge duplicate or overlapping entries into single combined lines. + - Only add patterns that are **genuinely reusable** across stories. + - Never add: story-specific details, temporary debugging notes, or info already in `scripts/ralph/progress.md`. +9. Commit ALL changes: `feat: [Story ID] - [Story Title]` +10. **APPEND** to `scripts/ralph/progress.md`: date, story ID, thread URL, what was done, files changed, learnings for future sessions. + **PROMOTE (mandatory)**: re-read your learnings — any learning useful beyond the current story MUST go to `## Codebase Patterns` (top of `scripts/ralph/progress.md`). Cross-PRD conventions → AGENTS.md files. Format: `scripts/ralph/PROGRESS-GUIDE.md`. +11. Update PRD: set `passes: true` for the completed story in `scripts/ralph/prd.json`. If final iteration, compact notes to max 2 lines (~200 chars). Details in `scripts/ralph/PROGRESS-GUIDE.md`. +12. **Update `scripts/ralph/state.json`** (see State Update Rules below). +13. **STOP** — end response immediately. The shell loop detects completion from `scripts/ralph/prd.json`; a new session handles remaining work. + +## Progress Report Format + +APPEND to `scripts/ralph/progress.md` (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 sessions:** + - 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") +--- +``` + +Include the thread URL so future sessions can use the `read_thread` tool to reference previous work if needed. + +## State Update Rules + +At END of every session, update `scripts/ralph/state.json`: + +1. Scan `scripts/ralph/prd.json` for the next incomplete story (first with `passes: false`, ordered by `priority`) +2. `currentStory`: that story's ID (or `null` if all complete) +3. `storyTitle`: that story's title (or `"all stories complete"`) +4. `nextAction`: + - If iterative with `currentIteration > 0`: `"iteration N/M (review pass)"` or `"iteration N/M"` + - If iterative with `currentIteration == 0`: `"iteration 1/M"` + - If standard: `"implement"` + - If all complete: `"all stories complete"` +5. `branch`: keep as-is unless the PRD changes +6. `progressTokens`: estimate current size of `scripts/ralph/progress.md` (~15 tokens/line) +7. `compactionNeeded`: set to `true` if `progressTokens` exceeds `compactionThreshold` +8. `lastUpdated`: current date + +## Critical Rules + +These rules MUST be followed every session, even if earlier context is summarized. + +1. **ALWAYS** read `scripts/ralph/state.json` FIRST, before any other file. +2. **ALWAYS** read `scripts/ralph/progress.md` (Codebase Patterns first) before starting work. +3. **ALWAYS** work on exactly ONE story per session. +4. The story to work on comes from `state.json.currentStory` — NEVER scan `scripts/ralph/prd.json` to find it. +5. **ALWAYS** append to `scripts/ralph/progress.md` before ending a session. NEVER replace its contents (except during compaction — see Step 0.2). +6. **ALWAYS** commit all changes before ending a session. Commits MUST pass quality checks. +7. For iterative stories, all iteration-specific rules are in `scripts/ralph/ITERATIVE.md`. +8. After steps 9-13, **STOP**. End the session. A new session handles remaining work. +9. **ALWAYS** update `scripts/ralph/state.json` at the end of every session. +10. If `compactionNeeded` is true, follow `scripts/ralph/COMPACTION.md` — do NOT work on stories. diff --git a/scripts/ralph/ralph.sh b/scripts/ralph/ralph.sh new file mode 100755 index 00000000..6c872006 --- /dev/null +++ b/scripts/ralph/ralph.sh @@ -0,0 +1,202 @@ +#!/bin/bash +# Ralph Wiggum - Long-running AI agent loop +# Usage: ./ralph.sh [--tool amp|claude] [--debug] [max_sessions] + +set -e + +# Parse arguments +TOOL="amp" +MAX_SESSIONS=10 +DEBUG=false + +while [[ $# -gt 0 ]]; do + case $1 in + --tool) + TOOL="$2" + shift 2 + ;; + --tool=*) + TOOL="${1#*=}" + shift + ;; + --debug) + DEBUG=true + shift + ;; + *) + if [[ "$1" =~ ^[0-9]+$ ]]; then + MAX_SESSIONS="$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 + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PRD_FILE="$SCRIPT_DIR/prd.json" +PROGRESS_FILE="$SCRIPT_DIR/progress.md" +ARCHIVE_DIR="$SCRIPT_DIR/archive" +STATE_FILE="$SCRIPT_DIR/state.json" +LAST_BRANCH_FILE="$SCRIPT_DIR/.last-branch" + +# Validate required files exist +if [ ! -f "$PRD_FILE" ]; then + echo "Error: PRD file not found at $PRD_FILE" + echo "Create a prd.json first (see prd.json.example)." + exit 1 +fi + +# Validate PRD is valid JSON +if ! jq empty "$PRD_FILE" 2>/dev/null; then + echo "Error: $PRD_FILE is not valid JSON." + exit 1 +fi + +# Validate required PRD fields +if ! jq -e '.project and .branchName and .userStories and (.userStories | length > 0)' "$PRD_FILE" > /dev/null 2>&1; then + echo "Error: $PRD_FILE is missing required fields (project, branchName, userStories)." + exit 1 +fi + +# Archive previous run if branch changed +if [ -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 + DATE=$(date +%Y-%m-%d) + 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/" + [ -f "$STATE_FILE" ] && cp "$STATE_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" + echo "" >> "$PROGRESS_FILE" + echo "## Codebase Patterns" >> "$PROGRESS_FILE" + echo "> Reusable patterns discovered during implementation. Read this FIRST every session." >> "$PROGRESS_FILE" + # Reset state.json for new run (will be re-bootstrapped) + rm -f "$STATE_FILE" + fi +fi + +# Track current branch +CURRENT_BRANCH=$(jq -r '.branchName // empty' "$PRD_FILE" 2>/dev/null || echo "") +if [ -n "$CURRENT_BRANCH" ]; then + echo "$CURRENT_BRANCH" > "$LAST_BRANCH_FILE" +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" + echo "" >> "$PROGRESS_FILE" + echo "## Codebase Patterns" >> "$PROGRESS_FILE" + echo "> Reusable patterns discovered during implementation. Read this FIRST every session." >> "$PROGRESS_FILE" +fi + +# Bootstrap state.json if it doesn't exist +if [ ! -f "$STATE_FILE" ]; then + echo "Bootstrapping state.json from prd.json..." + FIRST_STORY_ID=$(jq -r '[.userStories[] | select(.passes == false)] | sort_by(.priority) | first | .id // empty' "$PRD_FILE") + FIRST_STORY_TITLE=$(jq -r '[.userStories[] | select(.passes == false)] | sort_by(.priority) | first | .title // empty' "$PRD_FILE") + PRD_BRANCH=$(jq -r '.branchName // ""' "$PRD_FILE") + + if [ -n "$FIRST_STORY_ID" ]; then + ITER_MODE=$(jq -r --arg id "$FIRST_STORY_ID" '[.userStories[] | select(.id == $id)] | first | .iterationMode // empty' "$PRD_FILE") + MAX_ITER=$(jq -r --arg id "$FIRST_STORY_ID" '[.userStories[] | select(.id == $id)] | first | .maxIterations // 0' "$PRD_FILE") + + if [ -n "$ITER_MODE" ] && [ "$ITER_MODE" != "null" ]; then + NEXT_ACTION="iteration 1/$MAX_ITER" + else + NEXT_ACTION="implement" + fi + + jq -n \ + --arg branch "$PRD_BRANCH" \ + --arg story "$FIRST_STORY_ID" \ + --arg title "$FIRST_STORY_TITLE" \ + --arg action "$NEXT_ACTION" \ + --arg date "$(date +%Y-%m-%d)" \ + '{ + branch: $branch, + currentStory: $story, + storyTitle: $title, + nextAction: $action, + progressTokens: 0, + compactionNeeded: false, + compactionThreshold: 10000, + lastUpdated: $date + }' > "$STATE_FILE" + echo " Created state.json: $FIRST_STORY_ID - $FIRST_STORY_TITLE" + fi +fi + +echo "Starting Ralph - Tool: $TOOL - Max sessions: $MAX_SESSIONS - Debug: $DEBUG" + +for i in $(seq 1 $MAX_SESSIONS); do + echo "" + echo "===============================================================" + echo " Ralph Session $i of $MAX_SESSIONS ($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 flags: + # Normal: --print only (minimal, proven stable) + # Debug: full SDK stack (stream-json requires --verbose, + # --include-partial-messages requires stream-json) + CLAUDE_ARGS=( + --dangerously-skip-permissions + --print + ) + if [[ "$DEBUG" == "true" ]]; then + CLAUDE_ARGS+=(--output-format stream-json --verbose --include-partial-messages) + fi + + OUTPUT=$( + claude "${CLAUDE_ARGS[@]}" < "$SCRIPT_DIR/CLAUDE.md" 2>&1 | tee /dev/stderr + ) || true + fi + + # Check for completion by reading prd.json directly (ground truth) + # Immune to false positives from agent text output + ALL_PASS=$(jq '[.userStories[].passes] | all' "$PRD_FILE" 2>/dev/null || echo "false") + if [ "$ALL_PASS" = "true" ]; then + echo "" + echo "Ralph completed all tasks!" + echo "Completed at session $i of $MAX_SESSIONS" + exit 0 + fi + + # Validate state.json integrity after session + if [ -f "$STATE_FILE" ]; then + if ! jq -e '.currentStory and .lastUpdated and .branch' "$STATE_FILE" > /dev/null 2>&1; then + echo "Warning: state.json may be malformed after session $i. Check manually." + fi + fi + + echo "Session $i complete. Continuing..." + sleep 2 +done + +echo "" +echo "Ralph reached max sessions ($MAX_SESSIONS) without completing all tasks." +echo "Check $PROGRESS_FILE for status." +exit 1 \ No newline at end of file diff --git a/skills/prd/SKILL.md b/skills/prd/SKILL.md deleted file mode 100644 index 3c2f7acf..00000000 --- a/skills/prd/SKILL.md +++ /dev/null @@ -1,241 +0,0 @@ ---- -name: prd -description: "Generate a Product Requirements Document (PRD) for a new feature. Use when planning a feature, starting a new project, or when asked to create a PRD. Triggers on: create a prd, write prd for, plan this feature, requirements for, spec out." -user-invocable: true ---- - -# PRD Generator - -Create detailed Product Requirements Documents that are clear, actionable, and suitable for implementation. - ---- - -## The Job - -1. Receive a feature description from the user -2. Ask 3-5 essential clarifying questions (with lettered options) -3. Generate a structured PRD based on answers -4. Save to `tasks/prd-[feature-name].md` - -**Important:** Do NOT start implementing. Just create the PRD. - ---- - -## Step 1: Clarifying Questions - -Ask only critical questions where the initial prompt is ambiguous. Focus on: - -- **Problem/Goal:** What problem does this solve? -- **Core Functionality:** What are the key actions? -- **Scope/Boundaries:** What should it NOT do? -- **Success Criteria:** How do we know it's done? - -### Format Questions Like This: - -``` -1. What is the primary goal of this feature? - A. Improve user onboarding experience - B. Increase user retention - C. Reduce support burden - D. Other: [please specify] - -2. Who is the target user? - A. New users only - B. Existing users only - C. All users - D. Admin users only - -3. What is the scope? - A. Minimal viable version - B. Full-featured implementation - C. Just the backend/API - D. Just the UI -``` - -This lets users respond with "1A, 2C, 3B" for quick iteration. Remember to indent the options. - ---- - -## Step 2: PRD Structure - -Generate the PRD with these sections: - -### 1. Introduction/Overview -Brief description of the feature and the problem it solves. - -### 2. Goals -Specific, measurable objectives (bullet list). - -### 3. User Stories -Each story needs: -- **Title:** Short descriptive name -- **Description:** "As a [user], I want [feature] so that [benefit]" -- **Acceptance Criteria:** Verifiable checklist of what "done" means - -Each story should be small enough to implement in one focused session. - -**Format:** -```markdown -### US-001: [Title] -**Description:** As a [user], I want [feature] so that [benefit]. - -**Acceptance Criteria:** -- [ ] Specific verifiable criterion -- [ ] Another criterion -- [ ] Typecheck/lint passes -- [ ] **[UI stories only]** Verify in browser using dev-browser skill -``` - -**Important:** -- Acceptance criteria must be verifiable, not vague. "Works correctly" is bad. "Button shows confirmation dialog before deleting" is good. -- **For any story with UI changes:** Always include "Verify in browser using dev-browser skill" as acceptance criteria. This ensures visual verification of frontend work. - -### 4. Functional Requirements -Numbered list of specific functionalities: -- "FR-1: The system must allow users to..." -- "FR-2: When a user clicks X, the system must..." - -Be explicit and unambiguous. - -### 5. Non-Goals (Out of Scope) -What this feature will NOT include. Critical for managing scope. - -### 6. Design Considerations (Optional) -- UI/UX requirements -- Link to mockups if available -- Relevant existing components to reuse - -### 7. Technical Considerations (Optional) -- Known constraints or dependencies -- Integration points with existing systems -- Performance requirements - -### 8. Success Metrics -How will success be measured? -- "Reduce time to complete X by 50%" -- "Increase conversion rate by 10%" - -### 9. Open Questions -Remaining questions or areas needing clarification. - ---- - -## Writing for Junior Developers - -The PRD reader may be a junior developer or AI agent. Therefore: - -- Be explicit and unambiguous -- Avoid jargon or explain it -- Provide enough detail to understand purpose and core logic -- Number requirements for easy reference -- Use concrete examples where helpful - ---- - -## Output - -- **Format:** Markdown (`.md`) -- **Location:** `tasks/` -- **Filename:** `prd-[feature-name].md` (kebab-case) - ---- - -## Example PRD - -```markdown -# PRD: Task Priority System - -## Introduction - -Add priority levels to tasks so users can focus on what matters most. Tasks can be marked as high, medium, or low priority, with visual indicators and filtering to help users manage their workload effectively. - -## Goals - -- Allow assigning priority (high/medium/low) to any task -- Provide clear visual differentiation between priority levels -- Enable filtering and sorting by priority -- Default new tasks to medium priority - -## User Stories - -### US-001: Add priority field to database -**Description:** As a developer, I need to store task priority so it persists across sessions. - -**Acceptance Criteria:** -- [ ] Add priority column to tasks table: 'high' | 'medium' | 'low' (default 'medium') -- [ ] Generate and run migration successfully -- [ ] Typecheck passes - -### US-002: Display priority indicator on task cards -**Description:** As a user, I want to see task priority at a glance so I know what needs attention first. - -**Acceptance Criteria:** -- [ ] Each task card shows colored priority badge (red=high, yellow=medium, gray=low) -- [ ] Priority visible without hovering or clicking -- [ ] Typecheck passes -- [ ] Verify in browser using dev-browser skill - -### US-003: Add priority selector to task edit -**Description:** As a user, I want to change a task's priority when editing it. - -**Acceptance Criteria:** -- [ ] Priority dropdown in task edit modal -- [ ] Shows current priority as selected -- [ ] Saves immediately on selection change -- [ ] Typecheck passes -- [ ] Verify in browser using dev-browser skill - -### US-004: Filter tasks by priority -**Description:** As a user, I want to filter the task list to see only high-priority items when I'm focused. - -**Acceptance Criteria:** -- [ ] Filter dropdown with options: All | High | Medium | Low -- [ ] Filter persists in URL params -- [ ] Empty state message when no tasks match filter -- [ ] Typecheck passes -- [ ] Verify in browser using dev-browser skill - -## Functional Requirements - -- FR-1: Add `priority` field to tasks table ('high' | 'medium' | 'low', default 'medium') -- FR-2: Display colored priority badge on each task card -- FR-3: Include priority selector in task edit modal -- FR-4: Add priority filter dropdown to task list header -- FR-5: Sort by priority within each status column (high to medium to low) - -## Non-Goals - -- No priority-based notifications or reminders -- No automatic priority assignment based on due date -- No priority inheritance for subtasks - -## Technical Considerations - -- Reuse existing badge component with color variants -- Filter state managed via URL search params -- Priority stored in database, not computed - -## Success Metrics - -- Users can change priority in under 2 clicks -- High-priority tasks immediately visible at top of lists -- No regression in task list performance - -## Open Questions - -- Should priority affect task ordering within a column? -- Should we add keyboard shortcuts for priority changes? -``` - ---- - -## Checklist - -Before saving the PRD: - -- [ ] Asked clarifying questions with lettered options -- [ ] Incorporated user's answers -- [ ] User stories are small and specific -- [ ] Functional requirements are numbered and unambiguous -- [ ] Non-goals section defines clear boundaries -- [ ] Saved to `tasks/prd-[feature-name].md` diff --git a/skills/ralph/SKILL.md b/skills/ralph/SKILL.md index e402ab8d..43274c75 100644 --- a/skills/ralph/SKILL.md +++ b/skills/ralph/SKILL.md @@ -1,258 +1,292 @@ --- name: ralph -description: "Convert PRDs to prd.json format for the Ralph autonomous agent system. Use when you have an existing PRD and need to convert it to Ralph's JSON format. Triggers on: convert this prd, turn this into ralph format, create prd.json from this, ralph json." +description: "Generate a Product Requirements Document and Ralph-compatible prd.json for a new feature. Use when planning a feature, starting a new project, or when asked to create a PRD. Triggers on: create a prd, write prd for, plan this feature, requirements for, spec out." user-invocable: true --- -# Ralph PRD Converter +# PRD Generator -Converts existing PRDs to the prd.json format that Ralph uses for autonomous execution. +Produce two outputs for every feature request: ---- - -## The Job +1. **Human-readable PRD**: `tasks/prd-[feature-name].md` +2. **Machine-readable PRD**: `scripts/ralph/prd.json` (consumed by Ralph agent loop) -Take a PRD (markdown file or text) and convert it to `prd.json` in your ralph directory. +**IMPORTANT:** Do NOT start implementing. Only create the PRD and JSON. --- -## Output Format +## The Job -```json -{ - "project": "[Project Name]", - "branchName": "ralph/[feature-name-kebab-case]", - "description": "[Feature description from PRD title/intro]", - "userStories": [ - { - "id": "US-001", - "title": "[Story title]", - "description": "As a [user], I want [feature] so that [benefit]", - "acceptanceCriteria": [ - "Criterion 1", - "Criterion 2", - "Typecheck passes" - ], - "priority": 1, - "passes": false, - "notes": "" - } - ] -} -``` +1. Receive a feature description from the user +2. Ask 3-5 clarifying questions (lettered options for quick answers) +3. **Archive previous run** if `prd.json` already exists with a different `branchName` (see Archiving below) +4. Generate the PRD markdown file +5. Generate the `prd.json` file +6. Save both files --- -## Story Size: The Number One Rule - -**Each story must be completable in ONE Ralph iteration (one context window).** - -Ralph spawns a fresh Amp instance per iteration with no memory of previous work. If a story is too big, the LLM runs out of context before finishing and produces broken code. +## Step 1: Clarifying Questions -### Right-sized stories: -- Add a database column and migration -- Add a UI component to an existing page -- Update a server action with new logic -- Add a filter dropdown to a list +Ask only where the initial prompt is ambiguous. Format with lettered options so the user can reply "1A, 2C, 3B": -### Too big (split these): -- "Build the entire dashboard" - Split into: schema, queries, UI components, filters -- "Add authentication" - Split into: schema, middleware, login UI, session handling -- "Refactor the API" - Split into one story per endpoint or pattern - -**Rule of thumb:** If you cannot describe the change in 2-3 sentences, it is too big. - ---- - -## Story Ordering: Dependencies First +``` +1. What is the primary goal? + A. [option] B. [option] C. [option] D. Other: [specify] -Stories execute in priority order. Earlier stories must not depend on later ones. +2. Who is the target user? + A. [option] B. [option] C. [option] -**Correct order:** -1. Schema/database changes (migrations) -2. Server actions / backend logic -3. UI components that use the backend -4. Dashboard/summary views that aggregate data +3. What is the scope? + A. Minimal viable version B. Full-featured C. Backend only D. UI only +``` -**Wrong order:** -1. UI component (depends on schema that does not exist yet) -2. Schema change +Focus on: problem/goal, core functionality, scope boundaries, success criteria. --- -## Acceptance Criteria: Must Be Verifiable +## Step 2: PRD Structure (`tasks/prd-[feature-name].md`) -Each criterion must be something Ralph can CHECK, not something vague. +Required sections in order: -### Good criteria (verifiable): -- "Add `status` column to tasks table with default 'pending'" -- "Filter dropdown has options: All, Active, Completed" -- "Clicking delete shows confirmation dialog" -- "Typecheck passes" -- "Tests pass" +| # | Section | Content | +|---|---------|---------| +| 1 | **Title + Summary** | One-paragraph overview of the feature and problem it solves | +| 2 | **Goals** | 3-6 bullet points, specific and measurable | +| 3 | **User Stories** | See Story Format below | +| 4 | **Functional Requirements** | Numbered list: "FR-1: The system must..." | +| 5 | **Non-Goals** | What this feature will NOT include | +| 6 | **Technical Notes** | Rule file references, gotchas, file paths, dependencies | +| 7 | **Open Questions** | Remaining unknowns | -### Bad criteria (vague): -- "Works correctly" -- "User can do X easily" -- "Good UX" -- "Handles edge cases" +**CRITICAL: PRD must stay under 150 lines.** Be concise. Use tables over prose. -### Always include as final criterion: -``` -"Typecheck passes" -``` +### Story Format -For stories with testable logic, also include: -``` -"Tests pass" -``` - -### For stories that change UI, also include: -``` -"Verify in browser using dev-browser skill" +```markdown +### US-001: Short title (under 50 chars) +**Description:** As a [role], I want [feature] so that [benefit]. + +**Acceptance Criteria:** +- Specific verifiable statement +- Another verifiable statement +- Quality gate (e.g., "Typecheck passes", "Tests pass", "Build succeeds") + +**Iteration (only if iterative):** +- Mode: fixed +- Max iterations: N +- Current iteration: 0 +- Validation: `command` (optional) ``` -Frontend stories are NOT complete until visually verified. Ralph will use the dev-browser skill to navigate to the page, interact with the UI, and confirm changes work. +### Story Rules ---- +| Rule | Detail | +|------|--------| +| **Scope** | ALWAYS completable in a single context window | +| **Criteria count** | 3-6 verifiable statements per story | +| **Quality gates** | ALWAYS include at least one project-appropriate quality gate criterion (e.g., "Typecheck passes", "Tests pass", "Build succeeds") | +| **Browser verification** | UI stories ALWAYS include a browser verification criterion (e.g., "Verify in browser using available tools") | +| **ID format** | `US-NNN` (zero-padded, sequential) | +| **Title length** | Under 50 characters (must work as commit message suffix) | +| **Splitting** | NEVER use iterations for oversized stories — split them instead | -## Conversion Rules +**NEVER** write vague acceptance criteria. "Works correctly" is bad. "Returns 404 when resource not found" is good. -1. **Each user story becomes one JSON entry** -2. **IDs**: Sequential (US-001, US-002, etc.) -3. **Priority**: Based on dependency order, then document order -4. **All stories**: `passes: false` and empty `notes` -5. **branchName**: Derive from feature name, kebab-case, prefixed with `ralph/` -6. **Always add**: "Typecheck passes" to every story's acceptance criteria +### Standard vs Iterative Stories ---- +| Type | When to Use | Iteration Fields | +|------|-------------|-----------------| +| **Standard** | Single-pass work (most stories) | None | +| **Iterative** | Batch/multi-pass work with known count (audit N files, process N items) | Required (see below) | -## Splitting Large PRDs +**IMPORTANT:** Iterative stories are for batch work, NOT for stories that are too big. If a story is too big, split it into multiple standard stories. -If a PRD has big features, split them: - -**Original:** -> "Add user notification system" - -**Split into:** -1. US-001: Add notifications table to database -2. US-002: Create notification service for sending notifications -3. US-003: Add notification bell icon to header -4. US-004: Create notification dropdown panel -5. US-005: Add mark-as-read functionality -6. US-006: Add notification preferences page - -Each is one focused change that can be completed and verified independently. +For iterative story rules, see `scripts/ralph/ITERATIVE.md`. --- -## Example - -**Input PRD:** -```markdown -# Task Status Feature +## Step 3: Ralph JSON (`scripts/ralph/prd.json`) -Add ability to mark tasks with different statuses. +**CRITICAL:** This file is the machine-readable contract consumed by Ralph. Every field matters. -## Requirements -- Toggle between pending/in-progress/done on task list -- Filter list by status -- Show status badge on each task -- Persist status in database -``` +### Schema -**Output prd.json:** ```json { - "project": "TaskApp", - "branchName": "ralph/task-status", - "description": "Task Status Feature - Track task progress with status indicators", + "project": "ProjectName", + "branchName": "ralph/feature-name", + "description": "Brief description of the feature", "userStories": [ { "id": "US-001", - "title": "Add status field to tasks table", - "description": "As a developer, I need to store task status in the database.", + "title": "Short title under 50 chars", + "description": "As a [role], I want [feature] so that [benefit].", "acceptanceCriteria": [ - "Add status column: 'pending' | 'in_progress' | 'done' (default 'pending')", - "Generate and run migration successfully", - "Typecheck passes" + "Verifiable statement as plain string", + "Another verifiable statement", + "Quality gate passes" ], "priority": 1, "passes": false, "notes": "" - }, - { - "id": "US-002", - "title": "Display status badge on task cards", - "description": "As a user, I want to see task status at a glance.", - "acceptanceCriteria": [ - "Each task card shows colored status badge", - "Badge colors: gray=pending, blue=in_progress, green=done", - "Typecheck passes", - "Verify in browser using dev-browser skill" - ], - "priority": 2, - "passes": false, - "notes": "" - }, - { - "id": "US-003", - "title": "Add status toggle to task list rows", - "description": "As a user, I want to change task status directly from the list.", - "acceptanceCriteria": [ - "Each row has status dropdown or toggle", - "Changing status saves immediately", - "UI updates without page refresh", - "Typecheck passes", - "Verify in browser using dev-browser skill" - ], - "priority": 3, - "passes": false, - "notes": "" - }, - { - "id": "US-004", - "title": "Filter tasks by status", - "description": "As a user, I want to filter the list to see only certain statuses.", - "acceptanceCriteria": [ - "Filter dropdown: All | Pending | In Progress | Done", - "Filter persists in URL params", - "Typecheck passes", - "Verify in browser using dev-browser skill" - ], - "priority": 4, - "passes": false, - "notes": "" } ] } ``` +### Project-Level Fields + +| Field | Type | Rules | +|-------|------|-------| +| `project` | string | Project name (from repo name, CLAUDE.md, or user input) | +| `branchName` | string | **ALWAYS** `ralph/[feature-name]` (kebab-case) | +| `description` | string | One-line feature summary | + +### Story-Level Fields (`userStories[]`) + +| Field | Type | Rules | +|-------|------|-------| +| `id` | string | `US-NNN` format, sequential | +| `title` | string | Under 50 chars, commit-message friendly | +| `description` | string | "As a [role], I want [feature] so that [benefit]" format | +| `acceptanceCriteria` | string[] | Plain strings, NOT checkbox markdown | +| `priority` | number | Execution order (1 = first). Use dependency order: if US-B depends on US-A's output, US-A must have higher priority (lower number). For independent stories, order by risk or complexity (hardest first). | +| `passes` | boolean | **ALWAYS** starts `false` | +| `notes` | string | **ALWAYS** starts `""` | + +### Additional Fields for Iterative Stories + +| Field | Type | Rules | +|-------|------|-------| +| `iterationMode` | string | **ALWAYS** `"fixed"` | +| `maxIterations` | number | Total passes required | +| `currentIteration` | number | **ALWAYS** starts `0` | +| `validationCommand` | string | Optional command to verify each iteration | + +**CRITICAL:** `passes` becomes `true` ONLY when `currentIteration >= maxIterations`. This is enforced by Ralph, not by the PRD author. + --- -## Archiving Previous Runs +## Subagent Usage Policy -**Before writing a new prd.json, check if there is an existing one from a different feature:** +When writing PRDs that may involve subagent delegation during implementation: -1. Read the current `prd.json` if it exists -2. Check if `branchName` differs from the new feature's branch name -3. If different AND `progress.txt` has content beyond the header: - - Create archive folder: `archive/YYYY-MM-DD-feature-name/` - - Copy current `prd.json` and `progress.txt` to archive - - Reset `progress.txt` with fresh header +**Use subagents when:** +- High-volume output (test suites, log analysis, codebase-wide exploration) +- Self-contained, isolated tasks with clear start/end +- Parallel independent investigations +- Context preservation (exploration in subagent frees main context) + +**Do NOT use subagents when:** +- Task requires iteration or back-and-forth +- Shared context across steps is critical +- Trivial or single-file scope +- Latency-sensitive simple changes -**The ralph.sh script handles this automatically** when you run it, but if you are manually updating prd.json between runs, archive first. +**Key trade-off:** Subagents isolate context but lose continuity. Use for isolated high-volume tasks only. Note this guidance in Technical Notes if relevant to the feature. --- -## Checklist Before Saving +## Example Skeleton + +```markdown +# PRD: User Notification Preferences + +## Summary +Allow users to configure which notifications they receive and through which channels. + +## Goals +- Users can toggle notification types on/off +- Support email and in-app channels +- Persist preferences across sessions + +## User Stories + +### US-001: Add preferences table to database +**Description:** As a developer, I need to store notification preferences per user. +**Acceptance Criteria:** +- Preferences table created with user_id FK +- Default preferences seeded on user creation +- Migration runs successfully +- Typecheck passes + +### US-002: Build notification settings panel +**Description:** As a user, I want a settings panel to manage my notification preferences. +**Acceptance Criteria:** +- Settings panel accessible from user menu +- Toggle switches for each notification type +- Save persists changes to backend +- Verify in browser using available tools +- Typecheck passes + +### US-003: Audit existing notification triggers +**Description:** As a developer, I need to verify all notification triggers respect user preferences. +**Acceptance Criteria:** +- Each trigger checked against preferences table +- Non-compliant triggers updated +- All findings documented +- Lint passes after each iteration +**Iteration:** +- Mode: fixed +- Max iterations: 3 +- Current iteration: 0 + +## Functional Requirements +- FR-1: Preferences table with columns per notification type +- FR-2: API endpoint GET/PUT /api/preferences +- FR-3: Notification dispatch checks preferences before sending + +## Non-Goals +- Push notifications (future phase) +- Notification scheduling/digest mode + +## Technical Notes +- See relevant rule files for database and API conventions +- Preferences must have RLS policies +- Subagent recommended for US-003 (batch audit across multiple files) + +## Open Questions +- Should preferences sync across devices in real-time? +``` -Before writing prd.json, verify: +--- + +## Archiving Previous Runs + +**Before writing a new `prd.json`, check if one already exists from a different feature:** + +1. Read the current `scripts/ralph/prd.json` if it exists +2. Check if `branchName` differs from the new feature's branch name +3. If different AND `scripts/ralph/progress.md` has content beyond the header: + - Create archive folder: `scripts/ralph/archive/YYYY-MM-DD-feature-name/` + - Copy current `scripts/ralph/prd.json`, `scripts/ralph/progress.md`, and `scripts/ralph/state.json` to the archive + - Reset `scripts/ralph/progress.md` with a fresh header + +The `scripts/ralph/ralph.sh` script handles this automatically when run (including archiving and resetting `scripts/ralph/state.json` when the branch changes), but if you are manually creating `prd.json`, archive first to avoid data loss. + +--- -- [ ] **Previous run archived** (if prd.json exists with different branchName, archive it first) -- [ ] Each story is completable in one iteration (small enough) -- [ ] Stories are ordered by dependency (schema to backend to UI) -- [ ] Every story has "Typecheck passes" as criterion -- [ ] UI stories have "Verify in browser using dev-browser skill" as criterion -- [ ] Acceptance criteria are verifiable (not vague) -- [ ] No story depends on a later story +## Checklist + +Before saving, verify: + +- [ ] Previous `prd.json` archived if it exists with a different `branchName` +- [ ] Asked clarifying questions with lettered options +- [ ] Incorporated user's answers +- [ ] Each story completable in one context window +- [ ] Story IDs follow `US-NNN` pattern +- [ ] Story titles under 50 characters +- [ ] 3-6 verifiable acceptance criteria per story +- [ ] Every story includes at least one project-appropriate quality gate (e.g., "Typecheck passes", "Tests pass", "Build succeeds") +- [ ] UI stories include browser verification criterion (e.g., "Verify in browser using available tools") +- [ ] Iterative stories used ONLY for batch/multi-pass work (not oversized stories) +- [ ] Iterative stories have all required fields (`iterationMode`, `maxIterations`, `currentIteration: 0`) +- [ ] Priorities reflect dependency order (dependencies first = lower number) +- [ ] Functional requirements numbered and unambiguous +- [ ] Non-goals section defines clear boundaries +- [ ] `prd.json` has `project`, `branchName`, `description` fields +- [ ] All stories in JSON have `priority`, `passes: false`, `notes: ""` +- [ ] `acceptanceCriteria` in JSON are string arrays (no checkboxes) +- [ ] Saved PRD to `tasks/prd-[feature-name].md` +- [ ] Saved JSON to `scripts/ralph/prd.json` \ No newline at end of file