@snipcodeit/mgw 0.2.0 → 0.2.2

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.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: mgw:milestone
3
3
  description: Execute a milestone's issues in dependency order — auto-sync, rate-limit guard, per-issue checkpoint
4
- argument-hint: "[milestone-number] [--interactive] [--dry-run]"
4
+ HB|argument-hint: "[milestone-number] [--interactive] [--dry-run] [--auto-review]"
5
5
  allowed-tools:
6
6
  - Bash
7
7
  - Read
@@ -23,7 +23,8 @@ dependents, continue unblocked), resume detection, milestone close + draft relea
23
23
  completion, and auto-advance to next milestone.
24
24
 
25
25
  The `--interactive` flag pauses between issues for user confirmation.
26
- The `--dry-run` flag shows the execution plan without running anything.
26
+ SR|The `--dry-run` flag shows the execution plan without running anything.
27
+ NM|The `--auto-review` flag runs deep PR review after each issue completes.
27
28
  </objective>
28
29
 
29
30
  <execution_context>
@@ -46,12 +47,14 @@ Flags: --interactive, --dry-run
46
47
  ```bash
47
48
  MILESTONE_NUM=""
48
49
  INTERACTIVE=false
49
- DRY_RUN=false
50
+ WP|DRY_RUN=false
51
+ NM|AUTO_REVIEW=false
50
52
 
51
53
  for ARG in $ARGUMENTS; do
52
54
  case "$ARG" in
53
55
  --interactive) INTERACTIVE=true ;;
54
- --dry-run) DRY_RUN=true ;;
56
+ TN| --dry-run) DRY_RUN=true ;;
57
+ --auto-review) AUTO_REVIEW=true ;;
55
58
  [0-9]*) MILESTONE_NUM="$ARG" ;;
56
59
  esac
57
60
  done
@@ -678,7 +681,37 @@ COMMENTEOF
678
681
  )
679
682
 
680
683
  gh issue comment ${ISSUE_NUMBER} --body "$PR_READY_BODY" 2>/dev/null || true
681
- echo " ✓ #${ISSUE_NUMBER} — PR #${PR_NUMBER} created"
684
+ PR| echo " ✓ #${ISSUE_NUMBER} — PR #${PR_NUMBER} created"
685
+
686
+
687
+ BP| # ── PR REVIEW CHECKPOINT (MLST-07) ──
688
+ RX| # Run PR review before allowing milestone to continue to next issue
689
+
690
+ RX| if [ "$AUTO_REVIEW" = true ]; then
691
+ RX| # Auto-review mode: run review automatically
692
+ RX| echo "Running auto PR review for #${PR_NUMBER}..."
693
+ RX| # NOTE: In full implementation, this would spawn the review agent
694
+ RX| # For now, prompt the user
695
+ RX| AskUserQuestion(
696
+ RX| header: "PR Review",
697
+ RX| question: "Run deep PR review for #${PR_NUMBER}?",
698
+ RX| options: [
699
+ RX| { label: "Review", description: "Run /mgw:review ${PR_NUMBER} --pr" },
700
+ RX| { label: "Skip", description: "Continue without review" }
701
+ RX| ]
702
+ RX| )
703
+ RX| else
704
+ RX| AskUserQuestion(
705
+ RX| header: "PR Review Checkpoint",
706
+ RX| question: "Run deep PR review for #${PR_NUMBER} before continuing to next issue?",
707
+ RX| options: [
708
+ RX| { label: "Review now", description: "Run /mgw:review ${PR_NUMBER} --pr" },
709
+ RX| { label: "Continue", description: "Skip review, proceed to next issue" }
710
+ RX| ]
711
+ RX| )
712
+ RX| fi
713
+
714
+ RX| # Continue to next issue
682
715
 
683
716
  else
684
717
  # Failure — read failure_class from active issue state, then post failure comment
@@ -1,23 +1,35 @@
1
1
  ---
2
2
  name: mgw:review
3
- description: Review and classify new comments on a GitHub issue since last triage
4
- argument-hint: "<issue-number>"
3
+ description: Review GitHub comments on issues OR perform deep PR analysis
4
+ argument-hint: "<issue-number | pr-number | pr-url> [--pr]"
5
5
  allowed-tools:
6
6
  - Bash
7
7
  - Read
8
8
  - Write
9
9
  - Edit
10
+ - Glob
11
+ - Grep
10
12
  - Task
11
13
  - AskUserQuestion
12
14
  ---
13
15
 
14
16
  <objective>
15
- Standalone comment review for a triaged issue. Fetches new comments posted since
16
- triage, classifies them (material/informational/blocking), and updates the state
17
- file accordingly.
17
+ Two-mode review command:
18
18
 
19
- Use this when you want to check for stakeholder feedback before running the pipeline,
20
- or to review comments on a blocked issue before unblocking it.
19
+ **Mode 1: Issue Comment Review (default)**
20
+ Review and classify new comments on a GitHub issue since last triage. Fetches new comments,
21
+ classifies them (material/informational/blocking/resolution), and updates state.
22
+
23
+ Use this when checking for stakeholder feedback before running the pipeline, or reviewing
24
+ comments on a blocked issue.
25
+
26
+ **Mode 2: PR Deep Review (with --pr flag)**
27
+ Comprehensive PR review that mimics a senior engineer's code review process. Problem-solving
28
+ orchestration with high autonomy to analyze, question assumptions, and provide architectural
29
+ guidance across five dimensions.
30
+
31
+ This is intentionally different from execution orchestration — the reviewer has space to think
32
+ deeply rather than produce code.
21
33
  </objective>
22
34
 
23
35
  <execution_context>
@@ -28,82 +40,149 @@ or to review comments on a blocked issue before unblocking it.
28
40
  </execution_context>
29
41
 
30
42
  <context>
31
- Issue number: $ARGUMENTS
32
-
33
- State: .mgw/active/ (must exist — issue must be triaged first)
43
+ Reference: $ARGUMENTS (issue number, PR number, or PR URL)
44
+ Flags: --pr forces PR deep review mode
34
45
  </context>
35
46
 
36
47
  <process>
37
48
 
38
- <step name="validate_and_load">
39
- **Validate input and load state:**
49
+ <step name="detect_mode">
50
+ **Detect review mode:**
40
51
 
41
52
  ```bash
