fix(installer): remove hardcoded 'bmad' prefix from files-manifest.csv paths (#1043)

The manifest writer hardcoded 'bmad' as the path prefix regardless of
the actual folder name (.bmad, bmad, etc). The reader had a matching
hardcoded strip, so it worked by accident.

Now paths are stored relative to bmadDir without any prefix. Legacy
fallback strips 'bmad/' on read - safe because no real path inside
bmadDir would start with 'bmad/'.

Co-authored-by: Brian <bmadcode@gmail.com>
This commit is contained in:
Alex Verkhovsky 2025-12-06 10:36:17 -08:00 committed by GitHub
parent 282bc27c7e
commit a6dffb4706
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 11 additions and 6 deletions

View File

@ -2210,8 +2210,9 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
const installedFilesMap = new Map();
for (const fileEntry of existingFilesManifest) {
if (fileEntry.path) {
// Files in manifest are stored as relative paths starting with 'bmad/'
// Convert to absolute path
// Paths are relative to bmadDir. Legacy manifests incorrectly prefixed 'bmad/' -
// strip it if present. This is safe because no real path inside bmadDir would
// start with 'bmad/' (you'd never have .bmad/bmad/... as an actual structure).
const relativePath = fileEntry.path.startsWith('bmad/') ? fileEntry.path.slice(5) : fileEntry.path;
const absolutePath = path.join(bmadDir, relativePath);
installedFilesMap.set(path.normalize(absolutePath), {

View File

@ -650,13 +650,14 @@ class ManifestGenerator {
if (this.allInstalledFiles && this.allInstalledFiles.length > 0) {
// Process all installed files
for (const filePath of this.allInstalledFiles) {
const relativePath = 'bmad' + filePath.replace(this.bmadDir, '').replaceAll('\\', '/');
// Store paths relative to bmadDir (no folder prefix)
const relativePath = filePath.replace(this.bmadDir, '').replaceAll('\\', '/').replace(/^\//, '');
const ext = path.extname(filePath).toLowerCase();
const fileName = path.basename(filePath, ext);
// Determine module from path
// Determine module from path (first directory component)
const pathParts = relativePath.split('/');
const module = pathParts.length > 1 ? pathParts[1] : 'unknown';
const module = pathParts.length > 0 ? pathParts[0] : 'unknown';
// Calculate hash
const hash = await this.calculateFileHash(filePath);
@ -672,10 +673,13 @@ class ManifestGenerator {
} else {
// Fallback: use the collected workflows/agents/tasks
for (const file of this.files) {
const filePath = path.join(this.bmadDir, file.path.replace(this.bmadFolderName + '/', ''));
// Strip the folder prefix if present (for consistency)
const relPath = file.path.replace(this.bmadFolderName + '/', '');
const filePath = path.join(this.bmadDir, relPath);
const hash = await this.calculateFileHash(filePath);
allFiles.push({
...file,
path: relPath,
hash: hash,
});
}