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.
Files changed (163) hide show
  1. package/.agents/agents/workflow-collab-planner.md +4 -1
  2. package/.agents/agents/workflow-plan-checker.md +11 -1
  3. package/.agents/agents/workflow-planner.md +4 -1
  4. package/.agents/skills/maestro/SKILL.md +8 -5
  5. package/.agents/skills/maestro-analyze/SKILL.md +1 -1
  6. package/.agents/skills/maestro-brainstorm/SKILL.md +2 -1
  7. package/.agents/skills/maestro-companion/SKILL.md +533 -0
  8. package/.agents/skills/maestro-grill/SKILL.md +116 -0
  9. package/.agents/skills/maestro-plan/SKILL.md +4 -0
  10. package/.agents/skills/maestro-ralph/SKILL.md +11 -7
  11. package/.agents/skills/maestro-ralph-execute/SKILL.md +2 -1
  12. package/.agents/skills/maestro-swarm-workflow/SKILL.md +266 -0
  13. package/.agents/skills/maestro-universal-workflow/SKILL.md +563 -0
  14. package/.agents/skills/manage-codebase-rebuild/SKILL.md +13 -1
  15. package/.agents/skills/manage-codebase-refresh/SKILL.md +3 -0
  16. package/.agents/skills/spec-setup/SKILL.md +9 -5
  17. package/.agents/skills/team-adversarial-swarm/SKILL.md +235 -0
  18. package/.agents/skills/team-adversarial-swarm/scripts/aco.py +473 -0
  19. package/.agents/skills/team-adversarial-swarm/scripts/pheromone.py +144 -0
  20. package/.agents/skills/team-adversarial-swarm/scripts/scoring.py +92 -0
  21. package/.agents/skills/team-adversarial-swarm/scripts/test_aco.py +475 -0
  22. package/.agents/skills/team-adversarial-swarm/specs/ant-output-schema.md +115 -0
  23. package/.agents/skills/team-adversarial-swarm/specs/convergence-criteria.md +75 -0
  24. package/.agents/skills/team-adversarial-swarm/specs/pheromone-schema.md +90 -0
  25. package/.agents/skills/team-adversarial-swarm/specs/swarm-config-template.json +66 -0
  26. package/.agents/skills/team-adversarial-swarm/specs/swarm-protocol.md +105 -0
  27. package/.agents/skills/team-adversarial-swarm/workflows/wf-swarm-converge.js +197 -0
  28. package/.agents/skills/team-adversarial-swarm/workflows/wf-swarm-explore.js +194 -0
  29. package/.agents/skills/team-adversarial-swarm/workflows/wf-swarm-score.js +188 -0
  30. package/.agents/skills/team-adversarial-swarm/workflows/wf-swarm-synthesize.js +248 -0
  31. package/.agy/agents/workflow-collab-planner.md +4 -1
  32. package/.agy/agents/workflow-plan-checker.md +11 -1
  33. package/.agy/agents/workflow-planner.md +4 -1
  34. package/.agy/skills/maestro/SKILL.md +8 -5
  35. package/.agy/skills/maestro-analyze/SKILL.md +1 -1
  36. package/.agy/skills/maestro-brainstorm/SKILL.md +2 -1
  37. package/.agy/skills/maestro-companion/SKILL.md +529 -0
  38. package/.agy/skills/maestro-grill/SKILL.md +116 -0
  39. package/.agy/skills/maestro-plan/SKILL.md +4 -0
  40. package/.agy/skills/maestro-ralph/SKILL.md +11 -7
  41. package/.agy/skills/maestro-ralph-execute/SKILL.md +2 -1
  42. package/.agy/skills/maestro-swarm-workflow/SKILL.md +263 -0
  43. package/.agy/skills/maestro-universal-workflow/SKILL.md +560 -0
  44. package/.agy/skills/manage-codebase-rebuild/SKILL.md +13 -1
  45. package/.agy/skills/manage-codebase-refresh/SKILL.md +3 -0
  46. package/.agy/skills/spec-setup/SKILL.md +9 -5
  47. package/.agy/skills/team-adversarial-swarm/SKILL.md +244 -0
  48. package/.agy/skills/team-adversarial-swarm/scripts/aco.py +473 -0
  49. package/.agy/skills/team-adversarial-swarm/scripts/pheromone.py +144 -0
  50. package/.agy/skills/team-adversarial-swarm/scripts/scoring.py +92 -0
  51. package/.agy/skills/team-adversarial-swarm/scripts/test_aco.py +475 -0
  52. package/.agy/skills/team-adversarial-swarm/specs/ant-output-schema.md +115 -0
  53. package/.agy/skills/team-adversarial-swarm/specs/convergence-criteria.md +75 -0
  54. package/.agy/skills/team-adversarial-swarm/specs/pheromone-schema.md +90 -0
  55. package/.agy/skills/team-adversarial-swarm/specs/swarm-config-template.json +66 -0
  56. package/.agy/skills/team-adversarial-swarm/specs/swarm-protocol.md +105 -0
  57. package/.agy/skills/team-adversarial-swarm/workflows/wf-swarm-converge.js +197 -0
  58. package/.agy/skills/team-adversarial-swarm/workflows/wf-swarm-explore.js +194 -0
  59. package/.agy/skills/team-adversarial-swarm/workflows/wf-swarm-score.js +188 -0
  60. package/.agy/skills/team-adversarial-swarm/workflows/wf-swarm-synthesize.js +248 -0
  61. package/.claude/agents/workflow-collab-planner.md +4 -1
  62. package/.claude/agents/workflow-plan-checker.md +11 -1
  63. package/.claude/agents/workflow-planner.md +4 -1
  64. package/.claude/commands/maestro-analyze.md +1 -1
  65. package/.claude/commands/maestro-brainstorm.md +2 -1
  66. package/.claude/commands/maestro-companion.md +531 -0
  67. package/.claude/commands/maestro-grill.md +114 -0
  68. package/.claude/commands/maestro-plan.md +4 -0
  69. package/.claude/commands/maestro-ralph-execute.md +2 -1
  70. package/.claude/commands/maestro-ralph.md +11 -7
  71. package/.claude/commands/maestro-swarm-workflow.md +264 -0
  72. package/.claude/commands/maestro-universal-workflow.md +561 -0
  73. package/.claude/commands/maestro.md +8 -5
  74. package/.claude/commands/manage-codebase-rebuild.md +13 -1
  75. package/.claude/commands/manage-codebase-refresh.md +3 -0
  76. package/.claude/commands/spec-setup.md +9 -5
  77. package/.claude/skills/team-adversarial-swarm/SKILL.md +233 -0
  78. package/.claude/skills/team-adversarial-swarm/scripts/aco.py +473 -0
  79. package/.claude/skills/team-adversarial-swarm/scripts/pheromone.py +144 -0
  80. package/.claude/skills/team-adversarial-swarm/scripts/scoring.py +92 -0
  81. package/.claude/skills/team-adversarial-swarm/scripts/test_aco.py +475 -0
  82. package/.claude/skills/team-adversarial-swarm/specs/ant-output-schema.md +115 -0
  83. package/.claude/skills/team-adversarial-swarm/specs/convergence-criteria.md +75 -0
  84. package/.claude/skills/team-adversarial-swarm/specs/pheromone-schema.md +90 -0
  85. package/.claude/skills/team-adversarial-swarm/specs/swarm-config-template.json +66 -0
  86. package/.claude/skills/team-adversarial-swarm/specs/swarm-protocol.md +105 -0
  87. package/.claude/skills/team-adversarial-swarm/workflows/wf-swarm-converge.js +197 -0
  88. package/.claude/skills/team-adversarial-swarm/workflows/wf-swarm-explore.js +194 -0
  89. package/.claude/skills/team-adversarial-swarm/workflows/wf-swarm-score.js +188 -0
  90. package/.claude/skills/team-adversarial-swarm/workflows/wf-swarm-synthesize.js +248 -0
  91. package/.codex/skills/maestro/SKILL.md +7 -2
  92. package/.codex/skills/maestro-companion/SKILL.md +485 -0
  93. package/.codex/skills/maestro-grill/SKILL.md +111 -0
  94. package/.codex/skills/maestro-ralph/SKILL.md +11 -7
  95. package/.codex/skills/manage-codebase-rebuild/SKILL.md +6 -0
  96. package/.codex/skills/manage-codebase-refresh/SKILL.md +6 -0
  97. package/dashboard/dist-server/dashboard/src/server/wiki/graph-analysis.d.ts +36 -0
  98. package/dashboard/dist-server/dashboard/src/server/wiki/graph-analysis.js +138 -2
  99. package/dashboard/dist-server/dashboard/src/server/wiki/graph-analysis.js.map +1 -1
  100. package/dashboard/dist-server/dashboard/src/server/wiki/search.js +13 -0
  101. package/dashboard/dist-server/dashboard/src/server/wiki/search.js.map +1 -1
  102. package/dashboard/dist-server/dashboard/src/server/wiki/virtual-wiki-adapters.d.ts +11 -0
  103. package/dashboard/dist-server/dashboard/src/server/wiki/virtual-wiki-adapters.js +178 -0
  104. package/dashboard/dist-server/dashboard/src/server/wiki/virtual-wiki-adapters.js.map +1 -1
  105. package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.d.ts +1 -0
  106. package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.js +39 -23
  107. package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.js.map +1 -1
  108. package/dashboard/dist-server/src/graph/types.d.ts +111 -0
  109. package/dashboard/dist-server/src/graph/types.js +2 -0
  110. package/dashboard/dist-server/src/graph/types.js.map +1 -0
  111. package/dist/src/cli.js +1 -0
  112. package/dist/src/cli.js.map +1 -1
  113. package/dist/src/commands/kg.d.ts +11 -0
  114. package/dist/src/commands/kg.d.ts.map +1 -0
  115. package/dist/src/commands/kg.js +486 -0
  116. package/dist/src/commands/kg.js.map +1 -0
  117. package/dist/src/graph/analyzers/fs-analyzer.d.ts +10 -0
  118. package/dist/src/graph/analyzers/fs-analyzer.d.ts.map +1 -0
  119. package/dist/src/graph/analyzers/fs-analyzer.js +959 -0
  120. package/dist/src/graph/analyzers/fs-analyzer.js.map +1 -0
  121. package/dist/src/graph/index.d.ts +6 -0
  122. package/dist/src/graph/index.d.ts.map +1 -0
  123. package/dist/src/graph/index.js +6 -0
  124. package/dist/src/graph/index.js.map +1 -0
  125. package/dist/src/graph/loader.d.ts +3 -0
  126. package/dist/src/graph/loader.d.ts.map +1 -0
  127. package/dist/src/graph/loader.js +12 -0
  128. package/dist/src/graph/loader.js.map +1 -0
  129. package/dist/src/graph/merger.d.ts +56 -0
  130. package/dist/src/graph/merger.d.ts.map +1 -0
  131. package/dist/src/graph/merger.js +896 -0
  132. package/dist/src/graph/merger.js.map +1 -0
  133. package/dist/src/graph/query.d.ts +7 -0
  134. package/dist/src/graph/query.d.ts.map +1 -0
  135. package/dist/src/graph/query.js +126 -0
  136. package/dist/src/graph/query.js.map +1 -0
  137. package/dist/src/graph/types.d.ts +112 -0
  138. package/dist/src/graph/types.d.ts.map +1 -0
  139. package/dist/src/graph/types.js +2 -0
  140. package/dist/src/graph/types.js.map +1 -0
  141. package/dist/src/tui/install-ui/KgVendorConfig.d.ts +7 -0
  142. package/dist/src/tui/install-ui/KgVendorConfig.d.ts.map +1 -0
  143. package/dist/src/tui/install-ui/KgVendorConfig.js +9 -0
  144. package/dist/src/tui/install-ui/KgVendorConfig.js.map +1 -0
  145. package/dist/src/utils/update-notices.js +23 -0
  146. package/dist/src/utils/update-notices.js.map +1 -1
  147. package/package.json +1 -1
  148. package/workflows/analyze.md +2 -1
  149. package/workflows/brainstorm.md +24 -1
  150. package/workflows/codebase-rebuild.md +141 -1
  151. package/workflows/codebase-refresh.md +20 -0
  152. package/workflows/finish-work.md +7 -2
  153. package/workflows/grill.md +513 -0
  154. package/workflows/plan.md +7 -4
  155. package/workflows/specs-setup.md +99 -3
  156. package/workflows/swarm/wf-analyze.js +347 -0
  157. package/workflows/swarm/wf-brainstorm.js +456 -0
  158. package/workflows/swarm/wf-execute.js +379 -0
  159. package/workflows/swarm/wf-grill.js +359 -0
  160. package/workflows/swarm/wf-milestone-audit.js +385 -0
  161. package/workflows/swarm/wf-plan.js +468 -0
  162. package/workflows/swarm/wf-review.js +341 -0
  163. 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
+ }