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.
- package/.claude/commands/workflow/analyze-with-file.md +108 -54
- package/.claude/commands/workflow-tune.md +811 -0
- package/.claude/skills/workflow-lite-execute/SKILL.md +106 -14
- package/.claude/skills/workflow-lite-plan/SKILL.md +34 -72
- package/.claude/skills/workflow-lite-test-review/SKILL.md +39 -26
- package/package.json +1 -1
- package/.claude/commands/ddd/auto.md +0 -359
- package/.claude/commands/ddd/doc-generate.md +0 -222
- package/.claude/commands/ddd/doc-refresh.md +0 -218
- package/.claude/commands/ddd/execute.md +0 -416
- package/.claude/commands/ddd/index-build.md +0 -212
- package/.claude/commands/ddd/plan.md +0 -611
- package/.claude/commands/ddd/scan.md +0 -365
- package/.claude/commands/ddd/sync.md +0 -353
- package/.claude/commands/ddd/update.md +0 -160
- package/.claude/commands/idaw/add.md +0 -287
- package/.claude/commands/idaw/resume.md +0 -442
- package/.claude/commands/idaw/run-coordinate.md +0 -648
- package/.claude/commands/idaw/run.md +0 -539
- package/.claude/commands/idaw/status.md +0 -182
- package/.claude/skills/workflow-tune/SKILL.md +0 -487
- package/.claude/skills/workflow-tune/phases/01-setup.md +0 -548
- package/.claude/skills/workflow-tune/phases/02-step-execute.md +0 -197
- package/.claude/skills/workflow-tune/phases/03-step-analyze.md +0 -386
- package/.claude/skills/workflow-tune/phases/04-synthesize.md +0 -257
- package/.claude/skills/workflow-tune/phases/05-optimize-report.md +0 -246
- package/.claude/skills/workflow-tune/specs/workflow-eval-criteria.md +0 -57
- package/.claude/skills/workflow-tune/templates/step-analysis-prompt.md +0 -88
- package/.claude/skills/workflow-tune/templates/synthesis-prompt.md +0 -90
|
@@ -1,539 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: run
|
|
3
|
-
description: IDAW orchestrator - execute task skill chains serially with git checkpoints
|
|
4
|
-
argument-hint: "[-y|--yes] [--task <id>[,<id>,...]] [--dry-run]"
|
|
5
|
-
allowed-tools: Skill(*), TodoWrite(*), AskUserQuestion(*), Read(*), Write(*), Bash(*), Glob(*)
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# IDAW Run Command (/idaw:run)
|
|
9
|
-
|
|
10
|
-
## Auto Mode
|
|
11
|
-
|
|
12
|
-
When `--yes` or `-y`: Skip all confirmations, auto-skip on failure, proceed with dirty git.
|
|
13
|
-
|
|
14
|
-
## Skill Chain Mapping
|
|
15
|
-
|
|
16
|
-
```javascript
|
|
17
|
-
const SKILL_CHAIN_MAP = {
|
|
18
|
-
'bugfix': ['workflow-lite-plan', 'workflow-test-fix'],
|
|
19
|
-
'bugfix-hotfix': ['workflow-lite-plan'],
|
|
20
|
-
'feature': ['workflow-lite-plan', 'workflow-test-fix'],
|
|
21
|
-
'feature-complex': ['workflow-plan', 'workflow-execute', 'workflow-test-fix'],
|
|
22
|
-
'refactor': ['workflow:refactor-cycle'],
|
|
23
|
-
'tdd': ['workflow-tdd-plan', 'workflow-execute'],
|
|
24
|
-
'test': ['workflow-test-fix'],
|
|
25
|
-
'test-fix': ['workflow-test-fix'],
|
|
26
|
-
'review': ['review-cycle'],
|
|
27
|
-
'docs': ['workflow-lite-plan']
|
|
28
|
-
};
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Task Type Inference
|
|
32
|
-
|
|
33
|
-
```javascript
|
|
34
|
-
function inferTaskType(title, description) {
|
|
35
|
-
const text = `${title} ${description}`.toLowerCase();
|
|
36
|
-
if (/urgent|production|critical/.test(text) && /fix|bug/.test(text)) return 'bugfix-hotfix';
|
|
37
|
-
if (/refactor|重构|tech.*debt/.test(text)) return 'refactor';
|
|
38
|
-
if (/tdd|test-driven|test first/.test(text)) return 'tdd';
|
|
39
|
-
if (/test fail|fix test|failing test/.test(text)) return 'test-fix';
|
|
40
|
-
if (/generate test|写测试|add test/.test(text)) return 'test';
|
|
41
|
-
if (/review|code review/.test(text)) return 'review';
|
|
42
|
-
if (/docs|documentation|readme/.test(text)) return 'docs';
|
|
43
|
-
if (/fix|bug|error|crash|fail/.test(text)) return 'bugfix';
|
|
44
|
-
if (/complex|multi-module|architecture/.test(text)) return 'feature-complex';
|
|
45
|
-
return 'feature';
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## 6-Phase Execution
|
|
50
|
-
|
|
51
|
-
### Phase 1: Load Tasks
|
|
52
|
-
|
|
53
|
-
```javascript
|
|
54
|
-
const args = $ARGUMENTS;
|
|
55
|
-
const autoYes = /(-y|--yes)/.test(args);
|
|
56
|
-
const dryRun = /--dry-run/.test(args);
|
|
57
|
-
const taskFilter = args.match(/--task\s+([\w,-]+)/)?.[1]?.split(',') || null;
|
|
58
|
-
|
|
59
|
-
// Load task files
|
|
60
|
-
const taskFiles = Glob('.workflow/.idaw/tasks/IDAW-*.json') || [];
|
|
61
|
-
|
|
62
|
-
if (taskFiles.length === 0) {
|
|
63
|
-
console.log('No IDAW tasks found. Use /idaw:add to create tasks.');
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Parse and filter
|
|
68
|
-
let tasks = taskFiles.map(f => JSON.parse(Read(f)));
|
|
69
|
-
|
|
70
|
-
if (taskFilter) {
|
|
71
|
-
tasks = tasks.filter(t => taskFilter.includes(t.id));
|
|
72
|
-
} else {
|
|
73
|
-
tasks = tasks.filter(t => t.status === 'pending');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (tasks.length === 0) {
|
|
77
|
-
console.log('No pending tasks to execute. Use /idaw:add to add tasks or --task to specify IDs.');
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Sort: priority ASC (1=critical first), then ID ASC
|
|
82
|
-
tasks.sort((a, b) => {
|
|
83
|
-
if (a.priority !== b.priority) return a.priority - b.priority;
|
|
84
|
-
return a.id.localeCompare(b.id);
|
|
85
|
-
});
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Phase 2: Session Setup
|
|
89
|
-
|
|
90
|
-
```javascript
|
|
91
|
-
// Generate session ID: IDA-{slug}-YYYYMMDD
|
|
92
|
-
const slug = tasks[0].title
|
|
93
|
-
.toLowerCase()
|
|
94
|
-
.replace(/[^a-z0-9]+/g, '-')
|
|
95
|
-
.substring(0, 20)
|
|
96
|
-
.replace(/-$/, '');
|
|
97
|
-
const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
98
|
-
let sessionId = `IDA-${slug}-${dateStr}`;
|
|
99
|
-
|
|
100
|
-
// Check collision
|
|
101
|
-
const existingSession = Glob(`.workflow/.idaw/sessions/${sessionId}/session.json`);
|
|
102
|
-
if (existingSession?.length > 0) {
|
|
103
|
-
sessionId = `${sessionId}-2`;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const sessionDir = `.workflow/.idaw/sessions/${sessionId}`;
|
|
107
|
-
Bash(`mkdir -p "${sessionDir}"`);
|
|
108
|
-
|
|
109
|
-
const session = {
|
|
110
|
-
session_id: sessionId,
|
|
111
|
-
status: 'running',
|
|
112
|
-
created_at: new Date().toISOString(),
|
|
113
|
-
updated_at: new Date().toISOString(),
|
|
114
|
-
tasks: tasks.map(t => t.id),
|
|
115
|
-
current_task: null,
|
|
116
|
-
completed: [],
|
|
117
|
-
failed: [],
|
|
118
|
-
skipped: []
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
|
|
122
|
-
|
|
123
|
-
// Initialize progress.md
|
|
124
|
-
const progressHeader = `# IDAW Progress — ${sessionId}\nStarted: ${session.created_at}\n\n`;
|
|
125
|
-
Write(`${sessionDir}/progress.md`, progressHeader);
|
|
126
|
-
|
|
127
|
-
// TodoWrite
|
|
128
|
-
TodoWrite({
|
|
129
|
-
todos: tasks.map((t, i) => ({
|
|
130
|
-
content: `IDAW:[${i + 1}/${tasks.length}] ${t.title}`,
|
|
131
|
-
status: i === 0 ? 'in_progress' : 'pending',
|
|
132
|
-
activeForm: `Executing ${t.title}`
|
|
133
|
-
}))
|
|
134
|
-
});
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### Phase 3: Startup Protocol
|
|
138
|
-
|
|
139
|
-
```javascript
|
|
140
|
-
// Check for existing running sessions
|
|
141
|
-
const runningSessions = Glob('.workflow/.idaw/sessions/IDA-*/session.json')
|
|
142
|
-
?.map(f => JSON.parse(Read(f)))
|
|
143
|
-
.filter(s => s.status === 'running' && s.session_id !== sessionId) || [];
|
|
144
|
-
|
|
145
|
-
if (runningSessions.length > 0) {
|
|
146
|
-
if (!autoYes) {
|
|
147
|
-
const answer = AskUserQuestion({
|
|
148
|
-
questions: [{
|
|
149
|
-
question: `Found running session: ${runningSessions[0].session_id}. How to proceed?`,
|
|
150
|
-
header: 'Conflict',
|
|
151
|
-
multiSelect: false,
|
|
152
|
-
options: [
|
|
153
|
-
{ label: 'Resume existing', description: 'Use /idaw:resume instead' },
|
|
154
|
-
{ label: 'Start fresh', description: 'Continue with new session' },
|
|
155
|
-
{ label: 'Abort', description: 'Cancel this run' }
|
|
156
|
-
]
|
|
157
|
-
}]
|
|
158
|
-
});
|
|
159
|
-
if (answer.answers?.Conflict === 'Resume existing') {
|
|
160
|
-
console.log(`Use: /idaw:resume ${runningSessions[0].session_id}`);
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
if (answer.answers?.Conflict === 'Abort') return;
|
|
164
|
-
}
|
|
165
|
-
// autoYes or "Start fresh": proceed
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Check git status
|
|
169
|
-
const gitStatus = Bash('git status --porcelain 2>/dev/null');
|
|
170
|
-
if (gitStatus?.trim()) {
|
|
171
|
-
if (!autoYes) {
|
|
172
|
-
const answer = AskUserQuestion({
|
|
173
|
-
questions: [{
|
|
174
|
-
question: 'Working tree has uncommitted changes. How to proceed?',
|
|
175
|
-
header: 'Git',
|
|
176
|
-
multiSelect: false,
|
|
177
|
-
options: [
|
|
178
|
-
{ label: 'Continue', description: 'Proceed with dirty tree' },
|
|
179
|
-
{ label: 'Stash', description: 'git stash before running' },
|
|
180
|
-
{ label: 'Abort', description: 'Stop and handle manually' }
|
|
181
|
-
]
|
|
182
|
-
}]
|
|
183
|
-
});
|
|
184
|
-
if (answer.answers?.Git === 'Stash') {
|
|
185
|
-
Bash('git stash push -m "idaw-pre-run"');
|
|
186
|
-
}
|
|
187
|
-
if (answer.answers?.Git === 'Abort') return;
|
|
188
|
-
}
|
|
189
|
-
// autoYes: proceed silently
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Dry run: show plan and exit
|
|
193
|
-
if (dryRun) {
|
|
194
|
-
console.log(`# Dry Run — ${sessionId}\n`);
|
|
195
|
-
for (const task of tasks) {
|
|
196
|
-
const taskType = task.task_type || inferTaskType(task.title, task.description);
|
|
197
|
-
const chain = task.skill_chain || SKILL_CHAIN_MAP[taskType] || SKILL_CHAIN_MAP['feature'];
|
|
198
|
-
console.log(`## ${task.id}: ${task.title}`);
|
|
199
|
-
console.log(` Type: ${taskType} | Priority: ${task.priority}`);
|
|
200
|
-
console.log(` Chain: ${chain.join(' → ')}\n`);
|
|
201
|
-
}
|
|
202
|
-
console.log(`Total: ${tasks.length} tasks`);
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### Phase 4: Main Loop (serial, one task at a time)
|
|
208
|
-
|
|
209
|
-
```javascript
|
|
210
|
-
for (let taskIdx = 0; taskIdx < tasks.length; taskIdx++) {
|
|
211
|
-
const task = tasks[taskIdx];
|
|
212
|
-
|
|
213
|
-
// Skip completed/failed/skipped
|
|
214
|
-
if (['completed', 'failed', 'skipped'].includes(task.status)) continue;
|
|
215
|
-
|
|
216
|
-
// Resolve skill chain
|
|
217
|
-
const resolvedType = task.task_type || inferTaskType(task.title, task.description);
|
|
218
|
-
const chain = task.skill_chain || SKILL_CHAIN_MAP[resolvedType] || SKILL_CHAIN_MAP['feature'];
|
|
219
|
-
|
|
220
|
-
// Update task status → in_progress
|
|
221
|
-
task.status = 'in_progress';
|
|
222
|
-
task.task_type = resolvedType; // persist inferred type
|
|
223
|
-
task.execution.started_at = new Date().toISOString();
|
|
224
|
-
Write(`.workflow/.idaw/tasks/${task.id}.json`, JSON.stringify(task, null, 2));
|
|
225
|
-
|
|
226
|
-
// Update session
|
|
227
|
-
session.current_task = task.id;
|
|
228
|
-
session.updated_at = new Date().toISOString();
|
|
229
|
-
Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
|
|
230
|
-
|
|
231
|
-
console.log(`\n--- [${taskIdx + 1}/${tasks.length}] ${task.id}: ${task.title} ---`);
|
|
232
|
-
console.log(`Chain: ${chain.join(' → ')}`);
|
|
233
|
-
|
|
234
|
-
// ━━━ Pre-Task CLI Context Analysis (for complex/bugfix tasks) ━━━
|
|
235
|
-
if (['bugfix', 'bugfix-hotfix', 'feature-complex'].includes(resolvedType)) {
|
|
236
|
-
console.log(` Pre-analysis: gathering context for ${resolvedType} task...`);
|
|
237
|
-
const affectedFiles = (task.context?.affected_files || []).join(', ');
|
|
238
|
-
const preAnalysisPrompt = `PURPOSE: Pre-analyze codebase context for IDAW task before execution.
|
|
239
|
-
TASK: • Understand current state of: ${affectedFiles || 'files related to: ' + task.title} • Identify dependencies and risk areas • Note existing patterns to follow
|
|
240
|
-
MODE: analysis
|
|
241
|
-
CONTEXT: @**/*
|
|
242
|
-
EXPECTED: Brief context summary (affected modules, dependencies, risk areas) in 3-5 bullet points
|
|
243
|
-
CONSTRAINTS: Keep concise | Focus on execution-relevant context`;
|
|
244
|
-
const preAnalysis = Bash(`ccw cli -p '${preAnalysisPrompt.replace(/'/g, "'\\''")}' --tool gemini --mode analysis 2>&1 || echo "Pre-analysis skipped"`);
|
|
245
|
-
task.execution.skill_results.push({
|
|
246
|
-
skill: 'cli-pre-analysis',
|
|
247
|
-
status: 'completed',
|
|
248
|
-
context_summary: preAnalysis?.substring(0, 500),
|
|
249
|
-
timestamp: new Date().toISOString()
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Execute each skill in chain
|
|
254
|
-
let previousResult = null;
|
|
255
|
-
let taskFailed = false;
|
|
256
|
-
|
|
257
|
-
for (let skillIdx = 0; skillIdx < chain.length; skillIdx++) {
|
|
258
|
-
const skillName = chain[skillIdx];
|
|
259
|
-
const skillArgs = assembleSkillArgs(skillName, task, previousResult, autoYes, skillIdx === 0);
|
|
260
|
-
|
|
261
|
-
console.log(` [${skillIdx + 1}/${chain.length}] ${skillName}`);
|
|
262
|
-
|
|
263
|
-
try {
|
|
264
|
-
const result = Skill({ skill: skillName, args: skillArgs });
|
|
265
|
-
previousResult = result;
|
|
266
|
-
task.execution.skill_results.push({
|
|
267
|
-
skill: skillName,
|
|
268
|
-
status: 'completed',
|
|
269
|
-
timestamp: new Date().toISOString()
|
|
270
|
-
});
|
|
271
|
-
} catch (error) {
|
|
272
|
-
// ━━━ CLI-Assisted Error Recovery ━━━
|
|
273
|
-
// Step 1: Invoke CLI diagnosis (auto-invoke trigger: self-repair fails)
|
|
274
|
-
console.log(` Diagnosing failure: ${skillName}...`);
|
|
275
|
-
const diagnosisPrompt = `PURPOSE: Diagnose why skill "${skillName}" failed during IDAW task execution.
|
|
276
|
-
TASK: • Analyze error: ${String(error).substring(0, 300)} • Check affected files: ${(task.context?.affected_files || []).join(', ') || 'unknown'} • Identify root cause • Suggest fix strategy
|
|
277
|
-
MODE: analysis
|
|
278
|
-
CONTEXT: @**/* | Memory: IDAW task ${task.id}: ${task.title}
|
|
279
|
-
EXPECTED: Root cause + actionable fix recommendation (1-2 sentences)
|
|
280
|
-
CONSTRAINTS: Focus on actionable diagnosis`;
|
|
281
|
-
const diagnosisResult = Bash(`ccw cli -p '${diagnosisPrompt.replace(/'/g, "'\\''")}' --tool gemini --mode analysis --rule analysis-diagnose-bug-root-cause 2>&1 || echo "CLI diagnosis unavailable"`);
|
|
282
|
-
|
|
283
|
-
task.execution.skill_results.push({
|
|
284
|
-
skill: `cli-diagnosis:${skillName}`,
|
|
285
|
-
status: 'completed',
|
|
286
|
-
diagnosis: diagnosisResult?.substring(0, 500),
|
|
287
|
-
timestamp: new Date().toISOString()
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
// Step 2: Retry with diagnosis context
|
|
291
|
-
console.log(` Retry with diagnosis: ${skillName}`);
|
|
292
|
-
try {
|
|
293
|
-
const retryResult = Skill({ skill: skillName, args: skillArgs });
|
|
294
|
-
previousResult = retryResult;
|
|
295
|
-
task.execution.skill_results.push({
|
|
296
|
-
skill: skillName,
|
|
297
|
-
status: 'completed-retry-with-diagnosis',
|
|
298
|
-
timestamp: new Date().toISOString()
|
|
299
|
-
});
|
|
300
|
-
} catch (retryError) {
|
|
301
|
-
// Step 3: Failed after CLI-assisted retry
|
|
302
|
-
task.execution.skill_results.push({
|
|
303
|
-
skill: skillName,
|
|
304
|
-
status: 'failed',
|
|
305
|
-
error: String(retryError).substring(0, 200),
|
|
306
|
-
timestamp: new Date().toISOString()
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
if (autoYes) {
|
|
310
|
-
taskFailed = true;
|
|
311
|
-
break;
|
|
312
|
-
} else {
|
|
313
|
-
const answer = AskUserQuestion({
|
|
314
|
-
questions: [{
|
|
315
|
-
question: `${skillName} failed after CLI diagnosis + retry: ${String(retryError).substring(0, 100)}. How to proceed?`,
|
|
316
|
-
header: 'Error',
|
|
317
|
-
multiSelect: false,
|
|
318
|
-
options: [
|
|
319
|
-
{ label: 'Skip task', description: 'Mark task as failed, continue to next' },
|
|
320
|
-
{ label: 'Abort', description: 'Stop entire run' }
|
|
321
|
-
]
|
|
322
|
-
}]
|
|
323
|
-
});
|
|
324
|
-
if (answer.answers?.Error === 'Abort') {
|
|
325
|
-
task.status = 'failed';
|
|
326
|
-
task.execution.error = String(retryError).substring(0, 200);
|
|
327
|
-
Write(`.workflow/.idaw/tasks/${task.id}.json`, JSON.stringify(task, null, 2));
|
|
328
|
-
session.failed.push(task.id);
|
|
329
|
-
session.status = 'failed';
|
|
330
|
-
session.updated_at = new Date().toISOString();
|
|
331
|
-
Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
taskFailed = true;
|
|
335
|
-
break;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// Phase 5: Checkpoint (per task) — inline
|
|
342
|
-
if (taskFailed) {
|
|
343
|
-
task.status = 'failed';
|
|
344
|
-
task.execution.error = 'Skill chain failed after retry';
|
|
345
|
-
task.execution.completed_at = new Date().toISOString();
|
|
346
|
-
session.failed.push(task.id);
|
|
347
|
-
} else {
|
|
348
|
-
// Git commit checkpoint
|
|
349
|
-
const commitMsg = `feat(idaw): ${task.title} [${task.id}]`;
|
|
350
|
-
const diffCheck = Bash('git diff --stat HEAD 2>/dev/null || echo ""');
|
|
351
|
-
const untrackedCheck = Bash('git ls-files --others --exclude-standard 2>/dev/null || echo ""');
|
|
352
|
-
|
|
353
|
-
if (diffCheck?.trim() || untrackedCheck?.trim()) {
|
|
354
|
-
Bash('git add -A');
|
|
355
|
-
const commitResult = Bash(`git commit -m "$(cat <<'EOF'\n${commitMsg}\nEOF\n)"`);
|
|
356
|
-
const commitHash = Bash('git rev-parse --short HEAD 2>/dev/null')?.trim();
|
|
357
|
-
task.execution.git_commit = commitHash;
|
|
358
|
-
} else {
|
|
359
|
-
task.execution.git_commit = 'no-commit';
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
task.status = 'completed';
|
|
363
|
-
task.execution.completed_at = new Date().toISOString();
|
|
364
|
-
session.completed.push(task.id);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// Write task + session state
|
|
368
|
-
task.updated_at = new Date().toISOString();
|
|
369
|
-
Write(`.workflow/.idaw/tasks/${task.id}.json`, JSON.stringify(task, null, 2));
|
|
370
|
-
|
|
371
|
-
session.updated_at = new Date().toISOString();
|
|
372
|
-
Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
|
|
373
|
-
|
|
374
|
-
// Append to progress.md
|
|
375
|
-
const duration = task.execution.started_at && task.execution.completed_at
|
|
376
|
-
? formatDuration(new Date(task.execution.completed_at) - new Date(task.execution.started_at))
|
|
377
|
-
: 'unknown';
|
|
378
|
-
|
|
379
|
-
const progressEntry = `## ${task.id} — ${task.title}\n` +
|
|
380
|
-
`- Status: ${task.status}\n` +
|
|
381
|
-
`- Type: ${task.task_type}\n` +
|
|
382
|
-
`- Chain: ${chain.join(' → ')}\n` +
|
|
383
|
-
`- Commit: ${task.execution.git_commit || '-'}\n` +
|
|
384
|
-
`- Duration: ${duration}\n\n`;
|
|
385
|
-
|
|
386
|
-
const currentProgress = Read(`${sessionDir}/progress.md`);
|
|
387
|
-
Write(`${sessionDir}/progress.md`, currentProgress + progressEntry);
|
|
388
|
-
|
|
389
|
-
// Update TodoWrite
|
|
390
|
-
if (taskIdx + 1 < tasks.length) {
|
|
391
|
-
TodoWrite({
|
|
392
|
-
todos: tasks.map((t, i) => ({
|
|
393
|
-
content: `IDAW:[${i + 1}/${tasks.length}] ${t.title}`,
|
|
394
|
-
status: i < taskIdx + 1 ? 'completed' : (i === taskIdx + 1 ? 'in_progress' : 'pending'),
|
|
395
|
-
activeForm: `Executing ${t.title}`
|
|
396
|
-
}))
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
### Phase 6: Report
|
|
403
|
-
|
|
404
|
-
```javascript
|
|
405
|
-
session.status = session.failed.length > 0 && session.completed.length === 0 ? 'failed' : 'completed';
|
|
406
|
-
session.current_task = null;
|
|
407
|
-
session.updated_at = new Date().toISOString();
|
|
408
|
-
Write(`${sessionDir}/session.json`, JSON.stringify(session, null, 2));
|
|
409
|
-
|
|
410
|
-
// Final progress summary
|
|
411
|
-
const summary = `\n---\n## Summary\n` +
|
|
412
|
-
`- Completed: ${session.completed.length}\n` +
|
|
413
|
-
`- Failed: ${session.failed.length}\n` +
|
|
414
|
-
`- Skipped: ${session.skipped.length}\n` +
|
|
415
|
-
`- Total: ${tasks.length}\n`;
|
|
416
|
-
|
|
417
|
-
const finalProgress = Read(`${sessionDir}/progress.md`);
|
|
418
|
-
Write(`${sessionDir}/progress.md`, finalProgress + summary);
|
|
419
|
-
|
|
420
|
-
// Display report
|
|
421
|
-
console.log('\n=== IDAW Run Complete ===');
|
|
422
|
-
console.log(`Session: ${sessionId}`);
|
|
423
|
-
console.log(`Completed: ${session.completed.length}/${tasks.length}`);
|
|
424
|
-
if (session.failed.length > 0) console.log(`Failed: ${session.failed.join(', ')}`);
|
|
425
|
-
if (session.skipped.length > 0) console.log(`Skipped: ${session.skipped.join(', ')}`);
|
|
426
|
-
|
|
427
|
-
// List git commits
|
|
428
|
-
for (const taskId of session.completed) {
|
|
429
|
-
const t = JSON.parse(Read(`.workflow/.idaw/tasks/${taskId}.json`));
|
|
430
|
-
if (t.execution.git_commit && t.execution.git_commit !== 'no-commit') {
|
|
431
|
-
console.log(` ${t.execution.git_commit} ${t.title}`);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
## Helper Functions
|
|
437
|
-
|
|
438
|
-
### assembleSkillArgs
|
|
439
|
-
|
|
440
|
-
```javascript
|
|
441
|
-
function assembleSkillArgs(skillName, task, previousResult, autoYes, isFirst) {
|
|
442
|
-
let args = '';
|
|
443
|
-
|
|
444
|
-
if (isFirst) {
|
|
445
|
-
// First skill: pass task goal — sanitize for shell safety
|
|
446
|
-
const goal = `${task.title}\n${task.description}`
|
|
447
|
-
.replace(/\\/g, '\\\\')
|
|
448
|
-
.replace(/"/g, '\\"')
|
|
449
|
-
.replace(/\$/g, '\\$')
|
|
450
|
-
.replace(/`/g, '\\`');
|
|
451
|
-
args = `"${goal}"`;
|
|
452
|
-
|
|
453
|
-
// bugfix-hotfix: add --hotfix
|
|
454
|
-
if (task.task_type === 'bugfix-hotfix') {
|
|
455
|
-
args += ' --hotfix';
|
|
456
|
-
}
|
|
457
|
-
} else if (previousResult?.session_id) {
|
|
458
|
-
// Subsequent skills: chain session
|
|
459
|
-
args = `--session="${previousResult.session_id}"`;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
// Propagate -y
|
|
463
|
-
if (autoYes && !args.includes('-y') && !args.includes('--yes')) {
|
|
464
|
-
args = args ? `${args} -y` : '-y';
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
return args;
|
|
468
|
-
}
|
|
469
|
-
```
|
|
470
|
-
|
|
471
|
-
### formatDuration
|
|
472
|
-
|
|
473
|
-
```javascript
|
|
474
|
-
function formatDuration(ms) {
|
|
475
|
-
const seconds = Math.floor(ms / 1000);
|
|
476
|
-
const minutes = Math.floor(seconds / 60);
|
|
477
|
-
const remainingSeconds = seconds % 60;
|
|
478
|
-
if (minutes > 0) return `${minutes}m ${remainingSeconds}s`;
|
|
479
|
-
return `${seconds}s`;
|
|
480
|
-
}
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
## CLI-Assisted Analysis
|
|
484
|
-
|
|
485
|
-
IDAW integrates `ccw cli` (Gemini) for intelligent analysis at two key points:
|
|
486
|
-
|
|
487
|
-
### Pre-Task Context Analysis
|
|
488
|
-
|
|
489
|
-
For `bugfix`, `bugfix-hotfix`, and `feature-complex` tasks, IDAW automatically invokes CLI analysis **before** executing the skill chain to gather codebase context:
|
|
490
|
-
|
|
491
|
-
```
|
|
492
|
-
Task starts → CLI pre-analysis (gemini) → Context gathered → Skill chain executes
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
- Identifies dependencies and risk areas
|
|
496
|
-
- Notes existing patterns to follow
|
|
497
|
-
- Results stored in `task.execution.skill_results` as `cli-pre-analysis`
|
|
498
|
-
|
|
499
|
-
### Error Recovery with CLI Diagnosis
|
|
500
|
-
|
|
501
|
-
When a skill fails, instead of blind retry, IDAW uses CLI-assisted diagnosis:
|
|
502
|
-
|
|
503
|
-
```
|
|
504
|
-
Skill fails → CLI diagnosis (gemini, analysis-diagnose-bug-root-cause)
|
|
505
|
-
→ Root cause identified → Retry with diagnosis context
|
|
506
|
-
→ Still fails → Skip (autoYes) or Ask user (interactive)
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
- Uses `--rule analysis-diagnose-bug-root-cause` template
|
|
510
|
-
- Diagnosis results stored in `task.execution.skill_results` as `cli-diagnosis:{skill}`
|
|
511
|
-
- Follows CLAUDE.md auto-invoke trigger pattern: "self-repair fails → invoke CLI analysis"
|
|
512
|
-
|
|
513
|
-
### Execution Flow (with CLI analysis)
|
|
514
|
-
|
|
515
|
-
```
|
|
516
|
-
Phase 4 Main Loop (per task):
|
|
517
|
-
├─ [bugfix/complex only] CLI pre-analysis → context summary
|
|
518
|
-
├─ Skill 1: execute
|
|
519
|
-
│ ├─ Success → next skill
|
|
520
|
-
│ └─ Failure → CLI diagnosis → retry → success/fail
|
|
521
|
-
├─ Skill 2: execute ...
|
|
522
|
-
└─ Phase 5: git checkpoint
|
|
523
|
-
```
|
|
524
|
-
|
|
525
|
-
## Examples
|
|
526
|
-
|
|
527
|
-
```bash
|
|
528
|
-
# Execute all pending tasks
|
|
529
|
-
/idaw:run -y
|
|
530
|
-
|
|
531
|
-
# Execute specific tasks
|
|
532
|
-
/idaw:run --task IDAW-001,IDAW-003
|
|
533
|
-
|
|
534
|
-
# Dry run (show plan without executing)
|
|
535
|
-
/idaw:run --dry-run
|
|
536
|
-
|
|
537
|
-
# Interactive mode (confirm at each step)
|
|
538
|
-
/idaw:run
|
|
539
|
-
```
|