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.
Files changed (131) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +3 -3
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +3 -3
  3. package/.github/workflows/discord.yaml +11 -2
  4. package/.github/workflows/format-check.yaml +42 -0
  5. package/.github/workflows/manual-release.yaml +173 -0
  6. package/.husky/pre-commit +3 -0
  7. package/.vscode/settings.json +26 -1
  8. package/CHANGELOG.md +0 -11
  9. package/README.md +2 -0
  10. package/bmad-core/agent-teams/team-all.yaml +1 -1
  11. package/bmad-core/agents/bmad-orchestrator.md +1 -1
  12. package/bmad-core/agents/dev.md +4 -4
  13. package/bmad-core/data/bmad-kb.md +1 -1
  14. package/bmad-core/data/test-levels-framework.md +12 -12
  15. package/bmad-core/tasks/facilitate-brainstorming-session.md +1 -1
  16. package/bmad-core/tasks/nfr-assess.md +10 -10
  17. package/bmad-core/tasks/qa-gate.md +23 -23
  18. package/bmad-core/tasks/review-story.md +18 -18
  19. package/bmad-core/tasks/risk-profile.md +25 -25
  20. package/bmad-core/tasks/test-design.md +9 -9
  21. package/bmad-core/tasks/trace-requirements.md +21 -21
  22. package/bmad-core/templates/architecture-tmpl.yaml +49 -49
  23. package/bmad-core/templates/brainstorming-output-tmpl.yaml +5 -5
  24. package/bmad-core/templates/brownfield-architecture-tmpl.yaml +31 -31
  25. package/bmad-core/templates/brownfield-prd-tmpl.yaml +13 -13
  26. package/bmad-core/templates/competitor-analysis-tmpl.yaml +19 -6
  27. package/bmad-core/templates/front-end-architecture-tmpl.yaml +21 -9
  28. package/bmad-core/templates/front-end-spec-tmpl.yaml +24 -24
  29. package/bmad-core/templates/fullstack-architecture-tmpl.yaml +122 -104
  30. package/bmad-core/templates/market-research-tmpl.yaml +2 -2
  31. package/bmad-core/templates/prd-tmpl.yaml +9 -9
  32. package/bmad-core/templates/project-brief-tmpl.yaml +4 -4
  33. package/bmad-core/templates/qa-gate-tmpl.yaml +9 -9
  34. package/bmad-core/templates/story-tmpl.yaml +12 -12
  35. package/bmad-core/workflows/brownfield-fullstack.yaml +9 -9
  36. package/bmad-core/workflows/brownfield-service.yaml +1 -1
  37. package/bmad-core/workflows/brownfield-ui.yaml +1 -1
  38. package/bmad-core/workflows/greenfield-fullstack.yaml +1 -1
  39. package/bmad-core/workflows/greenfield-service.yaml +1 -1
  40. package/bmad-core/workflows/greenfield-ui.yaml +1 -1
  41. package/common/utils/bmad-doc-template.md +5 -5
  42. package/dist/agents/analyst.txt +28 -15
  43. package/dist/agents/architect.txt +220 -190
  44. package/dist/agents/bmad-master.txt +298 -255
  45. package/dist/agents/bmad-orchestrator.txt +1 -1
  46. package/dist/agents/pm.txt +20 -20
  47. package/dist/agents/po.txt +11 -11
  48. package/dist/agents/qa.txt +275 -618
  49. package/dist/agents/sm.txt +11 -11
  50. package/dist/agents/ux-expert.txt +23 -23
  51. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +109 -109
  52. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +75 -77
  53. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +41 -41
  54. package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +483 -474
  55. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.txt +1 -1
  56. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.txt +149 -149
  57. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.txt +20 -20
  58. package/dist/expansion-packs/bmad-2d-unity-game-dev/teams/unity-2d-game-team.txt +371 -358
  59. package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +25 -25
  60. package/dist/teams/team-all.txt +581 -881
  61. package/dist/teams/team-fullstack.txt +316 -273
  62. package/dist/teams/team-ide-minimal.txt +276 -619
  63. package/dist/teams/team-no-ui.txt +281 -238
  64. package/docs/versioning-and-releases.md +114 -44
  65. package/eslint.config.mjs +119 -0
  66. 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
  67. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.md +4 -4
  68. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.md +1 -1
  69. package/expansion-packs/bmad-2d-phaser-game-dev/data/development-guidelines.md +26 -28
  70. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-architecture-tmpl.yaml +50 -50
  71. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-brief-tmpl.yaml +23 -23
  72. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-design-doc-tmpl.yaml +24 -24
  73. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-story-tmpl.yaml +42 -42
  74. package/expansion-packs/bmad-2d-phaser-game-dev/templates/level-design-doc-tmpl.yaml +65 -65
  75. package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-dev-greenfield.yaml +5 -5
  76. package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-prototype.yaml +1 -1
  77. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.md +3 -3
  78. package/expansion-packs/bmad-2d-unity-game-dev/data/bmad-kb.md +1 -1
  79. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-brief-tmpl.yaml +23 -23
  80. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-design-doc-tmpl.yaml +63 -63
  81. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-story-tmpl.yaml +20 -20
  82. package/expansion-packs/bmad-2d-unity-game-dev/templates/level-design-doc-tmpl.yaml +65 -65
  83. package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-dev-greenfield.yaml +5 -5
  84. package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-prototype.yaml +1 -1
  85. package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-architecture-tmpl.yaml +20 -20
  86. package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.yaml +7 -7
  87. package/package.json +62 -39
  88. package/prettier.config.mjs +32 -0
  89. package/release_notes.md +30 -0
  90. package/tools/bmad-npx-wrapper.js +10 -10
  91. package/tools/builders/web-builder.js +124 -130
  92. package/tools/bump-all-versions.js +42 -33
  93. package/tools/bump-expansion-version.js +23 -16
  94. package/tools/cli.js +10 -12
  95. package/tools/flattener/aggregate.js +10 -10
  96. package/tools/flattener/binary.js +44 -17
  97. package/tools/flattener/discovery.js +19 -18
  98. package/tools/flattener/files.js +6 -6
  99. package/tools/flattener/ignoreRules.js +125 -125
  100. package/tools/flattener/main.js +201 -304
  101. package/tools/flattener/projectRoot.js +75 -73
  102. package/tools/flattener/prompts.js +9 -9
  103. package/tools/flattener/stats.helpers.js +131 -67
  104. package/tools/flattener/stats.js +3 -3
  105. package/tools/flattener/test-matrix.js +201 -193
  106. package/tools/flattener/xml.js +33 -31
  107. package/tools/installer/bin/bmad.js +130 -89
  108. package/tools/installer/config/ide-agent-config.yaml +1 -1
  109. package/tools/installer/config/install.config.yaml +2 -2
  110. package/tools/installer/lib/config-loader.js +46 -42
  111. package/tools/installer/lib/file-manager.js +91 -113
  112. package/tools/installer/lib/ide-base-setup.js +57 -56
  113. package/tools/installer/lib/ide-setup.js +375 -343
  114. package/tools/installer/lib/installer.js +875 -714
  115. package/tools/installer/lib/memory-profiler.js +54 -53
  116. package/tools/installer/lib/module-manager.js +19 -15
  117. package/tools/installer/lib/resource-locator.js +26 -28
  118. package/tools/installer/package.json +19 -19
  119. package/tools/lib/dependency-resolver.js +26 -30
  120. package/tools/lib/yaml-utils.js +7 -7
  121. package/tools/preview-release-notes.js +66 -0
  122. package/tools/shared/bannerArt.js +3 -3
  123. package/tools/sync-installer-version.js +7 -9
  124. package/tools/update-expansion-version.js +14 -15
  125. package/tools/upgraders/v3-to-v4-upgrader.js +203 -294
  126. package/tools/version-bump.js +41 -26
  127. package/tools/yaml-format.js +56 -43
  128. package/.github/workflows/promote-to-stable.yml +0 -144
  129. package/.github/workflows/release.yaml +0 -60
  130. package/.releaserc.json +0 -21
  131. package/tools/semantic-release-sync-installer.js +0 -30
