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(); const installedFilesMap = new Map();
for (const fileEntry of existingFilesManifest) { for (const fileEntry of existingFilesManifest) {
if (fileEntry.path) { if (fileEntry.path) {
// Files in manifest are stored as relative paths starting with 'bmad/' // Paths are relative to bmadDir. Legacy manifests incorrectly prefixed 'bmad/' -
// Convert to absolute path // 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 relativePath = fileEntry.path.startsWith('bmad/') ? fileEntry.path.slice(5) : fileEntry.path;
const absolutePath = path.join(bmadDir, relativePath); const absolutePath = path.join(bmadDir, relativePath);
installedFilesMap.set(path.normalize(absolutePath), { installedFilesMap.set(path.normalize(absolutePath), {

View File

@ -650,13 +650,14 @@ class ManifestGenerator {
if (this.allInstalledFiles && this.allInstalledFiles.length > 0) { if (this.allInstalledFiles && this.allInstalledFiles.length > 0) {
// Process all installed files // Process all installed files
for (const filePath of this.allInstalledFiles) { 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 ext = path.extname(filePath).toLowerCase();
const fileName = path.basename(filePath, ext); const fileName = path.basename(filePath, ext);
// Determine module from path // Determine module from path (first directory component)
const pathParts = relativePath.split('/'); const pathParts = relativePath.split('/');
const module = pathParts.length > 1 ? pathParts[1] : 'unknown'; const module = pathParts.length > 0 ? pathParts[0] : 'unknown';
// Calculate hash // Calculate hash
const hash = await this.calculateFileHash(filePath); const hash = await this.calculateFileHash(filePath);
@ -672,10 +673,13 @@ class ManifestGenerator {
} else { } else {
// Fallback: use the collected workflows/agents/tasks // Fallback: use the collected workflows/agents/tasks
for (const file of this.files) { 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); const hash = await this.calculateFileHash(filePath);
allFiles.push({ allFiles.push({
...file, ...file,
path: relPath,
hash: hash, hash: hash,
}); });
} }