bmad-method 4.19.2 → 4.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/.github/FUNDING.yml +15 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
  4. package/.vscode/settings.json +6 -76
  5. package/CHANGELOG.md +19 -0
  6. package/CONTRIBUTING.md +39 -5
  7. package/GUIDING-PRINCIPLES.md +2 -2
  8. package/LICENSE +1 -1
  9. package/README.md +178 -220
  10. package/bmad-core/agents/dev.md +1 -1
  11. package/bmad-core/core-config.yml +1 -0
  12. package/bmad-core/data/bmad-kb.md +1 -1
  13. package/dist/agents/analyst.txt +1 -1
  14. package/dist/agents/bmad-master.txt +1 -1
  15. package/dist/agents/bmad-orchestrator.txt +1 -1
  16. package/dist/agents/dev.txt +1 -1
  17. package/dist/teams/team-all.txt +40 -40
  18. package/dist/teams/team-fullstack.txt +39 -39
  19. package/dist/teams/team-ide-minimal.txt +2 -2
  20. package/dist/teams/team-no-ui.txt +13 -13
  21. package/docs/agentic-tools/claude-code-guide.md +36 -0
  22. package/docs/agentic-tools/cline-guide.md +42 -0
  23. package/docs/agentic-tools/cursor-guide.md +37 -0
  24. package/docs/agentic-tools/gemini-cli-guide.md +46 -0
  25. package/docs/agentic-tools/roo-code-guide.md +46 -0
  26. package/docs/agentic-tools/windsurf-guide.md +37 -0
  27. package/docs/core-architecture.md +174 -6
  28. package/docs/expansion-packs.md +15 -0
  29. package/docs/how-to-contribute-with-pull-requests.md +24 -7
  30. package/docs/user-guide.md +283 -36
  31. package/docs/versioning-and-releases.md +2 -10
  32. package/docs/versions.md +0 -1
  33. package/docs/working-in-the-brownfield.md +4 -8
  34. package/expansion-packs/bmad-2d-phaser-game-dev/config.yml +4 -2
  35. package/expansion-packs/bmad-creator-tools/config.yml +1 -1
  36. package/expansion-packs/bmad-infrastructure-devops/config.yml +5 -2
  37. package/package.json +15 -1
  38. package/tools/bump-all-versions.js +107 -0
  39. package/tools/bump-core-version.js +57 -0
  40. package/tools/bump-expansion-version.js +78 -0
  41. package/tools/installer/bin/bmad.js +81 -160
  42. package/tools/installer/lib/file-manager.js +90 -2
  43. package/tools/installer/lib/installer.js +515 -64
  44. package/tools/installer/package.json +1 -1
  45. package/tools/update-expansion-version.js +54 -0
  46. package/.claude/commands/analyst.md +0 -68
  47. package/.claude/commands/architect.md +0 -68
  48. package/.claude/commands/bmad-master.md +0 -105
  49. package/.claude/commands/bmad-orchestrator.md +0 -130
  50. package/.claude/commands/bmad-the-creator.md +0 -57
  51. package/.claude/commands/dev.md +0 -69
  52. package/.claude/commands/game-designer.md +0 -62
  53. package/.claude/commands/game-developer.md +0 -70
  54. package/.claude/commands/game-sm.md +0 -55
  55. package/.claude/commands/infra-devops-platform.md +0 -63
  56. package/.claude/commands/pm.md +0 -65
  57. package/.claude/commands/po.md +0 -67
  58. package/.claude/commands/qa.md +0 -54
  59. package/.claude/commands/sm.md +0 -55
  60. package/.claude/commands/ux-expert.md +0 -67
  61. package/.clinerules/01-bmad-master.md +0 -116
  62. package/.clinerules/02-bmad-orchestrator.md +0 -141
  63. package/.clinerules/03-pm.md +0 -76
  64. package/.clinerules/04-analyst.md +0 -79
  65. package/.clinerules/05-architect.md +0 -79
  66. package/.clinerules/06-po.md +0 -78
  67. package/.clinerules/07-sm.md +0 -66
  68. package/.clinerules/08-dev.md +0 -80
  69. package/.clinerules/09-qa.md +0 -65
  70. package/.clinerules/10-ux-expert.md +0 -78
  71. package/.clinerules/11-bmad-the-creator.md +0 -68
  72. package/.clinerules/12-game-designer.md +0 -73
  73. package/.clinerules/13-game-developer.md +0 -81
  74. package/.clinerules/14-game-sm.md +0 -66
  75. package/.clinerules/15-infra-devops-platform.md +0 -74
  76. package/.cursor/rules/analyst.mdc +0 -82
  77. package/.cursor/rules/architect.mdc +0 -82
  78. package/.cursor/rules/bmad-master.mdc +0 -119
  79. package/.cursor/rules/bmad-orchestrator.mdc +0 -144
  80. package/.cursor/rules/bmad-the-creator.mdc +0 -71
  81. package/.cursor/rules/dev.mdc +0 -83
  82. package/.cursor/rules/game-designer.mdc +0 -76
  83. package/.cursor/rules/game-developer.mdc +0 -84
  84. package/.cursor/rules/game-sm.mdc +0 -69
  85. package/.cursor/rules/infra-devops-platform.mdc +0 -77
  86. package/.cursor/rules/pm.mdc +0 -79
  87. package/.cursor/rules/po.mdc +0 -81
  88. package/.cursor/rules/qa.mdc +0 -68
  89. package/.cursor/rules/sm.mdc +0 -69
  90. package/.cursor/rules/ux-expert.mdc +0 -81
  91. package/.gemini/agents/analyst.md +0 -64
  92. package/.gemini/agents/architect.md +0 -64
  93. package/.gemini/agents/bmad-master.md +0 -101
  94. package/.gemini/agents/bmad-orchestrator.md +0 -126
  95. package/.gemini/agents/bmad-the-creator.md +0 -53
  96. package/.gemini/agents/dev.md +0 -65
  97. package/.gemini/agents/game-designer.md +0 -58
  98. package/.gemini/agents/game-developer.md +0 -66
  99. package/.gemini/agents/game-sm.md +0 -51
  100. package/.gemini/agents/infra-devops-platform.md +0 -59
  101. package/.gemini/agents/pm.md +0 -61
  102. package/.gemini/agents/po.md +0 -63
  103. package/.gemini/agents/qa.md +0 -50
  104. package/.gemini/agents/sm.md +0 -51
  105. package/.gemini/agents/ux-expert.md +0 -63
  106. package/.gemini/settings.json +0 -20
  107. package/.roomodes +0 -139
  108. package/.vscode/extensions.json +0 -6
  109. package/.vscode/tasks.json +0 -41
  110. package/.windsurf/rules/analyst.md +0 -76
  111. package/.windsurf/rules/architect.md +0 -76
  112. package/.windsurf/rules/bmad-master.md +0 -113
  113. package/.windsurf/rules/bmad-orchestrator.md +0 -138
  114. package/.windsurf/rules/bmad-the-creator.md +0 -65
  115. package/.windsurf/rules/dev.md +0 -77
  116. package/.windsurf/rules/game-designer.md +0 -70
  117. package/.windsurf/rules/game-developer.md +0 -78
  118. package/.windsurf/rules/game-sm.md +0 -63
  119. package/.windsurf/rules/infra-devops-platform.md +0 -71
  120. package/.windsurf/rules/pm.md +0 -73
  121. package/.windsurf/rules/po.md +0 -75
  122. package/.windsurf/rules/qa.md +0 -62
  123. package/.windsurf/rules/sm.md +0 -63
  124. package/.windsurf/rules/ux-expert.md +0 -75
  125. package/docs/claude-code-guide.md +0 -121
  126. package/docs/cursor-guide.md +0 -131
  127. package/docs/expansion-pack-ideas.md +0 -121
  128. package/docs/roo-code-guide.md +0 -142
  129. package/docs/windsurf-guide.md +0 -129
  130. package/test-ide-paths.js +0 -41
  131. /package/dist/expansion-packs/{expansion-creator → bmad-creator-tools}/agents/bmad-the-creator.txt +0 -0
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const yaml = require('js-yaml');
6
+
7
+ const args = process.argv.slice(2);
8
+ const bumpType = args[0] || 'minor'; // default to minor
9
+
10
+ if (!['major', 'minor', 'patch'].includes(bumpType)) {
11
+ console.log('Usage: node bump-core-version.js [major|minor|patch]');
12
+ console.log('Default: minor');
13
+ process.exit(1);
14
+ }
15
+
16
+ function bumpVersion(currentVersion, type) {
17
+ const [major, minor, patch] = currentVersion.split('.').map(Number);
18
+
19
+ switch (type) {
20
+ case 'major':
21
+ return `${major + 1}.0.0`;
22
+ case 'minor':
23
+ return `${major}.${minor + 1}.0`;
24
+ case 'patch':
25
+ return `${major}.${minor}.${patch + 1}`;
26
+ default:
27
+ return currentVersion;
28
+ }
29
+ }
30
+
31
+ async function bumpCoreVersion() {
32
+ try {
33
+ const coreConfigPath = path.join(__dirname, '..', 'bmad-core', 'core-config.yml');
34
+
35
+ const coreConfigContent = fs.readFileSync(coreConfigPath, 'utf8');
36
+ const coreConfig = yaml.load(coreConfigContent);
37
+ const oldVersion = coreConfig.version || '1.0.0';
38
+ const newVersion = bumpVersion(oldVersion, bumpType);
39
+
40
+ coreConfig.version = newVersion;
41
+
42
+ const updatedYaml = yaml.dump(coreConfig, { indent: 2 });
43
+ fs.writeFileSync(coreConfigPath, updatedYaml);
44
+
45
+ console.log(`✓ BMad Core: ${oldVersion} → ${newVersion}`);
46
+ console.log(`\n✓ Successfully bumped BMad Core with ${bumpType} version bump`);
47
+ console.log('\nNext steps:');
48
+ console.log('1. Test the changes');
49
+ console.log('2. Commit: git add -A && git commit -m "chore: bump core version (' + bumpType + ')"');
50
+
51
+ } catch (error) {
52
+ console.error('Error updating core version:', error.message);
53
+ process.exit(1);
54
+ }
55
+ }
56
+
57
+ bumpCoreVersion();
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const yaml = require('js-yaml');
6
+
7
+ const args = process.argv.slice(2);
8
+
9
+ if (args.length < 1 || args.length > 2) {
10
+ console.log('Usage: node bump-expansion-version.js <expansion-pack-id> [major|minor|patch]');
11
+ console.log('Default: minor');
12
+ console.log('Example: node bump-expansion-version.js bmad-creator-tools patch');
13
+ process.exit(1);
14
+ }
15
+
16
+ const packId = args[0];
17
+ const bumpType = args[1] || 'minor'; // default to minor
18
+
19
+ if (!['major', 'minor', 'patch'].includes(bumpType)) {
20
+ console.error('Error: Bump type must be major, minor, or patch');
21
+ process.exit(1);
22
+ }
23
+
24
+ function bumpVersion(currentVersion, type) {
25
+ const [major, minor, patch] = currentVersion.split('.').map(Number);
26
+
27
+ switch (type) {
28
+ case 'major':
29
+ return `${major + 1}.0.0`;
30
+ case 'minor':
31
+ return `${major}.${minor + 1}.0`;
32
+ case 'patch':
33
+ return `${major}.${minor}.${patch + 1}`;
34
+ default:
35
+ return currentVersion;
36
+ }
37
+ }
38
+
39
+ async function updateVersion() {
40
+ try {
41
+ const configPath = path.join(__dirname, '..', 'expansion-packs', packId, 'config.yml');
42
+
43
+ if (!fs.existsSync(configPath)) {
44
+ console.error(`Error: Expansion pack '${packId}' not found`);
45
+ console.log('\nAvailable expansion packs:');
46
+ const expansionPacksDir = path.join(__dirname, '..', 'expansion-packs');
47
+ const entries = fs.readdirSync(expansionPacksDir, { withFileTypes: true });
48
+ entries.forEach(entry => {
49
+ if (entry.isDirectory() && !entry.name.startsWith('.')) {
50
+ console.log(` - ${entry.name}`);
51
+ }
52
+ });
53
+ process.exit(1);
54
+ }
55
+
56
+ const configContent = fs.readFileSync(configPath, 'utf8');
57
+ const config = yaml.load(configContent);
58
+ const oldVersion = config.version || '1.0.0';
59
+ const newVersion = bumpVersion(oldVersion, bumpType);
60
+
61
+ config.version = newVersion;
62
+
63
+ const updatedYaml = yaml.dump(config, { indent: 2 });
64
+ fs.writeFileSync(configPath, updatedYaml);
65
+
66
+ console.log(`✓ ${packId}: ${oldVersion} → ${newVersion}`);
67
+ console.log(`\n✓ Successfully bumped ${packId} with ${bumpType} version bump`);
68
+ console.log('\nNext steps:');
69
+ console.log('1. Test the changes');
70
+ console.log('2. Commit: git add -A && git commit -m "chore: bump ' + packId + ' version (' + bumpType + ')"');
71
+
72
+ } catch (error) {
73
+ console.error('Error updating version:', error.message);
74
+ process.exit(1);
75
+ }
76
+ }
77
+
78
+ updateVersion();
@@ -2,6 +2,8 @@
2
2
 
