Skip to content

feat: evolve PRD format toward PRP standard#111

Open
mtgibbs wants to merge 22 commits intosnarktank:mainfrom
mtgibbs:feat/prp-format-evolution
Open

feat: evolve PRD format toward PRP standard#111
mtgibbs wants to merge 22 commits intosnarktank:mainfrom
mtgibbs:feat/prp-format-evolution

Conversation

@mtgibbs
Copy link

@mtgibbs mtgibbs commented Feb 25, 2026

Summary

  • Enrich the spec format with project-level fields (constraints, nonGoals, glossary) and story-level fields (verificationCommands, context with relevantFiles/hints/examples) so agents have the context they need without losing information during PRD-to-JSON conversion
  • Add PRP versioning system — features evolve through numbered versions with diff-based story detection, archived prior versions, and automatic passes carry-over for unchanged stories
  • Support dual filenames (prp.json preferred, prd.json fallback) across all scripts (ralph.sh, agent-loop.sh, ralph-parallel.sh, status.sh) and agent prompts (CLAUDE.md, CLAUDE-parallel.md, CLAUDE-verifier.md)
  • All new fields are optional — existing prd.json files and jq story-selection queries work unchanged

Test plan

  • prp.json.example is valid JSON
  • jq story-selection query from agent-loop.sh works against both prp.json.example and prd.json.example
  • All shell scripts pass bash -n syntax check
  • Run ralph.sh with only prd.json present — should work as before
  • Run ralph.sh with both prp.json and prd.json present — should prefer prp.json
  • Test archive flow: create v1 prp.json, run archiver, verify archive/{feature}/v1.prp.json structure
  • Read through updated agent prompts to confirm instructions are clear

🤖 Generated with Claude Code

mtgibbs and others added 22 commits February 12, 2026 23:41
Add parallel mode that runs N containerized Claude Code agents
simultaneously against the same PRD, with network sandboxing,
resource limits, and git-based story claiming.

New directories:
- docker/ — Dockerfile, container entrypoint, iptables firewall scripts
- parallel/ — orchestrator, stop, status, parallel prompt, lib helpers

Upstream ralph.sh and all existing files are untouched.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Switch from env-var token passing to Docker volume-based auth:
- Mount ralph-claude-auth volume at /claude-auth:ro
- agent-loop.sh copies credentials to writable ~/.claude/
- Add check_auth_volume() to verify volume before launch
- Remove CLAUDE_CODE_OAUTH_TOKEN env var requirement

Add --project DIR flag to orchestrator, status, and stop scripts
so ralph can target external project directories.

Bug fixes discovered during smoke test:
- Fix UID 1000 conflict in Dockerfile (node:20-slim uses 1000)
- Fix macOS seq counting down when count=0 (guard with -le 0)
- Fix PARALLEL_PROMPT path resolution for external projects

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow projects to specify a custom Docker image via --image flag,
enabling project-specific tooling (e.g., Deno, Python) without
modifying the base ralph-agent image.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Redirect all git output in claim_story() to stderr so only the
  story ID goes to stdout (prevents garbage in CLAIMED_STORY)
- Wrap claim_story call in if-statement to prevent set -e from
  killing the script when claim returns non-zero
- Fix setup_workspace to reset to current branch on restart,
  not hard-coded origin/main (preserves feature branches)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deno projects need access to jsr.io (Deno's package registry) for
dependency resolution and type checking. Without this, agents can't
run `deno task check` inside builder containers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…city

- Mount only stop_requested file instead of entire .ralph/ directory,
  preventing agents from reading plaintext auth tokens
- Switch stop signal from file-existence to file-content (-s not -f)
  since the file must exist for Docker bind-mount
- Remove hardcoded --platform linux/arm64 so builds work on any arch
- Replace hardcoded npm/jsr/deno firewall whitelist with --allow-domain
  flag, making the firewall language-agnostic
- Use treeless bare clone (--filter=blob:none) to avoid exposing old
  file content that may contain secrets
- Add SETENV to sudoers so RALPH_EXTRA_DOMAINS passes through sudo
- Document custom image contract and extension pattern in README

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add push.autoSetupRemote to git config so first push on a new branch
  automatically sets up tracking
- Skip git pull --rebase when remote branch doesn't exist yet (new
  branch from prd.json branchName)
- Use file:// prefix for bare clone so --filter=blob:none takes effect
  (git ignores filters on local path clones)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Projects can now be "ralph-ready" by adding a Dockerfile.ralph to their
root. When detected, ralph automatically builds a project-specific image
(tagged ralph-agent-<project>:latest) without needing --image.

