claude-code-workflow 6.3.27 → 6.3.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +7 -1
- package/.claude/agents/action-planning-agent.md +1 -0
- package/.claude/agents/cli-discuss-agent.md +391 -0
- package/.claude/agents/cli-execution-agent.md +2 -0
- package/.claude/agents/cli-explore-agent.md +2 -1
- package/.claude/agents/cli-lite-planning-agent.md +1 -0
- package/.claude/agents/cli-planning-agent.md +1 -0
- package/.claude/agents/code-developer.md +1 -0
- package/.claude/agents/conceptual-planning-agent.md +2 -0
- package/.claude/agents/context-search-agent.md +1 -0
- package/.claude/agents/debug-explore-agent.md +2 -0
- package/.claude/agents/doc-generator.md +1 -0
- package/.claude/agents/issue-plan-agent.md +2 -1
- package/.claude/agents/issue-queue-agent.md +2 -1
- package/.claude/agents/memory-bridge.md +2 -0
- package/.claude/agents/test-context-search-agent.md +2 -0
- package/.claude/agents/test-fix-agent.md +1 -0
- package/.claude/agents/ui-design-agent.md +2 -0
- package/.claude/agents/universal-executor.md +1 -0
- package/.claude/commands/issue/execute.md +269 -176
- package/.claude/commands/workflow/debug.md +6 -0
- package/.claude/commands/workflow/execute.md +4 -0
- package/.claude/commands/workflow/lite-execute.md +4 -0
- package/.claude/commands/workflow/lite-lite-lite.md +433 -0
- package/.claude/commands/workflow/multi-cli-plan.md +510 -0
- package/.claude/commands/workflow/review-fix.md +4 -0
- package/.claude/commands/workflow/test-cycle-execute.md +4 -0
- package/.claude/skills/ccw/SKILL.md +262 -372
- package/.claude/skills/ccw/command.json +547 -0
- package/.claude/skills/ccw-help/SKILL.md +46 -107
- package/.claude/skills/ccw-help/command.json +511 -0
- package/.claude/skills/skill-tuning/SKILL.md +303 -0
- package/.claude/skills/skill-tuning/phases/actions/action-abort.md +164 -0
- package/.claude/skills/skill-tuning/phases/actions/action-analyze-requirements.md +406 -0
- package/.claude/skills/skill-tuning/phases/actions/action-apply-fix.md +206 -0
- package/.claude/skills/skill-tuning/phases/actions/action-complete.md +195 -0
- package/.claude/skills/skill-tuning/phases/actions/action-diagnose-agent.md +317 -0
- package/.claude/skills/skill-tuning/phases/actions/action-diagnose-context.md +243 -0
- package/.claude/skills/skill-tuning/phases/actions/action-diagnose-dataflow.md +318 -0
- package/.claude/skills/skill-tuning/phases/actions/action-diagnose-docs.md +299 -0
- package/.claude/skills/skill-tuning/phases/actions/action-diagnose-memory.md +269 -0
- package/.claude/skills/skill-tuning/phases/actions/action-diagnose-token-consumption.md +200 -0
- package/.claude/skills/skill-tuning/phases/actions/action-gemini-analysis.md +322 -0
- package/.claude/skills/skill-tuning/phases/actions/action-generate-report.md +228 -0
- package/.claude/skills/skill-tuning/phases/actions/action-init.md +149 -0
- package/.claude/skills/skill-tuning/phases/actions/action-propose-fixes.md +317 -0
- package/.claude/skills/skill-tuning/phases/actions/action-verify.md +222 -0
- package/.claude/skills/skill-tuning/phases/orchestrator.md +377 -0
- package/.claude/skills/skill-tuning/phases/state-schema.md +378 -0
- package/.claude/skills/skill-tuning/specs/category-mappings.json +284 -0
- package/.claude/skills/skill-tuning/specs/dimension-mapping.md +212 -0
- package/.claude/skills/skill-tuning/specs/problem-taxonomy.md +318 -0
- package/.claude/skills/skill-tuning/specs/quality-gates.md +263 -0
- package/.claude/skills/skill-tuning/specs/skill-authoring-principles.md +189 -0
- package/.claude/skills/skill-tuning/specs/tuning-strategies.md +1537 -0
- package/.claude/skills/skill-tuning/templates/diagnosis-report.md +153 -0
- package/.claude/skills/skill-tuning/templates/fix-proposal.md +204 -0
- package/.claude/workflows/cli-templates/schemas/multi-cli-discussion-schema.json +421 -0
- package/.claude/workflows/cli-tools-usage.md +0 -41
- package/.codex/prompts/issue-execute.md +72 -12
- package/README.md +3 -0
- package/ccw/dist/core/data-aggregator.d.ts +2 -0
- package/ccw/dist/core/data-aggregator.d.ts.map +1 -1
- package/ccw/dist/core/data-aggregator.js +5 -2
- package/ccw/dist/core/data-aggregator.js.map +1 -1
- package/ccw/dist/core/lite-scanner.d.ts +2 -1
- package/ccw/dist/core/lite-scanner.d.ts.map +1 -1
- package/ccw/dist/core/lite-scanner.js +348 -6
- package/ccw/dist/core/lite-scanner.js.map +1 -1
- package/ccw/dist/core/routes/session-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/session-routes.js +166 -48
- package/ccw/dist/core/routes/session-routes.js.map +1 -1
- package/ccw/dist/core/routes/system-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/system-routes.js +87 -0
- package/ccw/dist/core/routes/system-routes.js.map +1 -1
- package/ccw/dist/core/server.js +2 -2
- package/ccw/dist/core/server.js.map +1 -1
- package/ccw/dist/tools/memory-update-queue.d.ts.map +1 -1
- package/ccw/dist/tools/memory-update-queue.js +5 -11
- package/ccw/dist/tools/memory-update-queue.js.map +1 -1
- package/ccw/scripts/IMPLEMENTATION-SUMMARY.md +226 -0
- package/ccw/scripts/QUICK-REFERENCE.md +135 -0
- package/ccw/scripts/README-memory-embedder.md +157 -0
- package/ccw/scripts/__pycache__/memory_embedder.cpython-313.pyc +0 -0
- package/ccw/scripts/__pycache__/test_memory_embedder.cpython-313-pytest-8.4.2.pyc +0 -0
- package/ccw/scripts/memory-embedder-example.ts +184 -0
- package/ccw/scripts/memory_embedder.py +428 -0
- package/ccw/scripts/test_memory_embedder.py +245 -0
- package/ccw/src/core/data-aggregator.ts +7 -2
- package/ccw/src/core/lite-scanner.ts +495 -6
- package/ccw/src/core/routes/session-routes.ts +201 -48
- package/ccw/src/core/routes/system-routes.ts +102 -0
- package/ccw/src/core/server.ts +2 -2
- package/ccw/src/templates/dashboard-css/01-base.css +8 -0
- package/ccw/src/templates/dashboard-css/02-session.css +81 -0
- package/ccw/src/templates/dashboard-css/03-tasks.css +5 -0
- package/ccw/src/templates/dashboard-css/04-lite-tasks.css +3071 -0
- package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +157 -0
- package/ccw/src/templates/dashboard-css/32-issue-manager.css +23 -0
- package/ccw/src/templates/dashboard-js/components/cli-stream-viewer.js +38 -4
- package/ccw/src/templates/dashboard-js/components/hook-manager.js +68 -34
- package/ccw/src/templates/dashboard-js/components/navigation.js +24 -4
- package/ccw/src/templates/dashboard-js/i18n.js +278 -4
- package/ccw/src/templates/dashboard-js/views/api-settings.js +32 -0
- package/ccw/src/templates/dashboard-js/views/claude-manager.js +44 -3
- package/ccw/src/templates/dashboard-js/views/cli-manager.js +303 -31
- package/ccw/src/templates/dashboard-js/views/history.js +44 -6
- package/ccw/src/templates/dashboard-js/views/home.js +1 -0
- package/ccw/src/templates/dashboard-js/views/issue-manager.js +54 -7
- package/ccw/src/templates/dashboard-js/views/lite-tasks.js +2621 -4
- package/ccw/src/templates/dashboard.html +5 -0
- package/ccw/src/tools/memory-update-queue.js +5 -11
- package/package.json +2 -1
- package/.claude/skills/ccw/index/command-capabilities.json +0 -127
- package/.claude/skills/ccw/index/intent-rules.json +0 -136
- package/.claude/skills/ccw/index/workflow-chains.json +0 -451
- package/.claude/skills/ccw/phases/actions/bugfix.md +0 -218
- package/.claude/skills/ccw/phases/actions/coupled.md +0 -194
- package/.claude/skills/ccw/phases/actions/docs.md +0 -93
- package/.claude/skills/ccw/phases/actions/full.md +0 -154
- package/.claude/skills/ccw/phases/actions/issue.md +0 -201
- package/.claude/skills/ccw/phases/actions/rapid.md +0 -104
- package/.claude/skills/ccw/phases/actions/review-fix.md +0 -84
- package/.claude/skills/ccw/phases/actions/tdd.md +0 -66
- package/.claude/skills/ccw/phases/actions/ui.md +0 -79
- package/.claude/skills/ccw/phases/orchestrator.md +0 -435
- package/.claude/skills/ccw/specs/intent-classification.md +0 -336
- package/.claude/skills/ccw-help/index/all-agents.json +0 -82
- package/.claude/skills/ccw-help/index/all-commands.json +0 -882
- package/.claude/skills/ccw-help/index/by-category.json +0 -914
- package/.claude/skills/ccw-help/index/by-use-case.json +0 -896
- package/.claude/skills/ccw-help/index/command-relationships.json +0 -160
- package/.claude/skills/ccw-help/index/essential-commands.json +0 -112
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: execute
|
|
3
3
|
description: Execute queue with DAG-based parallel orchestration (one commit per solution)
|
|
4
|
-
argument-hint: "
|
|
4
|
+
argument-hint: "--queue <queue-id> [--worktree [<existing-path>]]"
|
|
5
5
|
allowed-tools: TodoWrite(*), Bash(*), Read(*), AskUserQuestion(*)
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -17,21 +17,64 @@ Minimal orchestrator that dispatches **solution IDs** to executors. Each executo
|
|
|
17
17
|
- `done <id>` → update solution completion status
|
|
18
18
|
- No race conditions: status changes only via `done`
|
|
19
19
|
- **Executor handles all tasks within a solution sequentially**
|
|
20
|
-
- **
|
|
20
|
+
- **Single worktree for entire queue**: One worktree isolates ALL queue execution from main workspace
|
|
21
|
+
|
|
22
|
+
## Queue ID Requirement (MANDATORY)
|
|
23
|
+
|
|
24
|
+
**Queue ID is REQUIRED.** You MUST specify which queue to execute via `--queue <queue-id>`.
|
|
25
|
+
|
|
26
|
+
### If Queue ID Not Provided
|
|
27
|
+
|
|
28
|
+
When `--queue` parameter is missing, you MUST:
|
|
29
|
+
|
|
30
|
+
1. **List available queues** by running:
|
|
31
|
+
```javascript
|
|
32
|
+
const result = Bash('ccw issue queue list --brief --json');
|
|
33
|
+
const index = JSON.parse(result);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. **Display available queues** to user:
|
|
37
|
+
```
|
|
38
|
+
Available Queues:
|
|
39
|
+
ID Status Progress Issues
|
|
40
|
+
-----------------------------------------------------------
|
|
41
|
+
→ QUE-20251215-001 active 3/10 ISS-001, ISS-002
|
|
42
|
+
QUE-20251210-002 active 0/5 ISS-003
|
|
43
|
+
QUE-20251205-003 completed 8/8 ISS-004
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
3. **Stop and ask user** to specify which queue to execute:
|
|
47
|
+
```javascript
|
|
48
|
+
AskUserQuestion({
|
|
49
|
+
questions: [{
|
|
50
|
+
question: "Which queue would you like to execute?",
|
|
51
|
+
header: "Queue",
|
|
52
|
+
multiSelect: false,
|
|
53
|
+
options: index.queues
|
|
54
|
+
.filter(q => q.status === 'active')
|
|
55
|
+
.map(q => ({
|
|
56
|
+
label: q.id,
|
|
57
|
+
description: `${q.status}, ${q.completed_solutions || 0}/${q.total_solutions || 0} completed, Issues: ${q.issue_ids.join(', ')}`
|
|
58
|
+
}))
|
|
59
|
+
}]
|
|
60
|
+
})
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
4. **After user selection**, continue execution with the selected queue ID.
|
|
64
|
+
|
|
65
|
+
**DO NOT auto-select queues.** Explicit user confirmation is required to prevent accidental execution of wrong queue.
|
|
21
66
|
|
|
22
67
|
## Usage
|
|
23
68
|
|
|
24
69
|
```bash
|
|
25
|
-
/issue:execute
|
|
26
|
-
/issue:execute --queue QUE-xxx
|
|
27
|
-
/issue:execute --
|
|
28
|
-
/issue:execute --worktree --queue QUE-xxx
|
|
29
|
-
/issue:execute --worktree /path/to/existing/worktree # Resume in existing worktree
|
|
70
|
+
/issue:execute --queue QUE-xxx # Execute specific queue (REQUIRED)
|
|
71
|
+
/issue:execute --queue QUE-xxx --worktree # Execute in isolated worktree
|
|
72
|
+
/issue:execute --queue QUE-xxx --worktree /path/to/existing/worktree # Resume
|
|
30
73
|
```
|
|
31
74
|
|
|
32
75
|
**Parallelism**: Determined automatically by task dependency DAG (no manual control)
|
|
33
76
|
**Executor & Dry-run**: Selected via interactive prompt (AskUserQuestion)
|
|
34
|
-
**Worktree**: Creates
|
|
77
|
+
**Worktree**: Creates ONE worktree for the entire queue execution (not per-solution)
|
|
35
78
|
|
|
36
79
|
**⭐ Recommended Executor**: **Codex** - Best for long-running autonomous work (2hr timeout), supports background execution and full write access
|
|
37
80
|
|
|
@@ -44,37 +87,101 @@ Minimal orchestrator that dispatches **solution IDs** to executors. Each executo
|
|
|
44
87
|
## Execution Flow
|
|
45
88
|
|
|
46
89
|
```
|
|
47
|
-
Phase 0
|
|
48
|
-
|
|
90
|
+
Phase 0: Validate Queue ID (REQUIRED)
|
|
91
|
+
├─ If --queue provided → use specified queue
|
|
92
|
+
├─ If --queue missing → list queues, prompt user to select
|
|
93
|
+
└─ Store QUEUE_ID for all subsequent commands
|
|
94
|
+
|
|
95
|
+
Phase 0.5 (if --worktree): Setup Queue Worktree
|
|
96
|
+
├─ Create ONE worktree for entire queue: .ccw/worktrees/queue-<timestamp>
|
|
97
|
+
├─ All subsequent execution happens in this worktree
|
|
98
|
+
└─ Main workspace remains clean and untouched
|
|
49
99
|
|
|
50
100
|
Phase 1: Get DAG & User Selection
|
|
51
|
-
├─ ccw issue queue dag
|
|
101
|
+
├─ ccw issue queue dag --queue ${QUEUE_ID} → { parallel_batches: [["S-1","S-2"], ["S-3"]] }
|
|
52
102
|
└─ AskUserQuestion → executor type (codex|gemini|agent), dry-run mode, worktree mode
|
|
53
103
|
|
|
54
104
|
Phase 2: Dispatch Parallel Batch (DAG-driven)
|
|
55
105
|
├─ Parallelism determined by DAG (no manual limit)
|
|
106
|
+
├─ All executors work in the SAME worktree (or main if no worktree)
|
|
56
107
|
├─ For each solution ID in batch (parallel - all at once):
|
|
57
|
-
│ ├─ (if worktree) Create isolated worktree: git worktree add
|
|
58
108
|
│ ├─ Executor calls: ccw issue detail <id> (READ-ONLY)
|
|
59
109
|
│ ├─ Executor gets FULL SOLUTION with all tasks
|
|
60
110
|
│ ├─ Executor implements all tasks sequentially (T1 → T2 → T3)
|
|
61
111
|
│ ├─ Executor tests + verifies each task
|
|
62
112
|
│ ├─ Executor commits ONCE per solution (with formatted summary)
|
|
63
|
-
│
|
|
64
|
-
│ └─ (if worktree) Cleanup: merge branch, remove worktree
|
|
113
|
+
│ └─ Executor calls: ccw issue done <id>
|
|
65
114
|
└─ Wait for batch completion
|
|
66
115
|
|
|
67
|
-
Phase 3: Next Batch
|
|
116
|
+
Phase 3: Next Batch (repeat Phase 2)
|
|
68
117
|
└─ ccw issue queue dag → check for newly-ready solutions
|
|
118
|
+
|
|
119
|
+
Phase 4 (if --worktree): Worktree Completion
|
|
120
|
+
├─ All batches complete → prompt for merge strategy
|
|
121
|
+
└─ Options: Create PR / Merge to main / Keep branch
|
|
69
122
|
```
|
|
70
123
|
|
|
71
124
|
## Implementation
|
|
72
125
|
|
|
126
|
+
### Phase 0: Validate Queue ID
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
// Check if --queue was provided
|
|
130
|
+
let QUEUE_ID = args.queue;
|
|
131
|
+
|
|
132
|
+
if (!QUEUE_ID) {
|
|
133
|
+
// List available queues
|
|
134
|
+
const listResult = Bash('ccw issue queue list --brief --json').trim();
|
|
135
|
+
const index = JSON.parse(listResult);
|
|
136
|
+
|
|
137
|
+
if (index.queues.length === 0) {
|
|
138
|
+
console.log('No queues found. Use /issue:queue to create one first.');
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Filter active queues only
|
|
143
|
+
const activeQueues = index.queues.filter(q => q.status === 'active');
|
|
144
|
+
|
|
145
|
+
if (activeQueues.length === 0) {
|
|
146
|
+
console.log('No active queues found.');
|
|
147
|
+
console.log('Available queues:', index.queues.map(q => `${q.id} (${q.status})`).join(', '));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Display and prompt user
|
|
152
|
+
console.log('\nAvailable Queues:');
|
|
153
|
+
console.log('ID'.padEnd(22) + 'Status'.padEnd(12) + 'Progress'.padEnd(12) + 'Issues');
|
|
154
|
+
console.log('-'.repeat(70));
|
|
155
|
+
for (const q of index.queues) {
|
|
156
|
+
const marker = q.id === index.active_queue_id ? '→ ' : ' ';
|
|
157
|
+
console.log(marker + q.id.padEnd(20) + q.status.padEnd(12) +
|
|
158
|
+
`${q.completed_solutions || 0}/${q.total_solutions || 0}`.padEnd(12) +
|
|
159
|
+
q.issue_ids.join(', '));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const answer = AskUserQuestion({
|
|
163
|
+
questions: [{
|
|
164
|
+
question: "Which queue would you like to execute?",
|
|
165
|
+
header: "Queue",
|
|
166
|
+
multiSelect: false,
|
|
167
|
+
options: activeQueues.map(q => ({
|
|
168
|
+
label: q.id,
|
|
169
|
+
description: `${q.completed_solutions || 0}/${q.total_solutions || 0} completed, Issues: ${q.issue_ids.join(', ')}`
|
|
170
|
+
}))
|
|
171
|
+
}]
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
QUEUE_ID = answer['Queue'];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
console.log(`\n## Executing Queue: ${QUEUE_ID}\n`);
|
|
178
|
+
```
|
|
179
|
+
|
|
73
180
|
### Phase 1: Get DAG & User Selection
|
|
74
181
|
|
|
75
182
|
```javascript
|
|
76
|
-
// Get dependency graph and parallel batches
|
|
77
|
-
const dagJson = Bash(`ccw issue queue dag`).trim();
|
|
183
|
+
// Get dependency graph and parallel batches (QUEUE_ID required)
|
|
184
|
+
const dagJson = Bash(`ccw issue queue dag --queue ${QUEUE_ID}`).trim();
|
|
78
185
|
const dag = JSON.parse(dagJson);
|
|
79
186
|
|
|
80
187
|
if (dag.error || dag.ready_count === 0) {
|
|
@@ -115,12 +222,12 @@ const answer = AskUserQuestion({
|
|
|
115
222
|
]
|
|
116
223
|
},
|
|
117
224
|
{
|
|
118
|
-
question: 'Use git
|
|
225
|
+
question: 'Use git worktree for queue isolation?',
|
|
119
226
|
header: 'Worktree',
|
|
120
227
|
multiSelect: false,
|
|
121
228
|
options: [
|
|
122
|
-
{ label: 'Yes (Recommended
|
|
123
|
-
{ label: 'No', description: 'Work directly in current directory
|
|
229
|
+
{ label: 'Yes (Recommended)', description: 'Create ONE worktree for entire queue - main stays clean' },
|
|
230
|
+
{ label: 'No', description: 'Work directly in current directory' }
|
|
124
231
|
]
|
|
125
232
|
}
|
|
126
233
|
]
|
|
@@ -140,7 +247,7 @@ if (isDryRun) {
|
|
|
140
247
|
}
|
|
141
248
|
```
|
|
142
249
|
|
|
143
|
-
### Phase 2:
|
|
250
|
+
### Phase 0 & 2: Setup Queue Worktree & Dispatch
|
|
144
251
|
|
|
145
252
|
```javascript
|
|
146
253
|
// Parallelism determined by DAG - no manual limit
|
|
@@ -158,24 +265,40 @@ TodoWrite({
|
|
|
158
265
|
|
|
159
266
|
console.log(`\n### Executing Solutions (DAG batch 1): ${batch.join(', ')}`);
|
|
160
267
|
|
|
161
|
-
//
|
|
268
|
+
// Parse existing worktree path from args if provided
|
|
269
|
+
// Example: --worktree /path/to/existing/worktree
|
|
270
|
+
const existingWorktree = args.worktree && typeof args.worktree === 'string' ? args.worktree : null;
|
|
271
|
+
|
|
272
|
+
// Setup ONE worktree for entire queue (not per-solution)
|
|
273
|
+
let worktreePath = null;
|
|
274
|
+
let worktreeBranch = null;
|
|
275
|
+
|
|
162
276
|
if (useWorktree) {
|
|
163
|
-
// Use absolute paths to avoid issues when running from subdirectories
|
|
164
277
|
const repoRoot = Bash('git rev-parse --show-toplevel').trim();
|
|
165
278
|
const worktreeBase = `${repoRoot}/.ccw/worktrees`;
|
|
166
279
|
Bash(`mkdir -p "${worktreeBase}"`);
|
|
167
|
-
//
|
|
168
|
-
Bash('git worktree prune');
|
|
169
|
-
}
|
|
280
|
+
Bash('git worktree prune'); // Cleanup stale worktrees
|
|
170
281
|
|
|
171
|
-
|
|
172
|
-
//
|
|
173
|
-
|
|
282
|
+
if (existingWorktree) {
|
|
283
|
+
// Resume mode: Use existing worktree
|
|
284
|
+
worktreePath = existingWorktree;
|
|
285
|
+
worktreeBranch = Bash(`git -C "${worktreePath}" branch --show-current`).trim();
|
|
286
|
+
console.log(`Resuming in existing worktree: ${worktreePath} (branch: ${worktreeBranch})`);
|
|
287
|
+
} else {
|
|
288
|
+
// Create mode: ONE worktree for the entire queue
|
|
289
|
+
const timestamp = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 14);
|
|
290
|
+
worktreeBranch = `queue-exec-${dag.queue_id || timestamp}`;
|
|
291
|
+
worktreePath = `${worktreeBase}/${worktreeBranch}`;
|
|
292
|
+
Bash(`git worktree add "${worktreePath}" -b "${worktreeBranch}"`);
|
|
293
|
+
console.log(`Created queue worktree: ${worktreePath}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
174
296
|
|
|
175
297
|
// Launch ALL solutions in batch in parallel (DAG guarantees no conflicts)
|
|
298
|
+
// All executors work in the SAME worktree (or main if no worktree)
|
|
176
299
|
const executions = batch.map(solutionId => {
|
|
177
300
|
updateTodo(solutionId, 'in_progress');
|
|
178
|
-
return dispatchExecutor(solutionId, executor,
|
|
301
|
+
return dispatchExecutor(solutionId, executor, worktreePath);
|
|
179
302
|
});
|
|
180
303
|
|
|
181
304
|
await Promise.all(executions);
|
|
@@ -185,126 +308,20 @@ batch.forEach(id => updateTodo(id, 'completed'));
|
|
|
185
308
|
### Executor Dispatch
|
|
186
309
|
|
|
187
310
|
```javascript
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
\`\`\`bash
|
|
194
|
-
# Use absolute paths to avoid issues when running from subdirectories
|
|
195
|
-
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
196
|
-
WORKTREE_BASE="\${REPO_ROOT}/.ccw/worktrees"
|
|
197
|
-
|
|
198
|
-
# Check if existing worktree path was provided
|
|
199
|
-
EXISTING_WORKTREE="${existingWorktree || ''}"
|
|
200
|
-
|
|
201
|
-
if [[ -n "\${EXISTING_WORKTREE}" && -d "\${EXISTING_WORKTREE}" ]]; then
|
|
202
|
-
# Resume mode: Use existing worktree
|
|
203
|
-
WORKTREE_PATH="\${EXISTING_WORKTREE}"
|
|
204
|
-
WORKTREE_NAME=$(basename "\${WORKTREE_PATH}")
|
|
205
|
-
|
|
206
|
-
# Verify it's a valid git worktree
|
|
207
|
-
if ! git -C "\${WORKTREE_PATH}" rev-parse --is-inside-work-tree &>/dev/null; then
|
|
208
|
-
echo "Error: \${EXISTING_WORKTREE} is not a valid git worktree"
|
|
209
|
-
exit 1
|
|
210
|
-
fi
|
|
211
|
-
|
|
212
|
-
echo "Resuming in existing worktree: \${WORKTREE_PATH}"
|
|
213
|
-
else
|
|
214
|
-
# Create mode: New worktree with timestamp
|
|
215
|
-
WORKTREE_NAME="exec-${solutionId}-$(date +%H%M%S)"
|
|
216
|
-
WORKTREE_PATH="\${WORKTREE_BASE}/\${WORKTREE_NAME}"
|
|
217
|
-
|
|
218
|
-
# Ensure worktree base exists
|
|
219
|
-
mkdir -p "\${WORKTREE_BASE}"
|
|
220
|
-
|
|
221
|
-
# Prune stale worktrees
|
|
222
|
-
git worktree prune
|
|
223
|
-
|
|
224
|
-
# Create worktree
|
|
225
|
-
git worktree add "\${WORKTREE_PATH}" -b "\${WORKTREE_NAME}"
|
|
226
|
-
|
|
227
|
-
echo "Created new worktree: \${WORKTREE_PATH}"
|
|
228
|
-
fi
|
|
229
|
-
|
|
230
|
-
# Setup cleanup trap for graceful failure handling
|
|
231
|
-
cleanup_worktree() {
|
|
232
|
-
echo "Cleaning up worktree due to interruption..."
|
|
233
|
-
cd "\${REPO_ROOT}" 2>/dev/null || true
|
|
234
|
-
git worktree remove "\${WORKTREE_PATH}" --force 2>/dev/null || true
|
|
235
|
-
echo "Worktree removed. Branch '\${WORKTREE_NAME}' kept for inspection."
|
|
236
|
-
}
|
|
237
|
-
trap cleanup_worktree EXIT INT TERM
|
|
238
|
-
|
|
239
|
-
cd "\${WORKTREE_PATH}"
|
|
240
|
-
\`\`\`
|
|
241
|
-
` : '';
|
|
242
|
-
|
|
243
|
-
const worktreeCleanup = useWorktree ? `
|
|
244
|
-
### Step 5: Worktree Completion (User Choice)
|
|
245
|
-
|
|
246
|
-
After all tasks complete, prompt for merge strategy:
|
|
247
|
-
|
|
248
|
-
\`\`\`javascript
|
|
249
|
-
AskUserQuestion({
|
|
250
|
-
questions: [{
|
|
251
|
-
question: "Solution ${solutionId} completed. What to do with worktree branch?",
|
|
252
|
-
header: "Merge",
|
|
253
|
-
multiSelect: false,
|
|
254
|
-
options: [
|
|
255
|
-
{ label: "Create PR (Recommended)", description: "Push branch and create pull request - safest for parallel execution" },
|
|
256
|
-
{ label: "Merge to main", description: "Merge branch and cleanup worktree (requires clean main)" },
|
|
257
|
-
{ label: "Keep branch", description: "Cleanup worktree, keep branch for manual handling" }
|
|
258
|
-
]
|
|
259
|
-
}]
|
|
260
|
-
})
|
|
261
|
-
\`\`\`
|
|
262
|
-
|
|
263
|
-
**Based on selection:**
|
|
264
|
-
\`\`\`bash
|
|
265
|
-
# Disable cleanup trap before intentional cleanup
|
|
266
|
-
trap - EXIT INT TERM
|
|
267
|
-
|
|
268
|
-
# Return to repo root (use REPO_ROOT from setup)
|
|
269
|
-
cd "\${REPO_ROOT}"
|
|
270
|
-
|
|
271
|
-
# Validate main repo state before merge
|
|
272
|
-
validate_main_clean() {
|
|
273
|
-
if [[ -n \$(git status --porcelain) ]]; then
|
|
274
|
-
echo "⚠️ Warning: Main repo has uncommitted changes."
|
|
275
|
-
echo "Cannot auto-merge. Falling back to 'Create PR' option."
|
|
276
|
-
return 1
|
|
277
|
-
fi
|
|
278
|
-
return 0
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
# Create PR (Recommended for parallel execution):
|
|
282
|
-
git push -u origin "\${WORKTREE_NAME}"
|
|
283
|
-
gh pr create --title "Solution ${solutionId}" --body "Issue queue execution"
|
|
284
|
-
git worktree remove "\${WORKTREE_PATH}"
|
|
285
|
-
|
|
286
|
-
# Merge to main (only if main is clean):
|
|
287
|
-
if validate_main_clean; then
|
|
288
|
-
git merge --no-ff "\${WORKTREE_NAME}" -m "Merge solution ${solutionId}"
|
|
289
|
-
git worktree remove "\${WORKTREE_PATH}" && git branch -d "\${WORKTREE_NAME}"
|
|
290
|
-
else
|
|
291
|
-
# Fallback to PR if main is dirty
|
|
292
|
-
git push -u origin "\${WORKTREE_NAME}"
|
|
293
|
-
gh pr create --title "Solution ${solutionId}" --body "Issue queue execution (main had uncommitted changes)"
|
|
294
|
-
git worktree remove "\${WORKTREE_PATH}"
|
|
295
|
-
fi
|
|
296
|
-
|
|
297
|
-
# Keep branch:
|
|
298
|
-
git worktree remove "\${WORKTREE_PATH}"
|
|
299
|
-
echo "Branch \${WORKTREE_NAME} kept for manual handling"
|
|
300
|
-
\`\`\`
|
|
301
|
-
|
|
302
|
-
**Parallel Execution Safety**: "Create PR" is the default and safest option for parallel executors, avoiding merge race conditions.
|
|
303
|
-
` : '';
|
|
311
|
+
// worktreePath: path to shared worktree (null if not using worktree)
|
|
312
|
+
function dispatchExecutor(solutionId, executorType, worktreePath = null) {
|
|
313
|
+
// If worktree is provided, executor works in that directory
|
|
314
|
+
// No per-solution worktree creation - ONE worktree for entire queue
|
|
315
|
+
const cdCommand = worktreePath ? `cd "${worktreePath}"` : '';
|
|
304
316
|
|
|
305
317
|
const prompt = `
|
|
306
318
|
## Execute Solution ${solutionId}
|
|
307
|
-
${
|
|
319
|
+
${worktreePath ? `
|
|
320
|
+
### Step 0: Enter Queue Worktree
|
|
321
|
+
\`\`\`bash
|
|
322
|
+
cd "${worktreePath}"
|
|
323
|
+
\`\`\`
|
|
324
|
+
` : ''}
|
|
308
325
|
### Step 1: Get Solution (read-only)
|
|
309
326
|
\`\`\`bash
|
|
310
327
|
ccw issue detail ${solutionId}
|
|
@@ -352,16 +369,21 @@ If any task failed:
|
|
|
352
369
|
\`\`\`bash
|
|
353
370
|
ccw issue done ${solutionId} --fail --reason '{"task_id": "TX", "error_type": "test_failure", "message": "..."}'
|
|
354
371
|
\`\`\`
|
|
355
|
-
|
|
372
|
+
|
|
373
|
+
**Note**: Do NOT cleanup worktree after this solution. Worktree is shared by all solutions in the queue.
|
|
374
|
+
`;
|
|
375
|
+
|
|
376
|
+
// For CLI tools, pass --cd to set working directory
|
|
377
|
+
const cdOption = worktreePath ? ` --cd "${worktreePath}"` : '';
|
|
356
378
|
|
|
357
379
|
if (executorType === 'codex') {
|
|
358
380
|
return Bash(
|
|
359
|
-
`ccw cli -p "${escapePrompt(prompt)}" --tool codex --mode write --id exec-${solutionId}`,
|
|
381
|
+
`ccw cli -p "${escapePrompt(prompt)}" --tool codex --mode write --id exec-${solutionId}${cdOption}`,
|
|
360
382
|
{ timeout: 7200000, run_in_background: true } // 2hr for full solution
|
|
361
383
|
);
|
|
362
384
|
} else if (executorType === 'gemini') {
|
|
363
385
|
return Bash(
|
|
364
|
-
`ccw cli -p "${escapePrompt(prompt)}" --tool gemini --mode write --id exec-${solutionId}`,
|
|
386
|
+
`ccw cli -p "${escapePrompt(prompt)}" --tool gemini --mode write --id exec-${solutionId}${cdOption}`,
|
|
365
387
|
{ timeout: 3600000, run_in_background: true }
|
|
366
388
|
);
|
|
367
389
|
} else {
|
|
@@ -369,7 +391,7 @@ ${worktreeCleanup}`;
|
|
|
369
391
|
subagent_type: 'code-developer',
|
|
370
392
|
run_in_background: false,
|
|
371
393
|
description: `Execute solution ${solutionId}`,
|
|
372
|
-
prompt: prompt
|
|
394
|
+
prompt: worktreePath ? `Working directory: ${worktreePath}\n\n${prompt}` : prompt
|
|
373
395
|
});
|
|
374
396
|
}
|
|
375
397
|
}
|
|
@@ -378,8 +400,8 @@ ${worktreeCleanup}`;
|
|
|
378
400
|
### Phase 3: Check Next Batch
|
|
379
401
|
|
|
380
402
|
```javascript
|
|
381
|
-
// Refresh DAG after batch completes
|
|
382
|
-
const refreshedDag = JSON.parse(Bash(`ccw issue queue dag`).trim());
|
|
403
|
+
// Refresh DAG after batch completes (use same QUEUE_ID)
|
|
404
|
+
const refreshedDag = JSON.parse(Bash(`ccw issue queue dag --queue ${QUEUE_ID}`).trim());
|
|
383
405
|
|
|
384
406
|
console.log(`
|
|
385
407
|
## Batch Complete
|
|
@@ -389,46 +411,117 @@ console.log(`
|
|
|
389
411
|
`);
|
|
390
412
|
|
|
391
413
|
if (refreshedDag.ready_count > 0) {
|
|
392
|
-
console.log(
|
|
414
|
+
console.log(`Run \`/issue:execute --queue ${QUEUE_ID}\` again for next batch.`);
|
|
415
|
+
// Note: If resuming, pass existing worktree path:
|
|
416
|
+
// /issue:execute --queue ${QUEUE_ID} --worktree <worktreePath>
|
|
417
|
+
}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Phase 4: Worktree Completion (after ALL batches)
|
|
421
|
+
|
|
422
|
+
```javascript
|
|
423
|
+
// Only run when ALL solutions completed AND using worktree
|
|
424
|
+
if (useWorktree && refreshedDag.ready_count === 0 && refreshedDag.completed_count === refreshedDag.total) {
|
|
425
|
+
console.log('\n## All Solutions Completed - Worktree Cleanup');
|
|
426
|
+
|
|
427
|
+
const answer = AskUserQuestion({
|
|
428
|
+
questions: [{
|
|
429
|
+
question: `Queue complete. What to do with worktree branch "${worktreeBranch}"?`,
|
|
430
|
+
header: 'Merge',
|
|
431
|
+
multiSelect: false,
|
|
432
|
+
options: [
|
|
433
|
+
{ label: 'Create PR (Recommended)', description: 'Push branch and create pull request' },
|
|
434
|
+
{ label: 'Merge to main', description: 'Merge all commits and cleanup worktree' },
|
|
435
|
+
{ label: 'Keep branch', description: 'Cleanup worktree, keep branch for manual handling' }
|
|
436
|
+
]
|
|
437
|
+
}]
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
const repoRoot = Bash('git rev-parse --show-toplevel').trim();
|
|
441
|
+
|
|
442
|
+
if (answer['Merge'].includes('Create PR')) {
|
|
443
|
+
Bash(`git -C "${worktreePath}" push -u origin "${worktreeBranch}"`);
|
|
444
|
+
Bash(`gh pr create --title "Queue ${dag.queue_id}" --body "Issue queue execution - all solutions completed" --head "${worktreeBranch}"`);
|
|
445
|
+
Bash(`git worktree remove "${worktreePath}"`);
|
|
446
|
+
console.log(`PR created for branch: ${worktreeBranch}`);
|
|
447
|
+
} else if (answer['Merge'].includes('Merge to main')) {
|
|
448
|
+
// Check main is clean
|
|
449
|
+
const mainDirty = Bash('git status --porcelain').trim();
|
|
450
|
+
if (mainDirty) {
|
|
451
|
+
console.log('Warning: Main has uncommitted changes. Falling back to PR.');
|
|
452
|
+
Bash(`git -C "${worktreePath}" push -u origin "${worktreeBranch}"`);
|
|
453
|
+
Bash(`gh pr create --title "Queue ${dag.queue_id}" --body "Issue queue execution (main had uncommitted changes)" --head "${worktreeBranch}"`);
|
|
454
|
+
} else {
|
|
455
|
+
Bash(`git merge --no-ff "${worktreeBranch}" -m "Merge queue ${dag.queue_id}"`);
|
|
456
|
+
Bash(`git branch -d "${worktreeBranch}"`);
|
|
457
|
+
}
|
|
458
|
+
Bash(`git worktree remove "${worktreePath}"`);
|
|
459
|
+
} else {
|
|
460
|
+
Bash(`git worktree remove "${worktreePath}"`);
|
|
461
|
+
console.log(`Branch ${worktreeBranch} kept for manual handling`);
|
|
462
|
+
}
|
|
393
463
|
}
|
|
394
464
|
```
|
|
395
465
|
|
|
396
466
|
## Parallel Execution Model
|
|
397
467
|
|
|
398
468
|
```
|
|
399
|
-
|
|
400
|
-
│ Orchestrator
|
|
401
|
-
|
|
402
|
-
│
|
|
403
|
-
│
|
|
404
|
-
│
|
|
405
|
-
│
|
|
406
|
-
│
|
|
407
|
-
│
|
|
408
|
-
│
|
|
409
|
-
│
|
|
410
|
-
│
|
|
411
|
-
│ │
|
|
412
|
-
│ │
|
|
413
|
-
│
|
|
414
|
-
│
|
|
415
|
-
│
|
|
416
|
-
│ →
|
|
417
|
-
|
|
469
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
470
|
+
│ Orchestrator │
|
|
471
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
472
|
+
│ 0. Validate QUEUE_ID (required, or prompt user to select) │
|
|
473
|
+
│ │
|
|
474
|
+
│ 0.5 (if --worktree) Create ONE worktree for entire queue │
|
|
475
|
+
│ → .ccw/worktrees/queue-exec-<queue-id> │
|
|
476
|
+
│ │
|
|
477
|
+
│ 1. ccw issue queue dag --queue ${QUEUE_ID} │
|
|
478
|
+
│ → { parallel_batches: [["S-1","S-2"], ["S-3"]] } │
|
|
479
|
+
│ │
|
|
480
|
+
│ 2. Dispatch batch 1 (parallel, SAME worktree): │
|
|
481
|
+
│ ┌──────────────────────────────────────────────────────┐ │
|
|
482
|
+
│ │ Shared Queue Worktree (or main) │ │
|
|
483
|
+
│ │ ┌──────────────────┐ ┌──────────────────┐ │ │
|
|
484
|
+
│ │ │ Executor 1 │ │ Executor 2 │ │ │
|
|
485
|
+
│ │ │ detail S-1 │ │ detail S-2 │ │ │
|
|
486
|
+
│ │ │ [T1→T2→T3] │ │ [T1→T2] │ │ │
|
|
487
|
+
│ │ │ commit S-1 │ │ commit S-2 │ │ │
|
|
488
|
+
│ │ │ done S-1 │ │ done S-2 │ │ │
|
|
489
|
+
│ │ └──────────────────┘ └──────────────────┘ │ │
|
|
490
|
+
│ └──────────────────────────────────────────────────────┘ │
|
|
491
|
+
│ │
|
|
492
|
+
│ 3. ccw issue queue dag (refresh) │
|
|
493
|
+
│ → S-3 now ready → dispatch batch 2 (same worktree) │
|
|
494
|
+
│ │
|
|
495
|
+
│ 4. (if --worktree) ALL batches complete → cleanup worktree │
|
|
496
|
+
│ → Prompt: Create PR / Merge to main / Keep branch │
|
|
497
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
418
498
|
```
|
|
419
499
|
|
|
420
500
|
**Why this works for parallel:**
|
|
501
|
+
- **ONE worktree for entire queue** → all solutions share same isolated workspace
|
|
421
502
|
- `detail <id>` is READ-ONLY → no race conditions
|
|
422
503
|
- Each executor handles **all tasks within a solution** sequentially
|
|
423
504
|
- **One commit per solution** with formatted summary (not per-task)
|
|
424
505
|
- `done <id>` updates only its own solution status
|
|
425
506
|
- `queue dag` recalculates ready solutions after each batch
|
|
426
|
-
- Solutions in same batch have NO file conflicts
|
|
507
|
+
- Solutions in same batch have NO file conflicts (DAG guarantees)
|
|
508
|
+
- **Main workspace stays clean** until merge/PR decision
|
|
427
509
|
|
|
428
510
|
## CLI Endpoint Contract
|
|
429
511
|
|
|
430
|
-
### `ccw issue queue
|
|
431
|
-
Returns
|
|
512
|
+
### `ccw issue queue list --brief --json`
|
|
513
|
+
Returns queue index for selection (used when --queue not provided):
|
|
514
|
+
```json
|
|
515
|
+
{
|
|
516
|
+
"active_queue_id": "QUE-20251215-001",
|
|
517
|
+
"queues": [
|
|
518
|
+
{ "id": "QUE-20251215-001", "status": "active", "issue_ids": ["ISS-001"], "total_solutions": 5, "completed_solutions": 2 }
|
|
519
|
+
]
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### `ccw issue queue dag --queue <queue-id>`
|
|
524
|
+
Returns dependency graph with parallel batches (solution-level, **--queue required**):
|
|
432
525
|
```json
|
|
433
526
|
{
|
|
434
527
|
"queue_id": "QUE-...",
|
|
@@ -311,6 +311,12 @@ Output:
|
|
|
311
311
|
└─ .workflow/.debug/DBG-{slug}-{date}/debug.log
|
|
312
312
|
```
|
|
313
313
|
|
|
314
|
+
## Post-Completion Expansion
|
|
315
|
+
|
|
316
|
+
完成后询问用户是否扩展为issue(test/enhance/refactor/doc),选中项调用 `/issue:new "{summary} - {dimension}"`
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
314
320
|
## Error Handling
|
|
315
321
|
|
|
316
322
|
| Situation | Action |
|
|
@@ -275,6 +275,10 @@ AskUserQuestion({
|
|
|
275
275
|
- **"Enter Review"**: Execute `/workflow:review`
|
|
276
276
|
- **"Complete Session"**: Execute `/workflow:session:complete`
|
|
277
277
|
|
|
278
|
+
### Post-Completion Expansion
|
|
279
|
+
|
|
280
|
+
完成后询问用户是否扩展为issue(test/enhance/refactor/doc),选中项调用 `/issue:new "{summary} - {dimension}"`
|
|
281
|
+
|
|
278
282
|
## Execution Strategy (IMPL_PLAN-Driven)
|
|
279
283
|
|
|
280
284
|
### Strategy Priority
|
|
@@ -664,6 +664,10 @@ Collected after each execution call completes:
|
|
|
664
664
|
|
|
665
665
|
Appended to `previousExecutionResults` array for context continuity in multi-execution scenarios.
|
|
666
666
|
|
|
667
|
+
## Post-Completion Expansion
|
|
668
|
+
|
|
669
|
+
完成后询问用户是否扩展为issue(test/enhance/refactor/doc),选中项调用 `/issue:new "{summary} - {dimension}"`
|
|
670
|
+
|
|
667
671
|
**Fixed ID Pattern**: `${sessionId}-${groupId}` enables predictable lookup without auto-generated timestamps.
|
|
668
672
|
|
|
669
673
|
**Resume Usage**: If `status` is "partial" or "failed", use `fixedCliId` to resume:
|