bmad-enhanced 1.3.7 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,7 @@
2
2
 
3
3
  const fs = require('fs-extra');
4
4
  const path = require('path');
5
+ const { refreshInstallation } = require('./update/lib/refresh-installation');
5
6
 
6
7
  const BOLD = '\x1b[1m';
7
8
  const RESET = '\x1b[0m';
@@ -17,200 +18,84 @@ function printBanner() {
17
18
  console.log(`${MAGENTA}${BOLD}║ ║${RESET}`);
18
19
  console.log(`${MAGENTA}${BOLD}║ BMAD-Enhanced Complete Installer 🚀 ║${RESET}`);
19
20
  console.log(`${MAGENTA}${BOLD}║ ║${RESET}`);
20
- console.log(`${MAGENTA}${BOLD}║ Installing Emma + Wade Design Agents ║${RESET}`);
21
+ console.log(`${MAGENTA}${BOLD}║ Installing Emma + Wade Vortex Agents ║${RESET}`);
21
22
  console.log(`${MAGENTA}${BOLD}║ ║${RESET}`);
22
23
  console.log(`${MAGENTA}${BOLD}╚════════════════════════════════════════════════════╝${RESET}`);
23
24
  console.log('');
24
25
  }
25
26
 
26
- function checkPrerequisites() {
27
+ function checkPrerequisites(projectRoot) {
27
28
  console.log(`${CYAN}[1/6]${RESET} Checking prerequisites...`);
28
29
 
29
- const targetDir = process.cwd();
30
- const bmadDir = path.join(targetDir, '_bmad');
30
+ const bmadDir = path.join(projectRoot, '_bmad');
31
31
 
32
- // Check if BMAD Method is installed
32
+ // Create _bmad directory if it doesn't exist
33
33
  if (!fs.existsSync(bmadDir)) {
34
- console.log('');
35
- console.error(`${RED}${BOLD}✗ BMAD Method not found!${RESET}`);
36
- console.log('');
37
- console.log(`${YELLOW}BMAD-Enhanced requires BMAD Method to be installed first.${RESET}`);
38
- console.log('');
39
- console.log('Please install BMAD Method:');
40
- console.log(` ${CYAN}npx bmad-method@alpha install${RESET}`);
41
- console.log('');
42
- console.log('Then run this installer again.');
43
- console.log('');
44
- process.exit(1);
34
+ console.log(`${YELLOW} ⚠${RESET} _bmad directory not found - creating it`);
35
+ fs.mkdirSync(bmadDir, { recursive: true });
36
+ } else {
37
+ console.log(`${GREEN} ✓${RESET} BMAD directory detected`);
45
38
  }
46
39
 
47
- console.log(`${GREEN} ✓${RESET} BMAD Method detected`);
48
-
49
- // Check for BMAD version/compatibility (optional but recommended)
40
+ // Check for BMAD Method configuration (optional)
50
41
  const bmadConfigPath = path.join(bmadDir, '_config', 'bmad.yaml');
51
42
  if (fs.existsSync(bmadConfigPath)) {
52
- console.log(`${GREEN} ✓${RESET} BMAD configuration found`);
43
+ console.log(`${GREEN} ✓${RESET} BMAD Method configuration found`);
53
44
  } else {
54
- console.log(`${YELLOW} ⚠${RESET} BMAD configuration not found (continuing anyway)`);
45
+ console.log(`${YELLOW} ⚠${RESET} BMAD Method not detected (BMAD-Enhanced will install standalone)`);
55
46
  }
56
47
 
57
48
  console.log(`${GREEN} ✓${RESET} Prerequisites met`);
58
49
  }
59
50
 
60
- function copyAllAgentFiles() {
61
- console.log(`${CYAN}[2/6]${RESET} Installing Emma + Wade agent files...`);
51
+ function archiveDeprecatedWorkflows(projectRoot) {
52
+ console.log(`${CYAN}[2/6]${RESET} Archiving deprecated workflows...`);
62
53
 
63
54
  const sourceDir = path.join(__dirname, '..', '_bmad', 'bme', '_vortex');
64
- const targetDir = path.join(process.cwd(), '_bmad', 'bme', '_vortex');
65
-
66
- // Create target directory structure
67
- fs.mkdirSync(path.join(targetDir, 'agents'), { recursive: true });
68
- fs.mkdirSync(path.join(targetDir, 'workflows', '_deprecated', 'empathy-map', 'steps'), { recursive: true });
69
- fs.mkdirSync(path.join(targetDir, 'workflows', '_deprecated', 'wireframe', 'steps'), { recursive: true });
70
-
71
- // Copy Emma agent file
72
- console.log(`${CYAN} →${RESET} Installing Emma (contextualization-expert)...`);
73
- fs.copyFileSync(
74
- path.join(sourceDir, 'agents', 'contextualization-expert.md'),
75
- path.join(targetDir, 'agents', 'contextualization-expert.md')
76
- );
77
-
78
- // Copy Emma workflow files
79
- const emmaWorkflowFiles = [
80
- 'workflow.md',
81
- 'empathy-map.template.md',
82
- 'steps/step-01-define-user.md',
83
- 'steps/step-02-says-thinks.md',
84
- 'steps/step-03-does-feels.md',
85
- 'steps/step-04-pain-points.md',
86
- 'steps/step-05-gains.md',
87
- 'steps/step-06-synthesize.md'
88
- ];
89
-
90
- emmaWorkflowFiles.forEach(file => {
91
- fs.copyFileSync(
92
- path.join(sourceDir, 'workflows', '_deprecated', 'empathy-map', file),
93
- path.join(targetDir, 'workflows', '_deprecated', 'empathy-map', file)
94
- );
95
- });
96
-
97
- console.log(`${GREEN} ✓${RESET} Emma installed`);
98
-
99
- // Copy Wade agent file
100
- console.log(`${CYAN} →${RESET} Installing Wade (lean-experiments-specialist)...`);
101
- fs.copyFileSync(
102
- path.join(sourceDir, 'agents', 'lean-experiments-specialist.md'),
103
- path.join(targetDir, 'agents', 'lean-experiments-specialist.md')
104
- );
105
-
106
- // Copy Wade workflow files
107
- const wadeWorkflowFiles = [
108
- 'workflow.md',
109
- 'wireframe.template.md',
110
- 'steps/step-01-define-requirements.md',
111
- 'steps/step-02-user-flows.md',
112
- 'steps/step-03-information-architecture.md',
113
- 'steps/step-04-wireframe-sketch.md',
114
- 'steps/step-05-components.md',
115
- 'steps/step-06-synthesize.md'
116
- ];
117
-
118
- wadeWorkflowFiles.forEach(file => {
119
- fs.copyFileSync(
120
- path.join(sourceDir, 'workflows', '_deprecated', 'wireframe', file),
121
- path.join(targetDir, 'workflows', '_deprecated', 'wireframe', file)
122
- );
123
- });
55
+ const targetDir = path.join(projectRoot, '_bmad', 'bme', '_vortex');
124
56
 
125
- console.log(`${GREEN} ✓${RESET} Wade installed`);
126
-
127
- // Copy all 7 new workflow directories
128
- console.log(`${CYAN} →${RESET} Installing Vortex Framework workflows...`);
129
- const workflows = [
130
- 'lean-persona',
131
- 'product-vision',
132
- 'contextualize-scope',
133
- 'mvp',
134
- 'lean-experiment',
135
- 'proof-of-concept',
136
- 'proof-of-value'
137
- ];
57
+ // Create deprecated workflow archive directories
58
+ const deprecatedWorkflows = ['empathy-map', 'wireframe'];
138
59
 
139
- workflows.forEach(workflow => {
140
- const workflowSourceDir = path.join(sourceDir, 'workflows', workflow);
141
- const workflowTargetDir = path.join(targetDir, 'workflows', workflow);
60
+ for (const workflow of deprecatedWorkflows) {
61
+ const workflowSourceDir = path.join(sourceDir, 'workflows', '_deprecated', workflow);
62
+ const workflowTargetDir = path.join(targetDir, 'workflows', '_deprecated', workflow);
142
63
 
143
64
  if (fs.existsSync(workflowSourceDir)) {
144
65
  fs.copySync(workflowSourceDir, workflowTargetDir);
145
- console.log(`${GREEN} ✓${RESET} ${workflow}`);
146
- } else {
147
- console.log(`${YELLOW} ⚠${RESET} ${workflow} not found in package (skipping)`);
66
+ console.log(`${GREEN} ✓${RESET} Archived ${workflow} to _deprecated/`);
148
67
  }
149
- });
68
+ }
150
69
 
151
- console.log(`${GREEN} ✓${RESET} All workflows installed`);
70
+ // Legacy cleanup
71
+ cleanupLegacyFiles(projectRoot);
152
72
  }
153
73
 
154
- function updateConfig() {
155
- console.log(`${CYAN}[3/6]${RESET} Configuring agents...`);
156
-
157
- const configPath = path.join(process.cwd(), '_bmad', 'bme', '_vortex', 'config.yaml');
158
- const manifestPath = path.join(process.cwd(), '_bmad', '_config', 'agent-manifest.csv');
159
-
160
- console.log(`${CYAN} →${RESET} Config path: ${configPath}`);
161
-
162
- // Create config
163
- const configContent = `---
164
- submodule_name: _vortex
165
- description: Contextualize and Externalize streams - Strategic framing and validated learning
166
- module: bme
167
- version: 1.3.7
168
-
169
- # Output Configuration
170
- output_folder: "{project-root}/_bmad-output/vortex-artifacts"
171
- user_name: "{user}"
172
- communication_language: "en"
173
-
174
- # Agents in this submodule
175
- agents:
176
- - contextualization-expert # Emma - Contextualization Expert
177
- - lean-experiments-specialist # Wade - Lean Experiments Specialist
178
-
179
- # Workflows available
180
- workflows:
181
- # Emma - Contextualize Stream
182
- - lean-persona # Create lean user personas
183
- - product-vision # Define product vision
184
- - contextualize-scope # Decide which problem space to investigate
185
-
186
- # Wade - Externalize Stream
187
- - mvp # Design Minimum Viable Product
188
- - lean-experiment # Run Build-Measure-Learn cycle
189
- - proof-of-concept # Validate technical feasibility
190
- - proof-of-value # Validate business value
191
-
192
- # Integration
193
- party_mode_enabled: true
194
- core_module: bme
195
- `;
74
+ function cleanupLegacyFiles(projectRoot) {
75
+ console.log(`${CYAN} →${RESET} Cleaning up legacy files...`);
196
76
 
197
- try {
198
- fs.mkdirSync(path.dirname(configPath), { recursive: true });
199
- fs.writeFileSync(configPath, configContent);
77
+ // Remove _designos directory (pre-Vortex structure) from all possible locations
78
+ const legacyPaths = [
79
+ path.join(projectRoot, '_bmad', 'bme', '_designos'),
80
+ path.join(projectRoot, '_bmad', '_designos'),
81
+ ];
200
82
 
201
- // Verify file was created
202
- if (fs.existsSync(configPath)) {
203
- console.log(`${GREEN} ✓${RESET} Created config.yaml`);
204
- } else {
205
- console.error(`${RED} ✗${RESET} Config file not found after write!`);
83
+ for (const legacyPath of legacyPaths) {
84
+ if (fs.existsSync(legacyPath)) {
85
+ fs.removeSync(legacyPath);
86
+ console.log(`${GREEN} ✓${RESET} Removed legacy directory: ${path.relative(projectRoot, legacyPath)}`);
206
87
  }
207
- } catch (error) {
208
- console.error(`${RED} ✗${RESET} Error creating config.yaml:`, error.message);
209
- throw error;
210
88
  }
211
89
 
212
- // Create manifest
90
+ console.log(`${GREEN} ✓${RESET} Legacy cleanup complete`);
91
+ }
92
+
93
+ function createAgentManifest(projectRoot) {
94
+ console.log(`${CYAN}[3/6]${RESET} Creating agent manifest...`);
95
+
96
+ const manifestPath = path.join(projectRoot, '_bmad', '_config', 'agent-manifest.csv');
213
97
  fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
98
+
214
99
  const header = '"agent_id","name","title","icon","role","identity","communication_style","expertise","submodule","path"\n';
215
100
  const emmaRow = '"contextualization-expert","Emma","Contextualization Expert","🎯","Strategic Framing + Problem-Product Space Navigator","Expert in helping teams contextualize their product strategy by defining clear problem spaces and validating assumptions. Specializes in Lean Startup methodologies, persona creation, and product vision framing. Guides teams through the critical \'Contextualize\' stream of the Vortex framework.","Strategic yet approachable - speaks in frameworks and validated learning. Like a product strategist who asks \'What are we really solving?\' and \'Who is this truly for?\' Uses Lean Startup language (hypotheses, assumptions, pivots) and focuses on clarity before action.","- Master of Lean Startup and strategic framing methodologies - Personas over demographics - focus on jobs-to-be-done and problem contexts - Vision before features - align team around the \'why\' before the \'what\' - Challenge assumptions - every belief is a hypothesis until validated - Problem-solution fit comes before product-market fit","bme","_bmad/bme/_vortex/agents/contextualization-expert.md"\n';
216
101
  const wadeRow = '"lean-experiments-specialist","Wade","Lean Experiments Specialist","🧪","Lean Startup + Validated Learning Expert","Lean Startup practitioner specialized in running rapid experiments to validate product hypotheses. Helps teams move from assumptions to evidence through Build-Measure-Learn cycles. Guides teams through the \'Externalize\' stream - taking ideas into the real world to test with actual users.","Experimental and evidence-driven - speaks in hypotheses, metrics, and learning. Like a scientist who says \'Let\'s test that assumption\' and \'What would prove us wrong?\' Uses Lean language (MVPs, pivots, validated learning) and focuses on speed-to-insight over perfection.","- Master of Lean Startup and rapid experimentation - Build the smallest thing that tests the riskiest assumption - Measure what matters - focus on actionable metrics, not vanity metrics - Learn fast, pivot faster - every experiment teaches something - Proof-of-concept before proof-of-value - validate feasibility before business case - Fail fast is good, learn fast is better","bme","_bmad/bme/_vortex/agents/lean-experiments-specialist.md"\n';
@@ -218,30 +103,27 @@ core_module: bme
218
103
  console.log(`${GREEN} ✓${RESET} Created agent-manifest.csv`);
219
104
  }
220
105
 
221
- function createOutputDirectory() {
106
+ function createOutputDirectory(projectRoot) {
222
107
  console.log(`${CYAN}[4/6]${RESET} Setting up output directory...`);
223
108
 
224
- const outputDir = path.join(process.cwd(), '_bmad-output', 'vortex-artifacts');
109
+ const outputDir = path.join(projectRoot, '_bmad-output', 'vortex-artifacts');
225
110
  fs.mkdirSync(outputDir, { recursive: true });
226
111
 
227
112
  console.log(`${GREEN} ✓${RESET} Output directory ready`);
228
113
  }
229
114
 
230
- function verifyInstallation() {
231
- console.log(`${CYAN}[5/6]${RESET} Verifying installation...`);
115
+ function verifyInstallation(projectRoot) {
116
+ console.log(`${CYAN}[6/6]${RESET} Verifying installation...`);
232
117
 
233
- const targetDir = process.cwd();
234
118
  const checks = [
235
119
  { path: '_bmad/bme/_vortex/agents/contextualization-expert.md', name: 'Emma agent file' },
236
120
  { path: '_bmad/bme/_vortex/agents/lean-experiments-specialist.md', name: 'Wade agent file' },
237
- { path: '_bmad/bme/_vortex/workflows/_deprecated/empathy-map/workflow.md', name: 'Emma workflow (legacy)' },
238
- { path: '_bmad/bme/_vortex/workflows/_deprecated/wireframe/workflow.md', name: 'Wade workflow (legacy)' },
239
121
  { path: '_bmad/bme/_vortex/config.yaml', name: 'Configuration file' },
240
122
  ];
241
123
 
242
124
  let allChecksPass = true;
243
125
  checks.forEach(check => {
244
- const fullPath = path.join(targetDir, check.path);
126
+ const fullPath = path.join(projectRoot, check.path);
245
127
  if (fs.existsSync(fullPath)) {
246
128
  console.log(`${GREEN} ✓${RESET} ${check.name}`);
247
129
  } else {
@@ -259,24 +141,6 @@ function verifyInstallation() {
259
141
  console.log(`${GREEN} ✓${RESET} All files installed successfully`);
260
142
  }
261
143
 
262
- function copyUserGuides() {
263
- console.log(`${CYAN}[6/6]${RESET} Installing user guides...`);
264
-
265
- const sourceDir = path.join(__dirname, '..', '_bmad-output', 'vortex-artifacts');
266
- const targetDir = path.join(process.cwd(), '_bmad-output', 'vortex-artifacts');
267
-
268
- // Copy user guides if they exist
269
- const guides = ['EMMA-USER-GUIDE.md', 'WADE-USER-GUIDE.md'];
270
- guides.forEach(guide => {
271
- const sourcePath = path.join(sourceDir, guide);
272
- if (fs.existsSync(sourcePath)) {
273
- fs.copyFileSync(sourcePath, path.join(targetDir, guide));
274
- }
275
- });
276
-
277
- console.log(`${GREEN} ✓${RESET} User guides installed`);
278
- }
279
-
280
144
  function printSuccess() {
281
145
  console.log('');
282
146
  console.log(`${GREEN}${BOLD}╔════════════════════════════════════════════════════╗${RESET}`);
@@ -298,51 +162,24 @@ function printSuccess() {
298
162
  console.log(' Activate Wade:');
299
163
  console.log(` ${CYAN}cat _bmad/bme/_vortex/agents/lean-experiments-specialist.md${RESET}`);
300
164
  console.log('');
301
- console.log(`${YELLOW}Note: User guides being updated for v1.2.0${RESET}`);
302
- console.log('');
303
- }
304
-
305
- function cleanupLegacyFiles() {
306
- console.log(`${CYAN} →${RESET} Cleaning up legacy files...`);
307
-
308
- // Remove _designos directory (pre-Vortex structure) from all possible locations
309
- const legacyPaths = [
310
- path.join(process.cwd(), '_bmad', 'bme', '_designos'),
311
- path.join(process.cwd(), '_bmad', '_designos'),
312
- ];
313
-
314
- for (const legacyPath of legacyPaths) {
315
- if (fs.existsSync(legacyPath)) {
316
- fs.removeSync(legacyPath);
317
- console.log(`${GREEN} ✓${RESET} Removed legacy directory: ${path.relative(process.cwd(), legacyPath)}`);
318
- }
319
- }
320
-
321
- // Remove deprecated agent files from _vortex/agents
322
- const agentsDir = path.join(process.cwd(), '_bmad', 'bme', '_vortex', 'agents');
323
- const deprecatedAgents = ['empathy-mapper.md', 'wireframe-designer.md'];
324
-
325
- for (const agent of deprecatedAgents) {
326
- const agentPath = path.join(agentsDir, agent);
327
- if (fs.existsSync(agentPath)) {
328
- fs.removeSync(agentPath);
329
- console.log(`${GREEN} ✓${RESET} Removed deprecated agent: ${agent}`);
330
- }
331
- }
332
-
333
- console.log(`${GREEN} ✓${RESET} Legacy cleanup complete`);
334
165
  }
335
166
 
336
167
  async function main() {
337
168
  try {
169
+ const projectRoot = process.cwd();
170
+
338
171
  printBanner();
339
- checkPrerequisites();
340
- copyAllAgentFiles();
341
- cleanupLegacyFiles();
342
- updateConfig();
343
- createOutputDirectory();
344
- verifyInstallation();
345
- copyUserGuides();
172
+ checkPrerequisites(projectRoot);
173
+ archiveDeprecatedWorkflows(projectRoot);
174
+ createAgentManifest(projectRoot);
175
+ createOutputDirectory(projectRoot);
176
+
177
+ // Use refreshInstallation for agents, workflows, config, and user guides
178
+ console.log(`${CYAN}[5/6]${RESET} Installing agents, workflows, config, and guides...`);
179
+ await refreshInstallation(projectRoot, { backupGuides: false });
180
+ console.log(`${GREEN} ✓${RESET} Installation refreshed`);
181
+
182
+ verifyInstallation(projectRoot);
346
183
  printSuccess();
347
184
  } catch (error) {
348
185
  console.error(`${RED}✗ Installation failed:${RESET}`, error.message);
@@ -27,9 +27,12 @@ async function main() {
27
27
  const versionDetector = require('./update/lib/version-detector');
28
28
  const registry = require('./update/migrations/registry');
29
29
 
30
- const currentVersion = versionDetector.getCurrentVersion();
30
+ const { findProjectRoot, compareVersions } = require('./update/lib/utils');
31
+ const projectRoot = findProjectRoot();
32
+
33
+ const currentVersion = versionDetector.getCurrentVersion(projectRoot);
31
34
  const targetVersion = versionDetector.getTargetVersion();
32
- const scenario = versionDetector.detectInstallationScenario();
35
+ const scenario = versionDetector.detectInstallationScenario(projectRoot);
33
36
 
34
37
  // Fresh install
35
38
  if (scenario === 'fresh' || !currentVersion) {
@@ -52,7 +55,7 @@ async function main() {
52
55
  }
53
56
 
54
57
  // Upgrade detected
55
- if (versionDetector.compareVersions(currentVersion, targetVersion) < 0) {
58
+ if (compareVersions(currentVersion, targetVersion) < 0) {
56
59
  console.log(`${YELLOW}${BOLD}⚠ UPGRADE DETECTED${RESET}`);
57
60
  console.log('');
58
61
  console.log(` Current version: ${RED}${currentVersion}${RESET}`);
@@ -60,7 +63,7 @@ async function main() {
60
63
  console.log('');
61
64
 
62
65
  // Check for breaking changes
63
- const breakingChanges = registry.getBreakingChanges(currentVersion, targetVersion);
66
+ const breakingChanges = registry.getBreakingChanges(currentVersion);
64
67
  if (breakingChanges.length > 0) {
65
68
  console.log(`${RED}${BOLD} ⚠ Breaking changes detected!${RESET}`);
66
69
  console.log('');
@@ -83,7 +86,7 @@ async function main() {
83
86
  }
84
87
 
85
88
  // Downgrade (shouldn't happen normally)
86
- if (versionDetector.compareVersions(currentVersion, targetVersion) > 0) {
89
+ if (compareVersions(currentVersion, targetVersion) > 0) {
87
90
  console.log(`${YELLOW}Note: Package version (${targetVersion}) is older than installed version (${currentVersion})${RESET}`);
88
91
  console.log('');
89
92
  return;
@@ -95,8 +98,8 @@ async function main() {
95
98
  console.log(` ${CYAN}npx bmad-install-agents${RESET} - Install all agents (Emma + Wade)`);
96
99
  console.log('');
97
100
  console.log('Or install individually:');
98
- console.log(` ${CYAN}npx bmad-install-emma${RESET} - Install Emma (empathy-mapper)`);
99
- console.log(` ${CYAN}npx bmad-install-wade${RESET} - Install Wade (wireframe-designer)`);
101
+ console.log(` ${CYAN}npx bmad-install-emma${RESET} - Install Emma (contextualization-expert)`);
102
+ console.log(` ${CYAN}npx bmad-install-wade${RESET} - Install Wade (lean-experiments-specialist)`);
100
103
  console.log('');
101
104
  }
102
105
  }
@@ -2,6 +2,9 @@
2
2
 
3
3
  const chalk = require('chalk');
4
4
  const registry = require('./migrations/registry');
5
+ const backupManager = require('./lib/backup-manager');
6
+ const { refreshInstallation } = require('./lib/refresh-installation');
7
+ const { findProjectRoot } = require('./lib/utils');
5
8
 
6
9
  /**
7
10
  * BMAD-Enhanced Migrate CLI
@@ -11,6 +14,15 @@ const registry = require('./migrations/registry');
11
14
  async function main() {
12
15
  const args = process.argv.slice(2);
13
16
 
17
+ // Validate project root
18
+ const projectRoot = findProjectRoot();
19
+ if (!projectRoot) {
20
+ console.error('');
21
+ console.error(chalk.red('Not in a BMAD project. Could not find _bmad/ directory.'));
22
+ console.error('');
23
+ process.exit(1);
24
+ }
25
+
14
26
  // No args - show available migrations
15
27
  if (args.length === 0) {
16
28
  showAvailableMigrations();
@@ -32,6 +44,15 @@ async function main() {
32
44
  process.exit(1);
33
45
  }
34
46
 
47
+ // Check if already applied
48
+ const configPath = require('path').join(projectRoot, '_bmad/bme/_vortex/config.yaml');
49
+ if (registry.hasMigrationBeenApplied(migrationName, configPath)) {
50
+ console.log('');
51
+ console.log(chalk.yellow(`Migration '${migrationName}' has already been applied.`));
52
+ console.log('');
53
+ process.exit(0);
54
+ }
55
+
35
56
  // Load migration module
36
57
  if (!migration.module) {
37
58
  try {
@@ -44,29 +65,61 @@ async function main() {
44
65
  }
45
66
  }
46
67
 
47
- // Run migration
68
+ // Run migration with backup and refresh
48
69
  console.log('');
49
70
  console.log(chalk.cyan.bold(`Running migration: ${migration.name}`));
50
71
  console.log(chalk.gray(migration.description));
51
72
  console.log('');
52
73
 
74
+ let backupMetadata = null;
75
+
53
76
  try {
54
- const changes = await migration.module.apply();
77
+ // Create backup before running delta
78
+ console.log(chalk.cyan('Creating backup...'));
79
+ backupMetadata = await backupManager.createBackup('manual', projectRoot);
80
+ console.log(chalk.green(`✓ Backup created: ${require('path').basename(backupMetadata.backup_dir)}`));
81
+ console.log('');
82
+
83
+ // Run the delta
84
+ const changes = await migration.module.apply(projectRoot);
55
85
 
56
86
  console.log('');
57
- console.log(chalk.green.bold('✓ Migration completed'));
87
+ console.log(chalk.green.bold('✓ Migration delta completed'));
58
88
  console.log('');
59
- console.log(chalk.cyan('Changes:'));
89
+ console.log(chalk.cyan('Delta changes:'));
60
90
  changes.forEach(change => {
61
91
  console.log(chalk.gray(` - ${change}`));
62
92
  });
63
93
  console.log('');
64
94
 
95
+ // Refresh installation after delta
96
+ console.log(chalk.cyan('Refreshing installation files...'));
97
+ const refreshChanges = await refreshInstallation(projectRoot);
98
+ console.log(chalk.green('✓ Installation refreshed'));
99
+ console.log('');
100
+
65
101
  } catch (error) {
66
102
  console.error('');
67
103
  console.error(chalk.red.bold('✗ Migration failed'));
68
104
  console.error(chalk.red(error.message));
69
105
  console.error('');
106
+
107
+ // Rollback if we have a backup
108
+ if (backupMetadata) {
109
+ console.log(chalk.yellow('Restoring from backup...'));
110
+ try {
111
+ await backupManager.restoreBackup(backupMetadata, projectRoot);
112
+ console.log(chalk.green('✓ Installation restored from backup'));
113
+ console.log('');
114
+ } catch (restoreError) {
115
+ console.error(chalk.red('✗ Restore failed!'));
116
+ console.error(chalk.red(restoreError.message));
117
+ console.error('');
118
+ console.error(chalk.yellow(`Manual restore may be needed from: ${backupMetadata.backup_dir}`));
119
+ console.error('');
120
+ }
121
+ }
122
+
70
123
  if (error.stack) {
71
124
  console.error(chalk.gray(error.stack));
72
125
  console.error('');
@@ -95,7 +148,7 @@ function showAvailableMigrations() {
95
148
  const breaking = m.breaking ? chalk.red('[BREAKING]') : chalk.green('[SAFE]');
96
149
  console.log(` ${index + 1}. ${chalk.cyan(m.name)} ${breaking}`);
97
150
  console.log(` ${chalk.gray(m.description)}`);
98
- console.log(` ${chalk.gray(`${m.fromVersion} ${m.toVersion}`)}`);
151
+ console.log(` ${chalk.gray(`From: ${m.fromVersion}`)}`);
99
152
  console.log('');
100
153
  });
101
154
 
@@ -5,6 +5,7 @@ const chalk = require('chalk');
5
5
  const versionDetector = require('./lib/version-detector');
6
6
  const migrationRunner = require('./lib/migration-runner');
7
7
  const registry = require('./migrations/registry');
8
+ const { findProjectRoot } = require('./lib/utils');
8
9
 
9
10
  /**
10
11
  * BMAD-Enhanced Update CLI
@@ -15,7 +16,6 @@ async function main() {
15
16
  const args = process.argv.slice(2);
16
17
  const dryRun = args.includes('--dry-run');
17
18
  const yes = args.includes('--yes') || args.includes('-y');
18
- const force = args.includes('--force');
19
19
  const verbose = args.includes('--verbose') || args.includes('-v');
20
20
 
21
21
  // Header
@@ -25,10 +25,20 @@ async function main() {
25
25
  console.log(chalk.bold.magenta('╚════════════════════════════════════════╝'));
26
26
  console.log('');
27
27
 
28
+ // Validate project root
29
+ const projectRoot = findProjectRoot();
30
+ if (!projectRoot) {
31
+ console.log(chalk.red('Not in a BMAD project. Could not find _bmad/ directory.'));
32
+ console.log('');
33
+ console.log('Run: ' + chalk.cyan('npx bmad-install-agents'));
34
+ console.log('');
35
+ process.exit(1);
36
+ }
37
+
28
38
  // 1. Detect current state
29
- const currentVersion = versionDetector.getCurrentVersion();
39
+ const currentVersion = versionDetector.getCurrentVersion(projectRoot);
30
40
  const targetVersion = versionDetector.getTargetVersion();
31
- const scenario = versionDetector.detectInstallationScenario();
41
+ const scenario = versionDetector.detectInstallationScenario(projectRoot);
32
42
 
33
43
  // Handle different scenarios
34
44
  if (scenario === 'fresh') {
@@ -88,7 +98,7 @@ async function main() {
88
98
  console.log(` To: ${chalk.green(targetVersion)}`);
89
99
  console.log('');
90
100
 
91
- const migrations = registry.getMigrationsFor(currentVersion, targetVersion);
101
+ const migrations = registry.getMigrationsFor(currentVersion);
92
102
 
93
103
  if (migrations.length === 0) {
94
104
  console.log(chalk.yellow('No migrations needed (versions compatible)'));
@@ -104,7 +114,7 @@ async function main() {
104
114
  console.log('');
105
115
 
106
116
  // 3. Show breaking changes warning
107
- const breakingChanges = registry.getBreakingChanges(currentVersion, targetVersion);
117
+ const breakingChanges = registry.getBreakingChanges(currentVersion);
108
118
  if (breakingChanges.length > 0) {
109
119
  console.log(chalk.red.bold('⚠ BREAKING CHANGES:'));
110
120
  breakingChanges.forEach(change => {
@@ -119,7 +129,7 @@ async function main() {
119
129
  console.log('');
120
130
 
121
131
  try {
122
- await migrationRunner.runMigrations(currentVersion, targetVersion, { dryRun: true, verbose });
132
+ await migrationRunner.runMigrations(currentVersion, { dryRun: true, verbose });
123
133
  } catch (error) {
124
134
  console.error(chalk.red('Error during preview:'), error.message);
125
135
  process.exit(1);
@@ -148,7 +158,7 @@ async function main() {
148
158
  console.log(chalk.cyan.bold('Starting migration...'));
149
159
 
150
160
  try {
151
- const result = await migrationRunner.runMigrations(currentVersion, targetVersion, { verbose });
161
+ const result = await migrationRunner.runMigrations(currentVersion, { verbose });
152
162
 
153
163
  // 7. Show success report
154
164
  console.log('');