3
3
  const { program } = require('commander');
4
4
  const path = require('path');
5
+ const fs = require('fs').promises;
6
+ const yaml = require('js-yaml');
5
7
 
6
8
  // Dynamic imports for ES modules
7
9
  let chalk, inquirer;
@@ -40,22 +42,20 @@ try {
40
42
 
41
43
  program
42
44
  .version(version)
43
- .description('BMAD Method installer - AI-powered Agile development framework');
45
+ .description('BMAD Method installer - Universal AI agent framework for any domain');
44
46
 
45
47
  program
46
48
  .command('install')
47
49
  .description('Install BMAD Method agents and tools')
48
- .option('-f, --full', 'Install complete .bmad-core folder')
49
- .option('-a, --agent <agent>', 'Install specific agent with dependencies')
50
- .option('-t, --team <team>', 'Install specific team with required agents and dependencies')
50
+ .option('-f, --full', 'Install complete BMAD Method')
51
51
  .option('-x, --expansion-only', 'Install only expansion packs (no bmad-core)')
52
- .option('-d, --directory <path>', 'Installation directory (default: .bmad-core)')
52
+ .option('-d, --directory <path>', 'Installation directory')
53
53
  .option('-i, --ide <ide...>', 'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, roo, cline, gemini, other)')
54
54
  .option('-e, --expansion-packs <packs...>', 'Install specific expansion packs (can specify multiple)')
55
55
  .action(async (options) => {
56
56
  try {
57
57
  await initializeModules();
58
- if (!options.full && !options.agent && !options.team && !options.expansionOnly) {
58
+ if (!options.full && !options.expansionOnly) {
59
59
  // Interactive mode
60
60
  const answers = await promptInstallation();
61
61
  if (!answers._alreadyInstalled) {
@@ -64,15 +64,11 @@ program
64
64
  } else {
65
65
  // Direct mode
66
66
  let installType = 'full';
67
- if (options.agent) installType = 'single-agent';
68
- else if (options.team) installType = 'team';
69
- else if (options.expansionOnly) installType = 'expansion-only';
67
+ if (options.expansionOnly) installType = 'expansion-only';
70
68
 
71
69
  const config = {
72
70
  installType,
73
- agent: options.agent,
74
- team: options.team,
75
- directory: options.directory || '.bmad-core',
71
+ directory: options.directory || '.',
76
72
  ides: (options.ide || []).filter(ide => ide !== 'other'),
77
73
  expansionPacks: options.expansionPacks || []
78
74
  };
@@ -100,19 +96,6 @@ program
100
96
  }
101
97
  });
102
98
 
103
- program
104
- .command('list')
105
- .description('List available agents')
106
- .action(async () => {
107
- try {
108
- await installer.listAgents();
109
- } catch (error) {
110
- if (!chalk) await initializeModules();
111
- console.error(chalk.red('Error:'), error.message);
112
- process.exit(1);
113
- }
114
- });
115
-
116
99
  program
117
100
  .command('list:expansions')
118
101
  .description('List available expansion packs')
@@ -145,7 +128,7 @@ async function promptInstallation() {
145
128
 
146
129
  const answers = {};
147
130
 
148
- // Ask for installation directory
131
+ // Ask for installation directory first
149
132
  const { directory } = await inquirer.prompt([
150
133
  {
151
134
  type: 'input',
@@ -161,147 +144,85 @@ async function promptInstallation() {
161
144
  ]);
162
145
  answers.directory = directory;
163
146
 
164
- // Check if this is an existing v4 installation
165
- const installDir = path.resolve(answers.directory);
147
+ // Detect existing installations
148
+ const installDir = path.resolve(directory);
166
149
  const state = await installer.detectInstallationState(installDir);
167
-
150
+
151
+ // Check for existing expansion packs
152
+ const existingExpansionPacks = state.expansionPacks || {};
153
+
154
+ // Get available expansion packs
155
+ const availableExpansionPacks = await installer.getAvailableExpansionPacks();
156
+
157
+ // Build choices list
158
+ const choices = [];
159
+
160
+ // Load core config to get short-title
161
+ const coreConfigPath = path.join(__dirname, '..', '..', '..', 'bmad-core', 'core-config.yml');
162
+ const coreConfig = yaml.load(await fs.readFile(coreConfigPath, 'utf8'));
163
+ const coreShortTitle = coreConfig['short-title'] || 'BMad Agile Core System';
164
+
165
+ // Add BMAD core option
166
+ let bmadOptionText;
168
167
  if (state.type === 'v4_existing') {
169
- console.log(chalk.yellow('\n🔍 Found existing BMAD v4 installation'));
170
- console.log(` Directory: ${installDir}`);
171
- console.log(` Version: ${state.manifest?.version || 'Unknown'}`);
172
- console.log(` Installed: ${state.manifest?.installed_at ? new Date(state.manifest.installed_at).toLocaleDateString() : 'Unknown'}`);
173
-
174
- const { shouldUpdate } = await inquirer.prompt([
175
- {
176
- type: 'confirm',
177
- name: 'shouldUpdate',
178
- message: 'Would you like to update your existing BMAD v4 installation?',
179
- default: true
180
- }
181
- ]);
182
-
183
- if (shouldUpdate) {
184
- // Skip other prompts and go directly to update
185
- answers.installType = 'update';
186
- answers._alreadyInstalled = true; // Flag to prevent double installation
187
- await installer.install(answers);
188
- return answers; // Return the answers object
189
- }
190
- // If user doesn't want to update, continue with normal flow
168
+ const currentVersion = state.manifest?.version || 'unknown';
169
+ const newVersion = coreConfig.version || 'unknown'; // Use version from core-config.yml
170
+ const versionInfo = currentVersion === newVersion
171
+ ? `(v${currentVersion} - reinstall)`
172
+ : `(v${currentVersion} → v${newVersion})`;
173
+ bmadOptionText = `Update ${coreShortTitle} ${versionInfo} .bmad-core`;
174
+ } else {
175
+ bmadOptionText = `Install ${coreShortTitle} (v${coreConfig.version || version}) .bmad-core`;
191
176
  }
192
-
193
- // Ask for installation type
194
- const { installType } = await inquirer.prompt([
195
- {
196
- type: 'list',
197
- name: 'installType',
198
- message: 'How would you like to install BMAD?',
199
- choices: [
200
- {
201
- name: 'Complete installation (recommended) - All agents and tools',
202
- value: 'full'
203
- },
204
- {
205
- name: 'Team installation - Install a specific team with required agents',
206
- value: 'team'
207
- },
208
- {
209
- name: 'Single agent - Choose one agent to install',
210
- value: 'single-agent'
211
- },
212
- {
213
- name: 'Expansion packs only - Install expansion packs without bmad-core',
214
- value: 'expansion-only'
215
- }
216
- ]
177
+
178
+ choices.push({
179
+ name: bmadOptionText,
180
+ value: 'bmad-core',
181
+ checked: true
182
+ });
183
+
184
+ // Add expansion pack options
185
+ for (const pack of availableExpansionPacks) {
186
+ const existing = existingExpansionPacks[pack.id];
187
+ let packOptionText;
188
+
189
+ if (existing) {
190
+ const currentVersion = existing.manifest?.version || 'unknown';
191
+ const newVersion = pack.version;
192
+ const versionInfo = currentVersion === newVersion
193
+ ? `(v${currentVersion} - reinstall)`
194
+ : `(v${currentVersion} v${newVersion})`;
195
+ packOptionText = `Update ${pack.description} ${versionInfo} .${pack.id}`;
196
+ } else {
197
+ packOptionText = `Install ${pack.description} (v${pack.version}) .${pack.id}`;
217
198
  }
218
- ]);
219
- answers.installType = installType;
220
-
221
- // If single agent, ask which one
222
- if (installType === 'single-agent') {
223
- const agents = await installer.getAvailableAgents();
224
- const { agent } = await inquirer.prompt([
225
- {
226
- type: 'list',
227
- name: 'agent',
228
- message: 'Select an agent to install:',
229
- choices: agents.map(a => ({
230
- name: `${a.id} - ${a.name} (${a.description})`,
231
- value: a.id
232
- }))
233
- }
234
- ]);
235
- answers.agent = agent;
236
- }
237
-
238
- // If team installation, ask which team
239
- if (installType === 'team') {
240
- const teams = await installer.getAvailableTeams();
241
- const { team } = await inquirer.prompt([
242
- {
243
- type: 'list',
244
- name: 'team',
245
- message: 'Select a team to install in your IDE project folder:',
246
- choices: teams.map(t => ({
247
- name: `${t.icon || '📋'} ${t.name}: ${t.description}`,
248
- value: t.id
249
- }))
250
- }
251
- ]);
252
- answers.team = team;
199
+
200
+ choices.push({
201
+ name: packOptionText,
202
+ value: pack.id,
203
+ checked: false
204
+ });
253
205
  }
254
-
255
- // Ask for expansion pack selection
256
- if (installType === 'full' || installType === 'team' || installType === 'expansion-only') {
257
- try {
258
- const availableExpansionPacks = await installer.getAvailableExpansionPacks();
259
-
260
- if (availableExpansionPacks.length > 0) {
261
- let choices;
262
- let message;
263
-
264
- if (installType === 'expansion-only') {
265
- message = 'Select expansion packs to install (required):'
266
- choices = availableExpansionPacks.map(pack => ({
267
- name: `${pack.name} - ${pack.description}`,
268
- value: pack.id
269
- }));
270
- } else {
271
- message = 'Select expansion packs to install (press Enter to skip, or check any to install):';
272
- choices = availableExpansionPacks.map(pack => ({
273
- name: `${pack.name} - ${pack.description}`,
274
- value: pack.id
275
- }));
206
+
207
+ // Ask what to install
208
+ const { selectedItems } = await inquirer.prompt([
209
+ {
210
+ type: 'checkbox',
211
+ name: 'selectedItems',
212
+ message: 'Select what to install/update (use space to select, enter to continue):',
213
+ choices: choices,
214
+ validate: (selected) => {
215
+ if (selected.length === 0) {
216
+ return 'Please select at least one item to install';
276
217
  }
277
-
278
- const { expansionPacks } = await inquirer.prompt([
279
- {
280
- type: 'checkbox',
281
- name: 'expansionPacks',
282
- message,
283
- choices,
284
- validate: installType === 'expansion-only' ? (answer) => {
285
- if (answer.length < 1) {
286
- return 'You must select at least one expansion pack for expansion-only installation.';
287
- }
288
- return true;
289
- } : undefined
290
- }
291
- ]);
292
-
293
- // Use selected expansion packs directly
294
- answers.expansionPacks = expansionPacks;
295
- } else {
296
- answers.expansionPacks = [];
218
+ return true;
297
219
  }
298
- } catch (error) {
299
- console.warn(chalk.yellow('Warning: Could not load expansion packs. Continuing without them.'));
300
- answers.expansionPacks = [];
301
220
  }
302
- } else {
303
- answers.expansionPacks = [];
304
- }
221
+ ]);
222
+
223
+ // Process selections
224
+ answers.installType = selectedItems.includes('bmad-core') ? 'full' : 'expansion-only';
225
+ answers.expansionPacks = selectedItems.filter(item => item !== 'bmad-core');
305
226
 
306
227
  // Ask for IDE configuration
307
228
  const { ides } = await inquirer.prompt([
@@ -329,7 +250,7 @@ async function promptInstallation() {
329
250
  type: 'confirm',
330
251
  name: 'includeWebBundles',
331
252
  message: 'Would you like to include pre-built web bundles? (standalone files for ChatGPT, Claude, Gemini)',
332
- default: true
253
+ default: false
333
254
  }
334
255
  ]);
335
256
 
@@ -83,12 +83,22 @@ class FileManager {
83
83
  this.manifestFile
84
84
  );
85
85
 
86
+ // Read version from core-config.yml
87
+ const coreConfigPath = path.join(__dirname, "../../../bmad-core/core-config.yml");
88
+ let coreVersion = "unknown";
89
+ try {
90
+ const coreConfigContent = await fs.readFile(coreConfigPath, "utf8");
91
+ const coreConfig = yaml.load(coreConfigContent);
92
+ coreVersion = coreConfig.version || "unknown";
93
+ } catch (error) {
94
+ console.warn("Could not read version from core-config.yml, using 'unknown'");
95
+ }
96
+
86
97
  const manifest = {
87
- version: require("../../../package.json").version,
98
+ version: coreVersion,
88
99
  installed_at: new Date().toISOString(),
89
100
  install_type: config.installType,
90
101
  agent: config.agent || null,
91
- ide_setup: config.ide || null,
92
102
  ides_setup: config.ides || [],
93
103
  expansion_packs: config.expansionPacks || [],
94
104
  files: [],
@@ -128,6 +138,21 @@ class FileManager {
128
138
  }
129
139
  }
130
140
 
141
+ async readExpansionPackManifest(installDir, packId) {
142
+ const manifestPath = path.join(
143
+ installDir,
144
+ `.${packId}`,
145
+ this.manifestFile
146
+ );
147
+
148
+ try {
149
+ const content = await fs.readFile(manifestPath, "utf8");
150
+ return yaml.load(content);
151
+ } catch (error) {
152
+ return null;
153
+ }
154
+ }
155
+
131
156
  async checkModifiedFiles(installDir, manifest) {
132
157
  const modified = [];
133
158
 
@@ -143,6 +168,33 @@ class FileManager {
143
168
  return modified;
144
169
  }
145
170
 
171
+ async checkFileIntegrity(installDir, manifest) {
172
+ const result = {
173
+ missing: [],
174
+ modified: []
175
+ };
176
+
177
+ for (const file of manifest.files) {
178
+ const filePath = path.join(installDir, file.path);
179
+
180
+ // Skip checking the manifest file itself - it will always be different due to timestamps
181
+ if (file.path.endsWith('install-manifest.yml')) {
182
+ continue;
183
+ }
184
+
185
+ if (!(await this.pathExists(filePath))) {
186
+ result.missing.push(file.path);
187
+ } else {
188
+ const currentHash = await this.calculateFileHash(filePath);
189
+ if (currentHash && currentHash !== file.hash) {
190
+ result.modified.push(file.path);
191
+ }
192
+ }
193
+ }
194
+
195
+ return result;
196
+ }
197
+
146
198
  async backupFile(filePath) {
147
199
  const backupPath = filePath + ".bak";
148
200
  let counter = 1;
@@ -183,6 +235,42 @@ class FileManager {
183
235
  async removeDirectory(dirPath) {
184
236
  await fs.remove(dirPath);
185
237
  }
238
+
239
+ async createExpansionPackManifest(installDir, packId, config, files) {
240
+ const manifestPath = path.join(
241
+ installDir,
242
+ `.${packId}`,
243
+ this.manifestFile
244
+ );
245
+
246
+ const manifest = {
247
+ version: config.expansionPackVersion || require("../../../package.json").version,
248
+ installed_at: new Date().toISOString(),
249
+ install_type: config.installType,
250
+ expansion_pack_id: config.expansionPackId,
251
+ expansion_pack_name: config.expansionPackName,
252
+ ides_setup: config.ides || [],
253
+ files: [],
254
+ };
255
+
256
+ // Add file information
257
+ for (const file of files) {
258
+ const filePath = path.join(installDir, file);
259
+ const hash = await this.calculateFileHash(filePath);
260
+
261
+ manifest.files.push({
262
+ path: file,
263
+ hash: hash,
264
+ modified: false,
265
+ });
266
+ }
267
+
268
+ // Write manifest
269
+ await fs.ensureDir(path.dirname(manifestPath));
270
+ await fs.writeFile(manifestPath, yaml.dump(manifest, { indent: 2 }));
271
+
272
+ return manifest;
273
+ }
186
274
  }
187
275
 
188
276
  module.exports = new FileManager();