From 6a282f86b4148971365bb9a8ef270ba1459558dc Mon Sep 17 00:00:00 2001 From: Brian Madison Date: Mon, 26 Jan 2026 17:33:02 -0600 Subject: [PATCH] allow updates from any beta, warn on alpha and v4 --- .../quick-spec/steps/step-04-review.md | 2 +- tools/cli/installers/lib/core/installer.js | 3 + .../ide/shared/task-tool-command-generator.js | 2 +- .../lib/ide/templates/combined/antigravity.md | 4 +- .../lib/ide/templates/combined/rovodev.md | 2 +- .../lib/ide/templates/combined/trae.md | 2 +- .../templates/combined/windsurf-workflow.md | 2 +- tools/cli/lib/ui.js | 93 ++++--------------- 8 files changed, 29 insertions(+), 81 deletions(-) diff --git a/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md b/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md index 6f234612..a223a2e4 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md @@ -139,7 +139,7 @@ b) **HALT and wait for user selection.** #### Menu Handling Logic: - IF A: Read fully and follow: `{advanced_elicitation}` with current spec content, process enhanced insights, ask user "Accept improvements? (y/n)", if yes update spec then redisplay menu, if no keep original then redisplay menu -- IF B: Load and execute `{quick_dev_workflow}` with the final spec file (warn: fresh context is better) +- IF B: Read the entire workflow file at `{quick_dev_workflow}` and follow the instructions with the final spec file (warn: fresh context is better) - IF D: Exit workflow - display final confirmation and path to spec - IF P: Read fully and follow: `{party_mode_exec}` with current spec content, process collaborative insights, ask user "Accept changes? (y/n)", if yes update spec then redisplay menu, if no keep original then redisplay menu - IF R: Execute Adversarial Review (see below) diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index b1acc917..a14c3d19 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -999,6 +999,9 @@ class Installer { // Configure IDEs and copy documentation if (!config.skipIde && config.ides && config.ides.length > 0) { + // Ensure IDE manager is initialized (handlers may not be loaded in quick update flow) + await this.ideManager.ensureInitialized(); + // Filter out any undefined/null values from the IDE list const validIdes = config.ides.filter((ide) => ide && typeof ide === 'string'); diff --git a/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js b/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js index 4c816ae4..0e54ad89 100644 --- a/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +++ b/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js @@ -76,7 +76,7 @@ description: '${description.replaceAll("'", "''")}' # ${item.displayName || item.name} -LOAD and execute the ${type} at: ${itemPath} +Read the entire ${type} file at: ${itemPath} Follow all instructions in the ${type} file exactly as written. `; diff --git a/tools/cli/installers/lib/ide/templates/combined/antigravity.md b/tools/cli/installers/lib/ide/templates/combined/antigravity.md index cbb3dd4e..88e806e9 100644 --- a/tools/cli/installers/lib/ide/templates/combined/antigravity.md +++ b/tools/cli/installers/lib/ide/templates/combined/antigravity.md @@ -1,6 +1,8 @@ +--- name: '{{name}}' description: '{{description}}' +--- -LOAD and execute the workflow at: {project-root}/_bmad/{{workflow_path}} +Read the entire workflow file at: {project-root}/_bmad/{{workflow_path}} Follow all instructions in the workflow file exactly as written. diff --git a/tools/cli/installers/lib/ide/templates/combined/rovodev.md b/tools/cli/installers/lib/ide/templates/combined/rovodev.md index a46b811d..066945ee 100644 --- a/tools/cli/installers/lib/ide/templates/combined/rovodev.md +++ b/tools/cli/installers/lib/ide/templates/combined/rovodev.md @@ -4,6 +4,6 @@ --- -LOAD and execute the workflow at: {project-root}/_bmad/{{workflow_path}} +Read the entire workflow file at: {project-root}/_bmad/{{workflow_path}} Follow all instructions in the workflow file exactly as written. diff --git a/tools/cli/installers/lib/ide/templates/combined/trae.md b/tools/cli/installers/lib/ide/templates/combined/trae.md index c4357874..b4d43d7a 100644 --- a/tools/cli/installers/lib/ide/templates/combined/trae.md +++ b/tools/cli/installers/lib/ide/templates/combined/trae.md @@ -4,6 +4,6 @@ ## Instructions -LOAD and execute the workflow at: {project-root}/_bmad/{{workflow_path}} +Read the entire workflow file at: {project-root}/_bmad/{{workflow_path}} Follow all instructions in the workflow file exactly as written. diff --git a/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md b/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md index d61b819a..6366425c 100644 --- a/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md +++ b/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md @@ -5,6 +5,6 @@ auto_execution_mode: "iterate" # {{name}} -LOAD and execute the workflow at: {project-root}/_bmad/{{workflow_path}} +Read the entire workflow file at {project-root}/_bmad/{{workflow_path}} Follow all instructions in the workflow file exactly as written. diff --git a/tools/cli/lib/ui.js b/tools/cli/lib/ui.js index dc12d4d5..da5420cb 100644 --- a/tools/cli/lib/ui.js +++ b/tools/cli/lib/ui.js @@ -81,7 +81,7 @@ class UI { hasLegacyCfg = bmadResult.hasLegacyCfg; } - // Handle legacy .bmad or _cfg folder - these are very old (more than 2 versions behind) + // Handle legacy .bmad or _cfg folder - these are very old (v4 or alpha) // Show version warning instead of offering conversion if (hasLegacyBmadFolder || hasLegacyCfg) { console.log(''); @@ -92,9 +92,8 @@ class UI { 'Found a ".bmad"/"bmad" folder, or a legacy "_cfg" folder under the bmad folder - this is from a old BMAD version that is out of date for automatic upgrade, manual intervention required.', ), ); - console.log(chalk.yellow('This version is more than 2 alpha versions behind current.')); + console.log(chalk.yellow('You have a legacy version installed (v4 or alpha).')); console.log(''); - console.log(chalk.dim('For stability, we only support updates from the previous 2 alpha versions.')); console.log(chalk.dim('Legacy installations may have compatibility issues.')); console.log(''); console.log(chalk.dim('For the best experience, we strongly recommend:')); @@ -188,8 +187,8 @@ class UI { const currentVersion = require(packageJsonPath).version; const installedVersion = existingInstall.version || 'unknown'; - // Check if version is too old and warn user - const shouldProceed = await this.showOldAlphaVersionWarning(installedVersion, currentVersion, path.basename(bmadDir)); + // Check if version is pre beta + const shouldProceed = await this.showLegacyVersionWarning(installedVersion, currentVersion, path.basename(bmadDir)); // If user chose to cancel, exit the installer if (!shouldProceed) { @@ -1457,96 +1456,40 @@ class UI { } /** - * Parse alpha version string (e.g., "6.0.0-Alpha.20") - * @param {string} version - Version string - * @returns {Object|null} Object with alphaNumber and fullVersion, or null if invalid - */ - parseAlphaVersion(version) { - if (!version || version === 'unknown') { - return null; - } - - // Remove 'v' prefix if present - const cleanVersion = version.toString().replace(/^v/i, ''); - - // Match alpha version pattern: X.Y.Z-Alpha.N (case-insensitive) - const match = cleanVersion.match(/[\d.]+-Alpha\.(\d+)/i); - - if (!match) { - return null; - } - - return { - alphaNumber: parseInt(match[1], 10), - fullVersion: cleanVersion, - }; - } - - /** - * Check if installed version is more than 2 alpha versions behind current + * Check if installed version is a legacy version that needs fresh install * @param {string} installedVersion - The installed version - * @param {string} currentVersion - The current version - * @returns {Object} Object with { isOldVersion, versionDiff, shouldWarn, installed, current } + * @returns {boolean} True if legacy (v4 or any alpha) */ - checkAlphaVersionAge(installedVersion, currentVersion) { - const installed = this.parseAlphaVersion(installedVersion); - const current = this.parseAlphaVersion(currentVersion); - - // If we can't parse either version, don't warn - if (!installed || !current) { - return { isOldVersion: false, versionDiff: 0, shouldWarn: false }; + isLegacyVersion(installedVersion) { + if (!installedVersion || installedVersion === 'unknown') { + return true; // Treat unknown as legacy for safety } - - // Calculate alpha version difference - const versionDiff = current.alphaNumber - installed.alphaNumber; - - // Consider it old if more than 2 versions behind - const isOldVersion = versionDiff > 2; - - return { - isOldVersion, - versionDiff, - shouldWarn: isOldVersion, - installed: installed.fullVersion, - current: current.fullVersion, - installedAlpha: installed.alphaNumber, - currentAlpha: current.alphaNumber, - }; + // Check if version string contains -alpha or -Alpha (any v6 alpha) + return /-alpha\./i.test(installedVersion); } /** - * Show warning for old alpha version and ask if user wants to proceed + * Show warning for legacy version (v4 or alpha) and ask if user wants to proceed * @param {string} installedVersion - The installed version * @param {string} currentVersion - The current version * @param {string} bmadFolderName - Name of the BMAD folder * @returns {Promise} True if user wants to proceed, false if they cancel */ - async showOldAlphaVersionWarning(installedVersion, currentVersion, bmadFolderName) { - const versionInfo = this.checkAlphaVersionAge(installedVersion, currentVersion); - - // Also warn if version is unknown or can't be parsed (legacy/unsupported) - const isUnknownVersion = installedVersion === 'unknown' || !versionInfo.installed; - - if (!versionInfo.shouldWarn && !isUnknownVersion) { - return true; // Not old, proceed + async showLegacyVersionWarning(installedVersion, currentVersion, bmadFolderName) { + if (!this.isLegacyVersion(installedVersion)) { + return true; // Not legacy, proceed } console.log(''); console.log(chalk.yellow.bold('⚠️ VERSION WARNING')); console.log(chalk.yellow('─'.repeat(80))); - if (isUnknownVersion) { + if (installedVersion === 'unknown') { console.log(chalk.yellow('Unable to detect your installed BMAD version.')); console.log(chalk.yellow('This appears to be a legacy or unsupported installation.')); - console.log(''); - console.log(chalk.dim('For stability, we only support updates from the previous 2 alpha versions.')); - console.log(chalk.dim('Legacy installations may have compatibility issues.')); } else { - console.log(chalk.yellow(`You are updating from ${versionInfo.installed} to ${versionInfo.current}.`)); - console.log(chalk.yellow(`This is ${versionInfo.versionDiff} alpha versions behind.`)); - console.log(''); - console.log(chalk.dim(`For stability, we only support updates from the previous 2 alpha versions`)); - console.log(chalk.dim(`(Alpha.${versionInfo.currentAlpha - 2} through Alpha.${versionInfo.currentAlpha - 1}).`)); + console.log(chalk.yellow(`You are updating from ${installedVersion} to ${currentVersion}.`)); + console.log(chalk.yellow('You have a legacy version installed (v4 or alpha).')); } console.log('');