7.3 KiB
Detection Report: Issue #478 Analysis
Date: 2025-10-26 Issue: No BMad installation found in current directory tree Status: Analysis Complete
FINDINGS
1. ROOT CAUSE IDENTIFIED
The issue is NOT about a findInstallation() function as initially suspected, but rather about how the status command resolves the working directory.
Problem Flow:
1. User runs: npx bmad-method status
2. npx may change the working directory to node_modules/.bin
3. Status command uses default directory "." (current working directory)
4. path.resolve(".") resolves relative to the changed working directory
5. Result: Looks in wrong location, doesn't find .bmad-core/
2. KEY CODE LOCATIONS
File 1: tools/cli/commands/status.js (Lines 8-9)
options: [['-d, --directory <path>', 'Installation directory', '.']],
action: async (options) => {
const status = await installer.getStatus(options.directory);
Issue: Default directory is "." but context may be wrong when invoked via npx
File 2: tools/cli/installers/lib/core/installer.js (Lines 626-629)
async getStatus(directory) {
const bmadDir = path.join(path.resolve(directory), 'bmad');
return await this.detector.detect(bmadDir);
}
Problem: path.resolve(directory) uses process.cwd() as base, which may be wrong
File 3: tools/cli/installers/lib/core/detector.js (Lines 1-150)
class Detector {
async detect(bmadDir) {
// Checks only the provided bmadDir
// Does NOT search up the directory tree
// Does NOT search for .bmad-core/ or .bmad-* folders
}
}
Issue: Detector expects the exact path to the bmad folder, doesn't search
3. THE REAL PROBLEM
The current implementation:
- ✅ Works:
bmad-method status(from within project, current dir is project root) - ❌ Fails:
npx bmad-method status(npx changes working directory) - ❌ Fails:
bmad-method statusfrom subdirectory (doesn't search parent dirs)
The implementation requires users to either:
- Run from project root with correct directory
- Explicitly pass
-d /path/to/project
But it should:
- Auto-detect BMAD installation in current directory tree
- Search up the directory hierarchy for
.bmad-*folders - Work regardless of where npx changes the working directory
4. WHAT NEEDS TO CHANGE
Current Behavior:
Status checks specific path: /project/bmad
If not there → "No BMAD installation found"
Desired Behavior:
Status searches from current directory:
1. Check ./bmad/
2. Check ../ bmad/
3. Check ../../bmad/
Until found or reach filesystem root
Also support legacy: .bmad-core/, .bmad-*, .bmm/, .cis/
5. IMPLEMENTATION STRATEGY
Option A: Add search function (Recommended)
- Create
findInstallation(startDir)that searches up the tree - Update
getStatus()to use search function - Returns path to closest BMAD installation
Option B: Fix working directory context
- Capture original working directory at CLI entry point
- Pass throughout the call chain
- Use for resolving relative paths
Recommendation: Combine both approaches
- Fix the working directory context (handle npx correctly)
- Add directory search for better UX (works from subdirectories)
6. AFFECTED FUNCTIONS
Direct Impact:
Installer.getStatus(directory)- needs to search, not just check one pathDetector.detect(bmadDir)- works as-is, but only checks provided path
Indirect Impact:
StatusCommand.action()- may need to handle working directory- CLI entry point - may need to capture originalCwd
7. TEST SCENARIOS NEEDED
Scenario 1: Run status from project root
cd /home/user/my-project
npx bmad-method status
Current: ❌ Fails (npx changes cwd) Expected: ✅ Detects .bmad-core/ or bmad/ folder
Scenario 2: Run status from project subdirectory
cd /home/user/my-project/src
npx bmad-method status
Current: ❌ Fails (no installation in src/) Expected: ✅ Searches up and finds ../bmad/
Scenario 3: Run status with explicit path
npx bmad-method status -d /home/user/my-project
Current: ✅ Works Expected: ✅ Still works
8. MIGRATION PATH
-
Phase 1: Add
findInstallation(searchPath)function- Searches directory tree upward
- Returns path to nearest BMAD installation
- Handles legacy folder names
-
Phase 2: Update
getStatus()to use search- If explicit path given, check that path
- Otherwise, search from current directory
- Return installation details or null
-
Phase 3: Handle npx working directory
- Optional: Capture originalCwd at CLI level
- Improves reliability when running via npx
-
Phase 4: Comprehensive testing
- Unit tests for search function
- Integration tests for status command
- Edge case tests (nested, legacy, symlinks, etc.)
CODE MODIFICATIONS NEEDED
New Function: findInstallation()
async findInstallation(searchPath = process.cwd()) {
let currentPath = path.resolve(searchPath);
const root = path.parse(currentPath).root;
while (currentPath !== root) {
// Check for modern BMAD installation
const bmadPath = path.join(currentPath, 'bmad');
if (await fs.pathExists(bmadPath)) {
return bmadPath;
}
// Check for legacy installations
const legacyFolders = ['.bmad-core', '.bmad-method', '.bmm', '.cis'];
for (const folder of legacyFolders) {
const legacyPath = path.join(currentPath, folder);
if (await fs.pathExists(legacyPath)) {
return legacyPath;
}
}
// Move up one directory
currentPath = path.dirname(currentPath);
}
return null; // Not found
}
Modified getStatus()
async getStatus(directory) {
let searchPath = directory === '.' ? process.cwd() : path.resolve(directory);
const installPath = await this.findInstallation(searchPath);
if (!installPath) {
return { installed: false, message: 'No BMAD installation found' };
}
return await this.detector.detect(installPath);
}
FILES TO MODIFY
-
tools/cli/installers/lib/core/installer.js- Add
findInstallation()method - Update
getStatus()to use it - Lines: ~626, ~new
- Add
-
tools/cli/commands/status.js- May need to handle originalCwd
- Lines: ~8-9 (optional)
RELATED ISSUES
- PR #480: Mentions honor original working directory (suggests this was a known issue)
- Comment from @dracic: "It's all about originalCwd"
- Issue was filed by @moyger, confirmed by @dracic, assigned to @manjaroblack
SUCCESS METRICS
✅ After fix:
npx bmad-method statusworks from project rootnpx bmad-method statusworks from project subdirectoriesbmad-method statusworks without explicit path- All existing tests pass
- New tests verify the fix
ESTIMATED EFFORT
- Implementation: 1-2 hours
- Testing: 2-3 hours
- Review & fixes: 1 hour
- Total: 4-6 hours
NEXT STEPS
- ✅ Detection complete - move to Phase 2
- Create unit tests for
findInstallation() - Create integration tests for status command
- Implement the fix
- Validate all tests pass
- Create PR and get review
Analyst: GitHub Copilot Confidence: High (95%) Verified Against:
- Issue description ✓
- Source code review ✓
- Related PR #480 context ✓
- Team comments ✓