@snipcodeit/mgw 0.3.0 → 0.6.0
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/README.md +1 -0
- package/bin/mgw-install.cjs +121 -24
- package/commands/board/create.md +192 -0
- package/commands/board/sync.md +44 -0
- package/commands/board/views.md +23 -0
- package/commands/context.md +183 -0
- package/commands/handoff.md +169 -0
- package/commands/issue.md +62 -0
- package/commands/milestone.md +37 -5
- package/commands/project.md +19 -0
- package/commands/run/execute.md +604 -27
- package/commands/run/pr-create.md +88 -0
- package/commands/run/triage.md +199 -2
- package/commands/run/worktree.md +41 -0
- package/commands/sync.md +69 -0
- package/commands/workflows/gsd.md +71 -0
- package/commands/workflows/state.md +340 -1
- package/dist/bin/mgw.cjs +14 -11
- package/dist/{index-s7v-ifd0.cjs → index-CHrVAIMY.cjs} +414 -23
- package/dist/lib/index.cjs +997 -20
- package/package.json +9 -4
package/commands/run/execute.md
CHANGED
|
@@ -4,9 +4,16 @@ description: Execute GSD pipeline (quick or milestone route) and post execution
|
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
<step name="execute_gsd_quick">
|
|
7
|
-
**Execute GSD pipeline (quick / quick --full route):**
|
|
7
|
+
**Execute GSD pipeline (quick / quick --full / plan-phase route):**
|
|
8
8
|
|
|
9
|
-
Only run this step if gsd_route
|
|
9
|
+
Only run this step if gsd_route matches any of these (prefixed or unprefixed):
|
|
10
|
+
- `quick` or `gsd:quick`
|
|
11
|
+
- `quick --full` or `gsd:quick --full`
|
|
12
|
+
- `plan-phase` or `gsd:plan-phase`
|
|
13
|
+
|
|
14
|
+
`plan-phase` follows the same lifecycle as `quick --full` (init -> plan -> check -> execute -> verify -> publish) so it is handled here with FULL_MODE forced on.
|
|
15
|
+
|
|
16
|
+
`plan-phase` follows the same lifecycle as `quick --full` (init → plan → check → execute → verify → publish) so it is handled here with FULL_MODE forced on.
|
|
10
17
|
|
|
11
18
|
**Retry loop initialization:**
|
|
12
19
|
```bash
|
|
@@ -60,12 +67,47 @@ QUICK_DIR=".planning/quick/${next_num}-${slug}"
|
|
|
60
67
|
mkdir -p "$QUICK_DIR"
|
|
61
68
|
```
|
|
62
69
|
|
|
63
|
-
3. **
|
|
70
|
+
3. **Assemble MGW context and spawn planner (task agent, with diagnostic capture):**
|
|
71
|
+
|
|
72
|
+
Assemble multi-machine context from GitHub issue comments before spawning:
|
|
73
|
+
```bash
|
|
74
|
+
MGW_CONTEXT=$(node -e "
|
|
75
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
76
|
+
ic.buildGSDPromptContext({
|
|
77
|
+
milestone: ${MILESTONE_NUM},
|
|
78
|
+
phase: ${PHASE_NUMBER},
|
|
79
|
+
issueNumber: ${ISSUE_NUMBER},
|
|
80
|
+
includeVision: true,
|
|
81
|
+
includePriorSummaries: true,
|
|
82
|
+
includeCurrentPlan: false
|
|
83
|
+
}).then(ctx => process.stdout.write(ctx));
|
|
84
|
+
" 2>/dev/null || echo "")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
<!-- mgw:criticality=critical spawn_point=planner -->
|
|
88
|
+
<!-- Critical: plan creation is required for pipeline to proceed.
|
|
89
|
+
On failure: retry via existing retry loop, then dead-letter. -->
|
|
90
|
+
|
|
91
|
+
**Pre-spawn diagnostic hook (planner):**
|
|
92
|
+
```bash
|
|
93
|
+
DIAG_PLANNER=$(node -e "
|
|
94
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
95
|
+
const id = dh.beforeAgentSpawn({
|
|
96
|
+
agentType: 'gsd-planner',
|
|
97
|
+
issueNumber: ${ISSUE_NUMBER},
|
|
98
|
+
prompt: 'Plan: ${issue_title}',
|
|
99
|
+
repoRoot: '${REPO_ROOT}'
|
|
100
|
+
});
|
|
101
|
+
process.stdout.write(id);
|
|
102
|
+
" 2>/dev/null || echo "")
|
|
103
|
+
```
|
|
64
104
|
```
|
|
65
105
|
Task(
|
|
66
106
|
prompt="
|
|
67
107
|
<planning_context>
|
|
68
108
|
|
|
109
|
+
${MGW_CONTEXT}
|
|
110
|
+
|
|
69
111
|
**Mode:** ${FULL_MODE ? 'quick-full' : 'quick'}
|
|
70
112
|
**Directory:** ${QUICK_DIR}
|
|
71
113
|
**Description:** ${TASK_DESCRIPTION}
|
|
@@ -109,7 +151,68 @@ Return: ## PLANNING COMPLETE with plan path
|
|
|
109
151
|
)
|
|
110
152
|
```
|
|
111
153
|
|
|
112
|
-
4. **
|
|
154
|
+
4. **Update checkpoint after planner completes:**
|
|
155
|
+
```bash
|
|
156
|
+
# Checkpoint: record plan completion and set resume to plan-check or execution
|
|
157
|
+
node -e "
|
|
158
|
+
const { updateCheckpoint } = require('${REPO_ROOT}/lib/state.cjs');
|
|
159
|
+
updateCheckpoint(${ISSUE_NUMBER}, {
|
|
160
|
+
pipeline_step: 'plan',
|
|
161
|
+
step_progress: { plan_path: '${QUICK_DIR}/${next_num}-PLAN.md', plan_checked: false, revision_count: 0 },
|
|
162
|
+
last_agent_output: '${QUICK_DIR}/${next_num}-PLAN.md',
|
|
163
|
+
artifacts: [{ path: '${QUICK_DIR}/${next_num}-PLAN.md', type: 'plan', created_at: new Date().toISOString() }],
|
|
164
|
+
step_history: [{ step: 'plan', completed_at: new Date().toISOString(), agent_type: 'gsd-planner', output_path: '${QUICK_DIR}/${next_num}-PLAN.md' }],
|
|
165
|
+
resume: { action: '${FULL_MODE ? \"run-plan-checker\" : \"spawn-executor\"}', context: { quick_dir: '${QUICK_DIR}', plan_num: ${next_num} } }
|
|
166
|
+
|
|
167
|
+
**Post-spawn diagnostic hook (planner):**
|
|
168
|
+
```bash
|
|
169
|
+
PLANNER_EXIT=$( [ -f "${QUICK_DIR}/${next_num}-PLAN.md" ] && echo "success" || echo "error" )
|
|
170
|
+
node -e "
|
|
171
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
172
|
+
dh.afterAgentSpawn({
|
|
173
|
+
diagId: '${DIAG_PLANNER}',
|
|
174
|
+
exitReason: '${PLANNER_EXIT}',
|
|
175
|
+
repoRoot: '${REPO_ROOT}'
|
|
176
|
+
});
|
|
177
|
+
" 2>/dev/null || true
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
4. **Checkpoint: record plan completion (atomic write):**
|
|
181
|
+
```bash
|
|
182
|
+
# Checkpoint: record plan completion and set resume to plan-check or execution.
|
|
183
|
+
# All checkpoint writes use atomicWriteJson() — write to .tmp then rename.
|
|
184
|
+
node -e "
|
|
185
|
+
const { updateCheckpoint } = require('${REPO_ROOT}/lib/state.cjs');
|
|
186
|
+
updateCheckpoint(${ISSUE_NUMBER}, {
|
|
187
|
+
pipeline_step: 'plan',
|
|
188
|
+
step_progress: { plan_path: '${QUICK_DIR}/${next_num}-PLAN.md', plan_checked: false, revision_count: 0 },
|
|
189
|
+
last_agent_output: '${QUICK_DIR}/${next_num}-PLAN.md',
|
|
190
|
+
artifacts: [{ path: '${QUICK_DIR}/${next_num}-PLAN.md', type: 'plan', created_at: new Date().toISOString() }],
|
|
191
|
+
step_history: [{ step: 'plan', completed_at: new Date().toISOString(), agent_type: 'gsd-planner', output_path: '${QUICK_DIR}/${next_num}-PLAN.md' }],
|
|
192
|
+
resume: { action: '${FULL_MODE ? \"run-plan-checker\" : \"spawn-executor\"}', context: { quick_dir: '${QUICK_DIR}', plan_num: ${next_num} } }
|
|
193
|
+
});
|
|
194
|
+
" 2>/dev/null || true
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
4b. **Publish plan comment (non-blocking):**
|
|
198
|
+
|
|
199
|
+
4b. **Publish plan comment (non-blocking):**
|
|
200
|
+
|
|
201
|
+
4. **Publish plan comment (non-blocking):**
|
|
202
|
+
```bash
|
|
203
|
+
PLAN_FILE="${QUICK_DIR}/${next_num}-PLAN.md"
|
|
204
|
+
if [ -f "$PLAN_FILE" ]; then
|
|
205
|
+
node -e "
|
|
206
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
207
|
+
const fs = require('fs');
|
|
208
|
+
const content = fs.readFileSync('${PLAN_FILE}', 'utf-8');
|
|
209
|
+
ic.postPlanningComment(${ISSUE_NUMBER}, 'plan', content, { phase: ${next_num}, milestone: ${MILESTONE_NUM} })
|
|
210
|
+
.catch(e => console.error('WARNING: Failed to post plan comment:', e.message));
|
|
211
|
+
" 2>/dev/null || true
|
|
212
|
+
fi
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
5. **Verify plan exists** at `${QUICK_DIR}/${next_num}-PLAN.md`
|
|
113
216
|
|
|
114
217
|
5. **Pre-flight plan structure check (gsd-tools):**
|
|
115
218
|
```bash
|
|
@@ -118,6 +221,37 @@ PLAN_CHECK=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs verify plan-structur
|
|
|
118
221
|
Parse the JSON result. If structural issues found, include them in the plan-checker prompt below so it has concrete problems to evaluate rather than searching from scratch.
|
|
119
222
|
|
|
120
223
|
6. **(If --full) Spawn plan-checker, handle revision loop (max 2 iterations):**
|
|
224
|
+
|
|
225
|
+
<!-- mgw:criticality=advisory spawn_point=plan-checker -->
|
|
226
|
+
<!-- Advisory: plan checking is a quality gate, not a pipeline blocker.
|
|
227
|
+
If this agent fails, log a warning and proceed with the unchecked plan.
|
|
228
|
+
The plan was already verified structurally by gsd-tools verify plan-structure.
|
|
229
|
+
|
|
230
|
+
Graceful degradation pattern:
|
|
231
|
+
```
|
|
232
|
+
PLAN_CHECK_RESULT=$(wrapAdvisoryAgent(Task(...), 'plan-checker', {
|
|
233
|
+
issueNumber: ISSUE_NUMBER,
|
|
234
|
+
fallback: '## VERIFICATION PASSED (plan-checker unavailable — structural check only)'
|
|
235
|
+
}))
|
|
236
|
+
# If fallback returned, skip the revision loop and proceed to execution
|
|
237
|
+
```
|
|
238
|
+
-->
|
|
239
|
+
|
|
240
|
+
6. **(If --full) Spawn plan-checker (with diagnostic capture), handle revision loop (max 2 iterations):**
|
|
241
|
+
|
|
242
|
+
**Pre-spawn diagnostic hook (plan-checker):**
|
|
243
|
+
```bash
|
|
244
|
+
DIAG_CHECKER=$(node -e "
|
|
245
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
246
|
+
const id = dh.beforeAgentSpawn({
|
|
247
|
+
agentType: 'gsd-plan-checker',
|
|
248
|
+
issueNumber: ${ISSUE_NUMBER},
|
|
249
|
+
prompt: 'Check quick plan: ${issue_title}',
|
|
250
|
+
repoRoot: '${REPO_ROOT}'
|
|
251
|
+
});
|
|
252
|
+
process.stdout.write(id);
|
|
253
|
+
" 2>/dev/null || echo "")
|
|
254
|
+
```
|
|
121
255
|
```
|
|
122
256
|
Task(
|
|
123
257
|
prompt="
|
|
@@ -159,10 +293,43 @@ Skip: context compliance (no CONTEXT.md), cross-plan deps (single plan), ROADMAP
|
|
|
159
293
|
)
|
|
160
294
|
```
|
|
161
295
|
|
|
296
|
+
**Post-spawn diagnostic hook (plan-checker):**
|
|
297
|
+
```bash
|
|
298
|
+
node -e "
|
|
299
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
300
|
+
dh.afterAgentSpawn({
|
|
301
|
+
diagId: '${DIAG_CHECKER}',
|
|
302
|
+
exitReason: 'success',
|
|
303
|
+
repoRoot: '${REPO_ROOT}'
|
|
304
|
+
});
|
|
305
|
+
" 2>/dev/null || true
|
|
306
|
+
```
|
|
307
|
+
|
|
162
308
|
If issues found and iteration < 2: spawn planner revision, then re-check.
|
|
163
309
|
If iteration >= 2: offer force proceed or abort.
|
|
164
310
|
|
|
165
311
|
7. **Spawn executor (task agent):**
|
|
312
|
+
|
|
313
|
+
<!-- mgw:criticality=critical spawn_point=executor -->
|
|
314
|
+
<!-- Critical: execution produces the code changes. Without it, there is
|
|
315
|
+
nothing to commit or PR. On failure: retry via existing retry loop,
|
|
316
|
+
then dead-letter. -->
|
|
317
|
+
|
|
318
|
+
7. **Spawn executor (task agent, with diagnostic capture):**
|
|
319
|
+
|
|
320
|
+
**Pre-spawn diagnostic hook (executor):**
|
|
321
|
+
```bash
|
|
322
|
+
DIAG_EXECUTOR=$(node -e "
|
|
323
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
324
|
+
const id = dh.beforeAgentSpawn({
|
|
325
|
+
agentType: 'gsd-executor',
|
|
326
|
+
issueNumber: ${ISSUE_NUMBER},
|
|
327
|
+
prompt: 'Execute: ${issue_title}',
|
|
328
|
+
repoRoot: '${REPO_ROOT}'
|
|
329
|
+
});
|
|
330
|
+
process.stdout.write(id);
|
|
331
|
+
" 2>/dev/null || echo "")
|
|
332
|
+
```
|
|
166
333
|
```
|
|
167
334
|
Task(
|
|
168
335
|
prompt="
|
|
@@ -187,13 +354,106 @@ Execute quick task ${next_num}.
|
|
|
187
354
|
)
|
|
188
355
|
```
|
|
189
356
|
|
|
190
|
-
8. **
|
|
357
|
+
8. **Update checkpoint after executor completes:**
|
|
358
|
+
```bash
|
|
359
|
+
# Checkpoint: record execution completion and set resume to verification
|
|
360
|
+
node -e "
|
|
361
|
+
const { updateCheckpoint } = require('${REPO_ROOT}/lib/state.cjs');
|
|
362
|
+
updateCheckpoint(${ISSUE_NUMBER}, {
|
|
363
|
+
pipeline_step: 'execute',
|
|
364
|
+
step_progress: { tasks_completed: ${TASK_COUNT}, tasks_total: ${TASK_COUNT} },
|
|
365
|
+
last_agent_output: '${QUICK_DIR}/${next_num}-SUMMARY.md',
|
|
366
|
+
artifacts: [{ path: '${QUICK_DIR}/${next_num}-SUMMARY.md', type: 'summary', created_at: new Date().toISOString() }],
|
|
367
|
+
step_history: [{ step: 'execute', completed_at: new Date().toISOString(), agent_type: 'gsd-executor', output_path: '${QUICK_DIR}/${next_num}-SUMMARY.md' }],
|
|
368
|
+
resume: { action: '${FULL_MODE ? \"spawn-verifier\" : \"create-pr\"}', context: { quick_dir: '${QUICK_DIR}', plan_num: ${next_num} } }
|
|
369
|
+
|
|
370
|
+
**Post-spawn diagnostic hook (executor):**
|
|
371
|
+
```bash
|
|
372
|
+
EXECUTOR_EXIT=$( [ -f "${QUICK_DIR}/${next_num}-SUMMARY.md" ] && echo "success" || echo "error" )
|
|
373
|
+
node -e "
|
|
374
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
375
|
+
dh.afterAgentSpawn({
|
|
376
|
+
diagId: '${DIAG_EXECUTOR}',
|
|
377
|
+
exitReason: '${EXECUTOR_EXIT}',
|
|
378
|
+
repoRoot: '${REPO_ROOT}'
|
|
379
|
+
});
|
|
380
|
+
" 2>/dev/null || true
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
8. **Checkpoint: record execution completion (atomic write):**
|
|
384
|
+
```bash
|
|
385
|
+
# Checkpoint: record execution completion and set resume to verification or PR creation.
|
|
386
|
+
node -e "
|
|
387
|
+
const { updateCheckpoint } = require('${REPO_ROOT}/lib/state.cjs');
|
|
388
|
+
updateCheckpoint(${ISSUE_NUMBER}, {
|
|
389
|
+
pipeline_step: 'execute',
|
|
390
|
+
step_progress: { tasks_completed: ${TASK_COUNT}, tasks_total: ${TASK_COUNT} },
|
|
391
|
+
last_agent_output: '${QUICK_DIR}/${next_num}-SUMMARY.md',
|
|
392
|
+
artifacts: [{ path: '${QUICK_DIR}/${next_num}-SUMMARY.md', type: 'summary', created_at: new Date().toISOString() }],
|
|
393
|
+
step_history: [{ step: 'execute', completed_at: new Date().toISOString(), agent_type: 'gsd-executor', output_path: '${QUICK_DIR}/${next_num}-SUMMARY.md' }],
|
|
394
|
+
resume: { action: '${FULL_MODE ? \"spawn-verifier\" : \"create-pr\"}', context: { quick_dir: '${QUICK_DIR}', plan_num: ${next_num} } }
|
|
395
|
+
});
|
|
396
|
+
" 2>/dev/null || true
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
8b. **Publish summary comment (non-blocking):**
|
|
400
|
+
|
|
401
|
+
8b. **Publish summary comment (non-blocking):**
|
|
402
|
+
|
|
403
|
+
8. **Publish summary comment (non-blocking):**
|
|
404
|
+
```bash
|
|
405
|
+
SUMMARY_FILE="${QUICK_DIR}/${next_num}-SUMMARY.md"
|
|
406
|
+
if [ -f "$SUMMARY_FILE" ]; then
|
|
407
|
+
node -e "
|
|
408
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
409
|
+
const fs = require('fs');
|
|
410
|
+
const content = fs.readFileSync('${SUMMARY_FILE}', 'utf-8');
|
|
411
|
+
ic.postPlanningComment(${ISSUE_NUMBER}, 'summary', content, { phase: ${next_num}, milestone: ${MILESTONE_NUM} })
|
|
412
|
+
.catch(e => console.error('WARNING: Failed to post summary comment:', e.message));
|
|
413
|
+
" 2>/dev/null || true
|
|
414
|
+
fi
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
9. **Verify summary (gsd-tools):**
|
|
191
418
|
```bash
|
|
192
419
|
VERIFY_RESULT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs verify-summary "${QUICK_DIR}/${next_num}-SUMMARY.md")
|
|
193
420
|
```
|
|
194
421
|
Parse JSON result. Use `passed` field for go/no-go. Checks summary existence, files created, and commits.
|
|
195
422
|
|
|
196
423
|
9. **(If --full) Spawn verifier:**
|
|
424
|
+
|
|
425
|
+
<!-- mgw:criticality=advisory spawn_point=verifier -->
|
|
426
|
+
<!-- Advisory: verification is quality assurance after execution is complete.
|
|
427
|
+
The code changes and commits already exist. If verification fails,
|
|
428
|
+
log a warning and proceed to PR creation with a note that verification
|
|
429
|
+
was skipped.
|
|
430
|
+
|
|
431
|
+
Graceful degradation pattern:
|
|
432
|
+
```
|
|
433
|
+
VERIFY_RESULT=$(wrapAdvisoryAgent(Task(...), 'verifier', {
|
|
434
|
+
issueNumber: ISSUE_NUMBER,
|
|
435
|
+
fallback: null
|
|
436
|
+
}))
|
|
437
|
+
# If fallback returned (null), create a minimal VERIFICATION.md:
|
|
438
|
+
# "## VERIFICATION SKIPPED\nVerifier agent unavailable. Manual review recommended."
|
|
439
|
+
```
|
|
440
|
+
-->
|
|
441
|
+
|
|
442
|
+
9. **(If --full) Spawn verifier (with diagnostic capture):**
|
|
443
|
+
|
|
444
|
+
**Pre-spawn diagnostic hook (verifier):**
|
|
445
|
+
```bash
|
|
446
|
+
DIAG_VERIFIER=$(node -e "
|
|
447
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
448
|
+
const id = dh.beforeAgentSpawn({
|
|
449
|
+
agentType: 'gsd-verifier',
|
|
450
|
+
issueNumber: ${ISSUE_NUMBER},
|
|
451
|
+
prompt: 'Verify: ${issue_title}',
|
|
452
|
+
repoRoot: '${REPO_ROOT}'
|
|
453
|
+
});
|
|
454
|
+
process.stdout.write(id);
|
|
455
|
+
" 2>/dev/null || echo "")
|
|
456
|
+
```
|
|
197
457
|
```
|
|
198
458
|
Task(
|
|
199
459
|
prompt="
|
|
@@ -214,7 +474,67 @@ Check must_haves against actual codebase. Create VERIFICATION.md at ${QUICK_DIR}
|
|
|
214
474
|
)
|
|
215
475
|
```
|
|
216
476
|
|
|
217
|
-
10. **
|
|
477
|
+
10. **Update checkpoint after verifier completes (--full only):**
|
|
478
|
+
```bash
|
|
479
|
+
# Checkpoint: record verification completion and set resume to PR creation
|
|
480
|
+
node -e "
|
|
481
|
+
const { updateCheckpoint } = require('${REPO_ROOT}/lib/state.cjs');
|
|
482
|
+
updateCheckpoint(${ISSUE_NUMBER}, {
|
|
483
|
+
pipeline_step: 'verify',
|
|
484
|
+
step_progress: { verification_path: '${QUICK_DIR}/${next_num}-VERIFICATION.md', must_haves_checked: true },
|
|
485
|
+
last_agent_output: '${QUICK_DIR}/${next_num}-VERIFICATION.md',
|
|
486
|
+
artifacts: [{ path: '${QUICK_DIR}/${next_num}-VERIFICATION.md', type: 'verification', created_at: new Date().toISOString() }],
|
|
487
|
+
step_history: [{ step: 'verify', completed_at: new Date().toISOString(), agent_type: 'gsd-verifier', output_path: '${QUICK_DIR}/${next_num}-VERIFICATION.md' }],
|
|
488
|
+
resume: { action: 'create-pr', context: { quick_dir: '${QUICK_DIR}', plan_num: ${next_num} } }
|
|
489
|
+
|
|
490
|
+
**Post-spawn diagnostic hook (verifier):**
|
|
491
|
+
```bash
|
|
492
|
+
VERIFIER_EXIT=$( [ -f "${QUICK_DIR}/${next_num}-VERIFICATION.md" ] && echo "success" || echo "error" )
|
|
493
|
+
node -e "
|
|
494
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
495
|
+
dh.afterAgentSpawn({
|
|
496
|
+
diagId: '${DIAG_VERIFIER}',
|
|
497
|
+
exitReason: '${VERIFIER_EXIT}',
|
|
498
|
+
repoRoot: '${REPO_ROOT}'
|
|
499
|
+
});
|
|
500
|
+
" 2>/dev/null || true
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
10. **Checkpoint: record verification completion (atomic write, --full only):**
|
|
504
|
+
```bash
|
|
505
|
+
# Checkpoint: record verification completion and set resume to PR creation.
|
|
506
|
+
node -e "
|
|
507
|
+
const { updateCheckpoint } = require('${REPO_ROOT}/lib/state.cjs');
|
|
508
|
+
updateCheckpoint(${ISSUE_NUMBER}, {
|
|
509
|
+
pipeline_step: 'verify',
|
|
510
|
+
step_progress: { verification_path: '${QUICK_DIR}/${next_num}-VERIFICATION.md', must_haves_checked: true },
|
|
511
|
+
last_agent_output: '${QUICK_DIR}/${next_num}-VERIFICATION.md',
|
|
512
|
+
artifacts: [{ path: '${QUICK_DIR}/${next_num}-VERIFICATION.md', type: 'verification', created_at: new Date().toISOString() }],
|
|
513
|
+
step_history: [{ step: 'verify', completed_at: new Date().toISOString(), agent_type: 'gsd-verifier', output_path: '${QUICK_DIR}/${next_num}-VERIFICATION.md' }],
|
|
514
|
+
resume: { action: 'create-pr', context: { quick_dir: '${QUICK_DIR}', plan_num: ${next_num} } }
|
|
515
|
+
});
|
|
516
|
+
" 2>/dev/null || true
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
10b. **Publish verification comment (non-blocking, --full only):**
|
|
520
|
+
|
|
521
|
+
10b. **Publish verification comment (non-blocking, --full only):**
|
|
522
|
+
|
|
523
|
+
10. **Publish verification comment (non-blocking, --full only):**
|
|
524
|
+
```bash
|
|
525
|
+
VERIFICATION_FILE="${QUICK_DIR}/${next_num}-VERIFICATION.md"
|
|
526
|
+
if [ -f "$VERIFICATION_FILE" ]; then
|
|
527
|
+
node -e "
|
|
528
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
529
|
+
const fs = require('fs');
|
|
530
|
+
const content = fs.readFileSync('${VERIFICATION_FILE}', 'utf-8');
|
|
531
|
+
ic.postPlanningComment(${ISSUE_NUMBER}, 'verification', content, { phase: ${next_num}, milestone: ${MILESTONE_NUM} })
|
|
532
|
+
.catch(e => console.error('WARNING: Failed to post verification comment:', e.message));
|
|
533
|
+
" 2>/dev/null || true
|
|
534
|
+
fi
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
11. **Post-execution artifact verification (non-blocking):**
|
|
218
538
|
```bash
|
|
219
539
|
ARTIFACT_CHECK=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs verify artifacts "${QUICK_DIR}/${next_num}-PLAN.md" 2>/dev/null || echo '{"passed":true}')
|
|
220
540
|
KEYLINK_CHECK=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs verify key-links "${QUICK_DIR}/${next_num}-PLAN.md" 2>/dev/null || echo '{"passed":true}')
|
|
@@ -234,8 +554,13 @@ If any step above fails (executor or verifier agent returns error, summary missi
|
|
|
234
554
|
|
|
235
555
|
```bash
|
|
236
556
|
# On failure — classify and decide whether to retry
|
|
557
|
+
# CRITICALITY-AWARE: check if the failing agent is advisory first.
|
|
558
|
+
# Advisory agent failures are logged and skipped (pipeline continues).
|
|
559
|
+
# Critical agent failures follow the existing retry/dead-letter flow.
|
|
560
|
+
|
|
237
561
|
FAILURE_CLASS=$(node -e "
|
|
238
562
|
const { classifyFailure, canRetry, incrementRetry, getBackoffMs } = require('./lib/retry.cjs');
|
|
563
|
+
const { isAdvisory } = require('./lib/agent-criticality.cjs');
|
|
239
564
|
const { loadActiveIssue } = require('./lib/state.cjs');
|
|
240
565
|
const fs = require('fs'), path = require('path');
|
|
241
566
|
|
|
@@ -245,29 +570,43 @@ const file = files.find(f => f.startsWith('${ISSUE_NUMBER}-') && f.endsWith('.js
|
|
|
245
570
|
const filePath = path.join(activeDir, file);
|
|
246
571
|
let issueState = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
247
572
|
|
|
248
|
-
//
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
issueState.last_failure_class = result.class;
|
|
255
|
-
|
|
256
|
-
if (result.class === 'transient' && canRetry(issueState)) {
|
|
257
|
-
const backoff = getBackoffMs(issueState.retry_count || 0);
|
|
258
|
-
issueState = incrementRetry(issueState);
|
|
259
|
-
fs.writeFileSync(filePath, JSON.stringify(issueState, null, 2));
|
|
260
|
-
// Output: backoff ms so shell can sleep
|
|
261
|
-
console.log('retry:' + backoff + ':' + result.class);
|
|
573
|
+
// Check if the failing agent is advisory
|
|
574
|
+
const failingSpawnPoint = '${FAILING_SPAWN_POINT}';
|
|
575
|
+
if (failingSpawnPoint && isAdvisory(failingSpawnPoint)) {
|
|
576
|
+
// Advisory agent failure — log warning and continue pipeline
|
|
577
|
+
console.error('MGW WARNING: Advisory agent \"' + failingSpawnPoint + '\" failed. Continuing pipeline.');
|
|
578
|
+
console.log('advisory_degraded:' + failingSpawnPoint);
|
|
262
579
|
} else {
|
|
263
|
-
//
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
console.
|
|
580
|
+
// Critical agent failure — classify and apply retry/dead-letter logic
|
|
581
|
+
const error = { message: '${EXECUTION_ERROR_MESSAGE}' };
|
|
582
|
+
const result = classifyFailure(error);
|
|
583
|
+
console.error('Failure classified as: ' + result.class + ' — ' + result.reason);
|
|
584
|
+
|
|
585
|
+
// Persist failure class to state
|
|
586
|
+
issueState.last_failure_class = result.class;
|
|
587
|
+
|
|
588
|
+
if (result.class === 'transient' && canRetry(issueState)) {
|
|
589
|
+
const backoff = getBackoffMs(issueState.retry_count || 0);
|
|
590
|
+
issueState = incrementRetry(issueState);
|
|
591
|
+
fs.writeFileSync(filePath, JSON.stringify(issueState, null, 2));
|
|
592
|
+
// Output: backoff ms so shell can sleep
|
|
593
|
+
console.log('retry:' + backoff + ':' + result.class);
|
|
594
|
+
} else {
|
|
595
|
+
// Permanent failure or retries exhausted — dead-letter
|
|
596
|
+
issueState.dead_letter = true;
|
|
597
|
+
fs.writeFileSync(filePath, JSON.stringify(issueState, null, 2));
|
|
598
|
+
console.log('dead_letter:' + result.class);
|
|
599
|
+
}
|
|
267
600
|
}
|
|
268
601
|
")
|
|
269
602
|
|
|
270
603
|
case "$FAILURE_CLASS" in
|
|
604
|
+
advisory_degraded:*)
|
|
605
|
+
DEGRADED_AGENT=$(echo "$FAILURE_CLASS" | cut -d':' -f2)
|
|
606
|
+
echo "MGW: Advisory agent '${DEGRADED_AGENT}' failed — gracefully degraded, continuing pipeline."
|
|
607
|
+
# Do NOT set EXECUTION_SUCCEEDED=false — pipeline continues
|
|
608
|
+
# Skip to next step (advisory output is optional)
|
|
609
|
+
;;
|
|
271
610
|
retry:*)
|
|
272
611
|
BACKOFF_MS=$(echo "$FAILURE_CLASS" | cut -d':' -f2)
|
|
273
612
|
BACKOFF_SEC=$(( (BACKOFF_MS + 999) / 1000 ))
|
|
@@ -394,6 +733,31 @@ If proceed: apply "mgw:approved" label and continue.
|
|
|
394
733
|
|
|
395
734
|
Update pipeline_stage to "planning" (at `${REPO_ROOT}/.mgw/active/`).
|
|
396
735
|
|
|
736
|
+
**Verify ROADMAP.md was created:**
|
|
737
|
+
```bash
|
|
738
|
+
if [ ! -f ".planning/ROADMAP.md" ]; then
|
|
739
|
+
echo "MGW ERROR: Roadmapper agent did not produce ROADMAP.md. Cannot proceed with milestone execution."
|
|
740
|
+
FAIL_TS=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs current-timestamp --raw 2>/dev/null || date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
741
|
+
gh issue comment ${ISSUE_NUMBER} --body "> **MGW** · \`pipeline-failed\` · ${FAIL_TS}
|
|
742
|
+
> Roadmapper agent did not produce ROADMAP.md. Pipeline cannot continue.
|
|
743
|
+
> Re-run with \`/mgw:run ${ISSUE_NUMBER}\` after investigating." 2>/dev/null || true
|
|
744
|
+
# Update pipeline_stage to failed (same pattern as post_execution_update dead_letter block)
|
|
745
|
+
node -e "
|
|
746
|
+
const fs = require('fs'), path = require('path');
|
|
747
|
+
const activeDir = path.join(process.cwd(), '.mgw', 'active');
|
|
748
|
+
const files = fs.readdirSync(activeDir);
|
|
749
|
+
const file = files.find(f => f.startsWith('${ISSUE_NUMBER}-') && f.endsWith('.json'));
|
|
750
|
+
if (file) {
|
|
751
|
+
const filePath = path.join(activeDir, file);
|
|
752
|
+
const state = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
753
|
+
state.pipeline_stage = 'failed';
|
|
754
|
+
fs.writeFileSync(filePath, JSON.stringify(state, null, 2));
|
|
755
|
+
}
|
|
756
|
+
" 2>/dev/null || true
|
|
757
|
+
exit 1
|
|
758
|
+
fi
|
|
759
|
+
```
|
|
760
|
+
|
|
397
761
|
2. **If resuming with pipeline_stage = "planning" and ROADMAP.md exists:**
|
|
398
762
|
Discover phases from ROADMAP and run the full per-phase GSD lifecycle:
|
|
399
763
|
|
|
@@ -430,7 +794,40 @@ If proceed: apply "mgw:approved" label and continue.
|
|
|
430
794
|
# Parse PHASE_INIT JSON for: planner_model, checker_model
|
|
431
795
|
```
|
|
432
796
|
|
|
433
|
-
**b.
|
|
797
|
+
**b. Assemble MGW context and spawn planner agent (gsd:plan-phase, with diagnostic capture):**
|
|
798
|
+
|
|
799
|
+
Assemble multi-machine context from GitHub issue comments before spawning:
|
|
800
|
+
```bash
|
|
801
|
+
MGW_CONTEXT=$(node -e "
|
|
802
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
803
|
+
ic.buildGSDPromptContext({
|
|
804
|
+
milestone: ${MILESTONE_NUM},
|
|
805
|
+
phase: ${PHASE_NUMBER},
|
|
806
|
+
issueNumber: ${ISSUE_NUMBER},
|
|
807
|
+
includeVision: true,
|
|
808
|
+
includePriorSummaries: true,
|
|
809
|
+
includeCurrentPlan: false
|
|
810
|
+
}).then(ctx => process.stdout.write(ctx));
|
|
811
|
+
" 2>/dev/null || echo "")
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
<!-- mgw:criticality=critical spawn_point=milestone-planner -->
|
|
815
|
+
<!-- Critical: phase planning is required — cannot execute without a plan.
|
|
816
|
+
On failure: retry via milestone retry loop, then dead-letter. -->
|
|
817
|
+
|
|
818
|
+
**Pre-spawn diagnostic hook (milestone planner):**
|
|
819
|
+
```bash
|
|
820
|
+
DIAG_MS_PLANNER=$(node -e "
|
|
821
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
822
|
+
const id = dh.beforeAgentSpawn({
|
|
823
|
+
agentType: 'gsd-planner',
|
|
824
|
+
issueNumber: ${ISSUE_NUMBER},
|
|
825
|
+
prompt: 'Plan phase ${PHASE_NUMBER}: ${PHASE_NAME}',
|
|
826
|
+
repoRoot: '${REPO_ROOT}'
|
|
827
|
+
});
|
|
828
|
+
process.stdout.write(id);
|
|
829
|
+
" 2>/dev/null || echo "")
|
|
830
|
+
```
|
|
434
831
|
```
|
|
435
832
|
Task(
|
|
436
833
|
prompt="
|
|
@@ -441,6 +838,8 @@ If proceed: apply "mgw:approved" label and continue.
|
|
|
441
838
|
- .planning/STATE.md (If exists -- project state)
|
|
442
839
|
</files_to_read>
|
|
443
840
|
|
|
841
|
+
${MGW_CONTEXT}
|
|
842
|
+
|
|
444
843
|
You are the GSD planner. Plan phase ${PHASE_NUMBER}: ${PHASE_NAME}.
|
|
445
844
|
|
|
446
845
|
Read and follow the plan-phase workflow:
|
|
@@ -462,6 +861,48 @@ If proceed: apply "mgw:approved" label and continue.
|
|
|
462
861
|
)
|
|
463
862
|
```
|
|
464
863
|
|
|
864
|
+
**Post-spawn diagnostic hook (milestone planner):**
|
|
865
|
+
```bash
|
|
866
|
+
MS_PLANNER_EXIT=$( ls ${phase_dir}/*-PLAN.md 2>/dev/null | wc -l | xargs test 0 -lt && echo "success" || echo "error" )
|
|
867
|
+
node -e "
|
|
868
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
869
|
+
dh.afterAgentSpawn({
|
|
870
|
+
diagId: '${DIAG_MS_PLANNER}',
|
|
871
|
+
exitReason: '${MS_PLANNER_EXIT}',
|
|
872
|
+
repoRoot: '${REPO_ROOT}'
|
|
873
|
+
});
|
|
874
|
+
" 2>/dev/null || true
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
**b1b. Checkpoint: record milestone phase plan completion (atomic write):**
|
|
878
|
+
```bash
|
|
879
|
+
# Checkpoint: record milestone plan completion for this phase.
|
|
880
|
+
node -e "
|
|
881
|
+
const { updateCheckpoint } = require('${REPO_ROOT}/lib/state.cjs');
|
|
882
|
+
updateCheckpoint(${ISSUE_NUMBER}, {
|
|
883
|
+
pipeline_step: 'plan',
|
|
884
|
+
step_progress: { gsd_phase: ${PHASE_NUMBER}, plan_path: '${phase_dir}' },
|
|
885
|
+
last_agent_output: '${phase_dir}',
|
|
886
|
+
step_history: [{ step: 'plan', completed_at: new Date().toISOString(), agent_type: 'gsd-planner', output_path: '${phase_dir}' }],
|
|
887
|
+
resume: { action: 'execute-phase', context: { phase_number: ${PHASE_NUMBER}, phase_dir: '${phase_dir}' } }
|
|
888
|
+
});
|
|
889
|
+
" 2>/dev/null || true
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
**b2. Publish plan comment (non-blocking):**
|
|
893
|
+
```bash
|
|
894
|
+
PLAN_FILES=$(ls ${phase_dir}/*-PLAN.md 2>/dev/null)
|
|
895
|
+
for PLAN_FILE in $PLAN_FILES; do
|
|
896
|
+
node -e "
|
|
897
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
898
|
+
const fs = require('fs');
|
|
899
|
+
const content = fs.readFileSync('${PLAN_FILE}', 'utf-8');
|
|
900
|
+
ic.postPlanningComment(${ISSUE_NUMBER}, 'plan', content, { phase: ${PHASE_NUMBER}, milestone: ${MILESTONE_NUM} })
|
|
901
|
+
.catch(e => console.error('WARNING: Failed to post plan comment:', e.message));
|
|
902
|
+
" 2>/dev/null || true
|
|
903
|
+
done
|
|
904
|
+
```
|
|
905
|
+
|
|
465
906
|
**c. Verify plans exist:**
|
|
466
907
|
```bash
|
|
467
908
|
PLAN_COUNT=$(ls ${phase_dir}/*-PLAN.md 2>/dev/null | wc -l)
|
|
@@ -473,11 +914,30 @@ If proceed: apply "mgw:approved" label and continue.
|
|
|
473
914
|
fi
|
|
474
915
|
```
|
|
475
916
|
|
|
476
|
-
**d. Init execute-phase and spawn executor agent (gsd:execute-phase):**
|
|
917
|
+
**d. Init execute-phase and spawn executor agent (gsd:execute-phase, with diagnostic capture):**
|
|
477
918
|
```bash
|
|
478
919
|
EXEC_INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs init execute-phase "${PHASE_NUMBER}")
|
|
479
920
|
# Parse EXEC_INIT JSON for: executor_model, verifier_model, phase_dir, plans, incomplete_plans, plan_count
|
|
480
921
|
```
|
|
922
|
+
|
|
923
|
+
<!-- mgw:criticality=critical spawn_point=milestone-executor -->
|
|
924
|
+
<!-- Critical: phase execution produces the code changes. Without it,
|
|
925
|
+
there is nothing to commit or PR. On failure: retry via milestone
|
|
926
|
+
retry loop, then dead-letter. -->
|
|
927
|
+
|
|
928
|
+
**Pre-spawn diagnostic hook (milestone executor):**
|
|
929
|
+
```bash
|
|
930
|
+
DIAG_MS_EXECUTOR=$(node -e "
|
|
931
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
932
|
+
const id = dh.beforeAgentSpawn({
|
|
933
|
+
agentType: 'gsd-executor',
|
|
934
|
+
issueNumber: ${ISSUE_NUMBER},
|
|
935
|
+
prompt: 'Execute phase ${PHASE_NUMBER}: ${PHASE_NAME}',
|
|
936
|
+
repoRoot: '${REPO_ROOT}'
|
|
937
|
+
});
|
|
938
|
+
process.stdout.write(id);
|
|
939
|
+
" 2>/dev/null || echo "")
|
|
940
|
+
```
|
|
481
941
|
```
|
|
482
942
|
Task(
|
|
483
943
|
prompt="
|
|
@@ -508,7 +968,82 @@ If proceed: apply "mgw:approved" label and continue.
|
|
|
508
968
|
)
|
|
509
969
|
```
|
|
510
970
|
|
|
511
|
-
**
|
|
971
|
+
**Post-spawn diagnostic hook (milestone executor):**
|
|
972
|
+
```bash
|
|
973
|
+
MS_EXECUTOR_EXIT=$( ls ${phase_dir}/*-SUMMARY.md 2>/dev/null | wc -l | xargs test 0 -lt && echo "success" || echo "error" )
|
|
974
|
+
node -e "
|
|
975
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
976
|
+
dh.afterAgentSpawn({
|
|
977
|
+
diagId: '${DIAG_MS_EXECUTOR}',
|
|
978
|
+
exitReason: '${MS_EXECUTOR_EXIT}',
|
|
979
|
+
repoRoot: '${REPO_ROOT}'
|
|
980
|
+
});
|
|
981
|
+
" 2>/dev/null || true
|
|
982
|
+
```
|
|
983
|
+
|
|
984
|
+
**d1b. Checkpoint: record milestone phase execution completion (atomic write):**
|
|
985
|
+
```bash
|
|
986
|
+
# Checkpoint: record milestone execution completion for this phase.
|
|
987
|
+
node -e "
|
|
988
|
+
const { updateCheckpoint } = require('${REPO_ROOT}/lib/state.cjs');
|
|
989
|
+
updateCheckpoint(${ISSUE_NUMBER}, {
|
|
990
|
+
pipeline_step: 'execute',
|
|
991
|
+
step_progress: { gsd_phase: ${PHASE_NUMBER} },
|
|
992
|
+
last_agent_output: '${phase_dir}',
|
|
993
|
+
step_history: [{ step: 'execute', completed_at: new Date().toISOString(), agent_type: 'gsd-executor', output_path: '${phase_dir}' }],
|
|
994
|
+
resume: { action: 'verify-phase', context: { phase_number: ${PHASE_NUMBER}, phase_dir: '${phase_dir}' } }
|
|
995
|
+
});
|
|
996
|
+
" 2>/dev/null || true
|
|
997
|
+
```
|
|
998
|
+
|
|
999
|
+
**d2. Publish summary comment (non-blocking):**
|
|
1000
|
+
```bash
|
|
1001
|
+
SUMMARY_FILES=$(ls ${phase_dir}/*-SUMMARY.md 2>/dev/null)
|
|
1002
|
+
for SUMMARY_FILE in $SUMMARY_FILES; do
|
|
1003
|
+
node -e "
|
|
1004
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
1005
|
+
const fs = require('fs');
|
|
1006
|
+
const content = fs.readFileSync('${SUMMARY_FILE}', 'utf-8');
|
|
1007
|
+
ic.postPlanningComment(${ISSUE_NUMBER}, 'summary', content, { phase: ${PHASE_NUMBER}, milestone: ${MILESTONE_NUM} })
|
|
1008
|
+
.catch(e => console.error('WARNING: Failed to post summary comment:', e.message));
|
|
1009
|
+
" 2>/dev/null || true
|
|
1010
|
+
done
|
|
1011
|
+
```
|
|
1012
|
+
|
|
1013
|
+
**e. Spawn verifier agent (gsd:verify-phase):**
|
|
1014
|
+
|
|
1015
|
+
<!-- mgw:criticality=advisory spawn_point=milestone-verifier -->
|
|
1016
|
+
<!-- Advisory: phase verification is quality assurance after execution
|
|
1017
|
+
completes. The code changes and commits already exist. If verification
|
|
1018
|
+
fails, log a warning and proceed with a note that verification was
|
|
1019
|
+
skipped for this phase.
|
|
1020
|
+
|
|
1021
|
+
Graceful degradation pattern:
|
|
1022
|
+
```
|
|
1023
|
+
VERIFY_RESULT=$(wrapAdvisoryAgent(Task(...), 'milestone-verifier', {
|
|
1024
|
+
issueNumber: ISSUE_NUMBER,
|
|
1025
|
+
fallback: null
|
|
1026
|
+
}))
|
|
1027
|
+
# If fallback returned, create minimal VERIFICATION.md:
|
|
1028
|
+
# "## VERIFICATION SKIPPED\nVerifier agent unavailable for phase ${PHASE_NUMBER}."
|
|
1029
|
+
```
|
|
1030
|
+
-->
|
|
1031
|
+
|
|
1032
|
+
**e. Spawn verifier agent (gsd:verify-phase, with diagnostic capture):**
|
|
1033
|
+
|
|
1034
|
+
**Pre-spawn diagnostic hook (milestone verifier):**
|
|
1035
|
+
```bash
|
|
1036
|
+
DIAG_MS_VERIFIER=$(node -e "
|
|
1037
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
1038
|
+
const id = dh.beforeAgentSpawn({
|
|
1039
|
+
agentType: 'gsd-verifier',
|
|
1040
|
+
issueNumber: ${ISSUE_NUMBER},
|
|
1041
|
+
prompt: 'Verify phase ${PHASE_NUMBER}: ${PHASE_NAME}',
|
|
1042
|
+
repoRoot: '${REPO_ROOT}'
|
|
1043
|
+
});
|
|
1044
|
+
process.stdout.write(id);
|
|
1045
|
+
" 2>/dev/null || echo "")
|
|
1046
|
+
```
|
|
512
1047
|
```
|
|
513
1048
|
Task(
|
|
514
1049
|
prompt="
|
|
@@ -536,6 +1071,48 @@ If proceed: apply "mgw:approved" label and continue.
|
|
|
536
1071
|
)
|
|
537
1072
|
```
|
|
538
1073
|
|
|
1074
|
+
**Post-spawn diagnostic hook (milestone verifier):**
|
|
1075
|
+
```bash
|
|
1076
|
+
MS_VERIFIER_EXIT=$( ls ${phase_dir}/*-VERIFICATION.md 2>/dev/null | wc -l | xargs test 0 -lt && echo "success" || echo "error" )
|
|
1077
|
+
node -e "
|
|
1078
|
+
const dh = require('${REPO_ROOT}/lib/diagnostic-hooks.cjs');
|
|
1079
|
+
dh.afterAgentSpawn({
|
|
1080
|
+
diagId: '${DIAG_MS_VERIFIER}',
|
|
1081
|
+
exitReason: '${MS_VERIFIER_EXIT}',
|
|
1082
|
+
repoRoot: '${REPO_ROOT}'
|
|
1083
|
+
});
|
|
1084
|
+
" 2>/dev/null || true
|
|
1085
|
+
```
|
|
1086
|
+
|
|
1087
|
+
**e1b. Checkpoint: record milestone phase verification completion (atomic write):**
|
|
1088
|
+
```bash
|
|
1089
|
+
# Checkpoint: record milestone verification completion for this phase.
|
|
1090
|
+
node -e "
|
|
1091
|
+
const { updateCheckpoint } = require('${REPO_ROOT}/lib/state.cjs');
|
|
1092
|
+
updateCheckpoint(${ISSUE_NUMBER}, {
|
|
1093
|
+
pipeline_step: 'verify',
|
|
1094
|
+
step_progress: { gsd_phase: ${PHASE_NUMBER}, verification_complete: true },
|
|
1095
|
+
last_agent_output: '${phase_dir}',
|
|
1096
|
+
step_history: [{ step: 'verify', completed_at: new Date().toISOString(), agent_type: 'gsd-verifier', output_path: '${phase_dir}' }],
|
|
1097
|
+
resume: { action: 'next-phase', context: { completed_phase: ${PHASE_NUMBER}, phase_dir: '${phase_dir}' } }
|
|
1098
|
+
});
|
|
1099
|
+
" 2>/dev/null || true
|
|
1100
|
+
```
|
|
1101
|
+
|
|
1102
|
+
**e2. Publish verification comment (non-blocking):**
|
|
1103
|
+
```bash
|
|
1104
|
+
VERIFICATION_FILES=$(ls ${phase_dir}/*-VERIFICATION.md 2>/dev/null)
|
|
1105
|
+
for VERIFICATION_FILE in $VERIFICATION_FILES; do
|
|
1106
|
+
node -e "
|
|
1107
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
1108
|
+
const fs = require('fs');
|
|
1109
|
+
const content = fs.readFileSync('${VERIFICATION_FILE}', 'utf-8');
|
|
1110
|
+
ic.postPlanningComment(${ISSUE_NUMBER}, 'verification', content, { phase: ${PHASE_NUMBER}, milestone: ${MILESTONE_NUM} })
|
|
1111
|
+
.catch(e => console.error('WARNING: Failed to post verification comment:', e.message));
|
|
1112
|
+
" 2>/dev/null || true
|
|
1113
|
+
done
|
|
1114
|
+
```
|
|
1115
|
+
|
|
539
1116
|
**f. Post phase-complete comment directly (no sub-agent):**
|
|
540
1117
|
```bash
|
|
541
1118
|
PHASE_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|