bmad-method 4.30.2 → 4.30.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/CONTRIBUTING.md +1 -1
  3. package/README.md +3 -3
  4. package/bmad-core/agents/analyst.md +6 -6
  5. package/bmad-core/agents/architect.md +8 -3
  6. package/bmad-core/agents/bmad-master.md +2 -1
  7. package/bmad-core/agents/pm.md +7 -2
  8. package/bmad-core/agents/po.md +2 -5
  9. package/bmad-core/agents/qa.md +0 -1
  10. package/bmad-core/agents/sm.md +3 -3
  11. package/bmad-core/agents/ux-expert.md +2 -5
  12. package/bmad-core/core-config.yaml +0 -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/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.txt +2409 -0
  17. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.txt +1480 -0
  18. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.txt +826 -0
  19. package/dist/expansion-packs/bmad-2d-unity-game-dev/teams/unity-2d-game-team.txt +10690 -0
  20. package/dist/teams/team-all.txt +1 -1
  21. package/dist/teams/team-fullstack.txt +1 -1
  22. package/dist/teams/team-ide-minimal.txt +1 -1
  23. package/dist/teams/team-no-ui.txt +1 -1
  24. package/docs/bmad-workflow-guide.md +1 -1
  25. package/docs/how-to-contribute-with-pull-requests.md +2 -2
  26. package/expansion-packs/bmad-2d-phaser-game-dev/config.yaml +2 -2
  27. package/expansion-packs/bmad-2d-unity-game-dev/agent-teams/unity-2d-game-team.yaml +13 -0
  28. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.md +72 -0
  29. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.md +78 -0
  30. package/expansion-packs/{bmad-creator-tools/agents/bmad-the-creator.md → bmad-2d-unity-game-dev/agents/game-sm.md} +26 -28
  31. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-design-checklist.md +201 -0
  32. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-story-dod-checklist.md +160 -0
  33. package/expansion-packs/bmad-2d-unity-game-dev/config.yaml +6 -0
  34. package/expansion-packs/bmad-2d-unity-game-dev/data/bmad-kb.md +251 -0
  35. package/expansion-packs/bmad-2d-unity-game-dev/data/development-guidelines.md +590 -0
  36. package/expansion-packs/bmad-2d-unity-game-dev/tasks/advanced-elicitation.md +111 -0
  37. package/expansion-packs/bmad-2d-unity-game-dev/tasks/create-game-story.md +217 -0
  38. package/expansion-packs/bmad-2d-unity-game-dev/tasks/game-design-brainstorming.md +308 -0
  39. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-architecture-tmpl.yaml +545 -0
  40. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-brief-tmpl.yaml +356 -0
  41. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-design-doc-tmpl.yaml +343 -0
  42. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-story-tmpl.yaml +256 -0
  43. package/expansion-packs/bmad-2d-unity-game-dev/templates/level-design-doc-tmpl.yaml +484 -0
  44. package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-dev-greenfield.yaml +183 -0
  45. package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-prototype.yaml +175 -0
  46. package/expansion-packs/bmad-infrastructure-devops/config.yaml +2 -2
  47. package/package.json +7 -10
  48. package/tools/bump-all-versions.js +8 -9
  49. package/tools/bump-expansion-version.js +40 -35
  50. package/tools/installer/bin/bmad.js +8 -21
  51. package/tools/installer/lib/file-manager.js +76 -44
  52. package/tools/installer/lib/ide-base-setup.js +227 -0
  53. package/tools/installer/lib/ide-setup.js +8 -58
  54. package/tools/installer/lib/installer.js +99 -121
  55. package/tools/installer/lib/memory-profiler.js +224 -0
  56. package/tools/installer/lib/module-manager.js +110 -0
  57. package/tools/installer/lib/resource-locator.js +310 -0
  58. package/tools/installer/package.json +1 -1
  59. package/tools/semantic-release-sync-installer.js +20 -21
  60. package/dist/expansion-packs/bmad-creator-tools/agents/bmad-the-creator.txt +0 -2008
  61. package/expansion-packs/bmad-creator-tools/README.md +0 -8
  62. package/expansion-packs/bmad-creator-tools/config.yaml +0 -6
  63. package/expansion-packs/bmad-creator-tools/tasks/create-agent.md +0 -200
  64. package/expansion-packs/bmad-creator-tools/tasks/generate-expansion-pack.md +0 -1020
  65. package/expansion-packs/bmad-creator-tools/templates/agent-teams-tmpl.yaml +0 -178
  66. package/expansion-packs/bmad-creator-tools/templates/agent-tmpl.yaml +0 -154
  67. package/expansion-packs/bmad-creator-tools/templates/expansion-pack-plan-tmpl.yaml +0 -120
  68. package/tools/bump-core-version.js +0 -57
