-
Notifications
You must be signed in to change notification settings - Fork 4
Description
branch: improve-spec-lifecycle
Spec: Improve Ralph Spec Lifecycle
Overview
Closes several gaps in how Ralph spec issues are created, tracked, reworked, and completed. The changes span the ralph script, the create-spec skill, the merge skill, and a new rework skill. Key improvements: local issue tracking via git config, issue closing on merge, a /rework skill for adding tasks back to an issue from review findings, moving execution boilerplate out of spec issue bodies into the iteration prompt, better handling of unfulfillable tasks, and fixing concurrent temp file collisions in create-spec.
Architecture
scripts/ralph # Python — iteration prompt, git config storage, [blocked] detection
claude/skills/create-spec/SKILL.md # Skill — trim template, fix temp file
claude/skills/merge/SKILL.md # Skill — close spec issue after merge
claude/skills/rework/SKILL.md # NEW skill — append tasks, re-ready issue
Data flow for issue tracking:
ralph process_issue()
→ ensure_worktree()
→ git config branch.<branch>.issue <number> ← NEW
→ iteration loop
→ status:done
/merge
→ git config branch.<branch>.issue ← READ
→ gh issue close
/rework
→ git config branch.<branch>.issue ← READ
→ append tasks to issue body
→ status:ready
1. Local Issue Tracking
Ralph must store the issue number in git config when it starts processing an issue. This provides a local cache so /merge and /rework can find the associated issue without querying GitHub.
- Set:
git config branch.<branch>.issue <number>— called fromprocess_issue()afterensure_worktree()returns. - Read: Any tool can retrieve it with
git config branch.<branch>.issue. - Scope: Per-repo config (not global), survives across sessions as long as the branch exists.
2. Iteration Prompt Improvements
Move execution instructions from the spec template into ITERATION_PROMPT in scripts/ralph. Also add rules for unfulfillable tasks and strengthen the "run all checks" step.
Boilerplate to move into ITERATION_PROMPT
The following content currently lives in every spec issue body (create-spec template) but should be in the iteration prompt instead:
- The "Each step follows this structure" block (implement, test, verify, review, address feedback, update spec)
- The "Spec maintenance rules" block (marking steps done, recording decisions, pausing for significant design changes)
New rule: unfulfillable tasks
Add to ITERATION_PROMPT: if a task cannot be completed because required tools or infrastructure are unavailable (e.g., test runner not installed, build tool missing, external service unreachable), do NOT silently skip or mark it done. Instead, write [blocked: <reason>] next to the task in the spec and do NOT make a commit. The outer loop will detect this and transition the issue to status:needs-attention.
Strengthen "run all checks"
Add to ITERATION_PROMPT: the "Run all checks" step (typically the last or second-to-last step) must ALWAYS execute the full test suite, linter, and syntax checks — even if earlier steps already ran individual tests. This step catches cross-cutting regressions. Never skip it or mark it done without actually running the checks.
3. Create-Spec Template Changes
Remove execution boilerplate from template
Remove from the spec template in claude/skills/create-spec/SKILL.md:
- The "Each step follows this structure:" block and its numbered list (lines 204-210)
- The "Spec maintenance rules" section and its bullet list (lines 212-217)
These now live in the ITERATION_PROMPT.
Remove "Create commit" final step
Remove "Step N: Create commit" from the template. Each implementation step already commits its changes, making a final commit step redundant. The agent either creates an empty/meaningless commit or skips the step entirely.
Keep "Step N-1: Run all checks" as the final step (now Step N). Reword it to also commit any fixes it makes.
Also remove the instruction at lines 9-11 requiring these final tasks
Update the Rules section: remove the line about "Always include these final tasks" that mandates both a run-all-checks step and a create-commit step. Replace with a rule that says the final step should always be a run-all-checks step that runs the full test suite, linting, and syntax checks, fixing any issues found.
Fix temp file
Replace the hardcoded /tmp/spec-body.md with mktemp. The SKILL.md currently instructs agents to write to a fixed path, causing collisions when multiple agents create specs concurrently.
Change the instruction from:
--body-file /tmp/spec-body.md
to:
tmp_spec=$(mktemp /tmp/spec-body-XXXXXX.md)
... write body to $tmp_spec ...
--body-file "$tmp_spec"
Update both the instruction text and the example command block.
4. Merge Skill: Close Spec Issue
After a successful merge, the /merge skill should offer to close the associated spec issue.
Behavior
After ta wt merge succeeds:
- Read
git config branch.<branch>.issuefor the merged branch (run from the base branch after merge, using the branch name that was just merged). - If an issue number is found, fetch its labels to confirm it's a spec issue with
status:done. - Offer to close: "Spec issue #N is marked done. Close it?"
- If confirmed, run
gh issue close <number> --repo <origin-repo>. - If no issue config found or labels don't match, skip silently.
This applies to both Path A (inside worktree) and Path B (on base branch) — add the close-issue logic after the merge succeeds in both paths.
5. New /rework Skill
A new skill at claude/skills/rework/SKILL.md that appends new tasks to a spec issue and transitions it back to status:ready.
Input Detection
| Input | Detection | Action |
|---|---|---|
| (none) | No arguments, no conversation context | Read issue from git config branch.<current-branch>.issue, ask what to rework |
| (none) | No arguments, conversation context exists (e.g., review findings) | Extract referenced items from conversation, read issue from git config |
#1234 or 1234 |
Numeric (with optional #) | Use that issue number directly |
Natural language with /rework |
e.g., "address issues 1, 3, 5 /rework" | Parse conversation context for review findings, match referenced items by number |
Session Context Awareness
When invoked after a /review that produced numbered findings (Critical/Suggestions sections), the skill must:
- Scan conversation history for the most recent code review output (look for the
## Code Review:heading pattern) - Parse the numbered findings from Critical and Suggestions sections
- If the user referenced specific numbers (e.g., "address 1, 3, 5"), select only those findings
- If no specific numbers referenced, include all Critical + Suggestions findings
Workflow
- Determine the issue number (from git config or input)
- Fetch the current issue body via
gh issue view <number> --repo <origin-repo> --json body - Determine which findings/changes to add (from conversation context or user input)
- Draft new implementation steps in the same format as existing steps, numbered continuing from the last step
- Present the new steps to the user for confirmation
- Append the new steps to the issue body via
gh issue edit <number> --repo <origin-repo> --body-file <tmpfile> - Transition label: remove
status:done, addstatus:ready - Report: "Updated issue #N with X new tasks, marked ready."
Rules
- Do NOT implement any code. This skill only modifies the spec issue.
- New steps must follow the same format as existing steps in the issue body.
- Reset all
[done]markers? No — leave completed steps marked done. Only append new steps. - The skill must resolve the origin repo the same way create-spec does.
6. Ralph: Detect [blocked] in Spec
When the iteration loop detects no new commit (head unchanged), ralph currently assumes all tasks are done and labels status:done. Add a check: if the updated spec body contains any [blocked: markers, label status:needs-attention instead of status:done and print a message identifying the blocked tasks.
Implementation Plan
Step 1: Store issue number in git config [done]
Files:
scripts/ralph—process_issue()function
Implement:
- After
ensure_worktree()returnswork_dir(around line 1358), add a call to set the git config:git.run("config", f"branch.{branch}.issue", str(issue_number), cwd=work_dir, check=False)
- This must happen before the iteration loop starts.
Test:
- Add a test in
tests/test_ralph.pythat mocksgit.runand verifies the config is set with the correct branch and issue number afterensure_worktree.
Verify: Run pytest tests/test_ralph.py -v. Fix any failures.
Review: Check that the config key format handles branch names with slashes (git config supports dotted section keys for branches like feature/foo).
Address feedback: Fix findings, re-run tests.
Step 2: Update ITERATION_PROMPT with execution instructions [done]
Files:
scripts/ralph—ITERATION_PROMPTconstant
Implement:
- Append the "each step follows this structure" block to the prompt (implement, test, verify, review, address feedback, update spec).
- Append the spec maintenance rules (mark done, record decisions, pause for significant changes).
- Add the unfulfillable task rule: "If a task cannot be completed because required tools are unavailable, write
[blocked: <reason>]next to the task and do NOT commit. The outer loop will handle this." - Add the run-all-checks rule: "The 'Run all checks' step must always execute the full test suite, linter, and syntax checks — even if earlier steps ran individual tests. Never skip it."
Test:
- Verify the
ITERATION_PROMPTstring contains the key phrases:[blocked:,Run all checks,Spec maintenance,each step follows.
Verify: Run pytest tests/test_ralph.py -v.
Review: Ensure the prompt isn't too long — it should be clear and scannable for the agent.
Address feedback: Fix findings, re-run tests.
Step 3: Remove boilerplate from create-spec template [done]
Files:
claude/skills/create-spec/SKILL.md
Implement:
- Remove the "Each step follows this structure:" numbered list (currently lines 204-210 in the template).
- Remove the "### Spec maintenance rules" section and its bullet list (currently lines 212-217).
- Remove the "Step N: Create commit" step from the template.
- Update the Rules section (line 9-11): replace the "Always include these final tasks" rule (which currently mandates both run-all-checks and create-commit) with: "Always include a final task to run all tests, checks, and formatting commands — fix any issues found."
- The "Step N-1: Run all checks" becomes the last step. Update its wording: "Run the full test suite, linting, and syntax checks. Fix any failures and commit the fixes."
Test:
- Read through the updated template to confirm no references to the removed sections remain.
Verify: Manual review — this is a markdown skill file, no automated tests.
Review: Ensure the template is still self-contained and clear without the moved sections.
Address feedback: Fix findings.
Step 4: Fix create-spec temp file [done]
Files:
claude/skills/create-spec/SKILL.md
Implement:
- Find the
--body-file /tmp/spec-body.mdinstruction and example. - Replace with instructions to use
mktemp:tmp_spec=$(mktemp /tmp/spec-body-XXXXXX.md) - Update the example command block to write to
"$tmp_spec"and use--body-file "$tmp_spec".
Test:
- Verify no remaining references to the hardcoded
/tmp/spec-body.mdpath in the file.
Verify: grep -c 'spec-body.md' claude/skills/create-spec/SKILL.md returns 0.
Review: Confirm the mktemp pattern is correct for both macOS and Linux.
Address feedback: Fix findings.
Step 5: Detect [blocked] markers in ralph [done]
Files:
scripts/ralph—process_issue()iteration loop
Implement:
- In the
head_before == head_afterblock (line 1402), before labelingstatus:done, check if the spec body contains[blocked::if "[blocked:" in body: print(f"ralph: blocked tasks found in issue #{issue_number}, marking needs-attention") gh.issue_edit(issue_number, repo, remove_label="status:in-progress", add_label="status:needs-attention") else: print(f"ralph: no commit made, marking issue #{issue_number} done") gh.issue_edit(issue_number, repo, remove_label="status:in-progress", add_label="status:done") unblock_ready_specs(repo, gh)
Test:
- Add tests in
tests/test_ralph.py:- Spec body with
[blocked: no test runner]→status:needs-attention - Spec body without
[blocked:]→status:done+unblock_ready_specscalled
- Spec body with
Verify: Run pytest tests/test_ralph.py -v.
Review: Ensure the [blocked: detection doesn't false-positive on literal text in spec descriptions.
Address feedback: Fix findings, re-run tests.
Step 6: Update merge skill to close spec issues [done]
Files:
claude/skills/merge/SKILL.md
Implement:
- Add a new section "## Post-merge: close spec issue" after the existing merge workflow.
- Document the procedure: after a successful
ta wt merge, readgit config branch.<merged-branch>.issue. If found, fetch labels to confirmspec+status:done, then offer to close withgh issue close. - Reference this section from both Path A (Step 3A, after merge succeeds) and Path B (Step 5B, after each successful merge).
- The repo for
gh issue closeshould be resolved the same way as in create-spec (origin remote).
Test:
- Manual review — skill files are not automatically tested.
Verify: Read through the updated skill to confirm the flow is clear and complete.
Review: Ensure the skill handles the case where git config has no issue key (skip silently).
Address feedback: Fix findings.
Step 7: Create rework skill [done]
Files:
claude/skills/rework/SKILL.md— NEW file
Implement:
- Create the skill file with sections:
- Rules (no code implementation, spec-only)
- Repo resolution (same as create-spec)
- Input detection (no args + context, no args + no context, numeric, natural language)
- Session context awareness (parse review findings, match by number)
- Workflow (fetch issue, draft new steps, confirm, append, re-label)
- The skill must read
git config branch.<current-branch>.issueas the default issue source. - Include the review-finding parsing logic: scan for
## Code Review:heading, parse Critical/Suggestions bullets, match user-referenced numbers. - New steps must continue numbering from the last existing step.
- The skill transitions labels: remove
status:done, addstatus:ready. - Register the skill by confirming it follows the SKILL.md naming convention that Claude Code auto-discovers.
Test:
- Manual review.
Verify: Confirm the file exists at claude/skills/rework/SKILL.md and follows the same structural patterns as other skills.
Review: Compare structure against create-spec and merge skills for consistency.
Address feedback: Fix findings.
Step 8: Run all checks
Implement:
- Run
pytest tests/test_ralph.py -v - Run
shellcheckon any modified shell scripts (if any) - Fix any failures
Verify: All checks pass clean.
Step 9: Create commit
Implement:
- Stage all changes and create a commit summarizing the spec lifecycle improvements.
Verify: git log -1 shows the commit.
Conventions
- Language: Python for
scripts/ralph, Markdown for skill files - Tests: pytest with
conftest.import_script()for ralph; skills are not automatically tested - Error messages: Prefix with
ralph:for the ralph script - Exit codes: 0=success, 1=runtime error