Merge branch 'main' into personal_build-bmm-lite-version-module
This commit is contained in:
commit
95efaec1d7
|
|
@ -4,7 +4,7 @@ description: 'Discovery & Understanding - Understand what user wants to edit and
|
||||||
|
|
||||||
# File references (ONLY variables used in this step)
|
# File references (ONLY variables used in this step)
|
||||||
altStepFile: './step-e-01b-legacy-conversion.md'
|
altStepFile: './step-e-01b-legacy-conversion.md'
|
||||||
prdPurpose: '{project-root}/src/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
|
prdPurpose: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
|
||||||
advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
|
advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
|
||||||
partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md'
|
partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md'
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ description: 'Legacy PRD Conversion Assessment - Analyze legacy PRD and propose
|
||||||
# File references (ONLY variables used in this step)
|
# File references (ONLY variables used in this step)
|
||||||
nextStepFile: './step-e-02-review.md'
|
nextStepFile: './step-e-02-review.md'
|
||||||
prdFile: '{prd_file_path}'
|
prdFile: '{prd_file_path}'
|
||||||
prdPurpose: '{project-root}/src/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
|
prdPurpose: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
|
||||||
---
|
---
|
||||||
|
|
||||||
# Step E-1B: Legacy PRD Conversion Assessment
|
# Step E-1B: Legacy PRD Conversion Assessment
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ description: 'Deep Review & Analysis - Thoroughly review existing PRD and prepar
|
||||||
nextStepFile: './step-e-03-edit.md'
|
nextStepFile: './step-e-03-edit.md'
|
||||||
prdFile: '{prd_file_path}'
|
prdFile: '{prd_file_path}'
|
||||||
validationReport: '{validation_report_path}' # If provided
|
validationReport: '{validation_report_path}' # If provided
|
||||||
prdPurpose: '{project-root}/src/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
|
prdPurpose: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
|
||||||
advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
|
advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ description: 'Edit & Update - Apply changes to PRD following approved change pla
|
||||||
# File references (ONLY variables used in this step)
|
# File references (ONLY variables used in this step)
|
||||||
nextStepFile: './step-e-04-complete.md'
|
nextStepFile: './step-e-04-complete.md'
|
||||||
prdFile: '{prd_file_path}'
|
prdFile: '{prd_file_path}'
|
||||||
prdPurpose: '{project-root}/src/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
|
prdPurpose: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
|
||||||
---
|
---
|
||||||
|
|
||||||
# Step E-3: Edit & Update
|
# Step E-3: Edit & Update
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,16 @@ modules:
|
||||||
type: bmad-org
|
type: bmad-org
|
||||||
npmPackage: bmad-game-dev-studio
|
npmPackage: bmad-game-dev-studio
|
||||||
|
|
||||||
|
bmad-method-test-architecture-enterprise:
|
||||||
|
url: https://github.com/bmad-code-org/bmad-method-test-architecture-enterprise
|
||||||
|
module-definition: src/module.yaml
|
||||||
|
code: tea
|
||||||
|
name: "Test Architect"
|
||||||
|
description: "Master Test Architect for quality strategy, test automation, and release gates"
|
||||||
|
defaultSelected: false
|
||||||
|
type: bmad-org
|
||||||
|
npmPackage: bmad-method-test-architecture-enterprise
|
||||||
|
|
||||||
# TODO: Enable once fixes applied:
|
# TODO: Enable once fixes applied:
|
||||||
|
|
||||||
# whiteport-design-system:
|
# whiteport-design-system:
|
||||||
|
|
|
||||||
|
|
@ -132,12 +132,12 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
|
||||||
*/
|
*/
|
||||||
async writeAgentArtifacts(targetPath, artifacts, templateType, config = {}) {
|
async writeAgentArtifacts(targetPath, artifacts, templateType, config = {}) {
|
||||||
// Try to load platform-specific template, fall back to default-agent
|
// Try to load platform-specific template, fall back to default-agent
|
||||||
const template = await this.loadTemplate(templateType, 'agent', config, 'default-agent');
|
const { content: template, extension } = await this.loadTemplate(templateType, 'agent', config, 'default-agent');
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
for (const artifact of artifacts) {
|
for (const artifact of artifacts) {
|
||||||
const content = this.renderTemplate(template, artifact);
|
const content = this.renderTemplate(template, artifact);
|
||||||
const filename = this.generateFilename(artifact, 'agent');
|
const filename = this.generateFilename(artifact, 'agent', extension);
|
||||||
const filePath = path.join(targetPath, filename);
|
const filePath = path.join(targetPath, filename);
|
||||||
await this.writeFile(filePath, content);
|
await this.writeFile(filePath, content);
|
||||||
count++;
|
count++;
|
||||||
|
|
@ -167,9 +167,10 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
|
||||||
|
|
||||||
// Fall back to default templates if specific ones don't exist
|
// Fall back to default templates if specific ones don't exist
|
||||||
const finalTemplateType = artifact.isYamlWorkflow ? 'default-workflow-yaml' : 'default-workflow';
|
const finalTemplateType = artifact.isYamlWorkflow ? 'default-workflow-yaml' : 'default-workflow';
|
||||||
const template = await this.loadTemplate(workflowTemplateType, 'workflow', config, finalTemplateType);
|
// workflowTemplateType already contains full name (e.g., 'gemini-workflow-yaml'), so pass empty artifactType
|
||||||
|
const { content: template, extension } = await this.loadTemplate(workflowTemplateType, '', config, finalTemplateType);
|
||||||
const content = this.renderTemplate(template, artifact);
|
const content = this.renderTemplate(template, artifact);
|
||||||
const filename = this.generateFilename(artifact, 'workflow');
|
const filename = this.generateFilename(artifact, 'workflow', extension);
|
||||||
const filePath = path.join(targetPath, filename);
|
const filePath = path.join(targetPath, filename);
|
||||||
await this.writeFile(filePath, content);
|
await this.writeFile(filePath, content);
|
||||||
count++;
|
count++;
|
||||||
|
|
@ -185,34 +186,47 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
|
||||||
* @param {string} artifactType - Artifact type (agent, workflow, task, tool)
|
* @param {string} artifactType - Artifact type (agent, workflow, task, tool)
|
||||||
* @param {Object} config - Installation configuration
|
* @param {Object} config - Installation configuration
|
||||||
* @param {string} fallbackTemplateType - Fallback template type if requested template not found
|
* @param {string} fallbackTemplateType - Fallback template type if requested template not found
|
||||||
* @returns {Promise<string>} Template content
|
* @returns {Promise<{content: string, extension: string}>} Template content and extension
|
||||||
*/
|
*/
|
||||||
async loadTemplate(templateType, artifactType, config = {}, fallbackTemplateType = null) {
|
async loadTemplate(templateType, artifactType, config = {}, fallbackTemplateType = null) {
|
||||||
const { header_template, body_template } = config;
|
const { header_template, body_template } = config;
|
||||||
|
|
||||||
// Check for separate header/body templates
|
// Check for separate header/body templates
|
||||||
if (header_template || body_template) {
|
if (header_template || body_template) {
|
||||||
return await this.loadSplitTemplates(templateType, artifactType, header_template, body_template);
|
const content = await this.loadSplitTemplates(templateType, artifactType, header_template, body_template);
|
||||||
|
// Allow config to override extension, default to .md
|
||||||
|
const ext = config.extension || '.md';
|
||||||
|
const normalizedExt = ext.startsWith('.') ? ext : `.${ext}`;
|
||||||
|
return { content, extension: normalizedExt };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load combined template
|
// Load combined template - try multiple extensions
|
||||||
const templateName = `${templateType}-${artifactType}.md`;
|
// If artifactType is empty, templateType already contains full name (e.g., 'gemini-workflow-yaml')
|
||||||
const templatePath = path.join(__dirname, 'templates', 'combined', templateName);
|
const templateBaseName = artifactType ? `${templateType}-${artifactType}` : templateType;
|
||||||
|
const templateDir = path.join(__dirname, 'templates', 'combined');
|
||||||
|
const extensions = ['.md', '.toml', '.yaml', '.yml'];
|
||||||
|
|
||||||
if (await fs.pathExists(templatePath)) {
|
for (const ext of extensions) {
|
||||||
return await fs.readFile(templatePath, 'utf8');
|
const templatePath = path.join(templateDir, templateBaseName + ext);
|
||||||
|
if (await fs.pathExists(templatePath)) {
|
||||||
|
const content = await fs.readFile(templatePath, 'utf8');
|
||||||
|
return { content, extension: ext };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fall back to default template (if provided)
|
// Fall back to default template (if provided)
|
||||||
if (fallbackTemplateType) {
|
if (fallbackTemplateType) {
|
||||||
const fallbackPath = path.join(__dirname, 'templates', 'combined', `${fallbackTemplateType}.md`);
|
for (const ext of extensions) {
|
||||||
if (await fs.pathExists(fallbackPath)) {
|
const fallbackPath = path.join(templateDir, `${fallbackTemplateType}${ext}`);
|
||||||
return await fs.readFile(fallbackPath, 'utf8');
|
if (await fs.pathExists(fallbackPath)) {
|
||||||
|
const content = await fs.readFile(fallbackPath, 'utf8');
|
||||||
|
return { content, extension: ext };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ultimate fallback - minimal template
|
// Ultimate fallback - minimal template
|
||||||
return this.getDefaultTemplate(artifactType);
|
return { content: this.getDefaultTemplate(artifactType), extension: '.md' };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -326,13 +340,26 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
|
||||||
* Generate filename for artifact
|
* Generate filename for artifact
|
||||||
* @param {Object} artifact - Artifact data
|
* @param {Object} artifact - Artifact data
|
||||||
* @param {string} artifactType - Artifact type (agent, workflow, task, tool)
|
* @param {string} artifactType - Artifact type (agent, workflow, task, tool)
|
||||||
|
* @param {string} extension - File extension to use (e.g., '.md', '.toml')
|
||||||
* @returns {string} Generated filename
|
* @returns {string} Generated filename
|
||||||
*/
|
*/
|
||||||
generateFilename(artifact, artifactType) {
|
generateFilename(artifact, artifactType, extension = '.md') {
|
||||||
const { toDashPath } = require('./shared/path-utils');
|
const { toDashPath } = require('./shared/path-utils');
|
||||||
// toDashPath already handles the .agent.md suffix for agents correctly
|
|
||||||
// No need to add it again here
|
// Reuse central logic to ensure consistent naming conventions
|
||||||
return toDashPath(artifact.relativePath);
|
const standardName = toDashPath(artifact.relativePath);
|
||||||
|
|
||||||
|
// Clean up potential double extensions from source files (e.g. .yaml.md -> .md)
|
||||||
|
const baseName = standardName.replace(/\.(yaml|yml)\.md$/, '.md');
|
||||||
|
|
||||||
|
// If using default markdown, preserve the bmad-agent- prefix for agents
|
||||||
|
if (extension === '.md') {
|
||||||
|
return baseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For other extensions (e.g., .toml), replace .md extension
|
||||||
|
// Note: agent prefix is preserved even with non-markdown extensions
|
||||||
|
return baseName.replace(/\.md$/, extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -14,18 +14,14 @@
|
||||||
# installer: Installation configuration (optional - omit for custom installers)
|
# installer: Installation configuration (optional - omit for custom installers)
|
||||||
|
|
||||||
platforms:
|
platforms:
|
||||||
# ============================================================================
|
antigravity:
|
||||||
# CLI Tools
|
name: "Google Antigravity"
|
||||||
# ============================================================================
|
preferred: false
|
||||||
|
category: ide
|
||||||
claude-code:
|
description: "Google's AI development environment"
|
||||||
name: "Claude Code"
|
|
||||||
preferred: true
|
|
||||||
category: cli
|
|
||||||
description: "Anthropic's official CLI for Claude"
|
|
||||||
installer:
|
installer:
|
||||||
target_dir: .claude/commands
|
target_dir: .agent/workflows
|
||||||
template_type: default
|
template_type: antigravity
|
||||||
|
|
||||||
auggie:
|
auggie:
|
||||||
name: "Auggie"
|
name: "Auggie"
|
||||||
|
|
@ -36,37 +32,15 @@ platforms:
|
||||||
target_dir: .augment/commands
|
target_dir: .augment/commands
|
||||||
template_type: default
|
template_type: default
|
||||||
|
|
||||||
gemini:
|
claude-code:
|
||||||
name: "Gemini CLI"
|
name: "Claude Code"
|
||||||
preferred: false
|
preferred: true
|
||||||
category: cli
|
category: cli
|
||||||
description: "Google's CLI for Gemini"
|
description: "Anthropic's official CLI for Claude"
|
||||||
installer:
|
installer:
|
||||||
target_dir: .gemini/commands
|
target_dir: .claude/commands
|
||||||
template_type: gemini
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# IDEs
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
cursor:
|
|
||||||
name: "Cursor"
|
|
||||||
preferred: true
|
|
||||||
category: ide
|
|
||||||
description: "AI-first code editor"
|
|
||||||
installer:
|
|
||||||
target_dir: .cursor/commands
|
|
||||||
template_type: default
|
template_type: default
|
||||||
|
|
||||||
windsurf:
|
|
||||||
name: "Windsurf"
|
|
||||||
preferred: true
|
|
||||||
category: ide
|
|
||||||
description: "AI-powered IDE with cascade flows"
|
|
||||||
installer:
|
|
||||||
target_dir: .windsurf/workflows
|
|
||||||
template_type: windsurf
|
|
||||||
|
|
||||||
cline:
|
cline:
|
||||||
name: "Cline"
|
name: "Cline"
|
||||||
preferred: false
|
preferred: false
|
||||||
|
|
@ -76,15 +50,40 @@ platforms:
|
||||||
target_dir: .clinerules/workflows
|
target_dir: .clinerules/workflows
|
||||||
template_type: windsurf
|
template_type: windsurf
|
||||||
|
|
||||||
roo:
|
codex:
|
||||||
name: "Roo Cline"
|
name: "Codex"
|
||||||
|
preferred: false
|
||||||
|
category: cli
|
||||||
|
description: "OpenAI Codex integration"
|
||||||
|
# No installer config - uses custom codex.js
|
||||||
|
|
||||||
|
crush:
|
||||||
|
name: "Crush"
|
||||||
preferred: false
|
preferred: false
|
||||||
category: ide
|
category: ide
|
||||||
description: "Enhanced Cline fork"
|
description: "AI development assistant"
|
||||||
installer:
|
installer:
|
||||||
target_dir: .roo/commands
|
target_dir: .crush/commands
|
||||||
template_type: default
|
template_type: default
|
||||||
|
|
||||||
|
cursor:
|
||||||
|
name: "Cursor"
|
||||||
|
preferred: true
|
||||||
|
category: ide
|
||||||
|
description: "AI-first code editor"
|
||||||
|
installer:
|
||||||
|
target_dir: .cursor/commands
|
||||||
|
template_type: default
|
||||||
|
|
||||||
|
gemini:
|
||||||
|
name: "Gemini CLI"
|
||||||
|
preferred: false
|
||||||
|
category: cli
|
||||||
|
description: "Google's CLI for Gemini"
|
||||||
|
installer:
|
||||||
|
target_dir: .gemini/commands
|
||||||
|
template_type: gemini
|
||||||
|
|
||||||
github-copilot:
|
github-copilot:
|
||||||
name: "GitHub Copilot"
|
name: "GitHub Copilot"
|
||||||
preferred: false
|
preferred: false
|
||||||
|
|
@ -99,24 +98,6 @@ platforms:
|
||||||
template_type: vscode_settings
|
template_type: vscode_settings
|
||||||
artifact_types: []
|
artifact_types: []
|
||||||
|
|
||||||
opencode:
|
|
||||||
name: "OpenCode"
|
|
||||||
preferred: false
|
|
||||||
category: ide
|
|
||||||
description: "OpenCode terminal coding assistant"
|
|
||||||
installer:
|
|
||||||
target_dir: .opencode/command
|
|
||||||
template_type: opencode
|
|
||||||
|
|
||||||
crush:
|
|
||||||
name: "Crush"
|
|
||||||
preferred: false
|
|
||||||
category: ide
|
|
||||||
description: "AI development assistant"
|
|
||||||
installer:
|
|
||||||
target_dir: .crush/commands
|
|
||||||
template_type: default
|
|
||||||
|
|
||||||
iflow:
|
iflow:
|
||||||
name: "iFlow"
|
name: "iFlow"
|
||||||
preferred: false
|
preferred: false
|
||||||
|
|
@ -126,6 +107,29 @@ platforms:
|
||||||
target_dir: .iflow/commands
|
target_dir: .iflow/commands
|
||||||
template_type: default
|
template_type: default
|
||||||
|
|
||||||
|
kilo:
|
||||||
|
name: "KiloCoder"
|
||||||
|
preferred: false
|
||||||
|
category: ide
|
||||||
|
description: "AI coding platform"
|
||||||
|
# No installer config - uses custom kilo.js (creates .kilocodemodes file)
|
||||||
|
|
||||||
|
kiro-cli:
|
||||||
|
name: "Kiro CLI"
|
||||||
|
preferred: false
|
||||||
|
category: cli
|
||||||
|
description: "Kiro command-line interface"
|
||||||
|
# No installer config - uses custom kiro-cli.js (YAML→JSON conversion)
|
||||||
|
|
||||||
|
opencode:
|
||||||
|
name: "OpenCode"
|
||||||
|
preferred: false
|
||||||
|
category: ide
|
||||||
|
description: "OpenCode terminal coding assistant"
|
||||||
|
installer:
|
||||||
|
target_dir: .opencode/command
|
||||||
|
template_type: opencode
|
||||||
|
|
||||||
qwen:
|
qwen:
|
||||||
name: "QwenCoder"
|
name: "QwenCoder"
|
||||||
preferred: false
|
preferred: false
|
||||||
|
|
@ -135,6 +139,15 @@ platforms:
|
||||||
target_dir: .qwen/commands
|
target_dir: .qwen/commands
|
||||||
template_type: default
|
template_type: default
|
||||||
|
|
||||||
|
roo:
|
||||||
|
name: "Roo Cline"
|
||||||
|
preferred: false
|
||||||
|
category: ide
|
||||||
|
description: "Enhanced Cline fork"
|
||||||
|
installer:
|
||||||
|
target_dir: .roo/commands
|
||||||
|
template_type: default
|
||||||
|
|
||||||
rovo-dev:
|
rovo-dev:
|
||||||
name: "Rovo Dev"
|
name: "Rovo Dev"
|
||||||
preferred: false
|
preferred: false
|
||||||
|
|
@ -153,41 +166,14 @@ platforms:
|
||||||
target_dir: .trae/rules
|
target_dir: .trae/rules
|
||||||
template_type: trae
|
template_type: trae
|
||||||
|
|
||||||
antigravity:
|
windsurf:
|
||||||
name: "Google Antigravity"
|
name: "Windsurf"
|
||||||
preferred: false
|
preferred: true
|
||||||
category: ide
|
category: ide
|
||||||
description: "Google's AI development environment"
|
description: "AI-powered IDE with cascade flows"
|
||||||
installer:
|
installer:
|
||||||
target_dir: .agent/workflows
|
target_dir: .windsurf/workflows
|
||||||
template_type: antigravity
|
template_type: windsurf
|
||||||
# Note: Antigravity uses .agent/workflows/ directory (not .antigravity/)
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# Custom Installers (no installer config - use custom file)
|
|
||||||
# These have unique installation logic that doesn't fit the config-driven model
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
codex:
|
|
||||||
name: "Codex"
|
|
||||||
preferred: false
|
|
||||||
category: cli
|
|
||||||
description: "OpenAI Codex integration"
|
|
||||||
# No installer config - uses custom codex.js
|
|
||||||
|
|
||||||
kilo:
|
|
||||||
name: "KiloCoder"
|
|
||||||
preferred: false
|
|
||||||
category: ide
|
|
||||||
description: "AI coding platform"
|
|
||||||
# No installer config - uses custom kilo.js (creates .kilocodemodes file)
|
|
||||||
|
|
||||||
kiro-cli:
|
|
||||||
name: "Kiro CLI"
|
|
||||||
preferred: false
|
|
||||||
category: cli
|
|
||||||
description: "Kiro command-line interface"
|
|
||||||
# No installer config - uses custom kiro-cli.js (YAML→JSON conversion)
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Installer Config Schema
|
# Installer Config Schema
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,9 @@ class AgentCommandGenerator {
|
||||||
// Use relativePath if available (for nested agents), otherwise just name with .md
|
// Use relativePath if available (for nested agents), otherwise just name with .md
|
||||||
const agentPathInModule = agent.relativePath || `${agent.name}.md`;
|
const agentPathInModule = agent.relativePath || `${agent.name}.md`;
|
||||||
// Calculate the relative agent path (e.g., bmm/agents/pm.md)
|
// Calculate the relative agent path (e.g., bmm/agents/pm.md)
|
||||||
let agentRelPath = agent.path;
|
let agentRelPath = agent.path || '';
|
||||||
|
// Normalize path separators for cross-platform compatibility
|
||||||
|
agentRelPath = agentRelPath.replaceAll('\\', '/');
|
||||||
// Remove _bmad/ prefix if present to get relative path from project root
|
// Remove _bmad/ prefix if present to get relative path from project root
|
||||||
// Handle both absolute paths (/path/to/_bmad/...) and relative paths (_bmad/...)
|
// Handle both absolute paths (/path/to/_bmad/...) and relative paths (_bmad/...)
|
||||||
if (agentRelPath.includes('_bmad/')) {
|
if (agentRelPath.includes('_bmad/')) {
|
||||||
|
|
@ -132,9 +134,9 @@ class AgentCommandGenerator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write agent launcher artifacts using dash format (NEW STANDARD)
|
* Write agent launcher artifacts using dash format (NEW STANDARD)
|
||||||
* Creates flat files like: bmad-bmm-pm.agent.md
|
* Creates flat files like: bmad-agent-bmm-pm.md
|
||||||
*
|
*
|
||||||
* The .agent.md suffix distinguishes agents from workflows/tasks/tools.
|
* The bmad-agent- prefix distinguishes agents from workflows/tasks/tools.
|
||||||
*
|
*
|
||||||
* @param {string} baseCommandsDir - Base commands directory for the IDE
|
* @param {string} baseCommandsDir - Base commands directory for the IDE
|
||||||
* @param {Array} artifacts - Agent launcher artifacts
|
* @param {Array} artifacts - Agent launcher artifacts
|
||||||
|
|
@ -145,7 +147,7 @@ class AgentCommandGenerator {
|
||||||
|
|
||||||
for (const artifact of artifacts) {
|
for (const artifact of artifacts) {
|
||||||
if (artifact.type === 'agent-launcher') {
|
if (artifact.type === 'agent-launcher') {
|
||||||
// Convert relativePath to dash format: bmm/agents/pm.md → bmad-bmm-pm.agent.md
|
// Convert relativePath to dash format: bmm/agents/pm.md → bmad-agent-bmm-pm.md
|
||||||
const flatName = toDashPath(artifact.relativePath);
|
const flatName = toDashPath(artifact.relativePath);
|
||||||
const launcherPath = path.join(baseCommandsDir, flatName);
|
const launcherPath = path.join(baseCommandsDir, flatName);
|
||||||
await fs.ensureDir(path.dirname(launcherPath));
|
await fs.ensureDir(path.dirname(launcherPath));
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@
|
||||||
* Provides utilities to convert hierarchical paths to flat naming conventions.
|
* Provides utilities to convert hierarchical paths to flat naming conventions.
|
||||||
*
|
*
|
||||||
* DASH-BASED NAMING (new standard):
|
* DASH-BASED NAMING (new standard):
|
||||||
* - Agents: bmad-module-name.agent.md (with .agent.md suffix)
|
* - Agents: bmad-agent-module-name.md (with bmad-agent- prefix)
|
||||||
* - Workflows/Tasks/Tools: bmad-module-name.md
|
* - Workflows/Tasks/Tools: bmad-module-name.md
|
||||||
*
|
*
|
||||||
* Example outputs:
|
* Example outputs:
|
||||||
* - cis/agents/storymaster.md → bmad-cis-storymaster.agent.md
|
* - cis/agents/storymaster.md → bmad-agent-cis-storymaster.md
|
||||||
* - bmm/workflows/plan-project.md → bmad-bmm-plan-project.md
|
* - bmm/workflows/plan-project.md → bmad-bmm-plan-project.md
|
||||||
* - bmm/tasks/create-story.md → bmad-bmm-create-story.md
|
* - bmm/tasks/create-story.md → bmad-bmm-create-story.md
|
||||||
* - core/agents/brainstorming.md → bmad-brainstorming.agent.md
|
* - core/agents/brainstorming.md → bmad-agent-brainstorming.md (core agents skip module name)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Type segments - agents are included in naming, others are filtered out
|
// Type segments - agents are included in naming, others are filtered out
|
||||||
|
|
@ -20,37 +20,38 @@ const AGENT_SEGMENT = 'agents';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert hierarchical path to flat dash-separated name (NEW STANDARD)
|
* Convert hierarchical path to flat dash-separated name (NEW STANDARD)
|
||||||
* Converts: 'bmm', 'agents', 'pm' → 'bmad-bmm-pm.agent.md'
|
* Converts: 'bmm', 'agents', 'pm' → 'bmad-agent-bmm-pm.md'
|
||||||
* Converts: 'bmm', 'workflows', 'correct-course' → 'bmad-bmm-correct-course.md'
|
* Converts: 'bmm', 'workflows', 'correct-course' → 'bmad-bmm-correct-course.md'
|
||||||
* Converts: 'core', 'agents', 'brainstorming' → 'bmad-brainstorming.agent.md' (core items skip module prefix)
|
* Converts: 'core', 'agents', 'brainstorming' → 'bmad-agent-brainstorming.md' (core agents skip module name)
|
||||||
*
|
*
|
||||||
* @param {string} module - Module name (e.g., 'bmm', 'core')
|
* @param {string} module - Module name (e.g., 'bmm', 'core')
|
||||||
* @param {string} type - Artifact type ('agents', 'workflows', 'tasks', 'tools')
|
* @param {string} type - Artifact type ('agents', 'workflows', 'tasks', 'tools')
|
||||||
* @param {string} name - Artifact name (e.g., 'pm', 'brainstorming')
|
* @param {string} name - Artifact name (e.g., 'pm', 'brainstorming')
|
||||||
* @returns {string} Flat filename like 'bmad-bmm-pm.agent.md' or 'bmad-bmm-correct-course.md'
|
* @returns {string} Flat filename like 'bmad-agent-bmm-pm.md' or 'bmad-bmm-correct-course.md'
|
||||||
*/
|
*/
|
||||||
function toDashName(module, type, name) {
|
function toDashName(module, type, name) {
|
||||||
const isAgent = type === AGENT_SEGMENT;
|
const isAgent = type === AGENT_SEGMENT;
|
||||||
|
|
||||||
// For core module, skip the module prefix: use 'bmad-name.md' instead of 'bmad-core-name.md'
|
// For core module, skip the module name: use 'bmad-agent-name.md' instead of 'bmad-agent-core-name.md'
|
||||||
if (module === 'core') {
|
if (module === 'core') {
|
||||||
return isAgent ? `bmad-${name}.agent.md` : `bmad-${name}.md`;
|
return isAgent ? `bmad-agent-${name}.md` : `bmad-${name}.md`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module artifacts: bmad-module-name.md or bmad-module-name.agent.md
|
// Module artifacts: bmad-module-name.md or bmad-agent-module-name.md
|
||||||
// eslint-disable-next-line unicorn/prefer-string-replace-all -- regex replace is intentional here
|
// eslint-disable-next-line unicorn/prefer-string-replace-all -- regex replace is intentional here
|
||||||
const dashName = name.replace(/\//g, '-'); // Flatten nested paths
|
const dashName = name.replace(/\//g, '-'); // Flatten nested paths
|
||||||
return isAgent ? `bmad-${module}-${dashName}.agent.md` : `bmad-${module}-${dashName}.md`;
|
return isAgent ? `bmad-agent-${module}-${dashName}.md` : `bmad-${module}-${dashName}.md`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert relative path to flat dash-separated name
|
* Convert relative path to flat dash-separated name
|
||||||
* Converts: 'bmm/agents/pm.md' → 'bmad-bmm-pm.agent.md'
|
* Converts: 'bmm/agents/pm.md' → 'bmad-agent-bmm-pm.md'
|
||||||
|
* Converts: 'bmm/agents/tech-writer/tech-writer.md' → 'bmad-agent-bmm-tech-writer.md' (uses folder name)
|
||||||
* Converts: 'bmm/workflows/correct-course.md' → 'bmad-bmm-correct-course.md'
|
* Converts: 'bmm/workflows/correct-course.md' → 'bmad-bmm-correct-course.md'
|
||||||
* Converts: 'core/agents/brainstorming.md' → 'bmad-brainstorming.agent.md' (core items skip module prefix)
|
* Converts: 'core/agents/brainstorming.md' → 'bmad-agent-brainstorming.md' (core agents skip module name)
|
||||||
*
|
*
|
||||||
* @param {string} relativePath - Path like 'bmm/agents/pm.md'
|
* @param {string} relativePath - Path like 'bmm/agents/pm.md'
|
||||||
* @returns {string} Flat filename like 'bmad-bmm-pm.agent.md' or 'bmad-brainstorming.md'
|
* @returns {string} Flat filename like 'bmad-agent-bmm-pm.md' or 'bmad-brainstorming.md'
|
||||||
*/
|
*/
|
||||||
function toDashPath(relativePath) {
|
function toDashPath(relativePath) {
|
||||||
if (!relativePath || typeof relativePath !== 'string') {
|
if (!relativePath || typeof relativePath !== 'string') {
|
||||||
|
|
@ -63,20 +64,30 @@ function toDashPath(relativePath) {
|
||||||
|
|
||||||
const module = parts[0];
|
const module = parts[0];
|
||||||
const type = parts[1];
|
const type = parts[1];
|
||||||
const name = parts.slice(2).join('-');
|
let name;
|
||||||
|
|
||||||
|
// For agents, if nested in a folder (more than 3 parts), use the folder name only
|
||||||
|
// e.g., 'bmm/agents/tech-writer/tech-writer' → 'tech-writer' (not 'tech-writer-tech-writer')
|
||||||
|
if (type === 'agents' && parts.length > 3) {
|
||||||
|
// Use the folder name (parts[2]) as the name, ignore the file name
|
||||||
|
name = parts[2];
|
||||||
|
} else {
|
||||||
|
// For non-nested or non-agents, join all parts after type
|
||||||
|
name = parts.slice(2).join('-');
|
||||||
|
}
|
||||||
|
|
||||||
return toDashName(module, type, name);
|
return toDashName(module, type, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create custom agent dash name
|
* Create custom agent dash name
|
||||||
* Creates: 'bmad-custom-fred-commit-poet.agent.md'
|
* Creates: 'bmad-custom-agent-fred-commit-poet.md'
|
||||||
*
|
*
|
||||||
* @param {string} agentName - Custom agent name
|
* @param {string} agentName - Custom agent name
|
||||||
* @returns {string} Flat filename like 'bmad-custom-fred-commit-poet.agent.md'
|
* @returns {string} Flat filename like 'bmad-custom-agent-fred-commit-poet.md'
|
||||||
*/
|
*/
|
||||||
function customAgentDashName(agentName) {
|
function customAgentDashName(agentName) {
|
||||||
return `bmad-custom-${agentName}.agent.md`;
|
return `bmad-custom-agent-${agentName}.md`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -90,9 +101,9 @@ function isDashFormat(filename) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract parts from a dash-formatted filename
|
* Extract parts from a dash-formatted filename
|
||||||
* Parses: 'bmad-bmm-pm.agent.md' → { prefix: 'bmad', module: 'bmm', type: 'agents', name: 'pm' }
|
* Parses: 'bmad-agent-bmm-pm.md' → { prefix: 'bmad', module: 'bmm', type: 'agents', name: 'pm' }
|
||||||
* Parses: 'bmad-bmm-correct-course.md' → { prefix: 'bmad', module: 'bmm', type: 'workflows', name: 'correct-course' }
|
* Parses: 'bmad-bmm-correct-course.md' → { prefix: 'bmad', module: 'bmm', type: 'workflows', name: 'correct-course' }
|
||||||
* Parses: 'bmad-brainstorming.agent.md' → { prefix: 'bmad', module: 'core', type: 'agents', name: 'brainstorming' } (core agents)
|
* Parses: 'bmad-agent-brainstorming.md' → { prefix: 'bmad', module: 'core', type: 'agents', name: 'brainstorming' } (core agents)
|
||||||
* Parses: 'bmad-brainstorming.md' → { prefix: 'bmad', module: 'core', type: 'workflows', name: 'brainstorming' } (core workflows)
|
* Parses: 'bmad-brainstorming.md' → { prefix: 'bmad', module: 'core', type: 'workflows', name: 'brainstorming' } (core workflows)
|
||||||
*
|
*
|
||||||
* @param {string} filename - Dash-formatted filename
|
* @param {string} filename - Dash-formatted filename
|
||||||
|
|
@ -106,27 +117,27 @@ function parseDashName(filename) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this is an agent file (has .agent suffix)
|
// Check if this is an agent file (has 'agent' as second part)
|
||||||
const isAgent = withoutExt.endsWith('.agent');
|
const isAgent = parts[1] === 'agent';
|
||||||
|
|
||||||
if (isAgent) {
|
if (isAgent) {
|
||||||
// This is an agent file
|
// This is an agent file
|
||||||
// Format: bmad-name.agent (core) or bmad-module-name.agent
|
// Format: bmad-agent-name (core) or bmad-agent-module-name
|
||||||
if (parts.length === 3) {
|
if (parts.length === 3) {
|
||||||
// Core agent: bmad-name.agent
|
// Core agent: bmad-agent-name
|
||||||
return {
|
return {
|
||||||
prefix: parts[0],
|
prefix: parts[0],
|
||||||
module: 'core',
|
module: 'core',
|
||||||
type: 'agents',
|
type: 'agents',
|
||||||
name: parts[1],
|
name: parts[2],
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// Module agent: bmad-module-name.agent
|
// Module agent: bmad-agent-module-name
|
||||||
return {
|
return {
|
||||||
prefix: parts[0],
|
prefix: parts[0],
|
||||||
module: parts[1],
|
module: parts[2],
|
||||||
type: 'agents',
|
type: 'agents',
|
||||||
name: parts.slice(2).join('-'),
|
name: parts.slice(3).join('-'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,7 @@ Follow all instructions in the ${type} file exactly as written.
|
||||||
* Write task/tool artifacts using dash format (NEW STANDARD)
|
* Write task/tool artifacts using dash format (NEW STANDARD)
|
||||||
* Creates flat files like: bmad-bmm-bmad-help.md
|
* Creates flat files like: bmad-bmm-bmad-help.md
|
||||||
*
|
*
|
||||||
* Note: Tasks/tools do NOT have .agent.md suffix - only agents do.
|
* Note: Tasks/tools do NOT have bmad-agent- prefix - only agents do.
|
||||||
*
|
*
|
||||||
* @param {string} baseCommandsDir - Base commands directory for the IDE
|
* @param {string} baseCommandsDir - Base commands directory for the IDE
|
||||||
* @param {Array} artifacts - Task/tool artifacts with relativePath
|
* @param {Array} artifacts - Task/tool artifacts with relativePath
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,9 @@ class WorkflowCommandGenerator {
|
||||||
for (const workflow of allWorkflows) {
|
for (const workflow of allWorkflows) {
|
||||||
const commandContent = await this.generateCommandContent(workflow, bmadDir);
|
const commandContent = await this.generateCommandContent(workflow, bmadDir);
|
||||||
// Calculate the relative workflow path (e.g., bmm/workflows/4-implementation/sprint-planning/workflow.yaml)
|
// Calculate the relative workflow path (e.g., bmm/workflows/4-implementation/sprint-planning/workflow.yaml)
|
||||||
let workflowRelPath = workflow.path;
|
let workflowRelPath = workflow.path || '';
|
||||||
|
// Normalize path separators for cross-platform compatibility
|
||||||
|
workflowRelPath = workflowRelPath.replaceAll('\\', '/');
|
||||||
// Remove _bmad/ prefix if present to get relative path from project root
|
// Remove _bmad/ prefix if present to get relative path from project root
|
||||||
// Handle both absolute paths (/path/to/_bmad/...) and relative paths (_bmad/...)
|
// Handle both absolute paths (/path/to/_bmad/...) and relative paths (_bmad/...)
|
||||||
if (workflowRelPath.includes('_bmad/')) {
|
if (workflowRelPath.includes('_bmad/')) {
|
||||||
|
|
@ -76,9 +78,15 @@ class WorkflowCommandGenerator {
|
||||||
if (parts.length > 1) {
|
if (parts.length > 1) {
|
||||||
workflowRelPath = parts.slice(1).join('/');
|
workflowRelPath = parts.slice(1).join('/');
|
||||||
}
|
}
|
||||||
|
} else if (workflowRelPath.includes('/src/')) {
|
||||||
|
// Normalize source paths (e.g. .../src/bmm/...) to relative module path (e.g. bmm/...)
|
||||||
|
const match = workflowRelPath.match(/\/src\/([^/]+)\/(.+)/);
|
||||||
|
if (match) {
|
||||||
|
workflowRelPath = `${match[1]}/${match[2]}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Determine if this is a YAML workflow
|
// Determine if this is a YAML workflow (use normalized path which is guaranteed to be a string)
|
||||||
const isYamlWorkflow = workflow.path.endsWith('.yaml') || workflow.path.endsWith('.yml');
|
const isYamlWorkflow = workflowRelPath.endsWith('.yaml') || workflowRelPath.endsWith('.yml');
|
||||||
artifacts.push({
|
artifacts.push({
|
||||||
type: 'workflow-command',
|
type: 'workflow-command',
|
||||||
isYamlWorkflow: isYamlWorkflow, // For template selection
|
isYamlWorkflow: isYamlWorkflow, // For template selection
|
||||||
|
|
@ -284,7 +292,7 @@ When running any workflow:
|
||||||
* Write workflow command artifacts using dash format (NEW STANDARD)
|
* Write workflow command artifacts using dash format (NEW STANDARD)
|
||||||
* Creates flat files like: bmad-bmm-correct-course.md
|
* Creates flat files like: bmad-bmm-correct-course.md
|
||||||
*
|
*
|
||||||
* Note: Workflows do NOT have .agent.md suffix - only agents do.
|
* Note: Workflows do NOT have bmad-agent- prefix - only agents do.
|
||||||
*
|
*
|
||||||
* @param {string} baseCommandsDir - Base commands directory for the IDE
|
* @param {string} baseCommandsDir - Base commands directory for the IDE
|
||||||
* @param {Array} artifacts - Workflow artifacts
|
* @param {Array} artifacts - Workflow artifacts
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
description = "Activates the {{name}} agent from the BMad Method."
|
||||||
|
prompt = """
|
||||||
|
CRITICAL: You are now the BMad '{{name}}' agent.
|
||||||
|
|
||||||
|
PRE-FLIGHT CHECKLIST:
|
||||||
|
1. [ ] IMMEDIATE ACTION: Load and parse {project-root}/{{bmadFolderName}}/{{module}}/config.yaml - store ALL config values in memory for use throughout the session.
|
||||||
|
2. [ ] IMMEDIATE ACTION: Read and internalize the full agent definition at {project-root}/{{bmadFolderName}}/{{path}}.
|
||||||
|
3. [ ] CONFIRM: The user's name from config is {user_name}.
|
||||||
|
|
||||||
|
Only after all checks are complete, greet the user by name and display the menu.
|
||||||
|
Acknowledge this checklist is complete in your first response.
|
||||||
|
|
||||||
|
AGENT DEFINITION: {project-root}/{{bmadFolderName}}/{{path}}
|
||||||
|
"""
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
description = """{{description}}"""
|
||||||
|
prompt = """
|
||||||
|
Execute the BMAD '{{name}}' workflow.
|
||||||
|
|
||||||
|
CRITICAL: This is a structured YAML workflow. Follow these steps precisely:
|
||||||
|
|
||||||
|
1. LOAD the workflow definition from {project-root}/{{bmadFolderName}}/{{workflow_path}}
|
||||||
|
2. PARSE the YAML structure to understand:
|
||||||
|
- Workflow phases and steps
|
||||||
|
- Required inputs and outputs
|
||||||
|
- Dependencies between steps
|
||||||
|
3. EXECUTE each step in order
|
||||||
|
4. VALIDATE outputs before proceeding to next step
|
||||||
|
|
||||||
|
WORKFLOW FILE: {project-root}/{{bmadFolderName}}/{{workflow_path}}
|
||||||
|
"""
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
description = """{{description}}"""
|
||||||
|
prompt = """
|
||||||
|
Execute the BMAD '{{name}}' workflow.
|
||||||
|
|
||||||
|
CRITICAL: You must load and follow the workflow definition exactly.
|
||||||
|
|
||||||
|
WORKFLOW INSTRUCTIONS:
|
||||||
|
1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{workflow_path}}
|
||||||
|
2. READ its entire contents
|
||||||
|
3. FOLLOW every step precisely as specified
|
||||||
|
4. DO NOT skip or modify any steps
|
||||||
|
|
||||||
|
WORKFLOW FILE: {project-root}/{{bmadFolderName}}/{{workflow_path}}
|
||||||
|
"""
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
description = "Activates the {{title}} agent from the BMad Method."
|
|
||||||
prompt = """
|
|
||||||
CRITICAL: You are now the BMad '{{title}}' agent.
|
|
||||||
|
|
||||||
PRE-FLIGHT CHECKLIST:
|
|
||||||
1. [ ] IMMEDIATE ACTION: Load and parse @{_bmad}/{{module}}/config.yaml - store ALL config values in memory for use throughout the session.
|
|
||||||
2. [ ] IMMEDIATE ACTION: Read and internalize the full agent definition at @{_bmad}/{{module}}/agents/{{name}}.md.
|
|
||||||
3. [ ] CONFIRM: The user's name from config is {user_name}.
|
|
||||||
|
|
||||||
Only after all checks are complete, greet the user by name and display the menu.
|
|
||||||
Acknowledge this checklist is complete in your first response.
|
|
||||||
|
|
||||||
AGENT DEFINITION: @{_bmad}/{{module}}/agents/{{name}}.md
|
|
||||||
"""
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
description = "Executes the {{taskName}} task from the BMad Method."
|
|
||||||
prompt = """
|
|
||||||
Execute the following BMad Method task workflow:
|
|
||||||
|
|
||||||
PRE-FLIGHT CHECKLIST:
|
|
||||||
1. [ ] IMMEDIATE ACTION: Load and parse @{_bmad}/{{module}}/config.yaml.
|
|
||||||
2. [ ] IMMEDIATE ACTION: Read and load the task definition at @{_bmad}/{{module}}/tasks/{{filename}}.
|
|
||||||
|
|
||||||
Follow all instructions and complete the task as defined.
|
|
||||||
|
|
||||||
TASK DEFINITION: @{_bmad}/{{module}}/tasks/{{filename}}
|
|
||||||
"""
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
|
|
||||||
|
|
||||||
<agent-activation CRITICAL="TRUE">
|
|
||||||
1. LOAD the FULL agent file from {project-root}/_bmad/{{path}}
|
|
||||||
2. READ its entire contents - this contains the complete agent persona, menu, and instructions
|
|
||||||
3. FOLLOW every step in the <activation> section precisely
|
|
||||||
4. DISPLAY the welcome/greeting as instructed
|
|
||||||
5. PRESENT the numbered menu
|
|
||||||
6. WAIT for user input before proceeding
|
|
||||||
</agent-activation>
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
name = "{{name}}"
|
|
||||||
description = "{{description}}"
|
|
||||||
Loading…
Reference in New Issue