Compare commits
6 Commits
cefdaddfbe
...
53a75cbf4a
| Author | SHA1 | Date |
|---|---|---|
|
|
53a75cbf4a | |
|
|
1677d54f22 | |
|
|
1ee10ddcab | |
|
|
147144a1ec | |
|
|
7a016d5efa | |
|
|
c017a5fdba |
|
|
@ -1,7 +1,7 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 📚 Documentation
|
||||
url: http://docs.bmad-method.org
|
||||
url: https://docs.bmad-method.org
|
||||
about: Check the docs first — tutorials, guides, and reference
|
||||
- name: 💬 Discord Community
|
||||
url: https://discord.gg/gk8jAdXWmj
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ body:
|
|||
attributes:
|
||||
label: Documentation location
|
||||
description: Where is the documentation that needs improvement?
|
||||
placeholder: e.g., http://docs.bmad-method.org/tutorials/getting-started/ or "In the README"
|
||||
placeholder: e.g., https://docs.bmad-method.org/tutorials/getting-started/ or "In the README"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
|
|
|||
12
README.md
12
README.md
|
|
@ -20,7 +20,7 @@ Traditional AI tools do the thinking for you, producing average results. BMad ag
|
|||
- **Party Mode** — Bring multiple agent personas into one session to collaborate and discuss
|
||||
- **Complete Lifecycle** — From brainstorming to deployment
|
||||
|
||||
[Learn more at **docs.bmad-method.org**](http://docs.bmad-method.org)
|
||||
[Learn more at **docs.bmad-method.org**](https://docs.bmad-method.org)
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ Traditional AI tools do the thinking for you, producing average results. BMad ag
|
|||
|
||||
**V6 is here and we're just getting started!** The BMad Method is evolving rapidly with optimizations including Cross Platform Agent Team and Sub Agent inclusion, Skills Architecture, BMad Builder v1, Dev Loop Automation, and so much more in the works.
|
||||
|
||||
**[📍 Check out the complete Roadmap →](http://docs.bmad-method.org/roadmap/)**
|
||||
**[📍 Check out the complete Roadmap →](https://docs.bmad-method.org/roadmap/)**
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ Follow the installer prompts, then open your AI IDE (Claude Code, Cursor, etc.)
|
|||
npx bmad-method install --directory /path/to/project --modules bmm --tools claude-code --yes
|
||||
```
|
||||
|
||||
[See all installation options](http://docs.bmad-method.org/how-to/non-interactive-installation/)
|
||||
[See all installation options](https://docs.bmad-method.org/how-to/non-interactive-installation/)
|
||||
|
||||
> **Not sure what to do?** Run `/bmad-help` — it tells you exactly what's next and what's optional. You can also ask questions like `/bmad-help I just finished the architecture, what do I do next?`
|
||||
|
||||
|
|
@ -68,11 +68,11 @@ BMad Method extends with official modules for specialized domains. Available dur
|
|||
|
||||
## Documentation
|
||||
|
||||
[BMad Method Docs Site](http://docs.bmad-method.org) — Tutorials, guides, concepts, and reference
|
||||
[BMad Method Docs Site](https://docs.bmad-method.org) — Tutorials, guides, concepts, and reference
|
||||
|
||||
**Quick links:**
|
||||
- [Getting Started Tutorial](http://docs.bmad-method.org/tutorials/getting-started/)
|
||||
- [Upgrading from Previous Versions](http://docs.bmad-method.org/how-to/upgrade-to-v6/)
|
||||
- [Getting Started Tutorial](https://docs.bmad-method.org/tutorials/getting-started/)
|
||||
- [Upgrading from Previous Versions](https://docs.bmad-method.org/how-to/upgrade-to-v6/)
|
||||
- [Test Architect Documentation](https://bmad-code-org.github.io/bmad-method-test-architecture-enterprise/)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@
|
|||
"lint:md": "markdownlint-cli2 \"**/*.md\"",
|
||||
"prepare": "command -v husky >/dev/null 2>&1 && husky || exit 0",
|
||||
"rebundle": "node tools/cli/bundlers/bundle-web.js rebundle",
|
||||
"test": "npm run test:schemas && npm run test:refs && npm run test:install && npm run validate:schemas && npm run lint && npm run lint:md && npm run format:check",
|
||||
"test": "npm run test:schemas && npm run test:refs && npm run test:install && npm run test:copilot && npm run validate:schemas && npm run lint && npm run lint:md && npm run format:check",
|
||||
"test:copilot": "node test/test-github-copilot-installer.js",
|
||||
"test:coverage": "c8 --reporter=text --reporter=html npm run test:schemas",
|
||||
"test:install": "node test/test-installation-components.js",
|
||||
"test:refs": "node test/test-file-refs-csv.js",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,238 @@
|
|||
/**
|
||||
* GitHub Copilot Installer Tests
|
||||
*
|
||||
* Tests for the GitHubCopilotSetup class methods:
|
||||
* - loadModuleConfig: module-aware config loading
|
||||
* - createTechWriterPromptContent: BMM-only tech-writer handling
|
||||
* - generateCopilotInstructions: selectedModules deduplication
|
||||
*
|
||||
* Usage: node test/test-github-copilot-installer.js
|
||||
*/
|
||||
|
||||
const path = require('node:path');
|
||||
const fs = require('fs-extra');
|
||||
const { GitHubCopilotSetup } = require('../tools/cli/installers/lib/ide/github-copilot');
|
||||
|
||||
// ANSI colors
|
||||
const colors = {
|
||||
reset: '\u001B[0m',
|
||||
green: '\u001B[32m',
|
||||
red: '\u001B[31m',
|
||||
yellow: '\u001B[33m',
|
||||
cyan: '\u001B[36m',
|
||||
dim: '\u001B[2m',
|
||||
};
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
/**
|
||||
* Test helper: Assert condition
|
||||
*/
|
||||
function assert(condition, testName, errorMessage = '') {
|
||||
if (condition) {
|
||||
console.log(`${colors.green}✓${colors.reset} ${testName}`);
|
||||
passed++;
|
||||
} else {
|
||||
console.log(`${colors.red}✗${colors.reset} ${testName}`);
|
||||
if (errorMessage) {
|
||||
console.log(` ${colors.dim}${errorMessage}${colors.reset}`);
|
||||
}
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Suite
|
||||
*/
|
||||
async function runTests() {
|
||||
console.log(`${colors.cyan}========================================`);
|
||||
console.log('GitHub Copilot Installer Tests');
|
||||
console.log(`========================================${colors.reset}\n`);
|
||||
|
||||
const tempDir = path.join(__dirname, 'temp-copilot-test');
|
||||
|
||||
try {
|
||||
// Clean up any leftover temp directory
|
||||
await fs.remove(tempDir);
|
||||
await fs.ensureDir(tempDir);
|
||||
|
||||
const installer = new GitHubCopilotSetup();
|
||||
|
||||
// ============================================================
|
||||
// Test Suite 1: loadModuleConfig
|
||||
// ============================================================
|
||||
console.log(`${colors.yellow}Test Suite 1: loadModuleConfig${colors.reset}\n`);
|
||||
|
||||
// Create mock bmad directory structure with multiple modules
|
||||
const bmadDir = path.join(tempDir, '_bmad');
|
||||
await fs.ensureDir(path.join(bmadDir, 'core'));
|
||||
await fs.ensureDir(path.join(bmadDir, 'bmm'));
|
||||
await fs.ensureDir(path.join(bmadDir, 'custom-module'));
|
||||
|
||||
// Create config files for each module
|
||||
await fs.writeFile(path.join(bmadDir, 'core', 'config.yaml'), 'project_name: Core Project\nuser_name: CoreUser\n');
|
||||
await fs.writeFile(path.join(bmadDir, 'bmm', 'config.yaml'), 'project_name: BMM Project\nuser_name: BmmUser\n');
|
||||
await fs.writeFile(path.join(bmadDir, 'custom-module', 'config.yaml'), 'project_name: Custom Project\nuser_name: CustomUser\n');
|
||||
|
||||
// Test 1a: Load config with only core module (default)
|
||||
const coreConfig = await installer.loadModuleConfig(bmadDir, ['core']);
|
||||
assert(
|
||||
coreConfig.project_name === 'Core Project',
|
||||
'loadModuleConfig loads core config when only core installed',
|
||||
`Got: ${coreConfig.project_name}`,
|
||||
);
|
||||
|
||||
// Test 1b: Load config with bmm module (should prefer bmm over core)
|
||||
const bmmConfig = await installer.loadModuleConfig(bmadDir, ['bmm', 'core']);
|
||||
assert(bmmConfig.project_name === 'BMM Project', 'loadModuleConfig prefers bmm config over core', `Got: ${bmmConfig.project_name}`);
|
||||
|
||||
// Test 1c: Load config with custom module (should prefer custom over core)
|
||||
const customConfig = await installer.loadModuleConfig(bmadDir, ['custom-module', 'core']);
|
||||
assert(
|
||||
customConfig.project_name === 'Custom Project',
|
||||
'loadModuleConfig prefers custom module config over core',
|
||||
`Got: ${customConfig.project_name}`,
|
||||
);
|
||||
|
||||
// Test 1d: Load config with multiple non-core modules (first wins)
|
||||
const multiConfig = await installer.loadModuleConfig(bmadDir, ['bmm', 'custom-module', 'core']);
|
||||
assert(
|
||||
multiConfig.project_name === 'BMM Project',
|
||||
'loadModuleConfig uses first non-core module config',
|
||||
`Got: ${multiConfig.project_name}`,
|
||||
);
|
||||
|
||||
// Test 1e: Empty modules list uses default (core)
|
||||
const defaultConfig = await installer.loadModuleConfig(bmadDir);
|
||||
assert(
|
||||
defaultConfig.project_name === 'Core Project',
|
||||
'loadModuleConfig defaults to core when no modules specified',
|
||||
`Got: ${defaultConfig.project_name}`,
|
||||
);
|
||||
|
||||
// Test 1f: Non-existent module falls back to core
|
||||
const fallbackConfig = await installer.loadModuleConfig(bmadDir, ['nonexistent', 'core']);
|
||||
assert(
|
||||
fallbackConfig.project_name === 'Core Project',
|
||||
'loadModuleConfig falls back to core for non-existent modules',
|
||||
`Got: ${fallbackConfig.project_name}`,
|
||||
);
|
||||
|
||||
console.log('');
|
||||
|
||||
// ============================================================
|
||||
// Test Suite 2: createTechWriterPromptContent (BMM-only)
|
||||
// ============================================================
|
||||
console.log(`${colors.yellow}Test Suite 2: createTechWriterPromptContent (BMM-only)${colors.reset}\n`);
|
||||
|
||||
// Test 2a: BMM tech-writer entry should generate content
|
||||
const bmmTechWriterEntry = {
|
||||
'agent-name': 'tech-writer',
|
||||
module: 'bmm',
|
||||
name: 'Write Document',
|
||||
};
|
||||
const bmmResult = installer.createTechWriterPromptContent(bmmTechWriterEntry);
|
||||
assert(
|
||||
bmmResult !== null && bmmResult.fileName === 'bmad-bmm-write-document',
|
||||
'createTechWriterPromptContent generates content for BMM tech-writer',
|
||||
`Got: ${bmmResult ? bmmResult.fileName : 'null'}`,
|
||||
);
|
||||
|
||||
// Test 2b: Non-BMM tech-writer entry should return null
|
||||
const customTechWriterEntry = {
|
||||
'agent-name': 'tech-writer',
|
||||
module: 'custom-module',
|
||||
name: 'Write Document',
|
||||
};
|
||||
const customResult = installer.createTechWriterPromptContent(customTechWriterEntry);
|
||||
assert(customResult === null, 'createTechWriterPromptContent returns null for non-BMM tech-writer', `Got: ${customResult}`);
|
||||
|
||||
// Test 2c: Core tech-writer entry should return null
|
||||
const coreTechWriterEntry = {
|
||||
'agent-name': 'tech-writer',
|
||||
module: 'core',
|
||||
name: 'Write Document',
|
||||
};
|
||||
const coreResult = installer.createTechWriterPromptContent(coreTechWriterEntry);
|
||||
assert(coreResult === null, 'createTechWriterPromptContent returns null for core tech-writer', `Got: ${coreResult}`);
|
||||
|
||||
// Test 2d: Non-tech-writer BMM entry should return null
|
||||
const nonTechWriterEntry = {
|
||||
'agent-name': 'pm',
|
||||
module: 'bmm',
|
||||
name: 'Write Document',
|
||||
};
|
||||
const nonTechResult = installer.createTechWriterPromptContent(nonTechWriterEntry);
|
||||
assert(nonTechResult === null, 'createTechWriterPromptContent returns null for non-tech-writer agents', `Got: ${nonTechResult}`);
|
||||
|
||||
// Test 2e: Unknown tech-writer command should return null
|
||||
const unknownCmdEntry = {
|
||||
'agent-name': 'tech-writer',
|
||||
module: 'bmm',
|
||||
name: 'Unknown Command',
|
||||
};
|
||||
const unknownResult = installer.createTechWriterPromptContent(unknownCmdEntry);
|
||||
assert(unknownResult === null, 'createTechWriterPromptContent returns null for unknown commands', `Got: ${unknownResult}`);
|
||||
|
||||
console.log('');
|
||||
|
||||
// ============================================================
|
||||
// Test Suite 3: selectedModules deduplication
|
||||
// ============================================================
|
||||
console.log(`${colors.yellow}Test Suite 3: selectedModules deduplication${colors.reset}\n`);
|
||||
|
||||
// We can't easily test generateCopilotInstructions directly without mocking,
|
||||
// but we can verify the deduplication logic pattern
|
||||
const testDedupe = (modules) => {
|
||||
const installedModules = modules.length > 0 ? [...new Set(modules)] : ['core'];
|
||||
return installedModules;
|
||||
};
|
||||
|
||||
// Test 3a: Duplicate modules should be deduplicated
|
||||
const dupeResult = testDedupe(['bmm', 'core', 'bmm', 'custom', 'core', 'custom']);
|
||||
assert(
|
||||
dupeResult.length === 3 && dupeResult.includes('bmm') && dupeResult.includes('core') && dupeResult.includes('custom'),
|
||||
'Deduplication removes duplicate modules',
|
||||
`Got: ${JSON.stringify(dupeResult)}`,
|
||||
);
|
||||
|
||||
// Test 3b: Empty array defaults to core
|
||||
const emptyResult = testDedupe([]);
|
||||
assert(
|
||||
emptyResult.length === 1 && emptyResult[0] === 'core',
|
||||
'Empty modules array defaults to core',
|
||||
`Got: ${JSON.stringify(emptyResult)}`,
|
||||
);
|
||||
|
||||
// Test 3c: Order is preserved after deduplication (first occurrence wins)
|
||||
const orderResult = testDedupe(['custom', 'bmm', 'custom', 'bmm']);
|
||||
assert(
|
||||
orderResult[0] === 'custom' && orderResult[1] === 'bmm',
|
||||
'Deduplication preserves order (first occurrence)',
|
||||
`Got: ${JSON.stringify(orderResult)}`,
|
||||
);
|
||||
} finally {
|
||||
// Cleanup
|
||||
await fs.remove(tempDir);
|
||||
}
|
||||
|
||||
// Print summary
|
||||
console.log(`${colors.cyan}========================================`);
|
||||
console.log('Test Results:');
|
||||
console.log(` Passed: ${passed}`);
|
||||
console.log(` Failed: ${failed}`);
|
||||
console.log(`========================================${colors.reset}\n`);
|
||||
|
||||
if (failed > 0) {
|
||||
console.log(`${colors.red}Some tests failed!${colors.reset}`);
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log(`${colors.green}✨ All GitHub Copilot installer tests passed!${colors.reset}`);
|
||||
}
|
||||
}
|
||||
|
||||
runTests().catch((error) => {
|
||||
console.error(`${colors.red}Test runner error:${colors.reset}`, error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
@ -12,7 +12,7 @@ startMessage: |
|
|||
- Select and install modules during setup - customize your experience
|
||||
- New BMad Method for Agile AI-Driven Development (the evolution of V4)
|
||||
- Exciting new modules available during installation, with community modules coming soon
|
||||
- Documentation: docs.bmad-method.com
|
||||
- Documentation: https://docs.bmad-method.org
|
||||
|
||||
🌟 BMad is 100% free and open source.
|
||||
- No gated Discord. No paywalls. No gated content.
|
||||
|
|
|
|||
|
|
@ -247,9 +247,9 @@ You must fully embody this agent's persona and follow all activation instruction
|
|||
*/
|
||||
createWorkflowPromptContent(entry, workflowFile, toolsStr) {
|
||||
const description = this.escapeYamlSingleQuote(this.createPromptDescription(entry.name));
|
||||
// bmm/config.yaml is safe to hardcode here: these prompts are only generated when
|
||||
// bmad-help.csv exists (bmm module data), so bmm is guaranteed to be installed.
|
||||
const configLine = `1. Load {project-root}/${this.bmadFolderName}/bmm/config.yaml and store ALL fields as session variables`;
|
||||
// Use the module from the bmad-help.csv entry to reference the correct config.yaml
|
||||
const configModule = entry.module || 'core';
|
||||
const configLine = `1. Load {project-root}/${this.bmadFolderName}/${configModule}/config.yaml and store ALL fields as session variables`;
|
||||
|
||||
let body;
|
||||
if (workflowFile.endsWith('.yaml')) {
|
||||
|
|
@ -324,11 +324,13 @@ ${body}
|
|||
|
||||
/**
|
||||
* Create prompt content for tech-writer agent-only commands (Pattern C)
|
||||
* Tech-writer is BMM-specific - these commands only work with the BMM module.
|
||||
* @param {Object} entry - bmad-help.csv row
|
||||
* @returns {Object|null} { fileName, content } or null if not a tech-writer command
|
||||
*/
|
||||
createTechWriterPromptContent(entry) {
|
||||
if (entry['agent-name'] !== 'tech-writer') return null;
|
||||
// Tech-writer is BMM-specific - only process entries from the bmm module
|
||||
if (entry['agent-name'] !== 'tech-writer' || entry.module !== 'bmm') return null;
|
||||
|
||||
const techWriterCommands = {
|
||||
'Write Document': { code: 'WD', file: 'bmad-bmm-write-document', description: 'Write document' },
|
||||
|
|
@ -344,14 +346,16 @@ ${body}
|
|||
const safeDescription = this.escapeYamlSingleQuote(cmd.description);
|
||||
const toolsStr = this.getToolsForFile(`${cmd.file}.prompt.md`);
|
||||
|
||||
// Use the module from the bmad-help.csv entry to reference the correct paths
|
||||
const configModule = entry.module || 'core';
|
||||
const content = `---
|
||||
description: '${safeDescription}'
|
||||
agent: 'agent'
|
||||
tools: ${toolsStr}
|
||||
---
|
||||
|
||||
1. Load {project-root}/${this.bmadFolderName}/bmm/config.yaml and store ALL fields as session variables
|
||||
2. Load the full agent file from {project-root}/${this.bmadFolderName}/bmm/agents/tech-writer/tech-writer.md and activate the Paige (Technical Writer) persona
|
||||
1. Load {project-root}/${this.bmadFolderName}/${configModule}/config.yaml and store ALL fields as session variables
|
||||
2. Load the full agent file from {project-root}/${this.bmadFolderName}/${configModule}/agents/tech-writer/tech-writer.md and activate the Paige (Technical Writer) persona
|
||||
3. Execute the ${entry.name} menu command (${cmd.code})
|
||||
`;
|
||||
|
||||
|
|
@ -376,15 +380,15 @@ tools: ${toolsStr}
|
|||
const agentPath = artifact.agentPath || artifact.relativePath;
|
||||
const agentFilePath = `{project-root}/${this.bmadFolderName}/${agentPath}`;
|
||||
|
||||
// bmm/config.yaml is safe to hardcode: agent activators are only generated from
|
||||
// bmm agent artifacts, so bmm is guaranteed to be installed.
|
||||
// Use the agent's module to reference the correct config.yaml
|
||||
const configModule = artifact.module || 'core';
|
||||
return `---
|
||||
description: '${safeDescription}'
|
||||
agent: 'agent'
|
||||
tools: ${toolsStr}
|
||||
---
|
||||
|
||||
1. Load {project-root}/${this.bmadFolderName}/bmm/config.yaml and store ALL fields as session variables
|
||||
1. Load {project-root}/${this.bmadFolderName}/${configModule}/config.yaml and store ALL fields as session variables
|
||||
2. Load the full agent file from ${agentFilePath}
|
||||
3. Follow ALL activation instructions in the agent file
|
||||
4. Display the welcome/greeting as instructed
|
||||
|
|
@ -400,7 +404,13 @@ tools: ${toolsStr}
|
|||
* @param {Map} agentManifest - Agent manifest data
|
||||
*/
|
||||
async generateCopilotInstructions(projectDir, bmadDir, agentManifest, options = {}) {
|
||||
const configVars = await this.loadModuleConfig(bmadDir);
|
||||
// Determine installed modules (excluding internal directories)
|
||||
const selectedModules = options.selectedModules || [];
|
||||
// Deduplicate selectedModules to prevent duplicate paths in generated markdown
|
||||
const installedModules = selectedModules.length > 0 ? [...new Set(selectedModules)] : ['core'];
|
||||
const configVars = await this.loadModuleConfig(bmadDir, installedModules);
|
||||
// Filter to only non-core modules for display (core is always listed separately)
|
||||
const nonCoreModules = installedModules.filter((m) => m !== 'core');
|
||||
|
||||
// Build the agents table from the manifest
|
||||
let agentsTable = '| Agent | Persona | Title | Capabilities |\n|---|---|---|---|\n';
|
||||
|
|
@ -427,6 +437,36 @@ tools: ${toolsStr}
|
|||
}
|
||||
|
||||
const bmad = this.bmadFolderName;
|
||||
|
||||
// Build dynamic module paths based on installed modules
|
||||
const moduleAgentPaths = nonCoreModules.map((m) => `\`${bmad}/${m}/agents/\``).join(', ');
|
||||
const moduleWorkflowPaths = nonCoreModules.map((m) => `\`${bmad}/${m}/workflows/\``).join(', ');
|
||||
const moduleConfigPaths = nonCoreModules.map((m) => `\`${bmad}/${m}/config.yaml\``).join(', ');
|
||||
|
||||
// Build agent definitions line
|
||||
let agentDefsLine;
|
||||
if (nonCoreModules.length > 0) {
|
||||
agentDefsLine = `- **Agent definitions**: ${moduleAgentPaths} and \`${bmad}/core/agents/\` (core)`;
|
||||
} else {
|
||||
agentDefsLine = `- **Agent definitions**: \`${bmad}/core/agents/\``;
|
||||
}
|
||||
|
||||
// Build workflow definitions line
|
||||
let workflowDefsLine;
|
||||
if (nonCoreModules.length > 0) {
|
||||
workflowDefsLine = `- **Workflow definitions**: ${moduleWorkflowPaths} (organized by phase)`;
|
||||
} else {
|
||||
workflowDefsLine = `- **Workflow definitions**: \`${bmad}/core/workflows/\``;
|
||||
}
|
||||
|
||||
// Build module configuration line
|
||||
let moduleConfigLine;
|
||||
if (nonCoreModules.length > 0) {
|
||||
moduleConfigLine = `- **Module configuration**: ${moduleConfigPaths}`;
|
||||
} else {
|
||||
moduleConfigLine = `- **Module configuration**: (no non-core modules installed)`;
|
||||
}
|
||||
|
||||
const bmadSection = `# BMAD Method — Project Instructions
|
||||
|
||||
## Project Configuration
|
||||
|
|
@ -443,12 +483,12 @@ tools: ${toolsStr}
|
|||
|
||||
## BMAD Runtime Structure
|
||||
|
||||
- **Agent definitions**: \`${bmad}/bmm/agents/\` (BMM module) and \`${bmad}/core/agents/\` (core)
|
||||
- **Workflow definitions**: \`${bmad}/bmm/workflows/\` (organized by phase)
|
||||
${agentDefsLine}
|
||||
${workflowDefsLine}
|
||||
- **Core tasks**: \`${bmad}/core/tasks/\` (help, editorial review, indexing, sharding, adversarial review)
|
||||
- **Core workflows**: \`${bmad}/core/workflows/\` (brainstorming, party-mode, advanced-elicitation)
|
||||
- **Workflow engine**: \`${bmad}/core/tasks/workflow.xml\` (executes YAML-based workflows)
|
||||
- **Module configuration**: \`${bmad}/bmm/config.yaml\`
|
||||
${moduleConfigLine}
|
||||
- **Core configuration**: \`${bmad}/core/config.yaml\`
|
||||
- **Agent manifest**: \`${bmad}/_config/agent-manifest.csv\`
|
||||
- **Workflow manifest**: \`${bmad}/_config/workflow-manifest.csv\`
|
||||
|
|
@ -457,7 +497,7 @@ tools: ${toolsStr}
|
|||
|
||||
## Key Conventions
|
||||
|
||||
- Always load \`${bmad}/bmm/config.yaml\` before any agent activation or workflow execution
|
||||
- Always load the agent/workflow's module \`config.yaml\` before activation or execution (each prompt file specifies which config to load)
|
||||
- Store all config fields as session variables: \`{user_name}\`, \`{communication_language}\`, \`{output_folder}\`, \`{planning_artifacts}\`, \`{implementation_artifacts}\`, \`{project_knowledge}\`
|
||||
- MD-based workflows execute directly — load and follow the \`.md\` file
|
||||
- YAML-based workflows require the workflow engine — load \`workflow.xml\` first, then pass the \`.yaml\` config
|
||||
|
|
@ -504,13 +544,15 @@ Type \`/bmad-\` in Copilot Chat to see all available BMAD workflows and agent ac
|
|||
/**
|
||||
* Load module config.yaml for template variables
|
||||
* @param {string} bmadDir - BMAD installation directory
|
||||
* @param {string[]} installedModules - List of installed modules to check for config
|
||||
* @returns {Object} Config variables
|
||||
*/
|
||||
async loadModuleConfig(bmadDir) {
|
||||
const bmmConfigPath = path.join(bmadDir, 'bmm', 'config.yaml');
|
||||
const coreConfigPath = path.join(bmadDir, 'core', 'config.yaml');
|
||||
async loadModuleConfig(bmadDir, installedModules = ['core']) {
|
||||
// Build config paths from installed modules (non-core first, then core as fallback)
|
||||
const nonCoreModules = installedModules.filter((m) => m !== 'core');
|
||||
const configPaths = [...nonCoreModules.map((m) => path.join(bmadDir, m, 'config.yaml')), path.join(bmadDir, 'core', 'config.yaml')];
|
||||
|
||||
for (const configPath of [bmmConfigPath, coreConfigPath]) {
|
||||
for (const configPath of configPaths) {
|
||||
if (await fs.pathExists(configPath)) {
|
||||
try {
|
||||
const content = await fs.readFile(configPath, 'utf8');
|
||||
|
|
|
|||
Loading…
Reference in New Issue