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.
- package/.claude/commands/maestro-brainstorm.md +10 -1
- package/.claude/commands/maestro-milestone-audit.md +1 -1
- package/.claude/commands/maestro-milestone-complete.md +2 -1
- package/.claude/commands/maestro-milestone-release.md +96 -0
- package/.claude/commands/maestro-phase-add.md +9 -1
- package/.claude/commands/maestro-phase-transition.md +9 -1
- package/.claude/commands/maestro.md +6 -0
- package/.claude/commands/manage-codebase-rebuild.md +76 -50
- package/.claude/commands/manage-codebase-refresh.md +9 -1
- package/.claude/commands/quality-refactor.md +1 -1
- package/.claude/commands/quality-sync.md +9 -1
- package/.claude/commands/spec-setup.md +1 -1
- package/.codex/skills/maestro-coordinate/SKILL.md +20 -6
- package/.codex/skills/manage-issue-analyze/SKILL.md +1 -1
- package/.codex/skills/quality-retrospective/SKILL.md +3 -3
- package/.codex/skills/team-coordinate/SKILL.md +1 -1
- package/.codex/skills/team-coordinate/roles/coordinator/commands/monitor.md +19 -10
- package/.codex/skills/team-coordinate/roles/coordinator/role.md +2 -2
- package/.codex/skills/team-executor/SKILL.md +1 -1
- package/.codex/skills/team-executor/roles/executor/commands/monitor.md +20 -9
- package/.codex/skills/team-lifecycle-v4/SKILL.md +2 -2
- package/.codex/skills/team-lifecycle-v4/roles/coordinator/commands/monitor.md +31 -12
- package/.codex/skills/team-lifecycle-v4/roles/coordinator/role.md +1 -1
- package/.codex/skills/team-quality-assurance/SKILL.md +1 -1
- package/.codex/skills/team-quality-assurance/roles/coordinator/commands/monitor.md +20 -9
- package/.codex/skills/team-quality-assurance/roles/coordinator/role.md +1 -1
- package/.codex/skills/team-review/SKILL.md +1 -1
- package/.codex/skills/team-review/roles/coordinator/commands/monitor.md +20 -9
- package/.codex/skills/team-review/roles/coordinator/role.md +1 -1
- package/.codex/skills/team-tech-debt/SKILL.md +1 -1
- package/.codex/skills/team-tech-debt/roles/coordinator/commands/monitor.md +20 -9
- package/.codex/skills/team-tech-debt/roles/coordinator/role.md +1 -1
- package/.codex/skills/team-testing/SKILL.md +2 -2
- package/.codex/skills/team-testing/roles/coordinator/commands/monitor.md +20 -9
- package/.codex/skills/team-testing/roles/coordinator/role.md +1 -1
- package/chains/singles/spec-map.json +2 -2
- package/dashboard/dist-server/dashboard/src/server/agents/codex-cli-adapter.js +1 -1
- package/dashboard/dist-server/dashboard/src/server/agents/codex-cli-adapter.js.map +1 -1
- package/dashboard/dist-server/src/commands/delegate.d.ts +23 -0
- package/dashboard/dist-server/src/commands/delegate.js +91 -55
- package/dashboard/dist-server/src/commands/delegate.js.map +1 -1
- package/dist/src/brainstorm-visualize/frame.d.ts +8 -0
- package/dist/src/brainstorm-visualize/frame.d.ts.map +1 -0
- package/dist/src/brainstorm-visualize/frame.js +655 -0
- package/dist/src/brainstorm-visualize/frame.js.map +1 -0
- package/dist/src/brainstorm-visualize/server.d.ts +2 -0
- package/dist/src/brainstorm-visualize/server.d.ts.map +1 -0
- package/dist/src/brainstorm-visualize/server.js +180 -0
- package/dist/src/brainstorm-visualize/server.js.map +1 -0
- package/dist/src/cli.js +11 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/brainstorm-visualize.d.ts +3 -0
- package/dist/src/commands/brainstorm-visualize.d.ts.map +1 -0
- package/dist/src/commands/brainstorm-visualize.js +337 -0
- package/dist/src/commands/brainstorm-visualize.js.map +1 -0
- package/dist/src/commands/core-memory.d.ts +3 -0
- package/dist/src/commands/core-memory.d.ts.map +1 -0
- package/dist/src/commands/core-memory.js +101 -0
- package/dist/src/commands/core-memory.js.map +1 -0
- package/dist/src/commands/delegate.d.ts +23 -0
- package/dist/src/commands/delegate.d.ts.map +1 -1
- package/dist/src/commands/delegate.js +91 -55
- package/dist/src/commands/delegate.js.map +1 -1
- package/dist/src/mcp/delegate-channel-relay.d.ts.map +1 -1
- package/dist/src/mcp/delegate-channel-relay.js +6 -0
- package/dist/src/mcp/delegate-channel-relay.js.map +1 -1
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +27 -0
- package/dist/src/mcp/server.js.map +1 -1
- package/package.json +1 -1
- 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:
|
|
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
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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:
|
|
238
|
-
if (cpResult.timed_out) {
|
|
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:
|
|
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:
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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": "
|
|
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",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-cli-adapter.js","sourceRoot":"","sources":["../../../../../src/server/agents/codex-cli-adapter.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kEAAkE;AAClE,8EAA8E;AAE9E,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAuC,MAAM,eAAe,CAAC;AAMrF,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AA+CjD,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAE9E,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAE7C,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E,MAAM,OAAO,eAAgB,SAAQ,gBAAgB;IAC1C,SAAS,GAAG,OAAgB,CAAC;IAErB,cAAc,GAAG,IAAI,GAAG,EAAwB,CAAC;IACjD,kBAAkB,GAAG,IAAI,GAAG,EAA6B,CAAC;IAC1D,cAAc,GAAG,IAAI,GAAG,EAAyB,CAAC;IAEnE,4EAA4E;IAElE,KAAK,CAAC,OAAO,CACrB,SAAiB,EACjB,MAAmB;QAEnB,MAAM,IAAI,GAAG;YACX,MAAM;YACN,
|
|
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
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
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
|
|
155
|
-
|
|
156
|
-
const currentSsePort = process.env.CLAUDE_CODE_SSE_PORT;
|
|
162
|
+
export function readLiveRelayRecords(asyncDir) {
|
|
163
|
+
let files;
|
|
157
164
|
try {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
-
|
|
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
|
-
|
|
189
|
+
live.push(data);
|
|
188
190
|
}
|
|
189
|
-
|
|
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
|
|
201
|
-
|
|
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
|
|
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
|
-
//
|
|
269
|
-
//
|
|
270
|
-
|
|
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) {
|