claude-code-workflow 7.2.11 → 7.2.12

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.
Files changed (29) hide show
  1. package/.claude/commands/workflow/analyze-with-file.md +108 -54
  2. package/.claude/commands/workflow-tune.md +811 -0
  3. package/.claude/skills/workflow-lite-execute/SKILL.md +106 -14
  4. package/.claude/skills/workflow-lite-plan/SKILL.md +34 -72
  5. package/.claude/skills/workflow-lite-test-review/SKILL.md +39 -26
  6. package/package.json +1 -1
  7. package/.claude/commands/ddd/auto.md +0 -359
  8. package/.claude/commands/ddd/doc-generate.md +0 -222
  9. package/.claude/commands/ddd/doc-refresh.md +0 -218
  10. package/.claude/commands/ddd/execute.md +0 -416
  11. package/.claude/commands/ddd/index-build.md +0 -212
  12. package/.claude/commands/ddd/plan.md +0 -611
  13. package/.claude/commands/ddd/scan.md +0 -365
  14. package/.claude/commands/ddd/sync.md +0 -353
  15. package/.claude/commands/ddd/update.md +0 -160
  16. package/.claude/commands/idaw/add.md +0 -287
  17. package/.claude/commands/idaw/resume.md +0 -442
  18. package/.claude/commands/idaw/run-coordinate.md +0 -648
  19. package/.claude/commands/idaw/run.md +0 -539
  20. package/.claude/commands/idaw/status.md +0 -182
  21. package/.claude/skills/workflow-tune/SKILL.md +0 -487
  22. package/.claude/skills/workflow-tune/phases/01-setup.md +0 -548
  23. package/.claude/skills/workflow-tune/phases/02-step-execute.md +0 -197
  24. package/.claude/skills/workflow-tune/phases/03-step-analyze.md +0 -386
  25. package/.claude/skills/workflow-tune/phases/04-synthesize.md +0 -257
  26. package/.claude/skills/workflow-tune/phases/05-optimize-report.md +0 -246
  27. package/.claude/skills/workflow-tune/specs/workflow-eval-criteria.md +0 -57
  28. package/.claude/skills/workflow-tune/templates/step-analysis-prompt.md +0 -88
  29. package/.claude/skills/workflow-tune/templates/synthesis-prompt.md +0 -90