@@ -1,18 +1,11 @@
1
1
  const fs = require("fs-extra");
2
2
  const path = require("path");
3
3
  const crypto = require("crypto");
4
- const glob = require("glob");
5
4
  const yaml = require("js-yaml");
6
-
7
- // Dynamic import for ES module
8
- let chalk;
9
-
10
- // Initialize ES modules
11
- async function initializeModules() {
12
- if (!chalk) {
13
- chalk = (await import("chalk")).default;
14
- }
15
- }
5
+ const chalk = require("chalk");
6
+ const { createReadStream, createWriteStream, promises: fsPromises } = require('fs');
7
+ const { pipeline } = require('stream/promises');
8
+ const resourceLocator = require('./resource-locator');
16
9
 
17
10
  class FileManager {
18
11
  constructor() {
@@ -23,10 +16,19 @@ class FileManager {
23
16
  async copyFile(source, destination) {
24
17
  try {
25
18
  await fs.ensureDir(path.dirname(destination));
26
- await fs.copy(source, destination);
19
+
20
+ // Use streaming for large files (> 10MB)
21
+ const stats = await fs.stat(source);
22
+ if (stats.size > 10 * 1024 * 1024) {
23
+ await pipeline(
24
+ createReadStream(source),
25
+ createWriteStream(destination)
26
+ );
27
+ } else {
28
+ await fs.copy(source, destination);
29
+ }
27
30
  return true;
28
31
  } catch (error) {
29
- await initializeModules();
30
32
  console.error(chalk.red(`Failed to copy ${source}:`), error.message);
31
33
  return false;
32
34
  }
@@ -35,10 +37,28 @@ class FileManager {
35
37
  async copyDirectory(source, destination) {
36
38
  try {
37
39
  await fs.ensureDir(destination);
38
- await fs.copy(source, destination);
40
+
41
+ // Use streaming copy for large directories
42
+ const files = await resourceLocator.findFiles('**/*', {
43
+ cwd: source,
44
+ nodir: true
45
+ });
46
+
47
+ // Process files in batches to avoid memory issues
48
+ const batchSize = 50;
49
+ for (let i = 0; i < files.length; i += batchSize) {
50
+ const batch = files.slice(i, i + batchSize);
51
+ await Promise.all(
52
+ batch.map(file =>
53
+ this.copyFile(
54
+ path.join(source, file),
55
+ path.join(destination, file)
56
+ )
57
+ )
58
+ );
59
+ }
39
60
  return true;
40
61
  } catch (error) {
41
- await initializeModules();
42
62
  console.error(
43
63
  chalk.red(`Failed to copy directory ${source}:`),
44
64
  error.message
@@ -48,7 +68,7 @@ class FileManager {
48
68
  }
49
69
 
50
70
  async copyGlobPattern(pattern, sourceDir, destDir, rootValue = null) {
51
- const files = glob.sync(pattern, { cwd: sourceDir });
71
+ const files = await resourceLocator.findFiles(pattern, { cwd: sourceDir });
52
72
  const copied = [];
53
73
 
54
74
  for (const file of files) {
@@ -75,12 +95,15 @@ class FileManager {
75
95
 
76
96
  async calculateFileHash(filePath) {
77
97
  try {
78
- const content = await fs.readFile(filePath);
79
- return crypto
80
- .createHash("sha256")
81
- .update(content)
82
- .digest("hex")
83
- .slice(0, 16);
98
+ // Use streaming for hash calculation to reduce memory usage
99
+ const stream = createReadStream(filePath);
100
+ const hash = crypto.createHash("sha256");
101
+
102
+ for await (const chunk of stream) {
103
+ hash.update(chunk);
104
+ }
105
+
106
+ return hash.digest("hex").slice(0, 16);
84
107
  } catch (error) {
85
108
  return null;
86
109
  }
@@ -93,15 +116,14 @@ class FileManager {
93
116
  this.manifestFile
94
117
  );
95
118
 
96
- // Read version from core-config.yaml
97
- const coreConfigPath = path.join(__dirname, "../../../bmad-core/core-config.yaml");
119
+ // Read version from package.json
98
120
  let coreVersion = "unknown";
99
121
  try {
100
- const coreConfigContent = await fs.readFile(coreConfigPath, "utf8");
101
- const coreConfig = yaml.load(coreConfigContent);
102
- coreVersion = coreConfig.version || "unknown";
122
+ const packagePath = path.join(__dirname, '..', '..', '..', 'package.json');
123
+ const packageJson = require(packagePath);
124
+ coreVersion = packageJson.version;
103
125
  } catch (error) {
104
- console.warn("Could not read version from core-config.yaml, using 'unknown'");
126
+ console.warn("Could not read version from package.json, using 'unknown'");
105
127
  }
106
128
 
107
129
  const manifest = {
@@ -304,7 +326,6 @@ class FileManager {
304
326
 
305
327
  return true;
306
328
  } catch (error) {
307
- await initializeModules();
308
329
  console.error(chalk.red(`Failed to modify core-config.yaml:`), error.message);
309
330
  return false;
310
331
  }
@@ -312,22 +333,35 @@ class FileManager {
312
333
 
313
334
  async copyFileWithRootReplacement(source, destination, rootValue) {
314
335
  try {
315
- // Read the source file content
316
- const fs = require('fs').promises;
317
- const content = await fs.readFile(source, 'utf8');
318
-
319
- // Replace {root} with the specified root value
320
- const updatedContent = content.replace(/\{root\}/g, rootValue);
336
+ // Check file size to determine if we should stream
337
+ const stats = await fs.stat(source);
321
338
 
322
- // Ensure directory exists
323
- await this.ensureDirectory(path.dirname(destination));
324
-
325
- // Write the updated content
326
- await fs.writeFile(destination, updatedContent, 'utf8');
339
+ if (stats.size > 5 * 1024 * 1024) { // 5MB threshold
340
+ // Use streaming for large files
341
+ const { Transform } = require('stream');
342
+ const replaceStream = new Transform({
343
+ transform(chunk, encoding, callback) {
344
+ const modified = chunk.toString().replace(/\{root\}/g, rootValue);
345
+ callback(null, modified);
346
+ }
347
+ });
348
+
349
+ await this.ensureDirectory(path.dirname(destination));
350
+ await pipeline(
351
+ createReadStream(source, { encoding: 'utf8' }),
352
+ replaceStream,
353
+ createWriteStream(destination, { encoding: 'utf8' })
354
+ );
355
+ } else {
356
+ // Regular approach for smaller files
357
+ const content = await fsPromises.readFile(source, 'utf8');
358
+ const updatedContent = content.replace(/\{root\}/g, rootValue);
359
+ await this.ensureDirectory(path.dirname(destination));
360
+ await fsPromises.writeFile(destination, updatedContent, 'utf8');
361
+ }
327
362
 
328
363
  return true;
329
364
  } catch (error) {
330
- await initializeModules();
331
365
  console.error(chalk.red(`Failed to copy ${source} with root replacement:`), error.message);
332
366
  return false;
333
367
  }
@@ -335,11 +369,10 @@ class FileManager {
335
369
 
336
370
  async copyDirectoryWithRootReplacement(source, destination, rootValue, fileExtensions = ['.md', '.yaml', '.yml']) {
337
371
  try {
338
- await initializeModules(); // Ensure chalk is initialized
339
372
  await this.ensureDirectory(destination);
340
373
 
341
374
  // Get all files in source directory
342
- const files = glob.sync('**/*', {
375
+ const files = await resourceLocator.findFiles('**/*', {
343
376
  cwd: source,
344
377
  nodir: true
345
378
  });
@@ -369,7 +402,6 @@ class FileManager {
369
402
 
370
403
  return true;
371
404
  } catch (error) {
372
- await initializeModules();
373
405
  console.error(chalk.red(`Failed to copy directory ${source} with root replacement:`), error.message);
374
406
  return false;
375
407
  }
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Base IDE Setup - Common functionality for all IDE setups
3
+ * Reduces duplication and provides shared methods
4
+ */
5
+
6
+ const path = require("path");
7
+ const fs = require("fs-extra");
8
+ const yaml = require("js-yaml");
9
+ const chalk = require("chalk");
10
+ const fileManager = require("./file-manager");
11
+ const resourceLocator = require("./resource-locator");
12
+ const { extractYamlFromAgent } = require("../../lib/yaml-utils");
13
+
14
+ class BaseIdeSetup {
15
+ constructor() {
16
+ this._agentCache = new Map();
17
+ this._pathCache = new Map();
18
+ }
19
+
20
+ /**
21
+ * Get all agent IDs with caching
22
+ */
23
+ async getAllAgentIds(installDir) {
24
+ const cacheKey = `all-agents:${installDir}`;
25
+ if (this._agentCache.has(cacheKey)) {
26
+ return this._agentCache.get(cacheKey);
27
+ }
28
+
29
+ const allAgents = new Set();
30
+
31
+ // Get core agents
32
+ const coreAgents = await this.getCoreAgentIds(installDir);
33
+ coreAgents.forEach(id => allAgents.add(id));
34
+
35
+ // Get expansion pack agents
36
+ const expansionPacks = await this.getInstalledExpansionPacks(installDir);
37
+ for (const pack of expansionPacks) {
38
+ const packAgents = await this.getExpansionPackAgents(pack.path);
39
+ packAgents.forEach(id => allAgents.add(id));
40
+ }
41
+
42
+ const result = Array.from(allAgents);
43
+ this._agentCache.set(cacheKey, result);
44
+ return result;
45
+ }
46
+
47
+ /**
48
+ * Get core agent IDs
49
+ */
50
+ async getCoreAgentIds(installDir) {
51
+ const coreAgents = [];
52
+ const corePaths = [
53
+ path.join(installDir, ".bmad-core", "agents"),
54
+ path.join(installDir, "bmad-core", "agents")
55
+ ];
56
+
57
+ for (const agentsDir of corePaths) {
58
+ if (await fileManager.pathExists(agentsDir)) {
59
+ const files = await resourceLocator.findFiles("*.md", { cwd: agentsDir });
60
+ coreAgents.push(...files.map(file => path.basename(file, ".md")));
61
+ break; // Use first found
62
+ }
63
+ }
64
+
65
+ return coreAgents;
66
+ }
67
+
68
+ /**
69
+ * Find agent path with caching
70
+ */
71
+ async findAgentPath(agentId, installDir) {
72
+ const cacheKey = `agent-path:${agentId}:${installDir}`;
73
+ if (this._pathCache.has(cacheKey)) {
74
+ return this._pathCache.get(cacheKey);
75
+ }
76
+
77
+ // Use resource locator for efficient path finding
78
+ let agentPath = await resourceLocator.getAgentPath(agentId);
79
+
80
+ if (!agentPath) {
81
+ // Check installation-specific paths
82
+ const possiblePaths = [
83
+ path.join(installDir, ".bmad-core", "agents", `${agentId}.md`),
84
+ path.join(installDir, "bmad-core", "agents", `${agentId}.md`),
85
+ path.join(installDir, "common", "agents", `${agentId}.md`)
86
+ ];
87
+
88
+ for (const testPath of possiblePaths) {
89
+ if (await fileManager.pathExists(testPath)) {
90
+ agentPath = testPath;
91
+ break;
92
+ }
93
+ }
94
+ }
95
+
96
+ if (agentPath) {
97
+ this._pathCache.set(cacheKey, agentPath);
98
+ }
99
+ return agentPath;
100
+ }
101
+
102
+ /**
103
+ * Get agent title from metadata
104
+ */
105
+ async getAgentTitle(agentId, installDir) {
106
+ const agentPath = await this.findAgentPath(agentId, installDir);
107
+ if (!agentPath) return agentId;
108
+
109
+ try {
110
+ const content = await fileManager.readFile(agentPath);
111
+ const yamlContent = extractYamlFromAgent(content);
112
+ if (yamlContent) {
113
+ const metadata = yaml.load(yamlContent);
114
+ return metadata.agent_name || agentId;
115
+ }
116
+ } catch (error) {
117
+ // Fallback to agent ID
118
+ }
119
+ return agentId;
120
+ }
121
+
122
+ /**
123
+ * Get installed expansion packs
124
+ */
125
+ async getInstalledExpansionPacks(installDir) {
126
+ const cacheKey = `expansion-packs:${installDir}`;
127
+ if (this._pathCache.has(cacheKey)) {
128
+ return this._pathCache.get(cacheKey);
129
+ }
130
+
131
+ const expansionPacks = [];
132
+
133
+ // Check for dot-prefixed expansion packs
134
+ const dotExpansions = await resourceLocator.findFiles(".bmad-*", { cwd: installDir });
135
+
136
+ for (const dotExpansion of dotExpansions) {
137
+ if (dotExpansion !== ".bmad-core") {
138
+ const packPath = path.join(installDir, dotExpansion);
139
+ const packName = dotExpansion.substring(1); // remove the dot
140
+ expansionPacks.push({
141
+ name: packName,
142
+ path: packPath
143
+ });
144
+ }
145
+ }
146
+
147
+ // Check other dot folders that have config.yaml
148
+ const allDotFolders = await resourceLocator.findFiles(".*", { cwd: installDir });
149
+ for (const folder of allDotFolders) {
150
+ if (!folder.startsWith(".bmad-") && folder !== ".bmad-core") {
151
+ const packPath = path.join(installDir, folder);
152
+ const configPath = path.join(packPath, "config.yaml");
153
+ if (await fileManager.pathExists(configPath)) {
154
+ expansionPacks.push({
155
+ name: folder.substring(1), // remove the dot
156
+ path: packPath
157
+ });
158
+ }
159
+ }
160
+ }
161
+
162
+ this._pathCache.set(cacheKey, expansionPacks);
163
+ return expansionPacks;
164
+ }
165
+
166
+ /**
167
+ * Get expansion pack agents
168
+ */
169
+ async getExpansionPackAgents(packPath) {
170
+ const agentsDir = path.join(packPath, "agents");
171
+ if (!(await fileManager.pathExists(agentsDir))) {
172
+ return [];
173
+ }
174
+
175
+ const agentFiles = await resourceLocator.findFiles("*.md", { cwd: agentsDir });
176
+ return agentFiles.map(file => path.basename(file, ".md"));
177
+ }
178
+
179
+ /**
180
+ * Create agent rule content (shared logic)
181
+ */
182
+ async createAgentRuleContent(agentId, agentPath, installDir, format = 'mdc') {
183
+ const agentContent = await fileManager.readFile(agentPath);
184
+ const agentTitle = await this.getAgentTitle(agentId, installDir);
185
+ const yamlContent = extractYamlFromAgent(agentContent);
186
+
187
+ let content = "";
188
+
189
+ if (format === 'mdc') {
190
+ // MDC format for Cursor
191
+ content = "---\n";
192
+ content += "description: \n";
193
+ content += "globs: []\n";
194
+ content += "alwaysApply: false\n";
195
+ content += "---\n\n";
196
+ content += `# ${agentId.toUpperCase()} Agent Rule\n\n`;
197
+ content += `This rule is triggered when the user types \`@${agentId}\` and activates the ${agentTitle} agent persona.\n\n`;
198
+ content += "## Agent Activation\n\n";
199
+ content += "CRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n";
200
+ content += "```yaml\n";
201
+ content += yamlContent || agentContent.replace(/^#.*$/m, "").trim();
202
+ content += "\n```\n\n";
203
+ content += "## File Reference\n\n";
204
+ const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
205
+ content += `The complete agent definition is available in [${relativePath}](mdc:${relativePath}).\n\n`;
206
+ content += "## Usage\n\n";
207
+ content += `When the user types \`@${agentId}\`, activate this ${agentTitle} persona and follow all instructions defined in the YAML configuration above.\n`;
208
+ } else if (format === 'claude') {
209
+ // Claude Code format
210
+ content = `# /${agentId} Command\n\n`;
211
+ content += `When this command is used, adopt the following agent persona:\n\n`;
212
+ content += agentContent;
213
+ }
214
+
215
+ return content;
216
+ }
217
+
218
+ /**
219
+ * Clear all caches
220
+ */
221
+ clearCache() {
222
+ this._agentCache.clear();
223
+ this._pathCache.clear();
224
+ }
225
+ }
226
+
227
+ module.exports = BaseIdeSetup;
@@ -1,26 +1,17 @@
1
1
  const path = require("path");
2
2
  const fs = require("fs-extra");
3
3
  const yaml = require("js-yaml");
4
+ const chalk = require("chalk");
5
+ const inquirer = require("inquirer");
4
6
  const fileManager = require("./file-manager");
5
7
  const configLoader = require("./config-loader");
6
8
  const { extractYamlFromAgent } = require("../../lib/yaml-utils");
9
+ const BaseIdeSetup = require("./ide-base-setup");
10
+ const resourceLocator = require("./resource-locator");
7
11
 
8
- // Dynamic import for ES module
9
- let chalk;
10
- let inquirer;
11
-
12
- // Initialize ES modules
13
- async function initializeModules() {
14
- if (!chalk) {
15
- chalk = (await import("chalk")).default;
16
- }
17
- if (!inquirer) {
18
- inquirer = (await import("inquirer")).default;
19
- }
20
- }
21
-
22
- class IdeSetup {
12
+ class IdeSetup extends BaseIdeSetup {
23
13
  constructor() {
14
+ super();
24
15
  this.ideAgentConfig = null;
25
16
  }
26
17
 
@@ -42,7 +33,6 @@ class IdeSetup {
42
33
  }
43
34
 
44
35
  async setup(ide, installDir, selectedAgent = null, spinner = null, preConfiguredSettings = null) {
45
- await initializeModules();
46
36
  const ideConfig = await configLoader.getIdeConfiguration(ide);
47
37
 
48
38
  if (!ideConfig) {
@@ -80,53 +70,17 @@ class IdeSetup {
80
70
  await fileManager.ensureDirectory(cursorRulesDir);
81
71
 
82
72
  for (const agentId of agents) {
83
- // Find the agent file
84
73
  const agentPath = await this.findAgentPath(agentId, installDir);
85
74
 
86
75
  if (agentPath) {
87
- const agentContent = await fileManager.readFile(agentPath);
76
+ const mdcContent = await this.createAgentRuleContent(agentId, agentPath, installDir, 'mdc');
88
77
  const mdcPath = path.join(cursorRulesDir, `${agentId}.mdc`);
89
-
90
- // Create MDC content with proper format
91
- let mdcContent = "---\n";
92
- mdcContent += "description: \n";
93
- mdcContent += "globs: []\n";
94
- mdcContent += "alwaysApply: false\n";
95
- mdcContent += "---\n\n";
96
- mdcContent += `# ${agentId.toUpperCase()} Agent Rule\n\n`;
97
- mdcContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${await this.getAgentTitle(
98
- agentId,
99
- installDir
100
- )} agent persona.\n\n`;
101
- mdcContent += "## Agent Activation\n\n";
102
- mdcContent +=
103
- "CRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n";
104
- mdcContent += "```yaml\n";
105
- // Extract just the YAML content from the agent file
106
- const yamlContent = extractYamlFromAgent(agentContent);
107
- if (yamlContent) {
108
- mdcContent += yamlContent;
109
- } else {
110
- // If no YAML found, include the whole content minus the header
111
- mdcContent += agentContent.replace(/^#.*$/m, "").trim();
112
- }
113
- mdcContent += "\n```\n\n";
114
- mdcContent += "## File Reference\n\n";
115
- const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
116
- mdcContent += `The complete agent definition is available in [${relativePath}](mdc:${relativePath}).\n\n`;
117
- mdcContent += "## Usage\n\n";
118
- mdcContent += `When the user types \`@${agentId}\`, activate this ${await this.getAgentTitle(
119
- agentId,
120
- installDir
121
- )} persona and follow all instructions defined in the YAML configuration above.\n`;
122
-
123
78
  await fileManager.writeFile(mdcPath, mdcContent);
124
79
  console.log(chalk.green(`✓ Created rule: ${agentId}.mdc`));
125
80
  }
126
81
  }
127
82
 
128
83
  console.log(chalk.green(`\n✓ Created Cursor rules in ${cursorRulesDir}`));
129
-
130
84
  return true;
131
85
  }
132
86
 
@@ -827,7 +781,6 @@ class IdeSetup {
827
781
  }
828
782
 
829
783
  async setupGeminiCli(installDir) {
830
- await initializeModules();
831
784
  const geminiDir = path.join(installDir, ".gemini");
832
785
  const bmadMethodDir = path.join(geminiDir, "bmad-method");
833
786
  await fileManager.ensureDirectory(bmadMethodDir);
@@ -928,8 +881,6 @@ class IdeSetup {
928
881
  }
929
882
 
930
883
  async setupGitHubCopilot(installDir, selectedAgent, spinner = null, preConfiguredSettings = null) {
931
- await initializeModules();
932
-
933
884
  // Configure VS Code workspace settings first to avoid UI conflicts with loading spinners
934
885
  await this.configureVsCodeSettings(installDir, spinner, preConfiguredSettings);
935
886
 
@@ -960,7 +911,7 @@ class IdeSetup {
960
911
 
961
912
  let chatmodeContent = `---
962
913
  description: "${description.replace(/"/g, '\\"')}"
963
- tools: ['changes', 'codebase', 'fetch', 'findTestFiles', 'githubRepo', 'problems', 'usages']
914
+ tools: ['changes', 'codebase', 'fetch', 'findTestFiles', 'githubRepo', 'problems', 'usages', 'editFiles', 'runCommands', 'runTasks', 'runTests', 'search', 'searchResults', 'terminalLastCommand', 'terminalSelection', 'testFailure']
964
915
  ---
965
916
 
966
917
  `;
@@ -978,7 +929,6 @@ tools: ['changes', 'codebase', 'fetch', 'findTestFiles', 'githubRepo', 'problems
978
929
  }
979
930
 
980
931
  async configureVsCodeSettings(installDir, spinner, preConfiguredSettings = null) {
981
- await initializeModules(); // Ensure inquirer is loaded
982
932
  const vscodeDir = path.join(installDir, ".vscode");
983
933
  const settingsPath = path.join(vscodeDir, "settings.json");
984
934