maestro-flow 0.4.19 → 0.4.21
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-ralph-execute/SKILL.md +2 -1
- package/.agents/skills/maestro-swarm-workflow/SKILL.md +266 -0
- package/.agents/skills/maestro-universal-workflow/SKILL.md +563 -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/.agents/skills/team-adversarial-swarm/SKILL.md +235 -0
- package/.agents/skills/team-adversarial-swarm/scripts/aco.py +473 -0
- package/.agents/skills/team-adversarial-swarm/scripts/pheromone.py +144 -0
- package/.agents/skills/team-adversarial-swarm/scripts/scoring.py +92 -0
- package/.agents/skills/team-adversarial-swarm/scripts/test_aco.py +475 -0
- package/.agents/skills/team-adversarial-swarm/specs/ant-output-schema.md +115 -0
- package/.agents/skills/team-adversarial-swarm/specs/convergence-criteria.md +75 -0
- package/.agents/skills/team-adversarial-swarm/specs/pheromone-schema.md +90 -0
- package/.agents/skills/team-adversarial-swarm/specs/swarm-config-template.json +66 -0
- package/.agents/skills/team-adversarial-swarm/specs/swarm-protocol.md +105 -0
- package/.agents/skills/team-adversarial-swarm/workflows/wf-swarm-converge.js +197 -0
- package/.agents/skills/team-adversarial-swarm/workflows/wf-swarm-explore.js +194 -0
- package/.agents/skills/team-adversarial-swarm/workflows/wf-swarm-score.js +188 -0
- package/.agents/skills/team-adversarial-swarm/workflows/wf-swarm-synthesize.js +248 -0
- 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-ralph-execute/SKILL.md +2 -1
- package/.agy/skills/maestro-swarm-workflow/SKILL.md +263 -0
- package/.agy/skills/maestro-universal-workflow/SKILL.md +560 -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/.agy/skills/team-adversarial-swarm/SKILL.md +244 -0
- package/.agy/skills/team-adversarial-swarm/scripts/aco.py +473 -0
- package/.agy/skills/team-adversarial-swarm/scripts/pheromone.py +144 -0
- package/.agy/skills/team-adversarial-swarm/scripts/scoring.py +92 -0
- package/.agy/skills/team-adversarial-swarm/scripts/test_aco.py +475 -0
- package/.agy/skills/team-adversarial-swarm/specs/ant-output-schema.md +115 -0
- package/.agy/skills/team-adversarial-swarm/specs/convergence-criteria.md +75 -0
- package/.agy/skills/team-adversarial-swarm/specs/pheromone-schema.md +90 -0
- package/.agy/skills/team-adversarial-swarm/specs/swarm-config-template.json +66 -0
- package/.agy/skills/team-adversarial-swarm/specs/swarm-protocol.md +105 -0
- package/.agy/skills/team-adversarial-swarm/workflows/wf-swarm-converge.js +197 -0
- package/.agy/skills/team-adversarial-swarm/workflows/wf-swarm-explore.js +194 -0
- package/.agy/skills/team-adversarial-swarm/workflows/wf-swarm-score.js +188 -0
- package/.agy/skills/team-adversarial-swarm/workflows/wf-swarm-synthesize.js +248 -0
- 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-execute.md +2 -1
- package/.claude/commands/maestro-ralph.md +11 -7
- package/.claude/commands/maestro-swarm-workflow.md +264 -0
- package/.claude/commands/maestro-universal-workflow.md +561 -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/.claude/skills/team-adversarial-swarm/SKILL.md +233 -0
- package/.claude/skills/team-adversarial-swarm/scripts/aco.py +473 -0
- package/.claude/skills/team-adversarial-swarm/scripts/pheromone.py +144 -0
- package/.claude/skills/team-adversarial-swarm/scripts/scoring.py +92 -0
- package/.claude/skills/team-adversarial-swarm/scripts/test_aco.py +475 -0
- package/.claude/skills/team-adversarial-swarm/specs/ant-output-schema.md +115 -0
- package/.claude/skills/team-adversarial-swarm/specs/convergence-criteria.md +75 -0
- package/.claude/skills/team-adversarial-swarm/specs/pheromone-schema.md +90 -0
- package/.claude/skills/team-adversarial-swarm/specs/swarm-config-template.json +66 -0
- package/.claude/skills/team-adversarial-swarm/specs/swarm-protocol.md +105 -0
- package/.claude/skills/team-adversarial-swarm/workflows/wf-swarm-converge.js +197 -0
- package/.claude/skills/team-adversarial-swarm/workflows/wf-swarm-explore.js +194 -0
- package/.claude/skills/team-adversarial-swarm/workflows/wf-swarm-score.js +188 -0
- package/.claude/skills/team-adversarial-swarm/workflows/wf-swarm-synthesize.js +248 -0
- 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/dashboard/dist-server/src/graph/types.d.ts +111 -0
- package/dashboard/dist-server/src/graph/types.js +2 -0
- package/dashboard/dist-server/src/graph/types.js.map +1 -0
- package/dist/src/cli.js +1 -0
- package/dist/src/cli.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 +486 -0
- package/dist/src/commands/kg.js.map +1 -0
- package/dist/src/graph/analyzers/fs-analyzer.d.ts +10 -0
- package/dist/src/graph/analyzers/fs-analyzer.d.ts.map +1 -0
- package/dist/src/graph/analyzers/fs-analyzer.js +959 -0
- package/dist/src/graph/analyzers/fs-analyzer.js.map +1 -0
- package/dist/src/graph/index.d.ts +6 -0
- package/dist/src/graph/index.d.ts.map +1 -0
- package/dist/src/graph/index.js +6 -0
- package/dist/src/graph/index.js.map +1 -0
- package/dist/src/graph/loader.d.ts +3 -0
- package/dist/src/graph/loader.d.ts.map +1 -0
- package/dist/src/graph/loader.js +12 -0
- package/dist/src/graph/loader.js.map +1 -0
- package/dist/src/graph/merger.d.ts +56 -0
- package/dist/src/graph/merger.d.ts.map +1 -0
- package/dist/src/graph/merger.js +896 -0
- package/dist/src/graph/merger.js.map +1 -0
- package/dist/src/graph/query.d.ts +7 -0
- package/dist/src/graph/query.d.ts.map +1 -0
- package/dist/src/graph/query.js +126 -0
- package/dist/src/graph/query.js.map +1 -0
- package/dist/src/graph/types.d.ts +112 -0
- package/dist/src/graph/types.d.ts.map +1 -0
- package/dist/src/graph/types.js +2 -0
- package/dist/src/graph/types.js.map +1 -0
- 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 +23 -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 +347 -0
- package/workflows/swarm/wf-brainstorm.js +456 -0
- package/workflows/swarm/wf-execute.js +379 -0
- package/workflows/swarm/wf-grill.js +359 -0
- package/workflows/swarm/wf-milestone-audit.js +385 -0
- package/workflows/swarm/wf-plan.js +468 -0
- package/workflows/swarm/wf-review.js +341 -0
- package/workflows/swarm/wf-verify.js +395 -0
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'wf-execute',
|
|
3
|
+
description: 'Wave-based parallel execution with adversarial convergence verification and 3-vote status determination',
|
|
4
|
+
whenToUse: 'Accelerate maestro-execute with parallel task implementation + adversarial convergence checks + 3-vote report',
|
|
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: 'VerifyConvergence', detail: 'Adversarial spot-check of convergence claims' },
|
|
9
|
+
{ title: 'Report', detail: '3-vote status determination (optimist/pessimist/realist)' },
|
|
10
|
+
],
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const TASK_RESULT_SCHEMA = {
|
|
14
|
+
type: 'object',
|
|
15
|
+
properties: {
|
|
16
|
+
task_id: { type: 'string' },
|
|
17
|
+
status: { type: 'string', enum: ['completed', 'failed', 'blocked'] },
|
|
18
|
+
files_changed: { type: 'array', items: { type: 'string' } },
|
|
19
|
+
summary: { type: 'string' },
|
|
20
|
+
convergence_met: { type: 'boolean' },
|
|
21
|
+
unmet_criteria: { type: 'array', items: { type: 'string' } },
|
|
22
|
+
commit_hash: { type: 'string' },
|
|
23
|
+
error: { type: 'string' },
|
|
24
|
+
},
|
|
25
|
+
required: ['task_id', 'status', 'summary'],
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const CONVERGENCE_CHECK_SCHEMA = {
|
|
29
|
+
type: 'object',
|
|
30
|
+
properties: {
|
|
31
|
+
task_id: { type: 'string' },
|
|
32
|
+
claimed_complete: { type: 'boolean' },
|
|
33
|
+
actually_complete: { type: 'boolean' },
|
|
34
|
+
checks: {
|
|
35
|
+
type: 'array',
|
|
36
|
+
items: {
|
|
37
|
+
type: 'object',
|
|
38
|
+
properties: {
|
|
39
|
+
criterion: { type: 'string' },
|
|
40
|
+
claimed: { type: 'boolean' },
|
|
41
|
+
verified: { type: 'boolean' },
|
|
42
|
+
evidence: { type: 'string' },
|
|
43
|
+
discrepancy: { type: 'string' },
|
|
44
|
+
},
|
|
45
|
+
required: ['criterion', 'claimed', 'verified', 'evidence'],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
trust_score: { type: 'number', minimum: 0, maximum: 100 },
|
|
49
|
+
assessment: { type: 'string' },
|
|
50
|
+
},
|
|
51
|
+
required: ['task_id', 'claimed_complete', 'actually_complete', 'checks', 'trust_score'],
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const STATUS_VOTE_SCHEMA = {
|
|
55
|
+
type: 'object',
|
|
56
|
+
properties: {
|
|
57
|
+
perspective: { type: 'string' },
|
|
58
|
+
status: { type: 'string', enum: ['DONE', 'DONE_WITH_CONCERNS', 'NEEDS_RETRY'] },
|
|
59
|
+
rationale: { type: 'string' },
|
|
60
|
+
confidence: { type: 'number', minimum: 0, maximum: 100 },
|
|
61
|
+
blocking_concerns: { type: 'array', items: { type: 'string' } },
|
|
62
|
+
},
|
|
63
|
+
required: ['perspective', 'status', 'rationale', 'confidence'],
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const REPORT_SCHEMA = {
|
|
67
|
+
type: 'object',
|
|
68
|
+
properties: {
|
|
69
|
+
status: { type: 'string', enum: ['DONE', 'DONE_WITH_CONCERNS', 'NEEDS_RETRY'] },
|
|
70
|
+
total_tasks: { type: 'number' },
|
|
71
|
+
completed: { type: 'number' },
|
|
72
|
+
failed: { type: 'number' },
|
|
73
|
+
blocked: { type: 'number' },
|
|
74
|
+
waves_executed: { type: 'number' },
|
|
75
|
+
files_changed: { type: 'array', items: { type: 'string' } },
|
|
76
|
+
adversarial_outcome: {
|
|
77
|
+
type: 'object',
|
|
78
|
+
properties: {
|
|
79
|
+
optimist: { type: 'string' },
|
|
80
|
+
pessimist: { type: 'string' },
|
|
81
|
+
realist: { type: 'string' },
|
|
82
|
+
convergence_trust: { type: 'number' },
|
|
83
|
+
decisive_factor: { type: 'string' },
|
|
84
|
+
},
|
|
85
|
+
required: ['optimist', 'pessimist', 'realist', 'decisive_factor'],
|
|
86
|
+
},
|
|
87
|
+
convergence_discrepancies: { type: 'array', items: { type: 'object', properties: { task_id: { type: 'string' }, criterion: { type: 'string' }, discrepancy: { type: 'string' } }, required: ['task_id', 'criterion'] } },
|
|
88
|
+
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'] } },
|
|
89
|
+
summary: { type: 'string' },
|
|
90
|
+
},
|
|
91
|
+
required: ['status', 'total_tasks', 'completed', 'failed', 'adversarial_outcome', 'summary'],
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const planDir = args?.plan_dir || ''
|
|
95
|
+
const specs = args?.specs || ''
|
|
96
|
+
const codebaseContext = args?.codebase_context || ''
|
|
97
|
+
const wikiContext = args?.wiki_context || ''
|
|
98
|
+
const autoCommit = args?.auto_commit !== false
|
|
99
|
+
|
|
100
|
+
// Phase 1: Load plan
|
|
101
|
+
phase('Load')
|
|
102
|
+
log('Loading plan and resolving task dependency waves...')
|
|
103
|
+
|
|
104
|
+
const planLoad = await agent(
|
|
105
|
+
`Load the execution plan and resolve task waves.
|
|
106
|
+
|
|
107
|
+
Plan directory: ${planDir || 'Find the most recent pending plan in .workflow/scratch/'}
|
|
108
|
+
|
|
109
|
+
Steps:
|
|
110
|
+
1. Read plan.json to get task_ids[], waves[], approach
|
|
111
|
+
2. Read each .task/TASK-{NNN}.json to get: description, scope, focus_paths, depends_on, convergence.criteria, files[], implementation[], read_first[], test.commands
|
|
112
|
+
3. Verify dependency order
|
|
113
|
+
4. Filter: only tasks with status="pending"
|
|
114
|
+
5. Return the wave structure with full task context`,
|
|
115
|
+
{
|
|
116
|
+
label: 'load:plan',
|
|
117
|
+
phase: 'Load',
|
|
118
|
+
schema: {
|
|
119
|
+
type: 'object',
|
|
120
|
+
properties: {
|
|
121
|
+
plan_dir: { type: 'string' },
|
|
122
|
+
plan_summary: { type: 'string' },
|
|
123
|
+
waves: {
|
|
124
|
+
type: 'array',
|
|
125
|
+
items: {
|
|
126
|
+
type: 'object',
|
|
127
|
+
properties: {
|
|
128
|
+
wave_index: { type: 'number' },
|
|
129
|
+
tasks: {
|
|
130
|
+
type: 'array',
|
|
131
|
+
items: {
|
|
132
|
+
type: 'object',
|
|
133
|
+
properties: {
|
|
134
|
+
task_id: { type: 'string' },
|
|
135
|
+
description: { type: 'string' },
|
|
136
|
+
scope: { type: 'string' },
|
|
137
|
+
focus_paths: { type: 'array', items: { type: 'string' } },
|
|
138
|
+
depends_on: { type: 'array', items: { type: 'string' } },
|
|
139
|
+
convergence_criteria: { type: 'array', items: { type: 'string' } },
|
|
140
|
+
test_commands: { type: 'array', items: { type: 'string' } },
|
|
141
|
+
files_to_create: { type: 'array', items: { type: 'string' } },
|
|
142
|
+
},
|
|
143
|
+
required: ['task_id', 'description'],
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
required: ['wave_index', 'tasks'],
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
total_pending: { type: 'number' },
|
|
151
|
+
},
|
|
152
|
+
required: ['plan_dir', 'waves', 'total_pending'],
|
|
153
|
+
},
|
|
154
|
+
agentType: 'workflow-planner',
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
if (!planLoad || !planLoad.waves || planLoad.waves.length === 0) {
|
|
159
|
+
log('No pending tasks found')
|
|
160
|
+
return { report: { status: 'DONE', total_tasks: 0, completed: 0, failed: 0, summary: 'No pending tasks.' }, metadata: { waves_executed: 0 } }
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
log(`Plan loaded: ${planLoad.total_pending} pending tasks across ${planLoad.waves.length} waves`)
|
|
164
|
+
|
|
165
|
+
// Phase 2: Execute waves
|
|
166
|
+
phase('Execute')
|
|
167
|
+
|
|
168
|
+
const allResults = []
|
|
169
|
+
let waveIndex = 0
|
|
170
|
+
|
|
171
|
+
for (const wave of planLoad.waves) {
|
|
172
|
+
waveIndex++
|
|
173
|
+
log(`Wave ${waveIndex}/${planLoad.waves.length}: executing ${wave.tasks.length} tasks in parallel...`)
|
|
174
|
+
|
|
175
|
+
const waveResults = await parallel(
|
|
176
|
+
wave.tasks.map(task => () =>
|
|
177
|
+
agent(
|
|
178
|
+
`Execute task: ${task.task_id}
|
|
179
|
+
Description: ${task.description}
|
|
180
|
+
Scope: ${task.scope || 'project root'}
|
|
181
|
+
Focus paths: ${(task.focus_paths || []).join(', ') || 'see task JSON'}
|
|
182
|
+
Plan directory: ${planLoad.plan_dir}
|
|
183
|
+
|
|
184
|
+
${specs ? 'Project specs (MUST comply):\n' + specs : ''}
|
|
185
|
+
${codebaseContext ? 'Codebase architecture:\n' + codebaseContext : ''}
|
|
186
|
+
${wikiContext ? 'Wiki knowledge:\n' + wikiContext : ''}
|
|
187
|
+
|
|
188
|
+
Process:
|
|
189
|
+
1. Read the full task JSON at ${planLoad.plan_dir}/.task/${task.task_id}.json
|
|
190
|
+
2. Read all files in read_first[] before any modification
|
|
191
|
+
3. Read reference.files for patterns to follow
|
|
192
|
+
4. Implement changes following implementation[] steps in order
|
|
193
|
+
5. Verify every convergence criterion: ${(task.convergence_criteria || []).join('; ') || 'see task JSON'}
|
|
194
|
+
6. Run test commands: ${(task.test_commands || []).join('; ') || 'none defined'}
|
|
195
|
+
${autoCommit ? '7. Create atomic git commit with message referencing ' + task.task_id : ''}
|
|
196
|
+
8. Write summary to ${planLoad.plan_dir}/.summaries/${task.task_id}-summary.md
|
|
197
|
+
9. Update task status to "completed" in the task JSON
|
|
198
|
+
|
|
199
|
+
Stay within scope.`,
|
|
200
|
+
{ label: `exec:${task.task_id}`, phase: 'Execute', schema: TASK_RESULT_SCHEMA, agentType: 'workflow-executor', isolation: 'worktree' }
|
|
201
|
+
)
|
|
202
|
+
)
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
allResults.push(...waveResults.filter(Boolean))
|
|
206
|
+
|
|
207
|
+
const waveFailed = waveResults.filter(r => r && r.status === 'failed')
|
|
208
|
+
if (waveFailed.length > 0) {
|
|
209
|
+
log(`Wave ${waveIndex}: ${waveFailed.length} tasks failed — ${waveFailed.map(f => f.task_id).join(', ')}`)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const completed = allResults.filter(r => r.status === 'completed')
|
|
214
|
+
const failed = allResults.filter(r => r.status === 'failed')
|
|
215
|
+
const blocked = allResults.filter(r => r.status === 'blocked')
|
|
216
|
+
|
|
217
|
+
// Phase 3: Adversarial convergence verification
|
|
218
|
+
phase('VerifyConvergence')
|
|
219
|
+
|
|
220
|
+
const tasksToVerify = completed.slice(0, Math.min(completed.length, 5))
|
|
221
|
+
|
|
222
|
+
if (tasksToVerify.length > 0) {
|
|
223
|
+
log(`Adversarial convergence spot-check of ${tasksToVerify.length} completed tasks...`)
|
|
224
|
+
|
|
225
|
+
const convergenceChecks = await parallel(
|
|
226
|
+
tasksToVerify.map(task => () => {
|
|
227
|
+
const waveTask = planLoad.waves.flatMap(w => w.tasks).find(t => t.task_id === task.task_id)
|
|
228
|
+
return agent(
|
|
229
|
+
`ADVERSARIAL convergence verification for: ${task.task_id}
|
|
230
|
+
|
|
231
|
+
The executor claims this task is COMPLETED.
|
|
232
|
+
Claimed summary: ${task.summary}
|
|
233
|
+
Files changed: ${(task.files_changed || []).join(', ')}
|
|
234
|
+
|
|
235
|
+
Convergence criteria to verify:
|
|
236
|
+
${(waveTask ? waveTask.convergence_criteria : []).map((c, i) => `${i + 1}. ${c}`).join('\n')}
|
|
237
|
+
|
|
238
|
+
Your job: VERIFY each criterion independently.
|
|
239
|
+
- Read the actual files that were supposedly changed
|
|
240
|
+
- Run any grep/search commands to verify claims
|
|
241
|
+
- Check if the implementation actually satisfies the criterion
|
|
242
|
+
- Do NOT trust the executor's self-assessment
|
|
243
|
+
|
|
244
|
+
For each criterion:
|
|
245
|
+
- claimed: what the executor says (true/false)
|
|
246
|
+
- verified: what YOU find after checking (true/false)
|
|
247
|
+
- evidence: your proof
|
|
248
|
+
- discrepancy: if claimed != verified, explain what's wrong
|
|
249
|
+
|
|
250
|
+
Set actually_complete=true ONLY if ALL criteria are genuinely met.
|
|
251
|
+
trust_score: 100 = perfect match, 0 = complete fabrication.`,
|
|
252
|
+
{ label: `verify:${task.task_id}`, phase: 'VerifyConvergence', schema: CONVERGENCE_CHECK_SCHEMA, agentType: 'workflow-verifier' }
|
|
253
|
+
)
|
|
254
|
+
})
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
var validConvergenceChecks = convergenceChecks.filter(Boolean)
|
|
258
|
+
var discrepancies = validConvergenceChecks.flatMap(c =>
|
|
259
|
+
c.checks.filter(ch => ch.claimed !== ch.verified).map(ch => ({
|
|
260
|
+
task_id: c.task_id,
|
|
261
|
+
criterion: ch.criterion,
|
|
262
|
+
discrepancy: ch.discrepancy || 'claimed ' + ch.claimed + ' but verified ' + ch.verified,
|
|
263
|
+
}))
|
|
264
|
+
)
|
|
265
|
+
var avgTrust = validConvergenceChecks.length > 0
|
|
266
|
+
? Math.round(validConvergenceChecks.reduce((s, c) => s + c.trust_score, 0) / validConvergenceChecks.length)
|
|
267
|
+
: 100
|
|
268
|
+
|
|
269
|
+
log(`Convergence verification: ${discrepancies.length} discrepancies found, avg trust: ${avgTrust}%`)
|
|
270
|
+
} else {
|
|
271
|
+
var validConvergenceChecks = []
|
|
272
|
+
var discrepancies = []
|
|
273
|
+
var avgTrust = 100
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Phase 4: 3-vote status determination
|
|
277
|
+
phase('Report')
|
|
278
|
+
|
|
279
|
+
const executionSummary = `Results: ${completed.length} completed, ${failed.length} failed, ${blocked.length} blocked out of ${planLoad.total_pending} total.
|
|
280
|
+
|
|
281
|
+
Completed tasks:
|
|
282
|
+
${completed.map(r => `- ${r.task_id}: ${r.summary} (${(r.files_changed || []).length} files)`).join('\n') || 'None'}
|
|
283
|
+
|
|
284
|
+
Failed tasks:
|
|
285
|
+
${failed.map(r => `- ${r.task_id}: ${r.error || r.summary}\n Unmet: ${(r.unmet_criteria || []).join(', ') || 'unknown'}`).join('\n') || 'None'}
|
|
286
|
+
|
|
287
|
+
Convergence verification:
|
|
288
|
+
- Tasks spot-checked: ${validConvergenceChecks.length}
|
|
289
|
+
- Discrepancies: ${discrepancies.length}
|
|
290
|
+
- Average trust score: ${avgTrust}%
|
|
291
|
+
${discrepancies.map(d => `- ${d.task_id}: ${d.criterion} — ${d.discrepancy}`).join('\n')}`
|
|
292
|
+
|
|
293
|
+
log('3-vote status determination (optimist / pessimist / realist)...')
|
|
294
|
+
|
|
295
|
+
const statusVotes = await parallel([
|
|
296
|
+
() => agent(
|
|
297
|
+
`OPTIMIST: Vote on execution status.
|
|
298
|
+
|
|
299
|
+
${executionSummary}
|
|
300
|
+
|
|
301
|
+
Your lens: Focus on progress made. Discount minor convergence discrepancies. Trust high trust scores.
|
|
302
|
+
- DONE: if majority completed, failures are minor, trust is >70%
|
|
303
|
+
- DONE_WITH_CONCERNS: if some failures but not blocking
|
|
304
|
+
- NEEDS_RETRY: only if critical failures make the whole execution invalid`,
|
|
305
|
+
{ label: 'vote:optimist', phase: 'Report', schema: STATUS_VOTE_SCHEMA }
|
|
306
|
+
),
|
|
307
|
+
() => agent(
|
|
308
|
+
`PESSIMIST: Vote on execution status.
|
|
309
|
+
|
|
310
|
+
${executionSummary}
|
|
311
|
+
|
|
312
|
+
Your lens: Focus on failures and convergence discrepancies. Low trust = unreliable results.
|
|
313
|
+
- NEEDS_RETRY: if any failures exist or trust < 80%
|
|
314
|
+
- DONE_WITH_CONCERNS: if all tasks completed but trust < 90%
|
|
315
|
+
- DONE: only if zero failures AND zero discrepancies AND trust > 95%`,
|
|
316
|
+
{ label: 'vote:pessimist', phase: 'Report', schema: STATUS_VOTE_SCHEMA }
|
|
317
|
+
),
|
|
318
|
+
() => agent(
|
|
319
|
+
`REALIST: Vote on execution status.
|
|
320
|
+
|
|
321
|
+
${executionSummary}
|
|
322
|
+
|
|
323
|
+
Your lens: Evidence-based judgment. No bias.
|
|
324
|
+
- DONE: all tasks completed, convergence verified, no critical discrepancies
|
|
325
|
+
- DONE_WITH_CONCERNS: completed with minor issues that don't block downstream
|
|
326
|
+
- NEEDS_RETRY: critical failures or convergence trust below 60%`,
|
|
327
|
+
{ label: 'vote:realist', phase: 'Report', schema: STATUS_VOTE_SCHEMA }
|
|
328
|
+
),
|
|
329
|
+
])
|
|
330
|
+
|
|
331
|
+
const validVotes = statusVotes.filter(Boolean)
|
|
332
|
+
const voteCounts = {}
|
|
333
|
+
validVotes.forEach(v => { voteCounts[v.status] = (voteCounts[v.status] || 0) + 1 })
|
|
334
|
+
|
|
335
|
+
const voteDigest = validVotes.map(v =>
|
|
336
|
+
`${v.perspective}: ${v.status} (confidence: ${v.confidence}%)\n ${v.rationale}`
|
|
337
|
+
).join('\n\n')
|
|
338
|
+
|
|
339
|
+
log(`Status votes: ${Object.entries(voteCounts).map(([k, v]) => k + '=' + v).join(', ')}`)
|
|
340
|
+
|
|
341
|
+
const report = await agent(
|
|
342
|
+
`Generate execution report from 3-vote adversarial determination.
|
|
343
|
+
|
|
344
|
+
=== VOTES ===
|
|
345
|
+
${voteDigest}
|
|
346
|
+
|
|
347
|
+
Vote tally: ${Object.entries(voteCounts).map(([k, v]) => k + '=' + v).join(', ')}
|
|
348
|
+
|
|
349
|
+
=== EXECUTION DATA ===
|
|
350
|
+
${executionSummary}
|
|
351
|
+
|
|
352
|
+
RESOLVE:
|
|
353
|
+
1. Majority vote wins. Tie-break: go with REALIST.
|
|
354
|
+
2. Record adversarial_outcome with each vote and convergence_trust
|
|
355
|
+
3. Include convergence_discrepancies in report
|
|
356
|
+
4. List failed_tasks with errors and unmet criteria
|
|
357
|
+
5. Compile all files_changed across completed tasks
|
|
358
|
+
6. Summarize execution including adversarial deliberation outcome`,
|
|
359
|
+
{ label: 'report', phase: 'Report', schema: REPORT_SCHEMA }
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
return {
|
|
363
|
+
report: report,
|
|
364
|
+
results: allResults,
|
|
365
|
+
convergence_checks: validConvergenceChecks,
|
|
366
|
+
status_votes: validVotes,
|
|
367
|
+
metadata: {
|
|
368
|
+
plan_dir: planLoad.plan_dir,
|
|
369
|
+
waves_executed: waveIndex,
|
|
370
|
+
total_tasks: planLoad.total_pending,
|
|
371
|
+
completed: completed.length,
|
|
372
|
+
failed: failed.length,
|
|
373
|
+
blocked: blocked.length,
|
|
374
|
+
convergence_trust: avgTrust,
|
|
375
|
+
discrepancy_count: discrepancies.length,
|
|
376
|
+
vote_counts: voteCounts,
|
|
377
|
+
all_files_changed: completed.flatMap(r => r.files_changed || []),
|
|
378
|
+
},
|
|
379
|
+
}
|