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.
@@ -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
+ }