bmad-enhanced 1.1.2 → 1.3.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 +178 -58
- package/package.json +7 -3
- package/scripts/install-all-agents.js +10 -12
- package/scripts/install-emma.js +5 -5
- package/scripts/install-wade.js +5 -5
- package/scripts/postinstall.js +100 -11
- package/scripts/update/bmad-migrate.js +116 -0
- package/scripts/update/bmad-update.js +206 -0
- package/scripts/update/bmad-version.js +94 -0
- package/scripts/update/lib/backup-manager.js +279 -0
- package/scripts/update/lib/config-merger.js +232 -0
- package/scripts/update/lib/migration-runner.js +402 -0
- package/scripts/update/lib/validator.js +430 -0
- package/scripts/update/lib/version-detector.js +246 -0
- package/scripts/update/migrations/1.0.x-to-1.3.0.js +265 -0
- package/scripts/update/migrations/1.1.x-to-1.3.0.js +166 -0
- package/scripts/update/migrations/1.2.x-to-1.3.0.js +166 -0
- package/scripts/update/migrations/registry.js +185 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const yaml = require('js-yaml');
|
|
6
|
+
const configMerger = require('../lib/config-merger');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Migration: 1.0.x → 1.3.0
|
|
10
|
+
* BREAKING CHANGES:
|
|
11
|
+
* - Workflow renamed: empathy-map → lean-persona
|
|
12
|
+
* - Agent roles updated in manifest
|
|
13
|
+
* - Template structure changed
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
name: '1.0.x-to-1.3.0',
|
|
18
|
+
fromVersion: '1.0.x',
|
|
19
|
+
toVersion: '1.3.0',
|
|
20
|
+
breaking: true,
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Preview changes without applying
|
|
24
|
+
* @returns {Promise<object>} Preview information
|
|
25
|
+
*/
|
|
26
|
+
async preview() {
|
|
27
|
+
return {
|
|
28
|
+
actions: [
|
|
29
|
+
'BREAKING: Move empathy-map workflow to _deprecated/',
|
|
30
|
+
'Install new lean-persona workflow',
|
|
31
|
+
'Install 6 new workflows (product-vision, contextualize-scope, mvp, lean-experiment, proof-of-concept, proof-of-value)',
|
|
32
|
+
'Update config.yaml: agents and workflows lists',
|
|
33
|
+
'Update agent-manifest.csv: agent names/roles',
|
|
34
|
+
'Update agent files (Emma → Contextualization Expert, Wade → Lean Experiments Specialist)',
|
|
35
|
+
'Preserve all user data in _bmad-output/'
|
|
36
|
+
]
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Apply the migration
|
|
42
|
+
* @returns {Promise<Array<string>>} List of changes made
|
|
43
|
+
*/
|
|
44
|
+
async apply() {
|
|
45
|
+
const changes = [];
|
|
46
|
+
const sourceDir = path.join(__dirname, '../../../_bmad/bme/_vortex');
|
|
47
|
+
const targetDir = path.join(process.cwd(), '_bmad/bme/_vortex');
|
|
48
|
+
|
|
49
|
+
// 1. Archive old empathy-map workflow (if exists)
|
|
50
|
+
await moveToDeprecated(targetDir, 'empathy-map');
|
|
51
|
+
changes.push('Archived empathy-map workflow to _deprecated/');
|
|
52
|
+
|
|
53
|
+
// 2. Archive wireframe workflow (if exists)
|
|
54
|
+
await moveToDeprecated(targetDir, 'wireframe');
|
|
55
|
+
changes.push('Archived wireframe workflow to _deprecated/');
|
|
56
|
+
|
|
57
|
+
// 3. Install all new workflow files
|
|
58
|
+
await copyAllWorkflows(sourceDir, targetDir);
|
|
59
|
+
changes.push('Installed 7 new Vortex Framework workflows');
|
|
60
|
+
|
|
61
|
+
// 4. Update config.yaml with new structure
|
|
62
|
+
await updateConfig(targetDir, '1.3.0');
|
|
63
|
+
changes.push('Updated config.yaml');
|
|
64
|
+
|
|
65
|
+
// 5. Update agent files
|
|
66
|
+
await copyAgentFiles(sourceDir, targetDir);
|
|
67
|
+
changes.push('Updated agent files');
|
|
68
|
+
|
|
69
|
+
// 6. Update agent manifest
|
|
70
|
+
await updateAgentManifest();
|
|
71
|
+
changes.push('Updated agent manifest');
|
|
72
|
+
|
|
73
|
+
// 7. Update user guides
|
|
74
|
+
await copyUserGuides();
|
|
75
|
+
changes.push('Updated user guides');
|
|
76
|
+
|
|
77
|
+
return changes;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Move workflow to _deprecated directory
|
|
83
|
+
* @param {string} targetDir - Target vortex directory
|
|
84
|
+
* @param {string} workflowName - Name of workflow to deprecate
|
|
85
|
+
*/
|
|
86
|
+
async function moveToDeprecated(targetDir, workflowName) {
|
|
87
|
+
const workflowsDir = path.join(targetDir, 'workflows');
|
|
88
|
+
const workflowPath = path.join(workflowsDir, workflowName);
|
|
89
|
+
const deprecatedPath = path.join(workflowsDir, '_deprecated', workflowName);
|
|
90
|
+
|
|
91
|
+
// If workflow exists and not already in _deprecated
|
|
92
|
+
if (fs.existsSync(workflowPath)) {
|
|
93
|
+
await fs.ensureDir(path.join(workflowsDir, '_deprecated'));
|
|
94
|
+
await fs.move(workflowPath, deprecatedPath, { overwrite: true });
|
|
95
|
+
console.log(` Moved ${workflowName} → _deprecated/`);
|
|
96
|
+
} else {
|
|
97
|
+
console.log(` ${workflowName} not found (may already be deprecated)`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Copy all workflow files from package
|
|
103
|
+
* @param {string} sourceDir - Package vortex directory
|
|
104
|
+
* @param {string} targetDir - Installation vortex directory
|
|
105
|
+
*/
|
|
106
|
+
async function copyAllWorkflows(sourceDir, targetDir) {
|
|
107
|
+
const workflows = [
|
|
108
|
+
'lean-persona',
|
|
109
|
+
'product-vision',
|
|
110
|
+
'contextualize-scope',
|
|
111
|
+
'mvp',
|
|
112
|
+
'lean-experiment',
|
|
113
|
+
'proof-of-concept',
|
|
114
|
+
'proof-of-value'
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
const workflowsSourceDir = path.join(sourceDir, 'workflows');
|
|
118
|
+
const workflowsTargetDir = path.join(targetDir, 'workflows');
|
|
119
|
+
|
|
120
|
+
await fs.ensureDir(workflowsTargetDir);
|
|
121
|
+
|
|
122
|
+
for (const workflow of workflows) {
|
|
123
|
+
const sourcePath = path.join(workflowsSourceDir, workflow);
|
|
124
|
+
const targetPath = path.join(workflowsTargetDir, workflow);
|
|
125
|
+
|
|
126
|
+
if (fs.existsSync(sourcePath)) {
|
|
127
|
+
await fs.copy(sourcePath, targetPath, { overwrite: true });
|
|
128
|
+
console.log(` Installed: ${workflow}`);
|
|
129
|
+
} else {
|
|
130
|
+
console.warn(` Warning: ${workflow} not found in package`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Update config.yaml with new structure
|
|
137
|
+
* @param {string} targetDir - Target vortex directory
|
|
138
|
+
* @param {string} newVersion - New version
|
|
139
|
+
*/
|
|
140
|
+
async function updateConfig(targetDir, newVersion) {
|
|
141
|
+
const configPath = path.join(targetDir, 'config.yaml');
|
|
142
|
+
|
|
143
|
+
const updates = {
|
|
144
|
+
agents: [
|
|
145
|
+
'contextualization-expert',
|
|
146
|
+
'lean-experiments-specialist'
|
|
147
|
+
],
|
|
148
|
+
workflows: [
|
|
149
|
+
'lean-persona',
|
|
150
|
+
'product-vision',
|
|
151
|
+
'contextualize-scope',
|
|
152
|
+
'mvp',
|
|
153
|
+
'lean-experiment',
|
|
154
|
+
'proof-of-concept',
|
|
155
|
+
'proof-of-value'
|
|
156
|
+
]
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const mergedConfig = await configMerger.mergeConfig(configPath, newVersion, updates);
|
|
160
|
+
|
|
161
|
+
// Validate
|
|
162
|
+
const validation = configMerger.validateConfig(mergedConfig);
|
|
163
|
+
if (!validation.valid) {
|
|
164
|
+
console.error('Config validation errors:', validation.errors);
|
|
165
|
+
throw new Error('Config validation failed');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Write
|
|
169
|
+
await configMerger.writeConfig(configPath, mergedConfig);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Copy agent files from package
|
|
174
|
+
* @param {string} sourceDir - Package vortex directory
|
|
175
|
+
* @param {string} targetDir - Installation vortex directory
|
|
176
|
+
*/
|
|
177
|
+
async function copyAgentFiles(sourceDir, targetDir) {
|
|
178
|
+
const agentFiles = [
|
|
179
|
+
'contextualization-expert.md',
|
|
180
|
+
'lean-experiments-specialist.md'
|
|
181
|
+
];
|
|
182
|
+
|
|
183
|
+
const agentsSourceDir = path.join(sourceDir, 'agents');
|
|
184
|
+
const agentsTargetDir = path.join(targetDir, 'agents');
|
|
185
|
+
|
|
186
|
+
await fs.ensureDir(agentsTargetDir);
|
|
187
|
+
|
|
188
|
+
for (const file of agentFiles) {
|
|
189
|
+
const sourcePath = path.join(agentsSourceDir, file);
|
|
190
|
+
const targetPath = path.join(agentsTargetDir, file);
|
|
191
|
+
|
|
192
|
+
if (fs.existsSync(sourcePath)) {
|
|
193
|
+
await fs.copy(sourcePath, targetPath, { overwrite: true });
|
|
194
|
+
console.log(` Updated: ${file}`);
|
|
195
|
+
} else {
|
|
196
|
+
console.warn(` Warning: ${file} not found in package`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Update agent manifest CSV
|
|
203
|
+
*/
|
|
204
|
+
async function updateAgentManifest() {
|
|
205
|
+
const manifestPath = path.join(process.cwd(), '_bmad/_config/agent-manifest.csv');
|
|
206
|
+
|
|
207
|
+
if (!fs.existsSync(manifestPath)) {
|
|
208
|
+
console.log(' Agent manifest not found, skipping update');
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
let manifestContent = await fs.readFile(manifestPath, 'utf8');
|
|
213
|
+
|
|
214
|
+
// Update Emma's entry (empathy-mapper → contextualization-expert)
|
|
215
|
+
manifestContent = manifestContent.replace(
|
|
216
|
+
/empathy-mapper/g,
|
|
217
|
+
'contextualization-expert'
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
manifestContent = manifestContent.replace(
|
|
221
|
+
/Empathy Mapping Specialist/g,
|
|
222
|
+
'Contextualization Expert'
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
// Update Wade's entry if needed
|
|
226
|
+
manifestContent = manifestContent.replace(
|
|
227
|
+
/wireframe-designer/g,
|
|
228
|
+
'lean-experiments-specialist'
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
manifestContent = manifestContent.replace(
|
|
232
|
+
/Wireframe Designer/g,
|
|
233
|
+
'Lean Experiments Specialist'
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
await fs.writeFile(manifestPath, manifestContent, 'utf8');
|
|
237
|
+
console.log(' Updated agent manifest');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Copy user guides to output directory
|
|
242
|
+
*/
|
|
243
|
+
async function copyUserGuides() {
|
|
244
|
+
const sourceDir = path.join(__dirname, '../../../_bmad-output/vortex-artifacts');
|
|
245
|
+
const targetDir = path.join(process.cwd(), '_bmad-output/vortex-artifacts');
|
|
246
|
+
|
|
247
|
+
await fs.ensureDir(targetDir);
|
|
248
|
+
|
|
249
|
+
const guides = [
|
|
250
|
+
'EMMA-USER-GUIDE.md',
|
|
251
|
+
'WADE-USER-GUIDE.md'
|
|
252
|
+
];
|
|
253
|
+
|
|
254
|
+
for (const guide of guides) {
|
|
255
|
+
const sourcePath = path.join(sourceDir, guide);
|
|
256
|
+
const targetPath = path.join(targetDir, guide);
|
|
257
|
+
|
|
258
|
+
if (fs.existsSync(sourcePath)) {
|
|
259
|
+
await fs.copy(sourcePath, targetPath, { overwrite: true });
|
|
260
|
+
console.log(` Updated: ${guide}`);
|
|
261
|
+
} else {
|
|
262
|
+
console.warn(` Warning: ${guide} not found in package`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const yaml = require('js-yaml');
|
|
6
|
+
const configMerger = require('../lib/config-merger');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Migration: 1.1.x → 1.3.0
|
|
10
|
+
* Minor update - no breaking changes
|
|
11
|
+
* - Update version number
|
|
12
|
+
* - Verify deprecated workflow structure
|
|
13
|
+
* - Refresh agent files (bug fixes)
|
|
14
|
+
* - Update user guides
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
name: '1.1.x-to-1.3.0',
|
|
19
|
+
fromVersion: '1.1.x',
|
|
20
|
+
toVersion: '1.3.0',
|
|
21
|
+
breaking: false,
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Preview changes without applying
|
|
25
|
+
* @returns {Promise<object>} Preview information
|
|
26
|
+
*/
|
|
27
|
+
async preview() {
|
|
28
|
+
return {
|
|
29
|
+
actions: [
|
|
30
|
+
'Update version: 1.1.x → 1.3.0',
|
|
31
|
+
'Verify deprecated workflows archived',
|
|
32
|
+
'Update agent files to latest (bug fixes/improvements)',
|
|
33
|
+
'Refresh user guides (EMMA-USER-GUIDE.md, WADE-USER-GUIDE.md)'
|
|
34
|
+
]
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Apply the migration
|
|
40
|
+
* @returns {Promise<Array<string>>} List of changes made
|
|
41
|
+
*/
|
|
42
|
+
async apply() {
|
|
43
|
+
const changes = [];
|
|
44
|
+
const sourceDir = path.join(__dirname, '../../../_bmad/bme/_vortex');
|
|
45
|
+
const targetDir = path.join(process.cwd(), '_bmad/bme/_vortex');
|
|
46
|
+
|
|
47
|
+
// 1. Update version in config.yaml
|
|
48
|
+
await updateConfigVersion('1.3.0');
|
|
49
|
+
changes.push('Updated version to 1.3.0');
|
|
50
|
+
|
|
51
|
+
// 2. Verify deprecated structure exists
|
|
52
|
+
await ensureDeprecatedStructure(targetDir);
|
|
53
|
+
changes.push('Verified deprecated workflow structure');
|
|
54
|
+
|
|
55
|
+
// 3. Update agent files (in case of bug fixes or improvements)
|
|
56
|
+
await copyAgentFiles(sourceDir, targetDir);
|
|
57
|
+
changes.push('Refreshed agent files');
|
|
58
|
+
|
|
59
|
+
// 4. Update user guides
|
|
60
|
+
await copyUserGuides();
|
|
61
|
+
changes.push('Updated user guides');
|
|
62
|
+
|
|
63
|
+
return changes;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Update version in config.yaml
|
|
69
|
+
* @param {string} newVersion - New version to set
|
|
70
|
+
*/
|
|
71
|
+
async function updateConfigVersion(newVersion) {
|
|
72
|
+
const configPath = path.join(process.cwd(), '_bmad/bme/_vortex/config.yaml');
|
|
73
|
+
|
|
74
|
+
if (!fs.existsSync(configPath)) {
|
|
75
|
+
throw new Error('config.yaml not found');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const configContent = fs.readFileSync(configPath, 'utf8');
|
|
79
|
+
const config = yaml.load(configContent);
|
|
80
|
+
|
|
81
|
+
// Update version
|
|
82
|
+
config.version = newVersion;
|
|
83
|
+
|
|
84
|
+
// Write back
|
|
85
|
+
await configMerger.writeConfig(configPath, config);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Ensure deprecated workflow structure is correct
|
|
90
|
+
* @param {string} targetDir - Target vortex directory
|
|
91
|
+
*/
|
|
92
|
+
async function ensureDeprecatedStructure(targetDir) {
|
|
93
|
+
const deprecatedDir = path.join(targetDir, 'workflows/_deprecated');
|
|
94
|
+
|
|
95
|
+
// Ensure _deprecated directory exists
|
|
96
|
+
if (!fs.existsSync(deprecatedDir)) {
|
|
97
|
+
await fs.ensureDir(deprecatedDir);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Check if deprecated workflows are there
|
|
101
|
+
const empathyMapDir = path.join(deprecatedDir, 'empathy-map');
|
|
102
|
+
const wireframeDir = path.join(deprecatedDir, 'wireframe');
|
|
103
|
+
|
|
104
|
+
// These should exist from v1.1.0, but verify
|
|
105
|
+
if (fs.existsSync(empathyMapDir) || fs.existsSync(wireframeDir)) {
|
|
106
|
+
console.log(' ✓ Deprecated workflows found in _deprecated/');
|
|
107
|
+
} else {
|
|
108
|
+
console.log(' Note: No deprecated workflows found (this is OK if starting fresh)');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Copy agent files from package to installation
|
|
114
|
+
* @param {string} sourceDir - Package vortex directory
|
|
115
|
+
* @param {string} targetDir - Installation vortex directory
|
|
116
|
+
*/
|
|
117
|
+
async function copyAgentFiles(sourceDir, targetDir) {
|
|
118
|
+
const agentFiles = [
|
|
119
|
+
'contextualization-expert.md',
|
|
120
|
+
'lean-experiments-specialist.md'
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
const agentsSourceDir = path.join(sourceDir, 'agents');
|
|
124
|
+
const agentsTargetDir = path.join(targetDir, 'agents');
|
|
125
|
+
|
|
126
|
+
await fs.ensureDir(agentsTargetDir);
|
|
127
|
+
|
|
128
|
+
for (const file of agentFiles) {
|
|
129
|
+
const sourcePath = path.join(agentsSourceDir, file);
|
|
130
|
+
const targetPath = path.join(agentsTargetDir, file);
|
|
131
|
+
|
|
132
|
+
if (fs.existsSync(sourcePath)) {
|
|
133
|
+
await fs.copy(sourcePath, targetPath, { overwrite: true });
|
|
134
|
+
console.log(` Updated: ${file}`);
|
|
135
|
+
} else {
|
|
136
|
+
console.warn(` Warning: ${file} not found in package`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Copy user guides to output directory
|
|
143
|
+
*/
|
|
144
|
+
async function copyUserGuides() {
|
|
145
|
+
const sourceDir = path.join(__dirname, '../../../_bmad-output/vortex-artifacts');
|
|
146
|
+
const targetDir = path.join(process.cwd(), '_bmad-output/vortex-artifacts');
|
|
147
|
+
|
|
148
|
+
await fs.ensureDir(targetDir);
|
|
149
|
+
|
|
150
|
+
const guides = [
|
|
151
|
+
'EMMA-USER-GUIDE.md',
|
|
152
|
+
'WADE-USER-GUIDE.md'
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
for (const guide of guides) {
|
|
156
|
+
const sourcePath = path.join(sourceDir, guide);
|
|
157
|
+
const targetPath = path.join(targetDir, guide);
|
|
158
|
+
|
|
159
|
+
if (fs.existsSync(sourcePath)) {
|
|
160
|
+
await fs.copy(sourcePath, targetPath, { overwrite: true });
|
|
161
|
+
console.log(` Updated: ${guide}`);
|
|
162
|
+
} else {
|
|
163
|
+
console.warn(` Warning: ${guide} not found in package`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const yaml = require('js-yaml');
|
|
6
|
+
const configMerger = require('../lib/config-merger');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Migration: 1.2.x → 1.3.0
|
|
10
|
+
* Minor update - no breaking changes
|
|
11
|
+
* - Update version number
|
|
12
|
+
* - Verify deprecated workflow structure
|
|
13
|
+
* - Refresh agent files (bug fixes)
|
|
14
|
+
* - Update user guides
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
name: '1.2.x-to-1.3.0',
|
|
19
|
+
fromVersion: '1.2.x',
|
|
20
|
+
toVersion: '1.3.0',
|
|
21
|
+
breaking: false,
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Preview changes without applying
|
|
25
|
+
* @returns {Promise<object>} Preview information
|
|
26
|
+
*/
|
|
27
|
+
async preview() {
|
|
28
|
+
return {
|
|
29
|
+
actions: [
|
|
30
|
+
'Update version: 1.2.x → 1.3.0',
|
|
31
|
+
'Verify deprecated workflows archived',
|
|
32
|
+
'Update agent files to latest (bug fixes/improvements)',
|
|
33
|
+
'Refresh user guides (EMMA-USER-GUIDE.md, WADE-USER-GUIDE.md)'
|
|
34
|
+
]
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Apply the migration
|
|
40
|
+
* @returns {Promise<Array<string>>} List of changes made
|
|
41
|
+
*/
|
|
42
|
+
async apply() {
|
|
43
|
+
const changes = [];
|
|
44
|
+
const sourceDir = path.join(__dirname, '../../../_bmad/bme/_vortex');
|
|
45
|
+
const targetDir = path.join(process.cwd(), '_bmad/bme/_vortex');
|
|
46
|
+
|
|
47
|
+
// 1. Update version in config.yaml
|
|
48
|
+
await updateConfigVersion('1.3.0');
|
|
49
|
+
changes.push('Updated version to 1.3.0');
|
|
50
|
+
|
|
51
|
+
// 2. Verify deprecated structure exists
|
|
52
|
+
await ensureDeprecatedStructure(targetDir);
|
|
53
|
+
changes.push('Verified deprecated workflow structure');
|
|
54
|
+
|
|
55
|
+
// 3. Update agent files (in case of bug fixes or improvements)
|
|
56
|
+
await copyAgentFiles(sourceDir, targetDir);
|
|
57
|
+
changes.push('Refreshed agent files');
|
|
58
|
+
|
|
59
|
+
// 4. Update user guides
|
|
60
|
+
await copyUserGuides();
|
|
61
|
+
changes.push('Updated user guides');
|
|
62
|
+
|
|
63
|
+
return changes;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Update version in config.yaml
|
|
69
|
+
* @param {string} newVersion - New version to set
|
|
70
|
+
*/
|
|
71
|
+
async function updateConfigVersion(newVersion) {
|
|
72
|
+
const configPath = path.join(process.cwd(), '_bmad/bme/_vortex/config.yaml');
|
|
73
|
+
|
|
74
|
+
if (!fs.existsSync(configPath)) {
|
|
75
|
+
throw new Error('config.yaml not found');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const configContent = fs.readFileSync(configPath, 'utf8');
|
|
79
|
+
const config = yaml.load(configContent);
|
|
80
|
+
|
|
81
|
+
// Update version
|
|
82
|
+
config.version = newVersion;
|
|
83
|
+
|
|
84
|
+
// Write back
|
|
85
|
+
await configMerger.writeConfig(configPath, config);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Ensure deprecated workflow structure is correct
|
|
90
|
+
* @param {string} targetDir - Target vortex directory
|
|
91
|
+
*/
|
|
92
|
+
async function ensureDeprecatedStructure(targetDir) {
|
|
93
|
+
const deprecatedDir = path.join(targetDir, 'workflows/_deprecated');
|
|
94
|
+
|
|
95
|
+
// Ensure _deprecated directory exists
|
|
96
|
+
if (!fs.existsSync(deprecatedDir)) {
|
|
97
|
+
await fs.ensureDir(deprecatedDir);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Check if deprecated workflows are there
|
|
101
|
+
const empathyMapDir = path.join(deprecatedDir, 'empathy-map');
|
|
102
|
+
const wireframeDir = path.join(deprecatedDir, 'wireframe');
|
|
103
|
+
|
|
104
|
+
// These should exist from v1.1.0, but verify
|
|
105
|
+
if (fs.existsSync(empathyMapDir) || fs.existsSync(wireframeDir)) {
|
|
106
|
+
console.log(' ✓ Deprecated workflows found in _deprecated/');
|
|
107
|
+
} else {
|
|
108
|
+
console.log(' Note: No deprecated workflows found (this is OK if starting fresh)');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Copy agent files from package to installation
|
|
114
|
+
* @param {string} sourceDir - Package vortex directory
|
|
115
|
+
* @param {string} targetDir - Installation vortex directory
|
|
116
|
+
*/
|
|
117
|
+
async function copyAgentFiles(sourceDir, targetDir) {
|
|
118
|
+
const agentFiles = [
|
|
119
|
+
'contextualization-expert.md',
|
|
120
|
+
'lean-experiments-specialist.md'
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
const agentsSourceDir = path.join(sourceDir, 'agents');
|
|
124
|
+
const agentsTargetDir = path.join(targetDir, 'agents');
|
|
125
|
+
|
|
126
|
+
await fs.ensureDir(agentsTargetDir);
|
|
127
|
+
|
|
128
|
+
for (const file of agentFiles) {
|
|
129
|
+
const sourcePath = path.join(agentsSourceDir, file);
|
|
130
|
+
const targetPath = path.join(agentsTargetDir, file);
|
|
131
|
+
|
|
132
|
+
if (fs.existsSync(sourcePath)) {
|
|
133
|
+
await fs.copy(sourcePath, targetPath, { overwrite: true });
|
|
134
|
+
console.log(` Updated: ${file}`);
|
|
135
|
+
} else {
|
|
136
|
+
console.warn(` Warning: ${file} not found in package`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Copy user guides to output directory
|
|
143
|
+
*/
|
|
144
|
+
async function copyUserGuides() {
|
|
145
|
+
const sourceDir = path.join(__dirname, '../../../_bmad-output/vortex-artifacts');
|
|
146
|
+
const targetDir = path.join(process.cwd(), '_bmad-output/vortex-artifacts');
|
|
147
|
+
|
|
148
|
+
await fs.ensureDir(targetDir);
|
|
149
|
+
|
|
150
|
+
const guides = [
|
|
151
|
+
'EMMA-USER-GUIDE.md',
|
|
152
|
+
'WADE-USER-GUIDE.md'
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
for (const guide of guides) {
|
|
156
|
+
const sourcePath = path.join(sourceDir, guide);
|
|
157
|
+
const targetPath = path.join(targetDir, guide);
|
|
158
|
+
|
|
159
|
+
if (fs.existsSync(sourcePath)) {
|
|
160
|
+
await fs.copy(sourcePath, targetPath, { overwrite: true });
|
|
161
|
+
console.log(` Updated: ${guide}`);
|
|
162
|
+
} else {
|
|
163
|
+
console.warn(` Warning: ${guide} not found in package`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|