@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.
@@ -0,0 +1,416 @@
1
+ ---
2
+ name: mgw:ask
3
+ description: Route a question/observation — classify as in-scope, adjacent, separate, duplicate, or out-of-scope
4
+ argument-hint: "<question>"
5
+ allowed-tools:
6
+ - Bash
7
+ - Read
8
+ - Task
9
+ - AskUserQuestion
10
+ ---
11
+
12
+ <objective>
13
+ During milestone execution, observations arise that need classification: is this
14
+ in-scope for the current issue, adjacent to a different issue, a separate concern,
15
+ a duplicate, or out-of-scope entirely?
16
+
17
+ /mgw:ask spawns a general-purpose agent with full project context (milestone, all
18
+ issues, active state, recent git diff) that classifies the question and recommends
19
+ an action. Read-only for the orchestrator — the agent reads state and code, MGW
20
+ presents the structured result.
21
+ </objective>
22
+
23
+ <execution_context>
24
+ @~/.claude/commands/mgw/workflows/state.md
25
+ @~/.claude/commands/mgw/workflows/github.md
26
+ @~/.claude/commands/mgw/workflows/gsd.md
27
+ @~/.claude/commands/mgw/workflows/validation.md
28
+ </execution_context>
29
+
30
+ <context>
31
+ Question text: $ARGUMENTS
32
+
33
+ Active issues context: .mgw/active/ (current work state)
34
+ Project context: .mgw/project.json (milestone + all issues)
35
+ Capability context: commands/*.md front matter (name + description per command)
36
+ Live state: open PRs via gh pr list, milestones via gh api
37
+ </context>
38
+
39
+ <process>
40
+
41
+ <step name="validate_input">
42
+ **Validate question text provided:**
43
+
44
+ Parse $ARGUMENTS for the question text. If missing or empty:
45
+ ```
46
+ AskUserQuestion(
47
+ header: "Question Required",
48
+ question: "What question or observation do you want to classify?",
49
+ followUp: "Enter a question or observation (e.g., 'The slug generation doesn't handle unicode characters')"
50
+ )
51
+ ```
52
+ Store as $QUESTION.
53
+ </step>
54
+
55
+ <step name="load_project_context">
56
+ **Load project.json for milestone and issue context:**
57
+
58
+ ```bash
59
+ REPO_ROOT=$(git rev-parse --show-toplevel)
60
+ MGW_DIR="${REPO_ROOT}/.mgw"
61
+
62
+ # Load project state
63
+ PROJECT_JSON=""
64
+ MILESTONE_CONTEXT=""
65
+ ALL_ISSUES_CONTEXT=""
66
+
67
+ if [ -f "${MGW_DIR}/project.json" ]; then
68
+ PROJECT_JSON=$(cat "${MGW_DIR}/project.json")
69
+
70
+ # Extract current milestone info
71
+ MILESTONE_CONTEXT=$(echo "$PROJECT_JSON" | python3 -c "
72
+ import json, sys
73
+ p = json.load(sys.stdin)
74
+ idx = p['current_milestone'] - 1
75
+ if idx < len(p['milestones']):
76
+ m = p['milestones'][idx]
77
+ print(f\"Milestone: {m['name']}\")
78
+ if m.get('description'):
79
+ print(f\"Description: {m['description']}\")
80
+ else:
81
+ print('No active milestone')
82
+ " 2>/dev/null || echo "No project initialized")
83
+
84
+ # Extract all issues in current milestone with titles, bodies, scopes, labels
85
+ ALL_ISSUES_CONTEXT=$(echo "$PROJECT_JSON" | python3 -c "
86
+ import json, sys
87
+ p = json.load(sys.stdin)
88
+ idx = p['current_milestone'] - 1
89
+ if idx >= len(p['milestones']):
90
+ print('No issues found')
91
+ sys.exit(0)
92
+ m = p['milestones'][idx]
93
+ for issue in m.get('issues', []):
94
+ num = issue.get('github_number', '?')
95
+ title = issue.get('title', 'untitled')
96
+ stage = issue.get('pipeline_stage', 'new')
97
+ labels = ', '.join(issue.get('labels', []))
98
+ phase = issue.get('phase_name', '')
99
+ scope = issue.get('scope', '')
100
+ print(f'#{num} [{stage}] {title}')
101
+ if phase:
102
+ print(f' Phase: {phase}')
103
+ if labels:
104
+ print(f' Labels: {labels}')
105
+ if scope:
106
+ print(f' Scope: {scope}')
107
+ print()
108
+ " 2>/dev/null || echo "")
109
+ else
110
+ MILESTONE_CONTEXT="No project initialized"
111
+ ALL_ISSUES_CONTEXT=""
112
+ fi
113
+ ```
114
+ </step>
115
+
116
+ <step name="load_capability_context">
117
+ **Load MGW command surface, open PRs, and live milestones:**
118
+
119
+ ```bash
120
+ # Extract name + description from each command's front matter
121
+ COMMAND_SURFACE=""
122
+ COMMANDS_DIR="${REPO_ROOT}/commands"
123
+ for f in "${COMMANDS_DIR}"/*.md; do
124
+ CMD_NAME=$(grep -m1 "^name:" "$f" 2>/dev/null | sed 's/^name:[[:space:]]*//')
125
+ CMD_DESC=$(grep -m1 "^description:" "$f" 2>/dev/null | sed 's/^description:[[:space:]]*//')
126
+ if [ -n "$CMD_NAME" ]; then
127
+ COMMAND_SURFACE="${COMMAND_SURFACE}${CMD_NAME}: ${CMD_DESC}\n"
128
+ fi
129
+ done
130
+
131
+ # Fetch open PRs
132
+ PR_CONTEXT=$(gh pr list --state open --json number,title,headRefName \
133
+ --jq '.[] | "#\(.number) [\(.headRefName)] \(.title)"' 2>/dev/null || echo "No open PRs")
134
+
135
+ # Fetch live milestones from GitHub API
136
+ REPO_SLUG=$(gh repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null || echo "")
137
+ MILESTONE_LIST=""
138
+ if [ -n "$REPO_SLUG" ]; then
139
+ MILESTONE_LIST=$(gh api "repos/${REPO_SLUG}/milestones" \
140
+ --jq '.[] | "[\(.state)] \(.title)"' 2>/dev/null || echo "")
141
+ fi
142
+ if [ -z "$MILESTONE_LIST" ]; then
143
+ MILESTONE_LIST="No milestones found (or GitHub API unavailable)"
144
+ fi
145
+ ```
146
+ </step>
147
+
148
+ <step name="load_active_state">
149
+ **Load active issue state from .mgw/active/:**
150
+
151
+ ```bash
152
+ ACTIVE_STATE=""
153
+ ACTIVE_ISSUE_NUMBER=""
154
+
155
+ ACTIVE_FILES=$(ls "${MGW_DIR}/active/"*.json 2>/dev/null)
156
+ if [ -n "$ACTIVE_FILES" ]; then
157
+ for f in ${ACTIVE_FILES}; do
158
+ ISSUE_DATA=$(cat "$f")
159
+ ISSUE_NUM=$(echo "$ISSUE_DATA" | python3 -c "import json,sys; print(json.load(sys.stdin).get('issue',{}).get('number','?'))")
160
+ ISSUE_TITLE=$(echo "$ISSUE_DATA" | python3 -c "import json,sys; print(json.load(sys.stdin).get('issue',{}).get('title','untitled'))")
161
+ PIPELINE_STAGE=$(echo "$ISSUE_DATA" | python3 -c "import json,sys; print(json.load(sys.stdin).get('pipeline_stage','unknown'))")
162
+ ACTIVE_STATE="${ACTIVE_STATE}#${ISSUE_NUM} [${PIPELINE_STAGE}] ${ISSUE_TITLE}\n"
163
+ # Track the most recently active issue (last in list)
164
+ ACTIVE_ISSUE_NUMBER="$ISSUE_NUM"
165
+ done
166
+ else
167
+ ACTIVE_STATE="No active issues"
168
+ fi
169
+ ```
170
+ </step>
171
+
172
+ <step name="gather_git_diff">
173
+ **Gather recent git diff for change context:**
174
+
175
+ ```bash
176
+ # Get recent changes (staged + unstaged, limited to keep prompt reasonable)
177
+ RECENT_DIFF=$(git diff HEAD --stat 2>/dev/null | head -30 || echo "No changes")
178
+ CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
179
+ ```
180
+ </step>
181
+
182
+ <step name="fetch_issue_details">
183
+ **Fetch full issue bodies from GitHub for matching context:**
184
+
185
+ If project.json has issues, fetch their bodies for the agent to compare against:
186
+
187
+ ```bash
188
+ ISSUE_BODIES=""
189
+ if [ -n "$PROJECT_JSON" ]; then
190
+ ISSUE_NUMBERS=$(echo "$PROJECT_JSON" | python3 -c "
191
+ import json, sys
192
+ p = json.load(sys.stdin)
193
+ idx = p['current_milestone'] - 1
194
+ if idx < len(p['milestones']):
195
+ m = p['milestones'][idx]
196
+ for issue in m.get('issues', []):
197
+ print(issue.get('github_number', ''))
198
+ " 2>/dev/null)
199
+
200
+ for NUM in $ISSUE_NUMBERS; do
201
+ if [ -n "$NUM" ]; then
202
+ BODY=$(gh issue view "$NUM" --json number,title,body -q '"\(.number)|\(.title)|\(.body)"' 2>/dev/null || echo "")
203
+ if [ -n "$BODY" ]; then
204
+ ISSUE_BODIES="${ISSUE_BODIES}${BODY}\n---\n"
205
+ fi
206
+ fi
207
+ done
208
+ fi
209
+ ```
210
+ </step>
211
+
212
+ <step name="spawn_classification_agent">
213
+ **Spawn general-purpose agent for question classification:**
214
+
215
+ ```
216
+ Task(
217
+ prompt="
218
+ <files_to_read>
219
+ - ./CLAUDE.md (Project instructions — if exists, follow all guidelines)
220
+ - .agents/skills/ (Project skills — if dir exists, list skills, read SKILL.md for each, follow relevant rules)
221
+ </files_to_read>
222
+
223
+ You are a question classification agent for the MGW pipeline. Your job is to
224
+ classify a question or observation against the current project context and
225
+ recommend an action.
226
+
227
+ <question>
228
+ ${QUESTION}
229
+ </question>
230
+
231
+ <current_milestone>
232
+ ${MILESTONE_CONTEXT}
233
+ </current_milestone>
234
+
235
+ <milestone_issues>
236
+ ${ALL_ISSUES_CONTEXT}
237
+ </milestone_issues>
238
+
239
+ <issue_bodies>
240
+ ${ISSUE_BODIES}
241
+ </issue_bodies>
242
+
243
+ <active_work>
244
+ Current branch: ${CURRENT_BRANCH}
245
+ Active issues in .mgw/:
246
+ ${ACTIVE_STATE}
247
+ </active_work>
248
+
249
+ <recent_changes>
250
+ ${RECENT_DIFF}
251
+ </recent_changes>
252
+
253
+ <mgw_capabilities>
254
+ ## MGW Command Surface
255
+ ${COMMAND_SURFACE}
256
+
257
+ ## Open Pull Requests
258
+ ${PR_CONTEXT}
259
+
260
+ ## GitHub Milestones
261
+ ${MILESTONE_LIST}
262
+ </mgw_capabilities>
263
+
264
+ <classification_rules>
265
+
266
+ Classify the question into exactly ONE of these categories:
267
+
268
+ | Category | Criteria | Action |
269
+ |----------|----------|--------|
270
+ | In-scope | Directly relates to the current active issue being worked on | Include in current work — no new issue needed |
271
+ | Adjacent | Relates to a DIFFERENT issue in the same milestone | Note it on that issue — suggest posting a comment |
272
+ | Separate | Doesn't match any open issue in the milestone | Suggest filing a new issue with a title |
273
+ | Duplicate | Matches an existing issue (same root cause or fix) | Point to the existing issue |
274
+ | Out-of-scope | Beyond the current milestone entirely | Note for future planning |
275
+
276
+ Decision process:
277
+ 1. Read the question carefully
278
+ 2. Compare against each issue title, body, and scope in the milestone
279
+ 3. Check if it relates to current active work (branch, diff, active state)
280
+ 4. Look for keyword/concept overlap with existing issues
281
+ 5. If no match, determine if it fits the milestone's theme or is out-of-scope
282
+
283
+ </classification_rules>
284
+
285
+ <output_format>
286
+ Return a structured classification report:
287
+
288
+ ## Classification: ${CATEGORY}
289
+
290
+ ### Analysis
291
+ - What the question is about (1-2 sentences)
292
+ - Why this classification was chosen (1-2 sentences)
293
+
294
+ ### Related Issue
295
+ - Issue number and title (if adjacent or duplicate)
296
+ - Or 'N/A — current work' (if in-scope)
297
+ - Or 'No matching issue' (if separate or out-of-scope)
298
+
299
+ ### Recommendation
300
+ - Specific actionable next step
301
+ - If 'separate': suggest an issue title and brief body
302
+ - If 'adjacent': suggest a comment to post on the related issue
303
+ - If 'in-scope': note what to include in current work
304
+ - If 'duplicate': point to the matching issue
305
+ - If 'out-of-scope': note for future milestone planning
306
+ </output_format>
307
+ ",
308
+ subagent_type="general-purpose",
309
+ description="Classify question: ${QUESTION}"
310
+ )
311
+ ```
312
+ </step>
313
+
314
+ <step name="present_result">
315
+ **Present the classification result to the user:**
316
+
317
+ Display the agent's report, then present the MGW action banner:
318
+
319
+ ```
320
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
321
+ MGW ► QUESTION ROUTING
322
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
323
+
324
+ ${classification_report_from_agent}
325
+
326
+ ───────────────────────────────────────────────────────
327
+ ```
328
+ </step>
329
+
330
+ <step name="offer_actions">
331
+ **Offer follow-up actions based on classification:**
332
+
333
+ **If "Separate":**
334
+ ```
335
+ AskUserQuestion(
336
+ header: "File New Issue?",
337
+ question: "Create a new issue from this observation?",
338
+ options: [
339
+ { label: "Yes", description: "File the suggested issue via /mgw:issue" },
340
+ { label: "No", description: "Note it and continue current work" }
341
+ ]
342
+ )
343
+ ```
344
+
345
+ If user says "Yes":
346
+ ```
347
+ Suggested issue ready. To file it:
348
+
349
+ gh issue create --title "${suggested_title}" --body "${suggested_body}"
350
+
351
+ Or use /mgw:project to add it to a future milestone.
352
+ ```
353
+
354
+ **If "Adjacent":**
355
+ ```
356
+ AskUserQuestion(
357
+ header: "Post Comment?",
358
+ question: "Post a note on the related issue #${related_number}?",
359
+ options: [
360
+ { label: "Yes", description: "Post observation as a comment on #${related_number}" },
361
+ { label: "No", description: "Note it and continue current work" }
362
+ ]
363
+ )
364
+ ```
365
+
366
+ If user says "Yes":
367
+ ```bash
368
+ gh issue comment ${related_number} --body "> **MGW** · \`observation\` · $(node ~/.claude/get-shit-done/bin/gsd-tools.cjs current-timestamp --raw)
369
+
370
+ Observation noted during work on #${ACTIVE_ISSUE_NUMBER}:
371
+
372
+ ${QUESTION}"
373
+ ```
374
+
375
+ Report: "Comment posted on #${related_number}."
376
+
377
+ **If "In-scope":**
378
+ ```
379
+ This relates to your current work on #${ACTIVE_ISSUE_NUMBER}.
380
+ No action needed — include it in your current implementation.
381
+ ```
382
+
383
+ **If "Duplicate":**
384
+ ```
385
+ This appears to duplicate #${duplicate_number} — ${duplicate_title}.
386
+ No new issue needed. Check that issue for existing progress.
387
+ ```
388
+
389
+ **If "Out-of-scope":**
390
+ ```
391
+ This is beyond the current milestone scope.
392
+ Consider adding it to a future milestone or filing it for backlog:
393
+
394
+ gh issue create --title "${suggested_title}" --label "backlog"
395
+ ```
396
+ </step>
397
+
398
+ </process>
399
+
400
+ <success_criteria>
401
+ - [ ] Question text parsed from $ARGUMENTS (or prompted)
402
+ - [ ] project.json loaded for milestone + issue context
403
+ - [ ] .mgw/active/ state loaded for current work context
404
+ - [ ] Recent git diff gathered for change context
405
+ - [ ] Issue bodies fetched from GitHub for comparison
406
+ - [ ] Classification agent spawned with full context
407
+ - [ ] Classification returned: in-scope, adjacent, separate, duplicate, or out-of-scope
408
+ - [ ] Related issue identified (if adjacent or duplicate)
409
+ - [ ] Actionable recommendation provided
410
+ - [ ] Follow-up action offered (file issue, post comment, etc.)
411
+ - [ ] Delegation boundary respected: agent reads code/state, MGW presents results
412
+ - [ ] Command surface index built from commands/*.md front matter
413
+ - [ ] Open PRs fetched and injected into agent context
414
+ - [ ] Live GitHub milestones fetched as fallback when project.json is absent
415
+ </success_criteria>
416
+ </output>