@@ -1,648 +0,0 @@
1
- ---
2
- name: run-coordinate
3
- description: IDAW coordinator - execute task skill chains via external CLI with hook callbacks and git checkpoints
4
- argument-hint: "[-y|--yes] [--task <id>[,<id>,...]] [--dry-run] [--tool <tool>]"
5
- allowed-tools: Agent(*), AskUserQuestion(*), Read(*), Write(*), Bash(*), Glob(*), Grep(*)
6
- ---
7
-
8
- # IDAW Run Coordinate Command (/idaw:run-coordinate)
9
-
10
- Coordinator variant of `/idaw:run`: external CLI execution with background tasks and hook callbacks.
11
-
12
- **Execution Model**: `ccw cli -p "..." --tool <tool> --mode write` in background → hook callback → next step.
13
-
14
- **vs `/idaw:run`**: Direct `Skill()` calls (blocking, main process) vs `ccw cli` (background, external process).
15
-
16
- ## When to Use
17
-
18
- | Scenario | Use |
19
- |----------|-----|
20
- | Standard IDAW execution (main process) | `/idaw:run` |
21
- | External CLI execution (background, hook-driven) | `/idaw:run-coordinate` |
22
- | Need `claude` or `gemini` as execution tool | `/idaw:run-coordinate --tool claude` |
23
- | Long-running tasks, avoid context window pressure | `/idaw:run-coordinate` |
24
-
25
- ## Skill Chain Mapping
26
-
27
- ```javascript
28
- const SKILL_CHAIN_MAP = {
29
- 'bugfix': ['workflow-lite-plan', 'workflow-test-fix'],
30
- 'bugfix-hotfix': ['workflow-lite-plan'],
31
- 'feature': ['workflow-lite-plan', 'workflow-test-fix'],
32
- 'feature-complex': ['workflow-plan', 'workflow-execute', 'workflow-test-fix'],
33
- 'refactor': ['workflow:refactor-cycle'],
34
- 'tdd': ['workflow-tdd-plan', 'workflow-execute'],
35
- 'test': ['workflow-test-fix'],
36
- 'test-fix': ['workflow-test-fix'],
37
- 'review': ['review-cycle'],
38
- 'docs': ['workflow-lite-plan']
39
- };
40
- ```
41
-
42
- ## Task Type Inference
43
-
44
- ```javascript
45
- function inferTaskType(title, description) {
46
- const text = `${title} ${description}`.toLowerCase();
47
- if (/urgent|production|critical/.test(text) && /fix|bug/.test(text)) return 'bugfix-hotfix';
48
- if (/refactor|重构|tech.*debt/.test(text)) return 'refactor';
49
- if (/tdd|test-driven|test first/.test(text)) return 'tdd';
50
- if (/test fail|fix test|failing test/.test(text)) return 'test-fix';
51
- if (/generate test|写测试|add test/.test(text)) return 'test';
52
- if (/review|code review/.test(text)) return 'review';
53
- if (/docs|documentation|readme/.test(text)) return 'docs';
54
- if (/fix|bug|error|crash|fail/.test(text)) return 'bugfix';
55
- if (/complex|multi-module|architecture/.test(text)) return 'feature-complex';
56
- return 'feature';
57
- }
58
- ```
59
-
60
- ## 6-Phase Execution (Coordinator Model)
61
-
62
- ### Phase 1: Load Tasks
63
-
64
- ```javascript
65
- const args = $ARGUMENTS;
66
- const autoYes = /(-y|--yes)/.test(args);
67
- const dryRun = /--dry-run/.test(args);
68
- const taskFilter = args.match(/--task\s+([\w,-]+)/)?.[1]?.split(',') || null;
69
- const cliTool = args.match(/--tool\s+(\w+)/)?.[1] || 'claude';
70
-
71
- // Load task files
72
- const taskFiles = Glob('.workflow/.idaw/tasks/IDAW-*.json') || [];
73
-
74
- if (taskFiles.length === 0) {
75
- console.log('No IDAW tasks found. Use /idaw:add to create tasks.');
76
- return;
77
- }
78
-
79
- // Parse and filter
80
- let tasks = taskFiles.map(f => JSON.parse(Read(f)));
81
-
82
- if (taskFilter) {
83
- tasks = tasks.filter(t => taskFilter.includes(t.id));
84
- } else {
85
- tasks = tasks.filter(t => t.status === 'pending');
86
- }
87
-
88
- if (tasks.length === 0) {
89
- console.log('No pending tasks to execute. Use /idaw:add to add tasks or --task to specify IDs.');
90
- return;
91
- }
92
-
93
- // Sort: priority ASC (1=critical first), then ID ASC
94
- tasks.sort((a, b) => {
95
- if (a.priority !== b.priority) return a.priority - b.priority;
96
- return a.id.localeCompare(b.id);
97
- });
98
- ```
99
-
100
- ### Phase 2: Session Setup
101
-
102
- ```javascript
103
- // Generate session ID: IDA-{slug}-YYYYMMDD
104
- const slug = tasks[0].title
105
- .toLowerCase()
106
- .replace(/[^a-z0-9]+/g, '-')
107
- .substring(0, 20)
108
- .replace(/-$/, '');
109
- const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, '');
110
- let sessionId = `IDA-${slug}-${dateStr}`;
111
-
112
- // Check collision
113
- const existingSession = Glob(`.workflow/.idaw/sessions/${sessionId}/session.json`);
114
- if (existingSession?.length > 0) {
115
- sessionId = `${sessionId}-2`;
116
- }
117
-
118
- const sessionDir = `.workflow/.idaw/sessions/${sessionId}`;
119
- Bash(`mkdir -p "${sessionDir}"`);
120
-
121
- const session = {
122
- session_id: sessionId,
123
- mode: 'coordinate', // ★ Marks this as coordinator-mode session
124
- cli_tool: cliTool,
125
- status: 'running',
126
- created_at: new Date().toISOString(),
127
- updated_at: new Date().toISOString(),
128
- tasks: tasks.map(t => t.id),
129
- current_task: null,
130
- current_skill_index: 0,
131
- completed: [],
132
- failed: [],
133
- skipped: [],
134
- prompts_used: []
135
- };
136
-
137
- Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
138
-
139
- // Initialize progress.md
140
- const progressHeader = `# IDAW Progress — ${sessionId} (coordinate mode)\nStarted: ${session.created_at}\nCLI Tool: ${cliTool}\n\n`;
141
- Write(`${sessionDir}/progress.md`, progressHeader);
142
- ```
143
-
144
- ### Phase 3: Startup Protocol
145
-
146
- ```javascript
147
- // Check for existing running sessions
148
- const runningSessions = Glob('.workflow/.idaw/sessions/IDA-*/session.json')
149
- ?.map(f => { try { return JSON.parse(Read(f)); } catch { return null; } })
150
- .filter(s => s && s.status === 'running' && s.session_id !== sessionId) || [];
151
-
152
- if (runningSessions.length > 0 && !autoYes) {
153
- const answer = AskUserQuestion({
154
- questions: [{
155
- question: `Found running session: ${runningSessions[0].session_id}. How to proceed?`,
156
- header: 'Conflict',
157
- multiSelect: false,
158
- options: [
159
- { label: 'Resume existing', description: 'Use /idaw:resume instead' },
160
- { label: 'Start fresh', description: 'Continue with new session' },
161
- { label: 'Abort', description: 'Cancel this run' }
162
- ]
163
- }]
164
- });
165
- if (answer.answers?.Conflict === 'Resume existing') {
166
- console.log(`Use: /idaw:resume ${runningSessions[0].session_id}`);
167
- return;
168
- }
169
- if (answer.answers?.Conflict === 'Abort') return;
170
- }
171
-
172
- // Check git status
173
- const gitStatus = Bash('git status --porcelain 2>/dev/null');
174
- if (gitStatus?.trim() && !autoYes) {
175
- const answer = AskUserQuestion({
176
- questions: [{
177
- question: 'Working tree has uncommitted changes. How to proceed?',
178
- header: 'Git',
179
- multiSelect: false,
180
- options: [
181
- { label: 'Continue', description: 'Proceed with dirty tree' },
182
- { label: 'Stash', description: 'git stash before running' },
183
- { label: 'Abort', description: 'Stop and handle manually' }
184
- ]
185
- }]
186
- });
187
- if (answer.answers?.Git === 'Stash') Bash('git stash push -m "idaw-pre-run"');
188
- if (answer.answers?.Git === 'Abort') return;
189
- }
190
-
191
- // Dry run
192
- if (dryRun) {
193
- console.log(`# Dry Run — ${sessionId} (coordinate mode, tool: ${cliTool})\n`);
194
- for (const task of tasks) {
195
- const taskType = task.task_type || inferTaskType(task.title, task.description);
196
- const chain = task.skill_chain || SKILL_CHAIN_MAP[taskType] || SKILL_CHAIN_MAP['feature'];
197
- console.log(`## ${task.id}: ${task.title}`);
198
- console.log(` Type: ${taskType} | Priority: ${task.priority}`);
199
- console.log(` Chain: ${chain.join(' → ')}`);
200
- console.log(` CLI: ccw cli --tool ${cliTool} --mode write\n`);
201
- }
202
- console.log(`Total: ${tasks.length} tasks`);
203
- return;
204
- }
205
- ```
206
-
207
- ### Phase 4: Launch First Task (then wait for hook)
208
-
209
- ```javascript
210
- // Start with the first task, first skill
211
- const firstTask = tasks[0];
212
- const resolvedType = firstTask.task_type || inferTaskType(firstTask.title, firstTask.description);
213
- const chain = firstTask.skill_chain || SKILL_CHAIN_MAP[resolvedType] || SKILL_CHAIN_MAP['feature'];
214
-
215
- // Update task → in_progress
216
- firstTask.status = 'in_progress';
217
- firstTask.task_type = resolvedType;
218
- firstTask.execution.started_at = new Date().toISOString();
219
- Write(`.workflow/.idaw/tasks/${firstTask.id}.json`, JSON.stringify(firstAgent, null, 2));
220
-
221
- // Update session
222
- session.current_task = firstTask.id;
223
- session.current_skill_index = 0;
224
- session.updated_at = new Date().toISOString();
225
- Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
226
-
227
- // ━━━ Pre-Task CLI Context Analysis (for complex/bugfix tasks) ━━━
228
- if (['bugfix', 'bugfix-hotfix', 'feature-complex'].includes(resolvedType)) {
229
- console.log(`Pre-analysis: gathering context for ${resolvedType} task...`);
230
- const affectedFiles = (firstTask.context?.affected_files || []).join(', ');
231
- const preAnalysisPrompt = `PURPOSE: Pre-analyze codebase context for IDAW task.
232
- TASK: • Understand current state of: ${affectedFiles || 'files related to: ' + firstTask.title} • Identify dependencies and risk areas
233
- MODE: analysis
234
- CONTEXT: @**/*
235
- EXPECTED: Brief context summary in 3-5 bullet points
236
- CONSTRAINTS: Keep concise`;
237
- Bash(`ccw cli -p '${preAnalysisPrompt.replace(/'/g, "'\\''")}' --tool gemini --mode analysis 2>&1 || echo "Pre-analysis skipped"`);
238
- }
239
-
240
- // Assemble prompt for first skill
241
- const skillName = chain[0];
242
- const prompt = assembleCliPrompt(skillName, firstAgent, null, autoYes);
243
-
244
- session.prompts_used.push({
245
- task_id: firstTask.id,
246
- skill_index: 0,
247
- skill: skillName,
248
- prompt: prompt,
249
- timestamp: new Date().toISOString()
250
- });
251
- session.updated_at = new Date().toISOString();
252
- Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
253
-
254
- // Launch via ccw cli in background
255
- console.log(`[1/${tasks.length}] ${firstTask.id}: ${firstTask.title}`);
256
- console.log(` Chain: ${chain.join(' → ')}`);
257
- console.log(` Launching: ${skillName} via ccw cli --tool ${cliTool}`);
258
-
259
- Bash(
260
- `ccw cli -p "${escapeForShell(prompt)}" --tool ${cliTool} --mode write`,
261
- { run_in_background: true }
262
- );
263
-
264
- // ★ STOP HERE — wait for hook callback
265
- // Hook callback will trigger handleStepCompletion() below
266
- ```
267
-
268
- ### Phase 5: Hook Callback Handler (per-step completion)
269
-
270
- ```javascript
271
- // Called by hook when background CLI completes
272
- async function handleStepCompletion(sessionId, cliOutput) {
273
- const sessionDir = `.workflow/.idaw/sessions/${sessionId}`;
274
- const session = JSON.parse(Read(`${sessionDir}/session.json`));
275
-
276
- const taskId = session.current_task;
277
- const task = JSON.parse(Read(`.workflow/.idaw/tasks/${taskId}.json`));
278
-
279
- const resolvedType = task.task_type || inferTaskType(task.title, task.description);
280
- const chain = task.skill_chain || SKILL_CHAIN_MAP[resolvedType] || SKILL_CHAIN_MAP['feature'];
281
- const skillIdx = session.current_skill_index;
282
- const skillName = chain[skillIdx];
283
-
284
- // Parse CLI output for session ID
285
- const parsedOutput = parseCliOutput(cliOutput);
286
-
287
- // Record skill result
288
- task.execution.skill_results.push({
289
- skill: skillName,
290
- status: parsedOutput.success ? 'completed' : 'failed',
291
- session_id: parsedOutput.sessionId,
292
- timestamp: new Date().toISOString()
293
- });
294
-
295
- // ━━━ Handle failure with CLI diagnosis ━━━
296
- if (!parsedOutput.success) {
297
- console.log(` ${skillName} failed. Running CLI diagnosis...`);
298
- const diagnosisPrompt = `PURPOSE: Diagnose why skill "${skillName}" failed during IDAW task.
299
- TASK: • Analyze error output • Check affected files: ${(task.context?.affected_files || []).join(', ') || 'unknown'}
300
- MODE: analysis
301
- CONTEXT: @**/* | Memory: IDAW task ${task.id}: ${task.title}
302
- EXPECTED: Root cause + fix recommendation
303
- CONSTRAINTS: Actionable diagnosis`;
304
- Bash(`ccw cli -p '${diagnosisPrompt.replace(/'/g, "'\\''")}' --tool gemini --mode analysis --rule analysis-diagnose-bug-root-cause 2>&1 || true`);
305
-
306
- task.execution.skill_results.push({
307
- skill: `cli-diagnosis:${skillName}`,
308
- status: 'completed',
309
- timestamp: new Date().toISOString()
310
- });
311
-
312
- // Retry once
313
- console.log(` Retrying: ${skillName}`);
314
- const retryPrompt = assembleCliPrompt(skillName, task, parsedOutput, true);
315
- session.prompts_used.push({
316
- task_id: taskId,
317
- skill_index: skillIdx,
318
- skill: `${skillName}-retry`,
319
- prompt: retryPrompt,
320
- timestamp: new Date().toISOString()
321
- });
322
- Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
323
- Write(`.workflow/.idaw/tasks/${taskId}.json`, JSON.stringify(task, null, 2));
324
-
325
- Bash(
326
- `ccw cli -p "${escapeForShell(retryPrompt)}" --tool ${session.cli_tool} --mode write`,
327
- { run_in_background: true }
328
- );
329
- return; // Wait for retry hook
330
- }
331
-
332
- // ━━━ Skill succeeded — advance ━━━
333
- const nextSkillIdx = skillIdx + 1;
334
-
335
- if (nextSkillIdx < chain.length) {
336
- // More skills in this task's chain → launch next skill
337
- session.current_skill_index = nextSkillIdx;
338
- session.updated_at = new Date().toISOString();
339
-
340
- const nextSkill = chain[nextSkillIdx];
341
- const nextPrompt = assembleCliPrompt(nextSkill, task, parsedOutput, true);
342
-
343
- session.prompts_used.push({
344
- task_id: taskId,
345
- skill_index: nextSkillIdx,
346
- skill: nextSkill,
347
- prompt: nextPrompt,
348
- timestamp: new Date().toISOString()
349
- });
350
- Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
351
- Write(`.workflow/.idaw/tasks/${taskId}.json`, JSON.stringify(task, null, 2));
352
-
353
- console.log(` Next skill: ${nextSkill}`);
354
- Bash(
355
- `ccw cli -p "${escapeForShell(nextPrompt)}" --tool ${session.cli_tool} --mode write`,
356
- { run_in_background: true }
357
- );
358
- return; // Wait for next hook
359
- }
360
-
361
- // ━━━ Task chain complete — git checkpoint ━━━
362
- const commitMsg = `feat(idaw): ${task.title} [${task.id}]`;
363
- const diffCheck = Bash('git diff --stat HEAD 2>/dev/null || echo ""');
364
- const untrackedCheck = Bash('git ls-files --others --exclude-standard 2>/dev/null || echo ""');
365
-
366
- if (diffCheck?.trim() || untrackedCheck?.trim()) {
367
- Bash('git add -A');
368
- Bash(`git commit -m "$(cat <<'EOF'\n${commitMsg}\nEOF\n)"`);
369
- const commitHash = Bash('git rev-parse --short HEAD 2>/dev/null')?.trim();
370
- task.execution.git_commit = commitHash;
371
- } else {
372
- task.execution.git_commit = 'no-commit';
373
- }
374
-
375
- task.status = 'completed';
376
- task.execution.completed_at = new Date().toISOString();
377
- task.updated_at = new Date().toISOString();
378
- Write(`.workflow/.idaw/tasks/${taskId}.json`, JSON.stringify(task, null, 2));
379
-
380
- session.completed.push(taskId);
381
-
382
- // Append progress
383
- const progressEntry = `## ${task.id} — ${task.title}\n` +
384
- `- Status: completed\n` +
385
- `- Type: ${task.task_type}\n` +
386
- `- Chain: ${chain.join(' → ')}\n` +
387
- `- Commit: ${task.execution.git_commit || '-'}\n` +
388
- `- Mode: coordinate (${session.cli_tool})\n\n`;
389
- const currentProgress = Read(`${sessionDir}/progress.md`);
390
- Write(`${sessionDir}/progress.md`, currentProgress + progressEntry);
391
-
392
- // ━━━ Advance to next task ━━━
393
- const allTaskIds = session.tasks;
394
- const completedSet = new Set([...session.completed, ...session.failed, ...session.skipped]);
395
- const nextTaskId = allTaskIds.find(id => !completedSet.has(id));
396
-
397
- if (nextTaskId) {
398
- // Load next task
399
- const nextTask = JSON.parse(Read(`.workflow/.idaw/tasks/${nextTaskId}.json`));
400
- const nextType = nextTask.task_type || inferTaskType(nextTask.title, nextTask.description);
401
- const nextChain = nextTask.skill_chain || SKILL_CHAIN_MAP[nextType] || SKILL_CHAIN_MAP['feature'];
402
-
403
- nextTask.status = 'in_progress';
404
- nextTask.task_type = nextType;
405
- nextTask.execution.started_at = new Date().toISOString();
406
- Write(`.workflow/.idaw/tasks/${nextTaskId}.json`, JSON.stringify(nextAgent, null, 2));
407
-
408
- session.current_task = nextTaskId;
409
- session.current_skill_index = 0;
410
- session.updated_at = new Date().toISOString();
411
- Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
412
-
413
- // Pre-analysis for complex tasks
414
- if (['bugfix', 'bugfix-hotfix', 'feature-complex'].includes(nextType)) {
415
- const affectedFiles = (nextTask.context?.affected_files || []).join(', ');
416
- Bash(`ccw cli -p 'PURPOSE: Pre-analyze context for ${nextTask.title}. TASK: Check ${affectedFiles || "related files"}. MODE: analysis. EXPECTED: 3-5 bullet points.' --tool gemini --mode analysis 2>&1 || true`);
417
- }
418
-
419
- const nextSkillName = nextChain[0];
420
- const nextPrompt = assembleCliPrompt(nextSkillName, nextAgent, null, true);
421
-
422
- session.prompts_used.push({
423
- task_id: nextTaskId,
424
- skill_index: 0,
425
- skill: nextSkillName,
426
- prompt: nextPrompt,
427
- timestamp: new Date().toISOString()
428
- });
429
- Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
430
-
431
- const taskNum = session.completed.length + 1;
432
- const totalTasks = session.tasks.length;
433
- console.log(`\n[${taskNum}/${totalTasks}] ${nextTaskId}: ${nextTask.title}`);
434
- console.log(` Chain: ${nextChain.join(' → ')}`);
435
-
436
- Bash(
437
- `ccw cli -p "${escapeForShell(nextPrompt)}" --tool ${session.cli_tool} --mode write`,
438
- { run_in_background: true }
439
- );
440
- return; // Wait for hook
441
- }
442
-
443
- // ━━━ All tasks complete — Phase 6: Report ━━━
444
- session.status = session.failed.length > 0 && session.completed.length === 0 ? 'failed' : 'completed';
445
- session.current_task = null;
446
- session.updated_at = new Date().toISOString();
447
- Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
448
-
449
- const summary = `\n---\n## Summary (coordinate mode)\n` +
450
- `- CLI Tool: ${session.cli_tool}\n` +
451
- `- Completed: ${session.completed.length}\n` +
452
- `- Failed: ${session.failed.length}\n` +
453
- `- Skipped: ${session.skipped.length}\n` +
454
- `- Total: ${session.tasks.length}\n`;
455
- const finalProgress = Read(`${sessionDir}/progress.md`);
456
- Write(`${sessionDir}/progress.md`, finalProgress + summary);
457
-
458
- console.log('\n=== IDAW Coordinate Complete ===');
459
- console.log(`Session: ${sessionId}`);
460
- console.log(`Completed: ${session.completed.length}/${session.tasks.length}`);
461
- if (session.failed.length > 0) console.log(`Failed: ${session.failed.join(', ')}`);
462
- }
463
- ```
464
-
465
- ## Helper Functions
466
-
467
- ### assembleCliPrompt
468
-
469
- ```javascript
470
- function assembleCliPrompt(skillName, task, previousResult, autoYes) {
471
- let prompt = '';
472
- const yFlag = autoYes ? ' -y' : '';
473
-
474
- // Map skill to command invocation
475
- if (skillName === 'workflow-lite-plan') {
476
- const goal = sanitize(`${task.title}\n${task.description}`);
477
- prompt = `/workflow-lite-plan${yFlag} "${goal}"`;
478
- if (task.task_type === 'bugfix') prompt = `/workflow-lite-plan${yFlag} --bugfix "${goal}"`;
479
- if (task.task_type === 'bugfix-hotfix') prompt = `/workflow-lite-plan${yFlag} --hotfix "${goal}"`;
480
-
481
- } else if (skillName === 'workflow-plan') {
482
- prompt = `/workflow-plan${yFlag} "${sanitize(task.title)}"`;
483
-
484
- } else if (skillName === 'workflow-execute') {
485
- if (previousResult?.sessionId) {
486
- prompt = `/workflow-execute${yFlag} --resume-session="${previousResult.sessionId}"`;
487
- } else {
488
- prompt = `/workflow-execute${yFlag}`;
489
- }
490
-
491
- } else if (skillName === 'workflow-test-fix') {
492
- if (previousResult?.sessionId) {
493
- prompt = `/workflow-test-fix${yFlag} "${previousResult.sessionId}"`;
494
- } else {
495
- prompt = `/workflow-test-fix${yFlag} "${sanitize(task.title)}"`;
496
- }
497
-
498
- } else if (skillName === 'workflow-tdd-plan') {
499
- prompt = `/workflow-tdd-plan${yFlag} "${sanitize(task.title)}"`;
500
-
501
- } else if (skillName === 'workflow:refactor-cycle') {
502
- prompt = `/workflow:refactor-cycle${yFlag} "${sanitize(task.title)}"`;
503
-
504
- } else if (skillName === 'review-cycle') {
505
- if (previousResult?.sessionId) {
506
- prompt = `/review-cycle${yFlag} --session="${previousResult.sessionId}"`;
507
- } else {
508
- prompt = `/review-cycle${yFlag}`;
509
- }
510
-
511
- } else {
512
- // Generic fallback
513
- prompt = `/${skillName}${yFlag} "${sanitize(task.title)}"`;
514
- }
515
-
516
- // Append task context
517
- prompt += `\n\nTask: ${task.title}\nDescription: ${task.description}`;
518
- if (task.context?.affected_files?.length > 0) {
519
- prompt += `\nAffected files: ${task.context.affected_files.join(', ')}`;
520
- }
521
- if (task.context?.acceptance_criteria?.length > 0) {
522
- prompt += `\nAcceptance criteria: ${task.context.acceptance_criteria.join('; ')}`;
523
- }
524
-
525
- return prompt;
526
- }
527
- ```
528
-
529
- ### sanitize & escapeForShell
530
-
531
- ```javascript
532
- function sanitize(text) {
533
- return text
534
- .replace(/\\/g, '\\\\')
535
- .replace(/"/g, '\\"')
536
- .replace(/\$/g, '\\$')
537
- .replace(/`/g, '\\`');
538
- }
539
-
540
- function escapeForShell(prompt) {
541
- return prompt.replace(/'/g, "'\\''");
542
- }
543
- ```
544
-
545
- ### parseCliOutput
546
-
547
- ```javascript
548
- function parseCliOutput(output) {
549
- // Extract session ID from CLI output (e.g., WFS-xxx, session-xxx)
550
- const sessionMatch = output.match(/(?:session|WFS|Session ID)[:\s]*([\w-]+)/i);
551
- const success = !/(?:error|failed|fatal)/i.test(output) || /completed|success/i.test(output);
552
-
553
- return {
554
- success,
555
- sessionId: sessionMatch?.[1] || null,
556
- raw: output?.substring(0, 500)
557
- };
558
- }
559
- ```
560
-
561
- ## CLI-Assisted Analysis
562
-
563
- Same as `/idaw:run` — integrated at two points:
564
-
565
- ### Pre-Task Context Analysis
566
- For `bugfix`, `bugfix-hotfix`, `feature-complex` tasks: auto-invoke `ccw cli --tool gemini --mode analysis` before launching skill chain.
567
-
568
- ### Error Recovery with CLI Diagnosis
569
- When a skill's CLI execution fails: invoke diagnosis → retry once → if still fails, mark failed and advance.
570
-
571
- ```
572
- Skill CLI fails → CLI diagnosis (gemini) → Retry CLI → Still fails → mark failed → next task
573
- ```
574
-
575
- ## State Flow
576
-
577
- ```
578
- Phase 4: Launch first skill
579
-
580
- ccw cli --tool claude --mode write (background)
581
-
582
- ★ STOP — wait for hook callback
583
-
584
- Phase 5: handleStepCompletion()
585
- ├─ Skill succeeded + more in chain → launch next skill → STOP
586
- ├─ Skill succeeded + chain complete → git checkpoint → next task → STOP
587
- ├─ Skill failed → CLI diagnosis → retry → STOP
588
- └─ All tasks done → Phase 6: Report
589
- ```
590
-
591
- ## Session State (session.json)
592
-
593
- ```json
594
- {
595
- "session_id": "IDA-fix-login-20260301",
596
- "mode": "coordinate",
597
- "cli_tool": "claude",
598
- "status": "running|waiting|completed|failed",
599
- "created_at": "ISO",
600
- "updated_at": "ISO",
601
- "tasks": ["IDAW-001", "IDAW-002"],
602
- "current_task": "IDAW-001",
603
- "current_skill_index": 0,
604
- "completed": [],
605
- "failed": [],
606
- "skipped": [],
607
- "prompts_used": [
608
- {
609
- "task_id": "IDAW-001",
610
- "skill_index": 0,
611
- "skill": "workflow-lite-plan",
612
- "prompt": "/workflow-lite-plan -y \"Fix login timeout\"",
613
- "timestamp": "ISO"
614
- }
615
- ]
616
- }
617
- ```
618
-
619
- ## Differences from /idaw:run
620
-
621
- | Aspect | /idaw:run | /idaw:run-coordinate |
622
- |--------|-----------|---------------------|
623
- | Execution | `Skill()` blocking in main process | `ccw cli` background + hook callback |
624
- | Context window | Shared (each skill uses main context) | Isolated (each CLI gets fresh context) |
625
- | Concurrency | Sequential blocking | Sequential non-blocking (hook-driven) |
626
- | State tracking | session.json + task.json | session.json + task.json + prompts_used |
627
- | Tool selection | N/A (Skill native) | `--tool claude\|gemini\|qwen` |
628
- | Resume | Via `/idaw:resume` (same) | Via `/idaw:resume` (same, detects mode) |
629
- | Best for | Short chains, interactive | Long chains, autonomous, context-heavy |
630
-
631
- ## Examples
632
-
633
- ```bash
634
- # Execute all pending tasks via claude CLI
635
- /idaw:run-coordinate -y
636
-
637
- # Use specific CLI tool
638
- /idaw:run-coordinate -y --tool gemini
639
-
640
- # Execute specific tasks
641
- /idaw:run-coordinate --task IDAW-001,IDAW-003 --tool claude
642
-
643
- # Dry run (show plan without executing)
644
- /idaw:run-coordinate --dry-run
645
-
646
- # Interactive mode
647
- /idaw:run-coordinate
648
- ```