@@ -1,49 +1,44 @@
1
- const fs = require("fs-extra");
1
+ const fs = require('fs-extra');
2
2
 
3
- function escapeXml(str) {
4
- if (typeof str !== "string") {
5
- return String(str);
3
+ function escapeXml(string_) {
4
+ if (typeof string_ !== 'string') {
5
+ return String(string_);
6
6
  }
7
- return str
8
- .replace(/&/g, "&")
9
- .replace(/</g, "&lt;")
10
- .replace(/'/g, "&apos;");
7
+ return string_.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll("'", '&apos;');
11
8
  }
12
9
 
13
10
  function indentFileContent(content) {
14
- if (typeof content !== "string") {
11
+ if (typeof content !== 'string') {
15
12
  return String(content);
16
13
  }
17
- return content.split("\n").map((line) => ` ${line}`);
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: "utf8" });
19
+ const writeStream = fs.createWriteStream(outputPath, { encoding: 'utf8' });
23
20
 
24
21
  return new Promise((resolve, reject) => {
25
- writeStream.on("error", reject);
26
- writeStream.on("finish", resolve);
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("<files>\n");
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("</files>\n");
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 === "string" ? 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("<") || 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.replace(/]]>/g, "]]]]><![CDATA[>");
61
- const trimmed = safe.replace(/[\r\n]+$/, "");
62
- const indented = trimmed.length > 0
63
- ? trimmed.split("\n").map((line) => `\t\t${line}`).join("\n")
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("]]></file>\n");
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 = trimmed.length > 0
73
- ? trimmed.split("\n").map((line) => `\t\t${line}`).join("\n")
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 (e) {
21
+ } catch (error) {
22
22
  // Fall back to root context (when run via npx from GitHub)
23
- console.log(`Installer context not found (${e.message}), trying root context...`);
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 (e2) {
28
- console.error('Error: Could not load required modules. Please ensure you are running from the correct directory.');
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: e2.message
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('-i, --ide <ide...>', 'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, trae, roo, kilo, cline, gemini, qwen-code, github-copilot, crush, other)')
49
- .option('-e, --expansion-packs <packs...>', 'Install specific expansion packs (can specify multiple)')
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(chalk.bold.blue(`āš ļø ${packageName} update available: ${version} → ${latest}`));
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(30000, () => {
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(chalk.bold.cyan(`
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 = currentVersion === newVersion
242
- ? `(v${currentVersion} - reinstall)`
243
- : `(v${currentVersion} → v${newVersion})`;
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 = currentVersion === newVersion
264
- ? `(v${currentVersion} - reinstall)`
265
- : `(v${currentVersion} → v${newVersion})`;
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(chalk.yellow('With architecture sharding disabled, you should still create the files listed'));
329
- console.log(chalk.yellow('in devLoadAlwaysFiles (like coding-standards.md, tech-stack.md, source-tree.md)'));
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(chalk.yellow('\nAlternatively, you can remove these files from the devLoadAlwaysFiles list'));
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(chalk.bold.yellow.bgRed(' āš ļø IMPORTANT: This is a MULTISELECT! Use SPACEBAR to toggle each IDE! '));
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: 'Which IDE(s) do you want to configure? (Select with SPACEBAR, confirm with ENTER):',
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('āš ļø You have NOT selected any IDEs. This means NO IDE integration will be set up. Is this correct?'),
391
- default: false
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(chalk.bold.red('\nšŸ”„ Returning to IDE selection. Remember to use SPACEBAR to select IDEs!\n'));
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(chalk.dim('BMad works best with specific VS Code settings for optimal agent experience.\n'));
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: 'Skip settings configuration (I\'ll configure manually later)',
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: 'Would you like to include pre-built web bundles? (standalone files for ChatGPT, Claude, Gemini)',
444
- default: false
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(chalk.dim(' You can choose different teams/agents than your IDE installation.\n'));
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 < 1) {
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 (!process.argv.slice(2).length) {
583
+ if (process.argv.slice(2).length === 0) {
543
584
  program.outputHelp();
544
- }
585
+ }
@@ -55,4 +55,4 @@ cline-order:
55
55
  game-designer: 12
56
56
  game-developer: 13
57
57
  game-sm: 14
58
- infra-devops-platform: 15
58
+ infra-devops-platform: 15
@@ -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/rules/
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 @agent-name (e.g., "@dev", "@pm")
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