fix bmb workflow paths

This commit is contained in:
Brian Madison
2025-12-10 20:50:24 +09:00
parent 45a97b070a
commit 446a0359ab
336 changed files with 1414 additions and 1509 deletions

View File

@@ -59,7 +59,7 @@ function buildSimpleActivation(criticalActions = [], menuItems = [], deploymentT
// Standard steps
activation += ` <step n="${stepNum++}">Load persona from this current agent file (already in context)</step>\n`;
activation += ` <step n="${stepNum++}">Load and read {project-root}/{bmad_folder}/core/config.yaml to get {user_name}, {communication_language}, {output_folder}</step>\n`;
activation += ` <step n="${stepNum++}">Load and read {project-root}/.bmad/core/config.yaml to get {user_name}, {communication_language}, {output_folder}</step>\n`;
activation += ` <step n="${stepNum++}">Remember: user's name is {user_name}</step>\n`;
// Agent-specific steps from critical_actions
@@ -119,7 +119,7 @@ function buildSimpleActivation(criticalActions = [], menuItems = [], deploymentT
if (usedHandlers.has('workflow')) {
activation += ` <handler type="workflow">
When menu item has: workflow="path/to/workflow.yaml"
1. CRITICAL: Always LOAD {project-root}/{bmad_folder}/core/tasks/workflow.xml
1. CRITICAL: Always LOAD {project-root}/.bmad/core/tasks/workflow.xml
2. Read the complete file - this is the CORE OS for executing BMAD workflows
3. Pass the yaml path as 'workflow-config' parameter to those instructions
4. Execute workflow.xml instructions precisely following all steps
@@ -150,7 +150,7 @@ function buildSimpleActivation(criticalActions = [], menuItems = [], deploymentT
if (usedHandlers.has('validate-workflow')) {
activation += ` <handler type="validate-workflow">
When menu item has: validate-workflow="path/to/workflow.yaml"
1. CRITICAL: Always LOAD {project-root}/{bmad_folder}/core/tasks/validate-workflow.xml
1. CRITICAL: Always LOAD {project-root}/.bmad/core/tasks/validate-workflow.xml
2. Read the complete file - this is the CORE OS for validating BMAD workflows
3. Pass the workflow.yaml path as 'workflow' parameter to those instructions
4. Pass any checklist.md from the workflow location as 'checklist' parameter if available

View File

@@ -273,7 +273,7 @@ function installAgent(agentInfo, answers, targetPath, options = {}) {
// Resolve path variables
const resolvedSidecarFolder = agentSidecarFolder
.replaceAll('{project-root}', options.projectRoot || process.cwd())
.replaceAll('{bmad_folder}', options.bmadFolder || '.bmad');
.replaceAll('.bmad', options.bmadFolder || '.bmad');
// Create sidecar directory for this agent
const agentSidecarDir = path.join(resolvedSidecarFolder, agentFolderName);
@@ -407,7 +407,7 @@ function detectBmadProject(targetPath) {
// Walk up directory tree looking for BMAD installation
while (checkPath !== root) {
const possibleNames = ['.bmad', 'bmad'];
const possibleNames = ['.bmad'];
for (const name of possibleNames) {
const bmadFolder = path.join(checkPath, name);
const cfgFolder = path.join(bmadFolder, '_cfg');

View File

@@ -136,7 +136,7 @@ class UI {
// Create the bmad directory based on core config
const path = require('node:path');
const fs = require('fs-extra');
const bmadFolderName = coreConfig.bmad_folder || 'bmad';
const bmadFolderName = '.bmad';
const bmadDir = path.join(confirmedDirectory, bmadFolderName);
await fs.ensureDir(bmadDir);
@@ -1082,7 +1082,7 @@ class UI {
* @calls checkAgentVibesInstalled(), inquirer.prompt(), chalk.green/yellow/dim()
*
* AI NOTE: This prompt is strategically positioned in installation flow:
* - AFTER core config (bmad_folder, user_name, etc)
* - AFTER core config (user_name, etc)
* - BEFORE IDE selection (which can hang on Windows/PowerShell)
*
* Flow Logic:
@@ -1210,129 +1210,134 @@ class UI {
*/
async promptCustomContentForExisting() {
try {
CLIUtils.displaySection('Custom Content', 'Add new custom agents, workflows, or modules to your installation');
// Skip custom content installation - always return false
return { hasCustomContent: false };
const { hasCustomContent } = await inquirer.prompt([
{
type: 'list',
name: 'hasCustomContent',
message: 'Do you want to add or update custom content?',
choices: [
{
name: 'No, continue with current installation only',
value: false,
},
{
name: 'Yes, I have custom content to add or update',
value: true,
},
],
default: false,
},
]);
// TODO: Custom content installation temporarily disabled
// CLIUtils.displaySection('Custom Content', 'Add new custom agents, workflows, or modules to your installation');
if (!hasCustomContent) {
return { hasCustomContent: false };
}
// const { hasCustomContent } = await inquirer.prompt([
// {
// type: 'list',
// name: 'hasCustomContent',
// message: 'Do you want to add or update custom content?',
// choices: [
// {
// name: 'No, continue with current installation only',
// value: false,
// },
// {
// name: 'Yes, I have custom content to add or update',
// value: true,
// },
// ],
// default: false,
// },
// ]);
// Get directory path
const { customPath } = await inquirer.prompt([
{
type: 'input',
name: 'customPath',
message: 'Enter directory to search for custom content (will scan subfolders):',
default: process.cwd(),
validate: async (input) => {
if (!input || input.trim() === '') {
return 'Please enter a directory path';
}
// if (!hasCustomContent) {
// return { hasCustomContent: false };
// }
// Normalize and check if path exists
const expandedPath = CLIUtils.expandPath(input.trim());
const pathExists = await fs.pathExists(expandedPath);
if (!pathExists) {
return 'Directory does not exist';
}
// TODO: Custom content installation temporarily disabled
// // Get directory path
// const { customPath } = await inquirer.prompt([
// {
// type: 'input',
// name: 'customPath',
// message: 'Enter directory to search for custom content (will scan subfolders):',
// default: process.cwd(),
// validate: async (input) => {
// if (!input || input.trim() === '') {
// return 'Please enter a directory path';
// }
// Check if it's actually a directory
const stats = await fs.stat(expandedPath);
if (!stats.isDirectory()) {
return 'Path must be a directory';
}
// // Normalize and check if path exists
// const expandedPath = CLIUtils.expandPath(input.trim());
// const pathExists = await fs.pathExists(expandedPath);
// if (!pathExists) {
// return 'Directory does not exist';
// }
return true;
},
transformer: (input) => {
return CLIUtils.expandPath(input);
},
},
]);
// // Check if it's actually a directory
// const stats = await fs.stat(expandedPath);
// if (!stats.isDirectory()) {
// return 'Path must be a directory';
// }
const resolvedPath = CLIUtils.expandPath(customPath);
// return true;
// },
// transformer: (input) => {
// return CLIUtils.expandPath(input);
// },
// },
// ]);
// Find custom content
const customHandler = new CustomHandler();
const customFiles = await customHandler.findCustomContent(resolvedPath);
// const resolvedPath = CLIUtils.expandPath(customPath);
if (customFiles.length === 0) {
console.log(chalk.yellow(`\nNo custom content found in ${resolvedPath}`));
// // Find custom content
// const customHandler = new CustomHandler();
// const customFiles = await customHandler.findCustomContent(resolvedPath);
const { tryDifferent } = await inquirer.prompt([
{
type: 'confirm',
name: 'tryDifferent',
message: 'Try a different directory?',
default: true,
},
]);
// if (customFiles.length === 0) {
// console.log(chalk.yellow(`\nNo custom content found in ${resolvedPath}`));
if (tryDifferent) {
return await this.promptCustomContentForExisting();
}
// const { tryDifferent } = await inquirer.prompt([
// {
// type: 'confirm',
// name: 'tryDifferent',
// message: 'Try a different directory?',
// default: true,
// },
// ]);
return { hasCustomContent: false };
}
// if (tryDifferent) {
// return await this.promptCustomContentForExisting();
// }
// Display found items
console.log(chalk.cyan(`\nFound ${customFiles.length} custom content file(s):`));
const customContentItems = [];
// return { hasCustomContent: false };
// }
for (const customFile of customFiles) {
const customInfo = await customHandler.getCustomInfo(customFile);
if (customInfo) {
customContentItems.push({
name: `${chalk.cyan('✓')} ${customInfo.name} ${chalk.gray(`(${customInfo.relativePath})`)}`,
value: `__CUSTOM_CONTENT__${customFile}`,
checked: true,
});
}
}
// // Display found items
// console.log(chalk.cyan(`\nFound ${customFiles.length} custom content file(s):`));
// const customContentItems = [];
// Add option to keep existing custom content
console.log(chalk.yellow('\nExisting custom modules will be preserved unless you remove them'));
// for (const customFile of customFiles) {
// const customInfo = await customHandler.getCustomInfo(customFile);
// if (customInfo) {
// customContentItems.push({
// name: `${chalk.cyan('✓')} ${customInfo.name} ${chalk.gray(`(${customInfo.relativePath})`)}`,
// value: `__CUSTOM_CONTENT__${customFile}`,
// checked: true,
// });
// }
// }
const { selectedFiles } = await inquirer.prompt([
{
type: 'checkbox',
name: 'selectedFiles',
message: 'Select custom content to add:',
choices: customContentItems,
pageSize: 15,
validate: (answer) => {
if (answer.length === 0) {
return 'You must select at least one item';
}
return true;
},
},
]);
// // Add option to keep existing custom content
// console.log(chalk.yellow('\nExisting custom modules will be preserved unless you remove them'));
return {
hasCustomContent: true,
customPath: resolvedPath,
selected: true,
selectedFiles: selectedFiles,
};
// const { selectedFiles } = await inquirer.prompt([
// {
// type: 'checkbox',
// name: 'selectedFiles',
// message: 'Select custom content to add:',
// choices: customContentItems,
// pageSize: 15,
// validate: (answer) => {
// if (answer.length === 0) {
// return 'You must select at least one item';
// }
// return true;
// },
// },
// ]);
// return {
// hasCustomContent: true,
// customPath: resolvedPath,
// selected: true,
// selectedFiles: selectedFiles,
// };
} catch (error) {
console.error(chalk.red('Error configuring custom content:'), error);
return { hasCustomContent: false };