bmad-enhanced 1.5.2 → 1.6.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.
Files changed (145) hide show
  1. package/CHANGELOG.md +104 -6
  2. package/INSTALLATION.md +93 -245
  3. package/README.md +121 -1110
  4. package/UPDATE-GUIDE.md +70 -265
  5. package/_bmad/_config/agent-manifest.csv +0 -2
  6. package/_bmad/bme/_vortex/README.md +150 -0
  7. package/_bmad/bme/_vortex/agents/hypothesis-engineer.md +117 -0
  8. package/_bmad/bme/_vortex/agents/production-intelligence-specialist.md +117 -0
  9. package/_bmad/bme/_vortex/agents/research-convergence-specialist.md +117 -0
  10. package/_bmad/bme/_vortex/compass-routing-reference.md +312 -0
  11. package/_bmad/bme/_vortex/config.yaml +1 -1
  12. package/_bmad/bme/_vortex/contracts/hc1-empathy-artifacts.md +152 -0
  13. package/_bmad/bme/_vortex/contracts/hc2-problem-definition.md +125 -0
  14. package/_bmad/bme/_vortex/contracts/hc3-hypothesis-contract.md +112 -0
  15. package/_bmad/bme/_vortex/contracts/hc4-experiment-context.md +140 -0
  16. package/_bmad/bme/_vortex/contracts/hc5-signal-report.md +130 -0
  17. package/_bmad/bme/_vortex/examples/hc2-example-problem-definition.md +85 -0
  18. package/_bmad/bme/_vortex/examples/hc3-example-hypothesis-contract.md +103 -0
  19. package/_bmad/bme/_vortex/examples/hc5-example-signal-report.md +76 -0
  20. package/_bmad/bme/_vortex/guides/LIAM-USER-GUIDE.md +260 -0
  21. package/_bmad/bme/_vortex/guides/MILA-USER-GUIDE.md +240 -0
  22. package/_bmad/bme/_vortex/guides/NOAH-USER-GUIDE.md +263 -0
  23. package/_bmad/bme/_vortex/workflows/assumption-mapping/steps/step-01-setup.md +66 -0
  24. package/_bmad/bme/_vortex/workflows/assumption-mapping/steps/step-02-context.md +93 -0
  25. package/_bmad/bme/_vortex/workflows/assumption-mapping/steps/step-03-risk-mapping.md +103 -0
  26. package/_bmad/bme/_vortex/workflows/assumption-mapping/steps/step-04-synthesize.md +101 -0
  27. package/_bmad/bme/_vortex/workflows/assumption-mapping/workflow.md +49 -0
  28. package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-01-setup.md +81 -0
  29. package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-02-context.md +67 -0
  30. package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-03-classification.md +98 -0
  31. package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-04-evidence.md +100 -0
  32. package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-05-synthesize.md +174 -0
  33. package/_bmad/bme/_vortex/workflows/behavior-analysis/workflow.md +52 -0
  34. package/_bmad/bme/_vortex/workflows/contextualize-scope/contextualize-scope.template.md +1 -1
  35. package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-06-synthesize.md +4 -1
  36. package/_bmad/bme/_vortex/workflows/experiment-design/steps/step-01-setup.md +66 -0
  37. package/_bmad/bme/_vortex/workflows/experiment-design/steps/step-02-context.md +77 -0
  38. package/_bmad/bme/_vortex/workflows/experiment-design/steps/step-03-design.md +114 -0
  39. package/_bmad/bme/_vortex/workflows/experiment-design/steps/step-04-synthesize.md +128 -0
  40. package/_bmad/bme/_vortex/workflows/experiment-design/workflow.md +51 -0
  41. package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-01-setup.md +66 -0
  42. package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-02-context.md +80 -0
  43. package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-03-brainwriting.md +79 -0
  44. package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-04-assumption-mapping.md +102 -0
  45. package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-05-synthesize.md +130 -0
  46. package/_bmad/bme/_vortex/workflows/hypothesis-engineering/workflow.md +52 -0
  47. package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-06.md +4 -1
  48. package/_bmad/bme/_vortex/workflows/lean-persona/lean-persona.template.md +1 -1
  49. package/_bmad/bme/_vortex/workflows/learning-card/learning-card.template.md +1 -1
  50. package/_bmad/bme/_vortex/workflows/learning-card/steps/step-06-synthesize.md +4 -1
  51. package/_bmad/bme/_vortex/workflows/mvp/mvp.template.md +1 -1
  52. package/_bmad/bme/_vortex/workflows/mvp/steps/step-06-synthesize.md +3 -0
  53. package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-01-setup.md +102 -0
  54. package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-02-context.md +81 -0
  55. package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-03-pattern-identification.md +88 -0
  56. package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-04-theme-clustering.md +100 -0
  57. package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-05-synthesize.md +135 -0
  58. package/_bmad/bme/_vortex/workflows/pattern-mapping/workflow.md +58 -0
  59. package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/pivot-patch-persevere.template.md +1 -1
  60. package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-06-action-plan.md +5 -2
  61. package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-01-setup.md +97 -0
  62. package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-02-context.md +86 -0
  63. package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-03-jtbd-reframing.md +88 -0
  64. package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-04-pains-gains-revision.md +76 -0
  65. package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-05-synthesize.md +158 -0
  66. package/_bmad/bme/_vortex/workflows/pivot-resynthesis/workflow.md +52 -0
  67. package/_bmad/bme/_vortex/workflows/product-vision/product-vision.template.md +1 -1
  68. package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-01-setup.md +84 -0
  69. package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-02-context.md +66 -0
  70. package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-03-monitoring.md +74 -0
  71. package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-04-prioritization.md +97 -0
  72. package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-05-synthesize.md +183 -0
  73. package/_bmad/bme/_vortex/workflows/production-monitoring/workflow.md +52 -0
  74. package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-06.md +3 -0
  75. package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-06.md +3 -0
  76. package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-01-setup.md +69 -0
  77. package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-02-context.md +70 -0
  78. package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-03-jtbd-framing.md +81 -0
  79. package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-04-pains-gains.md +77 -0
  80. package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-05-synthesize.md +147 -0
  81. package/_bmad/bme/_vortex/workflows/research-convergence/workflow.md +50 -0
  82. package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-01-setup.md +68 -0
  83. package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-02-context.md +67 -0
  84. package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-03-signal-analysis.md +85 -0
  85. package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-04-anomaly-detection.md +93 -0
  86. package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-05-synthesize.md +163 -0
  87. package/_bmad/bme/_vortex/workflows/signal-interpretation/workflow.md +52 -0
  88. package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-06-synthesize.md +4 -1
  89. package/_bmad/bme/_vortex/workflows/user-interview/steps/step-06-synthesize.md +4 -1
  90. package/_bmad/bme/_vortex/workflows/user-interview/user-interview.template.md +1 -1
  91. package/_bmad/bme/_vortex/workflows/user-interview/validate.md +1 -1
  92. package/_bmad-output/implementation-artifacts/1-1-expand-agent-registry-to-7-agents.md +190 -0
  93. package/_bmad-output/implementation-artifacts/1-2-update-validator-config-merger-doctor-for-7-agents.md +184 -0
  94. package/_bmad-output/implementation-artifacts/1-3-create-migration-delta-installer-updates.md +270 -0
  95. package/_bmad-output/implementation-artifacts/1-4-define-handoff-contract-schemas-hc1-hc5.md +292 -0
  96. package/_bmad-output/implementation-artifacts/1-5-create-compass-routing-reference-document.md +324 -0
  97. package/_bmad-output/implementation-artifacts/2-1-design-milas-agent-definition-persona.md +270 -0
  98. package/_bmad-output/implementation-artifacts/2-2-create-research-convergence-workflow.md +429 -0
  99. package/_bmad-output/implementation-artifacts/2-3-create-pivot-resynthesis-workflow.md +411 -0
  100. package/_bmad-output/implementation-artifacts/2-4-create-pattern-mapping-workflow.md +397 -0
  101. package/_bmad-output/implementation-artifacts/2-5-create-mila-user-guide-example-artifacts.md +243 -0
  102. package/_bmad-output/implementation-artifacts/3-1-design-liams-agent-definition-persona.md +301 -0
  103. package/_bmad-output/implementation-artifacts/3-2-create-hypothesis-engineering-workflow.md +403 -0
  104. package/_bmad-output/implementation-artifacts/3-3-create-assumption-mapping-workflow.md +373 -0
  105. package/_bmad-output/implementation-artifacts/3-4-create-experiment-design-workflow.md +359 -0
  106. package/_bmad-output/implementation-artifacts/3-5-create-liam-user-guide-example-artifacts.md +258 -0
  107. package/_bmad-output/implementation-artifacts/4-1-design-noahs-agent-definition-persona.md +191 -0
  108. package/_bmad-output/implementation-artifacts/4-2-create-signal-interpretation-workflow.md +352 -0
  109. package/_bmad-output/implementation-artifacts/4-3-create-behavior-analysis-workflow.md +406 -0
  110. package/_bmad-output/implementation-artifacts/4-4-create-production-monitoring-workflow.md +430 -0
  111. package/_bmad-output/implementation-artifacts/4-5-create-noah-user-guide-example-artifacts.md +342 -0
  112. package/_bmad-output/implementation-artifacts/5-1-update-islas-compass-routes-to-mila.md +210 -0
  113. package/_bmad-output/implementation-artifacts/5-2-update-wades-maxs-compass-routes.md +260 -0
  114. package/_bmad-output/implementation-artifacts/5-3-update-documentation-for-complete-7-agent-vortex.md +268 -0
  115. package/_bmad-output/implementation-artifacts/5-4-add-ci-dead-end-detection-final-version-bump.md +206 -0
  116. package/_bmad-output/implementation-artifacts/epic-1-retro-2026-02-24.md +90 -0
  117. package/_bmad-output/implementation-artifacts/epic-2-retro-2026-02-25.md +104 -0
  118. package/_bmad-output/implementation-artifacts/epic-3-retro-2026-02-25.md +126 -0
  119. package/_bmad-output/implementation-artifacts/epic-4-retro-2026-02-26.md +151 -0
  120. package/_bmad-output/implementation-artifacts/epic-5-retro-2026-02-26.md +168 -0
  121. package/_bmad-output/implementation-artifacts/sprint-status.yaml +85 -0
  122. package/_bmad-output/planning-artifacts/architecture.md +607 -0
  123. package/_bmad-output/planning-artifacts/epics.md +826 -0
  124. package/_bmad-output/planning-artifacts/implementation-readiness-report-2026-02-23.md +156 -0
  125. package/_bmad-output/planning-artifacts/prd.md +498 -0
  126. package/_bmad-output/planning-artifacts/product-brief-BMAD-Enhanced-2026-02-22.md +262 -0
  127. package/_bmad-output/vortex-artifacts/EMMA-USER-GUIDE.md +10 -10
  128. package/_bmad-output/vortex-artifacts/ISLA-USER-GUIDE.md +4 -4
  129. package/_bmad-output/vortex-artifacts/MAX-USER-GUIDE.md +4 -4
  130. package/_bmad-output/vortex-artifacts/WADE-USER-GUIDE.md +10 -10
  131. package/index.js +6 -5
  132. package/package.json +2 -6
  133. package/scripts/bmad-doctor.js +3 -7
  134. package/scripts/install-vortex-agents.js +23 -18
  135. package/scripts/postinstall.js +5 -10
  136. package/scripts/update/bmad-update.js +136 -87
  137. package/scripts/update/lib/agent-registry.js +144 -0
  138. package/scripts/update/lib/config-merger.js +67 -43
  139. package/scripts/update/lib/migration-runner.js +2 -1
  140. package/scripts/update/lib/refresh-installation.js +4 -37
  141. package/scripts/update/lib/validator.js +69 -21
  142. package/scripts/update/migrations/1.5.x-to-1.6.0.js +95 -0
  143. package/scripts/update/migrations/registry.js +7 -0
  144. package/scripts/install-emma.js +0 -14
  145. package/scripts/install-wade.js +0 -14
