bmad-method 6.2.1-next.23 → 6.2.1-next.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "bmad-method",
4
- "version": "6.2.1-next.23",
4
+ "version": "6.2.1-next.25",
5
5
  "description": "Breakthrough Method of Agile AI-driven Development",
6
6
  "keywords": [
7
7
  "agile",
@@ -18,7 +18,7 @@ module.exports = {
18
18
  'Comma-separated list of tool/IDE IDs to configure (e.g., "claude-code,cursor"). Use "none" to skip tool configuration.',
19
19
  ],
20
20
  ['--custom-content <paths>', 'Comma-separated list of paths to custom modules/agents/workflows'],
21
- ['--action <type>', 'Action type for existing installations: install, update, quick-update, or compile-agents'],
21
+ ['--action <type>', 'Action type for existing installations: install, update, or quick-update'],
22
22
  ['--user-name <name>', 'Name for agents to use (default: system username)'],
23
23
  ['--communication-language <lang>', 'Language for agent communication (default: English)'],
24
24
  ['--document-output-language <lang>', 'Language for document output (default: English)'],
@@ -49,13 +49,6 @@ module.exports = {
49
49
  process.exit(0);
50
50
  }
51
51
 
52
- // Handle compile agents separately
53
- if (config.actionType === 'compile-agents') {
54
- const result = await installer.compileAgents(config);
55
- await prompts.log.info(`Recompiled ${result.agentCount} agents with customizations applied`);
56
- process.exit(0);
57
- }
58
-
59
52
  // Regular install/update flow
60
53
  const result = await installer.install(config);
61
54
 
@@ -6,7 +6,6 @@ const { ModuleManager } = require('../modules/manager');
6
6
  const { IdeManager } = require('../ide/manager');
7
7
  const { FileOps } = require('../../../lib/file-ops');
8
8
  const { Config } = require('../../../lib/config');
9
- const { XmlHandler } = require('../../../lib/xml-handler');
10
9
  const { DependencyResolver } = require('./dependency-resolver');
11
10
  const { ConfigCollector } = require('./config-collector');
12
11
  const { getProjectRoot, getSourcePath, getModulePath } = require('../../../lib/project-root');
@@ -25,7 +24,6 @@ class Installer {
25
24
  this.ideManager = new IdeManager();
26
25
  this.fileOps = new FileOps();
27
26
  this.config = new Config();
28
- this.xmlHandler = new XmlHandler();
29
27
  this.dependencyResolver = new DependencyResolver();
30
28
  this.configCollector = new ConfigCollector();
31
29
  this.ideConfigManager = new IdeConfigManager();
@@ -2114,10 +2112,6 @@ class Installer {
2114
2112
  },
2115
2113
  );
2116
2114
 
2117
- // Process agent files to build YAML agents and create customize templates
2118
- const modulePath = path.join(bmadDir, moduleName);
2119
- await this.processAgentFiles(modulePath, moduleName);
2120
-
2121
2115
  // Dependencies are already included in full module install
2122
2116
  }
2123
2117
 
@@ -2227,16 +2221,8 @@ class Installer {
2227
2221
  const sourcePath = getModulePath('core');
2228
2222
  const targetPath = path.join(bmadDir, 'core');
2229
2223
 
2230
- // Copy core files (skip .agent.yaml files like modules do)
2224
+ // Copy core files
2231
2225
  await this.copyCoreFiles(sourcePath, targetPath);
2232
-
2233
- // Compile agents using the same compiler as modules
2234
- const { ModuleManager } = require('../modules/manager');
2235
- const moduleManager = new ModuleManager();
2236
- await moduleManager.compileModuleAgents(sourcePath, targetPath, 'core', bmadDir, this);
2237
-
2238
- // Process agent files to inject activation block
2239
- await this.processAgentFiles(targetPath, 'core');
2240
2226
  }
2241
2227
 
