Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions test/test-installation-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,35 @@ async function runTests() {

console.log('');

// ============================================================
// Test 4: Workflow command paths anchor to project root
// ============================================================
console.log(`${colors.yellow}Test Suite 4: Workflow Command Paths${colors.reset}\n`);

try {
const { WorkflowCommandGenerator } = require('../tools/cli/installers/lib/ide/shared/workflow-command-generator');
const generator = new WorkflowCommandGenerator('.bmad');

const workflow = {
name: 'create-architecture',
module: 'bmm',
description: 'Architecture workflow',
path: '.bmad/bmm/workflows/3-solutioning/architecture/workflow.md',
};

const content = await generator.generateCommandContent(workflow, '');

assert(
content.includes('{project-root}/.bmad/bmm/workflows/3-solutioning/architecture/workflow.md'),
'workflow command uses project-root anchored workflow path',
);
assert(!content.includes('@.bmad/bmm'), 'workflow command avoids relative @.bmad paths that IDEs resolve incorrectly');
} catch (error) {
assert(false, 'workflow command generator anchors paths', error.message);
}

console.log('');

// ============================================================
// Test 5: TEA Agent Special Handling
// ============================================================
Expand Down
15 changes: 15 additions & 0 deletions tools/cli/installers/lib/ide/shared/workflow-command-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ class WorkflowCommandGenerator {
// To: {project-root}/{bmad_folder}/bmm/workflows/.../workflow.yaml
let workflowPath = workflow.path;

const withProjectRoot = (p) => {
if (!p) return p;
return p.startsWith('{project-root}/') ? p : `{project-root}/${p}`;
};

// Extract the relative path from source
if (workflowPath.includes('/src/modules/')) {
const match = workflowPath.match(/\/src\/modules\/(.+)/);
Expand All @@ -125,12 +130,19 @@ class WorkflowCommandGenerator {
}
}

// Anchor paths to project root to prevent IDEs from resolving relative to module folders
workflowPath = withProjectRoot(workflowPath);

// Core workflow is always at the BMAD root
const coreWorkflowPath = withProjectRoot(`${this.bmadFolderName}/core/tasks/workflow.xml`);

// Replace template variables
return template
.replaceAll('{{name}}', workflow.name)
.replaceAll('{{module}}', workflow.module)
.replaceAll('{{description}}', workflow.description)
.replaceAll('{{workflow_path}}', workflowPath)
.replaceAll('{{core_workflow_path}}', coreWorkflowPath)
.replaceAll('{bmad_folder}', this.bmadFolderName)
.replaceAll('{*bmad_folder*}', '{bmad_folder}');
}
Expand Down Expand Up @@ -218,6 +230,9 @@ When running any workflow:
if (match) {
transformed = `{project-root}/${this.bmadFolderName}/core/${match[1]}`;
}
} else if (!workflowPath.startsWith('{project-root}/')) {
// Already an installed path (e.g., ".bmad/bmm/...") - anchor to project root
transformed = `{project-root}/${workflowPath}`;
}

return transformed;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: '{{description}}'
IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded:

<steps CRITICAL="TRUE">
1. Always LOAD the FULL @{bmad_folder}/core/tasks/workflow.xml
1. Always LOAD the FULL @{{core_workflow_path}}
2. READ its entire contents - this is the CORE OS for EXECUTING the specific workflow-config @{{workflow_path}}
3. Pass the yaml path {{workflow_path}} as 'workflow-config' parameter to the workflow.xml instructions
4. Follow workflow.xml instructions EXACTLY as written to process and follow the specific workflow config and its instructions
Expand Down