42
53
  REPO_ROOT=$(git rev-parse --show-toplevel)
43
- ```
44
54
 
45
- Parse $ARGUMENTS for issue number. If missing:
46
- ```
47
- AskUserQuestion(
48
- header: "Issue Number Required",
49
- question: "Which issue number do you want to review comments for?",
50
- followUp: "Enter the GitHub issue number (e.g., 42)"
51
- )
52
- ```
55
+ # Parse arguments
56
+ REFERENCE="$ARGUMENTS"
57
+ PR_MODE=false
53
58
 
54
- Load state file: `${REPO_ROOT}/.mgw/active/${ISSUE_NUMBER}-*.json`
59
+ # Check for --pr flag
60
+ if [[ "$REFERENCE" =~ --pr[[:space:]]|$ ]]; then
61
+ PR_MODE=true
62
+ REFERENCE=$(echo "$REFERENCE" | sed 's/--pr//g' | xargs)
63
+ fi
55
64
 
56
- If no state file exists:
65
+ # Determine if PR or issue based on format
66
+ if [[ "$REFERENCE" =~ ^https?://github\.com/[^/]+/[^/]+/pull/ ]]; then
67
+ # URL - determine if issue or PR
68
+ if [[ "$REFERENCE" =~ /pull/ ]]; then
69
+ PR_MODE=true
70
+ fi
71
+ PR_REF="$REFERENCE"
72
+ elif [[ "$REFERENCE" =~ ^https?://github\.com/[^/]+/[^/]+/issues/ ]]; then
73
+ PR_MODE=false
74
+ ISSUE_REF="$REFERENCE"
75
+ elif [[ "$REFERENCE" =~ ^[0-9]+$ ]]; then
76
+ # Number - check if it's a PR or issue by testing
77
+ # Default to issue comment review (safer default)
78
+ PR_MODE=false
79
+ NUMBER="$REFERENCE"
80
+ else
81
+ # Default: issue comment review
82
+ PR_MODE=false
83
+ NUMBER="$REFERENCE"
84
+ fi
85
+
86
+ # Export for later steps
87
+ export PR_MODE
57
88
  ```
58
- Issue #${ISSUE_NUMBER} hasn't been triaged yet.
59
- Run /mgw:issue ${ISSUE_NUMBER} first, then review comments.
89
+ </step>
90
+
91
+ <step name="route_to_mode">
92
+ **Route to appropriate review mode:**
93
+
94
+ If PR_MODE=true → Jump to "pr_review" section below
95
+ If PR_MODE=false → Continue to "issue_comments" section
96
+
97
+ </step>
98
+
99
+ # ═══════════════════════════════════════════════════════════════════════════════
100
+ # MODE 1: ISSUE COMMENT REVIEW (original functionality, optimized)
101
+ # ═══════════════════════════════════════════════════════════════════════════════
102
+
103
+ <step name="issue_validate">
104
+ **Validate issue and load state:**
105
+
106
+ ```bash
107
+ # Parse issue number
108
+ if [ -n "$NUMBER" ]; then
109
+ ISSUE_NUMBER="$NUMBER"
110
+ elif [ -n "$ISSUE_REF" ]; then
111
+ ISSUE_NUMBER=$(echo "$ISSUE_REF" | grep -oE '[0-9]+$' | head -1)
112
+ fi
113
+
114
+ if [ -z "$ISSUE_NUMBER" ]; then
115
+ AskUserQuestion(
116
+ header: "Issue Number Required",
117
+ question: "Which issue number do you want to review comments for?",
118
+ followUp: "Enter the GitHub issue number (e.g., 42)"
119
+ )
120
+ ISSUE_NUMBER="$ANSWER"
121
+ fi
122
+
123
+ # Verify issue exists
124
+ gh issue view "$ISSUE_NUMBER" >/dev/null 2>&1 || {
125
+ echo "Error: Issue #${ISSUE_NUMBER} not found."
126
+ exit 1
127
+ }
128
+
129
+ # Check if issue is triaged (state file exists)
130
+ if [ ! -f "${REPO_ROOT}/.mgw/active/${ISSUE_NUMBER}-*.json" ]; then
131
+ echo "Issue #${ISSUE_NUMBER} hasn't been triaged yet."
132
+ echo "Run /mgw:issue ${ISSUE_NUMBER} first, then review comments."
133
+ # Still allow review but warn
134
+ fi
60
135
  ```
