|
| 1 | +--- |
| 2 | +name: queue |
| 3 | +description: Form execution queue from bound solutions using issue-queue-agent |
| 4 | +argument-hint: "[--rebuild] [--issue <id>]" |
| 5 | +allowed-tools: TodoWrite(*), Task(*), Bash(*), Read(*), Write(*) |
| 6 | +--- |
| 7 | + |
| 8 | +# Issue Queue Command (/issue:queue) |
| 9 | + |
| 10 | +## Overview |
| 11 | + |
| 12 | +Queue formation command using **issue-queue-agent** that analyzes all bound solutions, resolves conflicts, determines dependencies, and creates an ordered execution queue. The queue is global across all issues. |
| 13 | + |
| 14 | +**Core capabilities:** |
| 15 | +- **Agent-driven**: issue-queue-agent handles all ordering logic |
| 16 | +- ACE semantic search for relationship discovery |
| 17 | +- Dependency DAG construction and cycle detection |
| 18 | +- File conflict detection and resolution |
| 19 | +- Semantic priority calculation (0.0-1.0) |
| 20 | +- Parallel/Sequential group assignment |
| 21 | +- Output global queue.json |
| 22 | + |
| 23 | +## Storage Structure (Flat JSONL) |
| 24 | + |
| 25 | +``` |
| 26 | +.workflow/issues/ |
| 27 | +├── issues.jsonl # All issues (one per line) |
| 28 | +├── queue.json # Execution queue (output) |
| 29 | +└── solutions/ |
| 30 | + ├── {issue-id}.jsonl # Solutions for issue |
| 31 | + └── ... |
| 32 | +``` |
| 33 | + |
| 34 | +## Usage |
| 35 | + |
| 36 | +```bash |
| 37 | +/issue:queue [FLAGS] |
| 38 | + |
| 39 | +# Examples |
| 40 | +/issue:queue # Form queue from all bound solutions |
| 41 | +/issue:queue --rebuild # Rebuild queue (clear and regenerate) |
| 42 | +/issue:queue --issue GH-123 # Add only specific issue to queue |
| 43 | + |
| 44 | +# Flags |
| 45 | +--rebuild Clear existing queue and regenerate |
| 46 | +--issue <id> Add only specific issue's tasks |
| 47 | +``` |
| 48 | +
|
| 49 | +## Execution Process |
| 50 | +
|
| 51 | +``` |
| 52 | +Phase 1: Solution Loading |
| 53 | + ├─ Load issues.jsonl |
| 54 | + ├─ Filter issues with bound_solution_id |
| 55 | + ├─ Read solutions/{issue-id}.jsonl for each issue |
| 56 | + ├─ Find bound solution by ID |
| 57 | + └─ Extract tasks from bound solutions |
| 58 | +
|
| 59 | +Phase 2-4: Agent-Driven Queue Formation (issue-queue-agent) |
| 60 | + ├─ Launch issue-queue-agent with all tasks |
| 61 | + ├─ Agent performs: |
| 62 | + │ ├─ Build dependency DAG from depends_on |
| 63 | + │ ├─ Detect circular dependencies |
| 64 | + │ ├─ Identify file modification conflicts |
| 65 | + │ ├─ Resolve conflicts using ordering rules |
| 66 | + │ ├─ Calculate semantic priority (0.0-1.0) |
| 67 | + │ └─ Assign execution groups (parallel/sequential) |
| 68 | + └─ Output: queue JSON with ordered tasks |
| 69 | +
|
| 70 | +Phase 5: Queue Output |
| 71 | + ├─ Write queue.json |
| 72 | + ├─ Update issue statuses in issues.jsonl |
| 73 | + └─ Display queue summary |
| 74 | +``` |
| 75 | +
|
| 76 | +## Implementation |
| 77 | +
|
| 78 | +### Phase 1: Solution Loading |
| 79 | +
|
| 80 | +```javascript |
| 81 | +// Load issues.jsonl |
| 82 | +const issuesPath = '.workflow/issues/issues.jsonl'; |
| 83 | +const allIssues = Bash(`cat "${issuesPath}" 2>/dev/null || echo ''`) |
| 84 | + .split('\n') |
| 85 | + .filter(line => line.trim()) |
| 86 | + .map(line => JSON.parse(line)); |
| 87 | +
|
| 88 | +// Filter issues with bound solutions |
| 89 | +const plannedIssues = allIssues.filter(i => |
| 90 | + i.status === 'planned' && i.bound_solution_id |
| 91 | +); |
| 92 | +
|
| 93 | +if (plannedIssues.length === 0) { |
| 94 | + console.log('No issues with bound solutions found.'); |
| 95 | + console.log('Run /issue:plan first to create and bind solutions.'); |
| 96 | + return; |
| 97 | +} |
| 98 | +
|
| 99 | +// Load all tasks from bound solutions |
| 100 | +const allTasks = []; |
| 101 | +for (const issue of plannedIssues) { |
| 102 | + const solPath = `.workflow/issues/solutions/${issue.id}.jsonl`; |
| 103 | + const solutions = Bash(`cat "${solPath}" 2>/dev/null || echo ''`) |
| 104 | + .split('\n') |
| 105 | + .filter(line => line.trim()) |
| 106 | + .map(line => JSON.parse(line)); |
| 107 | +
|
| 108 | + // Find bound solution |
| 109 | + const boundSol = solutions.find(s => s.id === issue.bound_solution_id); |
| 110 | +
|
| 111 | + if (!boundSol) { |
| 112 | + console.log(`⚠ Bound solution ${issue.bound_solution_id} not found for ${issue.id}`); |
| 113 | + continue; |
| 114 | + } |
| 115 | +
|
| 116 | + for (const task of boundSol.tasks || []) { |
| 117 | + allTasks.push({ |
| 118 | + issue_id: issue.id, |
| 119 | + solution_id: issue.bound_solution_id, |
| 120 | + task, |
| 121 | + exploration_context: boundSol.exploration_context |
| 122 | + }); |
| 123 | + } |
| 124 | +} |
| 125 | +
|
| 126 | +console.log(`Loaded ${allTasks.length} tasks from ${plannedIssues.length} issues`); |
| 127 | +``` |
| 128 | +
|
| 129 | +### Phase 2-4: Agent-Driven Queue Formation |
| 130 | +
|
| 131 | +```javascript |
| 132 | +// Launch issue-queue-agent to handle all ordering logic |
| 133 | +const agentPrompt = ` |
| 134 | +## Tasks to Order |
| 135 | +
|
| 136 | +${JSON.stringify(allTasks, null, 2)} |
| 137 | +
|
| 138 | +## Project Root |
| 139 | +${process.cwd()} |
| 140 | +
|
| 141 | +## Requirements |
| 142 | +1. Build dependency DAG from depends_on fields |
| 143 | +2. Detect circular dependencies (abort if found) |
| 144 | +3. Identify file modification conflicts |
| 145 | +4. Resolve conflicts using ordering rules: |
| 146 | + - Create before Update/Implement |
| 147 | + - Foundation scopes (config/types) before implementation |
| 148 | + - Core logic before tests |
| 149 | +5. Calculate semantic priority (0.0-1.0) for each task |
| 150 | +6. Assign execution groups (parallel P* / sequential S*) |
| 151 | +7. Output queue JSON |
| 152 | +`; |
| 153 | +
|
| 154 | +const result = Task( |
| 155 | + subagent_type="issue-queue-agent", |
| 156 | + run_in_background=false, |
| 157 | + description=`Order ${allTasks.length} tasks from ${plannedIssues.length} issues`, |
| 158 | + prompt=agentPrompt |
| 159 | +); |
| 160 | +
|
| 161 | +// Parse agent output |
| 162 | +const agentOutput = JSON.parse(result); |
| 163 | +
|
| 164 | +if (!agentOutput.success) { |
| 165 | + console.error(`Queue formation failed: ${agentOutput.error}`); |
| 166 | + if (agentOutput.cycles) { |
| 167 | + console.error('Circular dependencies:', agentOutput.cycles.join(', ')); |
| 168 | + } |
| 169 | + return; |
| 170 | +} |
| 171 | +``` |
| 172 | +
|
| 173 | +### Phase 5: Queue Output & Summary |
| 174 | +
|
| 175 | +```javascript |
| 176 | +const queueOutput = agentOutput.output; |
| 177 | +
|
| 178 | +// Write queue.json |
| 179 | +Write('.workflow/issues/queue.json', JSON.stringify(queueOutput, null, 2)); |
| 180 | +
|
| 181 | +// Update issue statuses in issues.jsonl |
| 182 | +const updatedIssues = allIssues.map(issue => { |
| 183 | + if (plannedIssues.find(p => p.id === issue.id)) { |
| 184 | + return { |
| 185 | + ...issue, |
| 186 | + status: 'queued', |
| 187 | + queued_at: new Date().toISOString(), |
| 188 | + updated_at: new Date().toISOString() |
| 189 | + }; |
| 190 | + } |
| 191 | + return issue; |
| 192 | +}); |
| 193 | +
|
| 194 | +Write(issuesPath, updatedIssues.map(i => JSON.stringify(i)).join('\n')); |
| 195 | +
|
| 196 | +// Display summary |
| 197 | +console.log(` |
| 198 | +## Queue Formed |
| 199 | +
|
| 200 | +**Total Tasks**: ${queueOutput.queue.length} |
| 201 | +**Issues**: ${plannedIssues.length} |
| 202 | +**Conflicts**: ${queueOutput.conflicts?.length || 0} (${queueOutput._metadata?.resolved_conflicts || 0} resolved) |
| 203 | +
|
| 204 | +### Execution Groups |
| 205 | +${(queueOutput.execution_groups || []).map(g => { |
| 206 | + const type = g.type === 'parallel' ? 'Parallel' : 'Sequential'; |
| 207 | + return `- ${g.id} (${type}): ${g.task_count} tasks`; |
| 208 | +}).join('\n')} |
| 209 | +
|
| 210 | +### Next Steps |
| 211 | +1. Review queue: \`ccw issue queue list\` |
| 212 | +2. Execute: \`/issue:execute\` |
| 213 | +`); |
| 214 | +``` |
| 215 | +
|
| 216 | +## Queue Schema |
| 217 | +
|
| 218 | +Output `queue.json`: |
| 219 | +
|
| 220 | +```json |
| 221 | +{ |
| 222 | + "queue": [ |
| 223 | + { |
| 224 | + "queue_id": "Q-001", |
| 225 | + "issue_id": "GH-123", |
| 226 | + "solution_id": "SOL-001", |
| 227 | + "task_id": "T1", |
| 228 | + "status": "pending", |
| 229 | + "execution_order": 1, |
| 230 | + "execution_group": "P1", |
| 231 | + "depends_on": [], |
| 232 | + "semantic_priority": 0.7, |
| 233 | + "queued_at": "2025-12-26T10:00:00Z" |
| 234 | + } |
| 235 | + ], |
| 236 | + "conflicts": [ |
| 237 | + { |
| 238 | + "type": "file_conflict", |
| 239 | + "file": "src/auth.ts", |
| 240 | + "tasks": ["GH-123:T1", "GH-124:T2"], |
| 241 | + "resolution": "sequential", |
| 242 | + "resolution_order": ["GH-123:T1", "GH-124:T2"], |
| 243 | + "rationale": "T1 creates file before T2 updates", |
| 244 | + "resolved": true |
| 245 | + } |
| 246 | + ], |
| 247 | + "execution_groups": [ |
| 248 | + { "id": "P1", "type": "parallel", "task_count": 3, "tasks": ["GH-123:T1", "GH-124:T1", "GH-125:T1"] }, |
| 249 | + { "id": "S2", "type": "sequential", "task_count": 2, "tasks": ["GH-123:T2", "GH-124:T2"] } |
| 250 | + ], |
| 251 | + "_metadata": { |
| 252 | + "version": "2.0", |
| 253 | + "storage": "jsonl", |
| 254 | + "total_tasks": 5, |
| 255 | + "total_conflicts": 1, |
| 256 | + "resolved_conflicts": 1, |
| 257 | + "parallel_groups": 1, |
| 258 | + "sequential_groups": 1, |
| 259 | + "timestamp": "2025-12-26T10:00:00Z", |
| 260 | + "source": "issue-queue-agent" |
| 261 | + } |
| 262 | +} |
| 263 | +``` |
| 264 | +
|
| 265 | +## Semantic Priority Rules |
| 266 | +
|
| 267 | +| Factor | Priority Boost | |
| 268 | +|--------|---------------| |
| 269 | +| Create action | +0.2 | |
| 270 | +| Configure action | +0.15 | |
| 271 | +| Implement action | +0.1 | |
| 272 | +| Config/Types scope | +0.1 | |
| 273 | +| Refactor action | -0.05 | |
| 274 | +| Test action | -0.1 | |
| 275 | +| Delete action | -0.15 | |
| 276 | +
|
| 277 | +## Error Handling |
| 278 | +
|
| 279 | +| Error | Resolution | |
| 280 | +|-------|------------| |
| 281 | +| No bound solutions | Display message, suggest /issue:plan | |
| 282 | +| Circular dependency | List cycles, abort queue formation | |
| 283 | +| Unresolved conflicts | Agent resolves using ordering rules | |
| 284 | +| Invalid task reference | Skip and warn | |
| 285 | +
|
| 286 | +## Agent Integration |
| 287 | +
|
| 288 | +The command uses `issue-queue-agent` which: |
| 289 | +1. Builds dependency DAG from task depends_on fields |
| 290 | +2. Detects circular dependencies (aborts if found) |
| 291 | +3. Identifies file modification conflicts across issues |
| 292 | +4. Resolves conflicts using semantic ordering rules |
| 293 | +5. Calculates priority (0.0-1.0) for each task |
| 294 | +6. Assigns parallel/sequential execution groups |
| 295 | +7. Outputs structured queue JSON |
| 296 | +
|
| 297 | +See `.claude/agents/issue-queue-agent.md` for agent specification. |
| 298 | +
|
| 299 | +## Related Commands |
| 300 | +
|
| 301 | +- `/issue:plan` - Plan issues and bind solutions |
| 302 | +- `/issue:execute` - Execute queue with codex |
| 303 | +- `ccw issue queue list` - View current queue |
0 commit comments