@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.
- package/README.md +55 -5
- package/bin/mgw-install.cjs +121 -24
- package/commands/board/configure.md +205 -0
- package/commands/board/create.md +688 -0
- package/commands/board/show.md +221 -0
- package/commands/board/sync.md +461 -0
- package/commands/board/views.md +253 -0
- package/commands/board.md +23 -1543
- package/commands/context.md +183 -0
- package/commands/handoff.md +169 -0
- package/commands/issue.md +62 -0
- package/commands/milestone.md +42 -43
- package/commands/project.md +19 -0
- package/commands/review.md +222 -42
- package/commands/run/execute.md +820 -0
- package/commands/run/pr-create.md +324 -0
- package/commands/run/triage.md +510 -0
- package/commands/run/worktree.md +95 -0
- package/commands/run.md +23 -1547
- package/commands/sync.md +69 -0
- package/commands/workflows/gsd.md +1 -13
- package/dist/bin/mgw.cjs +107 -15
- package/dist/{index-BiwU0uWA.cjs → index-B-_JvYpz.cjs} +885 -69
- package/dist/lib/index.cjs +653 -155
- package/package.json +5 -2
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mgw:context
|
|
3
|
+
description: Show assembled context for an issue — what GSD agents see before planning/execution
|
|
4
|
+
argument-hint: "<issue-number>"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Bash
|
|
7
|
+
- Read
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<objective>
|
|
11
|
+
Display the full assembled context for a GitHub issue, showing exactly what a GSD agent
|
|
12
|
+
would receive as input before planning or execution. Useful for debugging context gaps,
|
|
13
|
+
verifying that prior phase summaries are available, and checking what a second developer's
|
|
14
|
+
agent will see.
|
|
15
|
+
|
|
16
|
+
This command is read-only. It does not modify any state.
|
|
17
|
+
</objective>
|
|
18
|
+
|
|
19
|
+
<process>
|
|
20
|
+
|
|
21
|
+
<step name="validate_input">
|
|
22
|
+
**Validate issue number provided:**
|
|
23
|
+
|
|
24
|
+
Parse $ARGUMENTS for a numeric issue number. If missing:
|
|
25
|
+
```
|
|
26
|
+
AskUserQuestion(
|
|
27
|
+
header: "Issue Number Required",
|
|
28
|
+
question: "Which issue number do you want context for?",
|
|
29
|
+
followUp: "Enter the GitHub issue number (e.g., 42)"
|
|
30
|
+
)
|
|
31
|
+
```
|
|
32
|
+
</step>
|
|
33
|
+
|
|
34
|
+
<step name="assemble_and_display">
|
|
35
|
+
**Assemble full context from GitHub and display formatted output:**
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
39
|
+
|
|
40
|
+
node -e "
|
|
41
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
42
|
+
|
|
43
|
+
(async () => {
|
|
44
|
+
// Assemble issue context
|
|
45
|
+
const ctx = await ic.assembleIssueContext(${ISSUE_NUMBER});
|
|
46
|
+
if (!ctx || !ctx.issue) {
|
|
47
|
+
console.log('No context found for issue #${ISSUE_NUMBER}.');
|
|
48
|
+
process.exit(0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const issue = ctx.issue;
|
|
52
|
+
const milestone = issue.milestone || {};
|
|
53
|
+
const labels = (issue.labels || []).map(l => typeof l === 'object' ? l.name : l);
|
|
54
|
+
|
|
55
|
+
// Header
|
|
56
|
+
console.log('');
|
|
57
|
+
console.log('Issue #' + issue.number + ': ' + issue.title);
|
|
58
|
+
if (milestone.title) {
|
|
59
|
+
console.log('Milestone: ' + milestone.title);
|
|
60
|
+
}
|
|
61
|
+
console.log('Status: ' + (issue.state || 'unknown'));
|
|
62
|
+
if (labels.length > 0) {
|
|
63
|
+
console.log('Labels: ' + labels.join(', '));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Vision
|
|
67
|
+
const vision = await ic.fetchProjectVision();
|
|
68
|
+
if (vision) {
|
|
69
|
+
console.log('');
|
|
70
|
+
console.log('-- Vision --');
|
|
71
|
+
console.log(vision.slice(0, 2000));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Prior phases (from milestone siblings)
|
|
75
|
+
if (ctx.milestoneContext && ctx.milestoneContext.length > 0) {
|
|
76
|
+
console.log('');
|
|
77
|
+
console.log('-- Prior Phases --');
|
|
78
|
+
for (const s of ctx.milestoneContext) {
|
|
79
|
+
if (s.issueNumber === issue.number) continue;
|
|
80
|
+
console.log('Phase #' + s.issueNumber + ': ' + s.title);
|
|
81
|
+
if (s.summary) {
|
|
82
|
+
// Indent summary lines
|
|
83
|
+
const lines = s.summary.split('\\n').slice(0, 5);
|
|
84
|
+
for (const line of lines) {
|
|
85
|
+
console.log(' ' + line);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Phase goal (from issue body)
|
|
92
|
+
if (issue.body) {
|
|
93
|
+
console.log('');
|
|
94
|
+
console.log('-- Phase Goal --');
|
|
95
|
+
// Extract acceptance criteria or goal sections from body
|
|
96
|
+
const body = issue.body;
|
|
97
|
+
const goalMatch = body.match(/##?\\s*(?:Goal|Description|Overview)\\s*\\n([\\s\\S]*?)(?=\\n##|$)/i);
|
|
98
|
+
if (goalMatch) {
|
|
99
|
+
console.log(goalMatch[1].trim().slice(0, 1000));
|
|
100
|
+
} else {
|
|
101
|
+
// Show first meaningful paragraph
|
|
102
|
+
const paras = body.split('\\n\\n').filter(p => p.trim() && !p.startsWith('<!--'));
|
|
103
|
+
if (paras.length > 0) {
|
|
104
|
+
console.log(paras[0].trim().slice(0, 1000));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const acMatch = body.match(/##?\\s*Acceptance\\s*Criteria\\s*\\n([\\s\\S]*?)(?=\\n##|$)/i);
|
|
109
|
+
if (acMatch) {
|
|
110
|
+
console.log('');
|
|
111
|
+
console.log('-- Acceptance Criteria --');
|
|
112
|
+
console.log(acMatch[1].trim().slice(0, 1000));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Dependencies (from labels)
|
|
117
|
+
const blockedBy = labels.filter(l => l.startsWith('blocked-by:'));
|
|
118
|
+
const blocks = labels.filter(l => l.startsWith('blocks:'));
|
|
119
|
+
if (blockedBy.length > 0 || blocks.length > 0) {
|
|
120
|
+
console.log('');
|
|
121
|
+
console.log('-- Dependencies --');
|
|
122
|
+
if (blockedBy.length > 0) {
|
|
123
|
+
console.log('Blocked by: ' + blockedBy.map(l => l.replace('blocked-by:', '')).join(', '));
|
|
124
|
+
}
|
|
125
|
+
if (blocks.length > 0) {
|
|
126
|
+
console.log('Blocks: ' + blocks.map(l => l.replace('blocks:', '')).join(', '));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Plan (if posted)
|
|
131
|
+
if (ctx.planComment) {
|
|
132
|
+
console.log('');
|
|
133
|
+
console.log('-- Plan (from structured comment) --');
|
|
134
|
+
const planBody = ctx.planComment.body.replace(/<!--[\\s\\S]*?-->\\n?/, '').trim();
|
|
135
|
+
console.log(planBody.slice(0, 2000));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Summary (if posted)
|
|
139
|
+
if (ctx.summaryComment) {
|
|
140
|
+
console.log('');
|
|
141
|
+
console.log('-- Summary (from structured comment) --');
|
|
142
|
+
const summaryBody = ctx.summaryComment.body.replace(/<!--[\\s\\S]*?-->\\n?/, '').trim();
|
|
143
|
+
console.log(summaryBody.slice(0, 1000));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.log('');
|
|
147
|
+
})().catch(e => {
|
|
148
|
+
console.error('Error assembling context: ' + e.message);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
});
|
|
151
|
+
" 2>/dev/null
|
|
152
|
+
```
|
|
153
|
+
</step>
|
|
154
|
+
|
|
155
|
+
<step name="display">
|
|
156
|
+
**Display context report with banner:**
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
160
|
+
MGW ► CONTEXT FOR #${ISSUE_NUMBER}
|
|
161
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
162
|
+
|
|
163
|
+
${FORMATTED_OUTPUT}
|
|
164
|
+
|
|
165
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
166
|
+
Tip: This is what GSD agents see before planning.
|
|
167
|
+
→ /mgw:run ${ISSUE_NUMBER} — Execute this issue
|
|
168
|
+
→ /mgw:status — Project dashboard
|
|
169
|
+
```
|
|
170
|
+
</step>
|
|
171
|
+
|
|
172
|
+
</process>
|
|
173
|
+
|
|
174
|
+
<success_criteria>
|
|
175
|
+
- [ ] Issue number validated
|
|
176
|
+
- [ ] Issue context assembled from GitHub comments via assembleIssueContext()
|
|
177
|
+
- [ ] Vision fetched via fetchProjectVision() (GitHub Project README first, local fallback)
|
|
178
|
+
- [ ] Output formatted with clear section headers (Vision, Prior Phases, Phase Goal, etc.)
|
|
179
|
+
- [ ] Acceptance criteria extracted from issue body when present
|
|
180
|
+
- [ ] Dependencies shown from labels
|
|
181
|
+
- [ ] Plan and summary comments displayed when available
|
|
182
|
+
- [ ] No state modified
|
|
183
|
+
</success_criteria>
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mgw:handoff
|
|
3
|
+
description: Generate onboarding context for a developer joining the project mid-milestone
|
|
4
|
+
argument-hint: "<developer-name>"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Bash
|
|
7
|
+
- Read
|
|
8
|
+
- Task
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<objective>
|
|
12
|
+
Produce a structured handoff document for a developer joining an MGW project. Assembles
|
|
13
|
+
current project state, milestone progress, active issues, and recent decisions from
|
|
14
|
+
GitHub issue comments into a single briefing.
|
|
15
|
+
|
|
16
|
+
This command is read-only. It does not modify any state.
|
|
17
|
+
</objective>
|
|
18
|
+
|
|
19
|
+
<execution_context>
|
|
20
|
+
@~/.claude/commands/mgw/workflows/state.md
|
|
21
|
+
</execution_context>
|
|
22
|
+
|
|
23
|
+
<process>
|
|
24
|
+
|
|
25
|
+
<step name="validate_input">
|
|
26
|
+
**Validate developer name provided:**
|
|
27
|
+
|
|
28
|
+
Parse $ARGUMENTS for a name. If missing, use "new developer" as default.
|
|
29
|
+
</step>
|
|
30
|
+
|
|
31
|
+
<step name="gather_state">
|
|
32
|
+
**Gather project state:**
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
36
|
+
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
|
|
37
|
+
MGW_DIR="${REPO_ROOT}/.mgw"
|
|
38
|
+
|
|
39
|
+
# Project info
|
|
40
|
+
PROJECT_NAME=$(echo "$REPO" | cut -d'/' -f2)
|
|
41
|
+
|
|
42
|
+
# Active milestone
|
|
43
|
+
MILESTONE_INFO=""
|
|
44
|
+
if [ -f "${MGW_DIR}/project.json" ]; then
|
|
45
|
+
MILESTONE_INFO=$(python3 -c "
|
|
46
|
+
import json
|
|
47
|
+
p = json.load(open('${MGW_DIR}/project.json'))
|
|
48
|
+
ms = p.get('milestones', [])
|
|
49
|
+
active = [m for m in ms if m.get('gsd_state') == 'active']
|
|
50
|
+
if active:
|
|
51
|
+
m = active[0]
|
|
52
|
+
total = len(m.get('issues', []))
|
|
53
|
+
done = len([i for i in m['issues'] if i.get('pipeline_stage') == 'done'])
|
|
54
|
+
print(f\"{m['name']} — {done}/{total} issues complete\")
|
|
55
|
+
else:
|
|
56
|
+
print('No active milestone')
|
|
57
|
+
" 2>/dev/null || echo "Unknown")
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Active issues
|
|
61
|
+
ACTIVE_ISSUES=$(ls ${MGW_DIR}/active/*.json 2>/dev/null | wc -l)
|
|
62
|
+
|
|
63
|
+
# Recent PRs
|
|
64
|
+
RECENT_PRS=$(gh pr list --limit 5 --json number,title,state --jq '.[] | "#\(.number) \(.title) [\(.state)]"' 2>/dev/null || echo "None")
|
|
65
|
+
```
|
|
66
|
+
</step>
|
|
67
|
+
|
|
68
|
+
<step name="assemble_context">
|
|
69
|
+
**Assemble project context from GitHub:**
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Vision/project description
|
|
73
|
+
VISION=$(node -e "
|
|
74
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
75
|
+
ic.buildGSDPromptContext({ includeVision: true })
|
|
76
|
+
.then(ctx => process.stdout.write(ctx));
|
|
77
|
+
" 2>/dev/null || echo "")
|
|
78
|
+
|
|
79
|
+
# Open milestones with issue counts
|
|
80
|
+
MILESTONES=$(gh api repos/${REPO}/milestones --jq '.[] | "- \(.title): \(.open_issues) open, \(.closed_issues) closed"' 2>/dev/null || echo "No milestones")
|
|
81
|
+
```
|
|
82
|
+
</step>
|
|
83
|
+
|
|
84
|
+
<step name="generate_handoff">
|
|
85
|
+
**Generate handoff briefing:**
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
Task(
|
|
89
|
+
prompt="
|
|
90
|
+
Generate a developer onboarding briefing for ${DEVELOPER_NAME} joining project ${PROJECT_NAME}.
|
|
91
|
+
|
|
92
|
+
<project_context>
|
|
93
|
+
Repository: ${REPO}
|
|
94
|
+
Active Milestone: ${MILESTONE_INFO}
|
|
95
|
+
Active Issues in Pipeline: ${ACTIVE_ISSUES}
|
|
96
|
+
Recent PRs:
|
|
97
|
+
${RECENT_PRS}
|
|
98
|
+
|
|
99
|
+
Open Milestones:
|
|
100
|
+
${MILESTONES}
|
|
101
|
+
</project_context>
|
|
102
|
+
|
|
103
|
+
<vision_context>
|
|
104
|
+
${VISION}
|
|
105
|
+
</vision_context>
|
|
106
|
+
|
|
107
|
+
<instructions>
|
|
108
|
+
Create a structured handoff document with these sections:
|
|
109
|
+
|
|
110
|
+
## Project Overview
|
|
111
|
+
- What the project is and its current state
|
|
112
|
+
- Key architectural decisions (from vision context)
|
|
113
|
+
|
|
114
|
+
## Current Milestone
|
|
115
|
+
- What's being built now
|
|
116
|
+
- Progress status
|
|
117
|
+
- Key deliverables remaining
|
|
118
|
+
|
|
119
|
+
## Getting Started
|
|
120
|
+
- How to set up the development environment
|
|
121
|
+
- Key commands: /mgw:status, /mgw:context, /mgw:next, /mgw:issue
|
|
122
|
+
- How context sharing works (structured comments on GitHub issues)
|
|
123
|
+
|
|
124
|
+
## Active Work
|
|
125
|
+
- Issues currently in the pipeline
|
|
126
|
+
- Recent PRs to review
|
|
127
|
+
|
|
128
|
+
## Key Conventions
|
|
129
|
+
- How MGW orchestrates work (issues → triage → plan → execute → PR)
|
|
130
|
+
- How to read structured comments (<!-- mgw:type=... --> headers)
|
|
131
|
+
- How to use /mgw:context <issue> to see what agents see
|
|
132
|
+
|
|
133
|
+
Keep it concise and actionable. This is a working document, not documentation.
|
|
134
|
+
</instructions>
|
|
135
|
+
",
|
|
136
|
+
subagent_type="general-purpose",
|
|
137
|
+
description="Generate handoff for ${DEVELOPER_NAME}"
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
</step>
|
|
141
|
+
|
|
142
|
+
<step name="display">
|
|
143
|
+
**Display handoff briefing:**
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
147
|
+
MGW ► HANDOFF BRIEFING
|
|
148
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
149
|
+
|
|
150
|
+
${HANDOFF_DOCUMENT}
|
|
151
|
+
|
|
152
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
153
|
+
Tip: Share this output or post it as a GitHub Discussion.
|
|
154
|
+
→ /mgw:context <issue> — See context for a specific issue
|
|
155
|
+
→ /mgw:status — Current project dashboard
|
|
156
|
+
→ /mgw:next — Find next unblocked issue
|
|
157
|
+
```
|
|
158
|
+
</step>
|
|
159
|
+
|
|
160
|
+
</process>
|
|
161
|
+
|
|
162
|
+
<success_criteria>
|
|
163
|
+
- [ ] Developer name parsed (or defaulted)
|
|
164
|
+
- [ ] Project state gathered from .mgw/ and GitHub
|
|
165
|
+
- [ ] Vision context assembled via buildGSDPromptContext()
|
|
166
|
+
- [ ] Handoff document generated by task agent
|
|
167
|
+
- [ ] Briefing displayed to user
|
|
168
|
+
- [ ] No state modified
|
|
169
|
+
</success_criteria>
|
package/commands/issue.md
CHANGED
|
@@ -113,6 +113,48 @@ Gather GSD project history for context (if available):
|
|
|
113
113
|
HISTORY=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs history-digest 2>/dev/null || echo "")
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
+
**Gather milestone context for top-down triage (if available):**
|
|
117
|
+
|
|
118
|
+
Primary source: GitHub issue comments (works on any machine):
|
|
119
|
+
```bash
|
|
120
|
+
MILESTONE_CONTEXT=$(node -e "
|
|
121
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
122
|
+
ic.safeContext({ issueNumber: ${ISSUE_NUMBER}, includeVision: true, includePriorSummaries: true })
|
|
123
|
+
.then(ctx => process.stdout.write(ctx));
|
|
124
|
+
" 2>/dev/null || echo "")
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Fallback: local files (backward compat for single-machine workflows):
|
|
128
|
+
```bash
|
|
129
|
+
if [ -z "$MILESTONE_CONTEXT" ] && [ -f "${REPO_ROOT}/.mgw/project.json" ]; then
|
|
130
|
+
MILESTONE_CONTEXT=$(python3 -c "
|
|
131
|
+
import json
|
|
132
|
+
try:
|
|
133
|
+
p = json.load(open('${REPO_ROOT}/.mgw/project.json'))
|
|
134
|
+
for m in p.get('milestones', []):
|
|
135
|
+
for i in m.get('issues', []):
|
|
136
|
+
if i.get('github_number') == ${ISSUE_NUMBER}:
|
|
137
|
+
parts = []
|
|
138
|
+
parts.append(f\"Milestone: {m['name']}\")
|
|
139
|
+
parts.append(f\"Phase {i['phase_number']}: {i['phase_name']}\")
|
|
140
|
+
parts.append(f\"GSD Route: {i.get('gsd_route', 'unknown')}\")
|
|
141
|
+
completed = [x for x in m['issues'] if x.get('pipeline_stage') == 'done']
|
|
142
|
+
if completed:
|
|
143
|
+
parts.append(f\"Completed in milestone: {len(completed)}/{len(m['issues'])} issues\")
|
|
144
|
+
parts.append('Delivered: ' + ', '.join(f\"Phase {x['phase_number']}: {x['phase_name']}\" for x in completed))
|
|
145
|
+
print('\n'.join(parts))
|
|
146
|
+
break
|
|
147
|
+
except Exception as e:
|
|
148
|
+
pass
|
|
149
|
+
" 2>/dev/null || echo "")
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
ROADMAP_CONTEXT=""
|
|
153
|
+
if [ -f ".planning/ROADMAP.md" ]; then
|
|
154
|
+
ROADMAP_CONTEXT=$(head -c 2000 .planning/ROADMAP.md)
|
|
155
|
+
fi
|
|
156
|
+
```
|
|
157
|
+
|
|
116
158
|
Build analysis prompt from issue data and spawn:
|
|
117
159
|
|
|
118
160
|
```
|
|
@@ -136,6 +178,14 @@ Comments: ${comments_summary}
|
|
|
136
178
|
${HISTORY}
|
|
137
179
|
</project_history>
|
|
138
180
|
|
|
181
|
+
<milestone_context>
|
|
182
|
+
${MILESTONE_CONTEXT}
|
|
183
|
+
</milestone_context>
|
|
184
|
+
|
|
185
|
+
<roadmap_context>
|
|
186
|
+
${ROADMAP_CONTEXT}
|
|
187
|
+
</roadmap_context>
|
|
188
|
+
|
|
139
189
|
<analysis_dimensions>
|
|
140
190
|
|
|
141
191
|
1. **Scope:** Search the codebase for files and systems related to this issue.
|
|
@@ -317,6 +367,18 @@ Post comment and apply label:
|
|
|
317
367
|
```bash
|
|
318
368
|
remove_mgw_labels_and_apply ${ISSUE_NUMBER} "mgw:triaged"
|
|
319
369
|
```
|
|
370
|
+
|
|
371
|
+
**Post structured metadata comment (non-blocking):**
|
|
372
|
+
|
|
373
|
+
In addition to the human-readable triage comment above, post a machine-readable
|
|
374
|
+
structured comment so other machines can read triage context from GitHub:
|
|
375
|
+
```bash
|
|
376
|
+
node -e "
|
|
377
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
378
|
+
ic.postPlanningComment(${ISSUE_NUMBER}, 'triage', TRIAGE_REPORT, {})
|
|
379
|
+
.catch(() => {});
|
|
380
|
+
" 2>/dev/null || true
|
|
381
|
+
```
|
|
320
382
|
</step>
|
|
321
383
|
|
|
322
384
|
<step name="present_report">
|
package/commands/milestone.md
CHANGED
|
@@ -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
|
-
|
|
4
|
+
argument-hint: "[milestone-number] [--interactive] [--dry-run]"
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Bash
|
|
7
7
|
- Read
|
|
@@ -23,8 +23,7 @@ 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
|
-
|
|
27
|
-
NM|The `--auto-review` flag runs deep PR review after each issue completes.
|
|
26
|
+
The `--dry-run` flag shows the execution plan without running anything.
|
|
28
27
|
</objective>
|
|
29
28
|
|
|
30
29
|
<execution_context>
|
|
@@ -47,14 +46,12 @@ Flags: --interactive, --dry-run
|
|
|
47
46
|
```bash
|
|
48
47
|
MILESTONE_NUM=""
|
|
49
48
|
INTERACTIVE=false
|
|
50
|
-
|
|
51
|
-
NM|AUTO_REVIEW=false
|
|
49
|
+
DRY_RUN=false
|
|
52
50
|
|
|
53
51
|
for ARG in $ARGUMENTS; do
|
|
54
52
|
case "$ARG" in
|
|
55
53
|
--interactive) INTERACTIVE=true ;;
|
|
56
|
-
|
|
57
|
-
--auto-review) AUTO_REVIEW=true ;;
|
|
54
|
+
--dry-run) DRY_RUN=true ;;
|
|
58
55
|
[0-9]*) MILESTONE_NUM="$ARG" ;;
|
|
59
56
|
esac
|
|
60
57
|
done
|
|
@@ -681,37 +678,7 @@ COMMENTEOF
|
|
|
681
678
|
)
|
|
682
679
|
|
|
683
680
|
gh issue comment ${ISSUE_NUMBER} --body "$PR_READY_BODY" 2>/dev/null || true
|
|
684
|
-
|
|
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
|
|
681
|
+
echo " ✓ #${ISSUE_NUMBER} — PR #${PR_NUMBER} created"
|
|
715
682
|
|
|
716
683
|
else
|
|
717
684
|
# Failure — read failure_class from active issue state, then post failure comment
|
|
@@ -914,7 +881,39 @@ Milestone: ${MILESTONE_NAME}
|
|
|
914
881
|
fi
|
|
915
882
|
```
|
|
916
883
|
|
|
917
|
-
4.
|
|
884
|
+
4. Update Project README with current milestone progress (non-blocking):
|
|
885
|
+
```bash
|
|
886
|
+
node -e "
|
|
887
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
888
|
+
ic.updateProjectReadme()
|
|
889
|
+
.then(ok => { if (ok) console.log(' Project README updated'); })
|
|
890
|
+
.catch(() => {});
|
|
891
|
+
" 2>/dev/null || true
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
5. Post Status Update to Projects v2 board (non-blocking):
|
|
895
|
+
```bash
|
|
896
|
+
BOARD_NODE_ID=$(python3 -c "
|
|
897
|
+
import json
|
|
898
|
+
try:
|
|
899
|
+
p = json.load(open('${MGW_DIR}/project.json'))
|
|
900
|
+
print(p.get('project', {}).get('project_board', {}).get('node_id', ''))
|
|
901
|
+
except: print('')
|
|
902
|
+
" 2>/dev/null || echo "")
|
|
903
|
+
|
|
904
|
+
if [ -n "$BOARD_NODE_ID" ]; then
|
|
905
|
+
MILESTONE_SUMMARY="Milestone ${MILESTONE_NUM} (${MILESTONE_NAME}) complete: ${TOTAL_ISSUES} issues, ${#COMPLETED_ISSUES[@]} PRs created"
|
|
906
|
+
gh api graphql -f query='mutation($projectId: ID!, $body: String!) {
|
|
907
|
+
createProjectV2StatusUpdate(input: {
|
|
908
|
+
projectId: $projectId
|
|
909
|
+
body: $body
|
|
910
|
+
status: ON_TRACK
|
|
911
|
+
}) { statusUpdate { id } }
|
|
912
|
+
}' -f projectId="$BOARD_NODE_ID" -f body="$MILESTONE_SUMMARY" 2>/dev/null || true
|
|
913
|
+
fi
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
6. Advance active milestone pointer in project.json:
|
|
918
917
|
```bash
|
|
919
918
|
node -e "
|
|
920
919
|
const { loadProjectState, resolveActiveMilestoneIndex, writeProjectState } = require('./lib/state.cjs');
|
|
@@ -937,7 +936,7 @@ writeProjectState(state);
|
|
|
937
936
|
"
|
|
938
937
|
```
|
|
939
938
|
|
|
940
|
-
|
|
939
|
+
7. Milestone mapping verification:
|
|
941
940
|
|
|
942
941
|
After advancing to the next milestone, check its GSD linkage using `getGsdState()`
|
|
943
942
|
from `lib/gsd-adapter.cjs` to read current GSD execution state (.planning/STATE.md
|
|
@@ -1028,7 +1027,7 @@ else:
|
|
|
1028
1027
|
esac
|
|
1029
1028
|
```
|
|
1030
1029
|
|
|
1031
|
-
|
|
1030
|
+
8. Display completion banner:
|
|
1032
1031
|
```
|
|
1033
1032
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1034
1033
|
MGW ► MILESTONE ${MILESTONE_NUM} COMPLETE ✓
|
|
@@ -1057,7 +1056,7 @@ Draft release created: ${RELEASE_TAG}
|
|
|
1057
1056
|
───────────────────────────────────────────────────────────────
|
|
1058
1057
|
```
|
|
1059
1058
|
|
|
1060
|
-
|
|
1059
|
+
9. Check if next milestone exists and offer auto-advance (only if no failures in current).
|
|
1061
1060
|
|
|
1062
1061
|
**If some issues failed:**
|
|
1063
1062
|
|
|
@@ -1160,7 +1159,7 @@ Milestone NOT closed. Re-run after resolving remaining failures:
|
|
|
1160
1159
|
/mgw:milestone ${MILESTONE_NUM}
|
|
1161
1160
|
```
|
|
1162
1161
|
|
|
1163
|
-
|
|
1162
|
+
10. Post final results table as GitHub comment on the first issue in the milestone:
|
|
1164
1163
|
```bash
|
|
1165
1164
|
gh issue comment ${FIRST_ISSUE_NUMBER} --body "$FINAL_RESULTS_COMMENT"
|
|
1166
1165
|
```
|
package/commands/project.md
CHANGED
|
@@ -180,6 +180,25 @@ fi
|
|
|
180
180
|
@workflows/create-github-structure.md
|
|
181
181
|
</step>
|
|
182
182
|
|
|
183
|
+
<step name="populate_project_readme">
|
|
184
|
+
**Populate Project README on GitHub Projects v2 board (non-blocking):**
|
|
185
|
+
|
|
186
|
+
After GitHub structure creation, if a board is configured, populate the Project README
|
|
187
|
+
with project vision and milestone overview. This gives developers a landing page
|
|
188
|
+
when they open the board. Uses the shared `updateProjectReadme()` function from
|
|
189
|
+
`lib/issue-context.cjs` — the same function called by `mgw:milestone` and `mgw:sync --full`
|
|
190
|
+
to keep the README current.
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
node -e "
|
|
194
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
195
|
+
ic.updateProjectReadme()
|
|
196
|
+
.then(ok => { if (ok) console.log('Project README populated on board'); })
|
|
197
|
+
.catch(() => {});
|
|
198
|
+
" 2>/dev/null || true
|
|
199
|
+
```
|
|
200
|
+
</step>
|
|
201
|
+
|
|
183
202
|
</process>
|
|
184
203
|
|
|
185
204
|
<success_criteria>
|