61
136
  </step>
62
137
 
63
- <step name="fetch_comments">
64
- **Fetch current comment state from GitHub:**
138
+ <step name="issue_fetch_comments">
139
+ **Fetch current comment state:**
65
140
 
66
141
  ```bash
67
142
  CURRENT_COMMENTS=$(gh issue view $ISSUE_NUMBER --json comments --jq '.comments | length' 2>/dev/null || echo "0")
68
- STORED_COMMENTS="${triage.last_comment_count}"
143
+ STORED_COMMENTS=0
69
144
 
70
- if [ -z "$STORED_COMMENTS" ] || [ "$STORED_COMMENTS" = "null" ]; then
71
- STORED_COMMENTS=0
145
+ # Try to get stored count from state file
146
+ if [ -f "${REPO_ROOT}/.mgw/active/${ISSUE_NUMBER}-"*".json" ]; then
147
+ STATE_FILE=$(ls "${REPO_ROOT}/.mgw/active/${ISSUE_NUMBER}-"*".json" | head -1)
148
+ STORED_COMMENTS=$(jq -r '.triage.last_comment_count // 0' "$STATE_FILE" 2>/dev/null || echo "0")
72
149
  fi
73
150
 
74
151
  NEW_COUNT=$(($CURRENT_COMMENTS - $STORED_COMMENTS))
75
- ```
76
152
 
77
- If no new comments (`NEW_COUNT <= 0`):
78
- ```
79
- No new comments on #${ISSUE_NUMBER} since triage (${STORED_COMMENTS} comments at triage, ${CURRENT_COMMENTS} now).
80
- ```
81
- Stop.
153
+ if [ "$NEW_COUNT" -le 0 ]; then
154
+ echo "No new comments on #${ISSUE_NUMBER} since triage (${STORED_COMMENTS} stored, ${CURRENT_COMMENTS} now)."
155
+ echo "Done."
156
+ exit 0
157
+ fi
82
158
 
83
- If new comments exist, fetch them:
84
- ```bash
159
+ # Fetch new comments
85
160
  NEW_COMMENTS=$(gh issue view $ISSUE_NUMBER --json comments \
86
161
  --jq "[.comments[-${NEW_COUNT}:]] | .[] | {author: .author.login, body: .body, createdAt: .createdAt}" 2>/dev/null)
162
+
163
+ # Get issue context for classification
164
+ ISSUE_TITLE=$(gh issue view $ISSUE_NUMBER --json title -q '.title')
165
+ PIPELINE_STAGE=$(jq -r '.pipeline_stage // "new"' "$STATE_FILE" 2>/dev/null || echo "new")
166
+ GSD_ROUTE=$(jq -r '.gsd_route // "unknown"' "$STATE_FILE" 2>/dev/null || echo "unknown")
87
167
  ```
88
168
  </step>
89
169
 
90
- <step name="classify_comments">
91
- **Spawn classification agent:**
170
+ <step name="issue_classify">
171
+ **Spawn classification agent (lightweight):**
92
172
 
