bmad-method 6.0.2 → 6.0.4
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/.claude/skills/bmad-os-root-cause-analysis/SKILL.md +12 -0
- package/.claude/skills/bmad-os-root-cause-analysis/prompts/instructions.md +74 -0
- package/.github/ISSUE_TEMPLATE/config.yaml +1 -1
- package/.github/ISSUE_TEMPLATE/documentation.yaml +1 -1
- package/CHANGELOG.md +40 -0
- package/README.md +8 -8
- package/docs/index.md +1 -1
- package/package.json +1 -1
- package/src/bmm/agents/qa.agent.yaml +1 -1
- package/src/bmm/module-help.csv +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/workflow.md +1 -1
- package/src/bmm/workflows/1-analysis/research/workflow-domain-research.md +1 -1
- package/src/bmm/workflows/1-analysis/research/workflow-market-research.md +1 -1
- package/src/bmm/workflows/1-analysis/research/workflow-technical-research.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md +1 -1
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +1 -1
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-architecture/workflow.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md +1 -1
- package/src/bmm/workflows/4-implementation/code-review/workflow.yaml +1 -1
- package/src/bmm/workflows/4-implementation/correct-course/workflow.yaml +1 -1
- package/src/bmm/workflows/4-implementation/create-story/workflow.yaml +1 -1
- package/src/bmm/workflows/4-implementation/dev-story/workflow.yaml +1 -1
- package/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +1 -1
- package/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +1 -1
- package/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml +1 -1
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +1 -1
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +1 -1
- package/src/bmm/workflows/document-project/workflow.yaml +1 -1
- package/src/bmm/workflows/generate-project-context/workflow.md +1 -1
- package/src/bmm/workflows/qa-generate-e2e-tests/workflow.yaml +2 -2
- package/src/core/module-help.csv +1 -0
- package/src/core/tasks/editorial-review-prose.xml +1 -1
- package/src/core/tasks/editorial-review-structure.xml +1 -1
- package/src/core/tasks/help.md +1 -1
- package/src/core/tasks/index-docs.xml +1 -1
- package/src/core/tasks/review-adversarial-general.xml +1 -1
- package/src/core/tasks/review-edge-case-hunter.xml +63 -0
- package/src/core/tasks/shard-doc.xml +1 -1
- package/src/core/workflows/advanced-elicitation/workflow.xml +1 -1
- package/src/core/workflows/brainstorming/steps/step-01-session-setup.md +31 -18
- package/src/core/workflows/brainstorming/steps/step-01b-continue.md +1 -1
- package/src/core/workflows/brainstorming/steps/step-03-technique-execution.md +2 -2
- package/src/core/workflows/brainstorming/steps/step-04-idea-organization.md +2 -2
- package/src/core/workflows/brainstorming/workflow.md +4 -2
- package/src/core/workflows/party-mode/workflow.md +1 -1
- package/test/test-installation-components.js +1 -1
- package/tools/cli/installers/install-messages.yaml +1 -1
- package/tools/cli/installers/lib/core/manifest-generator.js +4 -6
- package/tools/cli/installers/lib/ide/_config-driven.js +80 -5
- package/tools/cli/installers/lib/ide/manager.js +3 -1
- package/tools/cli/installers/lib/ide/platform-codes.yaml +11 -2
- package/tools/cli/installers/lib/ide/templates/agent-command-template.md +1 -1
- package/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md +3 -3
- package/tools/cli/installers/lib/ide/templates/combined/default-workflow.md +1 -1
- package/tools/cli/installers/lib/ide/templates/combined/gemini-workflow-yaml.toml +1 -1
- package/tools/cli/installers/lib/ide/templates/combined/gemini-workflow.toml +1 -1
- package/tools/cli/installers/lib/ide/templates/combined/opencode-agent.md +1 -1
- package/tools/cli/installers/lib/ide/templates/combined/opencode-task.md +0 -1
- package/tools/cli/installers/lib/ide/templates/combined/opencode-tool.md +0 -1
- package/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md +0 -1
- package/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md +0 -1
- package/tools/cli/installers/lib/ide/templates/workflow-command-template.md +2 -2
- package/tools/cli/installers/lib/ide/templates/workflow-commander.md +1 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<!-- if possible, run this in a separate subagent or process with read access to the project,
|
|
2
|
+
but no context except the content to review -->
|
|
3
|
+
|
|
4
|
+
<task id="_bmad/core/tasks/review-edge-case-hunter.xml" name="Edge Case Hunter Review"
|
|
5
|
+
description="Walk every branching path and boundary condition in content, report only unhandled edge cases. Orthogonal to adversarial review - method-driven not attitude-driven.">
|
|
6
|
+
<objective>You are a pure path tracer. Never comment on whether code is good or bad; only list missing handling.
|
|
7
|
+
When a diff is provided, scan only the diff hunks and list boundaries that are directly reachable from the changed lines and lack an explicit guard in the diff.
|
|
8
|
+
When no diff is provided (full file or function), treat the entire provided content as the scope.
|
|
9
|
+
Ignore the rest of the codebase unless the provided content explicitly references external functions.</objective>
|
|
10
|
+
|
|
11
|
+
<inputs>
|
|
12
|
+
<input name="content" desc="Content to review - diff, full file, or function" />
|
|
13
|
+
<input name="also_consider" required="false"
|
|
14
|
+
desc="Optional areas to keep in mind during review alongside normal edge-case analysis" />
|
|
15
|
+
</inputs>
|
|
16
|
+
|
|
17
|
+
<output-format>Return ONLY a valid JSON array of objects. Each object must contain exactly these four fields and nothing else:
|
|
18
|
+
{
|
|
19
|
+
"location": "file:line",
|
|
20
|
+
"trigger_condition": "one-line description (max 15 words)",
|
|
21
|
+
"guard_snippet": "minimal code sketch that closes the gap",
|
|
22
|
+
"potential_consequence": "what could actually go wrong (max 15 words)"
|
|
23
|
+
}
|
|
24
|
+
No extra text, no explanations, no markdown wrapping.</output-format>
|
|
25
|
+
|
|
26
|
+
<llm critical="true">
|
|
27
|
+
<i>MANDATORY: Execute ALL steps in the flow section IN EXACT ORDER</i>
|
|
28
|
+
<i>DO NOT skip steps or change the sequence</i>
|
|
29
|
+
<i>HALT immediately when halt-conditions are met</i>
|
|
30
|
+
<i>Each action xml tag within step xml tag is a REQUIRED action to complete that step</i>
|
|
31
|
+
|
|
32
|
+
<i>Your method is exhaustive path enumeration — mechanically walk every branch, not hunt by intuition</i>
|
|
33
|
+
<i>Trace each branching path: conditionals, switches, early returns, guard clauses, loops, error handlers</i>
|
|
34
|
+
<i>Trace each boundary condition: null, undefined, empty, zero, negative, overflow, max-length, type coercion, concurrency, timing</i>
|
|
35
|
+
<i>Report ONLY paths and conditions that lack handling — discard handled ones silently</i>
|
|
36
|
+
<i>Do NOT editorialize or add filler — findings only</i>
|
|
37
|
+
</llm>
|
|
38
|
+
|
|
39
|
+
<flow>
|
|
40
|
+
<step n="1" title="Receive Content">
|
|
41
|
+
<action>Load the content to review from provided input or context</action>
|
|
42
|
+
<action>If content to review is empty, ask for clarification and abort task</action>
|
|
43
|
+
<action>Identify content type (diff, full file, or function) to determine scope rules</action>
|
|
44
|
+
</step>
|
|
45
|
+
|
|
46
|
+
<step n="2" title="Exhaustive Path Analysis" critical="true">
|
|
47
|
+
<mandate>Walk every branching path and boundary condition within scope - report only unhandled ones</mandate>
|
|
48
|
+
<action>If also_consider input was provided, incorporate those areas into the analysis</action>
|
|
49
|
+
<action>Enumerate all branching paths and boundary conditions within scope: conditionals, switches, early returns, guard clauses, loops, error handlers, null/empty states, overflow, type edges, concurrency, timing</action>
|
|
50
|
+
<action>For each path: determine whether the content handles it</action>
|
|
51
|
+
<action>Collect only the unhandled paths as findings - discard handled ones silently</action>
|
|
52
|
+
</step>
|
|
53
|
+
|
|
54
|
+
<step n="3" title="Present Findings">
|
|
55
|
+
<action>Output findings as a JSON array following the output-format specification exactly</action>
|
|
56
|
+
</step>
|
|
57
|
+
</flow>
|
|
58
|
+
|
|
59
|
+
<halt-conditions>
|
|
60
|
+
<condition>HALT if content is empty or unreadable</condition>
|
|
61
|
+
</halt-conditions>
|
|
62
|
+
|
|
63
|
+
</task>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<task id="_bmad/core/tasks/shard-doc" name="Shard Document"
|
|
2
|
-
description="Splits large markdown documents into smaller, organized files based on level 2 (default) sections. Use if the user says
|
|
2
|
+
description="Splits large markdown documents into smaller, organized files based on level 2 (default) sections. Use if the user says perform shard document">
|
|
3
3
|
<objective>Split large markdown documents into smaller, organized files based on level 2 sections using @kayvan/markdown-tree-parser tool</objective>
|
|
4
4
|
|
|
5
5
|
<llm critical="true">
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<task id="_bmad/core/workflows/advanced-elicitation/workflow.xml" name="Advanced Elicitation"
|
|
2
|
-
description="Push the LLM to reconsider refine and improve its recent output. Use when the user asks for
|
|
2
|
+
description="Push the LLM to reconsider refine and improve its recent output. Use when the user asks for advanced elicitation"
|
|
3
3
|
methods="{project-root}/_bmad/core/workflows/advanced-elicitation/methods.csv"
|
|
4
4
|
agent-party="{project-root}/_bmad/_config/agent-manifest.csv">
|
|
5
5
|
<llm critical="true">
|
|
@@ -29,23 +29,30 @@ Initialize the brainstorming workflow by detecting continuation state and settin
|
|
|
29
29
|
|
|
30
30
|
## INITIALIZATION SEQUENCE:
|
|
31
31
|
|
|
32
|
-
### 1. Check for Existing
|
|
32
|
+
### 1. Check for Existing Sessions
|
|
33
33
|
|
|
34
|
-
First, check
|
|
34
|
+
First, check the brainstorming sessions folder for existing sessions:
|
|
35
35
|
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
- If
|
|
36
|
+
- List all files in `{output_folder}/brainstorming/`
|
|
37
|
+
- **DO NOT read any file contents** - only list filenames
|
|
38
|
+
- If files exist, identify the most recent by date/time in the filename
|
|
39
|
+
- If no files exist, this is a fresh workflow
|
|
39
40
|
|
|
40
|
-
### 2. Handle
|
|
41
|
+
### 2. Handle Existing Sessions (If Files Found)
|
|
41
42
|
|
|
42
|
-
If
|
|
43
|
+
If existing session files are found:
|
|
43
44
|
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
|
|
45
|
+
- Display the most recent session filename (do NOT read its content)
|
|
46
|
+
- Ask the user: "Found existing session: `[filename]`. Would you like to:
|
|
47
|
+
**[1]** Continue this session
|
|
48
|
+
**[2]** Start a new session
|
|
49
|
+
**[3]** See all existing sessions"
|
|
47
50
|
|
|
48
|
-
|
|
51
|
+
- If user selects **[1]** (continue): Set `{brainstorming_session_output_file}` to that file path and load `./step-01b-continue.md`
|
|
52
|
+
- If user selects **[2]** (new): Generate new filename with current date/time and proceed to step 3
|
|
53
|
+
- If user selects **[3]** (see all): List all session filenames and ask which to continue or if new
|
|
54
|
+
|
|
55
|
+
### 3. Fresh Workflow Setup (If No Files or User Chooses New)
|
|
49
56
|
|
|
50
57
|
If no document exists or no `stepsCompleted` in frontmatter:
|
|
51
58
|
|
|
@@ -55,10 +62,10 @@ Create the brainstorming session document:
|
|
|
55
62
|
|
|
56
63
|
```bash
|
|
57
64
|
# Create directory if needed
|
|
58
|
-
mkdir -p "$(dirname "{
|
|
65
|
+
mkdir -p "$(dirname "{brainstorming_session_output_file}")"
|
|
59
66
|
|
|
60
67
|
# Initialize from template
|
|
61
|
-
cp "{template_path}" "{
|
|
68
|
+
cp "{template_path}" "{brainstorming_session_output_file}"
|
|
62
69
|
```
|
|
63
70
|
|
|
64
71
|
#### B. Context File Check and Loading
|
|
@@ -134,7 +141,7 @@ _[Content based on conversation about session parameters and facilitator approac
|
|
|
134
141
|
|
|
135
142
|
## APPEND TO DOCUMENT:
|
|
136
143
|
|
|
137
|
-
When user selects approach, append the session overview content directly to `{
|
|
144
|
+
When user selects approach, append the session overview content directly to `{brainstorming_session_output_file}` using the structure from above.
|
|
138
145
|
|
|
139
146
|
### E. Continue to Technique Selection
|
|
140
147
|
|
|
@@ -152,7 +159,7 @@ Which approach appeals to you most? (Enter 1-4)"
|
|
|
152
159
|
|
|
153
160
|
#### When user selects approach number:
|
|
154
161
|
|
|
155
|
-
- **Append initial session overview to `{
|
|
162
|
+
- **Append initial session overview to `{brainstorming_session_output_file}`**
|
|
156
163
|
- **Update frontmatter:** `stepsCompleted: [1]`, `selected_approach: '[selected approach]'`
|
|
157
164
|
- **Load the appropriate step-02 file** based on selection
|
|
158
165
|
|
|
@@ -167,7 +174,9 @@ After user selects approach number:
|
|
|
167
174
|
|
|
168
175
|
## SUCCESS METRICS:
|
|
169
176
|
|
|
170
|
-
✅ Existing
|
|
177
|
+
✅ Existing sessions detected without reading file contents
|
|
178
|
+
✅ User prompted to continue existing session or start new
|
|
179
|
+
✅ Correct session file selected for continuation
|
|
171
180
|
✅ Fresh workflow initialized with correct document structure
|
|
172
181
|
✅ Session context gathered and understood clearly
|
|
173
182
|
✅ User's approach selection captured and routed correctly
|
|
@@ -176,7 +185,9 @@ After user selects approach number:
|
|
|
176
185
|
|
|
177
186
|
## FAILURE MODES:
|
|
178
187
|
|
|
179
|
-
❌
|
|
188
|
+
❌ Reading file contents during session detection (wastes context)
|
|
189
|
+
❌ Not asking user before continuing existing session
|
|
190
|
+
❌ Not properly routing user's continue/new session selection
|
|
180
191
|
❌ Missing continuation detection leading to duplicate work
|
|
181
192
|
❌ Insufficient session context gathering
|
|
182
193
|
❌ Not properly routing user's approach selection
|
|
@@ -184,7 +195,9 @@ After user selects approach number:
|
|
|
184
195
|
|
|
185
196
|
## SESSION SETUP PROTOCOLS:
|
|
186
197
|
|
|
187
|
-
- Always
|
|
198
|
+
- Always list sessions folder WITHOUT reading file contents
|
|
199
|
+
- Ask user before continuing any existing session
|
|
200
|
+
- Only load continue step after user confirms
|
|
188
201
|
- Load brain techniques CSV only when needed for technique presentation
|
|
189
202
|
- Use collaborative facilitation language throughout
|
|
190
203
|
- Maintain psychological safety for creative exploration
|
|
@@ -35,7 +35,7 @@ Load existing document and analyze current state:
|
|
|
35
35
|
|
|
36
36
|
**Document Analysis:**
|
|
37
37
|
|
|
38
|
-
- Read existing `{
|
|
38
|
+
- Read existing `{brainstorming_session_output_file}`
|
|
39
39
|
- Examine frontmatter for `stepsCompleted`, `session_topic`, `session_goals`
|
|
40
40
|
- Review content to understand session progress and outcomes
|
|
41
41
|
- Identify current stage and next logical steps
|
|
@@ -296,7 +296,7 @@ After final technique element:
|
|
|
296
296
|
|
|
297
297
|
#### If 'C' (Move to organization):
|
|
298
298
|
|
|
299
|
-
- **Append the technique execution content to `{
|
|
299
|
+
- **Append the technique execution content to `{brainstorming_session_output_file}`**
|
|
300
300
|
- **Update frontmatter:** `stepsCompleted: [1, 2, 3]`
|
|
301
301
|
- **Load:** `./step-04-idea-organization.md`
|
|
302
302
|
|
|
@@ -356,7 +356,7 @@ _[Short narrative describing the user and AI collaboration journey - what made t
|
|
|
356
356
|
|
|
357
357
|
## APPEND TO DOCUMENT:
|
|
358
358
|
|
|
359
|
-
When user selects 'C', append the content directly to `{
|
|
359
|
+
When user selects 'C', append the content directly to `{brainstorming_session_output_file}` using the structure from above.
|
|
360
360
|
|
|
361
361
|
## SUCCESS METRICS:
|
|
362
362
|
|
|
@@ -253,14 +253,14 @@ Provide final session wrap-up and forward guidance:
|
|
|
253
253
|
|
|
254
254
|
#### If [C] Complete:
|
|
255
255
|
|
|
256
|
-
- **Append the final session content to `{
|
|
256
|
+
- **Append the final session content to `{brainstorming_session_output_file}`**
|
|
257
257
|
- Update frontmatter: `stepsCompleted: [1, 2, 3, 4]`
|
|
258
258
|
- Set `session_active: false` and `workflow_completed: true`
|
|
259
259
|
- Complete workflow with positive closure message
|
|
260
260
|
|
|
261
261
|
## APPEND TO DOCUMENT:
|
|
262
262
|
|
|
263
|
-
When user selects 'C', append the content directly to `{
|
|
263
|
+
When user selects 'C', append the content directly to `{brainstorming_session_output_file}` using the structure from step 7.
|
|
264
264
|
|
|
265
265
|
## SUCCESS METRICS:
|
|
266
266
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: brainstorming
|
|
3
|
-
description:
|
|
3
|
+
description: 'Facilitate interactive brainstorming sessions using diverse creative techniques and ideation methods. Use when the user says help me brainstorm or help me ideate.'
|
|
4
4
|
context_file: '' # Optional context file path for project-specific guidance
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -45,7 +45,9 @@ Load config from `{project-root}/_bmad/core/config.yaml` and resolve:
|
|
|
45
45
|
- `installed_path` = `{project-root}/_bmad/core/workflows/brainstorming`
|
|
46
46
|
- `template_path` = `{installed_path}/template.md`
|
|
47
47
|
- `brain_techniques_path` = `{installed_path}/brain-methods.csv`
|
|
48
|
-
- `
|
|
48
|
+
- `brainstorming_session_output_file` = `{output_folder}/brainstorming/brainstorming-session-{{date}}-{{time}}.md` (evaluated once at workflow start)
|
|
49
|
+
|
|
50
|
+
All steps MUST reference `{brainstorming_session_output_file}` instead of the full path pattern.
|
|
49
51
|
- `context_file` = Optional context file path from workflow invocation for project-specific guidance
|
|
50
52
|
- `advancedElicitationTask` = `{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml`
|
|
51
53
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: party-mode
|
|
3
|
-
description:
|
|
3
|
+
description: 'Orchestrates group discussions between all installed BMAD agents, enabling natural multi-agent conversations. Use when user requests party mode.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Party Mode Workflow
|
|
@@ -173,7 +173,7 @@ async function runTests() {
|
|
|
173
173
|
|
|
174
174
|
assert(compiled.includes('QA Engineer'), 'QA agent compilation includes agent title');
|
|
175
175
|
|
|
176
|
-
assert(compiled.includes('qa
|
|
176
|
+
assert(compiled.includes('qa-generate-e2e-tests'), 'QA agent menu includes automate workflow');
|
|
177
177
|
|
|
178
178
|
// Cleanup
|
|
179
179
|
await fs.remove(tempOutput);
|
|
@@ -12,7 +12,7 @@ startMessage: |
|
|
|
12
12
|
- Select and install modules during setup - customize your experience
|
|
13
13
|
- New BMad Method for Agile AI-Driven Development (the evolution of V4)
|
|
14
14
|
- Exciting new modules available during installation, with community modules coming soon
|
|
15
|
-
- Documentation: docs.bmad-method.
|
|
15
|
+
- Documentation: https://docs.bmad-method.org
|
|
16
16
|
|
|
17
17
|
🌟 BMad is 100% free and open source.
|
|
18
18
|
- No gated Discord. No paywalls. No gated content.
|
|
@@ -24,16 +24,14 @@ class ManifestGenerator {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* Clean text for CSV output by normalizing whitespace
|
|
27
|
+
* Clean text for CSV output by normalizing whitespace.
|
|
28
|
+
* Note: Quote escaping is handled by escapeCsv() at write time.
|
|
28
29
|
* @param {string} text - Text to clean
|
|
29
|
-
* @returns {string} Cleaned text
|
|
30
|
+
* @returns {string} Cleaned text
|
|
30
31
|
*/
|
|
31
32
|
cleanForCSV(text) {
|
|
32
33
|
if (!text) return '';
|
|
33
|
-
return text
|
|
34
|
-
.trim()
|
|
35
|
-
.replaceAll(/\s+/g, ' ') // Normalize all whitespace (including newlines) to single space
|
|
36
|
-
.replaceAll('"', '""'); // Escape quotes for CSV
|
|
34
|
+
return text.trim().replaceAll(/\s+/g, ' '); // Normalize all whitespace (including newlines) to single space
|
|
37
35
|
}
|
|
38
36
|
|
|
39
37
|
/**
|
|
@@ -34,6 +34,25 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
|
|
|
34
34
|
* @returns {Promise<Object>} Setup result
|
|
35
35
|
*/
|
|
36
36
|
async setup(projectDir, bmadDir, options = {}) {
|
|
37
|
+
// Check for BMAD files in ancestor directories that would cause duplicates
|
|
38
|
+
if (this.installerConfig?.ancestor_conflict_check) {
|
|
39
|
+
const conflict = await this.findAncestorConflict(projectDir);
|
|
40
|
+
if (conflict) {
|
|
41
|
+
await prompts.log.error(
|
|
42
|
+
`Found existing BMAD commands in ancestor installation: ${conflict}\n` +
|
|
43
|
+
` ${this.name} inherits commands from parent directories, so this would cause duplicates.\n` +
|
|
44
|
+
` Please remove the BMAD files from that directory first:\n` +
|
|
45
|
+
` rm -rf "${conflict}"/bmad*`,
|
|
46
|
+
);
|
|
47
|
+
return {
|
|
48
|
+
success: false,
|
|
49
|
+
reason: 'ancestor-conflict',
|
|
50
|
+
error: `Ancestor conflict: ${conflict}`,
|
|
51
|
+
conflictDir: conflict,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
37
56
|
if (!options.silent) await prompts.log.info(`Setting up ${this.name}...`);
|
|
38
57
|
|
|
39
58
|
// Clean up any old BMAD installation first
|
|
@@ -453,6 +472,15 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
|
|
|
453
472
|
* @param {string} projectDir - Project directory
|
|
454
473
|
*/
|
|
455
474
|
async cleanup(projectDir, options = {}) {
|
|
475
|
+
// Migrate legacy target directories (e.g. .opencode/agent → .opencode/agents)
|
|
476
|
+
if (this.installerConfig?.legacy_targets) {
|
|
477
|
+
if (!options.silent) await prompts.log.message(' Migrating legacy directories...');
|
|
478
|
+
for (const legacyDir of this.installerConfig.legacy_targets) {
|
|
479
|
+
await this.cleanupTarget(projectDir, legacyDir, options);
|
|
480
|
+
await this.removeEmptyParents(projectDir, legacyDir);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
456
484
|
// Clean all target directories
|
|
457
485
|
if (this.installerConfig?.targets) {
|
|
458
486
|
const parentDirs = new Set();
|
|
@@ -532,24 +560,71 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
|
|
|
532
560
|
}
|
|
533
561
|
}
|
|
534
562
|
/**
|
|
535
|
-
*
|
|
563
|
+
* Check ancestor directories for existing BMAD files in the same target_dir.
|
|
564
|
+
* IDEs like Claude Code inherit commands from parent directories, so an existing
|
|
565
|
+
* installation in an ancestor would cause duplicate commands.
|
|
566
|
+
* @param {string} projectDir - Project directory being installed to
|
|
567
|
+
* @returns {Promise<string|null>} Path to conflicting directory, or null if clean
|
|
568
|
+
*/
|
|
569
|
+
async findAncestorConflict(projectDir) {
|
|
570
|
+
const targetDir = this.installerConfig?.target_dir;
|
|
571
|
+
if (!targetDir) return null;
|
|
572
|
+
|
|
573
|
+
const resolvedProject = await fs.realpath(path.resolve(projectDir));
|
|
574
|
+
let current = path.dirname(resolvedProject);
|
|
575
|
+
const root = path.parse(current).root;
|
|
576
|
+
|
|
577
|
+
while (current !== root && current.length > root.length) {
|
|
578
|
+
const candidatePath = path.join(current, targetDir);
|
|
579
|
+
try {
|
|
580
|
+
if (await fs.pathExists(candidatePath)) {
|
|
581
|
+
const entries = await fs.readdir(candidatePath);
|
|
582
|
+
const hasBmad = entries.some((e) => typeof e === 'string' && e.toLowerCase().startsWith('bmad'));
|
|
583
|
+
if (hasBmad) {
|
|
584
|
+
return candidatePath;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
} catch {
|
|
588
|
+
// Can't read directory — skip
|
|
589
|
+
}
|
|
590
|
+
current = path.dirname(current);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
return null;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Walk up ancestor directories from relativeDir toward projectDir, removing each if empty
|
|
536
598
|
* Stops at projectDir boundary — never removes projectDir itself
|
|
537
599
|
* @param {string} projectDir - Project root (boundary)
|
|
538
600
|
* @param {string} relativeDir - Relative directory to start from
|
|
539
601
|
*/
|
|
540
602
|
async removeEmptyParents(projectDir, relativeDir) {
|
|
603
|
+
const resolvedProject = path.resolve(projectDir);
|
|
541
604
|
let current = relativeDir;
|
|
542
605
|
let last = null;
|
|
543
606
|
while (current && current !== '.' && current !== last) {
|
|
544
607
|
last = current;
|
|
545
|
-
const fullPath = path.
|
|
608
|
+
const fullPath = path.resolve(projectDir, current);
|
|
609
|
+
// Boundary guard: never traverse outside projectDir
|
|
610
|
+
if (!fullPath.startsWith(resolvedProject + path.sep) && fullPath !== resolvedProject) break;
|
|
546
611
|
try {
|
|
547
|
-
if (!(await fs.pathExists(fullPath)))
|
|
612
|
+
if (!(await fs.pathExists(fullPath))) {
|
|
613
|
+
// Dir already gone — advance current; last is reset at top of next iteration
|
|
614
|
+
current = path.dirname(current);
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
548
617
|
const remaining = await fs.readdir(fullPath);
|
|
549
618
|
if (remaining.length > 0) break;
|
|
550
619
|
await fs.rmdir(fullPath);
|
|
551
|
-
} catch {
|
|
552
|
-
|
|
620
|
+
} catch (error) {
|
|
621
|
+
// ENOTEMPTY: TOCTOU race (file added between readdir and rmdir) — skip level, continue upward
|
|
622
|
+
// ENOENT: dir removed by another process between pathExists and rmdir — skip level, continue upward
|
|
623
|
+
if (error.code === 'ENOTEMPTY' || error.code === 'ENOENT') {
|
|
624
|
+
current = path.dirname(current);
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
break; // fatal error (e.g. EACCES) — stop upward walk
|
|
553
628
|
}
|
|
554
629
|
current = path.dirname(current);
|
|
555
630
|
}
|
|
@@ -206,7 +206,9 @@ class IdeManager {
|
|
|
206
206
|
if (handlerResult.tools > 0) parts.push(`${handlerResult.tools} tools`);
|
|
207
207
|
detail = parts.join(', ');
|
|
208
208
|
}
|
|
209
|
-
|
|
209
|
+
// Propagate handler's success status (default true for backward compat)
|
|
210
|
+
const success = handlerResult?.success !== false;
|
|
211
|
+
return { success, ide: ideName, detail, error: handlerResult?.error, handlerResult };
|
|
210
212
|
} catch (error) {
|
|
211
213
|
await prompts.log.error(`Failed to setup ${ideName}: ${error.message}`);
|
|
212
214
|
return { success: false, ide: ideName, error: error.message };
|
|
@@ -40,6 +40,7 @@ platforms:
|
|
|
40
40
|
installer:
|
|
41
41
|
target_dir: .claude/commands
|
|
42
42
|
template_type: default
|
|
43
|
+
ancestor_conflict_check: true
|
|
43
44
|
|
|
44
45
|
cline:
|
|
45
46
|
name: "Cline"
|
|
@@ -131,11 +132,14 @@ platforms:
|
|
|
131
132
|
category: ide
|
|
132
133
|
description: "OpenCode terminal coding assistant"
|
|
133
134
|
installer:
|
|
135
|
+
legacy_targets:
|
|
136
|
+
- .opencode/agent
|
|
137
|
+
- .opencode/command
|
|
134
138
|
targets:
|
|
135
|
-
- target_dir: .opencode/
|
|
139
|
+
- target_dir: .opencode/agents
|
|
136
140
|
template_type: opencode
|
|
137
141
|
artifact_types: [agents]
|
|
138
|
-
- target_dir: .opencode/
|
|
142
|
+
- target_dir: .opencode/commands
|
|
139
143
|
template_type: opencode
|
|
140
144
|
artifact_types: [workflows, tasks, tools]
|
|
141
145
|
|
|
@@ -191,12 +195,17 @@ platforms:
|
|
|
191
195
|
# template_type: string # Default template type to use
|
|
192
196
|
# header_template: string (optional) # Override for header/frontmatter template
|
|
193
197
|
# body_template: string (optional) # Override for body/content template
|
|
198
|
+
# legacy_targets: array (optional) # Old target dirs to clean up on reinstall (migration)
|
|
199
|
+
# - string # Relative path, e.g. .opencode/agent
|
|
194
200
|
# targets: array (optional) # For multi-target installations
|
|
195
201
|
# - target_dir: string
|
|
196
202
|
# template_type: string
|
|
197
203
|
# artifact_types: [agents, workflows, tasks, tools]
|
|
198
204
|
# artifact_types: array (optional) # Filter which artifacts to install (default: all)
|
|
199
205
|
# skip_existing: boolean (optional) # Skip files that already exist (default: false)
|
|
206
|
+
# ancestor_conflict_check: boolean (optional) # Refuse install when ancestor dir has BMAD files
|
|
207
|
+
# # in the same target_dir (for IDEs that inherit
|
|
208
|
+
# # commands from parent directories)
|
|
200
209
|
|
|
201
210
|
# ============================================================================
|
|
202
211
|
# Platform Categories
|
|
@@ -6,7 +6,7 @@ description: '{{description}}'
|
|
|
6
6
|
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
|
|
7
7
|
|
|
8
8
|
<agent-activation CRITICAL="TRUE">
|
|
9
|
-
1. LOAD the FULL agent file from
|
|
9
|
+
1. LOAD the FULL agent file from {project-root}/_bmad/{{module}}/agents/{{path}}
|
|
10
10
|
2. READ its entire contents - this contains the complete agent persona, menu, and instructions
|
|
11
11
|
3. Execute ALL activation steps exactly as written in the agent file
|
|
12
12
|
4. Follow the agent's persona and menu system precisely
|
|
@@ -6,9 +6,9 @@ description: '{{description}}'
|
|
|
6
6
|
IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded:
|
|
7
7
|
|
|
8
8
|
<steps CRITICAL="TRUE">
|
|
9
|
-
1. Always LOAD the FULL
|
|
10
|
-
2. READ its entire contents - this is the CORE OS for EXECUTING the specific workflow-config
|
|
11
|
-
3. Pass the yaml path
|
|
9
|
+
1. Always LOAD the FULL {project-root}/{{bmadFolderName}}/core/tasks/workflow.xml
|
|
10
|
+
2. READ its entire contents - this is the CORE OS for EXECUTING the specific workflow-config {project-root}/{{bmadFolderName}}/{{path}}
|
|
11
|
+
3. Pass the yaml path {project-root}/{{bmadFolderName}}/{{path}} as 'workflow-config' parameter to the workflow.xml instructions
|
|
12
12
|
4. Follow workflow.xml instructions EXACTLY as written to process and follow the specific workflow config and its instructions
|
|
13
13
|
5. Save outputs after EACH section when generating any documents from templates
|
|
14
14
|
</steps>
|
|
@@ -3,4 +3,4 @@ name: '{{name}}'
|
|
|
3
3
|
description: '{{description}}'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL
|
|
6
|
+
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL {project-root}/{{bmadFolderName}}/{{path}}, READ its entire contents and follow its directions exactly!
|
|
@@ -5,8 +5,8 @@ description: '{{description}}'
|
|
|
5
5
|
IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded:
|
|
6
6
|
|
|
7
7
|
<steps CRITICAL="TRUE">
|
|
8
|
-
1. Always LOAD the FULL
|
|
9
|
-
2. READ its entire contents - this is the CORE OS for EXECUTING the specific workflow-config
|
|
8
|
+
1. Always LOAD the FULL {project-root}/_bmad/core/tasks/workflow.xml
|
|
9
|
+
2. READ its entire contents - this is the CORE OS for EXECUTING the specific workflow-config {project-root}/{{workflow_path}}
|
|
10
10
|
3. Pass the yaml path {{workflow_path}} as 'workflow-config' parameter to the workflow.xml instructions
|
|
11
11
|
4. Follow workflow.xml instructions EXACTLY as written to process and follow the specific workflow config and its instructions
|
|
12
12
|
5. Save outputs after EACH section when generating any documents from templates
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
description: '{{description}}'
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL
|
|
5
|
+
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL {project-root}/{{workflow_path}}, READ its entire contents and follow its directions exactly!
|