| name | issue-loop |
| description | Autonomous GitHub issue fixer. For each open issue: Session 1 writes a spec + runs /deep-verify-plan (≥95/100), Session 2 uses /writing-plans to produce a TDD task list, Session 3 implements with TDD + /verification-before-completion then commits and pushes. Quality gates validate each artifact. Loops until no open issues remain. All orchestration events are visible inline in the CC terminal. |
Issue Loop
Autonomous GitHub issue fixer running entirely in the CC terminal. Every event — issue selection, session start, gate result, label change — is visible inline as it happens.
Usage: /issue-loop [START_ISSUE=N] [START_SESSION=N]
Examples:
/issue-loop — process all open issues from the beginning
/issue-loop START_ISSUE=6 — skip issues #1–#5, start at #6
/issue-loop START_ISSUE=6 START_SESSION=3 — resume issue #6 at Session 3
Step 0: Argument Parsing
Parse $ARGUMENTS. Extract:
START_ISSUE — default 1. Skip all issues with number < this value.
START_SESSION — default 1. For the first issue processed, skip sessions before this number. After the first issue completes (or fails), reset START_SESSION to 1 for all subsequent issues.
Example: START_ISSUE=6 START_SESSION=3 → for issue #6 start at Session 3; all later issues start at Session 1.
Step 1: Setup
Run all of the following via Bash before the main loop.
1a. Hard dependency check
command -v jq &>/dev/null || { echo "ERROR: 'jq' not found. Install jq and re-run."; exit 1; }
command -v gh &>/dev/null || { echo "ERROR: 'gh' not found. Install GitHub CLI and re-run."; exit 1; }
command -v python3 &>/dev/null || { echo "ERROR: 'python3' not found. Install Python 3 and re-run."; exit 1; }
1b. Auto-detect project path and repo slug
PROJECT_PATH="$(git rev-parse --show-toplevel 2>/dev/null)" || { echo "ERROR: Not inside a git repo."; exit 1; }
REPO_SLUG="$(gh repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null)" || { echo "ERROR: gh not configured or no remote."; exit 1; }
echo "Project : $PROJECT_PATH"
echo "Repo : $REPO_SLUG"
1c. Ensure labels exist
for label in "in-progress" "implemented" "needs-review"; do
gh label create "$label" --force 2>/dev/null || true
done
1d. Create directories
mkdir -p "$PROJECT_PATH/.a5c/plans" "$PROJECT_PATH/.a5c/logs"
1e. Soft dependency warnings
Check these paths and warn (do not fail) if missing:
~/.claude/skills/deep-verify-plan/SKILL.md
- Superpowers
writing-plans skill (look in ~/.claude/plugins/cache/claude-plugins-official/superpowers/*/skills/writing-plans/SKILL.md)
- Superpowers
verification-before-completion skill
Warn format: ⚠ Soft dep missing: <name> — sessions will run but skill may not load
Step 2: Main Loop
Repeat the following until no open issues remain. Track TOTAL_FIXED=0, TOTAL_FAILED=0, ITERATION=0.
2a. Get next issue
Run via Bash. Increment ITERATION. Print a separator:
════════════════════════════════════════════
Iteration N — fetching next issue...
════════════════════════════════════════════
Fetch the next issue (sorted by number ascending, skip those labeled in-progress or needs-review, skip those with number < START_ISSUE):
ISSUE_JSON=$(gh issue list \
--state open \
--limit 50 \
--json number,title,body,labels \
--jq "[.[] | select(
(.labels | map(.name) | (contains([\"in-progress\"]) or contains([\"needs-review\"])) | not)
and (.number >= $START_ISSUE)
)] | sort_by(.number) | .[0]")
If the result is empty or null: print ✓ No more open issues. All done! with the summary, then exit.
Set from the result: ISSUE_NUM, ISSUE_TITLE (parse from $ISSUE_JSON).
Set file paths:
BRIEF_FILE = $PROJECT_PATH/.a5c/plans/issue-N-brief.md
SPEC_FILE = $PROJECT_PATH/.a5c/plans/issue-N-spec.md
PLAN_FILE = $PROJECT_PATH/.a5c/plans/issue-N-plan.md
Print:
Issue #N: <title>
Brief : $BRIEF_FILE
Spec : $SPEC_FILE
Plan : $PLAN_FILE
2b. Write brief file
Use Bash to write the issue brief:
{
printf "# Issue #%s: %s\n\n## Body\n\n%s\n" \
"$ISSUE_NUM" \
"$(echo "$ISSUE_JSON" | jq -r '.title')" \
"$(echo "$ISSUE_JSON" | jq -r '.body // "(no body)"')"
} > "$BRIEF_FILE"
2c. Label in-progress + record start SHA
gh issue edit "$ISSUE_NUM" --add-label "in-progress" 2>/dev/null || true
IMPL_START_SHA=$(git rev-parse HEAD 2>/dev/null || echo "")
2d. Determine effective start session
For this issue only: if ISSUE_NUM == START_ISSUE and START_SESSION > 1, set EFFECTIVE_START_SESSION = START_SESSION. Otherwise EFFECTIVE_START_SESSION = 1.
Create a TaskCreate task: Issue #N — Session 1: Spec + Deep-Verify.
Session 1: Spec + Deep-Verify
Skip if EFFECTIVE_START_SESSION > 1. In that case, validate the existing spec at SPEC_FILE using Gate 1 and skip to Session 2 if valid; if invalid, label needs-review, remove in-progress, increment TOTAL_FAILED, continue to next issue.
Otherwise, dispatch via Agent tool:
Agent(
subagent_type: "general-purpose",
description: "Issue #N — Session 1: Spec + Deep-Verify",
prompt: <SESSION 1 PROMPT — see Session Prompts section below>
)
After the agent completes:
- Run Gate 1 on
SPEC_FILE.
- Gate 1 FAIL or agent returned indicating rate-limit exhaustion → check output for rate limit signals (
you've hit your usage limit, rate limit, quota exceeded). If rate-limited: remove in-progress label (do NOT add needs-review), skip to next issue. Otherwise (genuine failure): label needs-review, remove in-progress, increment TOTAL_FAILED, continue to next issue.
- Gate 1 PASS → proceed to Session 2.
Update task to completed.
Session 2: Writing Plans
Create a TaskCreate task: Issue #N — Session 2: Writing Plans.
Skip if EFFECTIVE_START_SESSION > 2. In that case, validate the existing plan at PLAN_FILE using Gate 2; if invalid, label needs-review, remove in-progress, increment TOTAL_FAILED, continue.
Otherwise, dispatch via Agent tool:
Agent(
subagent_type: "general-purpose",
description: "Issue #N — Session 2: Writing Plans",
prompt: <SESSION 2 PROMPT — see Session Prompts section below>
)
After the agent completes:
- Run Gate 2 on
PLAN_FILE (with SPEC_FILE for drift check).
- Gate 2 FAIL: label
needs-review, remove in-progress, increment TOTAL_FAILED, continue to next issue.
- Gate 2 PASS → proceed to Session 3.
Update task to completed.
After processing the resume issue, reset START_SESSION = 1 for all subsequent issues.
Session 3: TDD Implementation
Create a TaskCreate task: Issue #N — Session 3: TDD Implementation.
Dispatch via Agent tool:
Agent(
subagent_type: "general-purpose",
description: "Issue #N — Session 3: TDD Implementation",
prompt: <SESSION 3 PROMPT — see Session Prompts section below>
)
After the agent completes:
Update task to completed.
Step 3: Loop End / Summary
When get_next_issue returns nothing, print:
════════════════════════════════════════════
Fixed : N | Failed : N | Iterations: N
════════════════════════════════════════════
Session Prompts
Substitute {ISSUE_NUM}, {REPO_SLUG}, {BRIEF_FILE}, {SPEC_FILE}, {PLAN_FILE}, {PROJECT_PATH} before dispatching.
Session 1 Prompt
You are writing a verified spec for GitHub issue #{ISSUE_NUM} from repo {REPO_SLUG}. The issue brief is at {BRIEF_FILE}.
Your tasks:
(1) Read {BRIEF_FILE} and the full issue with: gh issue view {ISSUE_NUM}
(2) Thoroughly explore the codebase to understand context and root cause.
(3) Write a comprehensive spec to {SPEC_FILE}. The spec must include:
## Problem (root cause analysis with exact file:line references)
## Acceptance Criteria (numbered, testable)
## Proposed Solution (architecture and approach)
## Edge Cases & Out of Scope
## Test Strategy (what to test and how)
(4) Run babysitter to deeply verify the spec using the deep-verify-plan skill. Invoke it like this:
/babysitter:yolo Run the deep-plan-verification process via the /deep-verify-plan skill.
Process file: ~/.a5c/processes/deep-plan-verification.js
Inputs: planFile={SPEC_FILE}, projectRoot={PROJECT_PATH}, requireApproval=false,
taskDescription=Deep spec verification for issue #{ISSUE_NUM} — improve quality to 95/100 across 8 dimensions
Wait for babysitter to complete (it will iterate automatically until score >= 95).
Save the final verified spec back to {SPEC_FILE}.
Do NOT write any implementation code — this session is spec-only.
Session 2 Prompt
You are writing an implementation plan for GitHub issue #{ISSUE_NUM} from repo {REPO_SLUG}. The issue brief is at {BRIEF_FILE}. The verified spec is at {SPEC_FILE}.
Your tasks:
(1) Read {BRIEF_FILE} and {SPEC_FILE} carefully.
(2) Run babysitter to write the implementation plan using the writing-plans skill:
/babysitter:yolo Run the writing-plans skill to produce a TDD implementation plan.
Invoke Skill("superpowers:writing-plans") with specFile={SPEC_FILE}, outputFile={PLAN_FILE}
Wait for babysitter to complete. The skill will write the plan directly to {PLAN_FILE}.
The plan must:
- Use checkbox (- [ ]) syntax for every step
- Include exact file paths
- Include real code for every code step (no placeholders)
- Specify exact test commands with expected output
- Include commit steps after each passing test group
Quality bar: minimum 5 task blocks, no TBD/TODO/FIXME anywhere.
Do NOT write any implementation code — plan only.
Session 3 Prompt
You are implementing the fix for GitHub issue #{ISSUE_NUM} from repo {REPO_SLUG}.
- Issue brief : {BRIEF_FILE}
- Verified spec: {SPEC_FILE}
- Implementation plan: {PLAN_FILE}
Your tasks:
(1) Read {BRIEF_FILE}, {SPEC_FILE}, and {PLAN_FILE} carefully. Also run: gh issue view {ISSUE_NUM}
(2) Before writing any code, invoke the coding standards skill: Invoke Skill("superpowers:coding-standards") — all code you write MUST comply with those standards.
(3) Execute the plan using strict TDD: for each task, write a failing test first, then implement the minimum code to make it pass.
(4) TESTING STRATEGY — detect whether the issue touches frontend (any .tsx/.ts React files, UI components, pages, hooks):
- If YES: write Playwright CLI tests using 'npx playwright test' (write test files under frontend/tests/ or e2e/, run with 'npx playwright test').
- If backend only: use pytest.
- If both: use both.
(5) Commit after each passing test group with a clear message referencing issue #{ISSUE_NUM}.
(6) Push after every commit.
(7) Maintain code quality: no regressions, no skipped tests, all edge cases from the spec handled.
(8) Run the full test suite before finishing.
(9) Run babysitter to run the final QA gate using the verification-before-completion skill:
/babysitter:yolo Run the verification-before-completion skill as the final QA gate.
Invoke Skill("superpowers:verification-before-completion")
Wait for babysitter to complete. Fix every issue it raises before continuing.
(10) All changes must be production-ready with no regressions.
Do NOT close the issue yourself — the runner closes it on success.
Quality Gates
Gate 1 — Spec Validation
Run via Bash after Session 1:
[ -s "$SPEC_FILE" ] || { echo "✗ Gate 1 FAIL: spec file missing or empty"; exit 1; }
char_count=$(wc -c < "$SPEC_FILE")
[ "$char_count" -lt 800 ] && { echo "✗ Gate 1 FAIL: spec too short (${char_count} chars < 800)"; exit 1; }
missing=()
grep -qi "## .*problem\|## .*root cause\|## .*issue" "$SPEC_FILE" || missing+=("Problem/Root Cause")
grep -qi "## .*accept\|## .*criteria\|## .*done\|## .*goal" "$SPEC_FILE" || missing+=("Acceptance Criteria/Goal")
grep -qi "## .*edge\|## .*corner\|## .*scope\|## .*out.of" "$SPEC_FILE" || missing+=("Edge Cases/Scope")
[ ${#missing[@]} -gt 0 ] && echo "⚠ Gate 1 WARNING: possible missing sections: ${missing[*]} (continuing — babysitter may use different headings)"
echo "✓ Gate 1 PASS: spec looks valid (${char_count} chars)"
Gate 2 — Plan Validation
Run via Bash after Session 2. Inline Python for placeholder check:
[ -s "$PLAN_FILE" ] || { echo "✗ Gate 2 FAIL: plan file missing or empty"; exit 1; }
task_count=$(grep -cE '^\s*-\s*\[[ x]\]' "$PLAN_FILE" 2>/dev/null || echo 0)
list_count=$(grep -cE '^\s*-\s+\S' "$PLAN_FILE" 2>/dev/null || echo 0)
if [ "$task_count" -lt 3 ] && [ "$list_count" -lt 5 ]; then
echo "✗ Gate 2 FAIL: plan has only ${task_count} checkbox / ${list_count} list items"
exit 1
fi
py_out=$(python3 - "$PLAN_FILE" 2>&1 <<'PYEOF'
import sys, re
content = open(sys.argv[1], encoding='utf-8', errors='replace').read()
content = re.sub(r'```[\s\S]*?```', '', content)
bad = []
for line in content.split('\n'):
if re.match(r'^\s*-\s*\[[ x]\]', line):
continue
if re.search(r'\b(no|zero|without|not found|none|absence of|free of)\b.{0,60}\b(TBD|TODO|FIXME)\b', line, re.IGNORECASE):
continue
if re.search(r'\b(TBD|TODO|FIXME)\b.{0,60}\b(not found|none found|free|clean|absent|zero|0)\b', line, re.IGNORECASE):
continue
if re.search(r'\b(TBD|TODO|FIXME)\b|implement later|fill in', line, re.IGNORECASE):
print(f' placeholder: {line.strip()[:120]}', file=sys.stderr)
bad.append(line)
if bad:
sys.exit(1)
PYEOF
)
if [ $? -ne 0 ]; then
echo "✗ Gate 2 FAIL: plan contains placeholder text (TBD/TODO/FIXME)"
[ -n "$py_out" ] && echo "$py_out"
exit 1
fi
if [ -s "$SPEC_FILE" ]; then
matched=0 total=0
while IFS= read -r f; do
[ -z "$f" ] && continue
total=$((total + 1))
grep -qF "$f" "$PLAN_FILE" 2>/dev/null && matched=$((matched + 1))
done < <(grep -oE '[a-zA-Z0-9_/-]+\.[a-zA-Z]{2,4}' "$SPEC_FILE" 2>/dev/null | grep -vE '^\.' | sort -u | head -20)
if [ "$total" -gt 0 ] && [ "$matched" -eq 0 ]; then
echo "⚠ Gate 2 WARNING: plan references none of the ${total} file paths mentioned in spec — possible drift"
elif [ "$total" -gt 0 ]; then
echo "✓ Gate 2: plan covers ${matched}/${total} file paths from spec"
fi
fi
echo "✓ Gate 2 PASS: plan looks valid (${task_count} task items)"
Gate 3 — Implementation Validation
Run via Bash after Session 3:
current_sha=$(git rev-parse HEAD 2>/dev/null || echo "")
if [ -z "$current_sha" ] || [ "$current_sha" = "$IMPL_START_SHA" ]; then
echo "✗ Gate 3 FAIL: no new commits since session start"
exit 1
fi
new_commits=$(git log --oneline "${IMPL_START_SHA}..HEAD" 2>/dev/null | wc -l || echo 0)
echo "✓ Gate 3 PASS: ${new_commits} new commit(s)"
if git rev-parse -q --verify "@{u}" >/dev/null 2>&1; then
unpushed=$(git log --oneline "@{u}..HEAD" 2>/dev/null | wc -l || echo 0)
else
unpushed=$(git log --oneline "origin/HEAD..HEAD" 2>/dev/null | wc -l || echo 0)
fi
if [ "$unpushed" -gt 0 ]; then
echo "↑ Pushing ${unpushed} unpushed commit(s)..."
git push 2>/dev/null && echo "✓ Push successful" || echo "⚠ Push failed — may need manual push"
fi
Failure Handling
| Scenario | Behavior |
|---|
| Gate 1 fail | Label needs-review, remove in-progress, TOTAL_FAILED++, continue to next issue |
| Gate 2 fail | Label needs-review, remove in-progress, TOTAL_FAILED++, continue to next issue |
| Gate 3 fail | Label needs-review, remove in-progress, TOTAL_FAILED++, continue to next issue |
| Agent output contains rate-limit signal | Remove in-progress, do NOT label needs-review, skip issue and continue |
| No open issues | Exit cleanly with summary |
Rate-limit detection in agent output: look for any of these patterns in the agent's response:
you've hit your usage limit / you've hit your session limit
rate limit / rate-limited
usage limit reached / quota exceeded
limit.*reset
If detected, the issue is skipped without the needs-review label (it will be retried next time you run /issue-loop).
Notes
- The skill auto-detects repo root and slug — works in any git repo with a GitHub remote.
- All orchestration (issue selection, session start, gate result, label changes) is printed inline in the CC terminal."
- Babysitter sessions handle quality convergence internally (score ≥ 95) using the babysitter:yolo process.
START_SESSION only applies to the first issue processed; all subsequent issues always start at Session 1.