@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
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mgw:issue
|
|
3
|
+
description: Triage a GitHub issue — analyze against codebase, validate scope/security, recommend GSD route
|
|
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
|
+
Deep analysis of a single GitHub issue against the codebase. Fetches the issue,
|
|
18
|
+
assigns to self if needed, spawns a task agent for full analysis (scope, validity,
|
|
19
|
+
purpose, security, conflicts), presents a triage report, and recommends a GSD route.
|
|
20
|
+
|
|
21
|
+
Creates .mgw/ state file for the issue. Optionally routes to /mgw:run.
|
|
22
|
+
</objective>
|
|
23
|
+
|
|
24
|
+
<execution_context>
|
|
25
|
+
@~/.claude/commands/mgw/workflows/state.md
|
|
26
|
+
@~/.claude/commands/mgw/workflows/github.md
|
|
27
|
+
@~/.claude/commands/mgw/workflows/gsd.md
|
|
28
|
+
@~/.claude/commands/mgw/workflows/validation.md
|
|
29
|
+
</execution_context>
|
|
30
|
+
|
|
31
|
+
<context>
|
|
32
|
+
Issue number: $ARGUMENTS
|
|
33
|
+
|
|
34
|
+
Active issues context: .mgw/active/ (check for conflicts)
|
|
35
|
+
</context>
|
|
36
|
+
|
|
37
|
+
<process>
|
|
38
|
+
|
|
39
|
+
<step name="validate_input">
|
|
40
|
+
**Validate issue number provided:**
|
|
41
|
+
|
|
42
|
+
Parse $ARGUMENTS for a numeric issue number. If missing:
|
|
43
|
+
```
|
|
44
|
+
AskUserQuestion(
|
|
45
|
+
header: "Issue Number Required",
|
|
46
|
+
question: "Which issue number do you want to triage?",
|
|
47
|
+
followUp: "Enter the GitHub issue number (e.g., 42)"
|
|
48
|
+
)
|
|
49
|
+
```
|
|
50
|
+
</step>
|
|
51
|
+
|
|
52
|
+
<step name="init_state">
|
|
53
|
+
**Initialize .mgw/ directory:**
|
|
54
|
+
|
|
55
|
+
Follow initialization procedure from @~/.claude/commands/mgw/workflows/state.md.
|
|
56
|
+
Ensure .mgw/, active/, completed/ exist and .gitignore includes .mgw/.
|
|
57
|
+
</step>
|
|
58
|
+
|
|
59
|
+
<step name="fetch_issue">
|
|
60
|
+
**Fetch issue from GitHub:**
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
gh issue view $ISSUE_NUMBER --json number,title,body,labels,assignees,state,comments,url,milestone
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
If issue not found → error: "Issue #$ISSUE_NUMBER not found in this repo."
|
|
67
|
+
|
|
68
|
+
Store as $ISSUE_DATA.
|
|
69
|
+
|
|
70
|
+
**Capture comment tracking snapshot:**
|
|
71
|
+
|
|
72
|
+
Record the current comment count and timestamp of the most recent comment. These
|
|
73
|
+
are stored in the triage state and used by run.md's pre-flight comment check to
|
|
74
|
+
detect new comments posted between triage and execution.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
COMMENT_COUNT=$(echo "$ISSUE_DATA" | python3 -c "import json,sys; d=json.load(sys.stdin); print(len(d.get('comments', [])))")
|
|
78
|
+
LAST_COMMENT_AT=$(echo "$ISSUE_DATA" | python3 -c "
|
|
79
|
+
import json,sys
|
|
80
|
+
d = json.load(sys.stdin)
|
|
81
|
+
comments = d.get('comments', [])
|
|
82
|
+
if comments:
|
|
83
|
+
print(comments[-1].get('createdAt', ''))
|
|
84
|
+
else:
|
|
85
|
+
print('')
|
|
86
|
+
" 2>/dev/null || echo "")
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Store $COMMENT_COUNT and $LAST_COMMENT_AT for use in the write_state step.
|
|
90
|
+
</step>
|
|
91
|
+
|
|
92
|
+
<step name="assign_self">
|
|
93
|
+
**Assign to self if unassigned:**
|
|
94
|
+
|
|
95
|
+
Check if current user is in assignees list:
|
|
96
|
+
```bash
|
|
97
|
+
GH_USER=$(gh api user -q .login)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If not assigned:
|
|
101
|
+
```bash
|
|
102
|
+
gh issue edit $ISSUE_NUMBER --add-assignee @me
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Report: "Assigned #$ISSUE_NUMBER to $GH_USER"
|
|
106
|
+
</step>
|
|
107
|
+
|
|
108
|
+
<step name="spawn_analysis">
|
|
109
|
+
**Spawn task agent for codebase analysis:**
|
|
110
|
+
|
|
111
|
+
Gather GSD project history for context (if available):
|
|
112
|
+
```bash
|
|
113
|
+
HISTORY=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs history-digest 2>/dev/null || echo "")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Build analysis prompt from issue data and spawn:
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
Task(
|
|
120
|
+
prompt="
|
|
121
|
+
<files_to_read>
|
|
122
|
+
- ./CLAUDE.md (Project instructions — if exists, follow all guidelines)
|
|
123
|
+
- .agents/skills/ (Project skills — if dir exists, list skills, read SKILL.md for each, follow relevant rules)
|
|
124
|
+
</files_to_read>
|
|
125
|
+
|
|
126
|
+
Analyze GitHub issue #${ISSUE_NUMBER} against this codebase.
|
|
127
|
+
|
|
128
|
+
<issue>
|
|
129
|
+
Title: ${title}
|
|
130
|
+
Body: ${body}
|
|
131
|
+
Labels: ${labels}
|
|
132
|
+
Comments: ${comments_summary}
|
|
133
|
+
</issue>
|
|
134
|
+
|
|
135
|
+
<project_history>
|
|
136
|
+
${HISTORY}
|
|
137
|
+
</project_history>
|
|
138
|
+
|
|
139
|
+
<analysis_dimensions>
|
|
140
|
+
|
|
141
|
+
1. **Scope:** Search the codebase for files and systems related to this issue.
|
|
142
|
+
- List affected files with paths
|
|
143
|
+
- List affected systems/modules
|
|
144
|
+
- Estimate: small (1-2 files), medium (3-8 files), large (9+ files or new system)
|
|
145
|
+
|
|
146
|
+
2. **Validity:** Based on the codebase, is this a real problem?
|
|
147
|
+
- Can the issue be confirmed by reading the code?
|
|
148
|
+
- Are there existing tests that cover this area?
|
|
149
|
+
- Is the described behavior actually a bug or expected?
|
|
150
|
+
|
|
151
|
+
3. **Purpose/Benefit:** What does resolving this achieve?
|
|
152
|
+
- Who benefits (users, developers, ops)?
|
|
153
|
+
- What's the impact of NOT doing this?
|
|
154
|
+
|
|
155
|
+
4. **Security:** Does this touch sensitive areas?
|
|
156
|
+
- Authentication/authorization
|
|
157
|
+
- User data handling
|
|
158
|
+
- External API calls
|
|
159
|
+
- Input validation/sanitization
|
|
160
|
+
- If yes to any: note specific concerns
|
|
161
|
+
|
|
162
|
+
5. **Conflicts:** Read all JSON files in .mgw/active/ directory.
|
|
163
|
+
- Do any active issues touch the same files/systems?
|
|
164
|
+
- Note overlaps with file paths and issue numbers
|
|
165
|
+
|
|
166
|
+
</analysis_dimensions>
|
|
167
|
+
|
|
168
|
+
<output_format>
|
|
169
|
+
Return a structured report:
|
|
170
|
+
|
|
171
|
+
## Triage Report: #${ISSUE_NUMBER}
|
|
172
|
+
|
|
173
|
+
### Scope
|
|
174
|
+
- Files: [list]
|
|
175
|
+
- Systems: [list]
|
|
176
|
+
- Size: small|medium|large
|
|
177
|
+
|
|
178
|
+
### Validity
|
|
179
|
+
- Status: confirmed|questionable|invalid
|
|
180
|
+
- Evidence: [explanation]
|
|
181
|
+
|
|
182
|
+
### Purpose
|
|
183
|
+
- Benefit: [who and how]
|
|
184
|
+
- Impact if skipped: [consequence]
|
|
185
|
+
|
|
186
|
+
### Security
|
|
187
|
+
- Risk: none|low|medium|high
|
|
188
|
+
- Notes: [specific concerns or 'none']
|
|
189
|
+
|
|
190
|
+
### Conflicts
|
|
191
|
+
- Active overlaps: [list or 'none']
|
|
192
|
+
|
|
193
|
+
### Recommended GSD Route
|
|
194
|
+
- Route: gsd:quick | gsd:quick --full | gsd:new-milestone
|
|
195
|
+
- Reasoning: [why this route]
|
|
196
|
+
</output_format>
|
|
197
|
+
",
|
|
198
|
+
subagent_type="general-purpose",
|
|
199
|
+
description="Triage issue #${ISSUE_NUMBER}"
|
|
200
|
+
)
|
|
201
|
+
```
|
|
202
|
+
</step>
|
|
203
|
+
|
|
204
|
+
<step name="evaluate_gates">
|
|
205
|
+
**Evaluate triage quality gates:**
|
|
206
|
+
|
|
207
|
+
After the analysis agent returns, evaluate three quality gates against the triage report
|
|
208
|
+
and the original issue data. This determines whether the issue can proceed to pipeline
|
|
209
|
+
execution or requires additional information/review.
|
|
210
|
+
|
|
211
|
+
Initialize gate result:
|
|
212
|
+
```
|
|
213
|
+
gate_result = {
|
|
214
|
+
"status": "passed",
|
|
215
|
+
"blockers": [],
|
|
216
|
+
"warnings": [],
|
|
217
|
+
"missing_fields": []
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Gate 1: Validity**
|
|
222
|
+
```
|
|
223
|
+
if triage.validity == "invalid":
|
|
224
|
+
gate_result.blockers.push("Validity gate failed: issue could not be confirmed against codebase")
|
|
225
|
+
gate_result.status = "blocked"
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Gate 2: Security**
|
|
229
|
+
```
|
|
230
|
+
if triage.security_risk == "high":
|
|
231
|
+
gate_result.blockers.push("Security gate: high-risk issue requires security review before execution")
|
|
232
|
+
gate_result.status = "blocked"
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**Gate 3: Detail Sufficiency**
|
|
236
|
+
Evaluate the original issue body (not the triage report):
|
|
237
|
+
```
|
|
238
|
+
BODY_LENGTH = len(issue_body.strip())
|
|
239
|
+
HAS_AC = issue has acceptance criteria field filled OR body contains "- [ ]" checklist items
|
|
240
|
+
IS_FEATURE = "enhancement" in issue_labels OR issue template is feature_request
|
|
241
|
+
|
|
242
|
+
if BODY_LENGTH < 200:
|
|
243
|
+
gate_result.blockers.push("Insufficient detail: issue body is ${BODY_LENGTH} characters (minimum 200)")
|
|
244
|
+
gate_result.missing_fields.push("Expand issue description with more detail")
|
|
245
|
+
gate_result.status = "blocked"
|
|
246
|
+
|
|
247
|
+
if IS_FEATURE and not HAS_AC:
|
|
248
|
+
gate_result.blockers.push("Feature requests require acceptance criteria")
|
|
249
|
+
gate_result.missing_fields.push("Add acceptance criteria (checklist of testable conditions)")
|
|
250
|
+
gate_result.status = "blocked"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Gate warnings (non-blocking):**
|
|
254
|
+
```
|
|
255
|
+
if triage.security_risk == "medium":
|
|
256
|
+
gate_result.warnings.push("Medium security risk — consider review before execution")
|
|
257
|
+
|
|
258
|
+
if triage.scope.size == "large" and gsd_route != "gsd:new-milestone":
|
|
259
|
+
gate_result.warnings.push("Large scope detected but not routed to new-milestone")
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Set `gate_result.status = "passed"` if no blockers. Store gate_result for state file.
|
|
263
|
+
</step>
|
|
264
|
+
|
|
265
|
+
<step name="post_triage_github">
|
|
266
|
+
**Post immediate triage feedback to GitHub:**
|
|
267
|
+
|
|
268
|
+
This step posts a comment on the GitHub issue IMMEDIATELY during /mgw:issue, not
|
|
269
|
+
deferred to /mgw:run. This gives stakeholders visibility into triage results as
|
|
270
|
+
soon as they happen.
|
|
271
|
+
|
|
272
|
+
Generate timestamp:
|
|
273
|
+
```bash
|
|
274
|
+
TIMESTAMP=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs current-timestamp --raw 2>/dev/null || date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**If gates blocked (gate_result.status == "blocked"):**
|
|
278
|
+
|
|
279
|
+
Build gate table rows from gate_result.blockers:
|
|
280
|
+
```
|
|
281
|
+
GATE_TABLE_ROWS = gate_result.blockers formatted as "| ${blocker} | Blocked |" rows
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Build missing fields list from gate_result.missing_fields:
|
|
285
|
+
```
|
|
286
|
+
MISSING_FIELDS_LIST = gate_result.missing_fields formatted as "- ${field}" list
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Use the "Gate Blocked Comment" template from @~/.claude/commands/mgw/workflows/github.md.
|
|
290
|
+
Post comment and apply label:
|
|
291
|
+
```bash
|
|
292
|
+
# Use remove_mgw_labels_and_apply pattern from github.md
|
|
293
|
+
# For validity failures:
|
|
294
|
+
# pipeline_stage = "needs-info", label = "mgw:needs-info"
|
|
295
|
+
# For security failures:
|
|
296
|
+
# pipeline_stage = "needs-security-review", label = "mgw:needs-security-review"
|
|
297
|
+
# For detail failures:
|
|
298
|
+
# pipeline_stage = "needs-info", label = "mgw:needs-info"
|
|
299
|
+
# If multiple blockers, use the highest-severity label (security > detail > validity)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**If gates passed (gate_result.status == "passed"):**
|
|
303
|
+
|
|
304
|
+
Use the "Gate Passed Comment" template from @~/.claude/commands/mgw/workflows/github.md.
|
|
305
|
+
|
|
306
|
+
Populate template variables:
|
|
307
|
+
```
|
|
308
|
+
SCOPE_SIZE = triage.scope.size
|
|
309
|
+
FILE_COUNT = triage.scope.file_count
|
|
310
|
+
SYSTEM_LIST = triage.scope.systems joined with ", "
|
|
311
|
+
VALIDITY = triage.validity
|
|
312
|
+
SECURITY_RISK = triage.security_notes
|
|
313
|
+
gsd_route = recommended route
|
|
314
|
+
ROUTE_REASONING = triage reasoning
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Post comment and apply label:
|
|
318
|
+
```bash
|
|
319
|
+
gh issue edit ${ISSUE_NUMBER} --add-label "mgw:triaged" 2>/dev/null
|
|
320
|
+
```
|
|
321
|
+
</step>
|
|
322
|
+
|
|
323
|
+
<step name="present_report">
|
|
324
|
+
**Present triage report to user:**
|
|
325
|
+
|
|
326
|
+
Display the analysis agent's report verbatim, then display gate results:
|
|
327
|
+
|
|
328
|
+
```
|
|
329
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
330
|
+
MGW ► TRIAGE COMPLETE
|
|
331
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
332
|
+
|
|
333
|
+
Recommended route: ${recommended_route}
|
|
334
|
+
Reasoning: ${reasoning}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Then display gate results:
|
|
338
|
+
|
|
339
|
+
```
|
|
340
|
+
${if gate_result.status == "blocked":}
|
|
341
|
+
GATES: BLOCKED
|
|
342
|
+
${for blocker in gate_result.blockers:}
|
|
343
|
+
- ${blocker}
|
|
344
|
+
${end}
|
|
345
|
+
|
|
346
|
+
${if gate_result.missing_fields:}
|
|
347
|
+
Missing information:
|
|
348
|
+
${for field in gate_result.missing_fields:}
|
|
349
|
+
- ${field}
|
|
350
|
+
${end}
|
|
351
|
+
${end}
|
|
352
|
+
|
|
353
|
+
The issue needs updates before pipeline execution.
|
|
354
|
+
Options:
|
|
355
|
+
1) Wait for updates → issue stays in needs-info/needs-security-review
|
|
356
|
+
2) Override → proceed despite gate failures (adds acknowledgment to state)
|
|
357
|
+
3) Reject → issue is invalid or out of scope
|
|
358
|
+
|
|
359
|
+
${else:}
|
|
360
|
+
GATES: PASSED ${if gate_result.warnings: '(with warnings)'}
|
|
361
|
+
${for warning in gate_result.warnings:}
|
|
362
|
+
- Warning: ${warning}
|
|
363
|
+
${end}
|
|
364
|
+
|
|
365
|
+
Options:
|
|
366
|
+
1) Accept recommendation → proceed with ${recommended_route}
|
|
367
|
+
2) Override route → choose different GSD entry point
|
|
368
|
+
3) Reject → issue is invalid or out of scope
|
|
369
|
+
${end}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
```
|
|
373
|
+
AskUserQuestion(
|
|
374
|
+
header: "Triage Decision",
|
|
375
|
+
question: "${gate_result.status == 'blocked' ? 'Override gates (1), wait for updates (2), or reject (3)?' : 'Accept recommendation (1), override (2), or reject (3)?'}",
|
|
376
|
+
followUp: "${gate_result.status == 'blocked' ? 'Override will log acknowledgment. Wait keeps issue in blocked state.' : 'If overriding, specify: quick, quick --full, or new-milestone'}"
|
|
377
|
+
)
|
|
378
|
+
```
|
|
379
|
+
</step>
|
|
380
|
+
|
|
381
|
+
<step name="write_state">
|
|
382
|
+
**Write issue state file:**
|
|
383
|
+
|
|
384
|
+
If accepted, overridden, or gates blocked but user overrides (not rejected, not "wait"):
|
|
385
|
+
|
|
386
|
+
Generate slug from title using gsd-tools:
|
|
387
|
+
```bash
|
|
388
|
+
SLUG=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs generate-slug "${issue_title}" --raw)
|
|
389
|
+
SLUG="${SLUG:0:40}" # gsd-tools doesn't truncate; MGW enforces 40-char limit
|
|
390
|
+
```
|
|
391
|
+
Write to `.mgw/active/${ISSUE_NUMBER}-${slug}.json` using the schema from state.md.
|
|
392
|
+
|
|
393
|
+
Populate:
|
|
394
|
+
- issue: from $ISSUE_DATA
|
|
395
|
+
- triage: from analysis report
|
|
396
|
+
- triage.last_comment_count: from $COMMENT_COUNT (captured in fetch_issue step)
|
|
397
|
+
- triage.last_comment_at: from $LAST_COMMENT_AT (captured in fetch_issue step, null if no comments)
|
|
398
|
+
- triage.gate_result: from gate_result evaluation (status, blockers, warnings, missing_fields)
|
|
399
|
+
- gsd_route: confirmed or overridden route
|
|
400
|
+
- pipeline_stage: set based on gate outcome:
|
|
401
|
+
- Gates blocked + validity failure (and not overridden): `"needs-info"`
|
|
402
|
+
- Gates blocked + security failure (and not overridden): `"needs-security-review"`
|
|
403
|
+
- Gates blocked + user overrides: `"triaged"` (with override_log entry noting acknowledged gate failures)
|
|
404
|
+
- Gates passed: `"triaged"`
|
|
405
|
+
- All other fields: defaults (empty arrays, null)
|
|
406
|
+
|
|
407
|
+
Also add branch cross-ref:
|
|
408
|
+
```bash
|
|
409
|
+
BRANCH=$(git branch --show-current)
|
|
410
|
+
```
|
|
411
|
+
Add to linked_branches if not main/master.
|
|
412
|
+
</step>
|
|
413
|
+
|
|
414
|
+
<step name="offer_next">
|
|
415
|
+
**Offer next steps:**
|
|
416
|
+
|
|
417
|
+
If accepted/overridden (gates passed):
|
|
418
|
+
```
|
|
419
|
+
Issue #${ISSUE_NUMBER} triaged and tracked in .mgw/active/${filename}.
|
|
420
|
+
|
|
421
|
+
Next steps:
|
|
422
|
+
→ /mgw:run ${ISSUE_NUMBER} — Start autonomous pipeline
|
|
423
|
+
→ /mgw:update ${ISSUE_NUMBER} — Post triage comment to GitHub
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
If gates blocked and user chose "wait" (no state file written):
|
|
427
|
+
```
|
|
428
|
+
Issue #${ISSUE_NUMBER} is blocked pending more information.
|
|
429
|
+
A comment has been posted to GitHub explaining what's needed.
|
|
430
|
+
|
|
431
|
+
When the issue is updated:
|
|
432
|
+
→ /mgw:issue ${ISSUE_NUMBER} — Re-triage with updated context
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
If gates blocked and user overrode:
|
|
436
|
+
```
|
|
437
|
+
Issue #${ISSUE_NUMBER} triaged with gate override. Tracked in .mgw/active/${filename}.
|
|
438
|
+
|
|
439
|
+
Note: Gate failures acknowledged. Override logged in state.
|
|
440
|
+
|
|
441
|
+
Next steps:
|
|
442
|
+
→ /mgw:run ${ISSUE_NUMBER} — Start autonomous pipeline
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
If rejected:
|
|
446
|
+
```
|
|
447
|
+
Issue #${ISSUE_NUMBER} rejected. No state file created.
|
|
448
|
+
Consider closing or commenting on the issue with your reasoning.
|
|
449
|
+
```
|
|
450
|
+
</step>
|
|
451
|
+
|
|
452
|
+
</process>
|
|
453
|
+
|
|
454
|
+
<success_criteria>
|
|
455
|
+
- [ ] Issue fetched from GitHub via gh CLI
|
|
456
|
+
- [ ] Comment tracking snapshot captured (count + last timestamp)
|
|
457
|
+
- [ ] Self-assigned if not already
|
|
458
|
+
- [ ] Analysis agent spawned and returned structured report
|
|
459
|
+
- [ ] Scope, validity, security, conflicts all assessed
|
|
460
|
+
- [ ] GSD route recommended with reasoning
|
|
461
|
+
- [ ] Triage gates evaluated (validity, security, detail sufficiency)
|
|
462
|
+
- [ ] Gate result stored in state file
|
|
463
|
+
- [ ] Triage comment posted IMMEDIATELY to GitHub
|
|
464
|
+
- [ ] Blocked issues get appropriate mgw: label (mgw:needs-info or mgw:needs-security-review)
|
|
465
|
+
- [ ] Passed issues get mgw:triaged label
|
|
466
|
+
- [ ] User confirms, overrides, or rejects
|
|
467
|
+
- [ ] State file written to .mgw/active/ (if accepted) with comment tracking fields and gate_result
|
|
468
|
+
- [ ] Next steps offered
|
|
469
|
+
</success_criteria>
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mgw:issues
|
|
3
|
+
description: List and filter GitHub issues, pick one to triage
|
|
4
|
+
argument-hint: "[--label <label>] [--milestone <name>] [--assignee <user>] [--state open|closed|all]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Bash
|
|
7
|
+
- Read
|
|
8
|
+
- Write
|
|
9
|
+
- AskUserQuestion
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<objective>
|
|
13
|
+
Browse GitHub issues for the current repo. Presents a scannable table filtered by
|
|
14
|
+
assignment (defaults to @me), labels, milestone, or state. Pick an issue to route
|
|
15
|
+
into triage via /mgw:issue.
|
|
16
|
+
|
|
17
|
+
No side effects — read-only GitHub access. Safe to run anytime.
|
|
18
|
+
</objective>
|
|
19
|
+
|
|
20
|
+
<execution_context>
|
|
21
|
+
@~/.claude/commands/mgw/workflows/github.md
|
|
22
|
+
</execution_context>
|
|
23
|
+
|
|
24
|
+
<context>
|
|
25
|
+
$ARGUMENTS
|
|
26
|
+
|
|
27
|
+
Repo detected via: gh repo view --json nameWithOwner -q .nameWithOwner
|
|
28
|
+
</context>
|
|
29
|
+
|
|
30
|
+
<process>
|
|
31
|
+
|
|
32
|
+
<step name="parse_filters">
|
|
33
|
+
**Parse arguments into gh filters:**
|
|
34
|
+
|
|
35
|
+
Defaults if no arguments:
|
|
36
|
+
- `--assignee @me`
|
|
37
|
+
- `--state open`
|
|
38
|
+
- `--limit 25`
|
|
39
|
+
|
|
40
|
+
Override with explicit flags from $ARGUMENTS:
|
|
41
|
+
- `--label <label>` → `gh --label`
|
|
42
|
+
- `--milestone <name>` → `gh --milestone`
|
|
43
|
+
- `--assignee <user>` → `gh --assignee` (use "all" to skip filter)
|
|
44
|
+
- `--state <state>` → `gh --state`
|
|
45
|
+
</step>
|
|
46
|
+
|
|
47
|
+
<step name="fetch_issues">
|
|
48
|
+
**Fetch issues from GitHub:**
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
gh issue list --assignee @me --state open --limit 25 --json number,title,labels,createdAt,comments,assignees
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Adjust flags based on parsed filters.
|
|
55
|
+
|
|
56
|
+
If result is empty:
|
|
57
|
+
```
|
|
58
|
+
No issues found matching filters.
|
|
59
|
+
Try: /mgw:issues --assignee all --state open
|
|
60
|
+
```
|
|
61
|
+
</step>
|
|
62
|
+
|
|
63
|
+
<step name="display_table">
|
|
64
|
+
**Present issues as a scannable table:**
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
68
|
+
MGW ► ISSUES
|
|
69
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
70
|
+
|
|
71
|
+
| # | Title | Labels | Age | Comments |
|
|
72
|
+
|----|----------------------------|--------------|------|----------|
|
|
73
|
+
| 42 | Fix auth bug in login flow | bug, auth | 3d | 2 |
|
|
74
|
+
| 38 | Add caching layer | enhancement | 1w | 5 |
|
|
75
|
+
| ... |
|
|
76
|
+
|
|
77
|
+
Enter issue number to triage, or 'q' to quit.
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Calculate age as human-readable relative time from createdAt.
|
|
81
|
+
Truncate title to 30 chars if needed.
|
|
82
|
+
Format labels as comma-separated.
|
|
83
|
+
</step>
|
|
84
|
+
|
|
85
|
+
<step name="pick_issue">
|
|
86
|
+
**User selects an issue:**
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
AskUserQuestion(
|
|
90
|
+
header: "Select Issue",
|
|
91
|
+
question: "Which issue number do you want to triage?",
|
|
92
|
+
followUp: "Enter a number from the table above, or 'q' to quit"
|
|
93
|
+
)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
If valid number → suggest: "Run /mgw:issue <number> to triage this issue."
|
|
97
|
+
If 'q' → exit cleanly.
|
|
98
|
+
If invalid → re-prompt.
|
|
99
|
+
</step>
|
|
100
|
+
|
|
101
|
+
</process>
|
|
102
|
+
|
|
103
|
+
<success_criteria>
|
|
104
|
+
- [ ] Issues fetched from current repo via gh CLI
|
|
105
|
+
- [ ] Filters applied correctly (defaults to @me + open)
|
|
106
|
+
- [ ] Table displayed with number, title, labels, age, comments
|
|
107
|
+
- [ ] User can pick an issue number
|
|
108
|
+
- [ ] Routes to /mgw:issue <number>
|
|
109
|
+
</success_criteria>
|
package/commands/link.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mgw:link
|
|
3
|
+
description: Cross-reference issues, PRs, and branches to each other
|
|
4
|
+
argument-hint: "<ref-a> <ref-b> [--quiet]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Bash
|
|
7
|
+
- Read
|
|
8
|
+
- Write
|
|
9
|
+
- Edit
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<objective>
|
|
13
|
+
Track relationships between issues, PRs, and branches. Writes bidirectional links
|
|
14
|
+
to .mgw/cross-refs.json. Optionally posts comments on linked GitHub issues/PRs.
|
|
15
|
+
|
|
16
|
+
Future mgw:update and mgw:pr calls automatically include these references.
|
|
17
|
+
|
|
18
|
+
Reference formats:
|
|
19
|
+
- Issue: 42 or #42 or issue:42
|
|
20
|
+
- PR: pr:15 or pr:#15
|
|
21
|
+
- Branch: branch:fix/auth-42
|
|
22
|
+
- GitHub Milestone: milestone:N
|
|
23
|
+
- GSD Milestone: gsd-milestone:name
|
|
24
|
+
</objective>
|
|
25
|
+
|
|
26
|
+
<execution_context>
|
|
27
|
+
@~/.claude/commands/mgw/workflows/state.md
|
|
28
|
+
@~/.claude/commands/mgw/workflows/github.md
|
|
29
|
+
</execution_context>
|
|
30
|
+
|
|
31
|
+
<context>
|
|
32
|
+
$ARGUMENTS — expects: <ref-a> <ref-b> [--quiet]
|
|
33
|
+
</context>
|
|
34
|
+
|
|
35
|
+
<process>
|
|
36
|
+
|
|
37
|
+
<step name="parse_refs">
|
|
38
|
+
**Parse two references from arguments:**
|
|
39
|
+
|
|
40
|
+
Normalize reference formats:
|
|
41
|
+
- Bare number or #N → "issue:N"
|
|
42
|
+
- pr:N or pr:#N → "pr:N"
|
|
43
|
+
- branch:name → "branch:name"
|
|
44
|
+
- milestone:N → "milestone:N" (GitHub milestone by number)
|
|
45
|
+
- gsd-milestone:name → "gsd-milestone:name" (GSD milestone by id/name)
|
|
46
|
+
|
|
47
|
+
If fewer than 2 refs provided:
|
|
48
|
+
```
|
|
49
|
+
AskUserQuestion(
|
|
50
|
+
header: "Link References",
|
|
51
|
+
question: "Provide two references to link (e.g., 42 #43, or 42 branch:fix/auth)",
|
|
52
|
+
followUp: null
|
|
53
|
+
)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Check for `--quiet` flag → skip GitHub comment posting if present.
|
|
57
|
+
</step>
|
|
58
|
+
|
|
59
|
+
<step name="init_state">
|
|
60
|
+
**Initialize .mgw/ if needed:**
|
|
61
|
+
|
|
62
|
+
Follow initialization from state.md workflow.
|
|
63
|
+
</step>
|
|
64
|
+
|
|
65
|
+
<step name="write_crossref">
|
|
66
|
+
**Write bidirectional link:**
|
|
67
|
+
|
|
68
|
+
Read `.mgw/cross-refs.json`.
|
|
69
|
+
|
|
70
|
+
Determine link type:
|
|
71
|
+
- issue + issue → "related"
|
|
72
|
+
- issue + pr → "implements"
|
|
73
|
+
- issue + branch → "tracks"
|
|
74
|
+
- pr + branch → "tracks"
|
|
75
|
+
- milestone + gsd-milestone → "maps-to" (maps GitHub milestone to GSD milestone)
|
|
76
|
+
|
|
77
|
+
Check for duplicate (same a+b pair exists). If duplicate, report and skip.
|
|
78
|
+
|
|
79
|
+
Append new link:
|
|
80
|
+
```json
|
|
81
|
+
{ "a": "${ref_a}", "b": "${ref_b}", "type": "${link_type}", "created": "$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs current-timestamp --raw)" }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Write back to `.mgw/cross-refs.json`.
|
|
85
|
+
|
|
86
|
+
Also update any matching .mgw/active/ state files:
|
|
87
|
+
- If ref_a is an issue with a state file → add ref_b to appropriate linked_* array
|
|
88
|
+
- If ref_b is an issue with a state file → add ref_a to appropriate linked_* array
|
|
89
|
+
</step>
|
|
90
|
+
|
|
91
|
+
<step name="post_comments">
|
|
92
|
+
**Post GitHub comments (unless --quiet):**
|
|
93
|
+
|
|
94
|
+
For each reference that is an issue or PR:
|
|
95
|
+
```bash
|
|
96
|
+
gh issue comment ${NUMBER} --body "Linked to ${other_ref} (${link_type}) via MGW"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Or for PRs:
|
|
100
|
+
```bash
|
|
101
|
+
gh pr comment ${NUMBER} --body "Linked to ${other_ref} (${link_type}) via MGW"
|
|
102
|
+
```
|
|
103
|
+
</step>
|
|
104
|
+
|
|
105
|
+
<step name="report">
|
|
106
|
+
**Report:**
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
Linked ${ref_a} ↔ ${ref_b} (${link_type})
|
|
110
|
+
${comment_status}
|
|
111
|
+
```
|
|
112
|
+
</step>
|
|
113
|
+
|
|
114
|
+
</process>
|
|
115
|
+
|
|
116
|
+
<success_criteria>
|
|
117
|
+
- [ ] Two references parsed and normalized
|
|
118
|
+
- [ ] Duplicate detection works
|
|
119
|
+
- [ ] Bidirectional link written to cross-refs.json
|
|
120
|
+
- [ ] Active state files updated if matching
|
|
121
|
+
- [ ] GitHub comments posted (unless --quiet)
|
|
122
|
+
</success_criteria>
|