mirror of
https://github.com/bmadcode/BMAD-METHOD.git
synced 2025-12-17 09:45:25 +00:00
remove dead and unused functionality - the web bundler will be replaced
This commit is contained in:
parent
ed0defbe08
commit
e6f911d791
@ -2,31 +2,26 @@ header: "BMAD™ Core Configuration"
|
||||
subheader: "Configure the core settings for your BMAD™ installation.\nThese settings will be used across all modules and agents."
|
||||
|
||||
user_name:
|
||||
prompt: "What shall the agents call you?"
|
||||
prompt: "What shall the agents call you (TIP: Use a team name if using with a group)?"
|
||||
default: "BMad"
|
||||
result: "{value}"
|
||||
|
||||
communication_language:
|
||||
prompt: "Preferred Chat Language/Style? (English, Mandarin, English Pirate, etc...)"
|
||||
prompt: "Preferred chat language/style? (English, Mandarin, English Pirate, etc...)"
|
||||
default: "English"
|
||||
result: "{value}"
|
||||
|
||||
document_output_language:
|
||||
prompt: "Preferred Document Output Language?"
|
||||
prompt: "Preferred document output language?"
|
||||
default: "{communication_language}"
|
||||
result: "{value}"
|
||||
|
||||
output_folder:
|
||||
prompt: "Where should AI generated artifacts be saved across all modules?"
|
||||
default: "docs"
|
||||
result: "{project-root}/{value}"
|
||||
|
||||
agent_sidecar_folder:
|
||||
prompt: "Where should users agent sidecar memory folders be stored?"
|
||||
default: ".bmad-user-memory"
|
||||
result: "{project-root}/{value}"
|
||||
|
||||
output_folder:
|
||||
prompt: "Where should AI Generated Artifacts be saved across all modules?"
|
||||
default: "docs"
|
||||
result: "{project-root}/{value}"
|
||||
|
||||
install_user_docs:
|
||||
prompt: "Install user documentation and optimized agent intelligence to each selected modules docs folder?"
|
||||
default: true
|
||||
result: "{value}"
|
||||
|
||||
@ -11,8 +11,6 @@ subheader: "Configure the settings for the BoMB Factory!\nThe agent, workflow an
|
||||
## user_name
|
||||
## communication_language
|
||||
## output_folder
|
||||
## install_user_docs
|
||||
## kb_install
|
||||
|
||||
custom_stand_alone_location:
|
||||
prompt: "Where do custom agents and workflows get stored?"
|
||||
|
||||
@ -11,8 +11,6 @@ subheader: "Agent and Workflow Configuration for this module"
|
||||
## user_name
|
||||
## communication_language
|
||||
## output_folder
|
||||
## install_user_docs
|
||||
## kb_install
|
||||
|
||||
project_name:
|
||||
prompt: "What is the title of your project you will be working on?"
|
||||
@ -21,9 +19,8 @@ project_name:
|
||||
|
||||
user_skill_level:
|
||||
prompt:
|
||||
- "What is your technical experience level?"
|
||||
- "This affects how agents explain concepts to you (NOT document content)."
|
||||
- "Documents are always concise for LLM efficiency."
|
||||
- "What is your development experience level?"
|
||||
- "This affects how agents explain concepts in chat."
|
||||
default: "intermediate"
|
||||
result: "{value}"
|
||||
single-select:
|
||||
@ -35,7 +32,7 @@ user_skill_level:
|
||||
label: "Expert - Deep technical knowledge, be direct and technical"
|
||||
|
||||
sprint_artifacts:
|
||||
prompt: "Where should Sprint Artifacts be stored (sprint status, stories, story context, temp context, etc...)?"
|
||||
prompt: "Where should sprint artifacts be stored (sprint status, stories, retrospectives)?"
|
||||
default: "{output_folder}/sprint-artifacts"
|
||||
result: "{project-root}/{value}"
|
||||
|
||||
|
||||
@ -1,85 +0,0 @@
|
||||
<task id="bmad/bmm/tasks/daily-standup.xml" name="Daily Standup">
|
||||
<llm critical="true">
|
||||
<i>MANDATORY: Execute ALL steps in the flow section IN EXACT ORDER</i>
|
||||
<i>DO NOT skip steps or change the sequence</i>
|
||||
<i>HALT immediately when halt-conditions are met</i>
|
||||
<i>Each action tag within a step tag is a REQUIRED action to complete that step</i>
|
||||
<i>Sections outside flow (validation, output, critical-context) provide essential context - review and apply throughout execution</i>
|
||||
</llm>
|
||||
<flow>
|
||||
<step n="1" title="Project Context Discovery">
|
||||
<action>Check for stories folder at {project-root}{output_folder}/stories/</action>
|
||||
<action>Find current story by identifying highest numbered story file</action>
|
||||
<action>Read story status (In Progress, Ready for Review, etc.)</action>
|
||||
<action>Extract agent notes from Dev Agent Record, TEA Results, PO Notes sections</action>
|
||||
<action>Check for next story references from epics</action>
|
||||
<action>Identify blockers from story sections</action>
|
||||
</step>
|
||||
|
||||
<step n="2" title="Initialize Standup with Context">
|
||||
<output>
|
||||
🏃 DAILY STANDUP - Story-{{number}}: {{title}}
|
||||
|
||||
Current Sprint Status:
|
||||
- Active Story: story-{{number}} ({{status}} - {{percentage}}% complete)
|
||||
- Next in Queue: story-{{next-number}}: {{next-title}}
|
||||
- Blockers: {{blockers-from-story}}
|
||||
|
||||
Team assembled based on story participants:
|
||||
{{ List Agents from {project-root}/bmad/_cfg/agent-manifest.csv }}
|
||||
</output>
|
||||
</step>
|
||||
|
||||
<step n="3" title="Structured Standup Discussion">
|
||||
<action>Each agent provides three items referencing real story data</action>
|
||||
<action>What I see: Their perspective on current work, citing story sections (1-2 sentences)</action>
|
||||
<action>What concerns me: Issues from their domain or story blockers (1-2 sentences)</action>
|
||||
<action>What I suggest: Actionable recommendations for progress (1-2 sentences)</action>
|
||||
</step>
|
||||
|
||||
<step n="4" title="Create Standup Summary">
|
||||
<output>
|
||||
📋 STANDUP SUMMARY:
|
||||
Key Items from Story File:
|
||||
- {{completion-percentage}}% complete ({{tasks-complete}}/{{total-tasks}} tasks)
|
||||
- Blocker: {{main-blocker}}
|
||||
- Next: {{next-story-reference}}
|
||||
|
||||
Action Items:
|
||||
- {{agent}}: {{action-item}}
|
||||
- {{agent}}: {{action-item}}
|
||||
- {{agent}}: {{action-item}}
|
||||
|
||||
Need extended discussion? Use *party-mode for detailed breakout.
|
||||
</output>
|
||||
</step>
|
||||
</flow>
|
||||
|
||||
<agent-selection>
|
||||
<context type="prd-review">
|
||||
<i>Primary: Sarah (PO), Mary (Analyst), Winston (Architect)</i>
|
||||
<i>Secondary: Murat (TEA), James (Dev)</i>
|
||||
</context>
|
||||
<context type="story-planning">
|
||||
<i>Primary: Sarah (PO), Bob (SM), James (Dev)</i>
|
||||
<i>Secondary: Murat (TEA)</i>
|
||||
</context>
|
||||
<context type="validate-architecture">
|
||||
<i>Primary: Winston (Architect), James (Dev), Murat (TEA)</i>
|
||||
<i>Secondary: Sarah (PO)</i>
|
||||
</context>
|
||||
<context type="implementation">
|
||||
<i>Primary: James (Dev), Murat (TEA), Winston (Architect)</i>
|
||||
<i>Secondary: Sarah (PO)</i>
|
||||
</context>
|
||||
</agent-selection>
|
||||
|
||||
<llm critical="true">
|
||||
<i>This task extends party-mode with agile-specific structure</i>
|
||||
<i>Time-box responses (standup = brief)</i>
|
||||
<i>Focus on actionable items from real story data when available</i>
|
||||
<i>End with clear next steps</i>
|
||||
<i>No deep dives (suggest breakout if needed)</i>
|
||||
<i>If no stories folder detected, run general standup format</i>
|
||||
</llm>
|
||||
</task>
|
||||
@ -10,6 +10,3 @@ subheader: "No Configuration needed - uses Core Config only."
|
||||
## user_name
|
||||
## communication_language
|
||||
## output_folder
|
||||
## install_user_docs
|
||||
## kb_install
|
||||
|
||||
|
||||
@ -1,179 +0,0 @@
|
||||
const { WebBundler } = require('./web-bundler');
|
||||
const chalk = require('chalk');
|
||||
const { program } = require('commander');
|
||||
const path = require('node:path');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
program.name('bundle-web').description('Generate web bundles for BMAD agents and teams').version('1.0.0');
|
||||
|
||||
program
|
||||
.command('all')
|
||||
.description('Bundle all modules')
|
||||
.option('-o, --output <path>', 'Output directory', 'web-bundles')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
const bundler = new WebBundler(null, options.output);
|
||||
await bundler.bundleAll();
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('rebundle')
|
||||
.description('Clean and rebundle all modules')
|
||||
.option('-o, --output <path>', 'Output directory', 'web-bundles')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
// Clean output directory first
|
||||
const outputDir = path.isAbsolute(options.output) ? options.output : path.join(process.cwd(), options.output);
|
||||
|
||||
if (await fs.pathExists(outputDir)) {
|
||||
console.log(chalk.cyan(`🧹 Cleaning ${options.output}...`));
|
||||
await fs.emptyDir(outputDir);
|
||||
}
|
||||
|
||||
// Bundle all
|
||||
const bundler = new WebBundler(null, options.output);
|
||||
await bundler.bundleAll();
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('module <name>')
|
||||
.description('Bundle a specific module')
|
||||
.option('-o, --output <path>', 'Output directory', 'web-bundles')
|
||||
.action(async (moduleName, options) => {
|
||||
try {
|
||||
const bundler = new WebBundler(null, options.output);
|
||||
const result = await bundler.bundleModule(moduleName);
|
||||
|
||||
if (result.agents.length === 0 && result.teams.length === 0) {
|
||||
console.log(chalk.yellow(`No agents or teams found in module: ${moduleName}`));
|
||||
} else {
|
||||
console.log(chalk.green(`\n✨ Successfully bundled ${result.agents.length} agents and ${result.teams.length} teams`));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('agent <module> <agent>')
|
||||
.description('Bundle a specific agent')
|
||||
.option('-o, --output <path>', 'Output directory', 'web-bundles')
|
||||
.action(async (moduleName, agentFile, options) => {
|
||||
try {
|
||||
const bundler = new WebBundler(null, options.output);
|
||||
|
||||
// Ensure .md extension
|
||||
if (!agentFile.endsWith('.md')) {
|
||||
agentFile += '.md';
|
||||
}
|
||||
|
||||
// Pre-discover module for complete manifests
|
||||
await bundler.preDiscoverModule(moduleName);
|
||||
|
||||
await bundler.bundleAgent(moduleName, agentFile, false);
|
||||
console.log(chalk.green(`\n✨ Successfully bundled agent: ${agentFile}`));
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('team <module> <team>')
|
||||
.description('Bundle a specific team')
|
||||
.option('-o, --output <path>', 'Output directory', 'web-bundles')
|
||||
.action(async (moduleName, teamFile, options) => {
|
||||
try {
|
||||
const bundler = new WebBundler(null, options.output);
|
||||
|
||||
// Ensure .yaml or .yml extension
|
||||
if (!teamFile.endsWith('.yaml') && !teamFile.endsWith('.yml')) {
|
||||
teamFile += '.yaml';
|
||||
}
|
||||
|
||||
// Pre-discover module for complete manifests
|
||||
await bundler.preDiscoverModule(moduleName);
|
||||
|
||||
await bundler.bundleTeam(moduleName, teamFile);
|
||||
console.log(chalk.green(`\n✨ Successfully bundled team: ${teamFile}`));
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('list')
|
||||
.description('List available modules and agents')
|
||||
.action(async () => {
|
||||
try {
|
||||
const bundler = new WebBundler();
|
||||
const modules = await bundler.discoverModules();
|
||||
|
||||
console.log(chalk.cyan.bold('\n📦 Available Modules:\n'));
|
||||
|
||||
for (const module of modules) {
|
||||
console.log(chalk.bold(` ${module}/`));
|
||||
|
||||
const modulePath = path.join(bundler.modulesPath, module);
|
||||
const agents = await bundler.discoverAgents(modulePath);
|
||||
const teams = await bundler.discoverTeams(modulePath);
|
||||
|
||||
if (agents.length > 0) {
|
||||
console.log(chalk.gray(' agents/'));
|
||||
for (const agent of agents) {
|
||||
console.log(chalk.gray(` - ${agent}`));
|
||||
}
|
||||
}
|
||||
|
||||
if (teams.length > 0) {
|
||||
console.log(chalk.gray(' teams/'));
|
||||
for (const team of teams) {
|
||||
console.log(chalk.gray(` - ${team}`));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('');
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('clean')
|
||||
.description('Remove all web bundles')
|
||||
.action(async () => {
|
||||
try {
|
||||
const fs = require('fs-extra');
|
||||
const outputDir = path.join(process.cwd(), 'web-bundles');
|
||||
|
||||
if (await fs.pathExists(outputDir)) {
|
||||
await fs.remove(outputDir);
|
||||
console.log(chalk.green('✓ Web bundles directory cleaned'));
|
||||
} else {
|
||||
console.log(chalk.yellow('Web bundles directory does not exist'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
// Parse command line arguments
|
||||
program.parse(process.argv);
|
||||
|
||||
// Show help if no command provided
|
||||
if (process.argv.slice(2).length === 0) {
|
||||
program.outputHelp();
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
const { WebBundler } = require('./web-bundler');
|
||||
const chalk = require('chalk');
|
||||
const path = require('node:path');
|
||||
|
||||
async function testAnalystBundle() {
|
||||
console.log(chalk.cyan.bold('\n🧪 Testing Analyst Agent Bundle\n'));
|
||||
|
||||
try {
|
||||
const bundler = new WebBundler();
|
||||
|
||||
// Load web activation first
|
||||
await bundler.loadWebActivation();
|
||||
|
||||
// Bundle just the analyst agent from bmm module
|
||||
// Only bundle the analyst for testing
|
||||
const agentPath = path.join(bundler.modulesPath, 'bmm', 'agents', 'analyst.md');
|
||||
await bundler.bundleAgent('bmm', 'analyst.md');
|
||||
|
||||
console.log(chalk.green.bold('\n✅ Test completed successfully!\n'));
|
||||
} catch (error) {
|
||||
console.error(chalk.red('\n❌ Test failed:'), error.message);
|
||||
console.error(error.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Run test
|
||||
testAnalystBundle();
|
||||
@ -1,118 +0,0 @@
|
||||
const { WebBundler } = require('./web-bundler');
|
||||
const chalk = require('chalk');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('node:path');
|
||||
|
||||
async function testWebBundler() {
|
||||
console.log(chalk.cyan.bold('\n🧪 Testing Web Bundler\n'));
|
||||
|
||||
const bundler = new WebBundler();
|
||||
let passedTests = 0;
|
||||
let failedTests = 0;
|
||||
|
||||
// Test 1: Load web activation
|
||||
try {
|
||||
await bundler.loadWebActivation();
|
||||
console.log(chalk.green('✓ Web activation loaded successfully'));
|
||||
passedTests++;
|
||||
} catch (error) {
|
||||
console.error(chalk.red('✗ Failed to load web activation:'), error.message);
|
||||
failedTests++;
|
||||
}
|
||||
|
||||
// Test 2: Discover modules
|
||||
try {
|
||||
const modules = await bundler.discoverModules();
|
||||
console.log(chalk.green(`✓ Discovered ${modules.length} modules:`, modules.join(', ')));
|
||||
passedTests++;
|
||||
} catch (error) {
|
||||
console.error(chalk.red('✗ Failed to discover modules:'), error.message);
|
||||
failedTests++;
|
||||
}
|
||||
|
||||
// Test 3: Bundle analyst agent
|
||||
try {
|
||||
const result = await bundler.bundleAgent('bmm', 'analyst.md');
|
||||
|
||||
// Check if bundle was created
|
||||
const bundlePath = path.join(bundler.outputDir, 'bmm', 'agents', 'analyst.xml');
|
||||
if (await fs.pathExists(bundlePath)) {
|
||||
const content = await fs.readFile(bundlePath, 'utf8');
|
||||
|
||||
// Validate bundle structure
|
||||
const hasAgent = content.includes('<agent');
|
||||
const hasActivation = content.includes('<activation');
|
||||
const hasPersona = content.includes('<persona>');
|
||||
const activationBeforePersona = content.indexOf('<activation') < content.indexOf('<persona>');
|
||||
const hasManifests =
|
||||
content.includes('<agent-party id="bmad/_cfg/agent-manifest.csv">') && content.includes('<manifest id="bmad/web-manifest.xml">');
|
||||
const hasDependencies = content.includes('<dependencies>');
|
||||
|
||||
console.log(chalk.green('✓ Analyst bundle created successfully'));
|
||||
console.log(chalk.gray(` - Has agent tag: ${hasAgent ? '✓' : '✗'}`));
|
||||
console.log(chalk.gray(` - Has activation: ${hasActivation ? '✓' : '✗'}`));
|
||||
console.log(chalk.gray(` - Has persona: ${hasPersona ? '✓' : '✗'}`));
|
||||
console.log(chalk.gray(` - Activation before persona: ${activationBeforePersona ? '✓' : '✗'}`));
|
||||
console.log(chalk.gray(` - Has manifests: ${hasManifests ? '✓' : '✗'}`));
|
||||
console.log(chalk.gray(` - Has dependencies: ${hasDependencies ? '✓' : '✗'}`));
|
||||
|
||||
if (hasAgent && hasActivation && hasPersona && activationBeforePersona && hasManifests && hasDependencies) {
|
||||
passedTests++;
|
||||
} else {
|
||||
console.error(chalk.red('✗ Bundle structure validation failed'));
|
||||
failedTests++;
|
||||
}
|
||||
} else {
|
||||
console.error(chalk.red('✗ Bundle file not created'));
|
||||
failedTests++;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(chalk.red('✗ Failed to bundle analyst agent:'), error.message);
|
||||
failedTests++;
|
||||
}
|
||||
|
||||
// Test 4: Bundle a different agent (architect which exists)
|
||||
try {
|
||||
const result = await bundler.bundleAgent('bmm', 'architect.md');
|
||||
const bundlePath = path.join(bundler.outputDir, 'bmm', 'agents', 'architect.xml');
|
||||
|
||||
if (await fs.pathExists(bundlePath)) {
|
||||
console.log(chalk.green('✓ Architect bundle created successfully'));
|
||||
passedTests++;
|
||||
} else {
|
||||
console.error(chalk.red('✗ Architect bundle file not created'));
|
||||
failedTests++;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(chalk.red('✗ Failed to bundle architect agent:'), error.message);
|
||||
failedTests++;
|
||||
}
|
||||
|
||||
// Test 5: Bundle all agents in a module
|
||||
try {
|
||||
const results = await bundler.bundleModule('bmm');
|
||||
console.log(chalk.green(`✓ Bundled ${results.agents.length} agents from bmm module`));
|
||||
passedTests++;
|
||||
} catch (error) {
|
||||
console.error(chalk.red('✗ Failed to bundle bmm module:'), error.message);
|
||||
failedTests++;
|
||||
}
|
||||
|
||||
// Summary
|
||||
console.log(chalk.bold('\n📊 Test Results:'));
|
||||
console.log(chalk.green(` Passed: ${passedTests}`));
|
||||
console.log(chalk.red(` Failed: ${failedTests}`));
|
||||
|
||||
if (failedTests === 0) {
|
||||
console.log(chalk.green.bold('\n✅ All tests passed!\n'));
|
||||
} else {
|
||||
console.log(chalk.red.bold(`\n❌ ${failedTests} test(s) failed\n`));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Run tests
|
||||
testWebBundler().catch((error) => {
|
||||
console.error(chalk.red('Fatal error:'), error);
|
||||
process.exit(1);
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,239 +0,0 @@
|
||||
/**
|
||||
* Utility function to replace {project-root} placeholders with actual installation target
|
||||
* Used during BMAD installation to set correct paths in agent and task files
|
||||
*/
|
||||
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
/**
|
||||
* Replace {project-root} and {output_folder}/ placeholders in a single file
|
||||
* @param {string} filePath - Path to the file to process
|
||||
* @param {string} projectRoot - The actual project root path to substitute (must include trailing slash)
|
||||
* @param {string} docOut - The document output path (with leading slash)
|
||||
* @param {boolean} removeCompletely - If true, removes placeholders entirely instead of replacing
|
||||
* @returns {boolean} - True if replacements were made, false otherwise
|
||||
*/
|
||||
function replacePlaceholdersInFile(filePath, projectRoot, docOut = '/docs', removeCompletely = false) {
|
||||
try {
|
||||
let content = fs.readFileSync(filePath, 'utf8');
|
||||
const originalContent = content;
|
||||
|
||||
if (removeCompletely) {
|
||||
// Remove placeholders entirely (for bundling)
|
||||
content = content.replaceAll('{project-root}', '');
|
||||
content = content.replaceAll('{output_folder}/', '');
|
||||
} else {
|
||||
// Handle the combined pattern first to avoid double slashes
|
||||
if (projectRoot && docOut) {
|
||||
// Replace {project-root}{output_folder}/ combinations first
|
||||
// Remove leading slash from docOut since projectRoot has trailing slash
|
||||
// Add trailing slash to docOut
|
||||
const docOutNoLeadingSlash = docOut.replace(/^\//, '');
|
||||
const docOutWithTrailingSlash = docOutNoLeadingSlash.endsWith('/') ? docOutNoLeadingSlash : docOutNoLeadingSlash + '/';
|
||||
content = content.replaceAll('{project-root}{output_folder}/', projectRoot + docOutWithTrailingSlash);
|
||||
}
|
||||
|
||||
// Then replace remaining individual placeholders
|
||||
if (projectRoot) {
|
||||
content = content.replaceAll('{project-root}', projectRoot);
|
||||
}
|
||||
|
||||
if (docOut) {
|
||||
// For standalone {output_folder}/, keep the leading slash and add trailing slash
|
||||
const docOutWithTrailingSlash = docOut.endsWith('/') ? docOut : docOut + '/';
|
||||
content = content.replaceAll('{output_folder}/', docOutWithTrailingSlash);
|
||||
}
|
||||
}
|
||||
|
||||
if (content !== originalContent) {
|
||||
fs.writeFileSync(filePath, content, 'utf8');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error(`Error processing file ${filePath}:`, error.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy function name for backward compatibility
|
||||
*/
|
||||
function replaceProjectRootInFile(filePath, projectRoot, removeCompletely = false) {
|
||||
return replacePlaceholdersInFile(filePath, projectRoot, '/docs', removeCompletely);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively replace {project-root} and {output_folder}/ in all files in a directory
|
||||
* @param {string} dirPath - Directory to process
|
||||
* @param {string} projectRoot - The actual project root path to substitute (or null to remove)
|
||||
* @param {string} docOut - The document output path (with leading slash)
|
||||
* @param {Array<string>} extensions - File extensions to process (default: ['.md', '.xml', '.yaml'])
|
||||
* @param {boolean} removeCompletely - If true, removes placeholders entirely instead of replacing
|
||||
* @param {boolean} verbose - If true, show detailed output for each file
|
||||
* @returns {Object} - Stats object with counts of files processed and modified
|
||||
*/
|
||||
function replacePlaceholdersInDirectory(
|
||||
dirPath,
|
||||
projectRoot,
|
||||
docOut = '/docs',
|
||||
extensions = ['.md', '.xml', '.yaml'],
|
||||
removeCompletely = false,
|
||||
verbose = false,
|
||||
) {
|
||||
const stats = {
|
||||
processed: 0,
|
||||
modified: 0,
|
||||
errors: 0,
|
||||
};
|
||||
|
||||
function processDirectory(currentPath) {
|
||||
try {
|
||||
const items = fs.readdirSync(currentPath, { withFileTypes: true });
|
||||
|
||||
for (const item of items) {
|
||||
const fullPath = path.join(currentPath, item.name);
|
||||
|
||||
if (item.isDirectory()) {
|
||||
// Skip node_modules and .git directories
|
||||
if (item.name !== 'node_modules' && item.name !== '.git') {
|
||||
processDirectory(fullPath);
|
||||
}
|
||||
} else if (item.isFile()) {
|
||||
// Check if file has one of the target extensions
|
||||
const ext = path.extname(item.name).toLowerCase();
|
||||
if (extensions.includes(ext)) {
|
||||
stats.processed++;
|
||||
if (replacePlaceholdersInFile(fullPath, projectRoot, docOut, removeCompletely)) {
|
||||
stats.modified++;
|
||||
if (verbose) {
|
||||
console.log(`✓ Updated: ${fullPath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error processing directory ${currentPath}:`, error.message);
|
||||
stats.errors++;
|
||||
}
|
||||
}
|
||||
|
||||
processDirectory(dirPath);
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy function for backward compatibility
|
||||
*/
|
||||
function replaceProjectRootInDirectory(dirPath, projectRoot, extensions = ['.md', '.xml'], removeCompletely = false) {
|
||||
return replacePlaceholdersInDirectory(dirPath, projectRoot, '/docs', extensions, removeCompletely);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace placeholders in a list of specific files
|
||||
* @param {Array<string>} filePaths - Array of file paths to process
|
||||
* @param {string} projectRoot - The actual project root path to substitute (or null to remove)
|
||||
* @param {string} docOut - The document output path (with leading slash)
|
||||
* @param {boolean} removeCompletely - If true, removes placeholders entirely instead of replacing
|
||||
* @returns {Object} - Stats object with counts of files processed and modified
|
||||
*/
|
||||
function replacePlaceholdersInFiles(filePaths, projectRoot, docOut = '/docs', removeCompletely = false) {
|
||||
const stats = {
|
||||
processed: 0,
|
||||
modified: 0,
|
||||
errors: 0,
|
||||
};
|
||||
|
||||
for (const filePath of filePaths) {
|
||||
stats.processed++;
|
||||
try {
|
||||
if (replacePlaceholdersInFile(filePath, projectRoot, docOut, removeCompletely)) {
|
||||
stats.modified++;
|
||||
console.log(`✓ Updated: ${filePath}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error processing file ${filePath}:`, error.message);
|
||||
stats.errors++;
|
||||
}
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy function for backward compatibility
|
||||
*/
|
||||
function replaceProjectRootInFiles(filePaths, projectRoot, removeCompletely = false) {
|
||||
return replacePlaceholdersInFiles(filePaths, projectRoot, '/docs', removeCompletely);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main installation helper - replaces {project-root} and {output_folder}/ during BMAD installation
|
||||
* @param {string} installPath - Path where BMAD is being installed
|
||||
* @param {string} targetProjectRoot - The project root to set in the files (slash will be added)
|
||||
* @param {string} docsOutputPath - The documentation output path (relative to project root)
|
||||
* @param {boolean} verbose - If true, show detailed output
|
||||
* @returns {Object} - Installation stats
|
||||
*/
|
||||
function processInstallation(installPath, targetProjectRoot, docsOutputPath = 'docs', verbose = false) {
|
||||
// Ensure project root has trailing slash since usage is like {project-root}/bmad
|
||||
const projectRootWithSlash = targetProjectRoot.endsWith('/') ? targetProjectRoot : targetProjectRoot + '/';
|
||||
|
||||
// Ensure docs path has leading slash (for internal use) but will add trailing slash during replacement
|
||||
const normalizedDocsPath = docsOutputPath.replaceAll(/^\/+|\/+$/g, '');
|
||||
const docOutPath = normalizedDocsPath ? `/${normalizedDocsPath}` : '/docs';
|
||||
|
||||
if (verbose) {
|
||||
console.log(`\nReplacing {project-root} with: ${projectRootWithSlash}`);
|
||||
console.log(`Replacing {output_folder}/ with: ${docOutPath}/`);
|
||||
console.log(`Processing files in: ${installPath}\n`);
|
||||
}
|
||||
|
||||
const stats = replacePlaceholdersInDirectory(installPath, projectRootWithSlash, docOutPath, ['.md', '.xml', '.yaml'], false, verbose);
|
||||
|
||||
if (verbose) {
|
||||
console.log('\n--- Installation Processing Complete ---');
|
||||
}
|
||||
console.log(`Files processed: ${stats.processed}`);
|
||||
console.log(`Files modified: ${stats.modified}`);
|
||||
if (stats.errors > 0) {
|
||||
console.log(`Errors encountered: ${stats.errors}`);
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bundle helper - removes {project-root}/ references for web bundling
|
||||
* @param {string} bundlePath - Path where files are being bundled
|
||||
* @returns {Object} - Bundle stats
|
||||
*/
|
||||
function processBundleRemoval(bundlePath) {
|
||||
console.log(`\nRemoving {project-root}/ references for bundling`);
|
||||
console.log(`Processing files in: ${bundlePath}\n`);
|
||||
|
||||
const stats = replaceProjectRootInDirectory(bundlePath, null, ['.md', '.xml'], true);
|
||||
|
||||
console.log('\n--- Bundle Processing Complete ---');
|
||||
console.log(`Files processed: ${stats.processed}`);
|
||||
console.log(`Files modified: ${stats.modified}`);
|
||||
if (stats.errors > 0) {
|
||||
console.log(`Errors encountered: ${stats.errors}`);
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
replacePlaceholdersInFile,
|
||||
replacePlaceholdersInDirectory,
|
||||
replacePlaceholdersInFiles,
|
||||
replaceProjectRootInFile,
|
||||
replaceProjectRootInDirectory,
|
||||
replaceProjectRootInFiles,
|
||||
processInstallation,
|
||||
processBundleRemoval,
|
||||
};
|
||||
@ -1,27 +0,0 @@
|
||||
const path = require('node:path');
|
||||
const { ManifestGenerator } = require('./installers/lib/core/manifest-generator');
|
||||
|
||||
async function regenerateManifests() {
|
||||
const generator = new ManifestGenerator();
|
||||
const targetDir = process.argv[2];
|
||||
|
||||
// List of modules to include in manifests
|
||||
const selectedModules = ['bmb', 'bmm', 'cis'];
|
||||
|
||||
console.log('Regenerating manifests with relative paths...');
|
||||
console.log('Target directory: .bmad');
|
||||
|
||||
try {
|
||||
const result = await generator.generateManifests('.bmad', selectedModules, [], { ides: [] });
|
||||
console.log('✓ Manifests generated successfully:');
|
||||
console.log(` - ${result.workflows} workflows`);
|
||||
console.log(` - ${result.agents} agents`);
|
||||
console.log(` - ${result.tasks} tasks`);
|
||||
console.log(` - ${result.files} files in files-manifest.csv`);
|
||||
} catch (error) {
|
||||
console.error('Error generating manifests:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
regenerateManifests();
|
||||
@ -1,43 +0,0 @@
|
||||
/**
|
||||
* Test script for YAML → XML agent builder
|
||||
* Usage: node tools/cli/test-yaml-builder.js
|
||||
*/
|
||||
|
||||
const path = require('node:path');
|
||||
const { YamlXmlBuilder } = require('./lib/yaml-xml-builder');
|
||||
const { getProjectRoot } = require('./lib/project-root');
|
||||
|
||||
async function test() {
|
||||
console.log('Testing YAML → XML Agent Builder\n');
|
||||
|
||||
const builder = new YamlXmlBuilder();
|
||||
const projectRoot = getProjectRoot();
|
||||
|
||||
// Paths
|
||||
const agentYamlPath = path.join(projectRoot, 'src/modules/bmm/agents/pm.agent.yaml');
|
||||
const outputPath = path.join(projectRoot, 'test-output-pm.md');
|
||||
|
||||
console.log(`Source: ${agentYamlPath}`);
|
||||
console.log(`Output: ${outputPath}\n`);
|
||||
|
||||
try {
|
||||
const result = await builder.buildAgent(
|
||||
agentYamlPath,
|
||||
null, // No customize file for this test
|
||||
outputPath,
|
||||
{ includeMetadata: true },
|
||||
);
|
||||
|
||||
console.log('✓ Build successful!');
|
||||
console.log(` Output: ${result.outputPath}`);
|
||||
console.log(` Source hash: ${result.sourceHash}`);
|
||||
console.log('\nGenerated XML file at:', outputPath);
|
||||
console.log('Review the output to verify correctness.\n');
|
||||
} catch (error) {
|
||||
console.error('✗ Build failed:', error.message);
|
||||
console.error(error.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
||||
@ -6,7 +6,7 @@ const ignore = require('ignore');
|
||||
// These complement .gitignore and are applied regardless of VCS presence.
|
||||
const DEFAULT_PATTERNS = [
|
||||
// Project/VCS
|
||||
'**/.bmad-method/**',
|
||||
'**/_bmad/**',
|
||||
'**/.git/**',
|
||||
'**/.svn/**',
|
||||
'**/.hg/**',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user