Resolution order: --image flag > Dockerfile.ralph > default base image.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Swap date parsing order to try GNU date -d first, macOS date -j as
  fallback (orchestrator runs on the host which could be either OS)
- Remove dead token_refresh docs and unused check_token_refresh_file()
  function — auth model is now volume-based, not token-file-based

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously both agent-loop.sh AND Claude claimed stories. The script
would claim US-001, then Claude would read CLAUDE-parallel.md's claim
protocol and grab US-002 and US-003 before doing any work.

Now:
- agent-loop.sh injects {{CLAIMED_STORY}} into the prompt via sed
- CLAUDE-parallel.md tells Claude which story is pre-assigned
- Claude is explicitly told not to claim additional stories
- Claiming is solely the script's responsibility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Agents could claim every story in rapid succession without completing
any — especially when Claude failed (e.g. expired OAuth token). Two
new mechanisms prevent this:

- check_existing_claim(): before claiming a new story, checks if the
  agent already owns an incomplete one and reuses that claim
- release_claim(): on auth/hard failure, releases the claim back to
  the pool so other agents can pick it up
- Auth failures trigger a 60s backoff before retrying

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add --verifier flag to ralph-parallel.sh for launching verifier agents
- Add ralph.role, ralph.agent_id, ralph.project_dir docker labels to
  containers for external tooling (voice TUI panel filtering)
- Verifiers use separate CLAUDE-verifier.md prompt
- Orchestrator checks verified field when verifiers are in use
- Add stale verification claim recovery

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tions

Bug 1: Add git fetch origin before git rev-parse --verify in
check_existing_claim() and claim_verification() to match the pattern
already used in claim_story(). Without the fetch, rev-parse checks
stale remote refs and skips the pull, causing agents to work on
outdated prd.json state.

Bug 5: Add git checkout/clean at the top of each iteration to remove
any unstaged changes left by the previous Claude session, preventing
rebase failures on the next pull.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously, auth failures caused a fixed 60s sleep and immediate retry,
which could loop indefinitely when tokens were revoked or rate-limited.

Now tracks consecutive AUTH_FAILURES with a counter that:
- Resets to 0 on successful Claude invocation
- Logs actual error lines from the logfile for debugging
- Exits after MAX_AUTH_FAILURES (5) consecutive failures
- Uses exponential backoff: 60s, 120s, 240s, 480s (capped)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bug 2: Replace silent-fail bare repo push (2>/dev/null || true) with
force-push that surfaces errors. If the project has rewritten history
(e.g., squash-merge from a PR), a non-force push silently fails and
agents start from stale code.

Bug 3: After syncing the bare repo, delete all non-main/master branches.
Previous runs leave behind feature branches that agents may accidentally
discover and work on, causing confusion and wasted iterations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: 5 agent orchestration bugs from retro
Agents can now commit as custom identities loaded from a gitignored
config file, with overflow agents falling back to default bot names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ontrol

Add dependsOn support so stories can declare prerequisite story IDs that
must pass before they become claimable. The claim_story() jq query now
builds a set of passing IDs and filters accordingly. Existing PRDs without
dependsOn work unchanged (defaults to empty array).

Also creates ~/taskflow test project with 8-story diamond dependency DAG
for testing 3-agent parallel runs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Agents now exit with code 2 (instead of 1) when auth failures are
exhausted. The orchestrator detects this and immediately stops all
agents rather than restarting them in an infinite loop, since all
agents share the same credentials.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
macOS grep doesn't support \| alternation in basic regex, causing
the stale branch cleanup to delete main/master from the bare repo.
Switch to grep -E with (main|master) pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enrich the spec format so agents have the context they need, with
acceptance criteria as the primary quality gate. Support both prp.json
(new) and prd.json (legacy) filenames across all scripts and prompts.

Key additions:
- Project-level: constraints, nonGoals, glossary, version, previousVersion
- Story-level: verificationCommands, context (relevantFiles, hints, examples)
- PRP versioning system for incremental feature evolution
- Dual filename detection (prp.json preferred, prd.json fallback)
- Versioned archiving (archive/{feature}/v{N}.prp.json)

All new fields are optional — existing prd.json files work unchanged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add launch-multi-prp.sh orchestrator that runs 1 agent per PRP file,
each on its own feature branch with no story contention. RALPH_BRANCH
env var in agent-loop.sh bypasses spec-file branch discovery. Tested
with 6 simultaneous agents against blackduck-polaris-mcp (PRs snarktank#15-snarktank#20).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant