convoke-agents 2.4.0 → 3.0.1

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 (67) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/INSTALLATION.md +109 -86
  3. package/README.md +220 -163
  4. package/UPDATE-GUIDE.md +63 -23
  5. package/_bmad/bme/_gyre/README.md +100 -0
  6. package/_bmad/bme/_gyre/agents/.gitkeep +0 -0
  7. package/_bmad/bme/_gyre/agents/model-curator.md +128 -0
  8. package/_bmad/bme/_gyre/agents/readiness-analyst.md +127 -0
  9. package/_bmad/bme/_gyre/agents/review-coach.md +130 -0
  10. package/_bmad/bme/_gyre/agents/stack-detective.md +125 -0
  11. package/_bmad/bme/_gyre/compass-routing-reference.md +168 -0
  12. package/_bmad/bme/_gyre/config.yaml +22 -0
  13. package/_bmad/bme/_gyre/contracts/.gitkeep +0 -0
  14. package/_bmad/bme/_gyre/contracts/gc1-stack-profile.md +152 -0
  15. package/_bmad/bme/_gyre/contracts/gc2-capabilities-manifest.md +189 -0
  16. package/_bmad/bme/_gyre/contracts/gc3-findings-report.md +197 -0
  17. package/_bmad/bme/_gyre/contracts/gc4-feedback-loop.md +209 -0
  18. package/_bmad/bme/_gyre/guides/ATLAS-USER-GUIDE.md +177 -0
  19. package/_bmad/bme/_gyre/guides/COACH-USER-GUIDE.md +172 -0
  20. package/_bmad/bme/_gyre/guides/LENS-USER-GUIDE.md +181 -0
  21. package/_bmad/bme/_gyre/guides/SCOUT-USER-GUIDE.md +158 -0
  22. package/_bmad/bme/_gyre/workflows/.gitkeep +0 -0
  23. package/_bmad/bme/_gyre/workflows/accuracy-validation/steps/step-01-select-repos.md +55 -0
  24. package/_bmad/bme/_gyre/workflows/accuracy-validation/steps/step-02-run-validation.md +78 -0
  25. package/_bmad/bme/_gyre/workflows/accuracy-validation/steps/step-03-score-results.md +143 -0
  26. package/_bmad/bme/_gyre/workflows/accuracy-validation/workflow.md +41 -0
  27. package/_bmad/bme/_gyre/workflows/delta-report/steps/step-01-load-history.md +63 -0
  28. package/_bmad/bme/_gyre/workflows/delta-report/steps/step-02-compute-delta.md +72 -0
  29. package/_bmad/bme/_gyre/workflows/delta-report/steps/step-03-present-delta.md +143 -0
  30. package/_bmad/bme/_gyre/workflows/delta-report/workflow.md +34 -0
  31. package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-01-initialize.md +68 -0
  32. package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-02-detect-stack.md +49 -0
  33. package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-03-generate-model.md +52 -0
  34. package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-04-analyze-gaps.md +42 -0
  35. package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-05-review-findings.md +128 -0
  36. package/_bmad/bme/_gyre/workflows/full-analysis/workflow.md +39 -0
  37. package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-01-load-manifest.md +70 -0
  38. package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-02-observability-analysis.md +110 -0
  39. package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-03-deployment-analysis.md +87 -0
  40. package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-04-cross-domain-correlation.md +105 -0
  41. package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-05-present-findings.md +172 -0
  42. package/_bmad/bme/_gyre/workflows/gap-analysis/workflow.md +38 -0
  43. package/_bmad/bme/_gyre/workflows/model-generation/steps/step-01-load-profile.md +74 -0
  44. package/_bmad/bme/_gyre/workflows/model-generation/steps/step-02-generate-capabilities.md +116 -0
  45. package/_bmad/bme/_gyre/workflows/model-generation/steps/step-03-web-enrichment.md +89 -0
  46. package/_bmad/bme/_gyre/workflows/model-generation/steps/step-04-write-manifest.md +122 -0
  47. package/_bmad/bme/_gyre/workflows/model-generation/workflow.md +40 -0
  48. package/_bmad/bme/_gyre/workflows/model-review/steps/step-01-load-context.md +86 -0
  49. package/_bmad/bme/_gyre/workflows/model-review/steps/step-02-walkthrough.md +116 -0
  50. package/_bmad/bme/_gyre/workflows/model-review/steps/step-03-apply-amendments.md +92 -0
  51. package/_bmad/bme/_gyre/workflows/model-review/steps/step-04-capture-feedback.md +107 -0
  52. package/_bmad/bme/_gyre/workflows/model-review/steps/step-05-summary.md +60 -0
  53. package/_bmad/bme/_gyre/workflows/model-review/workflow.md +41 -0
  54. package/_bmad/bme/_gyre/workflows/stack-detection/steps/step-01-scan-filesystem.md +176 -0
  55. package/_bmad/bme/_gyre/workflows/stack-detection/steps/step-02-classify-stack.md +111 -0
  56. package/_bmad/bme/_gyre/workflows/stack-detection/steps/step-03-guard-questions.md +117 -0
  57. package/_bmad/bme/_gyre/workflows/stack-detection/workflow.md +42 -0
  58. package/_bmad/bme/_vortex/config.yaml +1 -1
  59. package/package.json +5 -2
  60. package/scripts/archive.js +304 -0
  61. package/scripts/convoke-doctor.js +146 -132
  62. package/scripts/docs-audit.js +21 -5
  63. package/scripts/install-gyre-agents.js +140 -0
  64. package/scripts/install-vortex-agents.js +0 -0
  65. package/scripts/update/lib/agent-registry.js +70 -0
  66. package/scripts/update/lib/refresh-installation.js +152 -30
  67. package/scripts/update/lib/validator.js +160 -1