@@ -2,6 +2,7 @@
2
2
 
3
3
  const fs = require('fs-extra');
4
4
  const yaml = require('js-yaml');
5
+ const { AGENT_IDS, WORKFLOW_NAMES } = require('./agent-registry');
5
6
 
6
7
  /**
7
8
  * Config Merger for BMAD-Enhanced
@@ -22,7 +23,8 @@ async function mergeConfig(currentConfigPath, newVersion, updates = {}) {
22
23
  if (fs.existsSync(currentConfigPath)) {
23
24
  try {
24
25
  const currentContent = fs.readFileSync(currentConfigPath, 'utf8');
25
- current = yaml.load(currentContent);
26
+ const parsed = yaml.load(currentContent);
27
+ current = (parsed && typeof parsed === 'object') ? parsed : {};
26
28
  } catch (_error) {
27
29
  console.warn('Warning: Could not parse current config.yaml, using defaults');
28
30
  current = {};
@@ -35,9 +37,11 @@ async function mergeConfig(currentConfigPath, newVersion, updates = {}) {
35
37
  // Seed with required structural defaults for fresh installs
36
38
  const defaults = {
37
39
  submodule_name: '_vortex',
38
- description: 'Vortex Framework - Contextualize, Empathize, Externalize, and Systematize streams',
40
+ description: 'Vortex Pattern - Contextualize, Empathize, Synthesize, Hypothesize, Externalize, Sensitize, and Systematize streams',
39
41
  module: 'bme',
40
- output_folder: '{project-root}/_bmad-output/vortex-artifacts'
42
+ output_folder: '{project-root}/_bmad-output/vortex-artifacts',
43
+ agents: [...AGENT_IDS],
44
+ workflows: [...WORKFLOW_NAMES]
41
45
  };
42
46
 
43
47
  // Start with defaults, overlay current config (preserves existing values)
@@ -79,7 +83,7 @@ function extractUserPreferences(config) {
79
83
  prefs.user_name = config.user_name;
80
84
  }
81
85
 
82
- if (config.communication_language && config.communication_language !== 'en') {
86
+ if (config.communication_language) {
83
87
  prefs.communication_language = config.communication_language;
84
88
  }
85
89
 
@@ -98,6 +102,34 @@ function extractUserPreferences(config) {
98
102
  return prefs;
99
103
  }
100
104
 
105
+ /**
106
+ * Declarative config schema.
107
+ * Each entry declares a field's type, whether it's required, and an optional
108
+ * validation function that receives the value and returns an error string or null.
109
+ */
110
+ const CONFIG_SCHEMA = [
111
+ { field: 'submodule_name', type: 'string', required: true },
112
+ { field: 'description', type: 'string', required: true },
113
+ { field: 'module', type: 'string', required: true },
114
+ { field: 'version', type: 'string', required: true,
115
+ validate: v => /^\d+\.\d+\.\d+$/.test(v) ? null : `Invalid version format: ${v} (expected x.x.x)` },
116
+ { field: 'output_folder', type: 'string', required: true },
117
+ { field: 'agents', type: 'array', required: true, items: 'string' },
118
+ { field: 'workflows', type: 'array', required: true, items: 'string' },
119
+ { field: 'communication_language', type: 'string', required: false },
120
+ { field: 'party_mode_enabled', type: 'boolean', required: false },
121
+ { field: 'migration_history', type: 'array', required: false,
122
+ validate: (arr) => {
123
+ for (let i = 0; i < arr.length; i++) {
124
+ const e = arr[i];
125
+ if (!e.timestamp || !e.from_version || !e.to_version) {
126
+ return `migration_history[${i}] missing required fields`;
127
+ }
128
+ }
129
+ return null;
130
+ }},
131
+ ];
132
+
101
133
  /**
102
134
  * Validate merged config structure
103
135
  * @param {object} config - Config to validate
@@ -106,48 +138,39 @@ function extractUserPreferences(config) {
106
138
  function validateConfig(config) {
107
139
  const errors = [];
108
140
 
109
- // Required fields
110
- const requiredFields = [
111
- 'submodule_name',
112
- 'description',
113
- 'module',
114
- 'version',
115
- 'output_folder',
116
- 'agents',
117
- 'workflows'
118
- ];
119
-
120
- for (const field of requiredFields) {
121
- if (!Object.prototype.hasOwnProperty.call(config, field)) {
122
- errors.push(`Missing required field: ${field}`);
123
- }
124
- }
125
-
126
- // Validate version format (x.x.x)
127
- if (config.version && !/^\d+\.\d+\.\d+$/.test(config.version)) {
128
- errors.push(`Invalid version format: ${config.version} (expected x.x.x)`);
129
- }
141
+ for (const rule of CONFIG_SCHEMA) {
142
+ const has = Object.prototype.hasOwnProperty.call(config, rule.field);
130
143
 
131
- // Validate agents is array
132
- if (config.agents && !Array.isArray(config.agents)) {
133
- errors.push('agents must be an array');
134
- }
135
-
136
- // Validate workflows is array
137
- if (config.workflows && !Array.isArray(config.workflows)) {
138
- errors.push('workflows must be an array');
139
- }
144
+ if (!has) {
145
+ if (rule.required) errors.push(`Missing required field: ${rule.field}`);
146
+ continue;
147
+ }
140
148
 
141
- // Validate migration_history structure
142
- if (config.migration_history) {
143
- if (!Array.isArray(config.migration_history)) {
144
- errors.push('migration_history must be an array');
145
- } else {
146
- config.migration_history.forEach((entry, index) => {
147
- if (!entry.timestamp || !entry.from_version || !entry.to_version) {
148
- errors.push(`migration_history[${index}] missing required fields`);
149
+ const value = config[rule.field];
150
+
151
+ // Type check
152
+ if (rule.type === 'array') {
153
+ if (!Array.isArray(value)) {
154
+ errors.push(`${rule.field} must be an array`);
155
+ continue;
156
+ }
157
+ // Item type check
158
+ if (rule.items) {
159
+ for (let i = 0; i < value.length; i++) {
160
+ if (typeof value[i] !== rule.items) {
161
+ errors.push(`${rule.field}[${i}] must be a ${rule.items}`);
162
+ }
149
163
  }
150
- });
164
+ }
165
+ } else if (typeof value !== rule.type) {
166
+ errors.push(`${rule.field} must be a ${rule.type}`);
167
+ continue;
168
+ }
169
+
170
+ // Custom validation
171
+ if (rule.validate) {
172
+ const err = rule.validate(value);
173
+ if (err) errors.push(err);
151
174
  }
152
175
  }
153
176
 
@@ -197,6 +220,7 @@ function addMigrationHistory(config, fromVersion, toVersion, migrationsApplied)
197
220
  }
198
221
 
199
222
  module.exports = {
223
+ CONFIG_SCHEMA,
200
224
  mergeConfig,
201
225
  extractUserPreferences,
202
226
  validateConfig,
@@ -10,6 +10,7 @@ const configMerger = require('./config-merger');
10
10
  const validator = require('./validator');
11
11
  const { refreshInstallation } = require('./refresh-installation');
12
12
  const registry = require('../migrations/registry');
13
+ const { WORKFLOW_NAMES } = require('./agent-registry');
13
14
 
14
15
  /**
15
16
  * Migration Runner for BMAD-Enhanced
@@ -216,7 +217,7 @@ async function previewMigrations(migrations) {
216
217
  console.log('');
217
218
  console.log(chalk.white('After deltas, installation will be refreshed:'));
218
219
  console.log(chalk.gray(' - Refresh agent files'));
219
- console.log(chalk.gray(' - Refresh 7 workflow directories'));
220
+ console.log(chalk.gray(` - Refresh ${WORKFLOW_NAMES.length} workflow directories`));
220
221
  console.log(chalk.gray(' - Update config.yaml (preserving user preferences)'));
221
222
  console.log(chalk.gray(' - Update user guides (with .bak backup)'));
222
223
  console.log('');
@@ -4,6 +4,7 @@ const fs = require('fs-extra');
4
4
  const path = require('path');
5
5
  const { getPackageVersion } = require('./utils');
6
6
  const configMerger = require('./config-merger');
7
+ const { AGENT_FILES, AGENT_IDS, WORKFLOW_NAMES, USER_GUIDES } = require('./agent-registry');
7
8
 
8
9
  /**
9
10
  * Refresh Installation for BMAD-Enhanced
@@ -13,40 +14,6 @@ const configMerger = require('./config-merger');
13
14
  * or directly by the install script.
14
15
  */
