bmad-method 6.8.1-next.11 → 6.8.1-next.13
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/package.json +1 -1
- package/src/bmm-skills/4-implementation/bmad-retrospective/SKILL.md +15 -0
- package/src/bmm-skills/4-implementation/bmad-sprint-planning/SKILL.md +20 -1
- package/src/bmm-skills/4-implementation/bmad-sprint-planning/checklist.md +2 -1
- package/src/bmm-skills/4-implementation/bmad-sprint-planning/sprint-status-template.yaml +13 -0
- package/src/bmm-skills/4-implementation/bmad-sprint-status/SKILL.md +13 -0
- package/tools/installer/commands/install.js +3 -0
- package/tools/installer/core/wsl-node-check.js +109 -0
package/package.json
CHANGED
|
@@ -350,6 +350,7 @@ Amelia (Developer): "I found our retrospectives from Epic {{prev_epic_num}}. Let
|
|
|
350
350
|
|
|
351
351
|
**Action Item Follow-Through:**
|
|
352
352
|
- For each action item from Epic {{prev_epic_num}} retro, check if it was completed
|
|
353
|
+
- Cross-check the action_items section in {sprint_status_file} (if present) for Epic {{prev_epic_num}} entries and their current status
|
|
353
354
|
- Look for evidence in current epic's story records
|
|
354
355
|
- Mark each action item: ✅ Completed, ⏳ In Progress, ❌ Not Addressed
|
|
355
356
|
|
|
@@ -1403,6 +1404,19 @@ Amelia (Developer): "See you all when prep work is done. Meeting adjourned!"
|
|
|
1403
1404
|
<action>Find development_status key "epic-{{epic_number}}-retrospective"</action>
|
|
1404
1405
|
<action>Verify current status (typically "optional" or "pending")</action>
|
|
1405
1406
|
<action>Update development_status["epic-{{epic_number}}-retrospective"] = "done"</action>
|
|
1407
|
+
<action>Append each Epic {{epic_number}} action item to the action_items section, creating the section after development_status if missing. One entry per item:</action>
|
|
1408
|
+
|
|
1409
|
+
```yaml
|
|
1410
|
+
action_items:
|
|
1411
|
+
- epic: {{epic_number}}
|
|
1412
|
+
action: "{{action_description}}"
|
|
1413
|
+
owner: "{{owner}}"
|
|
1414
|
+
status: open
|
|
1415
|
+
```
|
|
1416
|
+
|
|
1417
|
+
<action>Quote action and owner values so punctuation (e.g., "#") cannot break YAML parsing</action>
|
|
1418
|
+
|
|
1419
|
+
<action>Update Epic {{prev_epic_num}} action_items entries based on Step 4 follow-through: ✅ Completed → done, ⏳ In Progress → in-progress, ❌ Not Addressed → keep existing status (do not modify)</action>
|
|
1406
1420
|
<action>Update last_updated field to current date</action>
|
|
1407
1421
|
<action>Save file, preserving ALL comments and structure including STATUS DEFINITIONS</action>
|
|
1408
1422
|
|
|
@@ -1412,6 +1426,7 @@ Amelia (Developer): "See you all when prep work is done. Meeting adjourned!"
|
|
|
1412
1426
|
|
|
1413
1427
|
Retrospective key: epic-{{epic_number}}-retrospective
|
|
1414
1428
|
Status: {{previous_status}} → done
|
|
1429
|
+
Action items recorded: {{action_count}}
|
|
1415
1430
|
</output>
|
|
1416
1431
|
</check>
|
|
1417
1432
|
|
|
@@ -151,6 +151,7 @@ development_status:
|
|
|
151
151
|
|
|
152
152
|
- If existing `{status_file}` exists and has more advanced status, preserve it
|
|
153
153
|
- Never downgrade status (e.g., don't change `done` to `ready-for-dev`)
|
|
154
|
+
- If existing `{status_file}` has an `action_items` section, carry it over unchanged
|
|
154
155
|
|
|
155
156
|
**Status Flow Reference:**
|
|
156
157
|
|
|
@@ -194,12 +195,18 @@ development_status:
|
|
|
194
195
|
# - optional: Can be completed but not required
|
|
195
196
|
# - done: Retrospective has been completed
|
|
196
197
|
#
|
|
198
|
+
# Action Item Status:
|
|
199
|
+
# - open: Committed during a retrospective, not yet addressed
|
|
200
|
+
# - in-progress: Actively being worked on
|
|
201
|
+
# - done: Completed
|
|
202
|
+
#
|
|
197
203
|
# WORKFLOW NOTES:
|
|
198
204
|
# ===============
|
|
199
205
|
# - Epic transitions to 'in-progress' automatically when first story is created
|
|
200
206
|
# - Stories can be worked in parallel if team capacity allows
|
|
201
207
|
# - Developer typically creates next story after previous one is 'done' to incorporate learnings
|
|
202
208
|
# - Dev moves story to 'review', then runs code-review (fresh context, different LLM recommended)
|
|
209
|
+
# - Retrospective appends its action items to action_items; sprint-status surfaces open ones
|
|
203
210
|
|
|
204
211
|
generated: { date }
|
|
205
212
|
last_updated: { date }
|
|
@@ -215,6 +222,7 @@ development_status:
|
|
|
215
222
|
<action>Write the complete sprint status YAML to {status_file}</action>
|
|
216
223
|
<action>CRITICAL: Metadata appears TWICE - once as comments (#) for documentation, once as YAML key:value fields for parsing</action>
|
|
217
224
|
<action>Ensure all items are ordered: epic, its stories, its retrospective, next epic...</action>
|
|
225
|
+
<action>If the existing file had an action_items section, write it back unchanged after development_status</action>
|
|
218
226
|
</step>
|
|
219
227
|
|
|
220
228
|
<step n="5" goal="Validate and report">
|
|
@@ -223,7 +231,8 @@ development_status:
|
|
|
223
231
|
- [ ] Every epic in epic files appears in {status_file}
|
|
224
232
|
- [ ] Every story in epic files appears in {status_file}
|
|
225
233
|
- [ ] Every epic has a corresponding retrospective entry
|
|
226
|
-
- [ ] No items in {status_file} that don't exist in epic files
|
|
234
|
+
- [ ] No development_status items in {status_file} that don't exist in epic files
|
|
235
|
+
- [ ] action_items section (if it existed) carried over unchanged
|
|
227
236
|
- [ ] All status values are legal (match state machine definitions)
|
|
228
237
|
- [ ] File is valid YAML syntax
|
|
229
238
|
|
|
@@ -291,6 +300,16 @@ optional ↔ done
|
|
|
291
300
|
- **optional**: Ready to be conducted but not required
|
|
292
301
|
- **done**: Finished
|
|
293
302
|
|
|
303
|
+
**Action Item Status:**
|
|
304
|
+
|
|
305
|
+
```
|
|
306
|
+
open → in-progress → done
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
- **open**: Committed during a retrospective, not yet addressed
|
|
310
|
+
- **in-progress**: Actively being worked on
|
|
311
|
+
- **done**: Completed
|
|
312
|
+
|
|
294
313
|
### Guidelines
|
|
295
314
|
|
|
296
315
|
1. **Epic Activation**: Mark epic as `in-progress` when starting work on its first story
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
- [ ] Every epic found in epic\*.md files appears in sprint-status.yaml
|
|
8
8
|
- [ ] Every story found in epic\*.md files appears in sprint-status.yaml
|
|
9
9
|
- [ ] Every epic has a corresponding retrospective entry
|
|
10
|
-
- [ ] No items in sprint-status.yaml that don't exist in epic files
|
|
10
|
+
- [ ] No development_status items in sprint-status.yaml that don't exist in epic files
|
|
11
|
+
- [ ] action_items section (if it existed) carried over unchanged
|
|
11
12
|
|
|
12
13
|
### Parsing Verification
|
|
13
14
|
|
|
@@ -26,11 +26,17 @@
|
|
|
26
26
|
# - optional: Can be completed but not required
|
|
27
27
|
# - done: Retrospective has been completed
|
|
28
28
|
#
|
|
29
|
+
# Action Item Status:
|
|
30
|
+
# - open: Committed during a retrospective, not yet addressed
|
|
31
|
+
# - in-progress: Actively being worked on
|
|
32
|
+
# - done: Completed
|
|
33
|
+
#
|
|
29
34
|
# WORKFLOW NOTES:
|
|
30
35
|
# ===============
|
|
31
36
|
# - Mark epic as 'in-progress' when starting work on its first story
|
|
32
37
|
# - Developer typically creates next story ONLY after previous one is 'done' to incorporate learnings
|
|
33
38
|
# - Dev moves story to 'review', then Dev runs code-review (fresh context, ideally different LLM)
|
|
39
|
+
# - Retrospective appends its action items to action_items; sprint-status surfaces open ones
|
|
34
40
|
|
|
35
41
|
# EXAMPLE STRUCTURE (your actual epics/stories will replace these):
|
|
36
42
|
|
|
@@ -54,3 +60,10 @@ development_status:
|
|
|
54
60
|
2-2-chat-interface: backlog
|
|
55
61
|
2-3-llm-integration: backlog
|
|
56
62
|
epic-2-retrospective: optional
|
|
63
|
+
|
|
64
|
+
# Action items committed during retrospectives (section created by the retrospective workflow)
|
|
65
|
+
action_items:
|
|
66
|
+
- epic: 1
|
|
67
|
+
action: "Add error-handling review to the code review checklist"
|
|
68
|
+
owner: "Charlie"
|
|
69
|
+
status: open
|
|
@@ -112,12 +112,14 @@ Run `/bmad:bmm:workflows:sprint-planning` to generate it, then rerun sprint-stat
|
|
|
112
112
|
<action>Map legacy epic status "contexted" → "in-progress"</action>
|
|
113
113
|
<action>Count epic statuses: backlog, in-progress, done</action>
|
|
114
114
|
<action>Count retrospective statuses: optional, done</action>
|
|
115
|
+
<action>Parse action_items list if present. Set open_action_items = entries with status "open" or "in-progress"</action>
|
|
115
116
|
|
|
116
117
|
<action>Validate all statuses against known values:</action>
|
|
117
118
|
|
|
118
119
|
- Valid story statuses: backlog, ready-for-dev, in-progress, review, done, drafted (legacy)
|
|
119
120
|
- Valid epic statuses: backlog, in-progress, done, contexted (legacy)
|
|
120
121
|
- Valid retrospective statuses: optional, done
|
|
122
|
+
- Valid action item statuses: open, in-progress, done
|
|
121
123
|
|
|
122
124
|
<check if="any status is unrecognized">
|
|
123
125
|
<output>
|
|
@@ -132,6 +134,7 @@ Run `/bmad:bmm:workflows:sprint-planning` to generate it, then rerun sprint-stat
|
|
|
132
134
|
- Stories: backlog, ready-for-dev, in-progress, review, done
|
|
133
135
|
- Epics: backlog, in-progress, done
|
|
134
136
|
- Retrospectives: optional, done
|
|
137
|
+
- Action items: open, in-progress, done
|
|
135
138
|
</output>
|
|
136
139
|
<ask>How should these be corrected?
|
|
137
140
|
{{#each invalid_entries}}
|
|
@@ -181,6 +184,14 @@ Enter corrections (e.g., "1=in-progress, 2=backlog") or "skip" to continue witho
|
|
|
181
184
|
|
|
182
185
|
**Next Recommendation:** /bmad:bmm:workflows:{{next_workflow_id}} ({{next_story_id}})
|
|
183
186
|
|
|
187
|
+
{{#if open_action_items}}
|
|
188
|
+
**Open Action Items:**
|
|
189
|
+
{{#each open_action_items}}
|
|
190
|
+
|
|
191
|
+
- {{action}} — {{status}} (epic {{epic}}, owner: {{owner}})
|
|
192
|
+
{{/each}}
|
|
193
|
+
{{/if}}
|
|
194
|
+
|
|
184
195
|
{{#if risks}}
|
|
185
196
|
**Risks:**
|
|
186
197
|
{{#each risks}}
|
|
@@ -243,6 +254,7 @@ If the command targets a story, set `story_key={{next_story_id}}` when prompted.
|
|
|
243
254
|
<template-output>epic_backlog = {{epic_backlog}}</template-output>
|
|
244
255
|
<template-output>epic_in_progress = {{epic_in_progress}}</template-output>
|
|
245
256
|
<template-output>epic_done = {{epic_done}}</template-output>
|
|
257
|
+
<template-output>open_action_items = {{open_action_items}}</template-output>
|
|
246
258
|
<template-output>risks = {{risks}}</template-output>
|
|
247
259
|
<action>Return to caller</action>
|
|
248
260
|
</step>
|
|
@@ -283,6 +295,7 @@ If the command targets a story, set `story_key={{next_story_id}}` when prompted.
|
|
|
283
295
|
- Stories: backlog, ready-for-dev, in-progress, review, done (legacy: drafted)
|
|
284
296
|
- Epics: backlog, in-progress, done (legacy: contexted)
|
|
285
297
|
- Retrospectives: optional, done
|
|
298
|
+
- Action items (if present): open, in-progress, done
|
|
286
299
|
<check if="any invalid status found">
|
|
287
300
|
<template-output>is_valid = false</template-output>
|
|
288
301
|
<template-output>error = "Invalid status values: {{invalid_entries}}"</template-output>
|
|
@@ -75,6 +75,9 @@ module.exports = {
|
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
const { checkWindowsNodeFromWsl } = require('../core/wsl-node-check');
|
|
79
|
+
await checkWindowsNodeFromWsl();
|
|
80
|
+
|
|
78
81
|
// Set debug flag as environment variable for all components
|
|
79
82
|
if (options.debug) {
|
|
80
83
|
process.env.BMAD_DEBUG_MANIFEST = 'true';
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const prompts = require('../prompts');
|
|
2
|
+
|
|
3
|
+
const WSL_UNC_PATTERN = /^\\\\wsl(?:\.localhost|\$)?\\/i;
|
|
4
|
+
|
|
5
|
+
function normalizePath(value) {
|
|
6
|
+
return typeof value === 'string' ? value.replaceAll('/', '\\').toLowerCase() : '';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function isLinuxStylePath(value) {
|
|
10
|
+
return (
|
|
11
|
+
typeof value === 'string' &&
|
|
12
|
+
value.startsWith('/') &&
|
|
13
|
+
!value.startsWith('//') &&
|
|
14
|
+
!/^\/[a-z](?:\/|$)/i.test(value) &&
|
|
15
|
+
!/^\/cygdrive\/[a-z](?:\/|$)/i.test(value)
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isWslUncPath(value) {
|
|
20
|
+
return WSL_UNC_PATTERN.test(value || '');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Detect the broken interop case where WSL resolved node/npx to Windows.
|
|
25
|
+
* @param {Object} [runtime]
|
|
26
|
+
* @param {string} [runtime.platform]
|
|
27
|
+
* @param {Object} [runtime.env]
|
|
28
|
+
* @param {string} [runtime.cwd]
|
|
29
|
+
* @param {string} [runtime.execPath]
|
|
30
|
+
* @returns {{isMismatch: boolean, reason: string|null, execPath: string}}
|
|
31
|
+
*/
|
|
32
|
+
function detectWindowsNodeFromWsl(runtime = {}) {
|
|
33
|
+
const platform = runtime.platform || process.platform;
|
|
34
|
+
const env = runtime.env || process.env;
|
|
35
|
+
const cwd = runtime.cwd || safeCwd();
|
|
36
|
+
const execPath = runtime.execPath || process.execPath || '';
|
|
37
|
+
|
|
38
|
+
if (platform !== 'win32') {
|
|
39
|
+
return { isMismatch: false, reason: null, execPath };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (env.WSL_DISTRO_NAME) {
|
|
43
|
+
return { isMismatch: true, reason: 'WSL_DISTRO_NAME is set', execPath };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (env.WSL_INTEROP) {
|
|
47
|
+
return { isMismatch: true, reason: 'WSL_INTEROP is set', execPath };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (isLinuxStylePath(env.PWD)) {
|
|
51
|
+
return { isMismatch: true, reason: 'PWD is a Linux path', execPath };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (isWslUncPath(cwd)) {
|
|
55
|
+
return { isMismatch: true, reason: 'current directory is a WSL UNC path', execPath };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const normalizedExecPath = normalizePath(execPath);
|
|
59
|
+
if (normalizedExecPath.includes('\\wsl$\\') || normalizedExecPath.includes('\\wsl.localhost\\')) {
|
|
60
|
+
return { isMismatch: true, reason: 'Node executable path is under a WSL UNC path', execPath };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return { isMismatch: false, reason: null, execPath };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function safeCwd() {
|
|
67
|
+
try {
|
|
68
|
+
return process.cwd();
|
|
69
|
+
} catch {
|
|
70
|
+
return '';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function formatWindowsNodeFromWslMessage(detection) {
|
|
75
|
+
const lines = [
|
|
76
|
+
'Windows Node.js was launched from a WSL shell.',
|
|
77
|
+
'',
|
|
78
|
+
'This usually means Node.js is not installed inside the WSL distro, so WSL resolved `node`/`npx` to Windows.',
|
|
79
|
+
'The installer cannot safely continue because Linux paths may be interpreted as Windows paths.',
|
|
80
|
+
'',
|
|
81
|
+
'Install Node.js inside WSL, then rerun the same command from the WSL terminal.',
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
if (detection.execPath) {
|
|
85
|
+
lines.push('', `Detected Node executable: ${detection.execPath}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (detection.reason) {
|
|
89
|
+
lines.push(`Detection signal: ${detection.reason}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return lines.join('\n');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function checkWindowsNodeFromWsl() {
|
|
96
|
+
const detection = module.exports.detectWindowsNodeFromWsl();
|
|
97
|
+
if (!detection.isMismatch) {
|
|
98
|
+
return detection;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
await prompts.log.error(formatWindowsNodeFromWslMessage(detection));
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = {
|
|
106
|
+
checkWindowsNodeFromWsl,
|
|
107
|
+
detectWindowsNodeFromWsl,
|
|
108
|
+
formatWindowsNodeFromWslMessage,
|
|
109
|
+
};
|