bmad-method 4.16.1 → 4.18.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 (45) hide show
  1. package/.claude/commands/bmad-master.md +0 -1
  2. package/CHANGELOG.md +15 -0
  3. package/{bmad-core → common}/tasks/create-doc.md +2 -2
  4. package/{expansion-packs/expansion-creator/common-tasks → common/tasks}/execute-checklist.md +2 -6
  5. package/common/utils/workflow-management.md +69 -0
  6. package/dist/agents/analyst.txt +2 -2
  7. package/dist/agents/architect.txt +4 -8
  8. package/dist/agents/bmad-master.txt +35 -270
  9. package/dist/agents/bmad-orchestrator.txt +33 -187
  10. package/dist/agents/dev.txt +2 -6
  11. package/dist/agents/pm.txt +4 -8
  12. package/dist/agents/po.txt +2 -6
  13. package/dist/agents/sm.txt +2 -6
  14. package/dist/agents/ux-expert.txt +4 -8
  15. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +4 -8
  16. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +2 -6
  17. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +2 -6
  18. package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +35 -193
  19. package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +2 -2
  20. package/dist/expansion-packs/expansion-creator/agents/bmad-the-creator.txt +5 -5
  21. package/dist/teams/team-all.txt +35 -193
  22. package/dist/teams/team-fullstack.txt +35 -193
  23. package/dist/teams/team-ide-minimal.txt +35 -193
  24. package/dist/teams/team-no-ui.txt +35 -193
  25. package/docs/working-in-the-brownfield.md +2 -2
  26. package/expansion-packs/expansion-creator/tasks/generate-expansion-pack.md +5 -5
  27. package/package.json +1 -1
  28. package/tools/builders/web-builder.js +60 -19
  29. package/tools/installer/config/install.config.yml +0 -85
  30. package/tools/installer/lib/config-loader.js +57 -30
  31. package/tools/installer/lib/file-manager.js +1 -0
  32. package/tools/installer/lib/ide-setup.js +47 -26
  33. package/tools/installer/lib/installer.js +250 -8
  34. package/tools/installer/package.json +1 -1
  35. package/tools/lib/dependency-resolver.js +15 -0
  36. package/bmad-core/tasks/core-dump.md +0 -74
  37. package/bmad-core/tasks/execute-checklist.md +0 -97
  38. package/bmad-core/utils/file-resolution-context.md +0 -10
  39. package/bmad-core/utils/workflow-management.md +0 -223
  40. package/expansion-packs/bmad-infrastructure-devops/tasks/create-doc.md +0 -74
  41. package/expansion-packs/expansion-creator/common-tasks/create-doc.md +0 -74
  42. package/expansion-packs/expansion-creator/utils/template-format.md +0 -26
  43. package/expansion-packs/expansion-creator/utils/workflow-management.md +0 -223
  44. /package/{bmad-core → common}/utils/template-format.md +0 -0
  45. /package/{bmad-core/utils → tools/md-assets}/web-agent-startup-instructions.md +0 -0
@@ -90,6 +90,7 @@ class FileManager {
90
90
  agent: config.agent || null,
91
91
  ide_setup: config.ide || null,
92
92
  ides_setup: config.ides || [],
93
+ expansion_packs: config.expansionPacks || [],
93
94
  files: [],
94
95
  };
95
96
 