15
16
 
16
- const AGENT_FILES = [
17
- 'contextualization-expert.md',
18
- 'lean-experiments-specialist.md',
19
- 'discovery-empathy-expert.md',
20
- 'learning-decision-expert.md'
21
- ];
22
-
23
- const WORKFLOWS = [
24
- // Emma — Contextualize Stream
25
- 'lean-persona',
26
- 'product-vision',
27
- 'contextualize-scope',
28
- // Wade — Externalize Stream
29
- 'mvp',
30
- 'lean-experiment',
31
- 'proof-of-concept',
32
- 'proof-of-value',
33
- // Isla — Empathize Stream
34
- 'empathy-map',
35
- 'user-interview',
36
- 'user-discovery',
37
- // Max — Systematize Stream
38
- 'learning-card',
39
- 'pivot-patch-persevere',
40
- 'vortex-navigation'
41
- ];
42
-
43
- const USER_GUIDES = [
44
- 'EMMA-USER-GUIDE.md',
45
- 'WADE-USER-GUIDE.md',
46
- 'ISLA-USER-GUIDE.md',
47
- 'MAX-USER-GUIDE.md'
48
- ];
49
-
50
17
  /**
51
18
  * Refresh all installation files from the package to the project.
52
19
  *
@@ -94,7 +61,7 @@ async function refreshInstallation(projectRoot, options = {}) {
94
61
  const workflowsTarget = path.join(targetVortex, 'workflows');
95
62
  await fs.ensureDir(workflowsTarget);
96
63
 
97
- for (const wf of WORKFLOWS) {
64
+ for (const wf of WORKFLOW_NAMES) {
98
65
  const src = path.join(workflowsSource, wf);
99
66
  if (fs.existsSync(src)) {
100
67
  await fs.copy(src, path.join(workflowsTarget, wf), { overwrite: true });
@@ -108,8 +75,8 @@ async function refreshInstallation(projectRoot, options = {}) {
108
75
  await fs.ensureDir(path.dirname(configPath));
109
76
 
110
77
  const updates = {
111
- agents: ['contextualization-expert', 'lean-experiments-specialist', 'discovery-empathy-expert', 'learning-decision-expert'],
112
- workflows: WORKFLOWS
78
+ agents: AGENT_IDS,
79
+ workflows: WORKFLOW_NAMES
113
80
  };
114
81
 
115
82
  const merged = await configMerger.mergeConfig(configPath, version, updates);
@@ -5,6 +5,7 @@ const path = require('path');
5
5
  const yaml = require('js-yaml');
6
6
  const configMerger = require('./config-merger');
7
7
  const { countUserDataFiles } = require('./utils');
8
+ const { AGENT_FILES, AGENT_IDS, WORKFLOW_NAMES, WAVE3_WORKFLOW_NAMES } = require('./agent-registry');
8
9
 
9
10
  /**
10
11
  * Validator for BMAD-Enhanced
@@ -40,6 +41,9 @@ async function validateInstallation(preMigrationData = {}, projectRoot) {
40
41
  // 6. Deprecated workflows validation (if applicable)
41
42
  checks.push(await validateDeprecatedWorkflows(projectRoot));
42
43
 
44
+ // 7. Workflow step structure validation (P17 count + P20 filenames)
45
+ checks.push(await validateWorkflowStepStructure(projectRoot));
46
+
43
47
  const allPassed = checks.every(c => c.passed);
44
48
 
45
49
  return {
@@ -101,12 +105,7 @@ async function validateAgentFiles(projectRoot) {
101
105
 
102
106
  try {
103
107
  const agentsDir = path.join(projectRoot, '_bmad/bme/_vortex/agents');
104
- const requiredAgents = [
105
- 'contextualization-expert.md',
106
- 'lean-experiments-specialist.md',
107
- 'discovery-empathy-expert.md',
108
- 'learning-decision-expert.md'
109
- ];
108
+ const requiredAgents = AGENT_FILES;
110
109
 
111
110
  if (!fs.existsSync(agentsDir)) {
112
111
  check.error = 'agents/ directory not found';
@@ -148,15 +147,7 @@ async function validateWorkflows(projectRoot) {
148
147
 
149
148
  try {
150
149
  const workflowsDir = path.join(projectRoot, '_bmad/bme/_vortex/workflows');
151
- const requiredWorkflows = [
152
- 'lean-persona',
153
- 'product-vision',
154
- 'contextualize-scope',
155
- 'mvp',
156
- 'lean-experiment',
157
- 'proof-of-concept',
158
- 'proof-of-value'
159
- ];
150
+ const requiredWorkflows = WORKFLOW_NAMES;
160
151
 
161
152
  if (!fs.existsSync(workflowsDir)) {
162
153
  check.error = 'workflows/ directory not found';
@@ -208,12 +199,11 @@ async function validateManifest(projectRoot) {
208
199
 
209
200
  const manifestContent = fs.readFileSync(manifestPath, 'utf8');
210
201
 
211
- // Check for BMAD-Enhanced agents
212
- const hasEmma = manifestContent.includes('contextualization-expert');
213
- const hasWade = manifestContent.includes('lean-experiments-specialist');
202
+ // Check for all BMAD-Enhanced agents
203
+ const missingFromManifest = AGENT_IDS.filter(id => !manifestContent.includes(id));
214
204
 
215
- if (!hasEmma || !hasWade) {
216
- check.error = 'Agent manifest missing BMAD-Enhanced agents';
205
+ if (missingFromManifest.length > 0) {
206
+ check.error = `Agent manifest missing: ${missingFromManifest.join(', ')}`;
217
207
  return check;
218
208
  }
219
209
 
@@ -301,6 +291,63 @@ async function validateDeprecatedWorkflows(projectRoot) {
301
291
  return check;
302
292
  }
303
293
 
294
+ /**
295
+ * Validate workflow step structure (P17 count + P20 filenames)
296
+ * @param {string} projectRoot - Absolute path to project root
297
+ * @returns {Promise<object>} Validation check result
298
+ */
299
+ async function validateWorkflowStepStructure(projectRoot) {
300
+ const check = {
301
+ name: 'Workflow step structure',
302
+ passed: true,
303
+ error: null
304
+ };
305
+
306
+ try {
307
+ const workflowsDir = path.join(projectRoot, '_bmad/bme/_vortex/workflows');
308
+ const issues = [];
309
+
310
+ for (const workflow of WORKFLOW_NAMES) {
311
+ const stepsDir = path.join(workflowsDir, workflow, 'steps');
312
+
313
+ if (!fs.existsSync(stepsDir)) {
314
+ continue; // Placeholder workflows without steps/ are valid
315
+ }
316
+
317
+ const files = fs.readdirSync(stepsDir).filter(f => f.endsWith('.md'));
318
+
319
+ // P17: step count must be 4-6
320
+ if (files.length < 4 || files.length > 6) {
321
+ issues.push(`${workflow}: ${files.length} step files (expected 4-6)`);
322
+ continue;
323
+ }
324
+
325
+ // P20: standardized filenames (Wave 3 workflows only)
326
+ if (WAVE3_WORKFLOW_NAMES.has(workflow)) {
327
+ if (!files.includes('step-01-setup.md')) {
328
+ issues.push(`${workflow}: missing step-01-setup.md`);
329
+ }
330
+ if (!files.includes('step-02-context.md')) {
331
+ issues.push(`${workflow}: missing step-02-context.md`);
332
+ }
333
+ if (!files.some(f => f.endsWith('-synthesize.md'))) {
334
+ issues.push(`${workflow}: missing *-synthesize.md final step`);
335
+ }
336
+ }
337
+ }
338
+
339
+ if (issues.length > 0) {
340
+ check.passed = false;
341
+ check.error = `Step structure issues: ${issues.join('; ')}`;
342
+ }
343
+ } catch (error) {
344
+ check.error = error.message;
345
+ check.passed = false;
346
+ }
347
+
348
+ return check;
349
+ }
350
+
304
351
  module.exports = {
305
352
  validateInstallation,
306
353
  validateConfigStructure,
@@ -308,5 +355,6 @@ module.exports = {
308
355
  validateWorkflows,
309
356
  validateManifest,
310
357
  validateUserDataIntegrity,
311
- validateDeprecatedWorkflows
358
+ validateDeprecatedWorkflows,
359
+ validateWorkflowStepStructure
312
360
  };
@@ -0,0 +1,95 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const yaml = require('js-yaml');
4
+ const { AGENTS, AGENT_IDS, WAVE3_WORKFLOW_NAMES } = require('../lib/agent-registry');
5
+
6
+ /**
7
+ * Migration: 1.5.x → current version (v1.6.0)
8
+ * Appends Wave 3 agents and workflows to existing config.
9
+ * refreshInstallation() handles file copying (agents, workflows, guides).
10
+ *
11
+ * Wave 3 agents: Mila (Synthesize), Liam (Hypothesize), Noah (Sensitize)
12
+ * Wave 3 workflows: 9 new workflows (3 per agent)
13
+ */
14
+
15
+ // Wave 1/2 agent IDs (pre-1.6.0)
16
+ const WAVE12_AGENT_IDS = new Set([
17
+ 'contextualization-expert',
18
+ 'discovery-empathy-expert',
19
+ 'lean-experiments-specialist',
20
+ 'learning-decision-expert'
21
+ ]);
22
+
23
+ // Wave 3 agent IDs derived from registry; workflow names from WAVE3_WORKFLOW_NAMES set
24
+ const WAVE3_AGENT_IDS = AGENT_IDS.filter(id => !WAVE12_AGENT_IDS.has(id));
25
+ const WAVE3_WORKFLOWS = [...WAVE3_WORKFLOW_NAMES];
26
+
27
+ module.exports = {
28
+ name: '1.5.x-to-1.6.0',
29
+ fromVersion: '1.5.x',
30
+ breaking: false,
31
+
32
+ async preview() {
33
+ const wave3Agents = AGENTS.filter(a => WAVE3_AGENT_IDS.includes(a.id));
34
+ const agentDesc = wave3Agents.map(a => `${a.name} (${a.id})`).join(', ');
35
+ return {
36
+ actions: [
37
+ `Append Wave 3 agents to config: ${agentDesc}`,
38
+ `Append ${WAVE3_WORKFLOWS.length} Wave 3 workflows to config: ${WAVE3_WORKFLOWS.join(', ')}`,
39
+ 'File copying handled by refreshInstallation()'
40
+ ]
41
+ };
42
+ },
43
+
44
+ /**
45
+ * Apply migration: append Wave 3 agents and workflows to config.
46
+ * Idempotent — skips entries already present.
47
+ * @param {string} projectRoot - Absolute path to project root
48
+ * @returns {Promise<Array<string>>} List of changes made
49
+ */
50
+ async apply(projectRoot) {
51
+ const changes = [];
52
+ const configPath = path.join(projectRoot, '_bmad', 'bme', '_vortex', 'config.yaml');
53
+
54
+ if (!await fs.pathExists(configPath)) {
55
+ changes.push('No config.yaml found — refreshInstallation will create it');
56
+ return changes;
57
+ }
58
+
59
+ const configContent = await fs.readFile(configPath, 'utf8');
60
+ const config = yaml.load(configContent) || {};
61
+
62
+ // Ensure arrays exist
63
+ if (!Array.isArray(config.agents)) {
64
+ config.agents = [];
65
+ }
66
+ if (!Array.isArray(config.workflows)) {
67
+ config.workflows = [];
68
+ }
69
+
70
+ // Append missing Wave 3 agents (idempotent)
71
+ const newAgents = WAVE3_AGENT_IDS.filter(id => !config.agents.includes(id));
72
+ if (newAgents.length > 0) {
73
+ config.agents.push(...newAgents);
74
+ changes.push(`Appended ${newAgents.length} Wave 3 agent(s): ${newAgents.join(', ')}`);
75
+ } else {
76
+ changes.push('Wave 3 agents already present in config');
77
+ }
78
+
79
+ // Append missing Wave 3 workflows (idempotent)
80
+ const newWorkflows = WAVE3_WORKFLOWS.filter(name => !config.workflows.includes(name));
81
+ if (newWorkflows.length > 0) {
82
+ config.workflows.push(...newWorkflows);
83
+ changes.push(`Appended ${newWorkflows.length} Wave 3 workflow(s): ${newWorkflows.join(', ')}`);
84
+ } else {
85
+ changes.push('Wave 3 workflows already present in config');
86
+ }
87
+
88
+ // Write updated config back
89
+ if (newAgents.length > 0 || newWorkflows.length > 0) {
90
+ await fs.writeFile(configPath, yaml.dump(config, { indent: 2, lineWidth: -1, noRefs: true }), 'utf8');
91
+ }
92
+
93
+ return changes;
94
+ }
95
+ };
@@ -46,6 +46,13 @@ const MIGRATIONS = [
46
46
  breaking: false,
47
47
  description: 'No-op delta (refresh handles Wave 2 agents and workflows)',
48
48
  module: null
49
+ },
50
+ {
51
+ name: '1.5.x-to-1.6.0',
52
+ fromVersion: '1.5.x',
53
+ breaking: false,
54
+ description: 'Add Wave 3 agents (Mila, Liam, Noah) and 9 workflows to config',
55
+ module: null
49
56
  }
50
57
  // Future migrations: append here. Only add delta logic for version-specific changes.
51
58
  ];
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * bmad-install-emma — Deprecated. Use bmad-install-vortex-agents instead.
5
- */
6
- const YELLOW = '\x1b[33m';
7
- const RESET = '\x1b[0m';
8
-
9
- console.log('');
10
- console.log(`${YELLOW}⚠ bmad-install-emma is deprecated as of v1.5.0.${RESET}`);
11
- console.log(`${YELLOW} Use: npx bmad-install-vortex-agents${RESET}`);
12
- console.log('');
13
-
14
- require('./install-vortex-agents.js');
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * bmad-install-wade — Deprecated. Use bmad-install-vortex-agents instead.
5
- */
6
- const YELLOW = '\x1b[33m';
7
- const RESET = '\x1b[0m';
8
-
9
- console.log('');
10
- console.log(`${YELLOW}⚠ bmad-install-wade is deprecated as of v1.5.0.${RESET}`);
11
- console.log(`${YELLOW} Use: npx bmad-install-vortex-agents${RESET}`);
12
- console.log('');
13
-
14
- require('./install-vortex-agents.js');