@snipcodeit/mgw 0.1.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/LICENSE +21 -0
- package/README.md +517 -0
- package/bin/mgw-install.cjs +81 -0
- package/commands/ask.md +416 -0
- package/commands/assign.md +333 -0
- package/commands/board.md +1679 -0
- package/commands/help.md +119 -0
- package/commands/init.md +250 -0
- package/commands/issue.md +469 -0
- package/commands/issues.md +109 -0
- package/commands/link.md +122 -0
- package/commands/milestone.md +952 -0
- package/commands/next.md +375 -0
- package/commands/pr.md +277 -0
- package/commands/project.md +1801 -0
- package/commands/review.md +260 -0
- package/commands/roadmap.md +489 -0
- package/commands/run.md +1282 -0
- package/commands/status.md +526 -0
- package/commands/sync.md +243 -0
- package/commands/update.md +282 -0
- package/commands/workflows/board-sync.md +404 -0
- package/commands/workflows/github.md +385 -0
- package/commands/workflows/gsd.md +377 -0
- package/commands/workflows/state.md +412 -0
- package/commands/workflows/validation.md +144 -0
- package/dist/bin/mgw.cjs +291 -0
- package/dist/claude-Vp9qvImH.cjs +466 -0
- package/dist/lib/index.cjs +395 -0
- package/package.json +51 -0
- package/templates/schema.json +164 -0
- package/templates/vision-brief-schema.json +98 -0
package/commands/run.md
ADDED
|
@@ -0,0 +1,1282 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mgw:run
|
|
3
|
+
description: Autonomous pipeline — triage issue through GSD execution to PR creation
|
|
4
|
+
argument-hint: "<issue-number>"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Bash
|
|
7
|
+
- Read
|
|
8
|
+
- Write
|
|
9
|
+
- Edit
|
|
10
|
+
- Glob
|
|
11
|
+
- Grep
|
|
12
|
+
- Task
|
|
13
|
+
- AskUserQuestion
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<objective>
|
|
17
|
+
The autonomous orchestrator. Takes an issue number, ensures it's triaged, then runs
|
|
18
|
+
the full GSD pipeline through to PR creation with minimal user interaction.
|
|
19
|
+
|
|
20
|
+
All work happens in an isolated git worktree — the user's main workspace stays on
|
|
21
|
+
the default branch throughout. The worktree is cleaned up after PR creation.
|
|
22
|
+
|
|
23
|
+
For quick/quick --full: runs entire pipeline in one session.
|
|
24
|
+
For new-milestone: runs full milestone flow, posting updates after each phase.
|
|
25
|
+
|
|
26
|
+
The orchestrator stays thin — all heavy work (analysis, GSD execution, GitHub
|
|
27
|
+
operations) happens in task agents with fresh context.
|
|
28
|
+
|
|
29
|
+
Checkpoints requiring user input:
|
|
30
|
+
- Triage confirmation (if not already triaged)
|
|
31
|
+
- GSD route confirmation
|
|
32
|
+
- Non-autonomous plan checkpoints
|
|
33
|
+
- Milestone scope decisions
|
|
34
|
+
</objective>
|
|
35
|
+
|
|
36
|
+
<execution_context>
|
|
37
|
+
@~/.claude/commands/mgw/workflows/state.md
|
|
38
|
+
@~/.claude/commands/mgw/workflows/github.md
|
|
39
|
+
@~/.claude/commands/mgw/workflows/gsd.md
|
|
40
|
+
@~/.claude/commands/mgw/workflows/validation.md
|
|
41
|
+
</execution_context>
|
|
42
|
+
|
|
43
|
+
<context>
|
|
44
|
+
Issue number: $ARGUMENTS
|
|
45
|
+
|
|
46
|
+
State: .mgw/active/ (if triaged already)
|
|
47
|
+
</context>
|
|
48
|
+
|
|
49
|
+
<process>
|
|
50
|
+
|
|
51
|
+
<step name="validate_and_load">
|
|
52
|
+
**Validate input and load state:**
|
|
53
|
+
|
|
54
|
+
Store repo root and default branch (used throughout):
|
|
55
|
+
```bash
|
|
56
|
+
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
57
|
+
DEFAULT=$(gh repo view --json defaultBranchRef -q .defaultBranchRef.name)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Parse $ARGUMENTS for issue number. If missing:
|
|
61
|
+
```
|
|
62
|
+
AskUserQuestion(
|
|
63
|
+
header: "Issue Number Required",
|
|
64
|
+
question: "Which issue number do you want to run the pipeline for?",
|
|
65
|
+
followUp: null
|
|
66
|
+
)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Check for existing state: `${REPO_ROOT}/.mgw/active/${ISSUE_NUMBER}-*.json`
|
|
70
|
+
|
|
71
|
+
If no state file exists → issue not triaged yet. Run triage inline:
|
|
72
|
+
- Inform user: "Issue #${ISSUE_NUMBER} hasn't been triaged. Running triage first."
|
|
73
|
+
- Execute the mgw:issue triage flow (steps from issue.md) inline.
|
|
74
|
+
- After triage, reload state file.
|
|
75
|
+
|
|
76
|
+
If state file exists → load it. Check pipeline_stage:
|
|
77
|
+
- "triaged" → proceed to GSD execution
|
|
78
|
+
- "planning" / "executing" → resume from where we left off
|
|
79
|
+
- "blocked" → "Pipeline for #${ISSUE_NUMBER} is blocked by a stakeholder comment. Review the issue comments, resolve the blocker, then re-run."
|
|
80
|
+
- "pr-created" / "done" → "Pipeline already completed for #${ISSUE_NUMBER}. Run /mgw:sync to reconcile."
|
|
81
|
+
- "needs-info" → Check for --force flag in $ARGUMENTS:
|
|
82
|
+
If --force NOT present:
|
|
83
|
+
```
|
|
84
|
+
Pipeline for #${ISSUE_NUMBER} is blocked by triage gate (needs-info).
|
|
85
|
+
The issue requires more detail before execution can begin.
|
|
86
|
+
|
|
87
|
+
To override: /mgw:run ${ISSUE_NUMBER} --force
|
|
88
|
+
To review: /mgw:issue ${ISSUE_NUMBER} (re-triage after updating the issue)
|
|
89
|
+
```
|
|
90
|
+
STOP.
|
|
91
|
+
If --force present:
|
|
92
|
+
Log warning: "MGW: WARNING — Overriding needs-info gate for #${ISSUE_NUMBER}. Proceeding with --force."
|
|
93
|
+
Update state: pipeline_stage = "triaged", add override_log entry.
|
|
94
|
+
Continue pipeline.
|
|
95
|
+
- "needs-security-review" → Check for --security-ack flag in $ARGUMENTS:
|
|
96
|
+
If --security-ack NOT present:
|
|
97
|
+
```
|
|
98
|
+
Pipeline for #${ISSUE_NUMBER} requires security review.
|
|
99
|
+
This issue was flagged as high security risk during triage.
|
|
100
|
+
|
|
101
|
+
To acknowledge and proceed: /mgw:run ${ISSUE_NUMBER} --security-ack
|
|
102
|
+
To review: /mgw:issue ${ISSUE_NUMBER} (re-triage)
|
|
103
|
+
```
|
|
104
|
+
STOP.
|
|
105
|
+
If --security-ack present:
|
|
106
|
+
Log warning: "MGW: WARNING — Acknowledging security risk for #${ISSUE_NUMBER}. Proceeding with --security-ack."
|
|
107
|
+
Update state: pipeline_stage = "triaged", add override_log entry.
|
|
108
|
+
Continue pipeline.
|
|
109
|
+
|
|
110
|
+
**Cross-milestone detection (runs after loading issue state):**
|
|
111
|
+
|
|
112
|
+
Check if this issue belongs to a non-active GSD milestone:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
CROSS_MILESTONE_WARN=$(node -e "
|
|
116
|
+
const { loadProjectState, resolveActiveMilestoneIndex } = require('./lib/state.cjs');
|
|
117
|
+
const state = loadProjectState();
|
|
118
|
+
if (!state) { console.log('none'); process.exit(0); }
|
|
119
|
+
|
|
120
|
+
const activeGsdId = state.active_gsd_milestone;
|
|
121
|
+
|
|
122
|
+
// Find this issue's milestone in project.json
|
|
123
|
+
const issueNum = ${ISSUE_NUMBER};
|
|
124
|
+
let issueMilestone = null;
|
|
125
|
+
for (const m of (state.milestones || [])) {
|
|
126
|
+
if ((m.issues || []).some(i => i.github_number === issueNum)) {
|
|
127
|
+
issueMilestone = m;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (!issueMilestone) { console.log('none'); process.exit(0); }
|
|
133
|
+
|
|
134
|
+
const issueGsdId = issueMilestone.gsd_milestone_id;
|
|
135
|
+
|
|
136
|
+
// No active_gsd_milestone set (legacy schema): no warning
|
|
137
|
+
if (!activeGsdId) { console.log('none'); process.exit(0); }
|
|
138
|
+
|
|
139
|
+
// Issue is in the active milestone: no warning
|
|
140
|
+
if (issueGsdId === activeGsdId) { console.log('none'); process.exit(0); }
|
|
141
|
+
|
|
142
|
+
// Issue is in a different milestone
|
|
143
|
+
const gsdRoute = '${GSD_ROUTE}';
|
|
144
|
+
if (gsdRoute === 'quick' || gsdRoute === 'gsd:quick') {
|
|
145
|
+
console.log('isolation:' + issueMilestone.name + ':' + (issueGsdId || 'unlinked'));
|
|
146
|
+
} else {
|
|
147
|
+
console.log('warn:' + issueMilestone.name + ':' + (issueGsdId || 'unlinked') + ':' + activeGsdId);
|
|
148
|
+
}
|
|
149
|
+
")
|
|
150
|
+
|
|
151
|
+
case "$CROSS_MILESTONE_WARN" in
|
|
152
|
+
none)
|
|
153
|
+
# No cross-milestone issue — proceed normally
|
|
154
|
+
;;
|
|
155
|
+
isolation:*)
|
|
156
|
+
MILESTONE_NAME=$(echo "$CROSS_MILESTONE_WARN" | cut -d':' -f2)
|
|
157
|
+
GSD_ID=$(echo "$CROSS_MILESTONE_WARN" | cut -d':' -f3)
|
|
158
|
+
|
|
159
|
+
# Re-validate route against live GitHub labels (project.json may be stale from triage time)
|
|
160
|
+
LIVE_LABELS=$(gh issue view ${ISSUE_NUMBER} --json labels --jq '[.labels[].name] | join(",")' 2>/dev/null || echo "")
|
|
161
|
+
QUICK_CONFIRMED=false
|
|
162
|
+
if echo "$LIVE_LABELS" | grep -qiE "gsd-route:quick|gsd:quick|quick"; then
|
|
163
|
+
QUICK_CONFIRMED=true
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
if [ "$QUICK_CONFIRMED" = "true" ]; then
|
|
167
|
+
echo ""
|
|
168
|
+
echo "NOTE: Issue #${ISSUE_NUMBER} belongs to milestone '${MILESTONE_NAME}' (GSD: ${GSD_ID})"
|
|
169
|
+
echo " Confirmed gsd:quick via live labels — running in isolation."
|
|
170
|
+
echo ""
|
|
171
|
+
else
|
|
172
|
+
# Route mismatch: project.json says quick but labels don't confirm it
|
|
173
|
+
echo ""
|
|
174
|
+
echo "⚠️ Route mismatch for cross-milestone issue #${ISSUE_NUMBER}:"
|
|
175
|
+
echo " project.json route: quick (set at triage time)"
|
|
176
|
+
echo " Live GitHub labels: ${LIVE_LABELS:-none}"
|
|
177
|
+
echo " Labels do not confirm gsd:quick — treating as plan-phase (requires milestone context)."
|
|
178
|
+
echo ""
|
|
179
|
+
echo "Options:"
|
|
180
|
+
echo " 1) Switch active milestone to '${GSD_ID}' and continue"
|
|
181
|
+
echo " 2) Re-triage this issue (/mgw:issue ${ISSUE_NUMBER}) to update its route"
|
|
182
|
+
echo " 3) Abort"
|
|
183
|
+
echo ""
|
|
184
|
+
read -p "Choice [1/2/3]: " ROUTE_MISMATCH_CHOICE
|
|
185
|
+
case "$ROUTE_MISMATCH_CHOICE" in
|
|
186
|
+
1)
|
|
187
|
+
node -e "
|
|
188
|
+
const { loadProjectState, writeProjectState } = require('./lib/state.cjs');
|
|
189
|
+
const state = loadProjectState();
|
|
190
|
+
state.active_gsd_milestone = '${GSD_ID}';
|
|
191
|
+
writeProjectState(state);
|
|
192
|
+
console.log('Switched active_gsd_milestone to: ${GSD_ID}');
|
|
193
|
+
"
|
|
194
|
+
# Validate ROADMAP.md matches (same check as option 1 in warn case)
|
|
195
|
+
ROADMAP_VALID=$(python3 -c "
|
|
196
|
+
import os
|
|
197
|
+
if not os.path.exists('.planning/ROADMAP.md'):
|
|
198
|
+
print('missing')
|
|
199
|
+
else:
|
|
200
|
+
with open('.planning/ROADMAP.md') as f:
|
|
201
|
+
content = f.read()
|
|
202
|
+
print('match' if '${GSD_ID}' in content else 'mismatch')
|
|
203
|
+
" 2>/dev/null || echo "missing")
|
|
204
|
+
if [ "$ROADMAP_VALID" != "match" ]; then
|
|
205
|
+
node -e "
|
|
206
|
+
const { loadProjectState, writeProjectState } = require('./lib/state.cjs');
|
|
207
|
+
const state = loadProjectState();
|
|
208
|
+
state.active_gsd_milestone = '$(echo "$CROSS_MILESTONE_WARN" | cut -d':' -f4)';
|
|
209
|
+
writeProjectState(state);
|
|
210
|
+
" 2>/dev/null || true
|
|
211
|
+
echo "Switch rolled back — ROADMAP.md does not match '${GSD_ID}'."
|
|
212
|
+
echo "Run /gsd:new-milestone to update ROADMAP.md first."
|
|
213
|
+
exit 0
|
|
214
|
+
fi
|
|
215
|
+
;;
|
|
216
|
+
2)
|
|
217
|
+
echo "Re-triage with: /mgw:issue ${ISSUE_NUMBER}"
|
|
218
|
+
exit 0
|
|
219
|
+
;;
|
|
220
|
+
*)
|
|
221
|
+
echo "Aborted."
|
|
222
|
+
exit 0
|
|
223
|
+
;;
|
|
224
|
+
esac
|
|
225
|
+
fi
|
|
226
|
+
;;
|
|
227
|
+
warn:*)
|
|
228
|
+
ISSUE_MILESTONE=$(echo "$CROSS_MILESTONE_WARN" | cut -d':' -f2)
|
|
229
|
+
ISSUE_GSD=$(echo "$CROSS_MILESTONE_WARN" | cut -d':' -f3)
|
|
230
|
+
ACTIVE_GSD=$(echo "$CROSS_MILESTONE_WARN" | cut -d':' -f4)
|
|
231
|
+
echo ""
|
|
232
|
+
echo "⚠️ Cross-milestone issue detected:"
|
|
233
|
+
echo " Issue #${ISSUE_NUMBER} belongs to: '${ISSUE_MILESTONE}' (GSD: ${ISSUE_GSD})"
|
|
234
|
+
echo " Active GSD milestone: ${ACTIVE_GSD}"
|
|
235
|
+
echo ""
|
|
236
|
+
echo "This issue requires plan-phase work that depends on ROADMAP.md context."
|
|
237
|
+
echo "Running it against the wrong active milestone may produce incorrect plans."
|
|
238
|
+
echo ""
|
|
239
|
+
echo "Options:"
|
|
240
|
+
echo " 1) Switch active milestone to '${ISSUE_GSD}' and continue"
|
|
241
|
+
echo " 2) Continue anyway (not recommended)"
|
|
242
|
+
echo " 3) Abort — run /gsd:new-milestone to set up the correct milestone first"
|
|
243
|
+
echo ""
|
|
244
|
+
read -p "Choice [1/2/3]: " MILESTONE_CHOICE
|
|
245
|
+
case "$MILESTONE_CHOICE" in
|
|
246
|
+
1)
|
|
247
|
+
node -e "
|
|
248
|
+
const { loadProjectState, writeProjectState } = require('./lib/state.cjs');
|
|
249
|
+
const state = loadProjectState();
|
|
250
|
+
state.active_gsd_milestone = '${ISSUE_GSD}';
|
|
251
|
+
writeProjectState(state);
|
|
252
|
+
console.log('Switched active_gsd_milestone to: ${ISSUE_GSD}');
|
|
253
|
+
"
|
|
254
|
+
# Validate ROADMAP.md matches the new active milestone
|
|
255
|
+
ROADMAP_VALID=$(python3 -c "
|
|
256
|
+
import os
|
|
257
|
+
if not os.path.exists('.planning/ROADMAP.md'):
|
|
258
|
+
print('missing')
|
|
259
|
+
else:
|
|
260
|
+
with open('.planning/ROADMAP.md') as f:
|
|
261
|
+
content = f.read()
|
|
262
|
+
print('match' if '${ISSUE_GSD}' in content else 'mismatch')
|
|
263
|
+
" 2>/dev/null || echo "missing")
|
|
264
|
+
if [ "$ROADMAP_VALID" = "match" ]; then
|
|
265
|
+
echo "Active milestone updated. ROADMAP.md confirmed for '${ISSUE_GSD}'."
|
|
266
|
+
else
|
|
267
|
+
# Roll back — ROADMAP.md doesn't match
|
|
268
|
+
node -e "
|
|
269
|
+
const { loadProjectState, writeProjectState } = require('./lib/state.cjs');
|
|
270
|
+
const state = loadProjectState();
|
|
271
|
+
state.active_gsd_milestone = '${ACTIVE_GSD}';
|
|
272
|
+
writeProjectState(state);
|
|
273
|
+
" 2>/dev/null || true
|
|
274
|
+
echo "Switch rolled back — ROADMAP.md does not match '${ISSUE_GSD}'."
|
|
275
|
+
echo "Run /gsd:new-milestone to update ROADMAP.md first."
|
|
276
|
+
exit 0
|
|
277
|
+
fi
|
|
278
|
+
;;
|
|
279
|
+
2)
|
|
280
|
+
echo "Proceeding with cross-milestone issue (may affect plan quality)."
|
|
281
|
+
;;
|
|
282
|
+
*)
|
|
283
|
+
echo "Aborted. Run /gsd:new-milestone then /mgw:project to align milestones."
|
|
284
|
+
exit 0
|
|
285
|
+
;;
|
|
286
|
+
esac
|
|
287
|
+
;;
|
|
288
|
+
esac
|
|
289
|
+
```
|
|
290
|
+
</step>
|
|
291
|
+
|
|
292
|
+
<step name="create_worktree">
|
|
293
|
+
**Create isolated worktree for issue work:**
|
|
294
|
+
|
|
295
|
+
Derive branch and worktree path:
|
|
296
|
+
```bash
|
|
297
|
+
BRANCH_NAME="issue/${ISSUE_NUMBER}-${slug}"
|
|
298
|
+
WORKTREE_DIR="${REPO_ROOT}/.worktrees/${BRANCH_NAME}"
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Ensure .worktrees/ is gitignored:
|
|
302
|
+
```bash
|
|
303
|
+
mkdir -p "$(dirname "${WORKTREE_DIR}")"
|
|
304
|
+
if ! git check-ignore -q .worktrees 2>/dev/null; then
|
|
305
|
+
echo ".worktrees/" >> "${REPO_ROOT}/.gitignore"
|
|
306
|
+
fi
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Create worktree with feature branch:
|
|
310
|
+
```bash
|
|
311
|
+
# If worktree already exists (resume in same session), skip creation
|
|
312
|
+
if [ -d "${WORKTREE_DIR}" ]; then
|
|
313
|
+
echo "Worktree exists, reusing"
|
|
314
|
+
# If branch already exists (resume from prior session)
|
|
315
|
+
elif git show-ref --verify --quiet "refs/heads/${BRANCH_NAME}"; then
|
|
316
|
+
git worktree add "${WORKTREE_DIR}" "${BRANCH_NAME}"
|
|
317
|
+
# New branch (first run)
|
|
318
|
+
else
|
|
319
|
+
git worktree add "${WORKTREE_DIR}" -b "${BRANCH_NAME}"
|
|
320
|
+
fi
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**Switch working directory to worktree:**
|
|
324
|
+
```bash
|
|
325
|
+
cd "${WORKTREE_DIR}"
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Update state (at `${REPO_ROOT}/.mgw/active/`): add branch to linked_branches.
|
|
329
|
+
Add cross-ref (at `${REPO_ROOT}/.mgw/cross-refs.json`): issue → branch.
|
|
330
|
+
|
|
331
|
+
**Apply in-progress label:**
|
|
332
|
+
```bash
|
|
333
|
+
# Use remove_mgw_labels_and_apply pattern from github.md
|
|
334
|
+
gh issue edit ${ISSUE_NUMBER} --remove-label "mgw:triaged" 2>/dev/null
|
|
335
|
+
gh issue edit ${ISSUE_NUMBER} --add-label "mgw:in-progress" 2>/dev/null
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**PATH CONVENTION for remaining steps:**
|
|
339
|
+
- File operations, git commands, and agent work use **relative paths** (CWD = worktree)
|
|
340
|
+
- `.mgw/` state operations use **absolute paths**: `${REPO_ROOT}/.mgw/`
|
|
341
|
+
(`.mgw/` is gitignored — it only exists in the main repo, not the worktree)
|
|
342
|
+
</step>
|
|
343
|
+
|
|
344
|
+
<step name="preflight_comment_check">
|
|
345
|
+
**Pre-flight comment check — detect new comments since triage:**
|
|
346
|
+
|
|
347
|
+
Before GSD execution begins, check if new comments have been posted on the issue
|
|
348
|
+
since triage. This prevents executing against a stale plan when stakeholders have
|
|
349
|
+
posted material changes, blockers, or scope updates.
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
# Fetch current comment count from GitHub
|
|
353
|
+
CURRENT_COMMENTS=$(gh issue view $ISSUE_NUMBER --json comments --jq '.comments | length' 2>/dev/null || echo "0")
|
|
354
|
+
STORED_COMMENTS="${triage.last_comment_count}" # From state file
|
|
355
|
+
|
|
356
|
+
# If stored count is missing (pre-comment-tracking state), skip check
|
|
357
|
+
if [ -z "$STORED_COMMENTS" ] || [ "$STORED_COMMENTS" = "null" ] || [ "$STORED_COMMENTS" = "0" ]; then
|
|
358
|
+
STORED_COMMENTS=0
|
|
359
|
+
fi
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
If new comments detected (`CURRENT_COMMENTS > STORED_COMMENTS`):
|
|
363
|
+
|
|
364
|
+
1. **Fetch new comment bodies:**
|
|
365
|
+
```bash
|
|
366
|
+
NEW_COUNT=$(($CURRENT_COMMENTS - $STORED_COMMENTS))
|
|
367
|
+
NEW_COMMENTS=$(gh issue view $ISSUE_NUMBER --json comments \
|
|
368
|
+
--jq "[.comments[-${NEW_COUNT}:]] | .[] | {author: .author.login, body: .body, createdAt: .createdAt}" 2>/dev/null)
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
2. **Spawn classification agent:**
|
|
372
|
+
```
|
|
373
|
+
Task(
|
|
374
|
+
prompt="
|
|
375
|
+
<files_to_read>
|
|
376
|
+
- ./CLAUDE.md (Project instructions — if exists, follow all guidelines)
|
|
377
|
+
</files_to_read>
|
|
378
|
+
|
|
379
|
+
Classify new comments on GitHub issue #${ISSUE_NUMBER}.
|
|
380
|
+
|
|
381
|
+
<issue_context>
|
|
382
|
+
Title: ${issue_title}
|
|
383
|
+
Current pipeline stage: ${pipeline_stage}
|
|
384
|
+
GSD Route: ${gsd_route}
|
|
385
|
+
Triage scope: ${triage.scope}
|
|
386
|
+
</issue_context>
|
|
387
|
+
|
|
388
|
+
<new_comments>
|
|
389
|
+
${NEW_COMMENTS}
|
|
390
|
+
</new_comments>
|
|
391
|
+
|
|
392
|
+
<classification_rules>
|
|
393
|
+
Classify each comment (and the overall batch) into ONE of:
|
|
394
|
+
|
|
395
|
+
- **material** — Comment changes scope, requirements, acceptance criteria, or design.
|
|
396
|
+
Examples: 'Actually we also need to handle X', 'Changed the requirement to Y',
|
|
397
|
+
'Don't forget about edge case Z'.
|
|
398
|
+
|
|
399
|
+
- **informational** — Status update, acknowledgment, question that doesn't change scope, +1.
|
|
400
|
+
Examples: 'Looks good', 'Thanks for picking this up', 'What's the ETA?', '+1'.
|
|
401
|
+
|
|
402
|
+
- **blocking** — Explicit instruction to stop or wait. Must contain clear hold language.
|
|
403
|
+
Examples: 'Don't work on this yet', 'Hold off', 'Blocked by external dependency',
|
|
404
|
+
'Wait for design review'.
|
|
405
|
+
|
|
406
|
+
If ANY comment in the batch is blocking, overall classification is blocking.
|
|
407
|
+
If ANY comment is material (and none blocking), overall classification is material.
|
|
408
|
+
Otherwise, informational.
|
|
409
|
+
</classification_rules>
|
|
410
|
+
|
|
411
|
+
<output_format>
|
|
412
|
+
Return ONLY valid JSON:
|
|
413
|
+
{
|
|
414
|
+
\"classification\": \"material|informational|blocking\",
|
|
415
|
+
\"reasoning\": \"Brief explanation of why this classification was chosen\",
|
|
416
|
+
\"new_requirements\": [\"list of new requirements if material, empty array otherwise\"],
|
|
417
|
+
\"blocking_reason\": \"reason if blocking, empty string otherwise\"
|
|
418
|
+
}
|
|
419
|
+
</output_format>
|
|
420
|
+
",
|
|
421
|
+
subagent_type="general-purpose",
|
|
422
|
+
description="Classify comments on #${ISSUE_NUMBER}"
|
|
423
|
+
)
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
3. **React based on classification:**
|
|
427
|
+
|
|
428
|
+
| Classification | Action |
|
|
429
|
+
|---------------|--------|
|
|
430
|
+
| **informational** | Log: "MGW: ${NEW_COUNT} new comment(s) reviewed — informational, continuing." Update `triage.last_comment_count` in state file. Continue pipeline. |
|
|
431
|
+
| **material** | Log: "MGW: Material comment(s) detected — scope may have changed." Update state: add new_requirements to triage context. Update `triage.last_comment_count`. Re-read issue body for updated requirements. Continue with enriched context (pass new_requirements to planner). Check for security keywords in material comments (see below). |
|
|
432
|
+
| **blocking** | Log: "MGW: Blocking comment detected — pipeline paused." Update state: `pipeline_stage = "blocked"`. Apply mgw:blocked label. Post comment on issue: `> **MGW** . \`pipeline-blocked\` . Blocked by stakeholder comment. Reason: ${blocking_reason}`. Stop pipeline execution. |
|
|
433
|
+
|
|
434
|
+
**Security keyword check for material comments:**
|
|
435
|
+
```bash
|
|
436
|
+
SECURITY_KEYWORDS="security|vulnerability|CVE|exploit|injection|XSS|CSRF|auth bypass"
|
|
437
|
+
if echo "$NEW_COMMENTS" | grep -qiE "$SECURITY_KEYWORDS"; then
|
|
438
|
+
# Add warning to gate_result and prompt user
|
|
439
|
+
echo "MGW: Security-related comment detected. Re-triage recommended."
|
|
440
|
+
# Prompt: "Security-related comment detected. Re-triage recommended. Continue or re-triage?"
|
|
441
|
+
fi
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
**When blocking comment detected — apply label:**
|
|
445
|
+
```bash
|
|
446
|
+
gh issue edit ${ISSUE_NUMBER} --remove-label "mgw:in-progress" 2>/dev/null
|
|
447
|
+
gh issue edit ${ISSUE_NUMBER} --add-label "mgw:blocked" 2>/dev/null
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
If no new comments detected, continue normally.
|
|
451
|
+
</step>
|
|
452
|
+
|
|
453
|
+
<step name="post_triage_update">
|
|
454
|
+
**Post work-starting comment on issue:**
|
|
455
|
+
|
|
456
|
+
Note: The triage gate evaluation and triage-complete/triage-blocked comment are now
|
|
457
|
+
posted IMMEDIATELY during /mgw:issue. This step posts a separate work-starting
|
|
458
|
+
notification when pipeline execution actually begins in run.md.
|
|
459
|
+
|
|
460
|
+
Gather enrichment data from triage state:
|
|
461
|
+
```bash
|
|
462
|
+
SCOPE_SIZE="${triage.scope.size}" # small|medium|large
|
|
463
|
+
FILE_COUNT="${triage.scope.file_count}"
|
|
464
|
+
SYSTEM_LIST="${triage.scope.systems}"
|
|
465
|
+
FILE_LIST="${triage.scope.files}"
|
|
466
|
+
CONFLICTS="${triage.conflicts}"
|
|
467
|
+
ROUTE_REASONING="${triage.route_reasoning}"
|
|
468
|
+
TIMESTAMP=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs current-timestamp --raw 2>/dev/null || date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
469
|
+
|
|
470
|
+
# Load milestone/phase context from project.json if available
|
|
471
|
+
MILESTONE_CONTEXT=""
|
|
472
|
+
if [ -f "${REPO_ROOT}/.mgw/project.json" ]; then
|
|
473
|
+
MILESTONE_CONTEXT=$(node -e "
|
|
474
|
+
const { loadProjectState, resolveActiveMilestoneIndex } = require('./lib/state.cjs');
|
|
475
|
+
const state = loadProjectState();
|
|
476
|
+
if (!state) process.exit(0);
|
|
477
|
+
// Search all milestones for the issue (not just active) to handle cross-milestone lookups
|
|
478
|
+
for (const m of (state.milestones || [])) {
|
|
479
|
+
for (const i of (m.issues || [])) {
|
|
480
|
+
if (i.github_number === ${ISSUE_NUMBER}) {
|
|
481
|
+
console.log('Milestone: ' + m.name + ' | Phase ' + i.phase_number + ': ' + i.phase_name);
|
|
482
|
+
process.exit(0);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
" 2>/dev/null || echo "")
|
|
487
|
+
fi
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Post the work-starting comment directly (no sub-agent — guarantees it happens):
|
|
491
|
+
|
|
492
|
+
```bash
|
|
493
|
+
WORK_STARTING_BODY=$(cat <<COMMENTEOF
|
|
494
|
+
> **MGW** · \`work-starting\` · ${TIMESTAMP}
|
|
495
|
+
> ${MILESTONE_CONTEXT}
|
|
496
|
+
|
|
497
|
+
### Work Starting
|
|
498
|
+
|
|
499
|
+
| | |
|
|
500
|
+
|---|---|
|
|
501
|
+
| **Route** | \`${gsd_route}\` — ${ROUTE_REASONING} |
|
|
502
|
+
| **Scope** | ${SCOPE_SIZE} — ${FILE_COUNT} files across ${SYSTEM_LIST} |
|
|
503
|
+
| **Conflicts** | ${CONFLICTS} |
|
|
504
|
+
|
|
505
|
+
Work begins on branch \`${BRANCH_NAME}\`.
|
|
506
|
+
|
|
507
|
+
<details>
|
|
508
|
+
<summary>Affected Files</summary>
|
|
509
|
+
|
|
510
|
+
${FILE_LIST as bullet points}
|
|
511
|
+
|
|
512
|
+
</details>
|
|
513
|
+
COMMENTEOF
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
gh issue comment ${ISSUE_NUMBER} --body "$WORK_STARTING_BODY" 2>/dev/null || true
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
Log comment in state file (at `${REPO_ROOT}/.mgw/active/`).
|
|
520
|
+
</step>
|
|
521
|
+
|
|
522
|
+
<step name="execute_gsd_quick">
|
|
523
|
+
**Execute GSD pipeline (quick / quick --full route):**
|
|
524
|
+
|
|
525
|
+
Only run this step if gsd_route is "gsd:quick" or "gsd:quick --full".
|
|
526
|
+
|
|
527
|
+
Update pipeline_stage to "executing" in state file (at `${REPO_ROOT}/.mgw/active/`).
|
|
528
|
+
|
|
529
|
+
Determine flags:
|
|
530
|
+
- "gsd:quick" → $QUICK_FLAGS = ""
|
|
531
|
+
- "gsd:quick --full" → $QUICK_FLAGS = "--full"
|
|
532
|
+
|
|
533
|
+
Read the issue description to use as the GSD task description (full body, capped at 5000 chars for pathological issues):
|
|
534
|
+
```
|
|
535
|
+
$TASK_DESCRIPTION = "Issue #${ISSUE_NUMBER}: ${issue_title}\n\n${issue_body}" # full body, max 5000 chars
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
Execute the GSD quick workflow. Read and follow the quick workflow steps:
|
|
539
|
+
|
|
540
|
+
1. **Init:** `node ~/.claude/get-shit-done/bin/gsd-tools.cjs init quick "$DESCRIPTION"`
|
|
541
|
+
Parse JSON for: planner_model, executor_model, checker_model, verifier_model, next_num, slug, date, quick_dir, task_dir.
|
|
542
|
+
|
|
543
|
+
**Handle missing .planning/:** Check `roadmap_exists` from init output. If false, do NOT
|
|
544
|
+
create GSD state files — .planning/ is owned by GSD. Only create the quick task
|
|
545
|
+
directory (GSD agents need it to store plans/summaries):
|
|
546
|
+
```bash
|
|
547
|
+
if [ "$roadmap_exists" = "false" ]; then
|
|
548
|
+
echo "NOTE: No .planning/ directory found. GSD manages its own state files."
|
|
549
|
+
echo " To create a ROADMAP.md, run /gsd:new-milestone after this pipeline."
|
|
550
|
+
mkdir -p .planning/quick
|
|
551
|
+
fi
|
|
552
|
+
```
|
|
553
|
+
MGW never writes config.json, ROADMAP.md, or STATE.md — those are GSD-owned files.
|
|
554
|
+
|
|
555
|
+
2. **Create task directory:**
|
|
556
|
+
```bash
|
|
557
|
+
QUICK_DIR=".planning/quick/${next_num}-${slug}"
|
|
558
|
+
mkdir -p "$QUICK_DIR"
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
3. **Spawn planner (task agent):**
|
|
562
|
+
```
|
|
563
|
+
Task(
|
|
564
|
+
prompt="
|
|
565
|
+
<planning_context>
|
|
566
|
+
|
|
567
|
+
**Mode:** ${FULL_MODE ? 'quick-full' : 'quick'}
|
|
568
|
+
**Directory:** ${QUICK_DIR}
|
|
569
|
+
**Description:** ${TASK_DESCRIPTION}
|
|
570
|
+
|
|
571
|
+
<triage_context>
|
|
572
|
+
Scope: ${triage.scope.files} files across systems: ${triage.scope.systems}
|
|
573
|
+
Validity: ${triage.validity}
|
|
574
|
+
Security: ${triage.security_notes}
|
|
575
|
+
Conflicts: ${triage.conflicts}
|
|
576
|
+
GSD Route: ${gsd_route}
|
|
577
|
+
</triage_context>
|
|
578
|
+
|
|
579
|
+
<issue_comments>
|
|
580
|
+
${recent_comments}
|
|
581
|
+
</issue_comments>
|
|
582
|
+
|
|
583
|
+
<files_to_read>
|
|
584
|
+
- ./CLAUDE.md (Project instructions — if exists, follow all guidelines)
|
|
585
|
+
- .agents/skills/ (Project skills — if dir exists, list skills, read SKILL.md for each, follow relevant rules)
|
|
586
|
+
</files_to_read>
|
|
587
|
+
|
|
588
|
+
</planning_context>
|
|
589
|
+
|
|
590
|
+
<constraints>
|
|
591
|
+
- Create a SINGLE plan with 1-3 focused tasks
|
|
592
|
+
- Quick tasks should be atomic and self-contained
|
|
593
|
+
- No research phase
|
|
594
|
+
${FULL_MODE ? '- Target ~40% context usage (structured for verification)' : '- Target ~30% context usage (simple, focused)'}
|
|
595
|
+
${FULL_MODE ? '- MUST generate must_haves in plan frontmatter (truths, artifacts, key_links)' : ''}
|
|
596
|
+
${FULL_MODE ? '- Each task MUST have files, action, verify, done fields' : ''}
|
|
597
|
+
</constraints>
|
|
598
|
+
|
|
599
|
+
<output>
|
|
600
|
+
Write plan to: ${QUICK_DIR}/${next_num}-PLAN.md
|
|
601
|
+
Return: ## PLANNING COMPLETE with plan path
|
|
602
|
+
</output>
|
|
603
|
+
",
|
|
604
|
+
subagent_type="gsd-planner",
|
|
605
|
+
model="{planner_model}",
|
|
606
|
+
description="Plan: ${issue_title}"
|
|
607
|
+
)
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
4. **Verify plan exists** at `${QUICK_DIR}/${next_num}-PLAN.md`
|
|
611
|
+
|
|
612
|
+
5. **Pre-flight plan structure check (gsd-tools):**
|
|
613
|
+
```bash
|
|
614
|
+
PLAN_CHECK=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs verify plan-structure "${QUICK_DIR}/${next_num}-PLAN.md")
|
|
615
|
+
```
|
|
616
|
+
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.
|
|
617
|
+
|
|
618
|
+
6. **(If --full) Spawn plan-checker, handle revision loop (max 2 iterations):**
|
|
619
|
+
```
|
|
620
|
+
Task(
|
|
621
|
+
prompt="
|
|
622
|
+
<files_to_read>
|
|
623
|
+
- ./CLAUDE.md (Project instructions — if exists, follow all guidelines)
|
|
624
|
+
- .agents/skills/ (Project skills — if dir exists, list skills, read SKILL.md for each, follow relevant rules)
|
|
625
|
+
- ${QUICK_DIR}/${next_num}-PLAN.md (Plan to verify)
|
|
626
|
+
</files_to_read>
|
|
627
|
+
|
|
628
|
+
<verification_context>
|
|
629
|
+
**Mode:** quick-full
|
|
630
|
+
**Task Description:** ${TASK_DESCRIPTION}
|
|
631
|
+
|
|
632
|
+
<structural_preflight>
|
|
633
|
+
${PLAN_CHECK}
|
|
634
|
+
</structural_preflight>
|
|
635
|
+
|
|
636
|
+
**Scope:** This is a quick task, not a full phase. Skip checks that require a ROADMAP phase goal. If structural_preflight flagged issues, prioritize evaluating those.
|
|
637
|
+
</verification_context>
|
|
638
|
+
|
|
639
|
+
<check_dimensions>
|
|
640
|
+
- Requirement coverage: Does the plan address the task description?
|
|
641
|
+
- Task completeness: Do tasks have files, action, verify, done fields?
|
|
642
|
+
- Key links: Are referenced files real?
|
|
643
|
+
- Scope sanity: Is this appropriately sized for a quick task (1-3 tasks)?
|
|
644
|
+
- must_haves derivation: Are must_haves traceable to the task description?
|
|
645
|
+
|
|
646
|
+
Skip: context compliance (no CONTEXT.md), cross-plan deps (single plan), ROADMAP alignment
|
|
647
|
+
</check_dimensions>
|
|
648
|
+
|
|
649
|
+
<expected_output>
|
|
650
|
+
- ## VERIFICATION PASSED — all checks pass
|
|
651
|
+
- ## ISSUES FOUND — structured issue list
|
|
652
|
+
</expected_output>
|
|
653
|
+
",
|
|
654
|
+
subagent_type="gsd-plan-checker",
|
|
655
|
+
model="{checker_model}",
|
|
656
|
+
description="Check quick plan: ${issue_title}"
|
|
657
|
+
)
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
If issues found and iteration < 2: spawn planner revision, then re-check.
|
|
661
|
+
If iteration >= 2: offer force proceed or abort.
|
|
662
|
+
|
|
663
|
+
7. **Spawn executor (task agent):**
|
|
664
|
+
```
|
|
665
|
+
Task(
|
|
666
|
+
prompt="
|
|
667
|
+
<files_to_read>
|
|
668
|
+
- ./CLAUDE.md (Project instructions — if exists, follow all guidelines)
|
|
669
|
+
- .agents/skills/ (Project skills — if dir exists, list skills, read SKILL.md for each, follow relevant rules)
|
|
670
|
+
- ${QUICK_DIR}/${next_num}-PLAN.md (Plan)
|
|
671
|
+
</files_to_read>
|
|
672
|
+
|
|
673
|
+
Execute quick task ${next_num}.
|
|
674
|
+
|
|
675
|
+
<constraints>
|
|
676
|
+
- Execute all tasks in the plan
|
|
677
|
+
- Commit each task atomically
|
|
678
|
+
- Create summary at: ${QUICK_DIR}/${next_num}-SUMMARY.md
|
|
679
|
+
- Do NOT update ROADMAP.md or STATE.md (GSD owns .planning/ files)
|
|
680
|
+
</constraints>
|
|
681
|
+
",
|
|
682
|
+
subagent_type="gsd-executor",
|
|
683
|
+
model="{executor_model}",
|
|
684
|
+
description="Execute: ${issue_title}"
|
|
685
|
+
)
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
8. **Verify summary (gsd-tools):**
|
|
689
|
+
```bash
|
|
690
|
+
VERIFY_RESULT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs verify-summary "${QUICK_DIR}/${next_num}-SUMMARY.md")
|
|
691
|
+
```
|
|
692
|
+
Parse JSON result. Use `passed` field for go/no-go. Checks summary existence, files created, and commits.
|
|
693
|
+
|
|
694
|
+
9. **(If --full) Spawn verifier:**
|
|
695
|
+
```
|
|
696
|
+
Task(
|
|
697
|
+
prompt="
|
|
698
|
+
<files_to_read>
|
|
699
|
+
- ./CLAUDE.md (Project instructions — if exists, follow all guidelines)
|
|
700
|
+
- .agents/skills/ (Project skills — if dir exists, list skills, read SKILL.md for each, follow relevant rules)
|
|
701
|
+
- ${QUICK_DIR}/${next_num}-PLAN.md (Plan)
|
|
702
|
+
</files_to_read>
|
|
703
|
+
|
|
704
|
+
Verify quick task goal achievement.
|
|
705
|
+
Task directory: ${QUICK_DIR}
|
|
706
|
+
Task goal: ${TASK_DESCRIPTION}
|
|
707
|
+
|
|
708
|
+
Check must_haves against actual codebase. Create VERIFICATION.md at ${QUICK_DIR}/${next_num}-VERIFICATION.md.",
|
|
709
|
+
subagent_type="gsd-verifier",
|
|
710
|
+
model="{verifier_model}",
|
|
711
|
+
description="Verify: ${issue_title}"
|
|
712
|
+
)
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
10. **Post-execution artifact verification (non-blocking):**
|
|
716
|
+
```bash
|
|
717
|
+
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}')
|
|
718
|
+
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}')
|
|
719
|
+
```
|
|
720
|
+
Non-blocking: if either check flags issues, include them in the PR description as warnings. Do not halt the pipeline.
|
|
721
|
+
|
|
722
|
+
11. **Commit artifacts:**
|
|
723
|
+
```bash
|
|
724
|
+
node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs(quick-${next_num}): ${issue_title}" --files ${file_list}
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
Update state (at `${REPO_ROOT}/.mgw/active/`): gsd_artifacts.path = $QUICK_DIR, pipeline_stage = "verifying".
|
|
728
|
+
</step>
|
|
729
|
+
|
|
730
|
+
<step name="execute_gsd_milestone">
|
|
731
|
+
**Execute GSD pipeline (new-milestone route):**
|
|
732
|
+
|
|
733
|
+
Only run this step if gsd_route is "gsd:new-milestone".
|
|
734
|
+
|
|
735
|
+
This is the most complex path. The orchestrator needs to:
|
|
736
|
+
|
|
737
|
+
**Resolve models for milestone agents:**
|
|
738
|
+
```bash
|
|
739
|
+
PLANNER_MODEL=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs resolve-model gsd-planner --raw)
|
|
740
|
+
EXECUTOR_MODEL=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs resolve-model gsd-executor --raw)
|
|
741
|
+
VERIFIER_MODEL=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs resolve-model gsd-verifier --raw)
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
1. **Discussion phase trigger for large-scope issues:**
|
|
745
|
+
|
|
746
|
+
If the issue was triaged with large scope and `gsd_route == "gsd:new-milestone"`, post
|
|
747
|
+
a scope proposal comment and set the discussing stage before proceeding to phase execution:
|
|
748
|
+
|
|
749
|
+
```bash
|
|
750
|
+
DISCUSS_TIMESTAMP=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs current-timestamp --raw 2>/dev/null || date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
751
|
+
|
|
752
|
+
# Build scope breakdown from triage data
|
|
753
|
+
SCOPE_SIZE="${triage.scope.size}"
|
|
754
|
+
SCOPE_BREAKDOWN="${triage.scope.files formatted as table rows}"
|
|
755
|
+
PHASE_COUNT="TBD (determined by roadmapper)"
|
|
756
|
+
|
|
757
|
+
# Post scope proposal comment using template from github.md
|
|
758
|
+
# Use Scope Proposal Comment template from @~/.claude/commands/mgw/workflows/github.md
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
Set pipeline_stage to "discussing" and apply "mgw:discussing" label:
|
|
762
|
+
```bash
|
|
763
|
+
gh issue edit ${ISSUE_NUMBER} --remove-label "mgw:in-progress" 2>/dev/null
|
|
764
|
+
gh issue edit ${ISSUE_NUMBER} --add-label "mgw:discussing" 2>/dev/null
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
Present to user:
|
|
768
|
+
```
|
|
769
|
+
AskUserQuestion(
|
|
770
|
+
header: "Scope Proposal Posted",
|
|
771
|
+
question: "A scope proposal has been posted to GitHub. Proceed with autonomous roadmap creation, or wait for stakeholder feedback?",
|
|
772
|
+
options: [
|
|
773
|
+
{ label: "Proceed", description: "Continue with roadmap creation now" },
|
|
774
|
+
{ label: "Wait", description: "Pipeline paused until stakeholder approves scope" }
|
|
775
|
+
]
|
|
776
|
+
)
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
If wait: stop here. User will re-run /mgw:run after scope is approved.
|
|
780
|
+
If proceed: apply "mgw:approved" label and continue.
|
|
781
|
+
|
|
782
|
+
2. **Create milestone:** Use `gsd-tools init new-milestone` to gather context, then attempt autonomous roadmap creation from issue data:
|
|
783
|
+
|
|
784
|
+
```bash
|
|
785
|
+
MILESTONE_INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs init new-milestone 2>/dev/null)
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
Extract requirements from structured issue template fields (BLUF, What's Needed, What's Involved) if present.
|
|
789
|
+
|
|
790
|
+
If issue body contains sufficient detail (has clear requirements/scope):
|
|
791
|
+
- Spawn roadmapper agent with issue-derived requirements
|
|
792
|
+
- After roadmap generation, present to user for confirmation checkpoint:
|
|
793
|
+
```
|
|
794
|
+
AskUserQuestion(
|
|
795
|
+
header: "Milestone Roadmap Generated",
|
|
796
|
+
question: "Review the generated ROADMAP.md. Proceed with execution, revise, or switch to interactive mode?",
|
|
797
|
+
followUp: "Enter: proceed, revise, or interactive"
|
|
798
|
+
)
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
If issue body lacks sufficient detail (no clear structure or too vague):
|
|
802
|
+
- Fall back to interactive mode:
|
|
803
|
+
```
|
|
804
|
+
The new-milestone route requires more detail than the issue provides.
|
|
805
|
+
Please run: /gsd:new-milestone
|
|
806
|
+
|
|
807
|
+
After the milestone is created, run /mgw:run ${ISSUE_NUMBER} again to
|
|
808
|
+
continue the pipeline through execution.
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
Update pipeline_stage to "planning" (at `${REPO_ROOT}/.mgw/active/`).
|
|
812
|
+
|
|
813
|
+
2. **If resuming with pipeline_stage = "planning" and ROADMAP.md exists:**
|
|
814
|
+
Discover phases from ROADMAP and run the full per-phase GSD lifecycle:
|
|
815
|
+
|
|
816
|
+
```bash
|
|
817
|
+
ROADMAP_ANALYSIS=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap analyze)
|
|
818
|
+
# Parse ROADMAP_ANALYSIS JSON for list of phases:
|
|
819
|
+
# Each phase has: phase_number, phase_name, phase_slug
|
|
820
|
+
PHASE_LIST=$(echo "$ROADMAP_ANALYSIS" | python3 -c "
|
|
821
|
+
import json, sys
|
|
822
|
+
data = json.load(sys.stdin)
|
|
823
|
+
for p in data.get('phases', []):
|
|
824
|
+
print(f\"{p['number']}|{p['name']}|{p.get('slug', '')}\")
|
|
825
|
+
")
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
For each phase in order:
|
|
829
|
+
|
|
830
|
+
**a. Scaffold phase directory, then init:**
|
|
831
|
+
|
|
832
|
+
`init plan-phase` requires the phase directory to exist before it can locate it.
|
|
833
|
+
Use `scaffold phase-dir` first (which creates the directory from ROADMAP data),
|
|
834
|
+
then call `init plan-phase` to get planner/checker model assignments.
|
|
835
|
+
|
|
836
|
+
```bash
|
|
837
|
+
# Generate slug from phase name (lowercase, hyphens, no special chars)
|
|
838
|
+
PHASE_SLUG=$(echo "${PHASE_NAME}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
|
|
839
|
+
|
|
840
|
+
# Scaffold creates the directory and returns the path
|
|
841
|
+
SCAFFOLD=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs scaffold phase-dir --phase "${PHASE_NUMBER}" --name "${PHASE_SLUG}")
|
|
842
|
+
phase_dir=$(echo "$SCAFFOLD" | python3 -c "import json,sys; print(json.load(sys.stdin)['directory'])")
|
|
843
|
+
|
|
844
|
+
# Now init plan-phase can find the directory for model resolution
|
|
845
|
+
PHASE_INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs init plan-phase "${PHASE_NUMBER}")
|
|
846
|
+
# Parse PHASE_INIT JSON for: planner_model, checker_model
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
**b. Spawn planner agent (gsd:plan-phase):**
|
|
850
|
+
```
|
|
851
|
+
Task(
|
|
852
|
+
prompt="
|
|
853
|
+
<files_to_read>
|
|
854
|
+
- ./CLAUDE.md (Project instructions -- if exists, follow all guidelines)
|
|
855
|
+
- .agents/skills/ (Project skills -- if dir exists, list skills, read SKILL.md for each, follow relevant rules)
|
|
856
|
+
- .planning/ROADMAP.md (Phase definitions and requirements)
|
|
857
|
+
- .planning/STATE.md (If exists -- project state)
|
|
858
|
+
</files_to_read>
|
|
859
|
+
|
|
860
|
+
You are the GSD planner. Plan phase ${PHASE_NUMBER}: ${PHASE_NAME}.
|
|
861
|
+
|
|
862
|
+
Read and follow the plan-phase workflow:
|
|
863
|
+
@~/.claude/get-shit-done/workflows/plan-phase.md
|
|
864
|
+
|
|
865
|
+
Phase directory: ${phase_dir}
|
|
866
|
+
Phase number: ${PHASE_NUMBER}
|
|
867
|
+
|
|
868
|
+
Create PLAN.md file(s) in the phase directory. Each plan must have:
|
|
869
|
+
- Frontmatter with phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
|
|
870
|
+
- Objective, context, tasks, verification, success criteria, output sections
|
|
871
|
+
- Each task with files, action, verify, done fields
|
|
872
|
+
|
|
873
|
+
Commit the plan files when done.
|
|
874
|
+
",
|
|
875
|
+
subagent_type="gsd-planner",
|
|
876
|
+
model="${PLANNER_MODEL}",
|
|
877
|
+
description="Plan phase ${PHASE_NUMBER}: ${PHASE_NAME}"
|
|
878
|
+
)
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
**c. Verify plans exist:**
|
|
882
|
+
```bash
|
|
883
|
+
PLAN_COUNT=$(ls ${phase_dir}/*-PLAN.md 2>/dev/null | wc -l)
|
|
884
|
+
if [ "$PLAN_COUNT" -eq 0 ]; then
|
|
885
|
+
echo "ERROR: No plans created for phase ${PHASE_NUMBER}. Skipping phase execution."
|
|
886
|
+
# Post error comment and continue to next phase
|
|
887
|
+
gh issue comment ${ISSUE_NUMBER} --body "> **MGW** \`phase-error\` Phase ${PHASE_NUMBER} planning produced no plans. Skipping." 2>/dev/null || true
|
|
888
|
+
continue
|
|
889
|
+
fi
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
**d. Init execute-phase and spawn executor agent (gsd:execute-phase):**
|
|
893
|
+
```bash
|
|
894
|
+
EXEC_INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs init execute-phase "${PHASE_NUMBER}")
|
|
895
|
+
# Parse EXEC_INIT JSON for: executor_model, verifier_model, phase_dir, plans, incomplete_plans, plan_count
|
|
896
|
+
```
|
|
897
|
+
```
|
|
898
|
+
Task(
|
|
899
|
+
prompt="
|
|
900
|
+
<files_to_read>
|
|
901
|
+
- ./CLAUDE.md (Project instructions -- if exists, follow all guidelines)
|
|
902
|
+
- .agents/skills/ (Project skills -- if dir exists, list skills, read SKILL.md for each, follow relevant rules)
|
|
903
|
+
- ${phase_dir}/*-PLAN.md (Plans to execute)
|
|
904
|
+
</files_to_read>
|
|
905
|
+
|
|
906
|
+
You are the GSD executor. Execute all plans for phase ${PHASE_NUMBER}: ${PHASE_NAME}.
|
|
907
|
+
|
|
908
|
+
Read and follow the execute-phase workflow:
|
|
909
|
+
@~/.claude/get-shit-done/workflows/execute-phase.md
|
|
910
|
+
|
|
911
|
+
Phase: ${PHASE_NUMBER}
|
|
912
|
+
Phase directory: ${phase_dir}
|
|
913
|
+
|
|
914
|
+
Execute each plan's tasks in wave order. For each plan:
|
|
915
|
+
1. Execute all tasks
|
|
916
|
+
2. Commit each task atomically
|
|
917
|
+
3. Create SUMMARY.md in the phase directory
|
|
918
|
+
|
|
919
|
+
Do NOT update ROADMAP.md or STATE.md directly -- those are managed by GSD tools.
|
|
920
|
+
",
|
|
921
|
+
subagent_type="gsd-executor",
|
|
922
|
+
model="${EXECUTOR_MODEL}",
|
|
923
|
+
description="Execute phase ${PHASE_NUMBER}: ${PHASE_NAME}"
|
|
924
|
+
)
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
**e. Spawn verifier agent (gsd:verify-phase):**
|
|
928
|
+
```
|
|
929
|
+
Task(
|
|
930
|
+
prompt="
|
|
931
|
+
<files_to_read>
|
|
932
|
+
- ./CLAUDE.md (Project instructions -- if exists, follow all guidelines)
|
|
933
|
+
- .agents/skills/ (Project skills -- if dir exists, list skills, read SKILL.md for each, follow relevant rules)
|
|
934
|
+
- ${phase_dir}/*-PLAN.md (Plans with must_haves)
|
|
935
|
+
- ${phase_dir}/*-SUMMARY.md (Execution summaries)
|
|
936
|
+
</files_to_read>
|
|
937
|
+
|
|
938
|
+
Verify phase ${PHASE_NUMBER}: ${PHASE_NAME} goal achievement.
|
|
939
|
+
|
|
940
|
+
Read and follow the verify-phase workflow:
|
|
941
|
+
@~/.claude/get-shit-done/workflows/verify-phase.md
|
|
942
|
+
|
|
943
|
+
Phase: ${PHASE_NUMBER}
|
|
944
|
+
Phase directory: ${phase_dir}
|
|
945
|
+
|
|
946
|
+
Check must_haves from plan frontmatter against actual codebase.
|
|
947
|
+
Create VERIFICATION.md in the phase directory.
|
|
948
|
+
",
|
|
949
|
+
subagent_type="gsd-verifier",
|
|
950
|
+
model="${VERIFIER_MODEL}",
|
|
951
|
+
description="Verify phase ${PHASE_NUMBER}: ${PHASE_NAME}"
|
|
952
|
+
)
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
**f. Post phase-complete comment directly (no sub-agent):**
|
|
956
|
+
```bash
|
|
957
|
+
PHASE_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
958
|
+
VERIFICATION_STATUS=$(grep -m1 "^## " "${phase_dir}/"*-VERIFICATION.md 2>/dev/null | head -1 || echo "Verification complete")
|
|
959
|
+
PHASE_BODY=$(cat <<COMMENTEOF
|
|
960
|
+
> **MGW** · \`phase-complete\` · ${PHASE_TIMESTAMP}
|
|
961
|
+
> ${MILESTONE_CONTEXT}
|
|
962
|
+
|
|
963
|
+
### Phase ${PHASE_NUMBER} Complete — ${PHASE_NAME}
|
|
964
|
+
|
|
965
|
+
Execution complete. See ${phase_dir} for plans, summaries, and verification.
|
|
966
|
+
|
|
967
|
+
**Verification:** ${VERIFICATION_STATUS}
|
|
968
|
+
COMMENTEOF
|
|
969
|
+
)
|
|
970
|
+
gh issue comment ${ISSUE_NUMBER} --body "$PHASE_BODY" 2>/dev/null || true
|
|
971
|
+
```
|
|
972
|
+
|
|
973
|
+
After ALL phases complete → update pipeline_stage to "verifying" (at `${REPO_ROOT}/.mgw/active/`).
|
|
974
|
+
</step>
|
|
975
|
+
|
|
976
|
+
<step name="post_execution_update">
|
|
977
|
+
**Post execution-complete comment on issue:**
|
|
978
|
+
|
|
979
|
+
After GSD execution completes, post a structured update before creating the PR:
|
|
980
|
+
|
|
981
|
+
```bash
|
|
982
|
+
COMMIT_COUNT=$(git rev-list ${DEFAULT_BRANCH}..HEAD --count 2>/dev/null || echo "0")
|
|
983
|
+
TEST_STATUS=$(npm test 2>&1 >/dev/null && echo "passing" || echo "failing")
|
|
984
|
+
FILE_CHANGES=$(git diff --stat ${DEFAULT_BRANCH}..HEAD 2>/dev/null | tail -1)
|
|
985
|
+
EXEC_TIMESTAMP=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs current-timestamp --raw 2>/dev/null || date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
Post the execution-complete comment directly (no sub-agent — guarantees it happens):
|
|
989
|
+
|
|
990
|
+
```bash
|
|
991
|
+
EXEC_BODY=$(cat <<COMMENTEOF
|
|
992
|
+
> **MGW** · \`execution-complete\` · ${EXEC_TIMESTAMP}
|
|
993
|
+
> ${MILESTONE_CONTEXT}
|
|
994
|
+
|
|
995
|
+
### Execution Complete
|
|
996
|
+
|
|
997
|
+
${COMMIT_COUNT} atomic commit(s) on branch \`${BRANCH_NAME}\`.
|
|
998
|
+
|
|
999
|
+
**Changes:** ${FILE_CHANGES}
|
|
1000
|
+
|
|
1001
|
+
**Tests:** ${TEST_STATUS}
|
|
1002
|
+
|
|
1003
|
+
Preparing pull request.
|
|
1004
|
+
COMMENTEOF
|
|
1005
|
+
)
|
|
1006
|
+
|
|
1007
|
+
gh issue comment ${ISSUE_NUMBER} --body "$EXEC_BODY" 2>/dev/null || true
|
|
1008
|
+
```
|
|
1009
|
+
|
|
1010
|
+
Update pipeline_stage to "pr-pending" (at `${REPO_ROOT}/.mgw/active/`).
|
|
1011
|
+
</step>
|
|
1012
|
+
|
|
1013
|
+
<step name="create_pr">
|
|
1014
|
+
**Create PR (task agent):**
|
|
1015
|
+
|
|
1016
|
+
After GSD execution completes (any route):
|
|
1017
|
+
|
|
1018
|
+
Push branch and gather artifacts:
|
|
1019
|
+
```bash
|
|
1020
|
+
git push -u origin ${BRANCH_NAME}
|
|
1021
|
+
|
|
1022
|
+
# Structured summary data via gsd-tools (returns JSON with one_liner, key_files, tech_added, patterns, decisions)
|
|
1023
|
+
SUMMARY_DATA=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs summary-extract "${gsd_artifacts_path}/*SUMMARY*" 2>/dev/null || echo '{}')
|
|
1024
|
+
# Also keep raw summary for full context
|
|
1025
|
+
SUMMARY=$(cat ${gsd_artifacts_path}/*SUMMARY* 2>/dev/null)
|
|
1026
|
+
VERIFICATION=$(cat ${gsd_artifacts_path}/*VERIFICATION* 2>/dev/null)
|
|
1027
|
+
COMMITS=$(git log ${DEFAULT_BRANCH}..HEAD --oneline)
|
|
1028
|
+
CROSS_REFS=$(cat ${REPO_ROOT}/.mgw/cross-refs.json 2>/dev/null)
|
|
1029
|
+
# Progress table for PR details section
|
|
1030
|
+
PROGRESS_TABLE=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs progress table --raw 2>/dev/null || echo "")
|
|
1031
|
+
|
|
1032
|
+
# Milestone/phase context for PR body
|
|
1033
|
+
MILESTONE_TITLE=""
|
|
1034
|
+
PHASE_INFO=""
|
|
1035
|
+
DEPENDENCY_CHAIN=""
|
|
1036
|
+
PROJECT_BOARD_URL=""
|
|
1037
|
+
if [ -f "${REPO_ROOT}/.mgw/project.json" ]; then
|
|
1038
|
+
MILESTONE_TITLE=$(python3 -c "
|
|
1039
|
+
import json
|
|
1040
|
+
p = json.load(open('${REPO_ROOT}/.mgw/project.json'))
|
|
1041
|
+
for m in p['milestones']:
|
|
1042
|
+
for i in m.get('issues', []):
|
|
1043
|
+
if i.get('github_number') == ${ISSUE_NUMBER}:
|
|
1044
|
+
print(m['name'])
|
|
1045
|
+
break
|
|
1046
|
+
" 2>/dev/null || echo "")
|
|
1047
|
+
|
|
1048
|
+
PHASE_INFO=$(python3 -c "
|
|
1049
|
+
import json
|
|
1050
|
+
p = json.load(open('${REPO_ROOT}/.mgw/project.json'))
|
|
1051
|
+
total_phases = sum(len(m.get('issues', [])) for m in p['milestones'])
|
|
1052
|
+
for m in p['milestones']:
|
|
1053
|
+
for i in m.get('issues', []):
|
|
1054
|
+
if i.get('github_number') == ${ISSUE_NUMBER}:
|
|
1055
|
+
total_in_milestone = len(m.get('issues', []))
|
|
1056
|
+
idx = [x['github_number'] for x in m['issues']].index(${ISSUE_NUMBER}) + 1
|
|
1057
|
+
print(f\"Phase {i['phase_number']}: {i['phase_name']} (issue {idx}/{total_in_milestone} in milestone)\")
|
|
1058
|
+
break
|
|
1059
|
+
" 2>/dev/null || echo "")
|
|
1060
|
+
|
|
1061
|
+
DEPENDENCY_CHAIN=$(python3 -c "
|
|
1062
|
+
import json
|
|
1063
|
+
p = json.load(open('${REPO_ROOT}/.mgw/project.json'))
|
|
1064
|
+
refs = json.load(open('${REPO_ROOT}/.mgw/cross-refs.json'))
|
|
1065
|
+
blockers = [l['b'].split(':')[1] for l in refs.get('links', [])
|
|
1066
|
+
if l.get('type') == 'blocked-by' and l['a'] == 'issue:${ISSUE_NUMBER}']
|
|
1067
|
+
blocks = [l['a'].split(':')[1] for l in refs.get('links', [])
|
|
1068
|
+
if l.get('type') == 'blocked-by' and l['b'] == 'issue:${ISSUE_NUMBER}']
|
|
1069
|
+
parts = []
|
|
1070
|
+
if blockers: parts.append('Blocked by: ' + ', '.join(f'#{b}' for b in blockers))
|
|
1071
|
+
if blocks: parts.append('Unblocks: ' + ', '.join(f'#{b}' for b in blocks))
|
|
1072
|
+
print(' | '.join(parts) if parts else 'No dependencies')
|
|
1073
|
+
" 2>/dev/null || echo "")
|
|
1074
|
+
|
|
1075
|
+
PROJECT_BOARD_URL=$(python3 -c "
|
|
1076
|
+
import json
|
|
1077
|
+
p = json.load(open('${REPO_ROOT}/.mgw/project.json'))
|
|
1078
|
+
print(p.get('project', {}).get('project_board', {}).get('url', ''))
|
|
1079
|
+
" 2>/dev/null || echo "")
|
|
1080
|
+
fi
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
Read issue state for context.
|
|
1084
|
+
|
|
1085
|
+
```
|
|
1086
|
+
Task(
|
|
1087
|
+
prompt="
|
|
1088
|
+
<files_to_read>
|
|
1089
|
+
- ./CLAUDE.md (Project instructions — if exists, follow all guidelines)
|
|
1090
|
+
- .agents/skills/ (Project skills — if dir exists, list skills, read SKILL.md for each, follow relevant rules)
|
|
1091
|
+
</files_to_read>
|
|
1092
|
+
|
|
1093
|
+
Create a GitHub PR for issue #${ISSUE_NUMBER}.
|
|
1094
|
+
|
|
1095
|
+
<issue>
|
|
1096
|
+
Title: ${issue_title}
|
|
1097
|
+
Body: ${issue_body}
|
|
1098
|
+
</issue>
|
|
1099
|
+
|
|
1100
|
+
<milestone_context>
|
|
1101
|
+
Milestone: ${MILESTONE_TITLE}
|
|
1102
|
+
Phase: ${PHASE_INFO}
|
|
1103
|
+
Dependencies: ${DEPENDENCY_CHAIN}
|
|
1104
|
+
Board: ${PROJECT_BOARD_URL}
|
|
1105
|
+
</milestone_context>
|
|
1106
|
+
|
|
1107
|
+
<summary_structured>
|
|
1108
|
+
${SUMMARY_DATA}
|
|
1109
|
+
</summary_structured>
|
|
1110
|
+
|
|
1111
|
+
<summary_raw>
|
|
1112
|
+
${SUMMARY}
|
|
1113
|
+
</summary_raw>
|
|
1114
|
+
|
|
1115
|
+
<verification>
|
|
1116
|
+
${VERIFICATION}
|
|
1117
|
+
</verification>
|
|
1118
|
+
|
|
1119
|
+
<artifact_warnings>
|
|
1120
|
+
${ARTIFACT_CHECK}
|
|
1121
|
+
${KEYLINK_CHECK}
|
|
1122
|
+
</artifact_warnings>
|
|
1123
|
+
|
|
1124
|
+
<commits>
|
|
1125
|
+
${COMMITS}
|
|
1126
|
+
</commits>
|
|
1127
|
+
|
|
1128
|
+
<cross_refs>
|
|
1129
|
+
${CROSS_REFS}
|
|
1130
|
+
</cross_refs>
|
|
1131
|
+
|
|
1132
|
+
<instructions>
|
|
1133
|
+
1. Build PR title: short, prefixed with fix:/feat:/refactor: based on issue labels. Under 70 characters.
|
|
1134
|
+
|
|
1135
|
+
2. Build PR body using this EXACT structure (fill in from data above):
|
|
1136
|
+
|
|
1137
|
+
## Summary
|
|
1138
|
+
- 2-4 bullets of what was built and why (use one_liner from summary_structured if available)
|
|
1139
|
+
|
|
1140
|
+
Closes #${ISSUE_NUMBER}
|
|
1141
|
+
|
|
1142
|
+
## Milestone Context
|
|
1143
|
+
- **Milestone:** ${MILESTONE_TITLE}
|
|
1144
|
+
- **Phase:** ${PHASE_INFO}
|
|
1145
|
+
- **Dependencies:** ${DEPENDENCY_CHAIN}
|
|
1146
|
+
(Skip this section entirely if MILESTONE_TITLE is empty)
|
|
1147
|
+
|
|
1148
|
+
## Changes
|
|
1149
|
+
- File-level changes grouped by module (use key_files from summary_structured)
|
|
1150
|
+
|
|
1151
|
+
## Test Plan
|
|
1152
|
+
- Verification checklist from VERIFICATION artifact
|
|
1153
|
+
|
|
1154
|
+
## Cross-References
|
|
1155
|
+
- ${CROSS_REFS entries as bullet points}
|
|
1156
|
+
(Skip if no cross-refs)
|
|
1157
|
+
|
|
1158
|
+
<details>
|
|
1159
|
+
<summary>GSD Progress</summary>
|
|
1160
|
+
|
|
1161
|
+
${PROGRESS_TABLE}
|
|
1162
|
+
</details>
|
|
1163
|
+
(Skip if PROGRESS_TABLE is empty)
|
|
1164
|
+
|
|
1165
|
+
3. Create PR: gh pr create --title '<title>' --base '${DEFAULT_BRANCH}' --head '${BRANCH_NAME}' --body '<body>'
|
|
1166
|
+
4. Post testing procedures as separate PR comment: gh pr comment <pr_number> --body '<testing>'
|
|
1167
|
+
5. Return: PR number, PR URL
|
|
1168
|
+
</instructions>
|
|
1169
|
+
",
|
|
1170
|
+
subagent_type="general-purpose",
|
|
1171
|
+
description="Create PR for #${ISSUE_NUMBER}"
|
|
1172
|
+
)
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
Parse PR number and URL from agent response.
|
|
1176
|
+
|
|
1177
|
+
Update state (at `${REPO_ROOT}/.mgw/active/`):
|
|
1178
|
+
- linked_pr = PR number
|
|
1179
|
+
- pipeline_stage = "pr-created"
|
|
1180
|
+
|
|
1181
|
+
Add cross-ref (at `${REPO_ROOT}/.mgw/cross-refs.json`): issue → PR.
|
|
1182
|
+
</step>
|
|
1183
|
+
|
|
1184
|
+
<step name="cleanup_and_complete">
|
|
1185
|
+
**Clean up worktree, post completion, and prompt sync:**
|
|
1186
|
+
|
|
1187
|
+
Return to main repo and remove worktree (branch persists for PR):
|
|
1188
|
+
```bash
|
|
1189
|
+
cd "${REPO_ROOT}"
|
|
1190
|
+
git worktree remove "${WORKTREE_DIR}" 2>/dev/null
|
|
1191
|
+
rmdir "${REPO_ROOT}/.worktrees/issue" 2>/dev/null
|
|
1192
|
+
rmdir "${REPO_ROOT}/.worktrees" 2>/dev/null
|
|
1193
|
+
```
|
|
1194
|
+
|
|
1195
|
+
Remove in-progress label at completion:
|
|
1196
|
+
```bash
|
|
1197
|
+
gh issue edit ${ISSUE_NUMBER} --remove-label "mgw:in-progress" 2>/dev/null
|
|
1198
|
+
```
|
|
1199
|
+
|
|
1200
|
+
Extract one-liner summary for concise comment:
|
|
1201
|
+
```bash
|
|
1202
|
+
ONE_LINER=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs summary-extract "${gsd_artifacts_path}/*SUMMARY*" --fields one_liner --raw 2>/dev/null || echo "")
|
|
1203
|
+
```
|
|
1204
|
+
|
|
1205
|
+
Post structured PR-ready comment directly (no sub-agent — guarantees it happens):
|
|
1206
|
+
|
|
1207
|
+
```bash
|
|
1208
|
+
DONE_TIMESTAMP=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs current-timestamp --raw 2>/dev/null || date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
1209
|
+
|
|
1210
|
+
PR_READY_BODY=$(cat <<COMMENTEOF
|
|
1211
|
+
> **MGW** · \`pr-ready\` · ${DONE_TIMESTAMP}
|
|
1212
|
+
> ${MILESTONE_CONTEXT}
|
|
1213
|
+
|
|
1214
|
+
### PR Ready
|
|
1215
|
+
|
|
1216
|
+
**PR #${PR_NUMBER}** — ${PR_URL}
|
|
1217
|
+
|
|
1218
|
+
${ONE_LINER}
|
|
1219
|
+
|
|
1220
|
+
Testing procedures posted on the PR.
|
|
1221
|
+
This issue will auto-close when the PR is merged.
|
|
1222
|
+
|
|
1223
|
+
<details>
|
|
1224
|
+
<summary>Pipeline Summary</summary>
|
|
1225
|
+
|
|
1226
|
+
| Stage | Status |
|
|
1227
|
+
|-------|--------|
|
|
1228
|
+
| Triage | ✓ |
|
|
1229
|
+
| Planning | ✓ |
|
|
1230
|
+
| Execution | ✓ |
|
|
1231
|
+
| PR Creation | ✓ |
|
|
1232
|
+
|
|
1233
|
+
</details>
|
|
1234
|
+
COMMENTEOF
|
|
1235
|
+
)
|
|
1236
|
+
|
|
1237
|
+
gh issue comment ${ISSUE_NUMBER} --body "$PR_READY_BODY" 2>/dev/null || true
|
|
1238
|
+
```
|
|
1239
|
+
|
|
1240
|
+
Update pipeline_stage to "done" (at `${REPO_ROOT}/.mgw/active/`).
|
|
1241
|
+
|
|
1242
|
+
Report to user:
|
|
1243
|
+
```
|
|
1244
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1245
|
+
MGW ► PIPELINE COMPLETE
|
|
1246
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1247
|
+
|
|
1248
|
+
Issue: #${ISSUE_NUMBER} — ${issue_title}
|
|
1249
|
+
Route: ${gsd_route}
|
|
1250
|
+
PR: #${PR_NUMBER} — ${PR_URL}
|
|
1251
|
+
Branch: ${BRANCH_NAME} (worktree cleaned up)
|
|
1252
|
+
|
|
1253
|
+
Status comments posted. PR includes testing procedures.
|
|
1254
|
+
Issue will auto-close on merge.
|
|
1255
|
+
|
|
1256
|
+
Next:
|
|
1257
|
+
→ Review the PR, then merge
|
|
1258
|
+
→ After merge: /mgw:sync to archive state and clean up branches
|
|
1259
|
+
```
|
|
1260
|
+
</step>
|
|
1261
|
+
|
|
1262
|
+
</process>
|
|
1263
|
+
|
|
1264
|
+
<success_criteria>
|
|
1265
|
+
- [ ] Issue number validated and state loaded (or triage run first)
|
|
1266
|
+
- [ ] Pipeline refuses needs-info without --force
|
|
1267
|
+
- [ ] Pipeline refuses needs-security-review without --security-ack
|
|
1268
|
+
- [ ] Isolated worktree created (.worktrees/ gitignored)
|
|
1269
|
+
- [ ] mgw:in-progress label applied during execution
|
|
1270
|
+
- [ ] Pre-flight comment check performed (new comments classified before execution)
|
|
1271
|
+
- [ ] mgw:blocked label applied when blocking comments detected
|
|
1272
|
+
- [ ] Work-starting comment posted on issue (route, scope, branch)
|
|
1273
|
+
- [ ] GSD pipeline executed in worktree (quick or milestone route)
|
|
1274
|
+
- [ ] New-milestone route triggers discussion phase with mgw:discussing label
|
|
1275
|
+
- [ ] Execution-complete comment posted on issue (commits, changes, test status)
|
|
1276
|
+
- [ ] PR created with summary, milestone context, testing procedures, cross-refs
|
|
1277
|
+
- [ ] Structured PR-ready comment posted on issue (PR link, pipeline summary)
|
|
1278
|
+
- [ ] Worktree cleaned up, user returned to main workspace
|
|
1279
|
+
- [ ] mgw:in-progress label removed at completion
|
|
1280
|
+
- [ ] State file updated through all pipeline stages
|
|
1281
|
+
- [ ] User prompted to run /mgw:sync after merge
|
|
1282
|
+
</success_criteria>
|