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.
- package/README.md +103 -124
- package/package.json +1 -1
- package/scripts/install-all-agents.js +61 -224
- package/scripts/postinstall.js +10 -7
- package/scripts/update/bmad-migrate.js +58 -5
- package/scripts/update/bmad-update.js +17 -7
- package/scripts/update/bmad-version.js +20 -6
- package/scripts/update/lib/backup-manager.js +22 -58
- package/scripts/update/lib/config-merger.js +1 -35
- package/scripts/update/lib/migration-runner.js +78 -114
- package/scripts/update/lib/refresh-installation.js +132 -0
- package/scripts/update/lib/utils.js +96 -0
- package/scripts/update/lib/validator.js +31 -151
- package/scripts/update/lib/version-detector.js +36 -41
- package/scripts/update/migrations/1.0.x-to-1.3.0.js +41 -222
- package/scripts/update/migrations/1.1.x-to-1.3.0.js +7 -188
- package/scripts/update/migrations/1.2.x-to-1.3.0.js +7 -188
- package/scripts/update/migrations/registry.js +27 -52
|
@@ -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
|
|
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
|
|
30
|
-
const bmadDir = path.join(targetDir, '_bmad');
|
|
30
|
+
const bmadDir = path.join(projectRoot, '_bmad');
|
|
31
31
|
|
|
32
|
-
//
|
|
32
|
+
// Create _bmad directory if it doesn't exist
|
|
33
33
|
if (!fs.existsSync(bmadDir)) {
|
|
34
|
-
console.log(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
console.log(`${
|
|
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
|
-
|
|
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
|
|
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
|
|
61
|
-
console.log(`${CYAN}[2/6]${RESET}
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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}
|
|
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
|
-
|
|
70
|
+
// Legacy cleanup
|
|
71
|
+
cleanupLegacyFiles(projectRoot);
|
|
152
72
|
}
|
|
153
73
|
|
|
154
|
-
function
|
|
155
|
-
console.log(`${CYAN}
|
|
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
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
|
|
202
|
-
if (fs.existsSync(
|
|
203
|
-
|
|
204
|
-
}
|
|
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
|
-
|
|
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(
|
|
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}[
|
|
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(
|
|
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
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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);
|
package/scripts/postinstall.js
CHANGED
|
@@ -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
|
|
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 (
|
|
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
|
|
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 (
|
|
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 (
|
|
99
|
-
console.log(` ${CYAN}npx bmad-install-wade${RESET} - Install Wade (
|
|
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
|
-
|
|
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('
|
|
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(
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
161
|
+
const result = await migrationRunner.runMigrations(currentVersion, { verbose });
|
|
152
162
|
|
|
153
163
|
// 7. Show success report
|
|
154
164
|
console.log('');
|