bmad-method 5.0.0-beta.2 ā 5.0.1
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/.github/ISSUE_TEMPLATE/bug_report.md +3 -3
- package/.github/ISSUE_TEMPLATE/feature_request.md +3 -3
- package/.github/workflows/discord.yaml +11 -2
- package/.github/workflows/format-check.yaml +42 -0
- package/.github/workflows/manual-release.yaml +173 -0
- package/.husky/pre-commit +3 -0
- package/.vscode/settings.json +26 -1
- package/CHANGELOG.md +0 -11
- package/README.md +2 -0
- package/bmad-core/agent-teams/team-all.yaml +1 -1
- package/bmad-core/agents/bmad-orchestrator.md +1 -1
- package/bmad-core/agents/dev.md +4 -4
- package/bmad-core/data/bmad-kb.md +1 -1
- package/bmad-core/data/test-levels-framework.md +12 -12
- package/bmad-core/tasks/facilitate-brainstorming-session.md +1 -1
- package/bmad-core/tasks/nfr-assess.md +10 -10
- package/bmad-core/tasks/qa-gate.md +23 -23
- package/bmad-core/tasks/review-story.md +18 -18
- package/bmad-core/tasks/risk-profile.md +25 -25
- package/bmad-core/tasks/test-design.md +9 -9
- package/bmad-core/tasks/trace-requirements.md +21 -21
- package/bmad-core/templates/architecture-tmpl.yaml +49 -49
- package/bmad-core/templates/brainstorming-output-tmpl.yaml +5 -5
- package/bmad-core/templates/brownfield-architecture-tmpl.yaml +31 -31
- package/bmad-core/templates/brownfield-prd-tmpl.yaml +13 -13
- package/bmad-core/templates/competitor-analysis-tmpl.yaml +19 -6
- package/bmad-core/templates/front-end-architecture-tmpl.yaml +21 -9
- package/bmad-core/templates/front-end-spec-tmpl.yaml +24 -24
- package/bmad-core/templates/fullstack-architecture-tmpl.yaml +122 -104
- package/bmad-core/templates/market-research-tmpl.yaml +2 -2
- package/bmad-core/templates/prd-tmpl.yaml +9 -9
- package/bmad-core/templates/project-brief-tmpl.yaml +4 -4
- package/bmad-core/templates/qa-gate-tmpl.yaml +9 -9
- package/bmad-core/templates/story-tmpl.yaml +12 -12
- package/bmad-core/workflows/brownfield-fullstack.yaml +9 -9
- package/bmad-core/workflows/brownfield-service.yaml +1 -1
- package/bmad-core/workflows/brownfield-ui.yaml +1 -1
- package/bmad-core/workflows/greenfield-fullstack.yaml +1 -1
- package/bmad-core/workflows/greenfield-service.yaml +1 -1
- package/bmad-core/workflows/greenfield-ui.yaml +1 -1
- package/common/utils/bmad-doc-template.md +5 -5
- package/dist/agents/analyst.txt +28 -15
- package/dist/agents/architect.txt +220 -190
- package/dist/agents/bmad-master.txt +298 -255
- package/dist/agents/bmad-orchestrator.txt +1 -1
- package/dist/agents/pm.txt +20 -20
- package/dist/agents/po.txt +11 -11
- package/dist/agents/qa.txt +275 -618
- package/dist/agents/sm.txt +11 -11
- package/dist/agents/ux-expert.txt +23 -23
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +109 -109
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +75 -77
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +41 -41
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +483 -474
- package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.txt +1 -1
- package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.txt +149 -149
- package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.txt +20 -20
- package/dist/expansion-packs/bmad-2d-unity-game-dev/teams/unity-2d-game-team.txt +371 -358
- package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +25 -25
- package/dist/teams/team-all.txt +581 -881
- package/dist/teams/team-fullstack.txt +316 -273
- package/dist/teams/team-ide-minimal.txt +276 -619
- package/dist/teams/team-no-ui.txt +281 -238
- package/docs/versioning-and-releases.md +114 -44
- package/eslint.config.mjs +119 -0
- package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.4 Deployment Configuration/1.4.2 - cloudbuild.yaml +26 -26
- package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.md +4 -4
- package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.md +1 -1
- package/expansion-packs/bmad-2d-phaser-game-dev/data/development-guidelines.md +26 -28
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-architecture-tmpl.yaml +50 -50
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-brief-tmpl.yaml +23 -23
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-design-doc-tmpl.yaml +24 -24
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-story-tmpl.yaml +42 -42
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/level-design-doc-tmpl.yaml +65 -65
- package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-dev-greenfield.yaml +5 -5
- package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-prototype.yaml +1 -1
- package/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.md +3 -3
- package/expansion-packs/bmad-2d-unity-game-dev/data/bmad-kb.md +1 -1
- package/expansion-packs/bmad-2d-unity-game-dev/templates/game-brief-tmpl.yaml +23 -23
- package/expansion-packs/bmad-2d-unity-game-dev/templates/game-design-doc-tmpl.yaml +63 -63
- package/expansion-packs/bmad-2d-unity-game-dev/templates/game-story-tmpl.yaml +20 -20
- package/expansion-packs/bmad-2d-unity-game-dev/templates/level-design-doc-tmpl.yaml +65 -65
- package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-dev-greenfield.yaml +5 -5
- package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-prototype.yaml +1 -1
- package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-architecture-tmpl.yaml +20 -20
- package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.yaml +7 -7
- package/package.json +62 -39
- package/prettier.config.mjs +32 -0
- package/release_notes.md +30 -0
- package/tools/bmad-npx-wrapper.js +10 -10
- package/tools/builders/web-builder.js +124 -130
- package/tools/bump-all-versions.js +42 -33
- package/tools/bump-expansion-version.js +23 -16
- package/tools/cli.js +10 -12
- package/tools/flattener/aggregate.js +10 -10
- package/tools/flattener/binary.js +44 -17
- package/tools/flattener/discovery.js +19 -18
- package/tools/flattener/files.js +6 -6
- package/tools/flattener/ignoreRules.js +125 -125
- package/tools/flattener/main.js +201 -304
- package/tools/flattener/projectRoot.js +75 -73
- package/tools/flattener/prompts.js +9 -9
- package/tools/flattener/stats.helpers.js +131 -67
- package/tools/flattener/stats.js +3 -3
- package/tools/flattener/test-matrix.js +201 -193
- package/tools/flattener/xml.js +33 -31
- package/tools/installer/bin/bmad.js +130 -89
- package/tools/installer/config/ide-agent-config.yaml +1 -1
- package/tools/installer/config/install.config.yaml +2 -2
- package/tools/installer/lib/config-loader.js +46 -42
- package/tools/installer/lib/file-manager.js +91 -113
- package/tools/installer/lib/ide-base-setup.js +57 -56
- package/tools/installer/lib/ide-setup.js +375 -343
- package/tools/installer/lib/installer.js +875 -714
- package/tools/installer/lib/memory-profiler.js +54 -53
- package/tools/installer/lib/module-manager.js +19 -15
- package/tools/installer/lib/resource-locator.js +26 -28
- package/tools/installer/package.json +19 -19
- package/tools/lib/dependency-resolver.js +26 -30
- package/tools/lib/yaml-utils.js +7 -7
- package/tools/preview-release-notes.js +66 -0
- package/tools/shared/bannerArt.js +3 -3
- package/tools/sync-installer-version.js +7 -9
- package/tools/update-expansion-version.js +14 -15
- package/tools/upgraders/v3-to-v4-upgrader.js +203 -294
- package/tools/version-bump.js +41 -26
- package/tools/yaml-format.js +56 -43
- package/.github/workflows/promote-to-stable.yml +0 -144
- package/.github/workflows/release.yaml +0 -60
- package/.releaserc.json +0 -21
- package/tools/semantic-release-sync-installer.js +0 -30
package/tools/flattener/xml.js
CHANGED
|
@@ -1,49 +1,44 @@
|
|
|
1
|
-
const fs = require(
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
2
|
|
|
3
|
-
function escapeXml(
|
|
4
|
-
if (typeof
|
|
5
|
-
return String(
|
|
3
|
+
function escapeXml(string_) {
|
|
4
|
+
if (typeof string_ !== 'string') {
|
|
5
|
+
return String(string_);
|
|
6
6
|
}
|
|
7
|
-
return
|
|
8
|
-
.replace(/&/g, "&")
|
|
9
|
-
.replace(/</g, "<")
|
|
10
|
-
.replace(/'/g, "'");
|
|
7
|
+
return string_.replaceAll('&', '&').replaceAll('<', '<').replaceAll("'", ''');
|
|
11
8
|
}
|
|
12
9
|
|
|
13
10
|
function indentFileContent(content) {
|
|
14
|
-
if (typeof content !==
|
|
11
|
+
if (typeof content !== 'string') {
|
|
15
12
|
return String(content);
|
|
16
13
|
}
|
|
17
|
-
return content.split(
|
|
14
|
+
return content.split('\n').map((line) => ` ${line}`);
|
|
18
15
|
}
|
|
19
16
|
|
|
20
17
|
function generateXMLOutput(aggregatedContent, outputPath) {
|
|
21
18
|
const { textFiles } = aggregatedContent;
|
|
22
|
-
const writeStream = fs.createWriteStream(outputPath, { encoding:
|
|
19
|
+
const writeStream = fs.createWriteStream(outputPath, { encoding: 'utf8' });
|
|
23
20
|
|
|
24
21
|
return new Promise((resolve, reject) => {
|
|
25
|
-
writeStream.on(
|
|
26
|
-
writeStream.on(
|
|
22
|
+
writeStream.on('error', reject);
|
|
23
|
+
writeStream.on('finish', resolve);
|
|
27
24
|
|
|
28
25
|
writeStream.write('<?xml version="1.0" encoding="UTF-8"?>\n');
|
|
29
|
-
writeStream.write(
|
|
26
|
+
writeStream.write('<files>\n');
|
|
30
27
|
|
|
31
28
|
// Sort files by path for deterministic order
|
|
32
|
-
const filesSorted = [...textFiles].sort((a, b) =>
|
|
33
|
-
a.path.localeCompare(b.path)
|
|
34
|
-
);
|
|
29
|
+
const filesSorted = [...textFiles].sort((a, b) => a.path.localeCompare(b.path));
|
|
35
30
|
let index = 0;
|
|
36
31
|
|
|
37
32
|
const writeNext = () => {
|
|
38
33
|
if (index >= filesSorted.length) {
|
|
39
|
-
writeStream.write(
|
|
34
|
+
writeStream.write('</files>\n');
|
|
40
35
|
writeStream.end();
|
|
41
36
|
return;
|
|
42
37
|
}
|
|
43
38
|
|
|
44
39
|
const file = filesSorted[index++];
|
|
45
40
|
const p = escapeXml(file.path);
|
|
46
|
-
const content = typeof file.content ===
|
|
41
|
+
const content = typeof file.content === 'string' ? file.content : '';
|
|
47
42
|
|
|
48
43
|
if (content.length === 0) {
|
|
49
44
|
writeStream.write(`\t<file path='${p}'/>\n`);
|
|
@@ -51,27 +46,34 @@ function generateXMLOutput(aggregatedContent, outputPath) {
|
|
|
51
46
|
return;
|
|
52
47
|
}
|
|
53
48
|
|
|
54
|
-
const needsCdata = content.includes(
|
|
55
|
-
content.includes("]]>");
|
|
49
|
+
const needsCdata = content.includes('<') || content.includes('&') || content.includes(']]>');
|
|
56
50
|
if (needsCdata) {
|
|
57
51
|
// Open tag and CDATA on their own line with tab indent; content lines indented with two tabs
|
|
58
52
|
writeStream.write(`\t<file path='${p}'><![CDATA[\n`);
|
|
59
53
|
// Safely split any occurrences of "]]>" inside content, trim trailing newlines, indent each line with two tabs
|
|
60
|
-
const safe = content.
|
|
61
|
-
const trimmed = safe.replace(/[\r\n]+$/,
|
|
62
|
-
const indented =
|
|
63
|
-
|
|
64
|
-
|
|
54
|
+
const safe = content.replaceAll(']]>', ']]]]><![CDATA[>');
|
|
55
|
+
const trimmed = safe.replace(/[\r\n]+$/, '');
|
|
56
|
+
const indented =
|
|
57
|
+
trimmed.length > 0
|
|
58
|
+
? trimmed
|
|
59
|
+
.split('\n')
|
|
60
|
+
.map((line) => `\t\t${line}`)
|
|
61
|
+
.join('\n')
|
|
62
|
+
: '';
|
|
65
63
|
writeStream.write(indented);
|
|
66
64
|
// Close CDATA and attach closing tag directly after the last content line
|
|
67
|
-
writeStream.write(
|
|
65
|
+
writeStream.write(']]></file>\n');
|
|
68
66
|
} else {
|
|
69
67
|
// Write opening tag then newline; indent content with two tabs; attach closing tag directly after last content char
|
|
70
68
|
writeStream.write(`\t<file path='${p}'>\n`);
|
|
71
|
-
const trimmed = content.replace(/[\r\n]+$/,
|
|
72
|
-
const indented =
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
const trimmed = content.replace(/[\r\n]+$/, '');
|
|
70
|
+
const indented =
|
|
71
|
+
trimmed.length > 0
|
|
72
|
+
? trimmed
|
|
73
|
+
.split('\n')
|
|
74
|
+
.map((line) => `\t\t${line}`)
|
|
75
|
+
.join('\n')
|
|
76
|
+
: '';
|
|
75
77
|
writeStream.write(indented);
|
|
76
78
|
writeStream.write(`</file>\n`);
|
|
77
79
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { program } = require('commander');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const fs = require('fs').promises;
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const fs = require('node:fs').promises;
|
|
6
6
|
const yaml = require('js-yaml');
|
|
7
7
|
const chalk = require('chalk').default || require('chalk');
|
|
8
8
|
const inquirer = require('inquirer').default || require('inquirer');
|
|
9
9
|
const semver = require('semver');
|
|
10
|
-
const https = require('https');
|
|
10
|
+
const https = require('node:https');
|
|
11
11
|
|
|
12
12
|
// Handle both execution contexts (from root via npx or from installer directory)
|
|
13
13
|
let version;
|
|
@@ -18,18 +18,20 @@ try {
|
|
|
18
18
|
version = require('../package.json').version;
|
|
19
19
|
packageName = require('../package.json').name;
|
|
20
20
|
installer = require('../lib/installer');
|
|
21
|
-
} catch (
|
|
21
|
+
} catch (error) {
|
|
22
22
|
// Fall back to root context (when run via npx from GitHub)
|
|
23
|
-
console.log(`Installer context not found (${
|
|
23
|
+
console.log(`Installer context not found (${error.message}), trying root context...`);
|
|
24
24
|
try {
|
|
25
25
|
version = require('../../../package.json').version;
|
|
26
26
|
installer = require('../../../tools/installer/lib/installer');
|
|
27
|
-
} catch (
|
|
28
|
-
console.error(
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error(
|
|
29
|
+
'Error: Could not load required modules. Please ensure you are running from the correct directory.',
|
|
30
|
+
);
|
|
29
31
|
console.error('Debug info:', {
|
|
30
32
|
__dirname,
|
|
31
33
|
cwd: process.cwd(),
|
|
32
|
-
error:
|
|
34
|
+
error: error.message,
|
|
33
35
|
});
|
|
34
36
|
process.exit(1);
|
|
35
37
|
}
|
|
@@ -45,8 +47,14 @@ program
|
|
|
45
47
|
.option('-f, --full', 'Install complete BMad Method')
|
|
46
48
|
.option('-x, --expansion-only', 'Install only expansion packs (no bmad-core)')
|
|
47
49
|
.option('-d, --directory <path>', 'Installation directory')
|
|
48
|
-
.option(
|
|
49
|
-
|
|
50
|
+
.option(
|
|
51
|
+
'-i, --ide <ide...>',
|
|
52
|
+
'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, trae, roo, kilo, cline, gemini, qwen-code, github-copilot, other)',
|
|
53
|
+
)
|
|
54
|
+
.option(
|
|
55
|
+
'-e, --expansion-packs <packs...>',
|
|
56
|
+
'Install specific expansion packs (can specify multiple)',
|
|
57
|
+
)
|
|
50
58
|
.action(async (options) => {
|
|
51
59
|
try {
|
|
52
60
|
if (!options.full && !options.expansionOnly) {
|
|
@@ -64,8 +72,8 @@ program
|
|
|
64
72
|
const config = {
|
|
65
73
|
installType,
|
|
66
74
|
directory: options.directory || '.',
|
|
67
|
-
ides: (options.ide || []).filter(ide => ide !== 'other'),
|
|
68
|
-
expansionPacks: options.expansionPacks || []
|
|
75
|
+
ides: (options.ide || []).filter((ide) => ide !== 'other'),
|
|
76
|
+
expansionPacks: options.expansionPacks || [],
|
|
69
77
|
};
|
|
70
78
|
await installer.install(config);
|
|
71
79
|
process.exit(0);
|
|
@@ -96,28 +104,30 @@ program
|
|
|
96
104
|
.description('Check for BMad Update')
|
|
97
105
|
.action(async () => {
|
|
98
106
|
console.log('Checking for updates...');
|
|
99
|
-
|
|
107
|
+
|
|
100
108
|
// Make HTTP request to npm registry for latest version info
|
|
101
|
-
const req = https.get(`https://registry.npmjs.org/${packageName}/latest`, res => {
|
|
109
|
+
const req = https.get(`https://registry.npmjs.org/${packageName}/latest`, (res) => {
|
|
102
110
|
// Check for HTTP errors (non-200 status codes)
|
|
103
111
|
if (res.statusCode !== 200) {
|
|
104
112
|
console.error(chalk.red(`Update check failed: Received status code ${res.statusCode}`));
|
|
105
113
|
return;
|
|
106
114
|
}
|
|
107
|
-
|
|
115
|
+
|
|
108
116
|
// Accumulate response data chunks
|
|
109
117
|
let data = '';
|
|
110
|
-
res.on('data', chunk => data += chunk);
|
|
111
|
-
|
|
118
|
+
res.on('data', (chunk) => (data += chunk));
|
|
119
|
+
|
|
112
120
|
// Process complete response
|
|
113
121
|
res.on('end', () => {
|
|
114
122
|
try {
|
|
115
123
|
// Parse npm registry response and extract version
|
|
116
124
|
const latest = JSON.parse(data).version;
|
|
117
|
-
|
|
125
|
+
|
|
118
126
|
// Compare versions using semver
|
|
119
127
|
if (semver.gt(latest, version)) {
|
|
120
|
-
console.log(
|
|
128
|
+
console.log(
|
|
129
|
+
chalk.bold.blue(`ā ļø ${packageName} update available: ${version} ā ${latest}`),
|
|
130
|
+
);
|
|
121
131
|
console.log(chalk.bold.blue('\nInstall latest by running:'));
|
|
122
132
|
console.log(chalk.bold.magenta(` npm install ${packageName}@latest`));
|
|
123
133
|
console.log(chalk.dim(' or'));
|
|
@@ -131,14 +141,14 @@ program
|
|
|
131
141
|
}
|
|
132
142
|
});
|
|
133
143
|
});
|
|
134
|
-
|
|
144
|
+
|
|
135
145
|
// Handle network/connection errors
|
|
136
|
-
req.on('error', error => {
|
|
146
|
+
req.on('error', (error) => {
|
|
137
147
|
console.error(chalk.red('Update check failed:'), error.message);
|
|
138
148
|
});
|
|
139
|
-
|
|
149
|
+
|
|
140
150
|
// Set 30 second timeout to prevent hanging
|
|
141
|
-
req.setTimeout(
|
|
151
|
+
req.setTimeout(30_000, () => {
|
|
142
152
|
req.destroy();
|
|
143
153
|
console.error(chalk.red('Update check timed out'));
|
|
144
154
|
});
|
|
@@ -183,16 +193,17 @@ program
|
|
|
183
193
|
});
|
|
184
194
|
|
|
185
195
|
async function promptInstallation() {
|
|
186
|
-
|
|
187
196
|
// Display ASCII logo
|
|
188
|
-
console.log(
|
|
189
|
-
|
|
197
|
+
console.log(
|
|
198
|
+
chalk.bold.cyan(`
|
|
199
|
+
āāāāāāā āāāā āāāā āāāāāā āāāāāāā āāāā āāāāāāāāāāāāāāāāāāāāāāāā āāā āāāāāāā āāāāāāā
|
|
190
200
|
āāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāāāā āāāāā āāāāāāāāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāāā
|
|
191
201
|
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāāāāāāāāā āāā āāāāāāāāāāā āāāāāā āāā
|
|
192
202
|
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāāāāāāāāā āāā āāāāāāāāāāā āāāāāā āāā
|
|
193
203
|
āāāāāāāāāāā āāā āāāāāā āāāāāāāāāāā āāā āāā āāāāāāāāāāā āāā āāā āāāāāāāāāāāāāāāāāāāā
|
|
194
|
-
āāāāāāā āāā āāāāāā āāāāāāāāāā āāā āāāāāāāāāāā āāā āāā āāā āāāāāāā āāāāāāā
|
|
195
|
-
`)
|
|
204
|
+
āāāāāāā āāā āāāāāā āāāāāāāāāā āāā āāāāāāāāāāā āāā āāā āāā āāāāāāā āāāāāāā
|
|
205
|
+
`),
|
|
206
|
+
);
|
|
196
207
|
|
|
197
208
|
console.log(chalk.bold.magenta('š Universal AI Agent Framework for Any Domain'));
|
|
198
209
|
console.log(chalk.bold.blue(`⨠Installer v${version}\n`));
|
|
@@ -210,8 +221,8 @@ async function promptInstallation() {
|
|
|
210
221
|
return 'Please enter a valid project path';
|
|
211
222
|
}
|
|
212
223
|
return true;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
224
|
+
},
|
|
225
|
+
},
|
|
215
226
|
]);
|
|
216
227
|
answers.directory = directory;
|
|
217
228
|
|
|
@@ -238,9 +249,10 @@ async function promptInstallation() {
|
|
|
238
249
|
if (state.type === 'v4_existing') {
|
|
239
250
|
const currentVersion = state.manifest?.version || 'unknown';
|
|
240
251
|
const newVersion = version; // Always use package.json version
|
|
241
|
-
const versionInfo =
|
|
242
|
-
|
|
243
|
-
|
|
252
|
+
const versionInfo =
|
|
253
|
+
currentVersion === newVersion
|
|
254
|
+
? `(v${currentVersion} - reinstall)`
|
|
255
|
+
: `(v${currentVersion} ā v${newVersion})`;
|
|
244
256
|
bmadOptionText = `Update ${coreShortTitle} ${versionInfo} .bmad-core`;
|
|
245
257
|
} else {
|
|
246
258
|
bmadOptionText = `${coreShortTitle} (v${version}) .bmad-core`;
|
|
@@ -249,7 +261,7 @@ async function promptInstallation() {
|
|
|
249
261
|
choices.push({
|
|
250
262
|
name: bmadOptionText,
|
|
251
263
|
value: 'bmad-core',
|
|
252
|
-
checked: true
|
|
264
|
+
checked: true,
|
|
253
265
|
});
|
|
254
266
|
|
|
255
267
|
// Add expansion pack options
|
|
@@ -260,9 +272,10 @@ async function promptInstallation() {
|
|
|
260
272
|
if (existing) {
|
|
261
273
|
const currentVersion = existing.manifest?.version || 'unknown';
|
|
262
274
|
const newVersion = pack.version;
|
|
263
|
-
const versionInfo =
|
|
264
|
-
|
|
265
|
-
|
|
275
|
+
const versionInfo =
|
|
276
|
+
currentVersion === newVersion
|
|
277
|
+
? `(v${currentVersion} - reinstall)`
|
|
278
|
+
: `(v${currentVersion} ā v${newVersion})`;
|
|
266
279
|
packOptionText = `Update ${pack.shortTitle} ${versionInfo} .${pack.id}`;
|
|
267
280
|
} else {
|
|
268
281
|
packOptionText = `${pack.shortTitle} (v${pack.version}) .${pack.id}`;
|
|
@@ -271,7 +284,7 @@ async function promptInstallation() {
|
|
|
271
284
|
choices.push({
|
|
272
285
|
name: packOptionText,
|
|
273
286
|
value: pack.id,
|
|
274
|
-
checked: false
|
|
287
|
+
checked: false,
|
|
275
288
|
});
|
|
276
289
|
}
|
|
277
290
|
|
|
@@ -287,13 +300,13 @@ async function promptInstallation() {
|
|
|
287
300
|
return 'Please select at least one item to install';
|
|
288
301
|
}
|
|
289
302
|
return true;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
303
|
+
},
|
|
304
|
+
},
|
|
292
305
|
]);
|
|
293
306
|
|
|
294
307
|
// Process selections
|
|
295
308
|
answers.installType = selectedItems.includes('bmad-core') ? 'full' : 'expansion-only';
|
|
296
|
-
answers.expansionPacks = selectedItems.filter(item => item !== 'bmad-core');
|
|
309
|
+
answers.expansionPacks = selectedItems.filter((item) => item !== 'bmad-core');
|
|
297
310
|
|
|
298
311
|
// Ask sharding questions if installing BMad core
|
|
299
312
|
if (selectedItems.includes('bmad-core')) {
|
|
@@ -306,8 +319,8 @@ async function promptInstallation() {
|
|
|
306
319
|
type: 'confirm',
|
|
307
320
|
name: 'prdSharded',
|
|
308
321
|
message: 'Will the PRD (Product Requirements Document) be sharded into multiple files?',
|
|
309
|
-
default: true
|
|
310
|
-
}
|
|
322
|
+
default: true,
|
|
323
|
+
},
|
|
311
324
|
]);
|
|
312
325
|
answers.prdSharded = prdSharded;
|
|
313
326
|
|
|
@@ -317,18 +330,30 @@ async function promptInstallation() {
|
|
|
317
330
|
type: 'confirm',
|
|
318
331
|
name: 'architectureSharded',
|
|
319
332
|
message: 'Will the architecture documentation be sharded into multiple files?',
|
|
320
|
-
default: true
|
|
321
|
-
}
|
|
333
|
+
default: true,
|
|
334
|
+
},
|
|
322
335
|
]);
|
|
323
336
|
answers.architectureSharded = architectureSharded;
|
|
324
337
|
|
|
325
338
|
// Show warning if architecture sharding is disabled
|
|
326
339
|
if (!architectureSharded) {
|
|
327
340
|
console.log(chalk.yellow.bold('\nā ļø IMPORTANT: Architecture Sharding Disabled'));
|
|
328
|
-
console.log(
|
|
329
|
-
|
|
341
|
+
console.log(
|
|
342
|
+
chalk.yellow(
|
|
343
|
+
'With architecture sharding disabled, you should still create the files listed',
|
|
344
|
+
),
|
|
345
|
+
);
|
|
346
|
+
console.log(
|
|
347
|
+
chalk.yellow(
|
|
348
|
+
'in devLoadAlwaysFiles (like coding-standards.md, tech-stack.md, source-tree.md)',
|
|
349
|
+
),
|
|
350
|
+
);
|
|
330
351
|
console.log(chalk.yellow('as these are used by the dev agent at runtime.'));
|
|
331
|
-
console.log(
|
|
352
|
+
console.log(
|
|
353
|
+
chalk.yellow(
|
|
354
|
+
'\nAlternatively, you can remove these files from the devLoadAlwaysFiles list',
|
|
355
|
+
),
|
|
356
|
+
);
|
|
332
357
|
console.log(chalk.yellow('in your core-config.yaml after installation.'));
|
|
333
358
|
|
|
334
359
|
const { acknowledge } = await inquirer.prompt([
|
|
@@ -336,8 +361,8 @@ async function promptInstallation() {
|
|
|
336
361
|
type: 'confirm',
|
|
337
362
|
name: 'acknowledge',
|
|
338
363
|
message: 'Do you acknowledge this requirement and want to proceed?',
|
|
339
|
-
default: false
|
|
340
|
-
}
|
|
364
|
+
default: false,
|
|
365
|
+
},
|
|
341
366
|
]);
|
|
342
367
|
|
|
343
368
|
if (!acknowledge) {
|
|
@@ -353,7 +378,11 @@ async function promptInstallation() {
|
|
|
353
378
|
|
|
354
379
|
while (!ideSelectionComplete) {
|
|
355
380
|
console.log(chalk.cyan('\nš ļø IDE Configuration'));
|
|
356
|
-
console.log(
|
|
381
|
+
console.log(
|
|
382
|
+
chalk.bold.yellow.bgRed(
|
|
383
|
+
' ā ļø IMPORTANT: This is a MULTISELECT! Use SPACEBAR to toggle each IDE! ',
|
|
384
|
+
),
|
|
385
|
+
);
|
|
357
386
|
console.log(chalk.bold.magenta('šø Use arrow keys to navigate'));
|
|
358
387
|
console.log(chalk.bold.magenta('šø Use SPACEBAR to select/deselect IDEs'));
|
|
359
388
|
console.log(chalk.bold.magenta('šø Press ENTER when finished selecting\n'));
|
|
@@ -362,7 +391,8 @@ async function promptInstallation() {
|
|
|
362
391
|
{
|
|
363
392
|
type: 'checkbox',
|
|
364
393
|
name: 'ides',
|
|
365
|
-
message:
|
|
394
|
+
message:
|
|
395
|
+
'Which IDE(s) do you want to configure? (Select with SPACEBAR, confirm with ENTER):',
|
|
366
396
|
choices: [
|
|
367
397
|
{ name: 'Cursor', value: 'cursor' },
|
|
368
398
|
{ name: 'Claude Code', value: 'claude-code' },
|
|
@@ -374,9 +404,9 @@ async function promptInstallation() {
|
|
|
374
404
|
{ name: 'Gemini CLI', value: 'gemini' },
|
|
375
405
|
{ name: 'Qwen Code', value: 'qwen-code' },
|
|
376
406
|
{ name: 'Crush', value: 'crush' },
|
|
377
|
-
{ name: 'Github Copilot', value: 'github-copilot' }
|
|
378
|
-
]
|
|
379
|
-
}
|
|
407
|
+
{ name: 'Github Copilot', value: 'github-copilot' },
|
|
408
|
+
],
|
|
409
|
+
},
|
|
380
410
|
]);
|
|
381
411
|
|
|
382
412
|
ides = ideResponse.ides;
|
|
@@ -387,13 +417,19 @@ async function promptInstallation() {
|
|
|
387
417
|
{
|
|
388
418
|
type: 'confirm',
|
|
389
419
|
name: 'confirmNoIde',
|
|
390
|
-
message: chalk.red(
|
|
391
|
-
|
|
392
|
-
|
|
420
|
+
message: chalk.red(
|
|
421
|
+
'ā ļø You have NOT selected any IDEs. This means NO IDE integration will be set up. Is this correct?',
|
|
422
|
+
),
|
|
423
|
+
default: false,
|
|
424
|
+
},
|
|
393
425
|
]);
|
|
394
426
|
|
|
395
427
|
if (!confirmNoIde) {
|
|
396
|
-
console.log(
|
|
428
|
+
console.log(
|
|
429
|
+
chalk.bold.red(
|
|
430
|
+
'\nš Returning to IDE selection. Remember to use SPACEBAR to select IDEs!\n',
|
|
431
|
+
),
|
|
432
|
+
);
|
|
397
433
|
continue; // Go back to IDE selection only
|
|
398
434
|
}
|
|
399
435
|
}
|
|
@@ -407,7 +443,9 @@ async function promptInstallation() {
|
|
|
407
443
|
// Configure GitHub Copilot immediately if selected
|
|
408
444
|
if (ides.includes('github-copilot')) {
|
|
409
445
|
console.log(chalk.cyan('\nš§ GitHub Copilot Configuration'));
|
|
410
|
-
console.log(
|
|
446
|
+
console.log(
|
|
447
|
+
chalk.dim('BMad works best with specific VS Code settings for optimal agent experience.\n'),
|
|
448
|
+
);
|
|
411
449
|
|
|
412
450
|
const { configChoice } = await inquirer.prompt([
|
|
413
451
|
{
|
|
@@ -417,19 +455,19 @@ async function promptInstallation() {
|
|
|
417
455
|
choices: [
|
|
418
456
|
{
|
|
419
457
|
name: 'Use recommended defaults (fastest setup)',
|
|
420
|
-
value: 'defaults'
|
|
458
|
+
value: 'defaults',
|
|
421
459
|
},
|
|
422
460
|
{
|
|
423
461
|
name: 'Configure each setting manually (customize to your preferences)',
|
|
424
|
-
value: 'manual'
|
|
462
|
+
value: 'manual',
|
|
425
463
|
},
|
|
426
464
|
{
|
|
427
|
-
name:
|
|
428
|
-
value: 'skip'
|
|
429
|
-
}
|
|
465
|
+
name: "Skip settings configuration (I'll configure manually later)",
|
|
466
|
+
value: 'skip',
|
|
467
|
+
},
|
|
430
468
|
],
|
|
431
|
-
default: 'defaults'
|
|
432
|
-
}
|
|
469
|
+
default: 'defaults',
|
|
470
|
+
},
|
|
433
471
|
]);
|
|
434
472
|
|
|
435
473
|
answers.githubCopilotConfig = { configChoice };
|
|
@@ -440,14 +478,17 @@ async function promptInstallation() {
|
|
|
440
478
|
{
|
|
441
479
|
type: 'confirm',
|
|
442
480
|
name: 'includeWebBundles',
|
|
443
|
-
message:
|
|
444
|
-
|
|
445
|
-
|
|
481
|
+
message:
|
|
482
|
+
'Would you like to include pre-built web bundles? (standalone files for ChatGPT, Claude, Gemini)',
|
|
483
|
+
default: false,
|
|
484
|
+
},
|
|
446
485
|
]);
|
|
447
486
|
|
|
448
487
|
if (includeWebBundles) {
|
|
449
488
|
console.log(chalk.cyan('\nš¦ Web bundles are standalone files perfect for web AI platforms.'));
|
|
450
|
-
console.log(
|
|
489
|
+
console.log(
|
|
490
|
+
chalk.dim(' You can choose different teams/agents than your IDE installation.\n'),
|
|
491
|
+
);
|
|
451
492
|
|
|
452
493
|
const { webBundleType } = await inquirer.prompt([
|
|
453
494
|
{
|
|
@@ -457,22 +498,22 @@ async function promptInstallation() {
|
|
|
457
498
|
choices: [
|
|
458
499
|
{
|
|
459
500
|
name: 'All available bundles (agents, teams, expansion packs)',
|
|
460
|
-
value: 'all'
|
|
501
|
+
value: 'all',
|
|
461
502
|
},
|
|
462
503
|
{
|
|
463
504
|
name: 'Specific teams only',
|
|
464
|
-
value: 'teams'
|
|
505
|
+
value: 'teams',
|
|
465
506
|
},
|
|
466
507
|
{
|
|
467
508
|
name: 'Individual agents only',
|
|
468
|
-
value: 'agents'
|
|
509
|
+
value: 'agents',
|
|
469
510
|
},
|
|
470
511
|
{
|
|
471
512
|
name: 'Custom selection',
|
|
472
|
-
value: 'custom'
|
|
473
|
-
}
|
|
474
|
-
]
|
|
475
|
-
}
|
|
513
|
+
value: 'custom',
|
|
514
|
+
},
|
|
515
|
+
],
|
|
516
|
+
},
|
|
476
517
|
]);
|
|
477
518
|
|
|
478
519
|
answers.webBundleType = webBundleType;
|
|
@@ -485,18 +526,18 @@ async function promptInstallation() {
|
|
|
485
526
|
type: 'checkbox',
|
|
486
527
|
name: 'selectedTeams',
|
|
487
528
|
message: 'Select team bundles to include:',
|
|
488
|
-
choices: teams.map(t => ({
|
|
529
|
+
choices: teams.map((t) => ({
|
|
489
530
|
name: `${t.icon || 'š'} ${t.name}: ${t.description}`,
|
|
490
531
|
value: t.id,
|
|
491
|
-
checked: webBundleType === 'teams' // Check all if teams-only mode
|
|
532
|
+
checked: webBundleType === 'teams', // Check all if teams-only mode
|
|
492
533
|
})),
|
|
493
534
|
validate: (answer) => {
|
|
494
|
-
if (answer.length
|
|
535
|
+
if (answer.length === 0) {
|
|
495
536
|
return 'You must select at least one team.';
|
|
496
537
|
}
|
|
497
538
|
return true;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
539
|
+
},
|
|
540
|
+
},
|
|
500
541
|
]);
|
|
501
542
|
answers.selectedWebBundleTeams = selectedTeams;
|
|
502
543
|
}
|
|
@@ -508,8 +549,8 @@ async function promptInstallation() {
|
|
|
508
549
|
type: 'confirm',
|
|
509
550
|
name: 'includeIndividualAgents',
|
|
510
551
|
message: 'Also include individual agent bundles?',
|
|
511
|
-
default: true
|
|
512
|
-
}
|
|
552
|
+
default: true,
|
|
553
|
+
},
|
|
513
554
|
]);
|
|
514
555
|
answers.includeIndividualAgents = includeIndividualAgents;
|
|
515
556
|
}
|
|
@@ -525,8 +566,8 @@ async function promptInstallation() {
|
|
|
525
566
|
return 'Please enter a valid directory path';
|
|
526
567
|
}
|
|
527
568
|
return true;
|
|
528
|
-
}
|
|
529
|
-
}
|
|
569
|
+
},
|
|
570
|
+
},
|
|
530
571
|
]);
|
|
531
572
|
answers.webBundlesDirectory = webBundlesDirectory;
|
|
532
573
|
}
|
|
@@ -539,6 +580,6 @@ async function promptInstallation() {
|
|
|
539
580
|
program.parse(process.argv);
|
|
540
581
|
|
|
541
582
|
// Show help if no command provided
|
|
542
|
-
if (
|
|
583
|
+
if (process.argv.slice(2).length === 0) {
|
|
543
584
|
program.outputHelp();
|
|
544
|
-
}
|
|
585
|
+
}
|
|
@@ -40,12 +40,12 @@ ide-configurations:
|
|
|
40
40
|
# 3. Crush will switch to that agent's persona / task
|
|
41
41
|
windsurf:
|
|
42
42
|
name: Windsurf
|
|
43
|
-
rule-dir: .windsurf/
|
|
43
|
+
rule-dir: .windsurf/workflows/
|
|
44
44
|
format: multi-file
|
|
45
45
|
command-suffix: .md
|
|
46
46
|
instructions: |
|
|
47
47
|
# To use BMad agents in Windsurf:
|
|
48
|
-
# 1. Type
|
|
48
|
+
# 1. Type /agent-name (e.g., "/dev", "/pm")
|
|
49
49
|
# 2. Windsurf will adopt that agent's persona
|
|
50
50
|
trae:
|
|
51
51
|
name: Trae
|