Use when user requests autonomous operation across multiple issues. Orchestrates parallel workers using Task tool, monitors with TaskOutput, handles SLEEP/WAKE cycles, and works until scope is complete without user intervention.
/plugin marketplace add troykelly/claude-skills/plugin install issue-driven-development@troykelly-skillsThis skill is limited to using the following tools:
reference/failure-recovery.mdreference/loop-implementation.mdreference/state-management.mdOrchestrates long-running autonomous work across multiple issues using the Task tool to spawn parallel worker agents and TaskOutput to monitor their progress.
Core principle: GitHub is the source of truth. Workers are disposable. State survives restarts.
Announce at start: "I'm using autonomous-orchestration to work through [SCOPE]. Starting autonomous operation now."
worker-dispatch skill for spawning workers with Task toolworker-protocol skill for worker behaviorci-monitoring skill for CI/WAKE handlinggh) authenticatedWorkers are spawned as background agents using the Task tool:
Orchestrator
│
├── Task(run_in_background: true) → Worker Agent #1 (task_id: aa93f22)
├── Task(run_in_background: true) → Worker Agent #2 (task_id: b51e54b)
└── Task(run_in_background: true) → Worker Agent #3 (task_id: c72f3d1)
Monitor progress with TaskOutput:
TaskOutput(task_id: "aa93f22", block: false) → "Task is still running..."
TaskOutput(task_id: "b51e54b", block: false) → Completed with result
TaskOutput(task_id: "c72f3d1", block: false) → "Task is still running..."
CRITICAL: Spawn all workers in the SAME message for true concurrent execution.
CRITICAL: All persistent state is stored in GitHub. Task IDs are ephemeral session state.
| State Store | Purpose | Used For |
|---|---|---|
| Project Board Status | THE source of truth | Ready, In Progress, In Review, Blocked, Done |
| Issue Comments | Activity log | Worker assignment, progress, deviations |
| Labels | Lineage only | spawned-from:#N, depth:N, epic-* |
| MCP Memory | Active marker + task tracking | Active orchestration detection, active task_ids |
| Orchestrator memory | Ephemeral session state | Map of issue# → task_id for monitoring |
See: reference/state-management.md for detailed state queries and updates.
CRITICAL: Orchestration must survive mid-loop context compaction.
# Write to MCP Memory when orchestration starts
mcp__memory__create_entities([{
"name": "ActiveOrchestration",
"entityType": "Orchestration",
"observations": [
"Status: ACTIVE",
"Scope: [MILESTONE/EPIC/unbounded]",
"Tracking Issue: #[NUMBER]",
"Started: [ISO_TIMESTAMP]",
"Repository: [owner/repo]",
"Phase: BOOTSTRAP|MAIN_LOOP",
"Last Loop: [ISO_TIMESTAMP]"
]
}])
mcp__memory__add_observations({
"observations": [{
"entityName": "ActiveOrchestration",
"contents": ["Last Loop: [ISO_TIMESTAMP]", "Phase: MAIN_LOOP"]
}]
})
mcp__memory__delete_entities({
"entityNames": ["ActiveOrchestration"]
})
Session-start skill checks for active orchestration:
# Check MCP Memory for active orchestration
ACTIVE=$(mcp__memory__open_nodes({"names": ["ActiveOrchestration"]}))
if [ -n "$ACTIVE" ]; then
echo "⚠️ ACTIVE ORCHESTRATION DETECTED"
echo "Scope: [from ACTIVE]"
echo "Tracking: [from ACTIVE]"
echo ""
echo "Resuming orchestration loop..."
# Invoke autonomous-orchestration skill to resume
fi
This ensures: Even if context compacts mid-loop, the next session will detect the active orchestration and resume it.
The user's request for autonomous operation IS their consent. No additional confirmation required.
When the user requests autonomous work:
## Starting Autonomous Operation
**Scope:** [MILESTONE/EPIC/ISSUES or "all open issues"]
**Workers:** Up to 5 parallel
**Mode:** Continuous until complete
Beginning work now...
Do NOT ask for "PROCEED" or any confirmation. The user asked for autonomous operation - that is the confirmation.
When the user requests autonomous operation without specifying a scope:
priority:urgent or priority:high labels not part of an epicdetect_work_scope() {
# 1. Check for urgent/high priority standalone issues first
PRIORITY_ISSUES=$(gh issue list --state open \
--label "priority:urgent,priority:high" \
--json number,labels \
--jq '[.[] | select(.labels | map(.name) | any(startswith("epic-")) | not)] | .[].number')
if [ -n "$PRIORITY_ISSUES" ]; then
echo "priority_standalone"
echo "$PRIORITY_ISSUES"
return
fi
# 2. Get epics in order (by creation date)
EPICS=$(gh issue list --state open --label "type:epic" \
--json number,title,createdAt \
--jq 'sort_by(.createdAt) | .[].number')
if [ -n "$EPICS" ]; then
echo "epics"
echo "$EPICS"
return
fi
# 3. Fall back to all open issues
ALL_ISSUES=$(gh issue list --state open --json number --jq '.[].number')
echo "all_issues"
echo "$ALL_ISSUES"
}
Autonomous operation continues until ALL of:
The operation does NOT pause for:
CRITICAL: Before spawning ANY new workers, resolve all existing open PRs first.
┌──────────────────────────────────────────────────────────┐
│ BOOTSTRAP PHASE │
│ (Runs ONCE before main loop) │
└─────────────────────────┬────────────────────────────────┘
│
▼
┌───────────────────┐
│ GET OPEN PRs │
│ │
│ Filter out: │
│ - release/* │
│ - release- │
│ placeholder │
└─────────┬─────────┘
│
┌──────────┴──────────┐
▼ ▼
┌───────────┐ ┌───────────┐
│ Has PRs? │─── No ──│ → MAIN │
│ │ │ LOOP │
└─────┬─────┘ └───────────┘
│ Yes
▼
┌───────────────────────────────┐
│ FOR EACH PR: │
│ │
│ 1. Check CI status │
│ 2. Verify review artifact │
│ 3. Merge if ready OR │
│ 4. Wait/fix if not │
└───────────────────────────────┘
│
▼
MAIN LOOP
resolve_existing_prs() {
echo "=== PR RESOLUTION BOOTSTRAP ==="
# Get all open PRs, excluding release placeholders
OPEN_PRS=$(gh pr list --json number,headRefName,labels \
--jq '[.[] | select(
(.headRefName | startswith("release/") | not) and
(.labels | map(.name) | index("release-placeholder") | not)
)] | .[].number')
if [ -z "$OPEN_PRS" ]; then
echo "No actionable PRs to resolve. Proceeding to main loop."
return 0
fi
echo "Found PRs to resolve: $OPEN_PRS"
for pr in $OPEN_PRS; do
echo "Processing PR #$pr..."
# Get CI status
ci_status=$(gh pr checks "$pr" --json state --jq '.[].state' 2>/dev/null | sort -u)
# Get linked issue
ISSUE=$(gh pr view "$pr" --json body --jq '.body' | grep -oE 'Closes #[0-9]+' | grep -oE '[0-9]+' | head -1)
if [ -z "$ISSUE" ]; then
echo " ⚠ No linked issue found, skipping"
continue
fi
# Check if CI passed
if echo "$ci_status" | grep -q "FAILURE"; then
echo " ❌ CI failing - triggering ci-monitoring for PR #$pr"
# Invoke ci-monitoring skill to fix
handle_ci_failure "$pr"
continue
fi
if echo "$ci_status" | grep -q "PENDING"; then
echo " ⏳ CI pending for PR #$pr, will check in main loop"
continue
fi
if echo "$ci_status" | grep -q "SUCCESS"; then
# Verify review artifact
REVIEW_EXISTS=$(gh api "/repos/$OWNER/$REPO/issues/$ISSUE/comments" \
--jq '[.[] | select(.body | contains("<!-- REVIEW:START -->"))] | length' 2>/dev/null || echo "0")
if [ "$REVIEW_EXISTS" = "0" ]; then
echo " ⚠ No review artifact - requesting review for #$ISSUE"
gh issue comment "$ISSUE" --body "## Review Required
PR #$pr has passing CI but no review artifact.
**Action needed:** Complete comprehensive-review and post artifact to this issue.
---
*Bootstrap phase - Orchestrator*"
continue
fi
# All checks pass - merge
echo " ✅ Merging PR #$pr"
gh pr merge "$pr" --squash --delete-branch
mark_issue_done "$ISSUE"
fi
done
echo "=== BOOTSTRAP COMPLETE ==="
}
PRs are excluded from bootstrap resolution if:
| Condition | Example |
|---|---|
Branch starts with release/ | release/v2.0.0, release/2025-01 |
Has release-placeholder label | Manual exclusion |
Has do-not-merge label | Explicit hold |
┌──────────────────────────────────────────────────────────┐
│ MAIN LOOP │
└─────────────────────────┬────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ MONITOR │ │ CHECK │ │ SPAWN │
│ WORKERS │ │ CI/PRs │ │ WORKERS │
│ (TaskOut) │ │ │ │ (Task) │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
│ │ │
└──────────────────┼──────────────────┘
│
▼
┌───────────────────┐
│ EVALUATE STATE │
│ │
│ All done? → Exit │
│ Waiting? → SLEEP │
│ Work? → Continue │
└───────────────────┘
See: reference/loop-implementation.md for full loop code.
TaskOutput(block: false) for each active task_idTask(run_in_background: true)Each loop iteration checks all active workers:
## Monitor Active Workers
For each task_id in active_workers:
TaskOutput(task_id: "[ID]", block: false, timeout: 1000)
Interpret results:
- "Task is still running..." → Continue monitoring
- Completed → Check GitHub for PR, update project board, remove from active list
- Error → Handle failure, potentially spawn replacement
Spawn multiple workers in ONE message for concurrent execution:
## Dispatch Workers
1. Count available slots: 5 - len(active_workers)
2. Get Ready issues from project board
3. For each issue to dispatch:
Task(
description: "Issue #123 worker",
prompt: [WORKER_PROMPT],
subagent_type: "general-purpose",
run_in_background: true
)
4. Store returned task_id → issue mapping
Every loop iteration must check for and merge passing PRs:
# In each loop iteration
for pr in $(gh pr list --json number,statusCheckRollup --jq '.[] | select(.statusCheckRollup | all(.conclusion == "SUCCESS")) | .number'); do
# Check for do-not-merge label
if ! gh pr view "$pr" --json labels --jq '.labels[].name' | grep -q "do-not-merge"; then
echo "Merging PR #$pr (CI passed)"
gh pr merge "$pr" --squash --delete-branch
# Get linked issue and mark done
ISSUE=$(gh pr view "$pr" --json body --jq '.body' | grep -oE 'Closes #[0-9]+' | grep -oE '[0-9]+' | head -1)
if [ -n "$ISSUE" ]; then
# Update project board status to Done
mark_issue_done "$ISSUE"
fi
fi
done
Do NOT:
The loop continues until scope is complete. Green PR = immediate merge.
gh issue list --milestone "v1.0.0" --state open --json number --jq '.[].number'
gh issue list --label "epic-dark-mode" --state open --json number --jq '.[].number'
gh issue list --state open --json number --jq '.[].number'
Do NOT ask for "UNBOUNDED" confirmation. The user's request is their consent.
Workers that fail do NOT immediately become blocked:
Attempt 1 → Research → Attempt 2 → Research → Attempt 3 → Research → Attempt 4 → BLOCKED
Only after 3+ research cycles is an issue marked as blocked.
See: reference/failure-recovery.md for research cycle implementation.
An issue is only marked blocked when:
Orchestration sleeps when:
State is posted to GitHub tracking issue (survives crashes).
claude --resume [SESSION_ID]Before starting orchestration:
gh auth status)orchestration-tracking labelBootstrap phase:
release/*, release-placeholder, do-not-merge labels)During orchestration:
Task(run_in_background: true)TaskOutput(block: false)CRITICAL: The orchestrator verifies review compliance:
Before PR merge:
Child issues (from deferred findings):
issue-driven-development processspawned-from:#N labelDeviation handling:
This skill coordinates:
| Skill | Purpose |
|---|---|
worker-dispatch | Spawning workers |
worker-protocol | Worker behavior |
worker-handover | Context passing |
ci-monitoring | CI and WAKE handling |
research-after-failure | Research cycles |
issue-driven-development | Worker follows this |
comprehensive-review | Workers must complete before PR |
project-board-enforcement | ALL state queries and updates |
reference/state-management.md - State queries, updates, deviation handlingreference/loop-implementation.md - Full loop code and helpersreference/failure-recovery.md - Research cycles, blocked handling, SLEEP/WAKEThis skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.