maestro-flow 0.4.19 → 0.4.20
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/.agents/agents/workflow-collab-planner.md +4 -1
- package/.agents/agents/workflow-plan-checker.md +11 -1
- package/.agents/agents/workflow-planner.md +4 -1
- package/.agents/skills/maestro/SKILL.md +8 -5
- package/.agents/skills/maestro-analyze/SKILL.md +1 -1
- package/.agents/skills/maestro-brainstorm/SKILL.md +2 -1
- package/.agents/skills/maestro-companion/SKILL.md +533 -0
- package/.agents/skills/maestro-grill/SKILL.md +116 -0
- package/.agents/skills/maestro-plan/SKILL.md +4 -0
- package/.agents/skills/maestro-ralph/SKILL.md +11 -7
- package/.agents/skills/maestro-swarm-workflow/SKILL.md +258 -0
- package/.agents/skills/manage-codebase-rebuild/SKILL.md +13 -1
- package/.agents/skills/manage-codebase-refresh/SKILL.md +3 -0
- package/.agents/skills/spec-setup/SKILL.md +9 -5
- package/.agy/agents/workflow-collab-planner.md +4 -1
- package/.agy/agents/workflow-plan-checker.md +11 -1
- package/.agy/agents/workflow-planner.md +4 -1
- package/.agy/skills/maestro/SKILL.md +8 -5
- package/.agy/skills/maestro-analyze/SKILL.md +1 -1
- package/.agy/skills/maestro-brainstorm/SKILL.md +2 -1
- package/.agy/skills/maestro-companion/SKILL.md +529 -0
- package/.agy/skills/maestro-grill/SKILL.md +116 -0
- package/.agy/skills/maestro-plan/SKILL.md +4 -0
- package/.agy/skills/maestro-ralph/SKILL.md +11 -7
- package/.agy/skills/maestro-swarm-workflow/SKILL.md +255 -0
- package/.agy/skills/manage-codebase-rebuild/SKILL.md +13 -1
- package/.agy/skills/manage-codebase-refresh/SKILL.md +3 -0
- package/.agy/skills/spec-setup/SKILL.md +9 -5
- package/.claude/agents/workflow-collab-planner.md +4 -1
- package/.claude/agents/workflow-plan-checker.md +11 -1
- package/.claude/agents/workflow-planner.md +4 -1
- package/.claude/commands/maestro-analyze.md +1 -1
- package/.claude/commands/maestro-brainstorm.md +2 -1
- package/.claude/commands/maestro-companion.md +531 -0
- package/.claude/commands/maestro-grill.md +114 -0
- package/.claude/commands/maestro-plan.md +4 -0
- package/.claude/commands/maestro-ralph.md +11 -7
- package/.claude/commands/maestro-swarm-workflow.md +256 -0
- package/.claude/commands/maestro.md +8 -5
- package/.claude/commands/manage-codebase-rebuild.md +13 -1
- package/.claude/commands/manage-codebase-refresh.md +3 -0
- package/.claude/commands/spec-setup.md +9 -5
- package/.codex/skills/maestro/SKILL.md +7 -2
- package/.codex/skills/maestro-companion/SKILL.md +485 -0
- package/.codex/skills/maestro-grill/SKILL.md +111 -0
- package/.codex/skills/maestro-ralph/SKILL.md +11 -7
- package/.codex/skills/manage-codebase-rebuild/SKILL.md +6 -0
- package/.codex/skills/manage-codebase-refresh/SKILL.md +6 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/graph-analysis.d.ts +36 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/graph-analysis.js +138 -2
- package/dashboard/dist-server/dashboard/src/server/wiki/graph-analysis.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/wiki/search.js +13 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/search.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/wiki/virtual-wiki-adapters.d.ts +11 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/virtual-wiki-adapters.js +178 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/virtual-wiki-adapters.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.d.ts +1 -0
- package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.js +39 -23
- package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.js.map +1 -1
- package/dist/src/cli.js +1 -0
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/install-backend.d.ts +7 -0
- package/dist/src/commands/install-backend.d.ts.map +1 -1
- package/dist/src/commands/install-backend.js +14 -0
- package/dist/src/commands/install-backend.js.map +1 -1
- package/dist/src/commands/install.d.ts.map +1 -1
- package/dist/src/commands/install.js +18 -0
- package/dist/src/commands/install.js.map +1 -1
- package/dist/src/commands/kg.d.ts +11 -0
- package/dist/src/commands/kg.d.ts.map +1 -0
- package/dist/src/commands/kg.js +515 -0
- package/dist/src/commands/kg.js.map +1 -0
- package/dist/src/i18n/locales/en.d.ts.map +1 -1
- package/dist/src/i18n/locales/en.js +10 -0
- package/dist/src/i18n/locales/en.js.map +1 -1
- package/dist/src/i18n/locales/zh.d.ts.map +1 -1
- package/dist/src/i18n/locales/zh.js +10 -0
- package/dist/src/i18n/locales/zh.js.map +1 -1
- package/dist/src/i18n/types.d.ts +9 -0
- package/dist/src/i18n/types.d.ts.map +1 -1
- package/dist/src/tui/install-ui/InstallConfirm.d.ts +1 -0
- package/dist/src/tui/install-ui/InstallConfirm.d.ts.map +1 -1
- package/dist/src/tui/install-ui/InstallConfirm.js +1 -1
- package/dist/src/tui/install-ui/InstallConfirm.js.map +1 -1
- package/dist/src/tui/install-ui/InstallExecution.d.ts +1 -0
- package/dist/src/tui/install-ui/InstallExecution.d.ts.map +1 -1
- package/dist/src/tui/install-ui/InstallExecution.js +22 -0
- package/dist/src/tui/install-ui/InstallExecution.js.map +1 -1
- package/dist/src/tui/install-ui/InstallFlow.d.ts +1 -1
- package/dist/src/tui/install-ui/InstallFlow.d.ts.map +1 -1
- package/dist/src/tui/install-ui/InstallFlow.js +23 -5
- package/dist/src/tui/install-ui/InstallFlow.js.map +1 -1
- package/dist/src/tui/install-ui/InstallHub.d.ts +2 -0
- package/dist/src/tui/install-ui/InstallHub.d.ts.map +1 -1
- package/dist/src/tui/install-ui/InstallHub.js +6 -0
- package/dist/src/tui/install-ui/InstallHub.js.map +1 -1
- package/dist/src/tui/install-ui/InstallResult.d.ts.map +1 -1
- package/dist/src/tui/install-ui/InstallResult.js +1 -1
- package/dist/src/tui/install-ui/InstallResult.js.map +1 -1
- package/dist/src/tui/install-ui/KgVendorConfig.d.ts +7 -0
- package/dist/src/tui/install-ui/KgVendorConfig.d.ts.map +1 -0
- package/dist/src/tui/install-ui/KgVendorConfig.js +9 -0
- package/dist/src/tui/install-ui/KgVendorConfig.js.map +1 -0
- package/dist/src/utils/update-notices.js +11 -0
- package/dist/src/utils/update-notices.js.map +1 -1
- package/package.json +1 -1
- package/workflows/analyze.md +2 -1
- package/workflows/brainstorm.md +24 -1
- package/workflows/codebase-rebuild.md +141 -1
- package/workflows/codebase-refresh.md +20 -0
- package/workflows/finish-work.md +7 -2
- package/workflows/grill.md +513 -0
- package/workflows/plan.md +7 -4
- package/workflows/specs-setup.md +99 -3
- package/workflows/swarm/wf-analyze.js +186 -0
- package/workflows/swarm/wf-brainstorm.js +284 -0
- package/workflows/swarm/wf-execute.js +203 -0
- package/workflows/swarm/wf-grill.js +198 -0
- package/workflows/swarm/wf-milestone-audit.js +236 -0
- package/workflows/swarm/wf-plan.js +233 -0
- package/workflows/swarm/wf-review.js +226 -0
- package/workflows/swarm/wf-verify.js +298 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'wf-analyze',
|
|
3
|
+
description: 'Multi-dimensional parallel analysis aligned with maestro-analyze 6-dimension scoring',
|
|
4
|
+
whenToUse: 'Accelerate maestro-analyze with parallel codebase exploration + dimension scoring + synthesis',
|
|
5
|
+
phases: [
|
|
6
|
+
{ title: 'Explore', detail: '3-layer codebase exploration via cli-explore-agent' },
|
|
7
|
+
{ title: 'Score', detail: 'Parallel 6-dimension scoring via workflow-analyzer' },
|
|
8
|
+
{ title: 'Synthesize', detail: 'Cross-dimension synthesis with Go/No-Go recommendation' },
|
|
9
|
+
],
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const DIMENSIONS = [
|
|
13
|
+
{ key: 'feasibility', focus: 'Technical difficulty, team capability, time constraints, tooling availability, infrastructure readiness' },
|
|
14
|
+
{ key: 'impact', focus: 'User value, business value, tech debt reduction, developer experience improvement, ecosystem contribution' },
|
|
15
|
+
{ key: 'risk', focus: 'Failure modes, security vulnerabilities, scalability limits, regression potential, data integrity threats' },
|
|
16
|
+
{ key: 'complexity', focus: 'Integration points, dependency count, learning curve, testing difficulty, migration path complexity' },
|
|
17
|
+
{ key: 'dependencies', focus: 'External services, internal module coupling, data dependencies, infrastructure requirements, third-party stability' },
|
|
18
|
+
{ key: 'alternatives', focus: 'Compare 2+ approaches with tradeoffs, evaluate build-vs-buy, assess migration paths, weigh technology options' },
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
const EXPLORATION_SCHEMA = {
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
relevant_files: { type: 'array', items: { type: 'object', properties: { path: { type: 'string' }, role: { type: 'string' }, relevance: { type: 'string' } }, required: ['path', 'role'] } },
|
|
25
|
+
call_chains: { type: 'array', items: { type: 'object', properties: { entry: { type: 'string' }, chain: { type: 'array', items: { type: 'string' } }, purpose: { type: 'string' } }, required: ['entry', 'chain'] } },
|
|
26
|
+
data_flows: { type: 'array', items: { type: 'object', properties: { source: { type: 'string' }, sink: { type: 'string' }, transforms: { type: 'array', items: { type: 'string' } } }, required: ['source', 'sink'] } },
|
|
27
|
+
code_anchors: { type: 'array', items: { type: 'object', properties: { file: { type: 'string' }, line: { type: 'number' }, snippet: { type: 'string' }, significance: { type: 'string' } }, required: ['file', 'significance'] } },
|
|
28
|
+
module_boundaries: { type: 'array', items: { type: 'object', properties: { module: { type: 'string' }, exports: { type: 'array', items: { type: 'string' } }, depends_on: { type: 'array', items: { type: 'string' } } }, required: ['module'] } },
|
|
29
|
+
},
|
|
30
|
+
required: ['relevant_files', 'code_anchors'],
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const DIMENSION_SCHEMA = {
|
|
34
|
+
type: 'object',
|
|
35
|
+
properties: {
|
|
36
|
+
dimension: { type: 'string' },
|
|
37
|
+
score: { type: 'number', minimum: 1, maximum: 5 },
|
|
38
|
+
confidence: { type: 'number', minimum: 0, maximum: 100 },
|
|
39
|
+
evidence: { type: 'array', items: { type: 'object', properties: { claim: { type: 'string' }, source: { type: 'string' }, strength: { type: 'string', enum: ['strong', 'moderate', 'weak'] } }, required: ['claim', 'source', 'strength'] } },
|
|
40
|
+
risks: { type: 'array', items: { type: 'object', properties: { risk: { type: 'string' }, probability: { type: 'string', enum: ['high', 'medium', 'low'] }, impact: { type: 'string', enum: ['critical', 'high', 'medium', 'low'] }, mitigation: { type: 'string' } }, required: ['risk', 'probability', 'impact'] } },
|
|
41
|
+
summary: { type: 'string' },
|
|
42
|
+
},
|
|
43
|
+
required: ['dimension', 'score', 'confidence', 'evidence', 'summary'],
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const SYNTHESIS_SCHEMA = {
|
|
47
|
+
type: 'object',
|
|
48
|
+
properties: {
|
|
49
|
+
overall_score: { type: 'number', minimum: 1, maximum: 5 },
|
|
50
|
+
overall_confidence: { type: 'number', minimum: 0, maximum: 100 },
|
|
51
|
+
recommendation: { type: 'string', enum: ['go', 'conditional-go', 'no-go'] },
|
|
52
|
+
scope_verdict: { type: 'string', enum: ['large', 'medium', 'small'] },
|
|
53
|
+
risk_matrix: { type: 'array', items: { type: 'object', properties: { risk: { type: 'string' }, probability: { type: 'string' }, impact: { type: 'string' }, dimension: { type: 'string' } }, required: ['risk', 'probability', 'impact', 'dimension'] } },
|
|
54
|
+
decisions: { type: 'array', items: { type: 'object', properties: { id: { type: 'string' }, decision: { type: 'string' }, status: { type: 'string', enum: ['locked', 'free', 'deferred'] }, rationale: { type: 'string' }, options_considered: { type: 'array', items: { type: 'string' } } }, required: ['id', 'decision', 'status', 'rationale'] } },
|
|
55
|
+
implementation_scope: { type: 'array', items: { type: 'object', properties: { objective: { type: 'string' }, acceptance_criteria: { type: 'string' }, priority: { type: 'string', enum: ['high', 'medium', 'low'] }, target_files: { type: 'array', items: { type: 'string' } } }, required: ['objective', 'priority'] } },
|
|
56
|
+
executive_summary: { type: 'string' },
|
|
57
|
+
},
|
|
58
|
+
required: ['overall_score', 'overall_confidence', 'recommendation', 'scope_verdict', 'risk_matrix', 'decisions', 'executive_summary'],
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const target = args?.target || 'the current codebase'
|
|
62
|
+
const scope = args?.scope || ''
|
|
63
|
+
const context = args?.context || ''
|
|
64
|
+
const phase = args?.phase || null
|
|
65
|
+
const selectedDimensions = args?.dimensions
|
|
66
|
+
? DIMENSIONS.filter(d => args.dimensions.includes(d.key))
|
|
67
|
+
: DIMENSIONS
|
|
68
|
+
|
|
69
|
+
// Phase 1: Codebase Exploration via cli-explore-agent
|
|
70
|
+
phase('Explore')
|
|
71
|
+
log('Launching 3-layer codebase exploration via cli-explore-agent...')
|
|
72
|
+
|
|
73
|
+
const exploration = await agent(
|
|
74
|
+
`Perform 3-layer codebase exploration for: ${target}
|
|
75
|
+
${scope ? 'File scope: ' + scope : 'Explore the full project structure.'}
|
|
76
|
+
${context ? 'Additional context: ' + context : ''}
|
|
77
|
+
${phase ? 'Phase context: ' + phase : ''}
|
|
78
|
+
|
|
79
|
+
Layer 1 — Module Discovery (Breadth):
|
|
80
|
+
Search by topic keywords, identify ALL relevant files, map module boundaries.
|
|
81
|
+
|
|
82
|
+
Layer 2 — Structure Tracing (Depth):
|
|
83
|
+
Top 3-5 key files: trace call chains 2-3 levels deep, identify data flow.
|
|
84
|
+
|
|
85
|
+
Layer 3 — Code Anchor Extraction (Detail):
|
|
86
|
+
Each key finding: extract code snippet (20-50 lines) with file:line reference.
|
|
87
|
+
|
|
88
|
+
Return structured exploration results.`,
|
|
89
|
+
{ label: 'explore:codebase', phase: 'Explore', schema: EXPLORATION_SCHEMA, agentType: 'cli-explore-agent' }
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
const explorationContext = exploration
|
|
93
|
+
? `Relevant files: ${exploration.relevant_files.map(f => f.path).join(', ')}
|
|
94
|
+
Call chains: ${(exploration.call_chains || []).map(c => c.entry + ' → ' + c.chain.join(' → ')).join('; ')}
|
|
95
|
+
Code anchors: ${exploration.code_anchors.map(a => a.file + ':' + (a.line || '?') + ' — ' + a.significance).join('\n')}`
|
|
96
|
+
: 'No exploration results available.'
|
|
97
|
+
|
|
98
|
+
log(`Exploration complete: ${exploration ? exploration.relevant_files.length : 0} files, ${exploration ? exploration.code_anchors.length : 0} anchors`)
|
|
99
|
+
|
|
100
|
+
// Phase 2: Parallel 6-Dimension Scoring via workflow-analyzer
|
|
101
|
+
phase('Score')
|
|
102
|
+
log(`Scoring ${selectedDimensions.length} dimensions in parallel via workflow-analyzer...`)
|
|
103
|
+
|
|
104
|
+
const scores = await parallel(
|
|
105
|
+
selectedDimensions.map(dim => () =>
|
|
106
|
+
agent(
|
|
107
|
+
`Evaluate dimension: ${dim.key}
|
|
108
|
+
Focus areas: ${dim.focus}
|
|
109
|
+
Target: ${target}
|
|
110
|
+
${phase ? 'Phase: ' + phase : ''}
|
|
111
|
+
|
|
112
|
+
Codebase exploration context:
|
|
113
|
+
${explorationContext}
|
|
114
|
+
|
|
115
|
+
Score this dimension on a 1-5 scale with specific evidence from the codebase:
|
|
116
|
+
- 1: Critical issues, blocks progress
|
|
117
|
+
- 2: Significant concerns, requires major effort
|
|
118
|
+
- 3: Manageable, standard effort required
|
|
119
|
+
- 4: Good position, minor concerns only
|
|
120
|
+
- 5: Excellent, minimal risk
|
|
121
|
+
|
|
122
|
+
Every score must have specific file:line evidence, not general impressions.
|
|
123
|
+
Include confidence percentage (0-100) based on evidence strength.
|
|
124
|
+
For Risk dimension: include probability × impact matrix entries.`,
|
|
125
|
+
{ label: `score:${dim.key}`, phase: 'Score', schema: DIMENSION_SCHEMA, agentType: 'workflow-analyzer' }
|
|
126
|
+
)
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
const validScores = scores.filter(Boolean)
|
|
131
|
+
log(`${validScores.length}/${selectedDimensions.length} dimensions scored`)
|
|
132
|
+
|
|
133
|
+
// Phase 3: Cross-Dimension Synthesis
|
|
134
|
+
phase('Synthesize')
|
|
135
|
+
|
|
136
|
+
const scoreDigest = validScores.map(s =>
|
|
137
|
+
`${s.dimension}: ${s.score}/5 (confidence: ${s.confidence}%)\n ${s.summary}\n Evidence: ${s.evidence.slice(0, 3).map(e => e.claim + ' [' + e.strength + ']').join('; ')}\n Risks: ${(s.risks || []).map(r => r.risk + ' (' + r.probability + '/' + r.impact + ')').join('; ') || 'none identified'}`
|
|
138
|
+
).join('\n\n')
|
|
139
|
+
|
|
140
|
+
const synthesis = await agent(
|
|
141
|
+
`Synthesize multi-dimensional analysis results into a Go/No-Go recommendation.
|
|
142
|
+
|
|
143
|
+
Target: ${target}
|
|
144
|
+
${phase ? 'Phase: ' + phase : ''}
|
|
145
|
+
|
|
146
|
+
Dimension Scores:
|
|
147
|
+
${scoreDigest}
|
|
148
|
+
|
|
149
|
+
Codebase Exploration:
|
|
150
|
+
${explorationContext}
|
|
151
|
+
|
|
152
|
+
Tasks:
|
|
153
|
+
1. Calculate weighted overall score (Feasibility .25, Impact .20, Risk .20, Complexity .15, Dependencies .15, Alternatives .05)
|
|
154
|
+
2. Build probability-impact risk matrix from all dimension risks
|
|
155
|
+
3. Determine scope_verdict:
|
|
156
|
+
- "large": 3+ independent subsystems or hard serial dependencies
|
|
157
|
+
- "medium": 1-2 subsystems, parallelizable
|
|
158
|
+
- "small": single-file or few-file change
|
|
159
|
+
4. Extract decisions (locked/free/deferred) based on findings
|
|
160
|
+
5. Define implementation_scope with objectives, acceptance criteria, and target files
|
|
161
|
+
6. Make Go/No-Go/Conditional-Go recommendation with confidence level
|
|
162
|
+
7. Write executive summary (2-3 paragraphs)
|
|
163
|
+
|
|
164
|
+
Recommendation rules:
|
|
165
|
+
- Any dimension at 1/5 with high confidence → no-go (unless mitigated)
|
|
166
|
+
- Average < 2.5 → no-go
|
|
167
|
+
- Average 2.5-3.5 with risks → conditional-go (list conditions)
|
|
168
|
+
- Average > 3.5 → go`,
|
|
169
|
+
{ label: 'synthesize', phase: 'Synthesize', schema: SYNTHESIS_SCHEMA, agentType: 'workflow-analyzer' }
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
exploration: exploration,
|
|
174
|
+
dimensions: validScores,
|
|
175
|
+
synthesis: synthesis,
|
|
176
|
+
metadata: {
|
|
177
|
+
target: target,
|
|
178
|
+
scope: scope,
|
|
179
|
+
phase: phase,
|
|
180
|
+
dimension_count: selectedDimensions.length,
|
|
181
|
+
completed_count: validScores.length,
|
|
182
|
+
overall_score: synthesis ? synthesis.overall_score : null,
|
|
183
|
+
recommendation: synthesis ? synthesis.recommendation : null,
|
|
184
|
+
scope_verdict: synthesis ? synthesis.scope_verdict : null,
|
|
185
|
+
},
|
|
186
|
+
}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'wf-brainstorm',
|
|
3
|
+
description: 'Multi-role parallel brainstorm with cross-role reviewer synthesis, aligned with maestro-brainstorm',
|
|
4
|
+
whenToUse: 'Accelerate maestro-brainstorm with parallel role analysis and cross-role conflict/synergy detection',
|
|
5
|
+
phases: [
|
|
6
|
+
{ title: 'Analyze', detail: 'Parallel multi-role analysis via role-design-author' },
|
|
7
|
+
{ title: 'CrossReview', detail: 'Cross-role conflict detection via cross-role-reviewer' },
|
|
8
|
+
{ title: 'Synthesize', detail: 'Resolution synthesis into guidance specification' },
|
|
9
|
+
],
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const VALID_ROLES = [
|
|
13
|
+
{ key: 'system-architect', focus: 'System design, scalability, maintainability, module boundaries, technical debt, design patterns, infrastructure' },
|
|
14
|
+
{ key: 'product-manager', focus: 'User value, market fit, MVP scope, prioritization, success metrics, stakeholder management, feature ROI' },
|
|
15
|
+
{ key: 'test-strategist', focus: 'Testability, quality assurance, test pyramid, coverage strategy, risk-based testing, regression prevention' },
|
|
16
|
+
{ key: 'ux-expert', focus: 'User experience, interaction patterns, accessibility, cognitive load, information architecture, user flows' },
|
|
17
|
+
{ key: 'subject-matter-expert', focus: 'Domain knowledge, business rules, industry standards, compliance requirements, edge cases from domain' },
|
|
18
|
+
{ key: 'data-architect', focus: 'Data modeling, storage strategy, query patterns, migration paths, data integrity, caching, consistency' },
|
|
19
|
+
{ key: 'ui-designer', focus: 'Visual design, component hierarchy, design tokens, responsive layout, motion, color and typography' },
|
|
20
|
+
{ key: 'product-owner', focus: 'Business priorities, backlog management, acceptance criteria, stakeholder value, sprint planning' },
|
|
21
|
+
{ key: 'scrum-master', focus: 'Process efficiency, team dynamics, impediment removal, delivery cadence, continuous improvement' },
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
const ROLE_ANALYSIS_SCHEMA = {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
role: { type: 'string' },
|
|
28
|
+
decision_digest: {
|
|
29
|
+
type: 'array',
|
|
30
|
+
items: {
|
|
31
|
+
type: 'object',
|
|
32
|
+
properties: {
|
|
33
|
+
id: { type: 'string' },
|
|
34
|
+
feature: { type: 'string' },
|
|
35
|
+
stance: { type: 'string' },
|
|
36
|
+
priority: { type: 'string', enum: ['must-have', 'should-have', 'nice-to-have'] },
|
|
37
|
+
rationale: { type: 'string' },
|
|
38
|
+
},
|
|
39
|
+
required: ['id', 'feature', 'stance', 'priority'],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
interfaces: {
|
|
43
|
+
type: 'array',
|
|
44
|
+
items: {
|
|
45
|
+
type: 'object',
|
|
46
|
+
properties: {
|
|
47
|
+
contract: { type: 'string' },
|
|
48
|
+
consumers: { type: 'array', items: { type: 'string' } },
|
|
49
|
+
provider: { type: 'string' },
|
|
50
|
+
},
|
|
51
|
+
required: ['contract', 'consumers'],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
cross_cutting_positions: {
|
|
55
|
+
type: 'array',
|
|
56
|
+
items: {
|
|
57
|
+
type: 'object',
|
|
58
|
+
properties: {
|
|
59
|
+
topic: { type: 'string' },
|
|
60
|
+
position: { type: 'string' },
|
|
61
|
+
strength: { type: 'string', enum: ['strong', 'moderate', 'weak'] },
|
|
62
|
+
},
|
|
63
|
+
required: ['topic', 'position', 'strength'],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
findings: {
|
|
67
|
+
type: 'array',
|
|
68
|
+
items: {
|
|
69
|
+
type: 'object',
|
|
70
|
+
properties: {
|
|
71
|
+
finding: { type: 'string' },
|
|
72
|
+
impact: { type: 'string' },
|
|
73
|
+
evidence: { type: 'string' },
|
|
74
|
+
},
|
|
75
|
+
required: ['finding', 'impact'],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
key_insight: { type: 'string' },
|
|
79
|
+
},
|
|
80
|
+
required: ['role', 'decision_digest', 'cross_cutting_positions', 'findings', 'key_insight'],
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const CROSS_REVIEW_SCHEMA = {
|
|
84
|
+
type: 'object',
|
|
85
|
+
properties: {
|
|
86
|
+
conflicts: {
|
|
87
|
+
type: 'array',
|
|
88
|
+
items: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {
|
|
91
|
+
id: { type: 'string' },
|
|
92
|
+
roles: { type: 'array', items: { type: 'string' } },
|
|
93
|
+
topic: { type: 'string' },
|
|
94
|
+
stances: { type: 'array', items: { type: 'object', properties: { role: { type: 'string' }, stance: { type: 'string' } }, required: ['role', 'stance'] } },
|
|
95
|
+
resolution_suggestion: { type: 'string' },
|
|
96
|
+
severity: { type: 'string', enum: ['blocking', 'significant', 'minor'] },
|
|
97
|
+
},
|
|
98
|
+
required: ['id', 'roles', 'topic', 'stances', 'severity'],
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
synergies: {
|
|
102
|
+
type: 'array',
|
|
103
|
+
items: {
|
|
104
|
+
type: 'object',
|
|
105
|
+
properties: {
|
|
106
|
+
roles: { type: 'array', items: { type: 'string' } },
|
|
107
|
+
topic: { type: 'string' },
|
|
108
|
+
combined_value: { type: 'string' },
|
|
109
|
+
},
|
|
110
|
+
required: ['roles', 'topic', 'combined_value'],
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
gaps: {
|
|
114
|
+
type: 'array',
|
|
115
|
+
items: {
|
|
116
|
+
type: 'object',
|
|
117
|
+
properties: {
|
|
118
|
+
area: { type: 'string' },
|
|
119
|
+
missing_perspective: { type: 'string' },
|
|
120
|
+
impact: { type: 'string' },
|
|
121
|
+
},
|
|
122
|
+
required: ['area', 'missing_perspective'],
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
required: ['conflicts', 'synergies', 'gaps'],
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const GUIDANCE_SCHEMA = {
|
|
130
|
+
type: 'object',
|
|
131
|
+
properties: {
|
|
132
|
+
guidelines: {
|
|
133
|
+
type: 'array',
|
|
134
|
+
items: {
|
|
135
|
+
type: 'object',
|
|
136
|
+
properties: {
|
|
137
|
+
id: { type: 'string' },
|
|
138
|
+
guideline: { type: 'string' },
|
|
139
|
+
category: { type: 'string', enum: ['must', 'must-not', 'should', 'should-not', 'may'] },
|
|
140
|
+
source_roles: { type: 'array', items: { type: 'string' } },
|
|
141
|
+
rationale: { type: 'string' },
|
|
142
|
+
resolved_conflict: { type: 'string' },
|
|
143
|
+
},
|
|
144
|
+
required: ['id', 'guideline', 'category', 'source_roles', 'rationale'],
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
resolved_conflicts: {
|
|
148
|
+
type: 'array',
|
|
149
|
+
items: {
|
|
150
|
+
type: 'object',
|
|
151
|
+
properties: {
|
|
152
|
+
conflict_id: { type: 'string' },
|
|
153
|
+
resolution: { type: 'string' },
|
|
154
|
+
rationale: { type: 'string' },
|
|
155
|
+
winner_role: { type: 'string' },
|
|
156
|
+
},
|
|
157
|
+
required: ['conflict_id', 'resolution', 'rationale'],
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
open_questions: { type: 'array', items: { type: 'string' } },
|
|
161
|
+
executive_summary: { type: 'string' },
|
|
162
|
+
},
|
|
163
|
+
required: ['guidelines', 'resolved_conflicts', 'executive_summary'],
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const topic = args?.topic || 'the proposed system'
|
|
167
|
+
const context = args?.context || ''
|
|
168
|
+
const roleCount = args?.count || 3
|
|
169
|
+
const selectedRoles = args?.roles
|
|
170
|
+
? VALID_ROLES.filter(r => args.roles.includes(r.key))
|
|
171
|
+
: VALID_ROLES.slice(0, roleCount)
|
|
172
|
+
|
|
173
|
+
// Phase 1: Parallel multi-role analysis via role-design-author
|
|
174
|
+
phase('Analyze')
|
|
175
|
+
log(`Launching ${selectedRoles.length} role analyses in parallel via role-design-author...`)
|
|
176
|
+
|
|
177
|
+
const analyses = await parallel(
|
|
178
|
+
selectedRoles.map(role => () =>
|
|
179
|
+
agent(
|
|
180
|
+
`You are the ${role.key} role analyzing: ${topic}
|
|
181
|
+
${context ? 'Context: ' + context : ''}
|
|
182
|
+
|
|
183
|
+
Your focus areas: ${role.focus}
|
|
184
|
+
|
|
185
|
+
Produce a structured role analysis with:
|
|
186
|
+
1. Decision Digest — your stances on each feature/aspect (id, feature, stance, priority, rationale)
|
|
187
|
+
2. Interfaces — contracts you propose/consume (contract, consumers, provider)
|
|
188
|
+
3. Cross-Cutting Positions — your stance on shared topics (topic, position, strength)
|
|
189
|
+
4. Findings — discoveries with impact and evidence
|
|
190
|
+
5. Key Insight — your single most important observation
|
|
191
|
+
|
|
192
|
+
Read relevant source files if needed to ground your analysis in reality.
|
|
193
|
+
Be specific and opinionated — take clear stances with rationale.`,
|
|
194
|
+
{ label: `role:${role.key}`, phase: 'Analyze', schema: ROLE_ANALYSIS_SCHEMA, agentType: 'role-design-author' }
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
const validAnalyses = analyses.filter(Boolean)
|
|
200
|
+
log(`${validAnalyses.length}/${selectedRoles.length} role analyses completed`)
|
|
201
|
+
|
|
202
|
+
// Phase 2: Cross-role review via cross-role-reviewer
|
|
203
|
+
phase('CrossReview')
|
|
204
|
+
log('Cross-role conflict and synergy detection...')
|
|
205
|
+
|
|
206
|
+
const analysesDigest = validAnalyses.map(a => {
|
|
207
|
+
const decisions = a.decision_digest.map(d => ` ${d.id}: [${d.priority}] ${d.feature} — ${d.stance}`).join('\n')
|
|
208
|
+
const positions = a.cross_cutting_positions.map(p => ` ${p.topic}: ${p.position} [${p.strength}]`).join('\n')
|
|
209
|
+
const findings = a.findings.map(f => ` - ${f.finding} (impact: ${f.impact})`).join('\n')
|
|
210
|
+
return `## ${a.role}\nKey insight: ${a.key_insight}\n\nDecisions:\n${decisions}\n\nPositions:\n${positions}\n\nFindings:\n${findings}`
|
|
211
|
+
}).join('\n\n---\n\n')
|
|
212
|
+
|
|
213
|
+
const crossReview = await agent(
|
|
214
|
+
`Compare these ${validAnalyses.length} role analyses for conflicts, gaps, and synergies.
|
|
215
|
+
|
|
216
|
+
${analysesDigest}
|
|
217
|
+
|
|
218
|
+
Identify:
|
|
219
|
+
1. CONFLICTS: Same feature/topic with contradictory stances between roles. Include severity (blocking/significant/minor).
|
|
220
|
+
2. SYNERGIES: Compatible positions that reinforce each other when combined.
|
|
221
|
+
3. GAPS: Areas where an important perspective is missing — a topic addressed by one role but not by another that should.
|
|
222
|
+
|
|
223
|
+
For each conflict, suggest a resolution direction.`,
|
|
224
|
+
{ label: 'cross-review', phase: 'CrossReview', schema: CROSS_REVIEW_SCHEMA, agentType: 'cross-role-reviewer' }
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
// Phase 3: Synthesis into guidance specification
|
|
228
|
+
phase('Synthesize')
|
|
229
|
+
log('Synthesizing guidance specification...')
|
|
230
|
+
|
|
231
|
+
const conflictDigest = crossReview.conflicts.map(c =>
|
|
232
|
+
`[${c.severity}] ${c.topic}: ${c.stances.map(s => s.role + '→' + s.stance).join(' vs ')}\n Suggestion: ${c.resolution_suggestion}`
|
|
233
|
+
).join('\n')
|
|
234
|
+
|
|
235
|
+
const synergyDigest = crossReview.synergies.map(s =>
|
|
236
|
+
`${s.roles.join(' + ')}: ${s.topic} — ${s.combined_value}`
|
|
237
|
+
).join('\n')
|
|
238
|
+
|
|
239
|
+
const guidance = await agent(
|
|
240
|
+
`Synthesize a unified guidance specification from multi-role brainstorm results.
|
|
241
|
+
|
|
242
|
+
Topic: ${topic}
|
|
243
|
+
|
|
244
|
+
Role Analyses:
|
|
245
|
+
${analysesDigest}
|
|
246
|
+
|
|
247
|
+
Cross-Review Findings:
|
|
248
|
+
Conflicts (${crossReview.conflicts.length}):
|
|
249
|
+
${conflictDigest || 'None'}
|
|
250
|
+
|
|
251
|
+
Synergies (${crossReview.synergies.length}):
|
|
252
|
+
${synergyDigest || 'None'}
|
|
253
|
+
|
|
254
|
+
Gaps: ${crossReview.gaps.map(g => g.area + ' — missing ' + g.missing_perspective).join('; ') || 'None'}
|
|
255
|
+
|
|
256
|
+
Produce:
|
|
257
|
+
1. Unified guidelines using RFC-2119 categories (MUST, MUST NOT, SHOULD, SHOULD NOT, MAY)
|
|
258
|
+
2. For each conflict: resolve by weighing evidence strength, severity, and downstream impact
|
|
259
|
+
3. Attribute each guideline to source roles
|
|
260
|
+
4. List remaining open questions that need user input
|
|
261
|
+
5. Executive summary (2-3 paragraphs)
|
|
262
|
+
|
|
263
|
+
Priority rules for conflict resolution:
|
|
264
|
+
- Security > correctness > user experience > performance > convenience
|
|
265
|
+
- "must-have" from multiple roles > "must-have" from single role
|
|
266
|
+
- Stances with strong evidence > moderate > weak`,
|
|
267
|
+
{ label: 'guidance', phase: 'Synthesize', schema: GUIDANCE_SCHEMA }
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
return {
|
|
271
|
+
analyses: validAnalyses,
|
|
272
|
+
crossReview: crossReview,
|
|
273
|
+
guidance: guidance,
|
|
274
|
+
metadata: {
|
|
275
|
+
topic: topic,
|
|
276
|
+
role_count: selectedRoles.length,
|
|
277
|
+
completed_count: validAnalyses.length,
|
|
278
|
+
conflict_count: crossReview.conflicts.length,
|
|
279
|
+
blocking_conflicts: crossReview.conflicts.filter(c => c.severity === 'blocking').length,
|
|
280
|
+
synergy_count: crossReview.synergies.length,
|
|
281
|
+
gap_count: crossReview.gaps.length,
|
|
282
|
+
guideline_count: guidance ? guidance.guidelines.length : 0,
|
|
283
|
+
},
|
|
284
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'wf-execute',
|
|
3
|
+
description: 'Wave-based parallel task execution via workflow-executor agents',
|
|
4
|
+
whenToUse: 'Accelerate maestro-execute with parallel task implementation within waves',
|
|
5
|
+
phases: [
|
|
6
|
+
{ title: 'Load', detail: 'Load plan and resolve task dependencies' },
|
|
7
|
+
{ title: 'Execute', detail: 'Wave-based parallel task execution via workflow-executor' },
|
|
8
|
+
{ title: 'Report', detail: 'Execution summary and status collection' },
|
|
9
|
+
],
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const TASK_RESULT_SCHEMA = {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
task_id: { type: 'string' },
|
|
16
|
+
status: { type: 'string', enum: ['completed', 'failed', 'blocked'] },
|
|
17
|
+
files_changed: { type: 'array', items: { type: 'string' } },
|
|
18
|
+
summary: { type: 'string' },
|
|
19
|
+
convergence_met: { type: 'boolean' },
|
|
20
|
+
unmet_criteria: { type: 'array', items: { type: 'string' } },
|
|
21
|
+
commit_hash: { type: 'string' },
|
|
22
|
+
error: { type: 'string' },
|
|
23
|
+
},
|
|
24
|
+
required: ['task_id', 'status', 'summary'],
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const REPORT_SCHEMA = {
|
|
28
|
+
type: 'object',
|
|
29
|
+
properties: {
|
|
30
|
+
status: { type: 'string', enum: ['DONE', 'DONE_WITH_CONCERNS', 'NEEDS_RETRY'] },
|
|
31
|
+
total_tasks: { type: 'number' },
|
|
32
|
+
completed: { type: 'number' },
|
|
33
|
+
failed: { type: 'number' },
|
|
34
|
+
blocked: { type: 'number' },
|
|
35
|
+
waves_executed: { type: 'number' },
|
|
36
|
+
files_changed: { type: 'array', items: { type: 'string' } },
|
|
37
|
+
failed_tasks: { type: 'array', items: { type: 'object', properties: { task_id: { type: 'string' }, error: { type: 'string' }, unmet_criteria: { type: 'array', items: { type: 'string' } } }, required: ['task_id'] } },
|
|
38
|
+
summary: { type: 'string' },
|
|
39
|
+
},
|
|
40
|
+
required: ['status', 'total_tasks', 'completed', 'failed', 'summary'],
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const planDir = args?.plan_dir || ''
|
|
44
|
+
const specs = args?.specs || ''
|
|
45
|
+
const codebaseContext = args?.codebase_context || ''
|
|
46
|
+
const wikiContext = args?.wiki_context || ''
|
|
47
|
+
const autoCommit = args?.auto_commit !== false
|
|
48
|
+
|
|
49
|
+
// Phase 1: Load plan and resolve waves
|
|
50
|
+
phase('Load')
|
|
51
|
+
log('Loading plan and resolving task dependency waves...')
|
|
52
|
+
|
|
53
|
+
const planLoad = await agent(
|
|
54
|
+
`Load the execution plan and resolve task waves.
|
|
55
|
+
|
|
56
|
+
Plan directory: ${planDir || 'Find the most recent pending plan in .workflow/scratch/'}
|
|
57
|
+
|
|
58
|
+
Steps:
|
|
59
|
+
1. Read plan.json to get task_ids[], waves[], approach
|
|
60
|
+
2. Read each .task/TASK-{NNN}.json to get: description, scope, focus_paths, depends_on, convergence.criteria, files[], implementation[], read_first[], test.commands
|
|
61
|
+
3. Verify dependency order: tasks in wave N must have all depends_on satisfied by waves < N
|
|
62
|
+
4. Filter: only include tasks with status="pending" (skip completed/blocked)
|
|
63
|
+
5. Return the wave structure with full task context for each pending task
|
|
64
|
+
|
|
65
|
+
Return the complete wave plan as structured data.`,
|
|
66
|
+
{
|
|
67
|
+
label: 'load:plan',
|
|
68
|
+
phase: 'Load',
|
|
69
|
+
schema: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
properties: {
|
|
72
|
+
plan_dir: { type: 'string' },
|
|
73
|
+
plan_summary: { type: 'string' },
|
|
74
|
+
waves: {
|
|
75
|
+
type: 'array',
|
|
76
|
+
items: {
|
|
77
|
+
type: 'object',
|
|
78
|
+
properties: {
|
|
79
|
+
wave_index: { type: 'number' },
|
|
80
|
+
tasks: {
|
|
81
|
+
type: 'array',
|
|
82
|
+
items: {
|
|
83
|
+
type: 'object',
|
|
84
|
+
properties: {
|
|
85
|
+
task_id: { type: 'string' },
|
|
86
|
+
description: { type: 'string' },
|
|
87
|
+
scope: { type: 'string' },
|
|
88
|
+
focus_paths: { type: 'array', items: { type: 'string' } },
|
|
89
|
+
depends_on: { type: 'array', items: { type: 'string' } },
|
|
90
|
+
convergence_criteria: { type: 'array', items: { type: 'string' } },
|
|
91
|
+
test_commands: { type: 'array', items: { type: 'string' } },
|
|
92
|
+
files_to_create: { type: 'array', items: { type: 'string' } },
|
|
93
|
+
},
|
|
94
|
+
required: ['task_id', 'description'],
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
required: ['wave_index', 'tasks'],
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
total_pending: { type: 'number' },
|
|
102
|
+
},
|
|
103
|
+
required: ['plan_dir', 'waves', 'total_pending'],
|
|
104
|
+
},
|
|
105
|
+
agentType: 'workflow-planner',
|
|
106
|
+
}
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if (!planLoad || !planLoad.waves || planLoad.waves.length === 0) {
|
|
110
|
+
log('No pending tasks found')
|
|
111
|
+
return { report: { status: 'DONE', total_tasks: 0, completed: 0, failed: 0, summary: 'No pending tasks.' }, metadata: { waves_executed: 0 } }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
log(`Plan loaded: ${planLoad.total_pending} pending tasks across ${planLoad.waves.length} waves`)
|
|
115
|
+
|
|
116
|
+
// Phase 2: Execute waves sequentially, tasks within each wave in parallel
|
|
117
|
+
phase('Execute')
|
|
118
|
+
|
|
119
|
+
const allResults = []
|
|
120
|
+
let waveIndex = 0
|
|
121
|
+
|
|
122
|
+
for (const wave of planLoad.waves) {
|
|
123
|
+
waveIndex++
|
|
124
|
+
log(`Wave ${waveIndex}/${planLoad.waves.length}: executing ${wave.tasks.length} tasks in parallel...`)
|
|
125
|
+
|
|
126
|
+
const waveResults = await parallel(
|
|
127
|
+
wave.tasks.map(task => () =>
|
|
128
|
+
agent(
|
|
129
|
+
`Execute task: ${task.task_id}
|
|
130
|
+
Description: ${task.description}
|
|
131
|
+
Scope: ${task.scope || 'project root'}
|
|
132
|
+
Focus paths: ${(task.focus_paths || []).join(', ') || 'see task JSON'}
|
|
133
|
+
Plan directory: ${planLoad.plan_dir}
|
|
134
|
+
|
|
135
|
+
${specs ? 'Project specs (MUST comply):\n' + specs : ''}
|
|
136
|
+
${codebaseContext ? 'Codebase architecture:\n' + codebaseContext : ''}
|
|
137
|
+
${wikiContext ? 'Wiki knowledge:\n' + wikiContext : ''}
|
|
138
|
+
|
|
139
|
+
Process:
|
|
140
|
+
1. Read the full task JSON at ${planLoad.plan_dir}/.task/${task.task_id}.json
|
|
141
|
+
2. Read all files in read_first[] before any modification
|
|
142
|
+
3. Read reference.files for patterns to follow
|
|
143
|
+
4. Implement changes following implementation[] steps in order
|
|
144
|
+
5. Verify every convergence criterion: ${(task.convergence_criteria || []).join('; ') || 'see task JSON'}
|
|
145
|
+
6. Run test commands: ${(task.test_commands || []).join('; ') || 'none defined'}
|
|
146
|
+
${autoCommit ? '7. Create atomic git commit with message referencing ' + task.task_id : ''}
|
|
147
|
+
8. Write summary to ${planLoad.plan_dir}/.summaries/${task.task_id}-summary.md
|
|
148
|
+
9. Update task status to "completed" in the task JSON
|
|
149
|
+
|
|
150
|
+
Stay within scope. Do not modify files outside focus_paths unless explicitly required by the task.`,
|
|
151
|
+
{ label: `exec:${task.task_id}`, phase: 'Execute', schema: TASK_RESULT_SCHEMA, agentType: 'workflow-executor', isolation: 'worktree' }
|
|
152
|
+
)
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
allResults.push(...waveResults.filter(Boolean))
|
|
157
|
+
|
|
158
|
+
const waveFailed = waveResults.filter(r => r && r.status === 'failed')
|
|
159
|
+
if (waveFailed.length > 0) {
|
|
160
|
+
log(`Wave ${waveIndex}: ${waveFailed.length} tasks failed — ${waveFailed.map(f => f.task_id).join(', ')}`)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Phase 3: Execution report
|
|
165
|
+
phase('Report')
|
|
166
|
+
|
|
167
|
+
const completed = allResults.filter(r => r.status === 'completed')
|
|
168
|
+
const failed = allResults.filter(r => r.status === 'failed')
|
|
169
|
+
const blocked = allResults.filter(r => r.status === 'blocked')
|
|
170
|
+
|
|
171
|
+
const report = await agent(
|
|
172
|
+
`Generate execution report.
|
|
173
|
+
|
|
174
|
+
Results: ${completed.length} completed, ${failed.length} failed, ${blocked.length} blocked out of ${planLoad.total_pending} total.
|
|
175
|
+
|
|
176
|
+
Completed tasks:
|
|
177
|
+
${completed.map(r => `- ${r.task_id}: ${r.summary} (${(r.files_changed || []).length} files)`).join('\n') || 'None'}
|
|
178
|
+
|
|
179
|
+
Failed tasks:
|
|
180
|
+
${failed.map(r => `- ${r.task_id}: ${r.error || r.summary}\n Unmet: ${(r.unmet_criteria || []).join(', ') || 'unknown'}`).join('\n') || 'None'}
|
|
181
|
+
|
|
182
|
+
Determine:
|
|
183
|
+
- DONE: all tasks completed, no failures
|
|
184
|
+
- DONE_WITH_CONCERNS: some failures but majority succeeded
|
|
185
|
+
- NEEDS_RETRY: critical failures blocking downstream work
|
|
186
|
+
|
|
187
|
+
Summarize what was accomplished and what needs attention.`,
|
|
188
|
+
{ label: 'report', phase: 'Report', schema: REPORT_SCHEMA }
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
report: report,
|
|
193
|
+
results: allResults,
|
|
194
|
+
metadata: {
|
|
195
|
+
plan_dir: planLoad.plan_dir,
|
|
196
|
+
waves_executed: waveIndex,
|
|
197
|
+
total_tasks: planLoad.total_pending,
|
|
198
|
+
completed: completed.length,
|
|
199
|
+
failed: failed.length,
|
|
200
|
+
blocked: blocked.length,
|
|
201
|
+
all_files_changed: completed.flatMap(r => r.files_changed || []),
|
|
202
|
+
},
|
|
203
|
+
}
|