maestro-flow 0.3.5 → 0.3.7

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 (71) hide show
  1. package/.claude/commands/maestro-brainstorm.md +10 -1
  2. package/.claude/commands/maestro-milestone-audit.md +1 -1
  3. package/.claude/commands/maestro-milestone-complete.md +2 -1
  4. package/.claude/commands/maestro-milestone-release.md +96 -0
  5. package/.claude/commands/maestro-phase-add.md +9 -1
  6. package/.claude/commands/maestro-phase-transition.md +9 -1
  7. package/.claude/commands/maestro.md +6 -0
  8. package/.claude/commands/manage-codebase-rebuild.md +76 -50
  9. package/.claude/commands/manage-codebase-refresh.md +9 -1
  10. package/.claude/commands/quality-refactor.md +1 -1
  11. package/.claude/commands/quality-sync.md +9 -1
  12. package/.claude/commands/spec-setup.md +1 -1
  13. package/.codex/skills/maestro-coordinate/SKILL.md +20 -6
  14. package/.codex/skills/manage-issue-analyze/SKILL.md +1 -1
  15. package/.codex/skills/quality-retrospective/SKILL.md +3 -3
  16. package/.codex/skills/team-coordinate/SKILL.md +1 -1
  17. package/.codex/skills/team-coordinate/roles/coordinator/commands/monitor.md +19 -10
  18. package/.codex/skills/team-coordinate/roles/coordinator/role.md +2 -2
  19. package/.codex/skills/team-executor/SKILL.md +1 -1
  20. package/.codex/skills/team-executor/roles/executor/commands/monitor.md +20 -9
  21. package/.codex/skills/team-lifecycle-v4/SKILL.md +2 -2
  22. package/.codex/skills/team-lifecycle-v4/roles/coordinator/commands/monitor.md +31 -12
  23. package/.codex/skills/team-lifecycle-v4/roles/coordinator/role.md +1 -1
  24. package/.codex/skills/team-quality-assurance/SKILL.md +1 -1
  25. package/.codex/skills/team-quality-assurance/roles/coordinator/commands/monitor.md +20 -9
  26. package/.codex/skills/team-quality-assurance/roles/coordinator/role.md +1 -1
  27. package/.codex/skills/team-review/SKILL.md +1 -1
  28. package/.codex/skills/team-review/roles/coordinator/commands/monitor.md +20 -9
  29. package/.codex/skills/team-review/roles/coordinator/role.md +1 -1
  30. package/.codex/skills/team-tech-debt/SKILL.md +1 -1
  31. package/.codex/skills/team-tech-debt/roles/coordinator/commands/monitor.md +20 -9
  32. package/.codex/skills/team-tech-debt/roles/coordinator/role.md +1 -1
  33. package/.codex/skills/team-testing/SKILL.md +2 -2
  34. package/.codex/skills/team-testing/roles/coordinator/commands/monitor.md +20 -9
  35. package/.codex/skills/team-testing/roles/coordinator/role.md +1 -1
  36. package/chains/singles/spec-map.json +2 -2
  37. package/dashboard/dist-server/dashboard/src/server/agents/codex-cli-adapter.js +1 -1
  38. package/dashboard/dist-server/dashboard/src/server/agents/codex-cli-adapter.js.map +1 -1
  39. package/dashboard/dist-server/src/commands/delegate.d.ts +23 -0
  40. package/dashboard/dist-server/src/commands/delegate.js +91 -55
  41. package/dashboard/dist-server/src/commands/delegate.js.map +1 -1
  42. package/dist/src/brainstorm-visualize/frame.d.ts +8 -0
  43. package/dist/src/brainstorm-visualize/frame.d.ts.map +1 -0
  44. package/dist/src/brainstorm-visualize/frame.js +655 -0
  45. package/dist/src/brainstorm-visualize/frame.js.map +1 -0
  46. package/dist/src/brainstorm-visualize/server.d.ts +2 -0
  47. package/dist/src/brainstorm-visualize/server.d.ts.map +1 -0
  48. package/dist/src/brainstorm-visualize/server.js +180 -0
  49. package/dist/src/brainstorm-visualize/server.js.map +1 -0
  50. package/dist/src/cli.js +11 -1
  51. package/dist/src/cli.js.map +1 -1
  52. package/dist/src/commands/brainstorm-visualize.d.ts +3 -0
  53. package/dist/src/commands/brainstorm-visualize.d.ts.map +1 -0
  54. package/dist/src/commands/brainstorm-visualize.js +337 -0
  55. package/dist/src/commands/brainstorm-visualize.js.map +1 -0
  56. package/dist/src/commands/core-memory.d.ts +3 -0
  57. package/dist/src/commands/core-memory.d.ts.map +1 -0
  58. package/dist/src/commands/core-memory.js +101 -0
  59. package/dist/src/commands/core-memory.js.map +1 -0
  60. package/dist/src/commands/delegate.d.ts +23 -0
  61. package/dist/src/commands/delegate.d.ts.map +1 -1
  62. package/dist/src/commands/delegate.js +91 -55
  63. package/dist/src/commands/delegate.js.map +1 -1
  64. package/dist/src/mcp/delegate-channel-relay.d.ts.map +1 -1
  65. package/dist/src/mcp/delegate-channel-relay.js +6 -0
  66. package/dist/src/mcp/delegate-channel-relay.js.map +1 -1
  67. package/dist/src/mcp/server.d.ts.map +1 -1
  68. package/dist/src/mcp/server.js +27 -0
  69. package/dist/src/mcp/server.js.map +1 -1
  70. package/package.json +1 -1
  71. package/.claude/commands/spec-map.md +0 -82