@@ -5,11 +5,12 @@ const path = require('path');
5
5
  const chalk = require('chalk');
6
6
  const yaml = require('js-yaml');
7
7
  const { findProjectRoot, getPackageVersion } = require('./update/lib/utils');
8
- const { AGENT_FILES, WORKFLOW_NAMES } = require('./update/lib/agent-registry');
9
8
 
10
9
  /**
11
10
  * convoke-doctor — Diagnose common Convoke installation issues.
12
- * Runs a series of checks and reports pass/fail with actionable fix suggestions.
11
+ *
12
+ * Config-driven: discovers all modules by scanning _bmad/bme/ config.yaml
13
+ * and validates file existence dynamically per module.
13
14
  */
14
15
 
15
16
  async function main() {
@@ -30,26 +31,41 @@ async function main() {
30
31
  return;
31
32
  }
32
33
 
33
- // 2. Config file
34
- checks.push(checkConfig(projectRoot));
34
+ // 2. Discover modules from _bmad/bme/*/config.yaml
35
+ const modules = discoverModules(projectRoot);
35
36
 
36
- // 3. Agent files
37
- checks.push(checkAgents(projectRoot));
37
+ if (modules.length === 0) {
38
+ checks.push({
39
+ name: 'Module discovery',
40
+ passed: false,
41
+ error: 'No modules found — expected config.yaml files in _bmad/bme/*/',
42
+ fix: 'Run: npx -p convoke-agents convoke-install'
43
+ });
44
+ printResults(checks);
45
+ process.exit(1);
46
+ return;
47
+ }
38
48
 
39
- // 4. Workflow directories
40
- checks.push(checkWorkflows(projectRoot));
49
+ checks.push({
50
+ name: 'Module discovery',
51
+ passed: true,
52
+ info: `Found ${modules.length} module(s): ${modules.map(m => m.name).join(', ')}`
53
+ });
41
54
 
42
- // 5. Output directory writable
43
- checks.push(await checkOutputDir(projectRoot));
55
+ // 3. Per-module checks
56
+ for (const mod of modules) {
57
+ const configCheck = checkModuleConfig(mod);
58
+ checks.push(configCheck);
59
+ if (configCheck.passed) {
60
+ checks.push(checkModuleAgents(mod));
61
+ checks.push(checkModuleWorkflows(mod));
62
+ }
63
+ }
44
64
 
45
- // 6. Stale migration lock
65
+ // 4. Global checks (module-agnostic)
66
+ checks.push(await checkOutputDir(projectRoot));
46
67
  checks.push(checkMigrationLock(projectRoot));
47
-
48
- // 7. Version consistency
49
- checks.push(checkVersionConsistency(projectRoot));
50
-
51
- // 8. Workflow step structure
52
- checks.push(checkWorkflowStepStructure(projectRoot));
68
+ checks.push(checkVersionConsistency(projectRoot, modules));
53
69
 
54
70
  printResults(checks);
55
71
 
@@ -57,6 +73,43 @@ async function main() {
57
73
  process.exit(failed.length > 0 ? 1 : 0);
58
74
  }
59
75
 
76
+ /**
77
+ * Scan _bmad/bme/ for subdirectories containing config.yaml.
78
+ * Returns an array of module descriptors with parsed config (or null on error).
79
+ */
80
+ function discoverModules(projectRoot) {
81
+ const bmeDir = path.join(projectRoot, '_bmad/bme');
82
+ if (!fs.existsSync(bmeDir)) return [];
83
+
84
+ const entries = fs.readdirSync(bmeDir, { withFileTypes: true });
85
+ const modules = [];
86
+
87
+ for (const entry of entries) {
88
+ if (!entry.isDirectory()) continue;
89
+ const configPath = path.join(bmeDir, entry.name, 'config.yaml');
90
+ if (!fs.existsSync(configPath)) continue;
91
+
92
+ let config = null;
93
+ let parseError = null;
94
+ try {
95
+ const content = fs.readFileSync(configPath, 'utf8');
96
+ config = yaml.load(content);
97
+ } catch (err) {
98
+ parseError = err.message;
99
+ }
100
+
101
+ modules.push({
102
+ name: entry.name,
103
+ dir: path.join(bmeDir, entry.name),
104
+ configPath,
105
+ config,
106
+ parseError,
107
+ });
108
+ }
109
+
110
+ return modules;
111
+ }
112
+
60
113
  function checkProjectRoot(projectRoot) {
61
114
  if (projectRoot) {
62
115
  return {
@@ -73,120 +126,124 @@ function checkProjectRoot(projectRoot) {
73
126
  };
74
127
  }
75
128
 
76
- function checkConfig(projectRoot) {
77
- const configPath = path.join(projectRoot, '_bmad/bme/_vortex/config.yaml');
129
+ function checkModuleConfig(mod) {
130
+ const label = `${mod.name} config`;
78
131
 
79
- if (!fs.existsSync(configPath)) {
132
+ if (mod.parseError) {
80
133
  return {
81
- name: 'Config file',
134
+ name: label,
82
135
  passed: false,
83
- error: 'config.yaml not found',
84
- fix: 'Run: npx -p convoke-agents convoke-install'
136
+ error: `YAML parse error: ${mod.parseError}`,
137
+ fix: `Check ${mod.configPath} for syntax errors`
85
138
  };
86
139
  }
87
140
 
88
- try {
89
- const content = fs.readFileSync(configPath, 'utf8');
90
- const config = yaml.load(content);
91
-
92
- if (!config || typeof config !== 'object') {
93
- return {
94
- name: 'Config file',
95
- passed: false,
96
- error: 'config.yaml is empty or invalid',
97
- fix: 'Delete _bmad/bme/_vortex/config.yaml and run: npx -p convoke-agents convoke-install'
98
- };
99
- }
141
+ if (!mod.config || typeof mod.config !== 'object') {
142
+ return {
143
+ name: label,
144
+ passed: false,
145
+ error: 'config.yaml is empty or invalid',
146
+ fix: `Reinstall the ${mod.name} module`
147
+ };
148
+ }
100
149
 
101
- if (!config.agents) {
102
- return {
103
- name: 'Config file',
104
- passed: false,
105
- error: 'config.yaml missing agents section',
106
- fix: 'Run: npx -p convoke-agents convoke-update'
107
- };
108
- }
150
+ if (!Array.isArray(mod.config.agents) || mod.config.agents.length === 0) {
151
+ return {
152
+ name: label,
153
+ passed: false,
154
+ error: 'config.yaml missing or empty agents section',
155
+ fix: `Check ${mod.configPath}`
156
+ };
157
+ }
109
158
 
110
- return { name: 'Config file', passed: true, info: 'Valid YAML with agents section' };
111
- } catch (err) {
159
+ if (!Array.isArray(mod.config.workflows) || mod.config.workflows.length === 0) {
112
160
  return {
113
- name: 'Config file',
161
+ name: label,
114
162
  passed: false,
115
- error: `YAML parse error: ${err.message}`,
116
- fix: 'Check config.yaml for syntax errors, or delete and run: npx -p convoke-agents convoke-install'
163
+ error: 'config.yaml missing or empty workflows section',
164
+ fix: `Check ${mod.configPath}`
117
165
  };
118
166
  }
167
+
168
+ return {
169
+ name: label,
170
+ passed: true,
171
+ info: `${mod.config.agents.length} agents, ${mod.config.workflows.length} workflows`
172
+ };
119
173
  }
120
174
 
121
- function checkAgents(projectRoot) {
122
- const agentsDir = path.join(projectRoot, '_bmad/bme/_vortex/agents');
123
- const required = AGENT_FILES;
175
+ function checkModuleAgents(mod) {
176
+ const label = `${mod.name} agents`;
177
+ const agentsDir = path.join(mod.dir, 'agents');
178
+ const agentIds = mod.config.agents;
124
179
 
125
180
  if (!fs.existsSync(agentsDir)) {
126
181
  return {
127
- name: 'Agent files',
182
+ name: label,
128
183
  passed: false,
129
184
  error: 'agents/ directory not found',
130
- fix: 'Run: npx -p convoke-agents convoke-install-vortex'
185
+ fix: `Reinstall the ${mod.name} module`
131
186
  };
132
187
  }
133
188
 
134
- const missing = required.filter(f => !fs.existsSync(path.join(agentsDir, f)));
189
+ const missing = agentIds.filter(id => !fs.existsSync(path.join(agentsDir, `${id}.md`)));
135
190
 
136
191
  if (missing.length > 0) {
137
192
  return {
138
- name: 'Agent files',
193
+ name: label,
139
194
  passed: false,
140
- error: `Missing: ${missing.join(', ')}`,
141
- fix: 'Run: npx -p convoke-agents convoke-install-vortex to reinstall'
195
+ error: `Missing: ${missing.map(id => `${id}.md`).join(', ')}`,
196
+ fix: `Reinstall the ${mod.name} module`
142
197
  };
143
198
  }
144
199
 
145
200
  // Check files are non-empty
146
- const empty = required.filter(f => {
147
- const stat = fs.statSync(path.join(agentsDir, f));
201
+ const empty = agentIds.filter(id => {
202
+ const stat = fs.statSync(path.join(agentsDir, `${id}.md`));
148
203
  return stat.size === 0;
149
204
  });
150
205
 
151
206
  if (empty.length > 0) {
152
207
  return {
153
- name: 'Agent files',
208
+ name: label,
154
209
  passed: false,
155
- error: `Empty agent files: ${empty.join(', ')}`,
156
- fix: 'Run: npx -p convoke-agents convoke-install to restore agent files'
210
+ error: `Empty agent files: ${empty.map(id => `${id}.md`).join(', ')}`,
211
+ fix: `Reinstall the ${mod.name} module`
157
212
  };
158
213
  }
159
214
 
160
- return { name: 'Agent files', passed: true, info: `${required.length} agents present` };
215
+ return { name: label, passed: true, info: `${agentIds.length} agents present` };
161
216
  }
162
217
 
163
- function checkWorkflows(projectRoot) {
164
- const workflowsDir = path.join(projectRoot, '_bmad/bme/_vortex/workflows');
165
- const required = WORKFLOW_NAMES;
218
+ function checkModuleWorkflows(mod) {
219
+ const label = `${mod.name} workflows`;
220
+ const workflowsDir = path.join(mod.dir, 'workflows');
221
+ const workflowNames = mod.config.workflows;
166
222
 
167
223
  if (!fs.existsSync(workflowsDir)) {
168
224
  return {
169
- name: 'Workflow directories',
225
+ name: label,
170
226
  passed: false,
171
227
  error: 'workflows/ directory not found',
172
- fix: 'Run: npx -p convoke-agents convoke-install'
228
+ fix: `Reinstall the ${mod.name} module`
173
229
  };
174
230
  }
175
231
 
176
- const missing = required.filter(w =>
177
- !fs.existsSync(path.join(workflowsDir, w, 'workflow.md'))
178
- );
232
+ const missing = workflowNames.filter(w => {
233
+ const name = typeof w === 'object' ? w.name : w;
234
+ return !fs.existsSync(path.join(workflowsDir, name, 'workflow.md'));
235
+ });
179
236
 
180
237
  if (missing.length > 0) {
181
238
  return {
182
- name: 'Workflow directories',
239
+ name: label,
183
240
  passed: false,
184
241
  error: `Missing: ${missing.join(', ')}`,
185
- fix: 'Run: npx -p convoke-agents convoke-update to restore workflows'
242
+ fix: `Reinstall the ${mod.name} module`
186
243
  };
187
244
  }
188
245
 
189
- return { name: 'Workflow directories', passed: true, info: `${required.length} workflows present` };
246
+ return { name: label, passed: true, info: `${workflowNames.length} workflows present` };
190
247
  }
191
248
 
192
249
  async function checkOutputDir(projectRoot) {
@@ -251,75 +308,32 @@ function checkMigrationLock(projectRoot) {
251
308
  }
252
309
  }
253
310
 
254
- function checkVersionConsistency(projectRoot) {
255
- const configPath = path.join(projectRoot, '_bmad/bme/_vortex/config.yaml');
311
+ function checkVersionConsistency(projectRoot, modules) {
256
312
  const packageVersion = getPackageVersion();
313
+ const mismatched = [];
257
314
 
258
- if (!fs.existsSync(configPath)) {
259
- return { name: 'Version consistency', passed: true, info: 'No config to check' };
260
- }
261
-
262
- try {
263
- const content = fs.readFileSync(configPath, 'utf8');
264
- const config = yaml.load(content);
265
- const installedVersion = config.version || config.installed_version;
266
-
267
- if (!installedVersion) {
268
- return {
269
- name: 'Version consistency',
270
- passed: true,
271
- info: `Package: ${packageVersion} (no installed version recorded in config)`
272
- };
273
- }
274
-
275
- if (installedVersion === packageVersion) {
276
- return {
277
- name: 'Version consistency',
278
- passed: true,
279
- info: `${packageVersion} — package and config match`
280
- };
315
+ for (const mod of modules) {
316
+ if (!mod.config) continue;
317
+ const installedVersion = mod.config.version || mod.config.installed_version;
318
+ if (installedVersion && installedVersion !== packageVersion) {
319
+ mismatched.push(`${mod.name}: ${installedVersion}`);
281
320
  }
321
+ }
282
322
 
323
+ if (mismatched.length > 0) {
283
324
  return {
284
325
  name: 'Version consistency',
285
326
  passed: false,
286
- error: `Package: ${packageVersion}, Config: ${installedVersion}`,
327
+ error: `Package: ${packageVersion}, ${mismatched.join(', ')}`,
287
328
  fix: 'Run: npx -p convoke-agents convoke-update'
288
329
  };
289
- } catch (_err) {
290
- return { name: 'Version consistency', passed: true, info: 'Could not read config version' };
291
- }
292
- }
293
-
294
- function checkWorkflowStepStructure(projectRoot) {
295
- const workflowsDir = path.join(projectRoot, '_bmad/bme/_vortex/workflows');
296
-
297
- if (!fs.existsSync(workflowsDir)) {
298
- return { name: 'Workflow step structure', passed: true, info: 'No workflows directory' };
299
- }
300
-
301
- const issues = [];
302
-
303
- for (const wf of WORKFLOW_NAMES) {
304
- const stepsDir = path.join(workflowsDir, wf, 'steps');
305
- if (!fs.existsSync(stepsDir)) continue;
306
-
307
- const files = fs.readdirSync(stepsDir).filter(f => f.endsWith('.md'));
308
- if (files.length < 4 || files.length > 6) {
309
- issues.push(`${wf}: ${files.length} step files (expected 4-6)`);
310
- }
311
330
  }
312
331
 
313
- if (issues.length > 0) {
314
- return {
315
- name: 'Workflow step structure',
316
- passed: false,
317
- error: issues.join('; '),
318
- fix: 'Run: npx -p convoke-agents convoke-install-vortex to reinstall clean workflow files'
319
- };
320
- }
321
-
322
- return { name: 'Workflow step structure', passed: true, info: 'All workflows have valid step counts' };
332
+ return {
333
+ name: 'Version consistency',
334
+ passed: true,
335
+ info: `${packageVersion} — package and config versions consistent`
336
+ };
323
337
  }
324
338
 
325
339
  function printResults(checks) {
@@ -7,7 +7,8 @@ const path = require('path');
7
7
  const chalk = require('chalk');
8
8
  const { findProjectRoot } = require('./update/lib/utils');
9
9
  const {
10
- AGENTS, WORKFLOWS, WORKFLOW_NAMES
10
+ AGENTS, WORKFLOWS, WORKFLOW_NAMES,
11
+ GYRE_AGENTS, GYRE_WORKFLOWS,
11
12
  } = require('./update/lib/agent-registry');
12
13
 
13
14
  // --- Constants (Task 1.1, 1.2) ---
@@ -61,6 +62,18 @@ function checkStaleReferences(content, filePath) {
61
62
  const agentCount = AGENTS.length;
62
63
  const workflowCount = WORKFLOWS.length;
63
64
 
65
+ // Valid counts from all registered teams and their combined totals
66
+ const validAgentCounts = new Set([
67
+ AGENTS.length, // Vortex
68
+ GYRE_AGENTS.length, // Gyre
69
+ AGENTS.length + GYRE_AGENTS.length, // Combined total
70
+ ]);
71
+ const validWorkflowCounts = new Set([
72
+ WORKFLOWS.length, // Vortex
73
+ GYRE_WORKFLOWS.length, // Gyre
74
+ WORKFLOWS.length + GYRE_WORKFLOWS.length, // Combined total
75
+ ]);
76
+
64
77
  // Build regex for written-out numbers
65
78
  const wordKeys = Object.keys(WORD_TO_NUM).join('|');
66
79
 
@@ -86,7 +99,7 @@ function checkStaleReferences(content, filePath) {
86
99
  digitAgentRe.lastIndex = 0;
87
100
  while ((m = digitAgentRe.exec(line)) !== null) {
88
101
  const num = parseInt(m[1], 10);
89
- if (num !== agentCount && num > 0 && num < 100) {
102
+ if (!validAgentCounts.has(num) && num > 0 && num < 100) {
90
103
  findings.push({
91
104
  file: filePath, line: lineNum,
92
105
  category: 'stale-reference',
@@ -99,7 +112,7 @@ function checkStaleReferences(content, filePath) {
99
112
  wordAgentRe.lastIndex = 0;
100
113
  while ((m = wordAgentRe.exec(line)) !== null) {
101
114
  const num = WORD_TO_NUM[m[1].toLowerCase()];
102
- if (num !== undefined && num !== agentCount) {
115
+ if (num !== undefined && !validAgentCounts.has(num)) {
103
116
  findings.push({
104
117
  file: filePath, line: lineNum,
105
118
  category: 'stale-reference',
@@ -112,7 +125,7 @@ function checkStaleReferences(content, filePath) {
112
125
  digitWorkflowRe.lastIndex = 0;
113
126
  while ((m = digitWorkflowRe.exec(line)) !== null) {
114
127
  const num = parseInt(m[1], 10);
115
- if (num !== workflowCount && num > 0 && num < 100) {
128
+ if (!validWorkflowCounts.has(num) && num > 0 && num < 100) {
116
129
  findings.push({
117
130
  file: filePath, line: lineNum,
118
131
  category: 'stale-reference',
@@ -125,7 +138,7 @@ function checkStaleReferences(content, filePath) {
125
138
  wordWorkflowRe.lastIndex = 0;
126
139
  while ((m = wordWorkflowRe.exec(line)) !== null) {
127
140
  const num = WORD_TO_NUM[m[1].toLowerCase()];
128
- if (num !== undefined && num !== workflowCount) {
141
+ if (num !== undefined && !validWorkflowCounts.has(num)) {
129
142
  findings.push({
130
143
  file: filePath, line: lineNum,
131
144
  category: 'stale-reference',
@@ -419,6 +432,9 @@ function checkStaleBrandReferences(content, filePath) {
419
432
  const line = lines[i];
420
433
  const lineNum = i + 1;
421
434
 
435
+ // Skip lines that document the rename transition (e.g., "bmad-enhanced → convoke-agents")
436
+ if (/→|->/.test(line) && /convoke/i.test(line)) continue;
437
+
422
438
  staleRe.lastIndex = 0;
423
439
  let m;
424
440
  while ((m = staleRe.exec(line)) !== null) {
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs-extra');
4
+ const path = require('path');
5
+ const { refreshInstallation } = require('./update/lib/refresh-installation');
6
+ const { findProjectRoot } = require('./update/lib/utils');
7
+ const { GYRE_AGENTS } = require('./update/lib/agent-registry');
8
+
9
+ const BOLD = '\x1b[1m';
10
+ const RESET = '\x1b[0m';
11
+ const GREEN = '\x1b[32m';
12
+ const CYAN = '\x1b[36m';
13
+ const YELLOW = '\x1b[33m';
14
+ const RED = '\x1b[31m';
15
+ const GREY = '\x1b[90m';
16
+
17
+ function printBanner() {
18
+ console.log('');
19
+ console.log(`${GREY} ██████╗ ██████╗ ███╗ ██╗██╗ ██╗ ██████╗ ██╗ ██╗███████╗${RESET}`);
20
+ console.log(`${GREY} ██╔════╝██╔═══██╗████╗ ██║██║ ██║██╔═══██╗██║ ██╔╝██╔════╝${RESET}`);
21
+ console.log(`${GREY} ██║ ██║ ██║██╔██╗ ██║██║ ██║██║ ██║█████╔╝ █████╗ ${RESET}`);
22
+ console.log(`${GREY} ██║ ██║ ██║██║╚██╗██║╚██╗ ██╔╝██║ ██║██╔═██╗ ██╔══╝ ${RESET}`);
23
+ console.log(`${GREY} ╚██████╗╚██████╔╝██║ ╚████║ ╚████╔╝ ╚██████╔╝██║ ██╗███████╗${RESET}`);
24
+ console.log(`${GREY} ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝${RESET}`);
25
+ console.log(`${GREY} Agent teams for complex systems${RESET}`);
26
+ console.log('');
27
+ console.log(`${BOLD} Gyre Module — Production readiness discovery${RESET}`);
28
+ console.log('');
29
+ }
30
+
31
+ function checkPrerequisites(projectRoot) {
32
+ console.log(`${CYAN}[1/4]${RESET} Checking prerequisites...`);
33
+
34
+ const bmadDir = path.join(projectRoot, '_bmad');
35
+
36
+ if (!fs.existsSync(bmadDir)) {
37
+ console.log(`${YELLOW} ⚠${RESET} _bmad directory not found - creating it`);
38
+ fs.mkdirSync(bmadDir, { recursive: true });
39
+ } else {
40
+ console.log(`${GREEN} ✓${RESET} BMAD directory detected`);
41
+ }
42
+
43
+ const bmadConfigPath = path.join(bmadDir, '_config', 'bmad.yaml');
44
+ if (fs.existsSync(bmadConfigPath)) {
45
+ console.log(`${GREEN} ✓${RESET} BMAD Method configuration found`);
46
+ } else {
47
+ console.log(`${YELLOW} ⚠${RESET} BMAD Method not detected (Convoke will install standalone)`);
48
+ }
49
+
50
+ console.log(`${GREEN} ✓${RESET} Prerequisites met`);
51
+ }
52
+
53
+ function createOutputDirectory(projectRoot) {
54
+ console.log(`${CYAN}[2/4]${RESET} Setting up output directory...`);
55
+
56
+ const outputDir = path.join(projectRoot, '_bmad-output', 'gyre-artifacts');
57
+ fs.mkdirSync(outputDir, { recursive: true });
58
+
59
+ console.log(`${GREEN} ✓${RESET} Output directory ready`);
60
+ }
61
+
62
+ function verifyInstallation(projectRoot) {
63
+ console.log(`${CYAN}[4/4]${RESET} Verifying installation...`);
64
+
65
+ const checks = [
66
+ ...GYRE_AGENTS.map(a => ({ path: `_bmad/bme/_gyre/agents/${a.id}.md`, name: `${a.name} agent file` })),
67
+ ...GYRE_AGENTS.map(a => ({ path: `.claude/skills/bmad-agent-bme-${a.id}/SKILL.md`, name: `${a.name} skill` })),
68
+ { path: '_bmad/bme/_gyre/config.yaml', name: 'Configuration file' },
69
+ ];
70
+
71
+ let allChecksPass = true;
72
+ checks.forEach(check => {
73
+ const fullPath = path.join(projectRoot, check.path);
74
+ if (fs.existsSync(fullPath)) {
75
+ console.log(`${GREEN} ✓${RESET} ${check.name}`);
76
+ } else {
77
+ console.log(`${RED} ✗${RESET} ${check.name} - MISSING`);
78
+ allChecksPass = false;
79
+ }
80
+ });
81
+
82
+ if (!allChecksPass) {
83
+ console.log('');
84
+ console.error(`${RED}Installation verification failed. Some files are missing.${RESET}`);
85
+ process.exit(1);
86
+ }
87
+
88
+ console.log(`${GREEN} ✓${RESET} All files installed successfully`);
89
+ }
90
+
91
+ function printSuccess() {
92
+ console.log('');
93
+ console.log(`${GREEN}${BOLD}╔════════════════════════════════════════════════════╗${RESET}`);
94
+ console.log(`${GREEN}${BOLD}║ ║${RESET}`);
95
+ console.log(`${GREEN}${BOLD}║ ✓ All Gyre Agents Installed! 🎉 ║${RESET}`);
96
+ console.log(`${GREEN}${BOLD}║ ║${RESET}`);
97
+ console.log(`${GREEN}${BOLD}╚════════════════════════════════════════════════════╝${RESET}`);
98
+ console.log('');
99
+ console.log(`${BOLD}Installed Agents:${RESET}`);
100
+ console.log('');
101
+ for (const agent of GYRE_AGENTS) {
102
+ console.log(` ${GREEN}✓${RESET} ${agent.name} (${agent.id}) - ${agent.title} ${agent.icon}`);
103
+ }
104
+ console.log('');
105
+ console.log(`${BOLD}Next Steps:${RESET}`);
106
+ console.log('');
107
+ console.log(` ${YELLOW}1.${RESET} Personalize your config:`);
108
+ console.log(` Edit ${CYAN}_bmad/bme/_gyre/config.yaml${RESET} and replace ${YELLOW}{user}${RESET} with your name`);
109
+ console.log('');
110
+ console.log(` ${YELLOW}2.${RESET} Activate an agent (skill) in Claude Code:`);
111
+ for (const agent of GYRE_AGENTS) {
112
+ console.log(` ${CYAN}/bmad-agent-bme-${agent.id}${RESET} (${agent.name})`);
113
+ }
114
+ console.log('');
115
+ console.log(` ${YELLOW}3.${RESET} Or read the agent file directly:`);
116
+ console.log(` ${CYAN}cat _bmad/bme/_gyre/agents/{agent-id}.md${RESET}`);
117
+ console.log('');
118
+ }
119
+
120
+ async function main() {
121
+ try {
122
+ const projectRoot = findProjectRoot();
123
+
124
+ printBanner();
125
+ checkPrerequisites(projectRoot);
126
+ createOutputDirectory(projectRoot);
127
+
128
+ console.log(`${CYAN}[3/4]${RESET} Installing agents, workflows, config, and contracts...`);
129
+ await refreshInstallation(projectRoot, { backupGuides: false });
130
+ console.log(`${GREEN} ✓${RESET} Installation refreshed`);
131
+
132
+ verifyInstallation(projectRoot);
133
+ printSuccess();
134
+ } catch (error) {
135
+ console.error(`${RED}✗ Installation failed:${RESET}`, error.message);
136
+ process.exit(1);
137
+ }
138
+ }
139
+
140
+ main();
File without changes