parsoFish

developer-ralph

Launch the Ralph loop runner for a single work item; iterate until quality gates pass, iteration budget is exhausted, or the loop is detected as wedged.

parsoFish 5 Updated 1mo ago
GitHub

Install

npx skillscat add parsofish/forge-studio/developer-ralph

Install via the SkillsCat registry.

SKILL.md

Developer — Ralph

Single responsibility

Drive a single work item to completion via the Ralph loop pattern (ADR 002). Thin wrapper: prepare loop input artifacts (PROMPT.md, AGENT.md, fix_plan.md), invoke `loops/ralph/runner.ts`.

Inputs / Outputs

Inputs:

  • <worktree>/.forge/work-items/WI-<n>.md — the work-item spec.
  • loops/ralph/PROMPT.md.tmpl + loops/ralph/AGENT.md.tmpl — templates.
  • The worktree itself.

Outputs:

  • Commits in the worktree (one per AC where possible).
  • <worktree>/AGENT.md — final institutional memory (updated each iteration).
  • <worktree>/fix_plan.md — checklist showing remaining work if loop didn't complete.
  • Iteration events to the event log.

Status frontmatter is owned by the orchestrator. Do not edit WI-<n>.md — the orchestrator writes status: complete | failed after run() returns.

Event-log entries to emit

  • ralph.start — event_type: 'log', loop initiated.
  • per-iteration event_type: 'iteration' — number, cost, duration, files touched.
  • ralph.uncommitted-work-swept — event_type: 'log'; the autocommit safety net fired (G1: the agent's commit-discipline gap, made visible for reflectors).
  • ralph.end — event_type: 'end'; carries status, iterations, stop_reason, tool_use.

Process

  1. Read the work item spec — single source of intent (no forge-brain query).
  2. Stamp loops/ralph/PROMPT.md.tmpl with work-item content + ACs → <worktree>/PROMPT.md.
  3. Stamp loops/ralph/AGENT.md.tmpl → <worktree>/AGENT.md (empty; loop fills it).
  4. Initialise <worktree>/fix_plan.md with ACs as a checklist.
  5. Invoke loops/ralph/runner.ts with worktree path and stop-condition config (from manifest's iteration_budget — no $ cap per C19).
  6. Runner returns { status: 'complete' | 'failed' | 'wedged', iterations: n, cost: usd }. The orchestrator writes status back to the WI spec.

Constraints

  • Quality gates verified by the orchestrator, not the agent. The runner runs the gates itself; the agent's claim of "tests pass" is not trusted.
  • Iteration budget is hard. Runner stops at iteration_budget regardless of progress.
  • Wedged-detector — see `loops/ralph/stop-conditions.ts`.

Ralph loop discipline

You are inside a Ralph loop. Each call is one iteration. Loop state carries across iterations via three worktree files you must read at the start of every iteration:

  • PROMPT.md — per-iteration brief (work item spec, ACs, files in scope, iteration counter).
  • AGENT.md — institutional memory across iterations. Read first, update last. Record what you tried, what worked, what didn't — so the next iteration does not re-tread dead ends.
  • fix_plan.md — checklist of ACs + sub-tasks. Tick items as you complete them; add items as you discover sub-problems.

After your work, commit with a conventional-commits message (feat:, fix:, refactor:, test:, docs:). Atomic commits — one concern per commit. Use Bash for git, npm test, pytest, bats, or any test runner.

Commit discipline (G1, 2026-07-11): committing your own work is YOUR job, every iteration — the forge-autocommit safety net exists only for the failure case, and every sweep it makes is flagged as a distinct ralph.uncommitted-work-swept event (a visible discipline gap, not a convenience). Two gitignore rules:

  • If a declared deliverable (a creates: path or verification artifact) falls under a .gitignore pattern, stage it with git add -f <path> — a plain git add/git add -A silently skips ignored paths, so the gate's required-paths diff check rejects the WI as if you wrote nothing (recurred across 3+ gitpulse initiatives before this clause).
  • Never git add the loop-scratch files (AGENT.md, PROMPT.md, fix_plan.md). They are gitignored on purpose (contract C2) and must stay off the branch — attempting to commit them silently does nothing and wastes tool calls.

The orchestrator decides when to stop, not you — it runs quality gates between your iterations. Your job is incremental progress every iteration.

Hard rules:

  • You are CONTINUING, not restarting. Every prior iteration's work is committed on this branch. FIRST move each iteration: git log --oneline main..HEAD + git diff --stat main..HEAD to see what is already built, and read AGENT.md for what has been tried. Build on it — never re-research what AGENT.md already answered, never re-investigate code a prior iteration already wrote. If you catch yourself reading SDK/docs/source to "understand" rather than to make a concrete edit, stop reading and write.
  • Write code EARLY. Make a concrete, committed change every iteration. Write a compiling skeleton in your first one or two tool calls; flesh it out across iterations — do NOT spend a whole iteration researching. Progress = committed diffs, not understanding.
  • Anchor on the WI's acceptance criteria. Make each AC's then clause observable. (Brain 3 is available as supplemental context per ADR 010 if the WI is thin on a project convention; the forge brain is off-limits.)
  • files_in_scope is advisory orientation, NOT a fence. It is the planner's best guess — a starting point. You are FREE to edit any file needed to make the gate pass, including sweeping changes (e.g. running a formatter over the whole tree) when the AC requires it. Don't rewrite unrelated features, but never let the scope list stop you from applying the actual fix.
  • Read what the gate is telling you, then use the project's own fixers. When the gate reports a failure, fix THAT, the cheap way. If a formatter/linter has an auto-fix target (make fmt, gofmt -w, prettier --write, ruff --fix), RUN IT over the whole tree in one command instead of hand-editing files.
  • No shortcuts. Don't skip tests, don't --no-verify, don't disable lint rules.
  • No hallucinated test passes. If you claim tests pass, prove it by running them via Bash.
  • creates: / verification_artifact: paths are MANDATORY outputs (ADR 037). If the WI lists either, the orchestrator runs git diff --name-only main...HEAD and rejects the iteration if NONE of those paths are in the diff. Before you exit each iteration, ensure at least one of those paths exists (a compiling stub satisfies the path check). If the gate emits "[forge gate-tightening] REJECTED: …", the message lists the exact paths — create one in the next iteration.