claude-code-workflow 6.3.49 → 6.3.51
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/issue/new.md +1 -2
- package/.claude/commands/view.md +367 -0
- package/.claude/commands/workflow/unified-execute-with-file.md +807 -0
- package/.claude/skills/ccw-help/SKILL.md +72 -12
- package/.claude/skills/ccw-help/command.json +922 -520
- package/.claude/skills/ccw-help/index/all-agents.json +97 -0
- package/.claude/skills/ccw-help/index/all-commands.json +805 -0
- package/.claude/skills/ccw-help/index/by-category.json +833 -0
- package/.claude/skills/ccw-help/index/by-use-case.json +819 -0
- package/.claude/skills/ccw-help/index/command-relationships.json +160 -0
- package/.claude/skills/ccw-help/index/essential-commands.json +90 -0
- package/.claude/skills/ccw-help/scripts/auto-update.py +34 -0
- package/.claude/skills/skill-generator/SKILL.md +255 -208
- package/.claude/skills/skill-generator/phases/01-requirements-discovery.md +238 -228
- package/.claude/skills/skill-generator/phases/02-structure-generation.md +261 -262
- package/.claude/skills/skill-generator/phases/03-phase-generation.md +976 -969
- package/.claude/skills/skill-generator/phases/04-specs-templates.md +398 -398
- package/.claude/skills/skill-generator/phases/05-validation.md +417 -417
- package/.claude/skills/skill-generator/specs/cli-integration.md +131 -131
- package/.claude/skills/skill-generator/specs/execution-modes.md +399 -396
- package/.claude/skills/skill-generator/specs/reference-docs-spec.md +271 -0
- package/.claude/skills/skill-generator/specs/scripting-integration.md +265 -265
- package/.claude/skills/skill-generator/specs/skill-requirements.md +466 -466
- package/.claude/skills/skill-generator/templates/autonomous-action.md +91 -88
- package/.claude/skills/skill-generator/templates/autonomous-orchestrator.md +89 -89
- package/.claude/skills/skill-generator/templates/code-analysis-action.md +148 -149
- package/.claude/skills/skill-generator/templates/llm-action.md +367 -367
- package/.claude/skills/skill-generator/templates/script-template.md +79 -79
- package/.claude/skills/skill-generator/templates/sequential-phase.md +129 -129
- package/.claude/skills/skill-generator/templates/skill-md.md +134 -75
- package/.codex/prompts/UNIFIED_EXECUTE_COMPARISON.md +205 -0
- package/.codex/prompts/analyze-with-file.md +5 -2
- package/.codex/prompts/brainstorm-to-cycle.md +4 -3
- package/.codex/prompts/brainstorm-with-file.md +6 -2
- package/.codex/prompts/clean.md +7 -2
- package/.codex/prompts/compact.md +5 -3
- package/.codex/prompts/debug-with-file.md +6 -2
- package/.codex/prompts/execute.md +6 -2
- package/.codex/prompts/issue-execute.md +10 -2
- package/.codex/prompts/issue-new.md +390 -285
- package/.codex/prompts/lite-execute.md +8 -7
- package/.codex/prompts/lite-fix.md +6 -2
- package/.codex/prompts/lite-plan-a.md +6 -2
- package/.codex/prompts/lite-plan-b.md +6 -2
- package/.codex/prompts/lite-plan-c.md +6 -2
- package/.codex/prompts/unified-execute-with-file.md +722 -0
- package/.codex/skills/codex-issue-plan-execute/SKILL.md +239 -0
- package/.codex/skills/codex-issue-plan-execute/phases/actions/action-complete.md +173 -0
- package/.codex/skills/codex-issue-plan-execute/phases/actions/action-execute.md +220 -0
- package/.codex/skills/codex-issue-plan-execute/phases/actions/action-init.md +86 -0
- package/.codex/skills/codex-issue-plan-execute/phases/actions/action-list.md +165 -0
- package/.codex/skills/codex-issue-plan-execute/phases/actions/action-plan.md +170 -0
- package/.codex/skills/codex-issue-plan-execute/phases/orchestrator.md +210 -0
- package/.codex/skills/codex-issue-plan-execute/phases/state-schema.md +136 -0
- package/.codex/skills/codex-issue-plan-execute/prompts/execution-agent-system.md +136 -0
- package/.codex/skills/codex-issue-plan-execute/prompts/execution-agent.md +135 -0
- package/.codex/skills/codex-issue-plan-execute/prompts/planning-agent-system.md +107 -0
- package/.codex/skills/codex-issue-plan-execute/prompts/planning-agent.md +122 -0
- package/.codex/skills/codex-issue-plan-execute/specs/issue-handling.md +187 -0
- package/.codex/skills/codex-issue-plan-execute/specs/quality-standards.md +231 -0
- package/.codex/skills/codex-issue-plan-execute/specs/solution-schema.md +270 -0
- package/.codex/skills/codex-issue-plan-execute/specs/subagent-roles.md +268 -0
- package/ccw/dist/cli.d.ts.map +1 -1
- package/ccw/dist/cli.js +1 -0
- package/ccw/dist/cli.js.map +1 -1
- package/ccw/dist/commands/cli.d.ts +1 -0
- package/ccw/dist/commands/cli.d.ts.map +1 -1
- package/ccw/dist/commands/cli.js +74 -6
- package/ccw/dist/commands/cli.js.map +1 -1
- package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/cli-routes.js +16 -1
- package/ccw/dist/core/routes/cli-routes.js.map +1 -1
- package/ccw/dist/core/routes/help-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/help-routes.js +51 -1
- package/ccw/dist/core/routes/help-routes.js.map +1 -1
- package/ccw/dist/tools/cli-executor-core.d.ts.map +1 -1
- package/ccw/dist/tools/cli-executor-core.js +5 -3
- package/ccw/dist/tools/cli-executor-core.js.map +1 -1
- package/ccw/dist/tools/cli-executor-utils.d.ts +1 -0
- package/ccw/dist/tools/cli-executor-utils.d.ts.map +1 -1
- package/ccw/dist/tools/cli-executor-utils.js +3 -1
- package/ccw/dist/tools/cli-executor-utils.js.map +1 -1
- package/ccw/src/cli.ts +1 -0
- package/ccw/src/commands/cli.ts +77 -6
- package/ccw/src/core/routes/cli-routes.ts +16 -1
- package/ccw/src/core/routes/help-routes.ts +60 -1
- package/ccw/src/templates/dashboard-js/views/help.js +423 -1
- package/ccw/src/tools/cli-executor-core.ts +6 -3
- package/ccw/src/tools/cli-executor-utils.ts +5 -2
- package/package.json +1 -1
|
@@ -0,0 +1,807 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: unified-execute-with-file
|
|
3
|
+
description: Universal execution engine for consuming any planning/brainstorm/analysis output with minimal progress tracking, multi-agent coordination, and incremental execution
|
|
4
|
+
argument-hint: "[-y|--yes] [-p|--plan <path>] [-m|--mode sequential|parallel] [\"execution context or task name\"]"
|
|
5
|
+
allowed-tools: TodoWrite(*), Task(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*)
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Auto Mode
|
|
9
|
+
|
|
10
|
+
When `--yes` or `-y`: Auto-confirm execution decisions, use default parallel strategy where possible.
|
|
11
|
+
|
|
12
|
+
# Workflow Unified-Execute-With-File Command (/workflow:unified-execute-with-file)
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
Universal execution engine that consumes **any** planning/brainstorm/analysis output and executes it with minimal progress tracking. Coordinates multiple agents (subagents or CLI tools), handles dependencies, and maintains execution timeline in a single minimal document.
|
|
17
|
+
|
|
18
|
+
**Core workflow**: Load Plan → Parse Tasks → Coordinate Agents → Execute → Track Progress → Verify
|
|
19
|
+
|
|
20
|
+
**Key features**:
|
|
21
|
+
- **Plan Format Agnostic**: Consumes IMPL_PLAN.md, brainstorm.md, analysis conclusions, debug resolutions
|
|
22
|
+
- **execution.md**: Single source of truth for progress, execution timeline, and results
|
|
23
|
+
- **Multi-Agent Orchestration**: Parallel execution where possible, sequential where needed
|
|
24
|
+
- **Incremental Execution**: Resume from failure point, no re-execution of completed tasks
|
|
25
|
+
- **Dependency Management**: Automatic topological sort and wait strategy
|
|
26
|
+
- **Real-Time Progress**: TodoWrite integration for live task status
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
/workflow:unified-execute-with-file [FLAGS] [EXECUTION_CONTEXT]
|
|
32
|
+
|
|
33
|
+
# Flags
|
|
34
|
+
-y, --yes Auto-confirm execution decisions, use defaults
|
|
35
|
+
-p, --plan <path> Explicitly specify plan file (auto-detected if omitted)
|
|
36
|
+
-m, --mode <mode> Execution strategy: sequential (strict order) | parallel (smart dependencies)
|
|
37
|
+
|
|
38
|
+
# Arguments
|
|
39
|
+
[execution-context] Optional: Task category, module name, or execution focus (for filtering/priority)
|
|
40
|
+
|
|
41
|
+
# Examples
|
|
42
|
+
/workflow:unified-execute-with-file # Auto-detect and execute latest plan
|
|
43
|
+
/workflow:unified-execute-with-file -p .workflow/plans/auth-plan.md # Execute specific plan
|
|
44
|
+
/workflow:unified-execute-with-file -y "auth module" # Auto-execute with context focus
|
|
45
|
+
/workflow:unified-execute-with-file -m sequential "payment feature" # Sequential execution
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Execution Process
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
Plan Detection:
|
|
52
|
+
├─ Check for IMPL_PLAN.md or task JSON files in .workflow/
|
|
53
|
+
├─ Or use explicit --plan path
|
|
54
|
+
├─ Or auto-detect from git branch/issue context
|
|
55
|
+
└─ Load plan metadata and task definitions
|
|
56
|
+
|
|
57
|
+
Session Initialization:
|
|
58
|
+
├─ Create .workflow/.execution/{sessionId}/
|
|
59
|
+
├─ Initialize execution.md with plan summary
|
|
60
|
+
├─ Parse all tasks, identify dependencies
|
|
61
|
+
├─ Determine execution strategy (parallel/sequential)
|
|
62
|
+
└─ Initialize progress tracking
|
|
63
|
+
|
|
64
|
+
Pre-Execution Validation:
|
|
65
|
+
├─ Check task feasibility (required files exist, tools available)
|
|
66
|
+
├─ Validate dependency graph (detect cycles)
|
|
67
|
+
├─ Ask user to confirm execution (unless --yes)
|
|
68
|
+
└─ Display execution plan and timeline estimate
|
|
69
|
+
|
|
70
|
+
Task Execution Loop (Parallel/Sequential):
|
|
71
|
+
├─ Select next executable tasks (dependencies satisfied)
|
|
72
|
+
├─ Launch agents in parallel (if strategy=parallel)
|
|
73
|
+
├─ Monitor execution, wait for completion
|
|
74
|
+
├─ Capture outputs, log results
|
|
75
|
+
├─ Update execution.md with progress
|
|
76
|
+
├─ Mark tasks complete/failed
|
|
77
|
+
└─ Repeat until all done or max failures reached
|
|
78
|
+
|
|
79
|
+
Error Handling:
|
|
80
|
+
├─ Task failure → Ask user: retry|skip|abort
|
|
81
|
+
├─ Dependency failure → Auto-skip dependent tasks
|
|
82
|
+
├─ Output conflict → Ask for resolution
|
|
83
|
+
└─ Timeout → Mark as timeout, continue or escalate
|
|
84
|
+
|
|
85
|
+
Completion:
|
|
86
|
+
├─ Mark session complete
|
|
87
|
+
├─ Summarize execution results in execution.md
|
|
88
|
+
├─ Generate completion report (statistics, failures, recommendations)
|
|
89
|
+
└─ Offer follow-up: review|debug|enhance
|
|
90
|
+
|
|
91
|
+
Output:
|
|
92
|
+
├─ .workflow/.execution/{sessionId}/execution.md (plan and overall status)
|
|
93
|
+
├─ .workflow/.execution/{sessionId}/execution-events.md (SINGLE SOURCE OF TRUTH - all task executions)
|
|
94
|
+
└─ Generated files in project directories (src/*, tests/*, docs/*, etc.)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Implementation
|
|
98
|
+
|
|
99
|
+
### Session Setup & Plan Detection
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
|
|
103
|
+
|
|
104
|
+
// Plan detection strategy
|
|
105
|
+
let planPath = $ARGUMENTS.match(/--plan\s+(\S+)/)?.[1]
|
|
106
|
+
|
|
107
|
+
if (!planPath) {
|
|
108
|
+
// Auto-detect: check recent workflow artifacts
|
|
109
|
+
const candidates = [
|
|
110
|
+
'.workflow/.plan/IMPL_PLAN.md',
|
|
111
|
+
'.workflow/plans/IMPL_PLAN.md',
|
|
112
|
+
'.workflow/IMPL_PLAN.md',
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
// Find most recent plan
|
|
116
|
+
planPath = findMostRecentPlan(candidates)
|
|
117
|
+
|
|
118
|
+
if (!planPath) {
|
|
119
|
+
// Check for task JSONs
|
|
120
|
+
const taskJsons = glob('.workflow/**/*.json').filter(f => f.includes('IMPL-') || f.includes('task'))
|
|
121
|
+
if (taskJsons.length > 0) {
|
|
122
|
+
planPath = taskJsons[0] // Primary task
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!planPath) {
|
|
128
|
+
AskUserQuestion({
|
|
129
|
+
questions: [{
|
|
130
|
+
question: "未找到执行规划。请选择方式:",
|
|
131
|
+
header: "Plan Source",
|
|
132
|
+
multiSelect: false,
|
|
133
|
+
options: [
|
|
134
|
+
{ label: "浏览文件", description: "从 .workflow 目录选择" },
|
|
135
|
+
{ label: "使用最近规划", description: "从git提交消息推断" },
|
|
136
|
+
{ label: "手动输入路径", description: "直接指定规划文件路径" }
|
|
137
|
+
]
|
|
138
|
+
}]
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Parse plan and extract tasks
|
|
143
|
+
const planContent = Read(planPath)
|
|
144
|
+
const plan = parsePlan(planContent, planPath) // Format-agnostic parser
|
|
145
|
+
|
|
146
|
+
const executionId = `EXEC-${plan.slug}-${getUtc8ISOString().substring(0, 10)}-${randomId(4)}`
|
|
147
|
+
const executionFolder = `.workflow/.execution/${executionId}`
|
|
148
|
+
const executionPath = `${executionFolder}/execution.md`
|
|
149
|
+
const eventLogPath = `${executionFolder}/execution-events.md`
|
|
150
|
+
|
|
151
|
+
bash(`mkdir -p ${executionFolder}`)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Plan Format Parsers
|
|
157
|
+
|
|
158
|
+
Support multiple plan sources:
|
|
159
|
+
|
|
160
|
+
```javascript
|
|
161
|
+
function parsePlan(content, filePath) {
|
|
162
|
+
const ext = filePath.split('.').pop()
|
|
163
|
+
|
|
164
|
+
if (filePath.includes('IMPL_PLAN')) {
|
|
165
|
+
return parseImplPlan(content) // From /workflow:plan
|
|
166
|
+
} else if (filePath.includes('brainstorm')) {
|
|
167
|
+
return parseBrainstormPlan(content) // From /workflow:brainstorm-with-file
|
|
168
|
+
} else if (filePath.includes('synthesis')) {
|
|
169
|
+
return parseSynthesisPlan(content) // From /workflow:brainstorm-with-file synthesis.json
|
|
170
|
+
} else if (filePath.includes('conclusions')) {
|
|
171
|
+
return parseConclusionsPlan(content) // From /workflow:analyze-with-file conclusions.json
|
|
172
|
+
} else if (filePath.endsWith('.json') && content.includes('tasks')) {
|
|
173
|
+
return parseTaskJson(content) // Direct task JSON
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
throw new Error(`Unsupported plan format: ${filePath}`)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// IMPL_PLAN.md parser
|
|
180
|
+
function parseImplPlan(content) {
|
|
181
|
+
// Extract:
|
|
182
|
+
// - Overview/summary
|
|
183
|
+
// - Phase sections
|
|
184
|
+
// - Task list with dependencies
|
|
185
|
+
// - Critical files
|
|
186
|
+
// - Execution order
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
type: 'impl-plan',
|
|
190
|
+
title: extractSection(content, 'Overview'),
|
|
191
|
+
phases: extractPhases(content),
|
|
192
|
+
tasks: extractTasks(content),
|
|
193
|
+
criticalFiles: extractCriticalFiles(content),
|
|
194
|
+
estimatedDuration: extractEstimate(content)
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Brainstorm synthesis.json parser
|
|
199
|
+
function parseSynthesisPlan(content) {
|
|
200
|
+
const synthesis = JSON.parse(content)
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
type: 'brainstorm-synthesis',
|
|
204
|
+
title: synthesis.topic,
|
|
205
|
+
ideas: synthesis.top_ideas,
|
|
206
|
+
tasks: synthesis.top_ideas.map(idea => ({
|
|
207
|
+
id: `IDEA-${slugify(idea.title)}`,
|
|
208
|
+
type: 'investigation',
|
|
209
|
+
title: idea.title,
|
|
210
|
+
description: idea.description,
|
|
211
|
+
dependencies: [],
|
|
212
|
+
agent_type: 'cli-execution-agent',
|
|
213
|
+
prompt: `Implement: ${idea.title}\n${idea.description}`,
|
|
214
|
+
expected_output: idea.next_steps
|
|
215
|
+
})),
|
|
216
|
+
recommendations: synthesis.recommendations
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### Phase 1: Plan Loading & Validation
|
|
224
|
+
|
|
225
|
+
**Step 1.1: Parse Plan and Extract Tasks**
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
const tasks = plan.tasks || parseTasksFromContent(plan)
|
|
229
|
+
|
|
230
|
+
// Normalize task structure
|
|
231
|
+
const normalizedTasks = tasks.map(task => ({
|
|
232
|
+
id: task.id || `TASK-${generateId()}`,
|
|
233
|
+
title: task.title || task.content,
|
|
234
|
+
description: task.description || task.activeForm,
|
|
235
|
+
type: task.type || inferTaskType(task), // 'code', 'test', 'doc', 'analysis', 'integration'
|
|
236
|
+
agent_type: task.agent_type || selectBestAgent(task),
|
|
237
|
+
dependencies: task.dependencies || [],
|
|
238
|
+
|
|
239
|
+
// Execution parameters
|
|
240
|
+
prompt: task.prompt || task.description,
|
|
241
|
+
files_to_modify: task.files_to_modify || [],
|
|
242
|
+
expected_output: task.expected_output || [],
|
|
243
|
+
|
|
244
|
+
// Metadata
|
|
245
|
+
priority: task.priority || 'normal',
|
|
246
|
+
parallel_safe: task.parallel_safe !== false,
|
|
247
|
+
estimated_duration: task.estimated_duration || null,
|
|
248
|
+
|
|
249
|
+
// Status tracking
|
|
250
|
+
status: 'pending',
|
|
251
|
+
attempts: 0,
|
|
252
|
+
max_retries: 2
|
|
253
|
+
}))
|
|
254
|
+
|
|
255
|
+
// Validate and detect issues
|
|
256
|
+
const validation = {
|
|
257
|
+
cycles: detectDependencyCycles(normalizedTasks),
|
|
258
|
+
missing_dependencies: findMissingDependencies(normalizedTasks),
|
|
259
|
+
file_conflicts: detectOutputConflicts(normalizedTasks),
|
|
260
|
+
warnings: []
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (validation.cycles.length > 0) {
|
|
264
|
+
throw new Error(`Circular dependencies detected: ${validation.cycles.join(', ')}`)
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Step 1.2: Create execution.md**
|
|
269
|
+
|
|
270
|
+
```markdown
|
|
271
|
+
# Execution Progress
|
|
272
|
+
|
|
273
|
+
**Execution ID**: ${executionId}
|
|
274
|
+
**Plan Source**: ${planPath}
|
|
275
|
+
**Started**: ${getUtc8ISOString()}
|
|
276
|
+
**Mode**: ${executionMode}
|
|
277
|
+
|
|
278
|
+
**Plan Summary**:
|
|
279
|
+
- Title: ${plan.title}
|
|
280
|
+
- Total Tasks: ${tasks.length}
|
|
281
|
+
- Phases: ${plan.phases?.length || 'N/A'}
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Execution Plan
|
|
286
|
+
|
|
287
|
+
### Task Overview
|
|
288
|
+
|
|
289
|
+
| Task ID | Title | Type | Agent | Dependencies | Status |
|
|
290
|
+
|---------|-------|------|-------|--------------|--------|
|
|
291
|
+
${normalizedTasks.map(t => `| ${t.id} | ${t.title} | ${t.type} | ${t.agent_type} | ${t.dependencies.join(',')} | ${t.status} |`).join('\n')}
|
|
292
|
+
|
|
293
|
+
### Dependency Graph
|
|
294
|
+
|
|
295
|
+
\`\`\`
|
|
296
|
+
${generateDependencyGraph(normalizedTasks)}
|
|
297
|
+
\`\`\`
|
|
298
|
+
|
|
299
|
+
### Execution Strategy
|
|
300
|
+
|
|
301
|
+
- **Mode**: ${executionMode}
|
|
302
|
+
- **Parallelization**: ${calculateParallel(normalizedTasks)}
|
|
303
|
+
- **Estimated Duration**: ${estimateTotalDuration(normalizedTasks)}
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Execution Timeline
|
|
308
|
+
|
|
309
|
+
*Updates as execution progresses*
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Current Status
|
|
314
|
+
|
|
315
|
+
${executionStatus()}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**Step 1.3: Pre-Execution Confirmation**
|
|
319
|
+
|
|
320
|
+
```javascript
|
|
321
|
+
const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y')
|
|
322
|
+
|
|
323
|
+
if (!autoYes) {
|
|
324
|
+
AskUserQuestion({
|
|
325
|
+
questions: [{
|
|
326
|
+
question: `准备执行 ${normalizedTasks.length} 个任务,模式: ${executionMode}\n\n关键任务:\n${normalizedTasks.slice(0, 3).map(t => `• ${t.id}: ${t.title}`).join('\n')}\n\n继续?`,
|
|
327
|
+
header: "Confirmation",
|
|
328
|
+
multiSelect: false,
|
|
329
|
+
options: [
|
|
330
|
+
{ label: "开始执行", description: "按计划执行" },
|
|
331
|
+
{ label: "调整参数", description: "修改执行参数" },
|
|
332
|
+
{ label: "查看详情", description: "查看完整任务列表" },
|
|
333
|
+
{ label: "取消", description: "退出不执行" }
|
|
334
|
+
]
|
|
335
|
+
}]
|
|
336
|
+
})
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## Phase 2: Execution Orchestration
|
|
343
|
+
|
|
344
|
+
**Step 2.1: Determine Execution Order**
|
|
345
|
+
|
|
346
|
+
```javascript
|
|
347
|
+
// Topological sort
|
|
348
|
+
const executionOrder = topologicalSort(normalizedTasks)
|
|
349
|
+
|
|
350
|
+
// For parallel mode, group tasks into waves
|
|
351
|
+
let executionWaves = []
|
|
352
|
+
if (executionMode === 'parallel') {
|
|
353
|
+
executionWaves = groupIntoWaves(executionOrder, parallelLimit = 3)
|
|
354
|
+
} else {
|
|
355
|
+
executionWaves = executionOrder.map(task => [task])
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Log execution plan to execution.md
|
|
359
|
+
// execution-events.md will track actual progress as tasks execute
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
**Step 2.2: Execute Task Waves**
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
let completedCount = 0
|
|
366
|
+
let failedCount = 0
|
|
367
|
+
const results = {}
|
|
368
|
+
|
|
369
|
+
for (let waveIndex = 0; waveIndex < executionWaves.length; waveIndex++) {
|
|
370
|
+
const wave = executionWaves[waveIndex]
|
|
371
|
+
|
|
372
|
+
console.log(`\n=== Wave ${waveIndex + 1}/${executionWaves.length} ===`)
|
|
373
|
+
console.log(`Tasks: ${wave.map(t => t.id).join(', ')}`)
|
|
374
|
+
|
|
375
|
+
// Launch tasks in parallel
|
|
376
|
+
const taskPromises = wave.map(task => executeTask(task, executionFolder))
|
|
377
|
+
|
|
378
|
+
// Wait for wave completion
|
|
379
|
+
const waveResults = await Promise.allSettled(taskPromises)
|
|
380
|
+
|
|
381
|
+
// Process results
|
|
382
|
+
for (let i = 0; i < waveResults.length; i++) {
|
|
383
|
+
const result = waveResults[i]
|
|
384
|
+
const task = wave[i]
|
|
385
|
+
|
|
386
|
+
if (result.status === 'fulfilled') {
|
|
387
|
+
results[task.id] = result.value
|
|
388
|
+
if (result.value.success) {
|
|
389
|
+
completedCount++
|
|
390
|
+
task.status = 'completed'
|
|
391
|
+
console.log(`✅ ${task.id}: Completed`)
|
|
392
|
+
} else if (result.value.retry) {
|
|
393
|
+
console.log(`⚠️ ${task.id}: Will retry`)
|
|
394
|
+
task.status = 'pending'
|
|
395
|
+
} else {
|
|
396
|
+
console.log(`❌ ${task.id}: Failed`)
|
|
397
|
+
}
|
|
398
|
+
} else {
|
|
399
|
+
console.log(`❌ ${task.id}: Execution error`)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Progress is tracked in execution-events.md (appended by executeTask)
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Update execution.md summary
|
|
406
|
+
appendExecutionTimeline(executionPath, waveIndex + 1, wave, waveResults)
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
**Step 2.3: Execute Individual Task with Unified Event Logging**
|
|
411
|
+
|
|
412
|
+
```javascript
|
|
413
|
+
async function executeTask(task, executionFolder) {
|
|
414
|
+
const eventLogPath = `${executionFolder}/execution-events.md`
|
|
415
|
+
const startTime = Date.now()
|
|
416
|
+
|
|
417
|
+
try {
|
|
418
|
+
// Read previous execution events for context
|
|
419
|
+
let previousEvents = ''
|
|
420
|
+
if (fs.existsSync(eventLogPath)) {
|
|
421
|
+
previousEvents = Read(eventLogPath)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Select agent based on task type
|
|
425
|
+
const agent = selectAgent(task.agent_type)
|
|
426
|
+
|
|
427
|
+
// Build execution context including previous agent outputs
|
|
428
|
+
const executionContext = `
|
|
429
|
+
## Previous Agent Executions (for reference)
|
|
430
|
+
|
|
431
|
+
${previousEvents}
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## Current Task: ${task.id}
|
|
436
|
+
|
|
437
|
+
**Title**: ${task.title}
|
|
438
|
+
**Agent**: ${agent}
|
|
439
|
+
**Time**: ${getUtc8ISOString()}
|
|
440
|
+
|
|
441
|
+
### Description
|
|
442
|
+
${task.description}
|
|
443
|
+
|
|
444
|
+
### Context
|
|
445
|
+
- Modified Files: ${task.files_to_modify.join(', ')}
|
|
446
|
+
- Expected Output: ${task.expected_output.join(', ')}
|
|
447
|
+
- Previous Artifacts: [list any artifacts from previous tasks]
|
|
448
|
+
|
|
449
|
+
### Requirements
|
|
450
|
+
${task.requirements || 'Follow the plan'}
|
|
451
|
+
|
|
452
|
+
### Constraints
|
|
453
|
+
${task.constraints || 'No breaking changes'}
|
|
454
|
+
`
|
|
455
|
+
|
|
456
|
+
// Execute based on agent type
|
|
457
|
+
let result
|
|
458
|
+
|
|
459
|
+
if (agent === 'code-developer' || agent === 'tdd-developer') {
|
|
460
|
+
// Code implementation
|
|
461
|
+
result = await Task({
|
|
462
|
+
subagent_type: agent,
|
|
463
|
+
description: `Execute: ${task.title}`,
|
|
464
|
+
prompt: executionContext,
|
|
465
|
+
run_in_background: false
|
|
466
|
+
})
|
|
467
|
+
} else if (agent === 'cli-execution-agent' || agent === 'universal-executor') {
|
|
468
|
+
// CLI-based execution
|
|
469
|
+
result = await Bash({
|
|
470
|
+
command: `ccw cli -p "${escapeQuotes(executionContext)}" --tool gemini --mode analysis`,
|
|
471
|
+
run_in_background: false
|
|
472
|
+
})
|
|
473
|
+
} else if (agent === 'test-fix-agent') {
|
|
474
|
+
// Test execution and fixing
|
|
475
|
+
result = await Task({
|
|
476
|
+
subagent_type: 'test-fix-agent',
|
|
477
|
+
description: `Execute Tests: ${task.title}`,
|
|
478
|
+
prompt: executionContext,
|
|
479
|
+
run_in_background: false
|
|
480
|
+
})
|
|
481
|
+
} else {
|
|
482
|
+
// Generic task execution
|
|
483
|
+
result = await Task({
|
|
484
|
+
subagent_type: 'universal-executor',
|
|
485
|
+
description: task.title,
|
|
486
|
+
prompt: executionContext,
|
|
487
|
+
run_in_background: false
|
|
488
|
+
})
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Capture artifacts (code, tests, docs generated by this task)
|
|
492
|
+
const artifacts = captureArtifacts(task, executionFolder)
|
|
493
|
+
|
|
494
|
+
// Append to unified execution events log
|
|
495
|
+
const eventEntry = `
|
|
496
|
+
## Task ${task.id} - COMPLETED ✅
|
|
497
|
+
|
|
498
|
+
**Timestamp**: ${getUtc8ISOString()}
|
|
499
|
+
**Duration**: ${calculateDuration(startTime)}ms
|
|
500
|
+
**Agent**: ${agent}
|
|
501
|
+
|
|
502
|
+
### Execution Summary
|
|
503
|
+
|
|
504
|
+
${generateSummary(result)}
|
|
505
|
+
|
|
506
|
+
### Key Outputs
|
|
507
|
+
|
|
508
|
+
${formatOutputs(result)}
|
|
509
|
+
|
|
510
|
+
### Generated Artifacts
|
|
511
|
+
|
|
512
|
+
${artifacts.map(a => `- **${a.type}**: \`${a.path}\` (${a.size})`).join('\n')}
|
|
513
|
+
|
|
514
|
+
### Notes for Next Agent
|
|
515
|
+
|
|
516
|
+
${generateNotesForNextAgent(result, task)}
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
`
|
|
520
|
+
|
|
521
|
+
appendToEventLog(eventLogPath, eventEntry)
|
|
522
|
+
|
|
523
|
+
return {
|
|
524
|
+
success: true,
|
|
525
|
+
task_id: task.id,
|
|
526
|
+
output: result,
|
|
527
|
+
artifacts: artifacts,
|
|
528
|
+
duration: calculateDuration(startTime)
|
|
529
|
+
}
|
|
530
|
+
} catch (error) {
|
|
531
|
+
// Append failure event to unified log
|
|
532
|
+
const failureEntry = `
|
|
533
|
+
## Task ${task.id} - FAILED ❌
|
|
534
|
+
|
|
535
|
+
**Timestamp**: ${getUtc8ISOString()}
|
|
536
|
+
**Duration**: ${calculateDuration(startTime)}ms
|
|
537
|
+
**Agent**: ${agent}
|
|
538
|
+
**Error**: ${error.message}
|
|
539
|
+
|
|
540
|
+
### Error Details
|
|
541
|
+
|
|
542
|
+
\`\`\`
|
|
543
|
+
${error.stack}
|
|
544
|
+
\`\`\`
|
|
545
|
+
|
|
546
|
+
### Recovery Notes for Next Attempt
|
|
547
|
+
|
|
548
|
+
${generateRecoveryNotes(error, task)}
|
|
549
|
+
|
|
550
|
+
---
|
|
551
|
+
`
|
|
552
|
+
|
|
553
|
+
appendToEventLog(eventLogPath, failureEntry)
|
|
554
|
+
|
|
555
|
+
// Handle failure: retry, skip, or abort
|
|
556
|
+
task.attempts++
|
|
557
|
+
if (task.attempts < task.max_retries && autoYes) {
|
|
558
|
+
console.log(`⚠️ ${task.id}: Failed, retrying (${task.attempts}/${task.max_retries})`)
|
|
559
|
+
return { success: false, task_id: task.id, error: error.message, retry: true, duration: calculateDuration(startTime) }
|
|
560
|
+
} else if (task.attempts >= task.max_retries && !autoYes) {
|
|
561
|
+
const decision = AskUserQuestion({
|
|
562
|
+
questions: [{
|
|
563
|
+
question: `任务失败: ${task.id}\n错误: ${error.message}`,
|
|
564
|
+
header: "Decision",
|
|
565
|
+
multiSelect: false,
|
|
566
|
+
options: [
|
|
567
|
+
{ label: "重试", description: "重新执行该任务" },
|
|
568
|
+
{ label: "跳过", description: "跳过此任务,继续下一个" },
|
|
569
|
+
{ label: "终止", description: "停止整个执行" }
|
|
570
|
+
]
|
|
571
|
+
}]
|
|
572
|
+
})
|
|
573
|
+
if (decision === 'retry') {
|
|
574
|
+
task.attempts = 0
|
|
575
|
+
return { success: false, task_id: task.id, error: error.message, retry: true, duration: calculateDuration(startTime) }
|
|
576
|
+
} else if (decision === 'skip') {
|
|
577
|
+
task.status = 'skipped'
|
|
578
|
+
skipDependentTasks(task.id, normalizedTasks)
|
|
579
|
+
} else {
|
|
580
|
+
throw new Error('Execution aborted by user')
|
|
581
|
+
}
|
|
582
|
+
} else {
|
|
583
|
+
task.status = 'failed'
|
|
584
|
+
skipDependentTasks(task.id, normalizedTasks)
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
return {
|
|
588
|
+
success: false,
|
|
589
|
+
task_id: task.id,
|
|
590
|
+
error: error.message,
|
|
591
|
+
duration: calculateDuration(startTime)
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// Helper function to append to unified event log
|
|
597
|
+
function appendToEventLog(logPath, eventEntry) {
|
|
598
|
+
if (fs.existsSync(logPath)) {
|
|
599
|
+
const currentContent = Read(logPath)
|
|
600
|
+
Write(logPath, currentContent + eventEntry)
|
|
601
|
+
} else {
|
|
602
|
+
Write(logPath, eventEntry)
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
---
|
|
608
|
+
|
|
609
|
+
## Phase 3: Progress Tracking & Event Logging
|
|
610
|
+
|
|
611
|
+
The `execution-events.md` file is the **single source of truth** for all agent executions:
|
|
612
|
+
- Each agent **reads** previous execution events for context
|
|
613
|
+
- **Executes** its task (with full knowledge of what was done before)
|
|
614
|
+
- **Writes** its execution event (success or failure) in markdown format
|
|
615
|
+
- Next agent **reads** all previous events, creating a "knowledge chain"
|
|
616
|
+
|
|
617
|
+
**Event log format** (appended entry):
|
|
618
|
+
```markdown
|
|
619
|
+
## Task {id} - {STATUS} {emoji}
|
|
620
|
+
|
|
621
|
+
**Timestamp**: {time}
|
|
622
|
+
**Duration**: {ms}
|
|
623
|
+
**Agent**: {type}
|
|
624
|
+
|
|
625
|
+
### Execution Summary
|
|
626
|
+
{What was done}
|
|
627
|
+
|
|
628
|
+
### Generated Artifacts
|
|
629
|
+
- `src/types/auth.ts` (2.3KB)
|
|
630
|
+
|
|
631
|
+
### Notes for Next Agent
|
|
632
|
+
- Key decisions made
|
|
633
|
+
- Potential issues
|
|
634
|
+
- Ready for: TASK-003
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
---
|
|
638
|
+
|
|
639
|
+
## Phase 4: Completion & Summary
|
|
640
|
+
|
|
641
|
+
After all tasks complete or max failures reached:
|
|
642
|
+
|
|
643
|
+
1. **Collect results**: Count completed/failed/skipped tasks
|
|
644
|
+
2. **Update execution.md**: Add "Execution Completed" section with statistics
|
|
645
|
+
3. **execution-events.md**: Already contains all detailed execution records
|
|
646
|
+
|
|
647
|
+
```javascript
|
|
648
|
+
const statistics = {
|
|
649
|
+
total_tasks: normalizedTasks.length,
|
|
650
|
+
completed: normalizedTasks.filter(t => t.status === 'completed').length,
|
|
651
|
+
failed: normalizedTasks.filter(t => t.status === 'failed').length,
|
|
652
|
+
skipped: normalizedTasks.filter(t => t.status === 'skipped').length,
|
|
653
|
+
success_rate: (completedCount / normalizedTasks.length * 100).toFixed(1)
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// Update execution.md with final status
|
|
657
|
+
appendExecutionSummary(executionPath, statistics)
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
**Post-Completion Options** (unless --yes):
|
|
661
|
+
|
|
662
|
+
```javascript
|
|
663
|
+
AskUserQuestion({
|
|
664
|
+
questions: [{
|
|
665
|
+
question: "执行完成。是否需要后续操作?",
|
|
666
|
+
header: "Next Steps",
|
|
667
|
+
multiSelect: true,
|
|
668
|
+
options: [
|
|
669
|
+
{ label: "查看详情", description: "查看完整执行日志" },
|
|
670
|
+
{ label: "调试失败项", description: "对失败任务进行调试" },
|
|
671
|
+
{ label: "优化执行", description: "分析执行改进建议" },
|
|
672
|
+
{ label: "完成", description: "不需要后续操作" }
|
|
673
|
+
]
|
|
674
|
+
}]
|
|
675
|
+
})
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
---
|
|
679
|
+
|
|
680
|
+
## Session Folder Structure
|
|
681
|
+
|
|
682
|
+
```
|
|
683
|
+
.workflow/.execution/{sessionId}/
|
|
684
|
+
├── execution.md # Execution plan and overall status
|
|
685
|
+
└── execution-events.md # 📋 Unified execution log (all agents) - SINGLE SOURCE OF TRUTH
|
|
686
|
+
# This is both human-readable AND machine-parseable
|
|
687
|
+
|
|
688
|
+
# Generated files go directly to project directories (not into execution folder)
|
|
689
|
+
# E.g. TASK-001 generates: src/types/auth.ts (not artifacts/src/types/auth.ts)
|
|
690
|
+
# execution-events.md records the actual project paths
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
**Key Concept**:
|
|
694
|
+
- **execution-events.md** is the **single source of truth** for execution state
|
|
695
|
+
- Human-readable: Clear markdown format with task summaries
|
|
696
|
+
- Machine-parseable: Status indicators (✅/❌/⏳) and structured sections
|
|
697
|
+
- Progress tracking: Read task count by parsing status indicators
|
|
698
|
+
- No redundancy: One unified log for all purposes
|
|
699
|
+
|
|
700
|
+
---
|
|
701
|
+
|
|
702
|
+
## Agent Selection Strategy
|
|
703
|
+
|
|
704
|
+
```javascript
|
|
705
|
+
function selectBestAgent(task) {
|
|
706
|
+
if (task.type === 'code' || task.type === 'implementation') {
|
|
707
|
+
return task.includes_tests ? 'tdd-developer' : 'code-developer'
|
|
708
|
+
} else if (task.type === 'test' || task.type === 'test-fix') {
|
|
709
|
+
return 'test-fix-agent'
|
|
710
|
+
} else if (task.type === 'doc' || task.type === 'documentation') {
|
|
711
|
+
return 'doc-generator'
|
|
712
|
+
} else if (task.type === 'analysis' || task.type === 'investigation') {
|
|
713
|
+
return 'cli-execution-agent'
|
|
714
|
+
} else if (task.type === 'debug') {
|
|
715
|
+
return 'debug-explore-agent'
|
|
716
|
+
} else {
|
|
717
|
+
return 'universal-executor'
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
## Parallelization Rules
|
|
723
|
+
|
|
724
|
+
```javascript
|
|
725
|
+
function calculateParallel(tasks) {
|
|
726
|
+
// Group tasks into execution waves
|
|
727
|
+
// Constraints:
|
|
728
|
+
// - Tasks with same file modifications must be sequential
|
|
729
|
+
// - Tasks with dependencies must wait
|
|
730
|
+
// - Max 3 parallel tasks per wave (resource constraint)
|
|
731
|
+
|
|
732
|
+
const waves = []
|
|
733
|
+
const completed = new Set()
|
|
734
|
+
|
|
735
|
+
while (completed.size < tasks.length) {
|
|
736
|
+
const available = tasks.filter(t =>
|
|
737
|
+
!completed.has(t.id) &&
|
|
738
|
+
t.dependencies.every(d => completed.has(d))
|
|
739
|
+
)
|
|
740
|
+
|
|
741
|
+
if (available.length === 0) break
|
|
742
|
+
|
|
743
|
+
// Check for file conflicts
|
|
744
|
+
const noConflict = []
|
|
745
|
+
const modifiedFiles = new Set()
|
|
746
|
+
|
|
747
|
+
for (const task of available) {
|
|
748
|
+
const conflicts = task.files_to_modify.some(f => modifiedFiles.has(f))
|
|
749
|
+
if (!conflicts && noConflict.length < 3) {
|
|
750
|
+
noConflict.push(task)
|
|
751
|
+
task.files_to_modify.forEach(f => modifiedFiles.add(f))
|
|
752
|
+
} else if (!conflicts && noConflict.length < 3) {
|
|
753
|
+
waves.push([task])
|
|
754
|
+
completed.add(task.id)
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
if (noConflict.length > 0) {
|
|
759
|
+
waves.push(noConflict)
|
|
760
|
+
noConflict.forEach(t => completed.add(t.id))
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
return waves
|
|
765
|
+
}
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
## Error Handling & Recovery
|
|
769
|
+
|
|
770
|
+
| Situation | Action |
|
|
771
|
+
|-----------|--------|
|
|
772
|
+
| Task timeout | Mark as timeout, ask user: retry/skip/abort |
|
|
773
|
+
| Missing dependency | Auto-skip dependent tasks, log warning |
|
|
774
|
+
| File conflict | Detect before execution, ask for resolution |
|
|
775
|
+
| Output mismatch | Validate against expected_output, flag for review |
|
|
776
|
+
| Agent unavailable | Fallback to universal-executor |
|
|
777
|
+
| Execution interrupted | Support resume with `/workflow:unified-execute-with-file --continue` |
|
|
778
|
+
|
|
779
|
+
## Usage Recommendations
|
|
780
|
+
|
|
781
|
+
Use `/workflow:unified-execute-with-file` when:
|
|
782
|
+
- Executing any planning document (IMPL_PLAN.md, brainstorm conclusions, analysis recommendations)
|
|
783
|
+
- Multiple tasks with dependencies need orchestration
|
|
784
|
+
- Want minimal progress tracking without clutter
|
|
785
|
+
- Need to handle failures gracefully and resume
|
|
786
|
+
- Want to parallelize where possible but ensure correctness
|
|
787
|
+
|
|
788
|
+
Use for consuming output from:
|
|
789
|
+
- `/workflow:plan` → IMPL_PLAN.md
|
|
790
|
+
- `/workflow:brainstorm-with-file` → synthesis.json → execution
|
|
791
|
+
- `/workflow:analyze-with-file` → conclusions.json → execution
|
|
792
|
+
- `/workflow:debug-with-file` → recommendations → execution
|
|
793
|
+
- `/workflow:lite-plan` → task JSONs → execution
|
|
794
|
+
|
|
795
|
+
## Session Resume
|
|
796
|
+
|
|
797
|
+
```bash
|
|
798
|
+
/workflow:unified-execute-with-file --continue # Resume last execution
|
|
799
|
+
/workflow:unified-execute-with-file --continue EXEC-xxx-2025-01-27-abcd # Resume specific
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
When resuming:
|
|
803
|
+
1. Load execution.md and execution-events.md
|
|
804
|
+
2. Parse execution-events.md to identify completed/failed/skipped tasks
|
|
805
|
+
3. Recalculate remaining dependencies
|
|
806
|
+
4. Resume from first incomplete task
|
|
807
|
+
5. Append to execution-events.md with "Resumed from [sessionId]" note
|