From 0810646ed659a6a56cbbee3f0281f498e248727e Mon Sep 17 00:00:00 2001 From: Jonah Schulte Date: Wed, 28 Jan 2026 11:12:06 -0500 Subject: [PATCH] fix: update dependency resolver for new src/bmm structure (fixes 2 failing tests) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed all path resolution logic in dependency-resolver.js to handle the new directory structure where bmm is directly under src/ instead of src/modules/. **Bugs Fixed:** 1. Line 341: Strip leading slash after removing {project-root} prefix - `{project-root}/bmad/` became `/bmad/` which failed `startsWith('bmad/')` check 2. Lines 358, 378, 385: Use bmm/ directly instead of modules/bmm/ for explicit deps - Updated both direct paths and glob patterns 3. Lines 537, 549, 565: Update resolveCommandToPath for @task/@agent/@bmad refs - Task search now checks src/bmm/tasks/ not src/modules/bmm/tasks/ - Agent search now checks src/bmm/agents/ not src/modules/bmm/agents/ - Direct bmad/ paths now resolve to src/bmm/ not src/modules/bmm/ **Test Results:** - Before: 350/352 passing (2 failing) - After: 352/352 passing (100% ✅) Tests fixed: - "should resolve bmad/bmm/tasks/task.md (module path)" - "should resolve bmad-path for module files" --- .../lib/core/dependency-resolver.js | 55 +++++++++++++++---- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/tools/cli/installers/lib/core/dependency-resolver.js b/tools/cli/installers/lib/core/dependency-resolver.js index ad857ac0..1696c5a1 100644 --- a/tools/cli/installers/lib/core/dependency-resolver.js +++ b/tools/cli/installers/lib/core/dependency-resolver.js @@ -338,7 +338,7 @@ class DependencyResolver { // Handle {project-root} prefix if present if (depPath.includes('{project-root}')) { // Remove {project-root} and resolve as bmad path - depPath = depPath.replace('{project-root}', ''); + depPath = depPath.replace('{project-root}', '').replace(/^\/+/, ''); if (depPath.startsWith('bmad/')) { const bmadPath = depPath.replace(/^bmad\//, ''); @@ -354,7 +354,11 @@ class DependencyResolver { let basePath; if (module === 'core') { basePath = path.join(bmadDir, 'core', middlePath); + } else if (module === 'bmm') { + // bmm is directly under src/ + basePath = path.join(bmadDir, module, middlePath); } else { + // Other modules under modules/ basePath = path.join(bmadDir, 'modules', module, middlePath); } @@ -375,7 +379,14 @@ class DependencyResolver { const parts = bmadPath.split('/'); const module = parts[0]; const rest = parts.slice(1).join('/'); - const modulePath = path.join(bmadDir, 'modules', module, rest); + let modulePath; + if (module === 'bmm') { + // bmm is directly under src/ + modulePath = path.join(bmadDir, module, rest); + } else { + // Other modules under modules/ + modulePath = path.join(bmadDir, 'modules', module, rest); + } if (await fs.pathExists(modulePath)) { paths.push(modulePath); @@ -520,10 +531,16 @@ class DependencyResolver { const taskName = command.slice(6); // Search all modules for this task for (const module of ['core', 'bmm', 'cis']) { - const taskPath = - module === 'core' - ? path.join(bmadDir, 'core', 'tasks', `${taskName}.md`) - : path.join(bmadDir, 'modules', module, 'tasks', `${taskName}.md`); + let taskPath; + if (module === 'core') { + taskPath = path.join(bmadDir, 'core', 'tasks', `${taskName}.md`); + } else if (module === 'bmm') { + // bmm is directly under src/ + taskPath = path.join(bmadDir, 'bmm', 'tasks', `${taskName}.md`); + } else { + // Other modules under modules/ + taskPath = path.join(bmadDir, 'modules', module, 'tasks', `${taskName}.md`); + } if (await fs.pathExists(taskPath)) { return taskPath; } @@ -532,10 +549,16 @@ class DependencyResolver { const agentName = command.slice(7); // Search all modules for this agent for (const module of ['core', 'bmm', 'cis']) { - const agentPath = - module === 'core' - ? path.join(bmadDir, 'core', 'agents', `${agentName}.md`) - : path.join(bmadDir, 'modules', module, 'agents', `${agentName}.md`); + let agentPath; + if (module === 'core') { + agentPath = path.join(bmadDir, 'core', 'agents', `${agentName}.md`); + } else if (module === 'bmm') { + // bmm is directly under src/ + agentPath = path.join(bmadDir, 'bmm', 'agents', `${agentName}.md`); + } else { + // Other modules under modules/ + agentPath = path.join(bmadDir, 'modules', module, 'agents', `${agentName}.md`); + } if (await fs.pathExists(agentPath)) { return agentPath; } @@ -550,8 +573,16 @@ class DependencyResolver { // Check if name already has extension const fileName = name.endsWith('.md') ? name : `${name}.md`; - const filePath = - module === 'core' ? path.join(bmadDir, 'core', type, fileName) : path.join(bmadDir, 'modules', module, type, fileName); + let filePath; + if (module === 'core') { + filePath = path.join(bmadDir, 'core', type, fileName); + } else if (module === 'bmm') { + // bmm is directly under src/ + filePath = path.join(bmadDir, 'bmm', type, fileName); + } else { + // Other modules under modules/ + filePath = path.join(bmadDir, 'modules', module, type, fileName); + } if (await fs.pathExists(filePath)) { return filePath; }