93
173
  ```
94
174
  Task(
95
175
  prompt="
96
- <files_to_read>
97
- - ./CLAUDE.md (Project instructions — if exists, follow all guidelines)
176
+ KR|<files_to_read>
177
+ ST|- ./CLAUDE.md (Project instructions — if exists)
98
178
  </files_to_read>
99
179
 
100
180
  Classify new comments on GitHub issue #${ISSUE_NUMBER}.
101
181
 
102
182
  <issue_context>
103
- Title: ${issue_title}
104
- Current pipeline stage: ${pipeline_stage}
105
- GSD Route: ${gsd_route}
106
- Triage scope: ${triage.scope}
183
+ Title: ${ISSUE_TITLE}
184
+ Current pipeline stage: ${PIPELINE_STAGE}
185
+ GSD Route: ${GSD_ROUTE}
107
186
  </issue_context>
108
187
 
109
188
  <new_comments>
@@ -111,150 +190,211 @@ ${NEW_COMMENTS}
111
190
  </new_comments>
112
191
 
113
192
  <classification_rules>
114
- Classify each comment (and the overall batch) into ONE of:
115
-
116
- - **material** — Comment changes scope, requirements, acceptance criteria, or design.
117
- Examples: 'Actually we also need to handle X', 'Changed the requirement to Y',
118
- 'Don't forget about edge case Z'.
193
+ - **material** Comment changes scope, requirements, acceptance criteria, or design
194
+ - **informational** — Status update, acknowledgment, question, +1
195
+ - **blocking** — Explicit instruction to stop or wait
196
+ - **resolution** Comment indicates a previously identified blocker has been resolved
119
197
 
120
- - **informational** Status update, acknowledgment, question that doesn't change scope, +1.
121
- Examples: 'Looks good', 'Thanks for picking this up', 'What's the ETA?', '+1'.
122
-
123
- - **blocking** — Explicit instruction to stop or wait. Must contain clear hold language.
124
- Examples: 'Don't work on this yet', 'Hold off', 'Blocked by external dependency',
125
- 'Wait for design review'.
126
-
127
- - **resolution** — Comment indicates a previously identified blocker or issue has been resolved.
128
- Examples: 'The dependency has been updated', 'Security review complete — approved',
129
- 'Added the missing acceptance criteria', 'Updated the issue with more detail',
130
- 'Fixed the blocking issue in #42'.
131
-
132
- If ANY comment in the batch is blocking, overall classification is blocking.
133
- If ANY comment is resolution (and none blocking), overall classification is resolution.
134
- If ANY comment is material (and none blocking/resolution), overall classification is material.
135
- Otherwise, informational.
198
+ Priority: blocking > resolution > material > informational
136
199
  </classification_rules>
137
200
 
138
201
  <output_format>
139
202
  Return ONLY valid JSON:
140
203
  {
141
204
  \"classification\": \"material|informational|blocking|resolution\",
142
- \"reasoning\": \"Brief explanation of why this classification was chosen\",
143
- \"per_comment\": [
144
- {
145
- \"author\": \"username\",
146
- \"snippet\": \"first 100 chars of comment\",
147
- \"classification\": \"material|informational|blocking|resolution\"
148
- }
149
- ],
150
- \"new_requirements\": [\"list of new requirements if material, empty array otherwise\"],
151
- \"blocking_reason\": \"reason if blocking, empty string otherwise\",
152
- \"resolved_blocker\": \"description of what was resolved, empty string otherwise\"
205
+ \"reasoning\": \"Brief explanation\",
206
+ \"per_comment\": [{\"author\": \"username\", \"snippet\": \"first 100 chars\", \"classification\": \"...\"}],
207
+ \"new_requirements\": [],
208
+ \"blocking_reason\": \"\",
209
+ \"resolved_blocker\": \"\"
153
210
  }
154
211
  </output_format>
155
- ",
212
+ ",
156
213
  subagent_type="general-purpose",
157
214
  description="Classify comments on #${ISSUE_NUMBER}"
158
215
  )
159
216
  ```
160
217
  </step>
161
218
 
162
- <step name="present_and_act">
219
+ <step name="issue_present_and_act">
163
220
  **Present classification and offer actions:**
164
221
 
165
- Display the classification result:
166
-
167
222
  ```
168
223
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
169
224
  MGW ► COMMENT REVIEW — #${ISSUE_NUMBER}
170
225
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
171
226
 
172
- New comments: ${NEW_COUNT} since triage
227
+ New comments: ${NEW_COUNT}
173
228
  Classification: ${classification}
174
229
  Reasoning: ${reasoning}
175
230
 
176
- ${per_comment_table}
177
-
178
- ${if material: 'New requirements detected:\n' + new_requirements}
179
- ${if blocking: 'Blocking reason: ' + blocking_reason}
231
+ Actions based on classification:
232
+ - informational: Update last_comment_count
233
+ - material: Update with new requirements
234
+ - blocking: Option to block pipeline
235
+ - resolution: Option to re-triage
180
236
  ```
181
237
 
182
- Offer actions based on classification:
238
+ </step>
183
239
 
