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.
- package/CHANGELOG.md +16 -0
- package/INSTALLATION.md +109 -86
- package/README.md +220 -163
- package/UPDATE-GUIDE.md +63 -23
- package/_bmad/bme/_gyre/README.md +100 -0
- package/_bmad/bme/_gyre/agents/.gitkeep +0 -0
- package/_bmad/bme/_gyre/agents/model-curator.md +128 -0
- package/_bmad/bme/_gyre/agents/readiness-analyst.md +127 -0
- package/_bmad/bme/_gyre/agents/review-coach.md +130 -0
- package/_bmad/bme/_gyre/agents/stack-detective.md +125 -0
- package/_bmad/bme/_gyre/compass-routing-reference.md +168 -0
- package/_bmad/bme/_gyre/config.yaml +22 -0
- package/_bmad/bme/_gyre/contracts/.gitkeep +0 -0
- package/_bmad/bme/_gyre/contracts/gc1-stack-profile.md +152 -0
- package/_bmad/bme/_gyre/contracts/gc2-capabilities-manifest.md +189 -0
- package/_bmad/bme/_gyre/contracts/gc3-findings-report.md +197 -0
- package/_bmad/bme/_gyre/contracts/gc4-feedback-loop.md +209 -0
- package/_bmad/bme/_gyre/guides/ATLAS-USER-GUIDE.md +177 -0
- package/_bmad/bme/_gyre/guides/COACH-USER-GUIDE.md +172 -0
- package/_bmad/bme/_gyre/guides/LENS-USER-GUIDE.md +181 -0
- package/_bmad/bme/_gyre/guides/SCOUT-USER-GUIDE.md +158 -0
- package/_bmad/bme/_gyre/workflows/.gitkeep +0 -0
- package/_bmad/bme/_gyre/workflows/accuracy-validation/steps/step-01-select-repos.md +55 -0
- package/_bmad/bme/_gyre/workflows/accuracy-validation/steps/step-02-run-validation.md +78 -0
- package/_bmad/bme/_gyre/workflows/accuracy-validation/steps/step-03-score-results.md +143 -0
- package/_bmad/bme/_gyre/workflows/accuracy-validation/workflow.md +41 -0
- package/_bmad/bme/_gyre/workflows/delta-report/steps/step-01-load-history.md +63 -0
- package/_bmad/bme/_gyre/workflows/delta-report/steps/step-02-compute-delta.md +72 -0
- package/_bmad/bme/_gyre/workflows/delta-report/steps/step-03-present-delta.md +143 -0
- package/_bmad/bme/_gyre/workflows/delta-report/workflow.md +34 -0
- package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-01-initialize.md +68 -0
- package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-02-detect-stack.md +49 -0
- package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-03-generate-model.md +52 -0
- package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-04-analyze-gaps.md +42 -0
- package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-05-review-findings.md +128 -0
- package/_bmad/bme/_gyre/workflows/full-analysis/workflow.md +39 -0
- package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-01-load-manifest.md +70 -0
- package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-02-observability-analysis.md +110 -0
- package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-03-deployment-analysis.md +87 -0
- package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-04-cross-domain-correlation.md +105 -0
- package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-05-present-findings.md +172 -0
- package/_bmad/bme/_gyre/workflows/gap-analysis/workflow.md +38 -0
- package/_bmad/bme/_gyre/workflows/model-generation/steps/step-01-load-profile.md +74 -0
- package/_bmad/bme/_gyre/workflows/model-generation/steps/step-02-generate-capabilities.md +116 -0
- package/_bmad/bme/_gyre/workflows/model-generation/steps/step-03-web-enrichment.md +89 -0
- package/_bmad/bme/_gyre/workflows/model-generation/steps/step-04-write-manifest.md +122 -0
- package/_bmad/bme/_gyre/workflows/model-generation/workflow.md +40 -0
- package/_bmad/bme/_gyre/workflows/model-review/steps/step-01-load-context.md +86 -0
- package/_bmad/bme/_gyre/workflows/model-review/steps/step-02-walkthrough.md +116 -0
- package/_bmad/bme/_gyre/workflows/model-review/steps/step-03-apply-amendments.md +92 -0
- package/_bmad/bme/_gyre/workflows/model-review/steps/step-04-capture-feedback.md +107 -0
- package/_bmad/bme/_gyre/workflows/model-review/steps/step-05-summary.md +60 -0
- package/_bmad/bme/_gyre/workflows/model-review/workflow.md +41 -0
- package/_bmad/bme/_gyre/workflows/stack-detection/steps/step-01-scan-filesystem.md +176 -0
- package/_bmad/bme/_gyre/workflows/stack-detection/steps/step-02-classify-stack.md +111 -0
- package/_bmad/bme/_gyre/workflows/stack-detection/steps/step-03-guard-questions.md +117 -0
- package/_bmad/bme/_gyre/workflows/stack-detection/workflow.md +42 -0
- package/_bmad/bme/_vortex/config.yaml +1 -1
- package/package.json +5 -2
- package/scripts/archive.js +304 -0
- package/scripts/convoke-doctor.js +146 -132
- package/scripts/docs-audit.js +21 -5
- package/scripts/install-gyre-agents.js +140 -0
- package/scripts/install-vortex-agents.js +0 -0
- package/scripts/update/lib/agent-registry.js +70 -0
- package/scripts/update/lib/refresh-installation.js +152 -30
- 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
|
-
*
|
|
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.
|
|
34
|
-
|
|
34
|
+
// 2. Discover modules from _bmad/bme/*/config.yaml
|
|
35
|
+
const modules = discoverModules(projectRoot);
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
40
|
-
|
|
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
|
-
//
|
|
43
|
-
|
|
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
|
-
//
|
|
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
|
|
77
|
-
const
|
|
129
|
+
function checkModuleConfig(mod) {
|
|
130
|
+
const label = `${mod.name} config`;
|
|
78
131
|
|
|
79
|
-
if (
|
|
132
|
+
if (mod.parseError) {
|
|
80
133
|
return {
|
|
81
|
-
name:
|
|
134
|
+
name: label,
|
|
82
135
|
passed: false,
|
|
83
|
-
error:
|
|
84
|
-
fix:
|
|
136
|
+
error: `YAML parse error: ${mod.parseError}`,
|
|
137
|
+
fix: `Check ${mod.configPath} for syntax errors`
|
|
85
138
|
};
|
|
86
139
|
}
|
|
87
140
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
111
|
-
} catch (err) {
|
|
159
|
+
if (!Array.isArray(mod.config.workflows) || mod.config.workflows.length === 0) {
|
|
112
160
|
return {
|
|
113
|
-
name:
|
|
161
|
+
name: label,
|
|
114
162
|
passed: false,
|
|
115
|
-
error:
|
|
116
|
-
fix:
|
|
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
|
|
122
|
-
const
|
|
123
|
-
const
|
|
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:
|
|
182
|
+
name: label,
|
|
128
183
|
passed: false,
|
|
129
184
|
error: 'agents/ directory not found',
|
|
130
|
-
fix:
|
|
185
|
+
fix: `Reinstall the ${mod.name} module`
|
|
131
186
|
};
|
|
132
187
|
}
|
|
133
188
|
|
|
134
|
-
const missing =
|
|
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:
|
|
193
|
+
name: label,
|
|
139
194
|
passed: false,
|
|
140
|
-
error: `Missing: ${missing.join(', ')}`,
|
|
141
|
-
fix:
|
|
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 =
|
|
147
|
-
const stat = fs.statSync(path.join(agentsDir,
|
|
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:
|
|
208
|
+
name: label,
|
|
154
209
|
passed: false,
|
|
155
|
-
error: `Empty agent files: ${empty.join(', ')}`,
|
|
156
|
-
fix:
|
|
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:
|
|
215
|
+
return { name: label, passed: true, info: `${agentIds.length} agents present` };
|
|
161
216
|
}
|
|
162
217
|
|
|
163
|
-
function
|
|
164
|
-
const
|
|
165
|
-
const
|
|
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:
|
|
225
|
+
name: label,
|
|
170
226
|
passed: false,
|
|
171
227
|
error: 'workflows/ directory not found',
|
|
172
|
-
fix:
|
|
228
|
+
fix: `Reinstall the ${mod.name} module`
|
|
173
229
|
};
|
|
174
230
|
}
|
|
175
231
|
|
|
176
|
-
const missing =
|
|
177
|
-
|
|
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:
|
|
239
|
+
name: label,
|
|
183
240
|
passed: false,
|
|
184
241
|
error: `Missing: ${missing.join(', ')}`,
|
|
185
|
-
fix:
|
|
242
|
+
fix: `Reinstall the ${mod.name} module`
|
|
186
243
|
};
|
|
187
244
|
}
|
|
188
245
|
|
|
189
|
-
return { name:
|
|
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
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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},
|
|
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
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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) {
|
package/scripts/docs-audit.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|