diff --git a/src/core/module.yaml b/src/core/module.yaml index ec066b95..2ae67f3d 100644 --- a/src/core/module.yaml +++ b/src/core/module.yaml @@ -20,8 +20,8 @@ document_output_language: result: "{value}" output_folder: - prompt: "Where should AI generated artifacts be saved across all modules?" - default: "bmad-output" + prompt: "Where should default output files be saved unless specified in other modules?" + default: "_bmad-output" result: "{project-root}/{value}" bmad_memory: diff --git a/tools/cli/installers/lib/core/config-collector.js b/tools/cli/installers/lib/core/config-collector.js index 095c44e1..ac3e4da2 100644 --- a/tools/cli/installers/lib/core/config-collector.js +++ b/tools/cli/installers/lib/core/config-collector.js @@ -105,7 +105,13 @@ class ConfigCollector { for (const entry of entries) { if (entry.isDirectory()) { + // Skip the _config directory - it's for system use + if (entry.name === '_config' || entry.name === '_memory') { + continue; + } + const moduleConfigPath = path.join(bmadDir, entry.name, 'config.yaml'); + if (await fs.pathExists(moduleConfigPath)) { try { const content = await fs.readFile(moduleConfigPath, 'utf8'); diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index 130fb053..9063f5d9 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -491,13 +491,11 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: let existingBmadDir = null; let existingBmadFolderName = null; - let hasLegacyCfg = false; if (await fs.pathExists(projectDir)) { const result = await this.findBmadDir(projectDir); existingBmadDir = result.bmadDir; existingBmadFolderName = path.basename(existingBmadDir); - hasLegacyCfg = result.hasLegacyCfg; } // Create a project directory if it doesn't exist (user already confirmed) @@ -522,44 +520,6 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: const bmadDir = path.join(projectDir, bmadFolderName); - // Check for legacy _cfg folder and prompt for rename - if (hasLegacyCfg && !config._quickUpdate) { - spinner.stop(); - - console.log(chalk.yellow('\n⚠️ Legacy configuration folder detected')); - console.log(chalk.dim(` Found: ${path.join(bmadDir, '_cfg')}`)); - console.log(chalk.dim(' The configuration folder has been renamed from "_cfg" to "_config"')); - - const inquirer = require('inquirer'); - const { shouldRename } = await inquirer.prompt([ - { - type: 'confirm', - name: 'shouldRename', - message: 'Would you like the installer to rename "_cfg" to "_config" for you?', - default: true, - }, - ]); - - if (!shouldRename) { - console.log(chalk.red('\n❌ Installation cancelled')); - console.log(chalk.dim('You must manually rename the "_cfg" folder to "_config" before proceeding.')); - return { success: false, cancelled: true }; - } - - // Perform the rename - spinner.start('Renaming configuration folder...'); - try { - const oldCfgPath = path.join(bmadDir, '_cfg'); - const newCfgPath = path.join(bmadDir, '_config'); - await fs.move(oldCfgPath, newCfgPath); - spinner.succeed('Configuration folder renamed successfully'); - } catch (error) { - spinner.fail('Failed to rename configuration folder'); - console.error(chalk.red(`Error: ${error.message}`)); - return { success: false, error: error.message }; - } - } - // Check existing installation spinner.text = 'Checking for existing installation...'; const existingInstall = await this.detector.detect(bmadDir); diff --git a/tools/cli/lib/ui.js b/tools/cli/lib/ui.js index ff94a6d2..0465feb1 100644 --- a/tools/cli/lib/ui.js +++ b/tools/cli/lib/ui.js @@ -33,10 +33,101 @@ class UI { await installer.handleLegacyV4Migration(confirmedDirectory, legacyV4); } - // Check if there's an existing BMAD installation - const fs = require('fs-extra'); - const path = require('node:path'); - const bmadDir = await installer.findBmadDir(confirmedDirectory); + // Check for legacy folders and prompt for rename before showing any menus + let hasLegacyCfg = false; + let hasLegacyBmadFolder = false; + let bmadDir = null; + let legacyBmadPath = null; + + // First check for legacy .bmad folder (instead of _bmad) + const entries = await fs.readdir(confirmedDirectory, { withFileTypes: true }); + for (const entry of entries) { + if (entry.isDirectory() && entry.name === '.bmad') { + hasLegacyBmadFolder = true; + legacyBmadPath = path.join(confirmedDirectory, '.bmad'); + bmadDir = legacyBmadPath; + + // Check if it has _cfg folder + const cfgPath = path.join(legacyBmadPath, '_cfg'); + if (await fs.pathExists(cfgPath)) { + hasLegacyCfg = true; + } + break; + } + } + + // If no .bmad found, check for current installations + if (!hasLegacyBmadFolder) { + const bmadResult = await installer.findBmadDir(confirmedDirectory); + bmadDir = bmadResult.bmadDir; + hasLegacyCfg = bmadResult.hasLegacyCfg; + } + + if (hasLegacyBmadFolder || hasLegacyCfg) { + console.log(chalk.yellow('\n⚠️ Legacy folder structure detected')); + + let message = 'The following folders need to be renamed:\n'; + if (hasLegacyBmadFolder) { + message += chalk.dim(` • ".bmad" → "_bmad"\n`); + } + if (hasLegacyCfg) { + message += chalk.dim(` • "_cfg" → "_config"\n`); + } + console.log(message); + + const { shouldRename } = await inquirer.prompt([ + { + type: 'confirm', + name: 'shouldRename', + message: 'Would you like the installer to rename these folders for you?', + default: true, + }, + ]); + + if (!shouldRename) { + console.log(chalk.red('\n❌ Installation cancelled')); + console.log(chalk.dim('You must manually rename the folders before proceeding:')); + if (hasLegacyBmadFolder) { + console.log(chalk.dim(` • Rename ".bmad" to "_bmad"`)); + } + if (hasLegacyCfg) { + console.log(chalk.dim(` • Rename "_cfg" to "_config"`)); + } + process.exit(0); + return; + } + + // Perform the renames + const ora = require('ora'); + const spinner = ora('Updating folder structure...').start(); + + try { + // First rename .bmad to _bmad if needed + if (hasLegacyBmadFolder) { + const newBmadPath = path.join(confirmedDirectory, '_bmad'); + await fs.move(legacyBmadPath, newBmadPath); + bmadDir = newBmadPath; + spinner.succeed('Renamed ".bmad" to "_bmad"'); + } + + // Then rename _cfg to _config if needed + if (hasLegacyCfg) { + spinner.start('Renaming configuration folder...'); + const oldCfgPath = path.join(bmadDir, '_cfg'); + const newCfgPath = path.join(bmadDir, '_config'); + await fs.move(oldCfgPath, newCfgPath); + spinner.succeed('Renamed "_cfg" to "_config"'); + } + + spinner.succeed('Folder structure updated successfully'); + } catch (error) { + spinner.fail('Failed to update folder structure'); + console.error(chalk.red(`Error: ${error.message}`)); + process.exit(1); + } + } + + // Check if there's an existing BMAD installation (after any folder renames) const hasExistingInstall = await fs.pathExists(bmadDir); // Always ask for custom content, but we'll handle it differently for new installs @@ -190,7 +281,8 @@ class UI { const { Installer } = require('../installers/lib/core/installer'); const detector = new Detector(); const installer = new Installer(); - const bmadDir = await installer.findBmadDir(projectDir || process.cwd()); + const bmadResult = await installer.findBmadDir(projectDir || process.cwd()); + const bmadDir = bmadResult.bmadDir; const existingInstall = await detector.detect(bmadDir); const configuredIdes = existingInstall.ides || [];