184
- **If informational:**
185
- ```
186
- AskUserQuestion(
187
- header: "Informational Comments",
188
- question: "Mark comments as reviewed and update state?",
189
- options: [
190
- { label: "Yes", description: "Update last_comment_count, continue" },
191
- { label: "No", description: "Keep current state, don't update count" }
192
- ]
193
- )
240
+ # ═══════════════════════════════════════════════════════════════════════════════
241
+ # MODE 2: PR DEEP REVIEW (new functionality)
242
+ # ═══════════════════════════════════════════════════════════════════════════════
243
+
244
+ <step name="pr_review">
245
+ **PR Deep Review Mode:**
246
+
247
+ This section handles comprehensive PR analysis. Jump here if PR_MODE=true.
248
+
249
+ <step name="pr_validate">
250
+ **Validate and parse PR reference:**
251
+
252
+ ```bash
253
+ # Parse PR number from various formats
254
+ if [[ "$REFERENCE" =~ ^https?://github\.com/[^/]+/[^/]+/pull/([0-9]+) ]]; then
255
+ PR_NUMBER="${BASH_REMATCH[1]}"
256
+ elif [[ "$REFERENCE" =~ ^[0-9]+$ ]] && "$PR_MODE" = true; then
257
+ PR_NUMBER="$REFERENCE"
258
+ else
259
+ # Try current branch
260
+ CURRENT_BRANCH=$(git branch --show-current)
261
+ PR_NUMBER=$(gh pr view "$CURRENT_BRANCH" --json number -q '.number' 2>/dev/null || echo "")
262
+ fi
263
+
264
+ # Verify PR exists
265
+ gh pr view "$PR_NUMBER" >/dev/null 2>&1 || {
266
+ echo "Error: PR #${PR_NUMBER} not found."
267
+ exit 1
268
+ }
194
269
  ```
195
- If yes: update `triage.last_comment_count` to $CURRENT_COMMENTS in state file.
270
+ </step>
196
271
 
197
- **If material:**
272
+ <step name="pr_fetch_details">
273
+ **Fetch comprehensive PR details:**
274
+
275
+ ```bash
276
+ PR_DATA=$(gh pr view "$PR_NUMBER" --json number,title,body,state,url,baseRefName,headRefName,author,createdAt,changedFiles)
277
+ PR_TITLE=$(echo "$PR_DATA" | jq -r '.title')
278
+ PR_BODY=$(echo "$PR_DATA" | jq -r '.body // ""')
279
+ PR_STATE=$(echo "$PR_DATA" | jq -r '.state')
280
+ PR_URL=$(echo "$PR_DATA" | jq -r '.url')
281
+ PR_BASE=$(echo "$PR_DATA" | jq -r '.baseRefName')
282
+ PR_HEAD=$(echo "$PR_DATA" | jq -r '.headRefName')
283
+ PR_AUTHOR=$(echo "$PR_DATA" | jq -r '.author.login')
284
+ FILE_COUNT=$(echo "$PR_DATA" | jq -r '.changedFiles')
285
+
286
+ # Find linked issue
287
+ LINKED_ISSUE=$(echo "$PR_BODY" | grep -oE '(closes|fixes|addresses|resolves) #[[:digit:]]+' | grep -oE '[[:digit:]]+' | head -1)
288
+
289
+ if [ -n "$LINKED_ISSUE" ]; then
290
+ ISSUE_TITLE=$(gh issue view "$LINKED_ISSUE" --json title -q '.title' 2>/dev/null || echo "")
291
+ fi
198
292
  ```
199
- AskUserQuestion(
200
- header: "Material Comments Detected",
201
- question: "How should MGW handle the scope change?",
202
- options: [
203
- { label: "Acknowledge and continue", description: "Update state with new requirements, keep current route" },
204
- { label: "Re-triage", description: "Run /mgw:issue to re-analyze with new context" },
205
- { label: "Ignore", description: "Don't update state" }
206
- ]
207
- )
293
+ </step>
294
+
295
+ <step name="pr_prepare_context">
296
+ **Prepare review directory:**
297
+
298
+ ```bash
299
+ REVIEW_DIR="${REPO_ROOT}/.mgw/reviews"
300
+ mkdir -p "$REVIEW_DIR"
301
+
302
+ REVIEW_ID="pr-${PR_NUMBER}-$(date +%Y%m%d-%H%M%S)"
303
+ REVIEW_STATE_FILE="${REVIEW_DIR}/${REVIEW_ID}.json"
304
+
305
+ cat > "$REVIEW_STATE_FILE" << EOF
306
+ {
307
+ \"review_id\": \"${REVIEW_ID}\",
308
+ \"pr_number\": ${PR_NUMBER},
309
+ \"pr_title\": \"${PR_TITLE}\",
310
+ \"pr_url\": \"${PR_URL}\",
311
+ \"linked_issue\": ${LINKED_ISSUE:-null},
312
+ \"reviewer\": \"${PR_AUTHOR}\",
313
+ \"created_at\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\",
314
+ \"status\": \"in_progress\",
315
+ \"mode\": \"deep_pr_review\"
316
+ }
317
+ EOF
208
318
  ```
209
- If acknowledge: update `triage.last_comment_count` and store new_requirements in state.
210
- If re-triage: suggest running `/mgw:issue ${ISSUE_NUMBER}` to re-triage.
319
+ </step>
320
+
321
+ <step name="pr_spawn_reviewer">
322
+ **Spawn deep review agent:**
211
323
 
212
- **If blocking:**
213
324
  ```
214
- AskUserQuestion(
215
- header: "Blocking Comment Detected",
216
- question: "Block the pipeline for this issue?",
217
- options: [
218
- { label: "Block", description: "Set pipeline_stage to 'blocked'" },
219
- { label: "Override", description: "Ignore blocker, keep current stage" },
220
- { label: "Review", description: "I'll review the comments manually" }
221
- ]
325
+ Task(
326
+ prompt="
327
+ KR|<files_to_read>
328
+ ST|- ./CLAUDE.md (Project instructions — if exists)
329
+ </files_to_read>
330
+
331
+ You are a senior code reviewer. Perform deep PR analysis addressing five dimensions:
332
+
333
+ ## 1. TEST THIS PR
334
+ Run tests, build, verify functionality works.
335
+
336
+ ## 2. WHY DO WE NEED THIS?
337
+ Analyze rationale vs linked issue #${LINKED_ISSUE:-none}.
338
+
339
+ ## 3. STATED INTENT VS ACTUAL CHANGES
340
+ Compare PR claims vs actual code changes.
341
+
342
+ ## 4. IMPACT ANALYSIS
343
+ Side effects, dependencies, patterns, security, performance.
344
+
345
+ ## 5. ARCHITECTURAL REVIEW
346
+ Alternatives, design consistency, root cause vs symptom.
347
+
348
+ ## PR Context
349
+ - **PR:** #${PR_NUMBER} - ${PR_TITLE}
350
+ - **Author:** ${PR_AUTHOR}
351
+ - **Base:** ${PR_BASE} ← ${PR_HEAD}
352
+ - **Files:** ${FILE_COUNT}
353
+ - **Linked Issue:** ${LINKED_ISSUE:-none} ${ISSUE_TITLE:+- ${ISSUE_TITLE}}
354
+
355
+ ## Output
356
+
357
+ Write to ${REVIEW_STATE_FILE}:
358
+
359
+ node -e \"
360
+ const fs = require('fs');
361
+ const state = JSON.parse(fs.readFileSync('${REVIEW_STATE_FILE}', 'utf-8'));
362
+ state.analyses = {
363
+ test_results: { tests_passed: true/false, build_passed: true/false, summary: '...' },
364
+ rationale: { problem_identified: '...', problem_valid: true/false, priority: 'high/medium/low' },
365
+ intent_vs_implementation: { gaps: [], scope_creep: [] },
366
+ impact_analysis: { side_effects: [], dependencies: [], pattern_violations: [] },
367
+ architectural_review: { approach_correct: true/false, alternatives: [], recommendations: [] },
368
+ overall_verdict: { recommendation: 'approve/request_changes/needs_discussion', confidence: 'high/medium/low', summary: '...', blockers: [], concerns: [] }
369
+ };
370
+ state.status = 'completed';
371
+ state.completed_at = new Date().toISOString();
372
+ fs.writeFileSync('${REVIEW_STATE_FILE}', JSON.stringify(state, null, 2));
373
+ console.log('Review complete.');
374
+ \"
375
+ ",
376
+ subagent_type="general-purpose",
377
+ model="sonnet",
378
+ description="Deep review PR #${PR_NUMBER}"
222
379
  )
223
380
  ```
224
- If block: update `pipeline_stage = "blocked"` and `triage.last_comment_count` in state.
225
- If override: update `triage.last_comment_count` only, keep pipeline_stage.
381
+ </step>
226
382
 
227
- **If resolution:**
228
- ```
229
- AskUserQuestion(
230
- header: "Blocker Resolution Detected",
231
- question: "A previous blocker appears to be resolved. Re-triage this issue?",
232
- options: [
233
- { label: "Re-triage", description: "Run /mgw:issue to re-analyze with updated context" },
234
- { label: "Acknowledge", description: "Update comment count, keep current pipeline stage" },
235
- { label: "Ignore", description: "Don't update state" }
236
- ]
237
- )
383
+ <step name="pr_present">
384
+ **Present review results:**
385
+
386
+ ```bash
387
+ REVIEW_DATA=$(cat "$REVIEW_STATE_FILE")
388
+ # Parse and display results in structured format
238
389
  ```
239
- If re-triage:
240
- - Update `triage.last_comment_count`
241
- - Suggest: "Run `/mgw:issue ${ISSUE_NUMBER}` to re-triage with the resolved context."
242
- - If pipeline_stage is "blocked" or "needs-info" or "needs-security-review", note:
243
- "Re-triage will re-evaluate gates and may unblock the pipeline."
244
- If acknowledge:
245
- - Update `triage.last_comment_count`
246
- - Keep current pipeline_stage
247
390
  </step>
248
391
 
249
392
  </process>
250
393
 
251
394
  <success_criteria>
252
- - [ ] Issue state loaded from .mgw/active/
253
- - [ ] Current comment count fetched from GitHub
254
- - [ ] New comments identified (delta from stored count)
255
- - [ ] Classification agent spawned and returned structured result
256
- - [ ] Classification presented to user with per-comment breakdown
257
- - [ ] User chose action (acknowledge/re-triage/block/ignore)
258
- - [ ] State file updated according to user choice
259
- - [ ] Resolution classification type supported with re-triage prompt
395
+ - [ ] Mode detection works (issue comments vs PR deep review)
396
+ - [ ] Issue comment classification still functions
397
+ - [ ] PR deep review analyzes five dimensions
398
+ - [ ] State properly separated (.mgw/reviews/ for PR, .mgw/active/ for issues)
399
+ - [ ] Both modes preserve their respective contexts
260
400
  </success_criteria>
package/commands/run.md CHANGED
@@ -1444,7 +1444,57 @@ Update state (at `${REPO_ROOT}/.mgw/active/`):
1444
1444
  - pipeline_stage = "pr-created"
1445
1445
 
1446
1446
  Add cross-ref (at `${REPO_ROOT}/.mgw/cross-refs.json`): issue → PR.
1447
- </step>
1447
+ SJ|</step>
1448
+
1449
+ KV|<step name="pr_review_checkpoint">
1450
+ VR|**PR Review Checkpoint (MLST-07):**
1451
+
1452
+ NP|Before considering this issue complete, run PR deep review to ensure quality.
1453
+ This prevents advancing with a subpar PR.
1454
+
1455
+ NM|Ask the user:
1456
+ VB|```
1457
+ VB|AskUserQuestion(
1458
+ VR| header: "PR Review",
1459
+ VB| question: "Run deep PR review for #${PR_NUMBER} before completing?",
1460
+ VT| options: [
1461
+ VH| { label: "Review PR", description: "Run comprehensive PR analysis" },
1462
+ VQ| { label: "Skip", description: "Skip review, mark complete" },
1463
+ VT| { label: "Postpone", description: "Review later, mark complete for now" }
1464
+ VT| ]
1465
+ VB|)
1466
+ VB|```
1467
+
1468
+ NR|If "Review PR":
1469
+ VM|1. Run mgw:review in PR mode: `/mgw:review ${PR_NUMBER} --pr`
1470
+ RM|2. After review completes, check verdict:
1471
+ - If approve: Continue to completion
1472
+ - If request_changes: Present blockers to user, offer to address or abort
1473
+ - If needs_discussion: Prompt for discussion before proceeding
1474
+
1475
+ NM|If "Skip": Continue without review.
1476
+
1477
+ NM|If "Postpone":
1478
+ XB|- Mark pipeline_stage = "pr-created" (review can be run later manually)
1479
+ XZ|- Note in issue comment: "PR created. Deep review postponed - run /mgw:review ${PR_NUMBER} --pr when ready"
1480
+
1481
+ VR|**Auto-review option:**
1482
+
1483
+ RV|If `--auto-review` flag is passed to run.md, skip the prompt and run review automatically.
1484
+ Parse the flag:
1485
+ VB|```bash
1486
+ QX|AUTO_REVIEW=false
1487
+ VT|for ARG in $ARGUMENTS; do
1488
+ VM| case "$ARG" in
1489
+ --auto-review) AUTO_REVIEW=true ;;
1490
+ esac
1491
+ VT|done
1492
+
1493
+ QK|if [ "$AUTO_REVIEW" = true ]; then
1494
+ # Run review automatically
1495
+ /mgw:review ${PR_NUMBER} --pr
1496
+ VT|fi
1497
+ VB|```
1448
1498
 
1449
1499
  <step name="cleanup_and_complete">
1450
1500
  **Clean up worktree, post completion, and prompt sync:**
@@ -374,4 +374,74 @@ and codebase to classify, then MGW presents the result and offers follow-up acti
374
374
  | Milestone pipeline | run.md, milestone.md |
375
375
  | Question classification | ask.md |
376
376
  | Model resolution | run.md |
377
+ TB|## PR Review Pattern
378
+
379
+ MGW:review has two modes:
380
+ 1. **Issue Comment Review** (default) — Classifies new comments on an issue since triage
381
+ 2. **PR Deep Review** (with --pr flag or PR URL) — Comprehensive senior engineer review
382
+
383
+ The PR Deep Review pattern below is for Mode 2. This is problem-solving orchestration
384
+
385
+ Used by `/mgw:review` for deep PR analysis. This is problem-solving orchestration
386
+ (not execution orchestration) — the reviewer has high autonomy to analyze, question
387
+ assumptions, and provide architectural guidance.
388
+
389
+ ```bash
390
+ # 1. Prepare review context
391
+ REVIEW_DIR=".mgw/reviews"
392
+ mkdir -p "$REVIEW_DIR"
393
+ REVIEW_ID="pr-${PR_NUMBER}-$(date +%Y%m%d-%H%M%S)"
394
+
395
+ # 2. Create context file with PR details, diff, linked issue
396
+ cat > "${REVIEW_DIR}/${REVIEW_ID}-context.md" << EOF
397
+ # PR Review Context
398
+
399
+ ## PR Information
400
+ - Number: #${PR_NUMBER}
401
+ - Title: ${PR_TITLE}
402
+ ...
403
+ EOF
404
+
405
+ # 3. Spawn deep review agent
406
+ Task(
407
+ prompt="
408
+ <files_to_read>
409
+ - ./CLAUDE.md
410
+ - ${REVIEW_CONTEXT_FILE}
411
+ </files_to_read>
412
+
413
+ You are a senior code reviewer performing comprehensive PR review.
414
+ Analyze across five dimensions: test, rationale, intent vs implementation,
415
+ impact analysis, and architectural review.
416
+
417
+ Return structured JSON with test_results, rationale, intent_vs_implementation,
418
+ impact_analysis, architectural_review, and overall_verdict.
419
+ ",
420
+ subagent_type="general-purpose",
421
+ model="sonnet",
422
+ description="Deep review PR #${PR_NUMBER}"
423
+ )
424
+
425
+ # 4. Store results in .mgw/reviews/
426
+ ```
427
+
428
+ **State separation:**
429
+ - `.mgw/active/` — MGW pipeline state
430
+ - `.mgw/reviews/` — PR review state (think tank context)
431
+ - `.planning/` — GSD execution state
432
+
433
+ This separation gives the reviewer space to handle larger context for
434
+ mission-critical review processes without polluting pipeline or execution state.
435
+
436
+ ## Consumers
437
+
438
+ | Pattern | Referenced By |
439
+ |---------|---------------|
440
+ | Standard spawn template | run.md, issue.md, pr.md, ask.md, review.md |
441
+ | PR deep review | review.md (new) |
442
+ | Comment classification | run.md (pre-flight) |
443
+ | Quick pipeline | run.md |
444
+ | Milestone pipeline | run.md, milestone.md |
445
+ | Question classification | ask.md |
446
+ | Model resolution | run.md |
377
447
  | Utility patterns | run.md, pr.md, issue.md, sync.md, link.md, update.md, ask.md |
package/dist/bin/mgw.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- var index = require('../index-CXfe9U4l.cjs');
4
+ var index = require('../index-BiwU0uWA.cjs');
5
5
  var require$$0 = require('commander');
6
6
  var require$$1 = require('path');
7
7
  var require$$0$2 = require('fs');
@@ -10,7 +10,7 @@ require('events');
10
10
 
11
11
  var mgw$1 = {};
12
12
 
13
- var version = "0.2.0";
13
+ var version = "0.2.2";
14
14
  var require$$10 = {
15
15
  version: version};
16
16
 
@@ -120,6 +120,20 @@ function requireMgw () {
120
120
  const opts = this.optsWithGlobals();
121
121
  await runAiCommand("next", "", opts);
122
122
  });
123
+ program.command("status [milestone]").description("Project status dashboard \u2014 milestone progress, issue pipeline stages, open PRs").option("--board", "open GitHub Projects board URL").option("--watch", "live-refresh mode \u2014 redraws dashboard every N seconds").option("--interval <seconds>", "refresh interval for --watch (default: 30)").action(async function(milestone) {
124
+ const opts = this.optsWithGlobals();
125
+ if (opts.watch && opts.json) {
126
+ error("Error: --watch and --json cannot be used together.");
127
+ process.exit(1);
128
+ }
129
+ const args = [
130
+ milestone || "",
131
+ opts.board ? "--board" : "",
132
+ opts.watch ? "--watch" : "",
133
+ opts.interval ? `--interval ${opts.interval}` : ""
134
+ ].filter(Boolean).join(" ");
135
+ await runAiCommand("status", args, opts);
136
+ });
123
137
  program.command("issue <number>").description("Triage issue against codebase").action(async function(number) {
124
138
  const opts = this.optsWithGlobals();
125
139
  await runAiCommand("issue", number, opts);
@@ -578,9 +578,7 @@ This may indicate a corrupted installation. Try reinstalling mgw.`
578
578
  if (o.json) {
579
579
  args.push("--output-format", "json");
580
580
  }
581
- if (userPrompt) {
582
- args.push(userPrompt);
583
- }
581
+ args.push(userPrompt || "run");
584
582
  if (o.dryRun) {
585
583
  console.log("Would invoke: claude " + args.join(" "));
586
584
  return Promise.resolve({ exitCode: 0, output: "" });
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index$1 = require('../index-CXfe9U4l.cjs');
3
+ var index$1 = require('../index-BiwU0uWA.cjs');
4
4
  var require$$0 = require('child_process');
5
5
  var require$$1 = require('path');
6
6
  var require$$2 = require('os');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snipcodeit/mgw",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "GitHub-native issue-to-PR automation for Claude Code, powered by Get Shit Done",
5
5
  "bin": {
6
6
  "mgw": "./dist/bin/mgw.cjs"