claude-code-workflow 6.3.26 → 6.3.28
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 +141 -163
- package/.claude/commands/workflow/lite-lite-lite.md +798 -0
- package/.claude/commands/workflow/multi-cli-plan.md +510 -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/ccw/dist/core/auth/csrf-middleware.d.ts.map +1 -1
- package/ccw/dist/core/auth/csrf-middleware.js +3 -1
- package/ccw/dist/core/auth/csrf-middleware.js.map +1 -1
- 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 +295 -6
- package/ccw/dist/core/lite-scanner.js.map +1 -1
- package/ccw/dist/core/routes/codexlens/config-handlers.d.ts.map +1 -1
- package/ccw/dist/core/routes/codexlens/config-handlers.js +5 -5
- package/ccw/dist/core/routes/codexlens/config-handlers.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/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/auth/csrf-middleware.ts +3 -1
- package/ccw/src/core/data-aggregator.ts +7 -2
- package/ccw/src/core/lite-scanner.ts +440 -6
- package/ccw/src/core/routes/codexlens/config-handlers.ts +12 -9
- 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/04-lite-tasks.css +2442 -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 +38 -13
- package/ccw/src/templates/dashboard-js/components/navigation.js +24 -4
- package/ccw/src/templates/dashboard-js/i18n.js +194 -6
- 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 +1817 -4
- package/ccw/src/templates/dashboard.html +5 -0
- 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
|
@@ -17,21 +17,21 @@ 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
21
|
|
|
22
22
|
## Usage
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
25
|
/issue:execute # Execute active queue(s)
|
|
26
26
|
/issue:execute --queue QUE-xxx # Execute specific queue
|
|
27
|
-
/issue:execute --worktree #
|
|
27
|
+
/issue:execute --worktree # Execute entire queue in isolated worktree
|
|
28
28
|
/issue:execute --worktree --queue QUE-xxx
|
|
29
29
|
/issue:execute --worktree /path/to/existing/worktree # Resume in existing worktree
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
**Parallelism**: Determined automatically by task dependency DAG (no manual control)
|
|
33
33
|
**Executor & Dry-run**: Selected via interactive prompt (AskUserQuestion)
|
|
34
|
-
**Worktree**: Creates
|
|
34
|
+
**Worktree**: Creates ONE worktree for the entire queue execution (not per-solution)
|
|
35
35
|
|
|
36
36
|
**⭐ Recommended Executor**: **Codex** - Best for long-running autonomous work (2hr timeout), supports background execution and full write access
|
|
37
37
|
|
|
@@ -44,8 +44,10 @@ Minimal orchestrator that dispatches **solution IDs** to executors. Each executo
|
|
|
44
44
|
## Execution Flow
|
|
45
45
|
|
|
46
46
|
```
|
|
47
|
-
Phase 0 (if --worktree): Setup Worktree
|
|
48
|
-
|
|
47
|
+
Phase 0 (if --worktree): Setup Queue Worktree
|
|
48
|
+
├─ Create ONE worktree for entire queue: .ccw/worktrees/queue-<timestamp>
|
|
49
|
+
├─ All subsequent execution happens in this worktree
|
|
50
|
+
└─ Main workspace remains clean and untouched
|
|
49
51
|
|
|
50
52
|
Phase 1: Get DAG & User Selection
|
|
51
53
|
├─ ccw issue queue dag [--queue QUE-xxx] → { parallel_batches: [["S-1","S-2"], ["S-3"]] }
|
|
@@ -53,19 +55,22 @@ Phase 1: Get DAG & User Selection
|
|
|
53
55
|
|
|
54
56
|
Phase 2: Dispatch Parallel Batch (DAG-driven)
|
|
55
57
|
├─ Parallelism determined by DAG (no manual limit)
|
|
58
|
+
├─ All executors work in the SAME worktree (or main if no worktree)
|
|
56
59
|
├─ For each solution ID in batch (parallel - all at once):
|
|
57
|
-
│ ├─ (if worktree) Create isolated worktree: git worktree add
|
|
58
60
|
│ ├─ Executor calls: ccw issue detail <id> (READ-ONLY)
|
|
59
61
|
│ ├─ Executor gets FULL SOLUTION with all tasks
|
|
60
62
|
│ ├─ Executor implements all tasks sequentially (T1 → T2 → T3)
|
|
61
63
|
│ ├─ Executor tests + verifies each task
|
|
62
64
|
│ ├─ Executor commits ONCE per solution (with formatted summary)
|
|
63
|
-
│
|
|
64
|
-
│ └─ (if worktree) Cleanup: merge branch, remove worktree
|
|
65
|
+
│ └─ Executor calls: ccw issue done <id>
|
|
65
66
|
└─ Wait for batch completion
|
|
66
67
|
|
|
67
|
-
Phase 3: Next Batch
|
|
68
|
+
Phase 3: Next Batch (repeat Phase 2)
|
|
68
69
|
└─ ccw issue queue dag → check for newly-ready solutions
|
|
70
|
+
|
|
71
|
+
Phase 4 (if --worktree): Worktree Completion
|
|
72
|
+
├─ All batches complete → prompt for merge strategy
|
|
73
|
+
└─ Options: Create PR / Merge to main / Keep branch
|
|
69
74
|
```
|
|
70
75
|
|
|
71
76
|
## Implementation
|
|
@@ -115,12 +120,12 @@ const answer = AskUserQuestion({
|
|
|
115
120
|
]
|
|
116
121
|
},
|
|
117
122
|
{
|
|
118
|
-
question: 'Use git
|
|
123
|
+
question: 'Use git worktree for queue isolation?',
|
|
119
124
|
header: 'Worktree',
|
|
120
125
|
multiSelect: false,
|
|
121
126
|
options: [
|
|
122
|
-
{ label: 'Yes (Recommended
|
|
123
|
-
{ label: 'No', description: 'Work directly in current directory
|
|
127
|
+
{ label: 'Yes (Recommended)', description: 'Create ONE worktree for entire queue - main stays clean' },
|
|
128
|
+
{ label: 'No', description: 'Work directly in current directory' }
|
|
124
129
|
]
|
|
125
130
|
}
|
|
126
131
|
]
|
|
@@ -140,7 +145,7 @@ if (isDryRun) {
|
|
|
140
145
|
}
|
|
141
146
|
```
|
|
142
147
|
|
|
143
|
-
### Phase 2:
|
|
148
|
+
### Phase 0 & 2: Setup Queue Worktree & Dispatch
|
|
144
149
|
|
|
145
150
|
```javascript
|
|
146
151
|
// Parallelism determined by DAG - no manual limit
|
|
@@ -158,24 +163,40 @@ TodoWrite({
|
|
|
158
163
|
|
|
159
164
|
console.log(`\n### Executing Solutions (DAG batch 1): ${batch.join(', ')}`);
|
|
160
165
|
|
|
161
|
-
//
|
|
166
|
+
// Parse existing worktree path from args if provided
|
|
167
|
+
// Example: --worktree /path/to/existing/worktree
|
|
168
|
+
const existingWorktree = args.worktree && typeof args.worktree === 'string' ? args.worktree : null;
|
|
169
|
+
|
|
170
|
+
// Setup ONE worktree for entire queue (not per-solution)
|
|
171
|
+
let worktreePath = null;
|
|
172
|
+
let worktreeBranch = null;
|
|
173
|
+
|
|
162
174
|
if (useWorktree) {
|
|
163
|
-
// Use absolute paths to avoid issues when running from subdirectories
|
|
164
175
|
const repoRoot = Bash('git rev-parse --show-toplevel').trim();
|
|
165
176
|
const worktreeBase = `${repoRoot}/.ccw/worktrees`;
|
|
166
177
|
Bash(`mkdir -p "${worktreeBase}"`);
|
|
167
|
-
//
|
|
168
|
-
Bash('git worktree prune');
|
|
169
|
-
}
|
|
178
|
+
Bash('git worktree prune'); // Cleanup stale worktrees
|
|
170
179
|
|
|
171
|
-
|
|
172
|
-
//
|
|
173
|
-
|
|
180
|
+
if (existingWorktree) {
|
|
181
|
+
// Resume mode: Use existing worktree
|
|
182
|
+
worktreePath = existingWorktree;
|
|
183
|
+
worktreeBranch = Bash(`git -C "${worktreePath}" branch --show-current`).trim();
|
|
184
|
+
console.log(`Resuming in existing worktree: ${worktreePath} (branch: ${worktreeBranch})`);
|
|
185
|
+
} else {
|
|
186
|
+
// Create mode: ONE worktree for the entire queue
|
|
187
|
+
const timestamp = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 14);
|
|
188
|
+
worktreeBranch = `queue-exec-${dag.queue_id || timestamp}`;
|
|
189
|
+
worktreePath = `${worktreeBase}/${worktreeBranch}`;
|
|
190
|
+
Bash(`git worktree add "${worktreePath}" -b "${worktreeBranch}"`);
|
|
191
|
+
console.log(`Created queue worktree: ${worktreePath}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
174
194
|
|
|
175
195
|
// Launch ALL solutions in batch in parallel (DAG guarantees no conflicts)
|
|
196
|
+
// All executors work in the SAME worktree (or main if no worktree)
|
|
176
197
|
const executions = batch.map(solutionId => {
|
|
177
198
|
updateTodo(solutionId, 'in_progress');
|
|
178
|
-
return dispatchExecutor(solutionId, executor,
|
|
199
|
+
return dispatchExecutor(solutionId, executor, worktreePath);
|
|
179
200
|
});
|
|
180
201
|
|
|
181
202
|
await Promise.all(executions);
|
|
@@ -185,126 +206,20 @@ batch.forEach(id => updateTodo(id, 'completed'));
|
|
|
185
206
|
### Executor Dispatch
|
|
186
207
|
|
|
187
208
|
```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
|
-
` : '';
|
|
209
|
+
// worktreePath: path to shared worktree (null if not using worktree)
|
|
210
|
+
function dispatchExecutor(solutionId, executorType, worktreePath = null) {
|
|
211
|
+
// If worktree is provided, executor works in that directory
|
|
212
|
+
// No per-solution worktree creation - ONE worktree for entire queue
|
|
213
|
+
const cdCommand = worktreePath ? `cd "${worktreePath}"` : '';
|
|
304
214
|
|
|
305
215
|
const prompt = `
|
|
306
216
|
## Execute Solution ${solutionId}
|
|
307
|
-
${
|
|
217
|
+
${worktreePath ? `
|
|
218
|
+
### Step 0: Enter Queue Worktree
|
|
219
|
+
\`\`\`bash
|
|
220
|
+
cd "${worktreePath}"
|
|
221
|
+
\`\`\`
|
|
222
|
+
` : ''}
|
|
308
223
|
### Step 1: Get Solution (read-only)
|
|
309
224
|
\`\`\`bash
|
|
310
225
|
ccw issue detail ${solutionId}
|
|
@@ -352,16 +267,21 @@ If any task failed:
|
|
|
352
267
|
\`\`\`bash
|
|
353
268
|
ccw issue done ${solutionId} --fail --reason '{"task_id": "TX", "error_type": "test_failure", "message": "..."}'
|
|
354
269
|
\`\`\`
|
|
355
|
-
|
|
270
|
+
|
|
271
|
+
**Note**: Do NOT cleanup worktree after this solution. Worktree is shared by all solutions in the queue.
|
|
272
|
+
`;
|
|
273
|
+
|
|
274
|
+
// For CLI tools, pass --cd to set working directory
|
|
275
|
+
const cdOption = worktreePath ? ` --cd "${worktreePath}"` : '';
|
|
356
276
|
|
|
357
277
|
if (executorType === 'codex') {
|
|
358
278
|
return Bash(
|
|
359
|
-
`ccw cli -p "${escapePrompt(prompt)}" --tool codex --mode write --id exec-${solutionId}`,
|
|
279
|
+
`ccw cli -p "${escapePrompt(prompt)}" --tool codex --mode write --id exec-${solutionId}${cdOption}`,
|
|
360
280
|
{ timeout: 7200000, run_in_background: true } // 2hr for full solution
|
|
361
281
|
);
|
|
362
282
|
} else if (executorType === 'gemini') {
|
|
363
283
|
return Bash(
|
|
364
|
-
`ccw cli -p "${escapePrompt(prompt)}" --tool gemini --mode write --id exec-${solutionId}`,
|
|
284
|
+
`ccw cli -p "${escapePrompt(prompt)}" --tool gemini --mode write --id exec-${solutionId}${cdOption}`,
|
|
365
285
|
{ timeout: 3600000, run_in_background: true }
|
|
366
286
|
);
|
|
367
287
|
} else {
|
|
@@ -369,7 +289,7 @@ ${worktreeCleanup}`;
|
|
|
369
289
|
subagent_type: 'code-developer',
|
|
370
290
|
run_in_background: false,
|
|
371
291
|
description: `Execute solution ${solutionId}`,
|
|
372
|
-
prompt: prompt
|
|
292
|
+
prompt: worktreePath ? `Working directory: ${worktreePath}\n\n${prompt}` : prompt
|
|
373
293
|
});
|
|
374
294
|
}
|
|
375
295
|
}
|
|
@@ -390,40 +310,98 @@ console.log(`
|
|
|
390
310
|
|
|
391
311
|
if (refreshedDag.ready_count > 0) {
|
|
392
312
|
console.log('Run `/issue:execute` again for next batch.');
|
|
313
|
+
// Note: If resuming, pass existing worktree path:
|
|
314
|
+
// /issue:execute --worktree <worktreePath>
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Phase 4: Worktree Completion (after ALL batches)
|
|
319
|
+
|
|
320
|
+
```javascript
|
|
321
|
+
// Only run when ALL solutions completed AND using worktree
|
|
322
|
+
if (useWorktree && refreshedDag.ready_count === 0 && refreshedDag.completed_count === refreshedDag.total) {
|
|
323
|
+
console.log('\n## All Solutions Completed - Worktree Cleanup');
|
|
324
|
+
|
|
325
|
+
const answer = AskUserQuestion({
|
|
326
|
+
questions: [{
|
|
327
|
+
question: `Queue complete. What to do with worktree branch "${worktreeBranch}"?`,
|
|
328
|
+
header: 'Merge',
|
|
329
|
+
multiSelect: false,
|
|
330
|
+
options: [
|
|
331
|
+
{ label: 'Create PR (Recommended)', description: 'Push branch and create pull request' },
|
|
332
|
+
{ label: 'Merge to main', description: 'Merge all commits and cleanup worktree' },
|
|
333
|
+
{ label: 'Keep branch', description: 'Cleanup worktree, keep branch for manual handling' }
|
|
334
|
+
]
|
|
335
|
+
}]
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
const repoRoot = Bash('git rev-parse --show-toplevel').trim();
|
|
339
|
+
|
|
340
|
+
if (answer['Merge'].includes('Create PR')) {
|
|
341
|
+
Bash(`git -C "${worktreePath}" push -u origin "${worktreeBranch}"`);
|
|
342
|
+
Bash(`gh pr create --title "Queue ${dag.queue_id}" --body "Issue queue execution - all solutions completed" --head "${worktreeBranch}"`);
|
|
343
|
+
Bash(`git worktree remove "${worktreePath}"`);
|
|
344
|
+
console.log(`PR created for branch: ${worktreeBranch}`);
|
|
345
|
+
} else if (answer['Merge'].includes('Merge to main')) {
|
|
346
|
+
// Check main is clean
|
|
347
|
+
const mainDirty = Bash('git status --porcelain').trim();
|
|
348
|
+
if (mainDirty) {
|
|
349
|
+
console.log('Warning: Main has uncommitted changes. Falling back to PR.');
|
|
350
|
+
Bash(`git -C "${worktreePath}" push -u origin "${worktreeBranch}"`);
|
|
351
|
+
Bash(`gh pr create --title "Queue ${dag.queue_id}" --body "Issue queue execution (main had uncommitted changes)" --head "${worktreeBranch}"`);
|
|
352
|
+
} else {
|
|
353
|
+
Bash(`git merge --no-ff "${worktreeBranch}" -m "Merge queue ${dag.queue_id}"`);
|
|
354
|
+
Bash(`git branch -d "${worktreeBranch}"`);
|
|
355
|
+
}
|
|
356
|
+
Bash(`git worktree remove "${worktreePath}"`);
|
|
357
|
+
} else {
|
|
358
|
+
Bash(`git worktree remove "${worktreePath}"`);
|
|
359
|
+
console.log(`Branch ${worktreeBranch} kept for manual handling`);
|
|
360
|
+
}
|
|
393
361
|
}
|
|
394
362
|
```
|
|
395
363
|
|
|
396
364
|
## Parallel Execution Model
|
|
397
365
|
|
|
398
366
|
```
|
|
399
|
-
|
|
400
|
-
│ Orchestrator
|
|
401
|
-
|
|
402
|
-
│
|
|
403
|
-
│ →
|
|
404
|
-
│
|
|
405
|
-
│
|
|
406
|
-
│
|
|
407
|
-
│
|
|
408
|
-
│
|
|
409
|
-
│ │
|
|
410
|
-
│ │
|
|
411
|
-
│ │
|
|
412
|
-
│ │
|
|
413
|
-
│
|
|
414
|
-
│
|
|
415
|
-
│
|
|
416
|
-
│
|
|
417
|
-
|
|
367
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
368
|
+
│ Orchestrator │
|
|
369
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
370
|
+
│ 0. (if --worktree) Create ONE worktree for entire queue │
|
|
371
|
+
│ → .ccw/worktrees/queue-exec-<queue-id> │
|
|
372
|
+
│ │
|
|
373
|
+
│ 1. ccw issue queue dag │
|
|
374
|
+
│ → { parallel_batches: [["S-1","S-2"], ["S-3"]] } │
|
|
375
|
+
│ │
|
|
376
|
+
│ 2. Dispatch batch 1 (parallel, SAME worktree): │
|
|
377
|
+
│ ┌──────────────────────────────────────────────────────┐ │
|
|
378
|
+
│ │ Shared Queue Worktree (or main) │ │
|
|
379
|
+
│ │ ┌──────────────────┐ ┌──────────────────┐ │ │
|
|
380
|
+
│ │ │ Executor 1 │ │ Executor 2 │ │ │
|
|
381
|
+
│ │ │ detail S-1 │ │ detail S-2 │ │ │
|
|
382
|
+
│ │ │ [T1→T2→T3] │ │ [T1→T2] │ │ │
|
|
383
|
+
│ │ │ commit S-1 │ │ commit S-2 │ │ │
|
|
384
|
+
│ │ │ done S-1 │ │ done S-2 │ │ │
|
|
385
|
+
│ │ └──────────────────┘ └──────────────────┘ │ │
|
|
386
|
+
│ └──────────────────────────────────────────────────────┘ │
|
|
387
|
+
│ │
|
|
388
|
+
│ 3. ccw issue queue dag (refresh) │
|
|
389
|
+
│ → S-3 now ready → dispatch batch 2 (same worktree) │
|
|
390
|
+
│ │
|
|
391
|
+
│ 4. (if --worktree) ALL batches complete → cleanup worktree │
|
|
392
|
+
│ → Prompt: Create PR / Merge to main / Keep branch │
|
|
393
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
418
394
|
```
|
|
419
395
|
|
|
420
396
|
**Why this works for parallel:**
|
|
397
|
+
- **ONE worktree for entire queue** → all solutions share same isolated workspace
|
|
421
398
|
- `detail <id>` is READ-ONLY → no race conditions
|
|
422
399
|
- Each executor handles **all tasks within a solution** sequentially
|
|
423
400
|
- **One commit per solution** with formatted summary (not per-task)
|
|
424
401
|
- `done <id>` updates only its own solution status
|
|
425
402
|
- `queue dag` recalculates ready solutions after each batch
|
|
426
|
-
- Solutions in same batch have NO file conflicts
|
|
403
|
+
- Solutions in same batch have NO file conflicts (DAG guarantees)
|
|
404
|
+
- **Main workspace stays clean** until merge/PR decision
|
|
427
405
|
|
|
428
406
|
## CLI Endpoint Contract
|
|
429
407
|
|