@snipcodeit/mgw 0.2.2 → 0.4.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.
@@ -57,25 +57,23 @@ REFERENCE="$ARGUMENTS"
57
57
  PR_MODE=false
58
58
 
59
59
  # Check for --pr flag
60
- if [[ "$REFERENCE" =~ --pr[[:space:]]|$ ]]; then
60
+ if [[ "$REFERENCE" == *"--pr"* ]]; then
61
61
  PR_MODE=true
62
62
  REFERENCE=$(echo "$REFERENCE" | sed 's/--pr//g' | xargs)
63
63
  fi
64
64
 
65
65
  # Determine if PR or issue based on format
66
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
67
+ PR_MODE=true
71
68
  PR_REF="$REFERENCE"
72
69
  elif [[ "$REFERENCE" =~ ^https?://github\.com/[^/]+/[^/]+/issues/ ]]; then
73
70
  PR_MODE=false
74
71
  ISSUE_REF="$REFERENCE"
75
72
  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
73
+ # Probe GitHub to determine if it's a PR or issue
74
+ if gh pr view "$REFERENCE" >/dev/null 2>&1; then
75
+ PR_MODE=true
76
+ fi
79
77
  NUMBER="$REFERENCE"
80
78
  else
81
79
  # Default: issue comment review
@@ -173,8 +171,8 @@ GSD_ROUTE=$(jq -r '.gsd_route // "unknown"' "$STATE_FILE" 2>/dev/null || echo "u
173
171
  ```
174
172
  Task(
175
173
  prompt="
176
- KR|<files_to_read>
177
- ST|- ./CLAUDE.md (Project instructions — if exists)
174
+ <files_to_read>
175
+ - ./CLAUDE.md (Project instructions — if exists, follow all guidelines)
178
176
  </files_to_read>
179
177
 
180
178
  Classify new comments on GitHub issue #${ISSUE_NUMBER}.
@@ -183,6 +181,7 @@ Classify new comments on GitHub issue #${ISSUE_NUMBER}.
183
181
  Title: ${ISSUE_TITLE}
184
182
  Current pipeline stage: ${PIPELINE_STAGE}
185
183
  GSD Route: ${GSD_ROUTE}
184
+ Triage scope: ${triage.scope}
186
185
  </issue_context>
187
186
 
188
187
  <new_comments>
@@ -190,23 +189,44 @@ ${NEW_COMMENTS}
190
189
  </new_comments>
191
190
 
192
191
  <classification_rules>
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
192
+ Classify each comment (and the overall batch) into ONE of:
193
+
194
+ - **material** — Comment changes scope, requirements, acceptance criteria, or design.
195
+ Examples: 'Actually we also need to handle X', 'Changed the requirement to Y',
196
+ 'Don't forget about edge case Z'.
197
197
 
198
- Priority: blocking > resolution > material > informational
198
+ - **informational** Status update, acknowledgment, question that doesn't change scope, +1.
199
+ Examples: 'Looks good', 'Thanks for picking this up', 'What's the ETA?', '+1'.
200
+
201
+ - **blocking** — Explicit instruction to stop or wait. Must contain clear hold language.
202
+ Examples: 'Don't work on this yet', 'Hold off', 'Blocked by external dependency',
203
+ 'Wait for design review'.
204
+
205
+ - **resolution** — Comment indicates a previously identified blocker or issue has been resolved.
206
+ Examples: 'The dependency has been updated', 'Security review complete — approved',
207
+ 'Added the missing acceptance criteria', 'Updated the issue with more detail'.
208
+
209
+ If ANY comment in the batch is blocking, overall classification is blocking.
210
+ If ANY comment is resolution (and none blocking), overall classification is resolution.
211
+ If ANY comment is material (and none blocking/resolution), overall classification is material.
212
+ Otherwise, informational.
199
213
  </classification_rules>
200
214
 
201
215
  <output_format>
202
216
  Return ONLY valid JSON:
203
217
  {
204
218
  \"classification\": \"material|informational|blocking|resolution\",
205
- \"reasoning\": \"Brief explanation\",
206
- \"per_comment\": [{\"author\": \"username\", \"snippet\": \"first 100 chars\", \"classification\": \"...\"}],
207
- \"new_requirements\": [],
208
- \"blocking_reason\": \"\",
209
- \"resolved_blocker\": \"\"
219
+ \"reasoning\": \"Brief explanation of why this classification was chosen\",
220
+ \"per_comment\": [
221
+ {
222
+ \"author\": \"username\",
223
+ \"snippet\": \"first 100 chars of comment\",
224
+ \"classification\": \"material|informational|blocking|resolution\"
225
+ }
226
+ ],
227
+ \"new_requirements\": [\"list of new requirements if material, empty array otherwise\"],
228
+ \"blocking_reason\": \"reason if blocking, empty string otherwise\",
229
+ \"resolved_blocker\": \"description of what was resolved, empty string otherwise\"
210
230
  }
211
231
  </output_format>
212
232
  ",
@@ -219,21 +239,88 @@ Return ONLY valid JSON:
219
239
  <step name="issue_present_and_act">
220
240
  **Present classification and offer actions:**
221
241
 
242
+ Display the classification result:
243
+
222
244
  ```
223
245
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
224
246
  MGW ► COMMENT REVIEW — #${ISSUE_NUMBER}
225
247
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
226
248
 
227
- New comments: ${NEW_COUNT}
249
+ New comments: ${NEW_COUNT} since triage
228
250
  Classification: ${classification}
229
251
  Reasoning: ${reasoning}
230
252
 
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
253
+ ${per_comment_table}
254
+
255
+ ${if material: 'New requirements detected:\n' + new_requirements}
256
+ ${if blocking: 'Blocking reason: ' + blocking_reason}
257
+ ```
258
+
259
+ Offer actions based on classification:
260
+
261
+ **If informational:**
262
+ ```
263
+ AskUserQuestion(
264
+ header: "Informational Comments",
265
+ question: "Mark comments as reviewed and update state?",
266
+ options: [
267
+ { label: "Yes", description: "Update last_comment_count, continue" },
268
+ { label: "No", description: "Keep current state, don't update count" }
269
+ ]
270
+ )
271
+ ```
272
+ If yes: update `triage.last_comment_count` to $CURRENT_COMMENTS in state file.
273
+
274
+ **If material:**
275
+ ```
276
+ AskUserQuestion(
277
+ header: "Material Comments Detected",
278
+ question: "How should MGW handle the scope change?",
279
+ options: [
280
+ { label: "Acknowledge and continue", description: "Update state with new requirements, keep current route" },
281
+ { label: "Re-triage", description: "Run /mgw:issue to re-analyze with new context" },
282
+ { label: "Ignore", description: "Don't update state" }
283
+ ]
284
+ )
285
+ ```
286
+ If acknowledge: update `triage.last_comment_count` and store new_requirements in state.
287
+ If re-triage: suggest running `/mgw:issue ${ISSUE_NUMBER}` to re-triage.
288
+
289
+ **If blocking:**
290
+ ```
291
+ AskUserQuestion(
292
+ header: "Blocking Comment Detected",
293
+ question: "Block the pipeline for this issue?",
294
+ options: [
295
+ { label: "Block", description: "Set pipeline_stage to 'blocked'" },
296
+ { label: "Override", description: "Ignore blocker, keep current stage" },
297
+ { label: "Review", description: "I'll review the comments manually" }
298
+ ]
299
+ )
300
+ ```
301
+ If block: update `pipeline_stage = "blocked"` and `triage.last_comment_count` in state.
302
+ If override: update `triage.last_comment_count` only, keep pipeline_stage.
303
+
304
+ **If resolution:**
305
+ ```
306
+ AskUserQuestion(
307
+ header: "Blocker Resolution Detected",
308
+ question: "A previous blocker appears to be resolved. Re-triage this issue?",
309
+ options: [
310
+ { label: "Re-triage", description: "Run /mgw:issue to re-analyze with updated context" },
311
+ { label: "Acknowledge", description: "Update comment count, keep current pipeline stage" },
312
+ { label: "Ignore", description: "Don't update state" }
313
+ ]
314
+ )
236
315
  ```
316
+ If re-triage:
317
+ - Update `triage.last_comment_count`
318
+ - Suggest: "Run `/mgw:issue ${ISSUE_NUMBER}` to re-triage with the resolved context."
319
+ - If pipeline_stage is "blocked" or "needs-info" or "needs-security-review", note:
320
+ "Re-triage will re-evaluate gates and may unblock the pipeline."
321
+ If acknowledge:
322
+ - Update `triage.last_comment_count`
323
+ - Keep current pipeline_stage
237
324
 
238
325
  </step>
239
326
 
@@ -253,7 +340,7 @@ This section handles comprehensive PR analysis. Jump here if PR_MODE=true.
253
340
  # Parse PR number from various formats
254
341
  if [[ "$REFERENCE" =~ ^https?://github\.com/[^/]+/[^/]+/pull/([0-9]+) ]]; then
255
342
  PR_NUMBER="${BASH_REMATCH[1]}"
256
- elif [[ "$REFERENCE" =~ ^[0-9]+$ ]] && "$PR_MODE" = true; then
343
+ elif [[ "$REFERENCE" =~ ^[0-9]+$ ]] && [[ "$PR_MODE" = true ]]; then
257
344
  PR_NUMBER="$REFERENCE"
258
345
  else
259
346
  # Try current branch
@@ -282,12 +369,17 @@ PR_BASE=$(echo "$PR_DATA" | jq -r '.baseRefName')
282
369
  PR_HEAD=$(echo "$PR_DATA" | jq -r '.headRefName')
283
370
  PR_AUTHOR=$(echo "$PR_DATA" | jq -r '.author.login')
284
371
  FILE_COUNT=$(echo "$PR_DATA" | jq -r '.changedFiles')
372
+ REVIEWER=$(gh api user -q .login 2>/dev/null || echo "unknown")
373
+
374
+ # Fetch the actual diff for the reviewer agent
375
+ PR_DIFF=$(gh pr diff "$PR_NUMBER" 2>/dev/null || echo "")
285
376
 
286
377
  # Find linked issue
287
378
  LINKED_ISSUE=$(echo "$PR_BODY" | grep -oE '(closes|fixes|addresses|resolves) #[[:digit:]]+' | grep -oE '[[:digit:]]+' | head -1)
288
379
 
289
380
  if [ -n "$LINKED_ISSUE" ]; then
290
381
  ISSUE_TITLE=$(gh issue view "$LINKED_ISSUE" --json title -q '.title' 2>/dev/null || echo "")
382
+ ISSUE_BODY=$(gh issue view "$LINKED_ISSUE" --json body -q '.body' 2>/dev/null || echo "")
291
383
  fi
292
384
  ```
293
385
  </step>
@@ -309,7 +401,7 @@ cat > "$REVIEW_STATE_FILE" << EOF
309
401
  \"pr_title\": \"${PR_TITLE}\",
310
402
  \"pr_url\": \"${PR_URL}\",
311
403
  \"linked_issue\": ${LINKED_ISSUE:-null},
312
- \"reviewer\": \"${PR_AUTHOR}\",
404
+ \"reviewer\": \"${REVIEWER}\",
313
405
  \"created_at\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\",
314
406
  \"status\": \"in_progress\",
315
407
  \"mode\": \"deep_pr_review\"
@@ -324,34 +416,67 @@ EOF
324
416
  ```
325
417
  Task(
326
418
  prompt="
327
- KR|<files_to_read>
328
- ST|- ./CLAUDE.md (Project instructions — if exists)
419
+ <files_to_read>
420
+ - ./CLAUDE.md (Project instructions — if exists, follow all guidelines)
421
+ - .agents/skills/ (Project skills — if dir exists, list skills, read SKILL.md for each, follow relevant rules)
329
422
  </files_to_read>
330
423
 
331
- You are a senior code reviewer. Perform deep PR analysis addressing five dimensions:
424
+ You are a senior code reviewer. Perform deep PR analysis addressing five dimensions.
425
+
426
+ **Important context about this repository:** MGW is a command system — the files being reviewed
427
+ are markdown command definitions (parsed by Claude Code at invocation time), not compiled source code.
428
+ There are no automated tests. \"Run tests\" means: parse each changed .md file, verify step tags are
429
+ properly closed, check bash snippets for syntax errors, and verify all XML tags balance.
332
430
 
333
431
  ## 1. TEST THIS PR
334
- Run tests, build, verify functionality works.
432
+ Parse each changed .md file for structural integrity:
433
+ - All `<step name="...">` tags have matching `</step>` closings
434
+ - XML tags balance (no unclosed tags)
435
+ - Bash code blocks have no syntax errors (check conditionals, variable references)
436
+ - YAML frontmatter is valid (no XX| prefixes, valid keys only)
437
+ - Agent Task() prompts have no stray line prefixes (e.g. XX| artifacts)
335
438
 
336
439
  ## 2. WHY DO WE NEED THIS?
337
- Analyze rationale vs linked issue #${LINKED_ISSUE:-none}.
440
+ Analyze rationale vs linked issue #${LINKED_ISSUE:-none}:
441
+ - Does the PR solve a real problem?
442
+ - Is the problem worth solving?
443
+ - Does the approach match the stated need?
338
444
 
339
445
  ## 3. STATED INTENT VS ACTUAL CHANGES
340
- Compare PR claims vs actual code changes.
446
+ Compare PR description vs actual diff:
447
+ - What the PR claims vs what the code actually does
448
+ - Gaps between intent and implementation
449
+ - Scope creep (changes beyond what was stated)
341
450
 
342
451
  ## 4. IMPACT ANALYSIS
343
- Side effects, dependencies, patterns, security, performance.
452
+ For markdown command files specifically:
453
+ - Which MGW commands/workflows reference the changed files?
454
+ - Does any change break existing behavior? (regression risk)
455
+ - Are any shared workflow patterns (state.md, github.md, gsd.md, validation.md) affected?
456
+ - Security or correctness issues in bash snippets?
344
457
 
345
458
  ## 5. ARCHITECTURAL REVIEW
346
- Alternatives, design consistency, root cause vs symptom.
459
+ - Does the approach follow MGW's delegation boundary (orchestrate, never code)?
460
+ - Is state properly separated (.mgw/active/ vs .mgw/reviews/ vs .planning/)?
461
+ - Are there simpler alternatives?
462
+ - Does it introduce technical debt?
347
463
 
348
464
  ## PR Context
349
465
  - **PR:** #${PR_NUMBER} - ${PR_TITLE}
350
466
  - **Author:** ${PR_AUTHOR}
467
+ - **Reviewer:** ${REVIEWER}
351
468
  - **Base:** ${PR_BASE} ← ${PR_HEAD}
352
- - **Files:** ${FILE_COUNT}
469
+ - **Files changed:** ${FILE_COUNT}
353
470
  - **Linked Issue:** ${LINKED_ISSUE:-none} ${ISSUE_TITLE:+- ${ISSUE_TITLE}}
354
471
 
472
+ ## Linked Issue Body
473
+ ${ISSUE_BODY:-N/A}
474
+
475
+ ## PR Diff
476
+ \`\`\`diff
477
+ ${PR_DIFF}
478
+ \`\`\`
479
+
355
480
  ## Output
356
481
 
357
482
  Write to ${REVIEW_STATE_FILE}:
@@ -385,16 +510,71 @@ console.log('Review complete.');
385
510
 
386
511
  ```bash
387
512
  REVIEW_DATA=$(cat "$REVIEW_STATE_FILE")
388
- # Parse and display results in structured format
389
513
  ```
514
+
515
+ Display structured report:
516
+
517
+ ```
518
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
519
+ MGW ► PR DEEP REVIEW — #${PR_NUMBER}
520
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
521
+
522
+ ${PR_TITLE}
523
+ Verdict: ${overall_verdict.recommendation} (${overall_verdict.confidence} confidence)
524
+
525
+ ── 1. TEST ──
526
+ ${test_results.summary}
527
+
528
+ ── 2. RATIONALE ──
529
+ ${rationale.problem_identified}
530
+ Valid: ${rationale.problem_valid} | Priority: ${rationale.priority}
531
+
532
+ ── 3. INTENT vs IMPLEMENTATION ──
533
+ Gaps: ${intent_vs_implementation.gaps}
534
+ Scope creep: ${intent_vs_implementation.scope_creep}
535
+
536
+ ── 4. IMPACT ──
537
+ Side effects: ${impact_analysis.side_effects}
538
+ Pattern violations: ${impact_analysis.pattern_violations}
539
+
540
+ ── 5. ARCHITECTURE ──
541
+ Approach correct: ${architectural_review.approach_correct}
542
+ Recommendations: ${architectural_review.recommendations}
543
+
544
+ ── VERDICT ──
545
+ ${overall_verdict.summary}
546
+ Blockers: ${overall_verdict.blockers}
547
+ Concerns: ${overall_verdict.concerns}
548
+
549
+ Review state: ${REVIEW_STATE_FILE}
550
+ ```
551
+
552
+ Offer follow-up actions:
553
+ ```
554
+ AskUserQuestion(
555
+ header: "Review Complete",
556
+ question: "What would you like to do with this review?",
557
+ options: [
558
+ { label: "Post to PR", description: "Post review summary as PR comment" },
559
+ { label: "Create issue", description: "File a follow-up issue for blockers/concerns" },
560
+ { label: "Done", description: "Review recorded in .mgw/reviews/" }
561
+ ]
562
+ )
563
+ ```
564
+
565
+ If "Post to PR": post `overall_verdict.summary` + blockers/concerns as a PR comment via `gh pr comment ${PR_NUMBER} --body "..."`.
566
+ If "Create issue": offer to file a new GitHub issue with the blockers as the body.
390
567
  </step>
391
568
 
392
569
  </process>
393
570
 
394
571
  <success_criteria>
395
- - [ ] Mode detection works (issue comments vs PR deep review)
396
- - [ ] Issue comment classification still functions
397
- - [ ] PR deep review analyzes five dimensions
572
+ - [ ] Mode detection correctly routes: --pr flag, PR URL, and bare PR numbers (via gh pr view probe) enter PR mode
573
+ - [ ] Issue comment review (Mode 1) classifies all four types and offers correct AskUserQuestion actions
574
+ - [ ] Issue state file updated according to user choice (last_comment_count, pipeline_stage)
575
+ - [ ] PR deep review (Mode 2) fetches diff and passes it to the reviewer agent
576
+ - [ ] Reviewer agent prompt is domain-aware (markdown command files, not compiled code)
577
+ - [ ] Review results stored in .mgw/reviews/ and presented with follow-up actions
398
578
  - [ ] State properly separated (.mgw/reviews/ for PR, .mgw/active/ for issues)
399
- - [ ] Both modes preserve their respective contexts
579
+ - [ ] reviewer field reflects the current user, not the PR author
400
580
  </success_criteria>