2242
2228
  /**
@@ -2254,16 +2240,6 @@ class Installer {
2254
2240
  continue;
2255
2241
  }
2256
2242
 
2257
- // Skip sidecar directories - they are handled separately during agent compilation
2258
- if (
2259
- path
2260
- .dirname(file)
2261
- .split('/')
2262
- .some((dir) => dir.toLowerCase().includes('sidecar'))
2263
- ) {
2264
- continue;
2265
- }
2266
-
2267
2243
  // Skip module.yaml at root - it's only needed at install time
2268
2244
  if (file === 'module.yaml') {
2269
2245
  continue;
@@ -2274,27 +2250,9 @@ class Installer {
2274
2250
  continue;
2275
2251
  }
2276
2252
 
2277
- // Skip .agent.yaml files - they will be compiled separately
2278
- if (file.endsWith('.agent.yaml')) {
2279
- continue;
2280
- }
2281
-
2282
2253
  const sourceFile = path.join(sourcePath, file);
2283
2254
  const targetFile = path.join(targetPath, file);
2284
2255
 
2285
- // Check if this is an agent file
2286
- if (file.startsWith('agents/') && file.endsWith('.md')) {
2287
- // Read the file to check for localskip
2288
- const content = await fs.readFile(sourceFile, 'utf8');
2289
-
2290
- // Check for localskip="true" in the agent tag
2291
- const agentMatch = content.match(/<agent[^>]*\slocalskip="true"[^>]*>/);
2292
- if (agentMatch) {
2293
- await prompts.log.message(` Skipping web-only agent: ${path.basename(file)}`);
2294
- continue; // Skip this agent
2295
- }
2296
- }
2297
-
2298
2256
  // Copy the file with placeholder replacement
2299
2257
  await fs.ensureDir(path.dirname(targetFile));
2300
2258
  await this.copyFileWithPlaceholderReplacement(sourceFile, targetFile);
@@ -2328,58 +2286,6 @@ class Installer {
2328
2286
  return files;
2329
2287
  }
2330
2288
 
2331
- /**
2332
- * Process agent files to build YAML agents and inject activation blocks
2333
- * @param {string} modulePath - Path to module in bmad/ installation
2334
- * @param {string} moduleName - Module name
2335
- */
2336
- async processAgentFiles(modulePath, moduleName) {
2337
- const agentsPath = path.join(modulePath, 'agents');
2338
-
2339
- // Check if agents directory exists
2340
- if (!(await fs.pathExists(agentsPath))) {
2341
- return; // No agents to process
2342
- }
2343
-
2344
- // Determine project directory (parent of bmad/ directory)
2345
- const bmadDir = path.dirname(modulePath);
2346
- const cfgAgentsDir = path.join(bmadDir, '_config', 'agents');
2347
-
2348
- // Ensure _config/agents directory exists
2349
- await fs.ensureDir(cfgAgentsDir);
2350
-
2351
- // Get all agent files
2352
- const agentFiles = await fs.readdir(agentsPath);
2353
-
2354
- for (const agentFile of agentFiles) {
2355
- // Skip .agent.yaml files - they should already be compiled by compileModuleAgents
2356
- if (agentFile.endsWith('.agent.yaml')) {
2357
- continue;
2358
- }
2359
-
2360
- // Only process .md files (already compiled from YAML)
2361
- if (!agentFile.endsWith('.md')) {
2362
- continue;
2363
- }
2364
-
2365
- const agentName = agentFile.replace('.md', '');
2366
- const mdPath = path.join(agentsPath, agentFile);
2367
- const customizePath = path.join(cfgAgentsDir, `${moduleName}-${agentName}.customize.yaml`);
2368
-
2369
- // For .md files that are already compiled, we don't need to do much
2370
- // Just ensure the customize template exists
2371
- if (!(await fs.pathExists(customizePath))) {
2372
- const genericTemplatePath = getSourcePath('utility', 'agent-components', 'agent.customize.template.yaml');
2373
- if (await fs.pathExists(genericTemplatePath)) {
2374
- await this.copyFileWithPlaceholderReplacement(genericTemplatePath, customizePath);
2375
- if (process.env.BMAD_VERBOSE_INSTALL === 'true') {
2376
- await prompts.log.message(` Created customize: ${moduleName}-${agentName}.customize.yaml`);
2377
- }
2378
- }
2379
- }
2380
- }
2381
- }
2382
-
2383
2289
  /**
2384
2290
  * Private: Update core
2385
2291
  */
@@ -2393,12 +2299,6 @@ class Installer {
2393
2299
  } else {
2394
2300
  // Selective update - preserve user modifications
2395
2301
  await this.fileOps.syncDirectory(sourcePath, targetPath);
2396
-
2397
- // Recompile agents (#1133)
2398
- const { ModuleManager } = require('../modules/manager');
2399
- const moduleManager = new ModuleManager();
2400
- await moduleManager.compileModuleAgents(sourcePath, targetPath, 'core', bmadDir, this);
2401
- await this.processAgentFiles(targetPath, 'core');
2402
2302
  }
2403
2303
  }
2404
2304
 
@@ -2643,114 +2543,6 @@ class Installer {
2643
2543
  }
2644
2544
  }
2645
2545
 
2646
- /**
2647
- * Compile agents with customizations only
2648
- * @param {Object} config - Configuration with directory
2649
- * @returns {Object} Compilation result
2650
- */
2651
- async compileAgents(config) {
2652
- // Using @clack prompts
2653
- const { ModuleManager } = require('../modules/manager');
2654
- const { getSourcePath } = require('../../../lib/project-root');
2655
-
2656
- const spinner = await prompts.spinner();
2657
- spinner.start('Recompiling agents with customizations...');
2658
-
2659
- try {
2660
- const projectDir = path.resolve(config.directory);
2661
- const { bmadDir } = await this.findBmadDir(projectDir);
2662
-
2663
- // Check if bmad directory exists
2664
- if (!(await fs.pathExists(bmadDir))) {
2665
- spinner.stop('No BMAD installation found');
2666
- throw new Error(`BMAD not installed at ${bmadDir}. Use regular install for first-time setup.`);
2667
- }
2668
-
2669
- // Detect existing installation
2670
- const existingInstall = await this.detector.detect(bmadDir);
2671
- const installedModules = existingInstall.modules.map((m) => m.id);
2672
-
2673
- // Initialize module manager
2674
- const moduleManager = new ModuleManager();
2675
- moduleManager.setBmadFolderName(path.basename(bmadDir));
2676
-
2677
- let totalAgentCount = 0;
2678
-
2679
- // Get custom module sources from cache
2680
- const customModuleSources = new Map();
2681
- const cacheDir = path.join(bmadDir, '_config', 'custom');
2682
- if (await fs.pathExists(cacheDir)) {
2683
- const cachedModules = await fs.readdir(cacheDir, { withFileTypes: true });
2684
-
2685
- for (const cachedModule of cachedModules) {
2686
- if (cachedModule.isDirectory()) {
2687
- const moduleId = cachedModule.name;
2688
- const cachedPath = path.join(cacheDir, moduleId);
2689
- const moduleYamlPath = path.join(cachedPath, 'module.yaml');
2690
-
2691
- // Check if this is actually a custom module
2692
- if (await fs.pathExists(moduleYamlPath)) {
2693
- // Check if this is an external official module - skip cache for those
2694
- const isExternal = await this.moduleManager.isExternalModule(moduleId);
2695
- if (isExternal) {
2696
- // External modules are handled via cloneExternalModule, not from cache
2697
- continue;
2698
- }
2699
- customModuleSources.set(moduleId, cachedPath);
2700
- }
2701
- }
2702
- }
2703
- }
2704
-
2705
- // Process each installed module
2706
- for (const moduleId of installedModules) {
2707
- spinner.message(`Recompiling agents in ${moduleId}...`);
2708
-
2709
- // Get source path
2710
- let sourcePath;
2711
- if (moduleId === 'core') {
2712
- sourcePath = getSourcePath('core-skills');
2713
- } else {
2714
- // First check if it's in the custom cache
2715
- if (customModuleSources.has(moduleId)) {
2716
- sourcePath = customModuleSources.get(moduleId);
2717
- } else {
2718
- sourcePath = await moduleManager.findModuleSource(moduleId);
2719
- }
2720
- }
2721
-
2722
- if (!sourcePath) {
2723
- await prompts.log.warn(`Source not found for module ${moduleId}, skipping...`);
2724
- continue;
2725
- }
2726
-
2727
- const targetPath = path.join(bmadDir, moduleId);
2728
-
2729
- // Compile agents for this module
2730
- await moduleManager.compileModuleAgents(sourcePath, targetPath, moduleId, bmadDir, this);
2731
-
2732
- // Count agents (rough estimate based on files)
2733
- const agentsPath = path.join(targetPath, 'agents');
2734
- if (await fs.pathExists(agentsPath)) {
2735
- const agentFiles = await fs.readdir(agentsPath);
2736
- const agentCount = agentFiles.filter((f) => f.endsWith('.md')).length;
2737
- totalAgentCount += agentCount;
2738
- }
2739
- }
2740
-
2741
- spinner.stop('Agent recompilation complete!');
2742
-
2743
- return {
2744
- success: true,
2745
- agentCount: totalAgentCount,
2746
- modules: installedModules,
2747
- };
2748
- } catch (error) {
2749
- spinner.error('Agent recompilation failed');
2750
- throw error;
2751
- }
2752
- }
2753
-
2754
2546
  /**
2755
2547
  * Private: Prompt for update action
2756
2548
  */
@@ -515,7 +515,7 @@ class ManifestGenerator {
515
515
 
516
516
  /**
517
517
  * Get agents from a directory recursively
518
- * Only includes compiled .md files (not .agent.yaml source files)
518
+ * Only includes .md files with agent content
519
519
  */
520
520
  async getAgentsFromDir(dirPath, moduleName, relativePath = '') {
521
521
  // Skip directories claimed by collectSkills
@@ -572,7 +572,7 @@ class ManifestGenerator {
572
572
  const newRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
573
573
  const subDirAgents = await this.getAgentsFromDir(fullPath, moduleName, newRelativePath);
574
574
  agents.push(...subDirAgents);
575
- } else if (entry.name.endsWith('.md') && !entry.name.endsWith('.agent.yaml') && entry.name.toLowerCase() !== 'readme.md') {
575
+ } else if (entry.name.endsWith('.md') && entry.name.toLowerCase() !== 'readme.md') {
576
576
  const content = await fs.readFile(fullPath, 'utf8');
577
577
 
578
578
  // Skip files that don't contain <agent> tag (e.g., README files)
@@ -2,19 +2,11 @@ const path = require('node:path');
2
2
  const fs = require('fs-extra');
3
3
  const yaml = require('yaml');
4
4
  const prompts = require('../../../lib/prompts');
5
- const { FileOps } = require('../../../lib/file-ops');
6
- const { XmlHandler } = require('../../../lib/xml-handler');
7
-
8
5
  /**
9
6
  * Handler for custom content (custom.yaml)
10
- * Installs custom agents and workflows without requiring a full module structure
7
+ * Discovers custom agents and workflows in the project
11
8
  */
12
9
  class CustomHandler {
13
- constructor() {
14
- this.fileOps = new FileOps();
15
- this.xmlHandler = new XmlHandler();
16
- }
17
-
18
10
  /**
19
11
  * Find all custom.yaml files in the project
20
12
  * @param {string} projectRoot - Project root directory
@@ -115,244 +107,6 @@ class CustomHandler {
115
107
  return null;
116
108
  }
117
109
  }
118
-
119
- /**
120
- * Install custom content
121
- * @param {string} customPath - Path to custom content directory
122
- * @param {string} bmadDir - Target bmad directory
123
- * @param {Object} config - Configuration from custom.yaml
124
- * @param {Function} fileTrackingCallback - Optional callback to track installed files
125
- * @returns {Object} Installation result
126
- */
127
- async install(customPath, bmadDir, config, fileTrackingCallback = null) {
128
- const results = {
129
- agentsInstalled: 0,
130
- workflowsInstalled: 0,
131
- filesCopied: 0,
132
- preserved: 0,
133
- errors: [],
134
- };
135
-
136
- try {
137
- // Create custom directories in bmad
138
- const bmadCustomDir = path.join(bmadDir, 'custom');
139
- const bmadAgentsDir = path.join(bmadCustomDir, 'agents');
140
- const bmadWorkflowsDir = path.join(bmadCustomDir, 'workflows');
141
-
142
- await fs.ensureDir(bmadCustomDir);
143
- await fs.ensureDir(bmadAgentsDir);
144
- await fs.ensureDir(bmadWorkflowsDir);
145
-
146
- // Process agents - compile and copy agents
147
- const agentsDir = path.join(customPath, 'agents');
148
- if (await fs.pathExists(agentsDir)) {
149
- await this.compileAndCopyAgents(agentsDir, bmadAgentsDir, bmadDir, config, fileTrackingCallback, results);
150
-
151
- // Count agent files
152
- const agentFiles = await this.findFilesRecursively(agentsDir, ['.agent.yaml', '.md']);
153
- results.agentsInstalled = agentFiles.length;
154
- }
155
-
156
- // Process workflows - copy entire workflows directory structure
157
- const workflowsDir = path.join(customPath, 'workflows');
158
- if (await fs.pathExists(workflowsDir)) {
159
- await this.copyDirectory(workflowsDir, bmadWorkflowsDir, results, fileTrackingCallback, config);
160
-
161
- // Count workflow files
162
- const workflowFiles = await this.findFilesRecursively(workflowsDir, ['.md']);
163
- results.workflowsInstalled = workflowFiles.length;
164
- }
165
-
166
- // Process any additional files at root
167
- const entries = await fs.readdir(customPath, { withFileTypes: true });
168
- for (const entry of entries) {
169
- if (entry.isFile() && entry.name !== 'custom.yaml' && !entry.name.startsWith('.') && !entry.name.endsWith('.md')) {
170
- // Skip .md files at root as they're likely docs
171
- const sourcePath = path.join(customPath, entry.name);
172
- const targetPath = path.join(bmadCustomDir, entry.name);
173
-
174
- try {
175
- // Check if file already exists
176
- if (await fs.pathExists(targetPath)) {
177
- // File already exists, preserve it
178
- results.preserved = (results.preserved || 0) + 1;
179
- } else {
180
- await fs.copy(sourcePath, targetPath);
181
- results.filesCopied++;
182
-
183
- if (fileTrackingCallback) {
184
- fileTrackingCallback(targetPath);
185
- }
186
- }
187
- } catch (error) {
188
- results.errors.push(`Failed to copy file ${entry.name}: ${error.message}`);
189
- }
190
- }
191
- }
192
- } catch (error) {
193
- results.errors.push(`Installation failed: ${error.message}`);
194
- }
195
-
196
- return results;
197
- }
198
-
199
- /**
200
- * Find all files with specific extensions recursively
201
- * @param {string} dir - Directory to search
202
- * @param {Array} extensions - File extensions to match
203
- * @returns {Array} List of matching files
204
- */
205
- async findFilesRecursively(dir, extensions) {
206
- const files = [];
207
-
208
- async function search(currentDir) {
209
- const entries = await fs.readdir(currentDir, { withFileTypes: true });
210
-
211
- for (const entry of entries) {
212
- const fullPath = path.join(currentDir, entry.name);
213
-
214
- if (entry.isDirectory()) {
215
- await search(fullPath);
216
- } else if (extensions.some((ext) => entry.name.endsWith(ext))) {
217
- files.push(fullPath);
218
- }
219
- }
220
- }
221
-
222
- await search(dir);
223
- return files;
224
- }
225
-
226
- /**
227
- * Recursively copy a directory
228
- * @param {string} sourceDir - Source directory
229
- * @param {string} targetDir - Target directory
230
- * @param {Object} results - Results object to update
231
- * @param {Function} fileTrackingCallback - Optional callback
232
- * @param {Object} config - Configuration for placeholder replacement
233
- */
234
- async copyDirectory(sourceDir, targetDir, results, fileTrackingCallback, config) {
235
- await fs.ensureDir(targetDir);
236
- const entries = await fs.readdir(sourceDir, { withFileTypes: true });
237
-
238
- for (const entry of entries) {
239
- const sourcePath = path.join(sourceDir, entry.name);
240
- const targetPath = path.join(targetDir, entry.name);
241
-
242
- if (entry.isDirectory()) {
243
- await this.copyDirectory(sourcePath, targetPath, results, fileTrackingCallback, config);
244
- } else {
245
- try {
246
- // Check if file already exists
247
- if (await fs.pathExists(targetPath)) {
248
- // File already exists, preserve it
249
- results.preserved = (results.preserved || 0) + 1;
250
- } else {
251
- // Copy with placeholder replacement for text files
252
- const textExtensions = ['.md', '.yaml', '.yml', '.txt', '.json'];
253
- if (textExtensions.some((ext) => entry.name.endsWith(ext))) {
254
- // Read source content
255
- let content = await fs.readFile(sourcePath, 'utf8');
256
-
257
- // Replace placeholders
258
- content = content.replaceAll('{user_name}', config.user_name || 'User');
259
- content = content.replaceAll('{communication_language}', config.communication_language || 'English');
260
- content = content.replaceAll('{output_folder}', config.output_folder || 'docs');
261
-
262
- // Write to target
263
- await fs.ensureDir(path.dirname(targetPath));
264
- await fs.writeFile(targetPath, content, 'utf8');
265
- } else {
266
- // Copy binary files as-is
267
- await fs.copy(sourcePath, targetPath);
268
- }
269
-
270
- results.filesCopied++;
271
- if (entry.name.endsWith('.md')) {
272
- results.workflowsInstalled++;
273
- }
274
- if (fileTrackingCallback) {
275
- fileTrackingCallback(targetPath);
276
- }
277
- }
278
- } catch (error) {
279
- results.errors.push(`Failed to copy ${entry.name}: ${error.message}`);
280
- }
281
- }
282
- }
283
- }
284
-
285
- /**
286
- * Compile .agent.yaml files to .md format and handle sidecars
287
- * @param {string} sourceAgentsPath - Source agents directory
288
- * @param {string} targetAgentsPath - Target agents directory
289
- * @param {string} bmadDir - BMAD installation directory
290
- * @param {Object} config - Configuration for placeholder replacement
291
- * @param {Function} fileTrackingCallback - Optional callback to track installed files
292
- * @param {Object} results - Results object to update
293
- */
294
- async compileAndCopyAgents(sourceAgentsPath, targetAgentsPath, bmadDir, config, fileTrackingCallback, results) {
295
- // Get all .agent.yaml files recursively
296
- const agentFiles = await this.findFilesRecursively(sourceAgentsPath, ['.agent.yaml']);
297
-
298
- for (const agentFile of agentFiles) {
299
- const relativePath = path.relative(sourceAgentsPath, agentFile).split(path.sep).join('/');
300
- const targetDir = path.join(targetAgentsPath, path.dirname(relativePath));
301
-
302
- await fs.ensureDir(targetDir);
303
-
304
- const agentName = path.basename(agentFile, '.agent.yaml');
305
- const targetMdPath = path.join(targetDir, `${agentName}.md`);
306
- // Use the actual bmadDir if available (for when installing to temp dir)
307
- const actualBmadDir = config._bmadDir || bmadDir;
308
- const customizePath = path.join(actualBmadDir, '_config', 'agents', `custom-${agentName}.customize.yaml`);
309
-
310
- // Read and compile the YAML
311
- try {
312
- const yamlContent = await fs.readFile(agentFile, 'utf8');
313
- const { compileAgent } = require('../../../lib/agent/compiler');
314
-
315
- // Create customize template if it doesn't exist
316
- if (!(await fs.pathExists(customizePath))) {
317
- const { getSourcePath } = require('../../../lib/project-root');
318
- const genericTemplatePath = getSourcePath('utility', 'agent-components', 'agent.customize.template.yaml');
319
- if (await fs.pathExists(genericTemplatePath)) {
320
- let templateContent = await fs.readFile(genericTemplatePath, 'utf8');
321
- await fs.writeFile(customizePath, templateContent, 'utf8');
322
- // Only show customize creation in verbose mode
323
- if (process.env.BMAD_VERBOSE_INSTALL === 'true') {
324
- await prompts.log.message(' Created customize: custom-' + agentName + '.customize.yaml');
325
- }
326
- }
327
- }
328
-
329
- // Compile the agent
330
- const { xml } = compileAgent(yamlContent, {}, agentName, relativePath, { config });
331
-
332
- // Replace placeholders in the compiled content
333
- let processedXml = xml;
334
- processedXml = processedXml.replaceAll('{user_name}', config.user_name || 'User');
335
- processedXml = processedXml.replaceAll('{communication_language}', config.communication_language || 'English');
336
- processedXml = processedXml.replaceAll('{output_folder}', config.output_folder || 'docs');
337
-
338
- // Write the compiled MD file
339
- await fs.writeFile(targetMdPath, processedXml, 'utf8');
340
-
341
- // Track the file
342
- if (fileTrackingCallback) {
343
- fileTrackingCallback(targetMdPath);
344
- }
345
-
346
- // Only show compilation details in verbose mode
347
- if (process.env.BMAD_VERBOSE_INSTALL === 'true') {
348
- await prompts.log.message(' Compiled agent: ' + agentName + ' -> ' + path.relative(targetAgentsPath, targetMdPath));
349
- }
350
- } catch (error) {
351
- await prompts.log.warn(' Failed to compile agent ' + agentName + ': ' + error.message);
352
- results.errors.push(`Failed to compile agent ${agentName}: ${error.message}`);
353
- }
354
- }
355
- }
356
110
  }
357
111
 
358
112
  module.exports = { CustomHandler };
@@ -1,6 +1,5 @@
1
1
  const path = require('node:path');
2
2
  const fs = require('fs-extra');
3
- const { XmlHandler } = require('../../../lib/xml-handler');
4
3
  const prompts = require('../../../lib/prompts');
5
4
  const { getSourcePath } = require('../../../lib/project-root');
6
5
  const { BMAD_FOLDER_NAME } = require('./shared/path-utils');
@@ -18,7 +17,6 @@ class BaseIdeSetup {
18
17
  this.rulesDir = null; // Override in subclasses
19
18
  this.configFile = null; // Override in subclasses when detection is file-based
20
19
  this.detectionPaths = []; // Additional paths that indicate the IDE is configured
21
- this.xmlHandler = new XmlHandler();
22
20
  this.bmadFolderName = BMAD_FOLDER_NAME; // Default, can be overridden
23
21
  }
24
22
 
@@ -30,15 +28,6 @@ class BaseIdeSetup {
30
28
  this.bmadFolderName = bmadFolderName;
31
29
  }
32
30
 
33
- /**
34
- * Get the agent command activation header from the central template
35
- * @returns {string} The activation header text
36
- */
37
- async getAgentCommandHeader() {
38
- const headerPath = getSourcePath('utility', 'agent-components', 'agent-command-header.md');
39
- return await fs.readFile(headerPath, 'utf8');
40
- }
41
-
42
31
  /**
43
32
  * Main setup method - must be implemented by subclasses
44
33
  * @param {string} projectDir - Project directory
@@ -511,11 +500,6 @@ class BaseIdeSetup {
511
500
  // Replace placeholders
512
501
  let processed = content;
513
502
 
514
- // Inject activation block for agent files FIRST (before replacements)
515
- if (metadata.name && content.includes('<agent')) {
516
- processed = this.xmlHandler.injectActivationSimple(processed, metadata);
517
- }
518
-
519
503
  // Only replace {project-root} if a specific projectDir is provided
520
504
  // Otherwise leave the placeholder intact
521
505
  // Note: Don't add trailing slash - paths in source include leading slash