@@ -65,8 +65,9 @@ class IdeSetup {
65
65
  mdcContent += "alwaysApply: false\n";
66
66
  mdcContent += "---\n\n";
67
67
  mdcContent += `# ${agentId.toUpperCase()} Agent Rule\n\n`;
68
- mdcContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${this.getAgentTitle(
69
- agentId
68
+ mdcContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${await this.getAgentTitle(
69
+ agentId,
70
+ installDir
70
71
  )} agent persona.\n\n`;
71
72
  mdcContent += "## Agent Activation\n\n";
72
73
  mdcContent +=
@@ -84,8 +85,9 @@ class IdeSetup {
84
85
  mdcContent += "## File Reference\n\n";
85
86
  mdcContent += `The complete agent definition is available in [.bmad-core/agents/${agentId}.md](mdc:.bmad-core/agents/${agentId}.md).\n\n`;
86
87
  mdcContent += "## Usage\n\n";
87
- mdcContent += `When the user types \`@${agentId}\`, activate this ${this.getAgentTitle(
88
- agentId
88
+ mdcContent += `When the user types \`@${agentId}\`, activate this ${await this.getAgentTitle(
89
+ agentId,
90
+ installDir
89
91
  )} persona and follow all instructions defined in the YML configuration above.\n`;
90
92
 
91
93
  await fileManager.writeFile(mdcPath, mdcContent);
@@ -150,8 +152,9 @@ class IdeSetup {
150
152
 
151
153
  // Create MD content (similar to Cursor but without frontmatter)
152
154
  let mdContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
153
- mdContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${this.getAgentTitle(
154
- agentId
155
+ mdContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${await this.getAgentTitle(
156
+ agentId,
157
+ installDir
155
158
  )} agent persona.\n\n`;
156
159
  mdContent += "## Agent Activation\n\n";
157
160
  mdContent +=
@@ -169,8 +172,9 @@ class IdeSetup {
169
172
  mdContent += "## File Reference\n\n";
170
173
  mdContent += `The complete agent definition is available in [.bmad-core/agents/${agentId}.md](.bmad-core/agents/${agentId}.md).\n\n`;
171
174
  mdContent += "## Usage\n\n";
172
- mdContent += `When the user types \`@${agentId}\`, activate this ${this.getAgentTitle(
173
- agentId
175
+ mdContent += `When the user types \`@${agentId}\`, activate this ${await this.getAgentTitle(
176
+ agentId,
177
+ installDir
174
178
  )} persona and follow all instructions defined in the YML configuration above.\n`;
175
179
 
176
180
  await fileManager.writeFile(mdPath, mdContent);
@@ -195,20 +199,34 @@ class IdeSetup {
195
199
  return agentFiles.map((file) => path.basename(file, ".md"));
196
200
  }
197
201
 
198
- getAgentTitle(agentId) {
199
- const agentTitles = {
200
- analyst: "Business Analyst",
201
- architect: "Solution Architect",
202
- "bmad-master": "BMAD Master",
203
- "bmad-orchestrator": "BMAD Orchestrator",
204
- dev: "Developer",
205
- pm: "Product Manager",
206
- po: "Product Owner",
207
- qa: "QA Specialist",
208
- sm: "Scrum Master",
209
- "ux-expert": "UX Expert",
210
- };
211
- return agentTitles[agentId] || agentId;
202
+ async getAgentTitle(agentId, installDir) {
203
+ // Try to read the actual agent file to get the title
204
+ let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`);
205
+ if (!(await fileManager.pathExists(agentPath))) {
206
+ agentPath = path.join(installDir, "agents", `${agentId}.md`);
207
+ }
208
+
209
+ if (await fileManager.pathExists(agentPath)) {
210
+ try {
211
+ const agentContent = await fileManager.readFile(agentPath);
212
+ const yamlMatch = agentContent.match(/```ya?ml\n([\s\S]*?)```/);
213
+
214
+ if (yamlMatch) {
215
+ const yaml = yamlMatch[1];
216
+ const titleMatch = yaml.match(/title:\s*(.+)/);
217
+ if (titleMatch) {
218
+ return titleMatch[1].trim();
219
+ }
220
+ }
221
+ } catch (error) {
222
+ console.warn(`Failed to read agent title for ${agentId}: ${error.message}`);
223
+ }
224
+ }
225
+
226
+ // Fallback to formatted agent ID
227
+ return agentId.split('-').map(word =>
228
+ word.charAt(0).toUpperCase() + word.slice(1)
229
+ ).join(' ');
212
230
  }
213
231
 
214
232
  async setupRoo(installDir, selectedAgent) {
@@ -294,7 +312,7 @@ class IdeSetup {
294
312
  const whenToUseMatch = yaml.match(/whenToUse:\s*"(.+)"/);
295
313
  const roleDefinitionMatch = yaml.match(/roleDefinition:\s*"(.+)"/);
296
314
 
297
- const title = titleMatch ? titleMatch[1].trim() : this.getAgentTitle(agentId);
315
+ const title = titleMatch ? titleMatch[1].trim() : await this.getAgentTitle(agentId, installDir);
298
316
  const icon = iconMatch ? iconMatch[1].trim() : "🤖";
299
317
  const whenToUse = whenToUseMatch ? whenToUseMatch[1].trim() : `Use for ${title} tasks`;
300
318
  const roleDefinition = roleDefinitionMatch
@@ -381,8 +399,8 @@ class IdeSetup {
381
399
  const mdPath = path.join(clineRulesDir, `${prefix}-${agentId}.md`);
382
400
 
383
401
  // Create MD content for Cline (focused on project standards and role)
384
- let mdContent = `# ${this.getAgentTitle(agentId)} Agent\n\n`;
385
- mdContent += `This rule defines the ${this.getAgentTitle(agentId)} persona and project standards.\n\n`;
402
+ let mdContent = `# ${await this.getAgentTitle(agentId, installDir)} Agent\n\n`;
403
+ mdContent += `This rule defines the ${await this.getAgentTitle(agentId, installDir)} persona and project standards.\n\n`;
386
404
  mdContent += "## Role Definition\n\n";
387
405
  mdContent +=
388
406
  "When the user types `@" + agentId + "`, adopt this persona and follow these guidelines:\n\n";
@@ -402,7 +420,7 @@ class IdeSetup {
402
420
  mdContent += `- Update relevant project files when making changes\n`;
403
421
  mdContent += `- Reference the complete agent definition in [.bmad-core/agents/${agentId}.md](.bmad-core/agents/${agentId}.md)\n\n`;
404
422
  mdContent += "## Usage\n\n";
405
- mdContent += `Type \`@${agentId}\` to activate this ${this.getAgentTitle(agentId)} persona.\n`;
423
+ mdContent += `Type \`@${agentId}\` to activate this ${await this.getAgentTitle(agentId, installDir)} persona.\n`;
406
424
 
407
425
  await fileManager.writeFile(mdPath, mdContent);
408
426
  console.log(chalk.green(`✓ Created rule: ${prefix}-${agentId}.md`));
@@ -447,6 +465,9 @@ class IdeSetup {
447
465
 
448
466
  console.log(chalk.green(`\n✓ Created individual agent context files in ${agentsContextDir}`));
449
467
 
468
+ // Add GEMINI.md to the context files array
469
+ agentContextFiles.push("GEMINI.md");
470
+
450
471
  // Create or update settings.json
451
472
  const settingsPath = path.join(geminiDir, "settings.json");
452
473
  let settings = {};
@@ -225,6 +225,10 @@ class Installer {
225
225
  const sourceDir = configLoader.getBmadCorePath();
226
226
  const bmadCoreDestDir = path.join(installDir, ".bmad-core");
227
227
  await fileManager.copyDirectory(sourceDir, bmadCoreDestDir);
228
+
229
+ // Copy common/ items to .bmad-core
230
+ spinner.text = "Copying common utilities...";
231
+ await this.copyCommonItems(installDir, ".bmad-core", spinner);
228
232
 
229
233
  // Get list of all files for manifest
230
234
  const glob = require("glob");
@@ -283,6 +287,11 @@ class Installer {
283
287
  }
284
288
  }
285
289
  }
290
+
291
+ // Copy common/ items to .bmad-core
292
+ spinner.text = "Copying common utilities...";
293
+ const commonFiles = await this.copyCommonItems(installDir, ".bmad-core", spinner);
294
+ files.push(...commonFiles);
286
295
  } else if (config.installType === "team") {
287
296
  // Team installation
288
297
  spinner.text = `Installing ${config.team} team...`;
@@ -313,6 +322,11 @@ class Installer {
313
322
  }
314
323
  }
315
324
  }
325
+
326
+ // Copy common/ items to .bmad-core
327
+ spinner.text = "Copying common utilities...";
328
+ const commonFiles = await this.copyCommonItems(installDir, ".bmad-core", spinner);
329
+ files.push(...commonFiles);
316
330
  } else if (config.installType === "expansion-only") {
317
331
  // Expansion-only installation - create minimal .bmad-core structure
318
332
  spinner.text = "Creating minimal .bmad-core structure for expansion packs...";
@@ -341,6 +355,10 @@ class Installer {
341
355
  );
342
356
  files.push(...copiedFiles.map(f => `.bmad-core/${f}`));
343
357
  }
358
+
359
+ // Copy common/ items to .bmad-core
360
+ spinner.text = "Copying common utilities...";
361
+ await this.copyCommonItems(installDir, ".bmad-core", spinner);
344
362
  }
345
363
 
346
364
  // Install expansion packs if requested
@@ -607,8 +625,10 @@ class Installer {
607
625
  console.log(chalk.green("✓ .bmad-core framework installed with all agents and workflows"));
608
626
 
609
627
  if (config.expansionPacks && config.expansionPacks.length > 0) {
610
- const packNames = config.expansionPacks.join(", ");
611
- console.log(chalk.green(`✓ Expansion packs installed: ${packNames}`));
628
+ console.log(chalk.green(`✓ Expansion packs installed:`));
629
+ for (const packId of config.expansionPacks) {
630
+ console.log(chalk.green(` - ${packId} → .${packId}/`));
631
+ }
612
632
  }
613
633
 
614
634
  if (config.includeWebBundles && config.webBundlesDirectory) {
@@ -799,7 +819,11 @@ class Installer {
799
819
 
800
820
  const expansionPackDir = path.dirname(pack.manifestPath);
801
821
 
802
- // Define the folders to copy from expansion packs to .bmad-core
822
+ // Create dedicated dot folder for this expansion pack
823
+ const expansionDotFolder = path.join(installDir, `.${packId}`);
824
+ await fileManager.ensureDirectory(expansionDotFolder);
825
+
826
+ // Define the folders to copy from expansion packs
803
827
  const foldersToSync = [
804
828
  'agents',
805
829
  'agent-teams',
@@ -824,21 +848,35 @@ class Installer {
824
848
  nodir: true
825
849
  });
826
850
 
827
- // Copy each file to the destination
851
+ // Copy each file to the expansion pack's dot folder
828
852
  for (const file of files) {
829
853
  const sourcePath = path.join(sourceFolder, file);
830
- const destPath = path.join(installDir, '.bmad-core', folder, file);
854
+ const destPath = path.join(expansionDotFolder, folder, file);
831
855
 
832
856
  if (await fileManager.copyFile(sourcePath, destPath)) {
833
- installedFiles.push(path.join('.bmad-core', folder, file));
857
+ installedFiles.push(path.join(`.${packId}`, folder, file));
834
858
  }
835
859
  }
836
860
  }
837
861
  }
838
862
 
839
- // Web bundles are now available in the dist/ directory and don't need to be copied
863
+ // Copy manifest to the expansion pack's dot folder
864
+ const manifestDestPath = path.join(expansionDotFolder, 'manifest.yml');
865
+ if (await fileManager.copyFile(pack.manifestPath, manifestDestPath)) {
866
+ installedFiles.push(path.join(`.${packId}`, 'manifest.yml'));
867
+ }
840
868
 
841
- console.log(chalk.green(`✓ Installed expansion pack: ${pack.name}`));
869
+ // Copy common/ items to expansion pack folder
870
+ spinner.text = `Copying common utilities to ${packId}...`;
871
+ await this.copyCommonItems(installDir, `.${packId}`, spinner);
872
+
873
+ // Check and resolve core dependencies
874
+ await this.resolveExpansionPackCoreDependencies(installDir, expansionDotFolder, packId, spinner);
875
+
876
+ // Check and resolve core agents referenced by teams
877
+ await this.resolveExpansionPackCoreAgents(installDir, expansionDotFolder, packId, spinner);
878
+
879
+ console.log(chalk.green(`✓ Installed expansion pack: ${pack.name} to ${`.${packId}`}`));
842
880
  } catch (error) {
843
881
  console.error(chalk.red(`Failed to install expansion pack ${packId}: ${error.message}`));
844
882
  }
@@ -847,6 +885,168 @@ class Installer {
847
885
  return installedFiles;
848
886
  }
849
887
 
888
+ async resolveExpansionPackCoreDependencies(installDir, expansionDotFolder, packId, spinner) {
889
+ const glob = require('glob');
890
+ const yaml = require('yaml');
891
+ const fs = require('fs').promises;
892
+
893
+ // Find all agent files in the expansion pack
894
+ const agentFiles = glob.sync('agents/*.md', {
895
+ cwd: expansionDotFolder
896
+ });
897
+
898
+ for (const agentFile of agentFiles) {
899
+ const agentPath = path.join(expansionDotFolder, agentFile);
900
+ const agentContent = await fs.readFile(agentPath, 'utf8');
901
+
902
+ // Extract YAML frontmatter to check dependencies
903
+ const yamlMatch = agentContent.match(/```yaml\n([\s\S]*?)```/);
904
+ if (yamlMatch) {
905
+ try {
906
+ const agentConfig = yaml.parse(yamlMatch[1]);
907
+ const dependencies = agentConfig.dependencies || {};
908
+
909
+ // Check for core dependencies (those that don't exist in the expansion pack)
910
+ for (const depType of ['tasks', 'templates', 'checklists', 'workflows', 'utils', 'data']) {
911
+ const deps = dependencies[depType] || [];
912
+
913
+ for (const dep of deps) {
914
+ const depFileName = dep.endsWith('.md') ? dep : `${dep}.md`;
915
+ const expansionDepPath = path.join(expansionDotFolder, depType, depFileName);
916
+
917
+ // Check if dependency exists in expansion pack
918
+ if (!(await fileManager.pathExists(expansionDepPath))) {
919
+ // Try to find it in core
920
+ const coreDepPath = path.join(configLoader.getBmadCorePath(), depType, depFileName);
921
+
922
+ if (await fileManager.pathExists(coreDepPath)) {
923
+ spinner.text = `Copying core dependency ${dep} for ${packId}...`;
924
+
925
+ // Copy from core to expansion pack dot folder
926
+ const destPath = path.join(expansionDotFolder, depType, depFileName);
927
+ await fileManager.copyFile(coreDepPath, destPath);
928
+
929
+ console.log(chalk.dim(` Added core dependency: ${depType}/${depFileName}`));
930
+ } else {
931
+ console.warn(chalk.yellow(` Warning: Dependency ${depType}/${dep} not found in core or expansion pack`));
932
+ }
933
+ }
934
+ }
935
+ }
936
+ } catch (error) {
937
+ console.warn(chalk.yellow(` Warning: Could not parse agent dependencies: ${error.message}`));
938
+ }
939
+ }
940
+ }
941
+ }
942
+
943
+ async resolveExpansionPackCoreAgents(installDir, expansionDotFolder, packId, spinner) {
944
+ const glob = require('glob');
945
+ const yaml = require('yaml');
946
+ const fs = require('fs').promises;
947
+
948
+ // Find all team files in the expansion pack
949
+ const teamFiles = glob.sync('agent-teams/*.yml', {
950
+ cwd: expansionDotFolder
951
+ });
952
+
953
+ // Also get existing agents in the expansion pack
954
+ const existingAgents = new Set();
955
+ const agentFiles = glob.sync('agents/*.md', {
956
+ cwd: expansionDotFolder
957
+ });
958
+ for (const agentFile of agentFiles) {
959
+ const agentName = path.basename(agentFile, '.md');
960
+ existingAgents.add(agentName);
961
+ }
962
+
963
+ // Process each team file
964
+ for (const teamFile of teamFiles) {
965
+ const teamPath = path.join(expansionDotFolder, teamFile);
966
+ const teamContent = await fs.readFile(teamPath, 'utf8');
967
+
968
+ try {
969
+ const teamConfig = yaml.parse(teamContent);
970
+ const agents = teamConfig.agents || [];
971
+
972
+ // Add bmad-orchestrator if not present (required for all teams)
973
+ if (!agents.includes('bmad-orchestrator')) {
974
+ agents.unshift('bmad-orchestrator');
975
+ }
976
+
977
+ // Check each agent in the team
978
+ for (const agentId of agents) {
979
+ if (!existingAgents.has(agentId)) {
980
+ // Agent not in expansion pack, try to get from core
981
+ const coreAgentPath = path.join(configLoader.getBmadCorePath(), 'agents', `${agentId}.md`);
982
+
983
+ if (await fileManager.pathExists(coreAgentPath)) {
984
+ spinner.text = `Copying core agent ${agentId} for ${packId}...`;
985
+
986
+ // Copy agent file
987
+ const destPath = path.join(expansionDotFolder, 'agents', `${agentId}.md`);
988
+ await fileManager.copyFile(coreAgentPath, destPath);
989
+ existingAgents.add(agentId);
990
+
991
+ console.log(chalk.dim(` Added core agent: ${agentId}`));
992
+
993
+ // Now resolve this agent's dependencies too
994
+ const agentContent = await fs.readFile(coreAgentPath, 'utf8');
995
+ const yamlMatch = agentContent.match(/```ya?ml\n([\s\S]*?)```/);
996
+
997
+ if (yamlMatch) {
998
+ try {
999
+ // Clean up the YAML to handle command descriptions
1000
+ let yamlContent = yamlMatch[1];
1001
+ yamlContent = yamlContent.replace(/^(\s*-)(\s*"[^"]+")(\s*-\s*.*)$/gm, '$1$2');
1002
+
1003
+ const agentConfig = yaml.parse(yamlContent);
1004
+ const dependencies = agentConfig.dependencies || {};
1005
+
1006
+ // Copy all dependencies for this agent
1007
+ for (const depType of ['tasks', 'templates', 'checklists', 'workflows', 'utils', 'data']) {
1008
+ const deps = dependencies[depType] || [];
1009
+
1010
+ for (const dep of deps) {
1011
+ const depFileName = dep.endsWith('.md') || dep.endsWith('.yml') ? dep : `${dep}.md`;
1012
+ const expansionDepPath = path.join(expansionDotFolder, depType, depFileName);
1013
+
1014
+ // Check if dependency exists in expansion pack
1015
+ if (!(await fileManager.pathExists(expansionDepPath))) {
1016
+ // Try to find it in core
1017
+ const coreDepPath = path.join(configLoader.getBmadCorePath(), depType, depFileName);
1018
+
1019
+ if (await fileManager.pathExists(coreDepPath)) {
1020
+ const destDepPath = path.join(expansionDotFolder, depType, depFileName);
1021
+ await fileManager.copyFile(coreDepPath, destDepPath);
1022
+ console.log(chalk.dim(` Added agent dependency: ${depType}/${depFileName}`));
1023
+ } else {
1024
+ // Try common folder
1025
+ const commonDepPath = path.join(this.rootDir, 'common', depType, depFileName);
1026
+ if (await fileManager.pathExists(commonDepPath)) {
1027
+ const destDepPath = path.join(expansionDotFolder, depType, depFileName);
1028
+ await fileManager.copyFile(commonDepPath, destDepPath);
1029
+ console.log(chalk.dim(` Added agent dependency from common: ${depType}/${depFileName}`));
1030
+ }
1031
+ }
1032
+ }
1033
+ }
1034
+ }
1035
+ } catch (error) {
1036
+ console.warn(chalk.yellow(` Warning: Could not parse agent ${agentId} dependencies: ${error.message}`));
1037
+ }
1038
+ }
1039
+ } else {
1040
+ console.warn(chalk.yellow(` Warning: Core agent ${agentId} not found for team ${path.basename(teamFile, '.yml')}`));
1041
+ }
1042
+ }
1043
+ }
1044
+ } catch (error) {
1045
+ console.warn(chalk.yellow(` Warning: Could not parse team file ${teamFile}: ${error.message}`));
1046
+ }
1047
+ }
1048
+ }
1049
+
850
1050
  getWebBundleInfo(config) {
851
1051
  const webBundleType = config.webBundleType || 'all';
852
1052
 
@@ -944,6 +1144,48 @@ class Installer {
944
1144
  }
945
1145
  }
946
1146
 
1147
+ async copyCommonItems(installDir, targetSubdir, spinner) {
1148
+ const glob = require('glob');
1149
+ const fs = require('fs').promises;
1150
+ const sourceBase = path.dirname(path.dirname(path.dirname(path.dirname(__filename)))); // Go up to project root
1151
+ const commonPath = path.join(sourceBase, 'common');
1152
+ const targetPath = path.join(installDir, targetSubdir);
1153
+ const copiedFiles = [];
1154
+
1155
+ // Check if common/ exists
1156
+ if (!(await fileManager.pathExists(commonPath))) {
1157
+ console.warn(chalk.yellow('Warning: common/ folder not found'));
1158
+ return copiedFiles;
1159
+ }
1160
+
1161
+ // Copy all items from common/ to target
1162
+ const commonItems = glob.sync('**/*', {
1163
+ cwd: commonPath,
1164
+ nodir: true
1165
+ });
1166
+
1167
+ for (const item of commonItems) {
1168
+ const sourcePath = path.join(commonPath, item);
1169
+ const destPath = path.join(targetPath, item);
1170
+
1171
+ // Read the file content
1172
+ const content = await fs.readFile(sourcePath, 'utf8');
1173
+
1174
+ // Replace {root} with the target subdirectory
1175
+ const updatedContent = content.replace(/\{root\}/g, targetSubdir);
1176
+
1177
+ // Ensure directory exists
1178
+ await fileManager.ensureDirectory(path.dirname(destPath));
1179
+
1180
+ // Write the updated content
1181
+ await fs.writeFile(destPath, updatedContent, 'utf8');
1182
+ copiedFiles.push(path.join(targetSubdir, item));
1183
+ }
1184
+
1185
+ console.log(chalk.dim(` Added ${commonItems.length} common utilities`));
1186
+ return copiedFiles;
1187
+ }
1188
+
947
1189
  async findInstallation() {
948
1190
  // Look for .bmad-core in current directory or parent directories
949
1191
  let currentDir = process.cwd();
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bmad-method",
3
- "version": "4.16.1",
3
+ "version": "4.18.0",
4
4
  "description": "BMAD Method installer - AI-powered Agile development framework",
5
5
  "main": "lib/installer.js",
6
6
  "bin": {
@@ -6,6 +6,7 @@ class DependencyResolver {
6
6
  constructor(rootDir) {
7
7
  this.rootDir = rootDir;
8
8
  this.bmadCore = path.join(rootDir, 'bmad-core');
9
+ this.common = path.join(rootDir, 'common');
9
10
  this.cache = new Map();
10
11
  }
11
12
 
@@ -123,6 +124,7 @@ class DependencyResolver {
123
124
  let content = null;
124
125
  let filePath = null;
125
126
 
127
+ // First try bmad-core
126
128
  for (const ext of extensions) {
127
129
  try {
128
130
  filePath = path.join(this.bmadCore, type, `${id}${ext}`);
@@ -132,6 +134,19 @@ class DependencyResolver {
132
134
  // Try next extension
133
135
  }
134
136
  }
137
+
138
+ // If not found in bmad-core, try common folder
139
+ if (!content) {
140
+ for (const ext of extensions) {
141
+ try {
142
+ filePath = path.join(this.common, type, `${id}${ext}`);
143
+ content = await fs.readFile(filePath, 'utf8');
144
+ break;
145
+ } catch (e) {
146
+ // Try next extension
147
+ }
148
+ }
149
+ }
135
150
 
136
151
  if (!content) {
137
152
  console.warn(`Resource not found: ${type}/${id}`);
@@ -1,74 +0,0 @@
1
- # Core Dump Task
2
-
3
- ## Purpose
4
-
5
- To create a concise memory recording file (`.ai/core-dump-n.md`) that captures the essential context of the current agent session, enabling seamless continuation of work in future agent sessions. This task ensures persistent context across agent conversations while maintaining minimal token usage for efficient context loading.
6
-
7
- ## Inputs for this Task
8
-
9
- - Current session conversation history and accomplishments
10
- - Files created, modified, or deleted during the session
11
- - Key decisions made and procedures followed
12
- - Current project state and next logical steps
13
- - User requests and agent responses that shaped the session
14
-
15
- ## Task Execution Instructions
16
-
17
- ### 0. Check Existing Core Dump
18
-
19
- Before proceeding, check if `.ai/core-dump.md` already exists:
20
-
21
- - If file exists, ask user: "Core dump file exists. Should I: 1. Overwrite, 2. Update, 3. Append or 4. Create new?"
22
- - **Overwrite**: Replace entire file with new content
23
- - **Update**: Merge new session info with existing content, updating relevant sections
24
- - **Append**: Add new session as a separate entry while preserving existing content
25
- - **Create New**: Create a new file, appending the next possible -# to the file, such as core-dump-3.md if 1 and 2 already exist.
26
- - If file doesn't exist, proceed with creation of `core-dump-1.md`
27
-
28
- ### 1. Analyze Session Context
29
-
30
- - Review the entire conversation to identify key accomplishments
31
- - Note any specific tasks, procedures, or workflows that were executed
32
- - Identify important decisions made or problems solved
33
- - Capture the user's working style and preferences observed during the session
34
-
35
- ### 2. Document What Was Accomplished
36
-
37
- - **Primary Actions**: List the main tasks completed concisely
38
- - **Story Progress**: For story work, use format "Tasks Complete: 1-6, 8. Next Task Pending: 7, 9"
39
- - **Problem Solving**: Document any challenges encountered and how they were resolved
40
- - **User Communications**: Summarize key user requests, preferences, and discussion points
41
-
42
- ### 3. Record File System Changes (Concise Format)
43
-
44
- - **Files Created**: `filename.ext` (brief purpose/size)
45
- - **Files Modified**: `filename.ext` (what changed)
46
- - **Files Deleted**: `filename.ext` (why removed)
47
- - Focus on essential details, avoid verbose descriptions
48
-
49
- ### 4. Capture Current Project State
50
-
51
- - **Project Progress**: Where the project stands after this session
52
- - **Current Issues**: Any blockers or problems that need resolution
53
- - **Next Logical Steps**: What would be the natural next actions to take
54
-
55
- ### 5. Create/Update Core Dump File
56
-
57
- Based on user's choice from step 0, handle the file accordingly:
58
-
59
- ### 6. Optimize for Minimal Context
60
-
61
- - Keep descriptions concise but informative
62
- - Use abbreviated formats where possible (file sizes, task numbers)
63
- - Focus on actionable information rather than detailed explanations
64
- - Avoid redundant information that can be found in project documentation
65
- - Prioritize information that would be lost without this recording
66
- - Ensure the file can be quickly scanned and understood
67
-
68
- ### 7. Validate Completeness
69
-
70
- - Verify all significant session activities are captured
71
- - Ensure a future agent could understand the current state
72
- - Check that file changes are accurately recorded
73
- - Confirm next steps are clear and actionable
74
- - Verify user communication style and preferences are noted