@@ -151,7 +151,7 @@ After spawning all ready regular tasks:
151
151
  const taskNames = Object.entries(state.active_agents)
152
152
  .filter(([_, a]) => !a.resident)
153
153
  .map(([taskId]) => taskId)
154
- const waitResult = wait_agent({ timeout_ms: 900000 })
154
+ const waitResult = wait_agent({ timeout_ms: 1800000 }) // 30 min
155
155
  // 4a) Drain progress from message bus (before collecting discoveries)
156
156
  const progressMsgs = mcp__maestro-tools__team_msg({
157
157
  operation: "list", session_id: sessionId, type: "progress", last: 100
@@ -173,15 +173,26 @@ if (blockerMsgs.result?.messages?.length > 0) {
173
173
  if (waitResult.timed_out) {
174
174
  // Use progress trace to understand where workers got stuck
175
175
  for (const taskId of taskNames) {
176
- const lastProgress = (progressMsgs.result?.messages || [])
177
- .filter(m => m.data?.task_id === taskId)
178
- .pop()
179
- state.tasks[taskId].status = 'timed_out'
180
- state.tasks[taskId].error = lastProgress
181
- ? `Timed out at ${lastProgress.data.phase} (${lastProgress.data.progress_pct}%)`
182
- : 'Timed out with no progress reported'
183
- close_agent({ target: taskId })
184
- delete state.active_agents[taskId]
176
+ // Status probe before closing
177
+ followup_task({ target: taskId, message: "STATUS_CHECK: Report current progress, findings so far, and estimated remaining work." })
178
+ const status = wait_agent({ timeout_ms: 180000 }) // 3 min
179
+ if (status.timed_out) {
180
+ followup_task({ target: taskId, message: "FINALIZE: Output all current findings immediately. Time limit reached.", interrupt: true })
181
+ const forced = wait_agent({ timeout_ms: 180000 }) // 3 min
182
+ if (forced.timed_out) {
183
+ const lastProgress = (progressMsgs.result?.messages || [])
184
+ .filter(m => m.data?.task_id === taskId)
185
+ .pop()
186
+ state.tasks[taskId].status = 'timed_out'
187
+ state.tasks[taskId].error = lastProgress
188
+ ? `Timed out at ${lastProgress.data.phase} (${lastProgress.data.progress_pct}%)`
189
+ : 'Timed out with no progress reported'
190
+ close_agent({ target: taskId })
191
+ delete state.active_agents[taskId]
192
+ }
193
+ // else: forced output received, process result
194
+ }
195
+ // else: status received, continue processing
185
196
  }
186
197
  } else {
187
198
  // 5) Collect results from discoveries/{task_id}.json
@@ -234,8 +245,16 @@ For each ready CHECKPOINT task:
234
245
  scope: [${task.deps.join(', ')}]
235
246
  pipeline_progress: ${completedCount}/${totalCount} tasks completed`
236
247
  })
237
- const cpResult = wait_agent({ timeout_ms: 600000 })
238
- if (cpResult.timed_out) { /* mark checkpoint timed_out, close supervisor, STOP */ }
248
+ const cpResult = wait_agent({ timeout_ms: 1800000 }) // 30 min
249
+ if (cpResult.timed_out) {
250
+ followup_task({ target: supervisorId, message: "STATUS_CHECK: Report current progress, findings so far, and estimated remaining work." })
251
+ const status = wait_agent({ timeout_ms: 180000 }) // 3 min
252
+ if (status.timed_out) {
253
+ followup_task({ target: supervisorId, message: "FINALIZE: Output all current findings immediately. Time limit reached.", interrupt: true })
254
+ const forced = wait_agent({ timeout_ms: 180000 }) // 3 min
255
+ if (forced.timed_out) { /* mark checkpoint timed_out, close supervisor, STOP */ }
256
+ }
257
+ }
239
258
  ```
240
259
  4. Read checkpoint report from artifacts/${task.id}-report.md
241
260
  5. Parse verdict (pass / warn / block):
@@ -170,7 +170,7 @@ Delegate to @commands/monitor.md#handleSpawnNext:
170
170
 
171
171
  ### Message Semantics
172
172
  - **send_message**: Queue supplementary info to a running agent. Does NOT interrupt current processing. Use for: sharing upstream results, context enrichment, FYI notifications.
173
- - **followup_task**: Assign new work and trigger processing. Use for: waking idle agents, redirecting work, requesting new output.
173
+ - **followup_task**: Assign new work and trigger processing. Use for: waking idle agents, redirecting work, requesting new output, and status probing on timeout (STATUS_CHECK / FINALIZE cascade before closing timed-out agents).
174
174
 
175
175
  ### Agent Lifecycle Management
176
176
  - **list_agents({})**: Returns all running agents. Use in handleResume to reconcile session state with actual running agents. Use in handleComplete to verify clean shutdown.
@@ -110,7 +110,7 @@ pipeline_phase: <pipeline-phase>
110
110
  })
111
111
  ```
112
112
 
113
- After spawning, use `wait_agent({ timeout_ms: 900000 })` to collect results, then `close_agent({ target })` each worker.
113
+ After spawning, use `wait_agent({ timeout_ms: 1800000 })` to collect results (30 min). If `result.timed_out`, send STATUS_CHECK via followup_task (wait 3 min), then FINALIZE with interrupt (wait 3 min), then mark timed_out and close agents. Use `close_agent({ target })` each worker.
114
114
 
115
115
 
116
116
  ### Model Selection Guide
@@ -188,7 +188,7 @@ Report completion via team_msg type="task_complete" after report_agent_job_resul
188
188
 
189
189
  f. Add to active_workers
190
190
  5. Update session, output summary, STOP
191
- 6. Use `wait_agent({ timeout_ms: 900000 })` to wait for callbacks. Workers use `report_agent_job_result()` to send results back.
191
+ 6. Use `wait_agent({ timeout_ms: 1800000 })` to wait for callbacks (30 min). If `result.timed_out`, send STATUS_CHECK via followup_task (wait 3 min), then FINALIZE with interrupt (wait 3 min), then mark timed_out and close agents. Workers use `report_agent_job_result()` to send results back.
192
192
 
193
193
  ### Post-Wait Processing
194
194
 
@@ -205,14 +205,25 @@ for (const msg of (progressMsgs.result?.messages || [])) {
205
205
 
206
206
  if (waitResult.timed_out) {
207
207
  for (const taskId of Object.keys(state.active_workers)) {
208
- const lastProgress = (progressMsgs.result?.messages || [])
209
- .filter(m => m.data?.task_id === taskId).pop()
210
- state.tasks[taskId].status = 'timed_out'
211
- state.tasks[taskId].error = lastProgress
212
- ? `Timed out at ${lastProgress.data.phase} (${lastProgress.data.progress_pct}%)`
213
- : 'Timed out with no progress reported'
214
- close_agent({ target: taskId })
215
- delete state.active_workers[taskId]
208
+ // Status probe before closing
209
+ followup_task({ target: taskId, message: "STATUS_CHECK: Report current progress, findings so far, and estimated remaining work." })
210
+ const status = wait_agent({ timeout_ms: 180000 }) // 3 min
211
+ if (status.timed_out) {
212
+ followup_task({ target: taskId, message: "FINALIZE: Output all current findings immediately. Time limit reached.", interrupt: true })
213
+ const forced = wait_agent({ timeout_ms: 180000 }) // 3 min
214
+ if (forced.timed_out) {
215
+ const lastProgress = (progressMsgs.result?.messages || [])
216
+ .filter(m => m.data?.task_id === taskId).pop()
217
+ state.tasks[taskId].status = 'timed_out'
218
+ state.tasks[taskId].error = lastProgress
219
+ ? `Timed out at ${lastProgress.data.phase} (${lastProgress.data.progress_pct}%)`
220
+ : 'Timed out with no progress reported'
221
+ close_agent({ target: taskId })
222
+ delete state.active_workers[taskId]
223
+ }
224
+ // else: forced output received, process result
225
+ }
226
+ // else: status received, continue processing
216
227
  }
217
228
  } else {
218
229
  // Collect results, mark completed, close agents
@@ -157,7 +157,7 @@ Delegate to @commands/monitor.md#handleSpawnNext:
157
157
 
158
158
  ### Message Semantics
159
159
  - **send_message**: Queue supplementary info to a running agent. Does NOT interrupt current processing. Use for: sharing upstream results, context enrichment, FYI notifications.
160
- - **followup_task**: Assign new work and trigger processing. Use for: waking idle agents, redirecting work, requesting new output.
160
+ - **followup_task**: Assign new work and trigger processing. Use for: waking idle agents, redirecting work, requesting new output, and status probing on timeout (STATUS_CHECK / FINALIZE cascade before closing timed-out agents).
161
161
 
162
162
  ### Agent Lifecycle Management
163
163
  - **list_agents({})**: Returns all running agents. Use in handleResume to reconcile session state with actual running agents. Use in handleComplete to verify clean shutdown.
@@ -108,7 +108,7 @@ pipeline_phase: <pipeline-phase>
108
108
  })
109
109
  ```
110
110
 
111
- After spawning, use `wait_agent({ timeout_ms: 900000 })` to collect results, then `close_agent({ target })` each worker.
111
+ After spawning, use `wait_agent({ timeout_ms: 1800000 })` to collect results (30 min). If `result.timed_out`, send STATUS_CHECK via followup_task (wait 3 min), then FINALIZE with interrupt (wait 3 min), then mark timed_out and close agents. Use `close_agent({ target })` each worker.
112
112
 
113
113
 
114
114
  ### Model Selection Guide
@@ -144,7 +144,7 @@ Report completion via team_msg type="task_complete" after report_agent_job_resul
144
144
  state.active_agents[taskId] = { agentId, role, started_at: now }
145
145
 
146
146
  // 4) Wait for completion — use task_name for stable targeting (v4)
147
- const waitResult = wait_agent({ timeout_ms: 900000 })
147
+ const waitResult = wait_agent({ timeout_ms: 1800000 }) // 30 min
148
148
 
149
149
  // Drain progress from message bus
150
150
  const progressMsgs = mcp__maestro-tools__team_msg({
@@ -155,14 +155,25 @@ for (const msg of (progressMsgs.result?.messages || [])) {
155
155
  }
156
156
 
157
157
  if (waitResult.timed_out) {
158
- const lastProgress = (progressMsgs.result?.messages || [])
159
- .filter(m => m.data?.task_id === taskId).pop()
160
- state.tasks[taskId].status = 'timed_out'
161
- state.tasks[taskId].error = lastProgress
162
- ? `Timed out at ${lastProgress.data.phase} (${lastProgress.data.progress_pct}%)`
163
- : 'Timed out with no progress reported'
164
- close_agent({ target: taskId })
165
- delete state.active_agents[taskId]
158
+ // Status probe before closing
159
+ followup_task({ target: taskId, message: "STATUS_CHECK: Report current progress, findings so far, and estimated remaining work." })
160
+ const status = wait_agent({ timeout_ms: 180000 }) // 3 min
161
+ if (status.timed_out) {
162
+ followup_task({ target: taskId, message: "FINALIZE: Output all current findings immediately. Time limit reached.", interrupt: true })
163
+ const forced = wait_agent({ timeout_ms: 180000 }) // 3 min
164
+ if (forced.timed_out) {
165
+ const lastProgress = (progressMsgs.result?.messages || [])
166
+ .filter(m => m.data?.task_id === taskId).pop()
167
+ state.tasks[taskId].status = 'timed_out'
168
+ state.tasks[taskId].error = lastProgress
169
+ ? `Timed out at ${lastProgress.data.phase} (${lastProgress.data.progress_pct}%)`
170
+ : 'Timed out with no progress reported'
171
+ close_agent({ target: taskId })
172
+ delete state.active_agents[taskId]
173
+ }
174
+ // else: forced output received, process result
175
+ }
176
+ // else: status received, continue processing
166
177
  } else {
167
178
  // 5) Collect results
168
179
  state.tasks[taskId].status = 'completed'
@@ -157,7 +157,7 @@ Delegate to @commands/monitor.md#handleSpawnNext:
157
157
 
158
158
  ### Message Semantics
159
159
  - **send_message**: Queue supplementary info to a running agent. Does NOT interrupt current processing. Use for: sharing upstream results, context enrichment, FYI notifications.
160
- - **followup_task**: Assign new work and trigger processing. Use for: waking idle agents, redirecting work, requesting new output.
160
+ - **followup_task**: Assign new work and trigger processing. Use for: waking idle agents, redirecting work, requesting new output, and status probing on timeout (STATUS_CHECK / FINALIZE cascade before closing timed-out agents).
161
161
 
162
162
  ### Agent Lifecycle Management
163
163
  - **list_agents({})**: Returns all running agents. Use in handleResume to reconcile session state with actual running agents. Use in handleComplete to verify clean shutdown.
@@ -110,7 +110,7 @@ pipeline_phase: <pipeline-phase>
110
110
  })
111
111
  ```
112
112
 
113
- After spawning, use `wait_agent({ timeout_ms: 900000 })` to collect results, then `close_agent({ target })` each worker.
113
+ After spawning, use `wait_agent({ timeout_ms: 1800000 })` to collect results (30 min). If `result.timed_out`, send STATUS_CHECK via followup_task (wait 3 min), then FINALIZE with interrupt (wait 3 min), then mark timed_out and close agents. Use `close_agent({ target })` each worker.
114
114
 
115
115
 
116
116
  ### Model Selection Guide
@@ -150,7 +150,7 @@ After spawning all ready tasks:
150
150
  ```javascript
151
151
  // 4) Batch wait — use task_name for stable targeting (v4)
152
152
  const taskNames = Object.keys(state.active_agents)
153
- const waitResult = wait_agent({ timeout_ms: 900000 })
153
+ const waitResult = wait_agent({ timeout_ms: 1800000 }) // 30 min
154
154
 
155
155
  // Drain progress from message bus
156
156
  const progressMsgs = mcp__maestro-tools__team_msg({
@@ -162,14 +162,25 @@ for (const msg of (progressMsgs.result?.messages || [])) {
162
162
 
163
163
  if (waitResult.timed_out) {
164
164
  for (const taskId of taskNames) {
165
- const lastProgress = (progressMsgs.result?.messages || [])
166
- .filter(m => m.data?.task_id === taskId).pop()
167
- state.tasks[taskId].status = 'timed_out'
168
- state.tasks[taskId].error = lastProgress
169
- ? `Timed out at ${lastProgress.data.phase} (${lastProgress.data.progress_pct}%)`
170
- : 'Timed out with no progress reported'
171
- close_agent({ target: taskId })
172
- delete state.active_agents[taskId]
165
+ // Status probe before closing
166
+ followup_task({ target: taskId, message: "STATUS_CHECK: Report current progress, findings so far, and estimated remaining work." })
167
+ const status = wait_agent({ timeout_ms: 180000 }) // 3 min
168
+ if (status.timed_out) {
169
+ followup_task({ target: taskId, message: "FINALIZE: Output all current findings immediately. Time limit reached.", interrupt: true })
170
+ const forced = wait_agent({ timeout_ms: 180000 }) // 3 min
171
+ if (forced.timed_out) {
172
+ const lastProgress = (progressMsgs.result?.messages || [])
173
+ .filter(m => m.data?.task_id === taskId).pop()
174
+ state.tasks[taskId].status = 'timed_out'
175
+ state.tasks[taskId].error = lastProgress
176
+ ? `Timed out at ${lastProgress.data.phase} (${lastProgress.data.progress_pct}%)`
177
+ : 'Timed out with no progress reported'
178
+ close_agent({ target: taskId })
179
+ delete state.active_agents[taskId]
180
+ }
181
+ // else: forced output received, process result
182
+ }
183
+ // else: status received, continue processing
173
184
  }
174
185
  } else {
175
186
  // 5) Collect results
@@ -153,7 +153,7 @@ Delegate to @commands/monitor.md#handleSpawnNext:
153
153
 
154
154
  ### Message Semantics
155
155
  - **send_message**: Queue supplementary info to a running agent. Does NOT interrupt current processing. Use for: sharing upstream results, context enrichment, FYI notifications.
156
- - **followup_task**: Assign new work and trigger processing. Use for: waking idle agents, redirecting work, requesting new output.
156
+ - **followup_task**: Assign new work and trigger processing. Use for: waking idle agents, redirecting work, requesting new output, and status probing on timeout (STATUS_CHECK / FINALIZE cascade before closing timed-out agents).
157
157
 
158
158
  ### Agent Lifecycle Management
159
159
  - **list_agents({})**: Returns all running agents. Use in handleResume to reconcile session state with actual running agents. Use in handleComplete to verify clean shutdown.
@@ -109,7 +109,7 @@ pipeline_phase: <pipeline-phase>
109
109
  })
110
110
  ```
111
111
 
112
- After spawning, use `wait_agent({ timeout_ms: 900000 })` to collect results, then `close_agent({ target })` each worker.
112
+ After spawning, use `wait_agent({ timeout_ms: 1800000 })` to collect results (30 min). If `result.timed_out`, send STATUS_CHECK via followup_task (wait 3 min), then FINALIZE with interrupt (wait 3 min), then mark timed_out and close agents. Use `close_agent({ target })` each worker.
113
113
 
114
114
 
115
115
  ### Model Selection Guide
@@ -162,7 +162,7 @@ const genNames = ["TESTGEN-001", "TESTGEN-002"]
162
162
  for (const name of genNames) {
163
163
  spawn_agent({ agent_type: "team_worker", task_name: name, ... })
164
164
  }
165
- wait_agent({ timeout_ms: 900000 })
165
+ wait_agent({ timeout_ms: 1800000 }) // 30 min
166
166
  ```
167
167
 
168
168
  ### GC Loop Coordination
@@ -172,7 +172,7 @@ After spawning all ready tasks:
172
172
  ```javascript
173
173
  // 4) Batch wait — use task_name for stable targeting (v4)
174
174
  const taskNames = Object.keys(state.active_agents)
175
- const waitResult = wait_agent({ timeout_ms: 900000 })
175
+ const waitResult = wait_agent({ timeout_ms: 1800000 }) // 30 min
176
176
 
177
177
  // Drain progress from message bus
178
178
  const progressMsgs = mcp__maestro-tools__team_msg({
@@ -184,14 +184,25 @@ for (const msg of (progressMsgs.result?.messages || [])) {
184
184
 
185
185
  if (waitResult.timed_out) {
186
186
  for (const taskId of taskNames) {
187
- const lastProgress = (progressMsgs.result?.messages || [])
188
- .filter(m => m.data?.task_id === taskId).pop()
189
- state.tasks[taskId].status = 'timed_out'
190
- state.tasks[taskId].error = lastProgress
191
- ? `Timed out at ${lastProgress.data.phase} (${lastProgress.data.progress_pct}%)`
192
- : 'Timed out with no progress reported'
193
- close_agent({ target: taskId })
194
- delete state.active_agents[taskId]
187
+ // Status probe before closing
188
+ followup_task({ target: taskId, message: "STATUS_CHECK: Report current progress, findings so far, and estimated remaining work." })
189
+ const status = wait_agent({ timeout_ms: 180000 }) // 3 min
190
+ if (status.timed_out) {
191
+ followup_task({ target: taskId, message: "FINALIZE: Output all current findings immediately. Time limit reached.", interrupt: true })
192
+ const forced = wait_agent({ timeout_ms: 180000 }) // 3 min
193
+ if (forced.timed_out) {
194
+ const lastProgress = (progressMsgs.result?.messages || [])
195
+ .filter(m => m.data?.task_id === taskId).pop()
196
+ state.tasks[taskId].status = 'timed_out'
197
+ state.tasks[taskId].error = lastProgress
198
+ ? `Timed out at ${lastProgress.data.phase} (${lastProgress.data.progress_pct}%)`
199
+ : 'Timed out with no progress reported'
200
+ close_agent({ target: taskId })
201
+ delete state.active_agents[taskId]
202
+ }
203
+ // else: forced output received, process result
204
+ }
205
+ // else: status received, continue processing
195
206
  }
196
207
  } else {
197
208
  // 5) Collect results
@@ -166,7 +166,7 @@ Delegate to @commands/monitor.md#handleSpawnNext:
166
166
 
167
167
  ### Message Semantics
168
168
  - **send_message**: Queue supplementary info to a running agent. Does NOT interrupt current processing. Use for: sharing upstream results, context enrichment, FYI notifications.
169
- - **followup_task**: Assign new work and trigger processing. Use for: waking idle agents, redirecting work, requesting new output.
169
+ - **followup_task**: Assign new work and trigger processing. Use for: waking idle agents, redirecting work, requesting new output, and status probing on timeout (STATUS_CHECK / FINALIZE cascade before closing timed-out agents).
170
170
 
171
171
  ### Agent Lifecycle Management
172
172
  - **list_agents({})**: Returns all running agents. Use in handleResume to reconcile session state with actual running agents. Use in handleComplete to verify clean shutdown.
@@ -12,10 +12,10 @@
12
12
  "nodes": {
13
13
  "spec_map": {
14
14
  "type": "command",
15
- "cmd": "spec-map",
15
+ "cmd": "manage-codebase-rebuild",
16
16
  "next": "done",
17
17
  "analyze": false,
18
- "description": "Analyze codebase with parallel mapper agents to produce codebase documents"
18
+ "description": "Analyze codebase with parallel mapper agents to produce codebase documents (consolidated into manage-codebase-rebuild)"
19
19
  },
20
20
  "done": {
21
21
  "type": "terminal",
@@ -24,7 +24,7 @@ export class CodexCliAdapter extends BaseAgentAdapter {
24
24
  async doSpawn(processId, config) {
25
25
  const args = [
26
26
  'exec',
27
- '--full-auto',
27
+ '--dangerously-bypass-approvals-and-sandbox',
28
28
  '--json',
29
29
  '--skip-git-repo-check',
30
30
  '-',
@@ -1 +1 @@
1
- {"version":3,"file":"codex-cli-adapter.js","sourceRoot":"","sources":["../../../../../src/server/agents/codex-cli-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codex-cli-adapter.js","sourceRoot":"","sources":["../../../../../src/server/agents/codex-cli-adapter.ts"],"names":[],"mappings":"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"}
@@ -32,5 +32,28 @@ export interface LaunchDetachedDelegateOptions {
32
32
  }
33
33
  export declare function buildDetachedDelegateWorkerArgs(request: DelegateExecutionRequest, entryScript?: string): string[];
34
34
  export declare function launchDetachedDelegateWorker(request: DelegateExecutionRequest, options?: LaunchDetachedDelegateOptions): void;
35
+ export interface RelayRecord {
36
+ sessionId?: string;
37
+ pid?: number;
38
+ ownerPid?: number;
39
+ ssePort?: string;
40
+ startedAt?: string;
41
+ }
42
+ /**
43
+ * Scan the async dir and return live relay records.
44
+ *
45
+ * "Live" requires BOTH:
46
+ * - `pid` (the MCP server process) is alive
47
+ * - `ownerPid` (the Claude Code process that spawned it) is alive, when recorded
48
+ *
49
+ * The `ownerPid` check rejects zombie MCP servers whose parent Claude Code
50
+ * exited but whose node process never shut down. Older relay files without
51
+ * `ownerPid` fall back to pid-only liveness (backward compatible).
52
+ *
53
+ * Stale files (dead pid OR dead ownerPid) are unlinked as a side effect.
54
+ */
55
+ export declare function readLiveRelayRecords(asyncDir: string): RelayRecord[];
56
+ /** Check if the MCP notification channel is functional for the current session. */
57
+ export declare function isChannelAvailable(): boolean;
35
58
  export declare function registerDelegateCommand(program: Command): void;
36
59
  export {};
@@ -147,72 +147,81 @@ function isProcessAlive(pid) {
147
147
  }
148
148
  }
149
149
  /**
150
- * Resolve the relay session ID that matches the current Claude Code session.
151
- * Matches by CLAUDE_CODE_SSE_PORT when available (precise), falls back to
152
- * newest alive session (legacy). Cleans up dead relay files along the way.
150
+ * Scan the async dir and return live relay records.
151
+ *
152
+ * "Live" requires BOTH:
153
+ * - `pid` (the MCP server process) is alive
154
+ * - `ownerPid` (the Claude Code process that spawned it) is alive, when recorded
155
+ *
156
+ * The `ownerPid` check rejects zombie MCP servers whose parent Claude Code
157
+ * exited but whose node process never shut down. Older relay files without
158
+ * `ownerPid` fall back to pid-only liveness (backward compatible).
159
+ *
160
+ * Stale files (dead pid OR dead ownerPid) are unlinked as a side effect.
153
161
  */
154
- function resolveRelaySessionId() {
155
- const asyncDir = join(paths.data, 'async');
156
- const currentSsePort = process.env.CLAUDE_CODE_SSE_PORT;
162
+ export function readLiveRelayRecords(asyncDir) {
163
+ let files;
157
164
  try {
158
- const files = readdirSync(asyncDir)
159
- .filter((f) => f.startsWith('relay-session-') && f.endsWith('.id'));
160
- if (files.length === 0)
161
- return undefined;
162
- let portMatch;
163
- let newest;
164
- for (const file of files) {
165
- const filePath = join(asyncDir, file);
165
+ files = readdirSync(asyncDir).filter((f) => f.startsWith('relay-session-') && f.endsWith('.id'));
166
+ }
167
+ catch {
168
+ return [];
169
+ }
170
+ const live = [];
171
+ for (const file of files) {
172
+ const filePath = join(asyncDir, file);
173
+ let data;
174
+ try {
175
+ data = JSON.parse(readFileSync(filePath, 'utf-8'));
176
+ }
177
+ catch {
178
+ continue;
179
+ }
180
+ const pidAlive = !data.pid || isProcessAlive(data.pid);
181
+ const ownerAlive = !data.ownerPid || isProcessAlive(data.ownerPid);
182
+ if (!pidAlive || !ownerAlive) {
166
183
  try {
167
- const data = JSON.parse(readFileSync(filePath, 'utf-8'));
168
- if (data.pid && !isProcessAlive(data.pid)) {
169
- try {
170
- unlinkSync(filePath);
171
- }
172
- catch { }
173
- continue;
174
- }
175
- // Precise match: relay recorded the same SSE port as this session
176
- if (currentSsePort && data.ssePort === currentSsePort) {
177
- portMatch = data.sessionId;
178
- }
179
- if (!newest || data.startedAt > newest.startedAt) {
180
- newest = data;
181
- }
182
- }
183
- catch {
184
- // Skip corrupted files
184
+ unlinkSync(filePath);
185
185
  }
186
+ catch { /* ignore */ }
187
+ continue;
186
188
  }
187
- return portMatch ?? newest?.sessionId;
189
+ live.push(data);
188
190
  }
189
- catch {
191
+ return live;
192
+ }
193
+ /**
194
+ * Resolve the relay session ID that matches the current Claude Code session.
195
+ * Matches by CLAUDE_CODE_SSE_PORT when available (precise), falls back to
196
+ * newest live session (legacy). Stale relay files are cleaned along the way.
197
+ */
198
+ function resolveRelaySessionId() {
199
+ const records = readLiveRelayRecords(join(paths.data, 'async'));
200
+ if (records.length === 0)
190
201
  return undefined;
202
+ const currentSsePort = process.env.CLAUDE_CODE_SSE_PORT;
203
+ if (currentSsePort) {
204
+ const portMatch = records.find((r) => r.ssePort === currentSsePort);
205
+ if (portMatch?.sessionId)
206
+ return portMatch.sessionId;
191
207
  }
208
+ let newest;
209
+ for (const record of records) {
210
+ if (!newest || (record.startedAt ?? '') > (newest.startedAt ?? '')) {
211
+ newest = record;
212
+ }
213
+ }
214
+ return newest?.sessionId;
192
215
  }
193
216
  /** Check if the MCP notification channel is functional for the current session. */
194
- function isChannelAvailable() {
217
+ export function isChannelAvailable() {
195
218
  if (process.env.CLAUDECODE !== '1')
196
219
  return false;
197
220
  const currentSsePort = process.env.CLAUDE_CODE_SSE_PORT;
198
221
  if (!currentSsePort)
199
222
  return false;
200
- const asyncDir = join(paths.data, 'async');
201
- try {
202
- const files = readdirSync(asyncDir)
203
- .filter((f) => f.startsWith('relay-session-') && f.endsWith('.id'));
204
- for (const file of files) {
205
- try {
206
- const data = JSON.parse(readFileSync(join(asyncDir, file), 'utf-8'));
207
- if (data.ssePort === currentSsePort && data.pid && isProcessAlive(data.pid)) {
208
- return true;
209
- }
210
- }
211
- catch { /* skip */ }
212
- }
213
- }
214
- catch { /* dir missing */ }
215
- return false;
223
+ const records = readLiveRelayRecords(join(paths.data, 'async'));
224
+ return records.some((r) => r.ssePort === currentSsePort);
216
225
  }
217
226
  export function registerDelegateCommand(program) {
218
227
  const delegate = program
@@ -230,7 +239,7 @@ export function registerDelegateCommand(program) {
230
239
  .option('--includeDirs <dirs>', 'Additional directories (comma-separated)')
231
240
  .option('--session <id>', 'Claude Code session ID for completion notifications')
232
241
  .option('--backend <type>', 'Adapter backend: direct (default) or terminal (tmux/wezterm)')
233
- .option('--async', 'Run in the background with MCP notifications (default is synchronous)')
242
+ .option('--async', 'Run detached in the background; results delivered via MCP channel notifications (default: synchronous)')
234
243
  .addOption(new Option('--worker').hideHelp())
235
244
  .action(async (prompt, opts) => {
236
245
  if (!prompt) {
@@ -265,9 +274,11 @@ export function registerDelegateCommand(program) {
265
274
  backend,
266
275
  };
267
276
  try {
268
- // Auto-detect: async only when the MCP notification channel can deliver
269
- // results back. Checks CLAUDECODE env + relay session matched by SSE port.
270
- const useAsync = !opts.worker && (opts.async || isChannelAvailable());
277
+ // Default = sync. Async only when --async is explicitly passed.
278
+ // Channel auto-detection is unreliable: CC's --channels mode is not
279
+ // observable from the MCP server side (verified via clientCapabilities
280
+ // diff — both modes announce identical capabilities).
281
+ const useAsync = !opts.worker && opts.async === true;
271
282
  if (useAsync) {
272
283
  process.stderr.write(`[MAESTRO_EXEC_ID=${execId}]\n`);
273
284
  launchDetachedDelegateWorker(request);
@@ -277,6 +288,31 @@ export function registerDelegateCommand(program) {
277
288
  }
278
289
  const runner = new CliAgentRunner();
279
290
  const syncMode = !opts.worker;
291
+ // Sync mode: emit ONE broker event at start so any active channel
292
+ // subscriber (CC launched with --dangerously-load-development-channels)
293
+ // sees a "started" notification. No subsequent events are published —
294
+ // sync output returns directly via stdout when the command completes.
295
+ if (syncMode) {
296
+ try {
297
+ const broker = new DelegateBrokerClient();
298
+ broker.publishEvent({
299
+ jobId: execId,
300
+ type: 'status_update',
301
+ status: 'running',
302
+ payload: { summary: `${toolName}/${mode} started (sync)` },
303
+ jobMetadata: {
304
+ tool: toolName,
305
+ mode,
306
+ workDir,
307
+ backend,
308
+ ...(request.sessionId ? { sessionId: request.sessionId } : {}),
309
+ },
310
+ });
311
+ }
312
+ catch {
313
+ // Broker publish is best-effort; sync execution must continue.
314
+ }
315
+ }
280
316
  const exitCode = await runner.run({ ...request, sync: syncMode });
281
317
  // In sync mode, output the final result after completion
282
318
  if (syncMode) {