convoke-agents 3.1.0 → 3.2.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 (78) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +1 -1
  3. package/_bmad/bme/_artifacts/config.yaml +15 -0
  4. package/_bmad/bme/_artifacts/workflows/bmad-migrate-artifacts/SKILL.md +6 -0
  5. package/_bmad/bme/_artifacts/workflows/bmad-migrate-artifacts/steps/step-01-scope.md +138 -0
  6. package/_bmad/bme/_artifacts/workflows/bmad-migrate-artifacts/steps/step-02-dryrun.md +199 -0
  7. package/_bmad/bme/_artifacts/workflows/bmad-migrate-artifacts/steps/step-03-resolve.md +174 -0
  8. package/_bmad/bme/_artifacts/workflows/bmad-migrate-artifacts/steps/step-04-execute.md +213 -0
  9. package/_bmad/bme/_artifacts/workflows/bmad-migrate-artifacts/workflow.md +85 -0
  10. package/_bmad/bme/_artifacts/workflows/bmad-portfolio-status/SKILL.md +6 -0
  11. package/_bmad/bme/_artifacts/workflows/bmad-portfolio-status/steps/step-01-scan.md +131 -0
  12. package/_bmad/bme/_artifacts/workflows/bmad-portfolio-status/steps/step-02-explore.md +131 -0
  13. package/_bmad/bme/_artifacts/workflows/bmad-portfolio-status/steps/step-03-recommend.md +149 -0
  14. package/_bmad/bme/_artifacts/workflows/bmad-portfolio-status/workflow.md +78 -0
  15. package/_bmad/bme/_portability/skills/bmad-export-skill/SKILL.md +6 -0
  16. package/_bmad/bme/_portability/skills/bmad-export-skill/workflow.md +74 -0
  17. package/_bmad/bme/_portability/skills/bmad-generate-catalog/SKILL.md +6 -0
  18. package/_bmad/bme/_portability/skills/bmad-generate-catalog/workflow.md +42 -0
  19. package/_bmad/bme/_portability/skills/bmad-seed-catalog/SKILL.md +6 -0
  20. package/_bmad/bme/_portability/skills/bmad-seed-catalog/workflow.md +61 -0
  21. package/_bmad/bme/_portability/skills/bmad-validate-exports/SKILL.md +6 -0
  22. package/_bmad/bme/_portability/skills/bmad-validate-exports/workflow.md +43 -0
  23. package/_bmad/bme/_team-factory/agents/team-factory.md +128 -0
  24. package/_bmad/bme/_team-factory/config.yaml +13 -0
  25. package/_bmad/bme/_team-factory/lib/cascade-logic.js +184 -0
  26. package/_bmad/bme/_team-factory/lib/collision-detector.js +228 -0
  27. package/_bmad/bme/_team-factory/lib/manifest-tracker.js +214 -0
  28. package/_bmad/bme/_team-factory/lib/spec-differ.js +176 -0
  29. package/_bmad/bme/_team-factory/lib/spec-parser.js +201 -0
  30. package/_bmad/bme/_team-factory/lib/spec-writer.js +128 -0
  31. package/_bmad/bme/_team-factory/lib/types/factory-types.js +193 -0
  32. package/_bmad/bme/_team-factory/lib/utils/csv-utils.js +62 -0
  33. package/_bmad/bme/_team-factory/lib/utils/naming-utils.js +45 -0
  34. package/_bmad/bme/_team-factory/lib/validators/end-to-end-validator.js +898 -0
  35. package/_bmad/bme/_team-factory/lib/writers/activation-validator.js +175 -0
  36. package/_bmad/bme/_team-factory/lib/writers/config-appender.js +192 -0
  37. package/_bmad/bme/_team-factory/lib/writers/config-creator.js +215 -0
  38. package/_bmad/bme/_team-factory/lib/writers/csv-appender.js +118 -0
  39. package/_bmad/bme/_team-factory/lib/writers/csv-creator.js +190 -0
  40. package/_bmad/bme/_team-factory/lib/writers/registry-appender.js +372 -0
  41. package/_bmad/bme/_team-factory/lib/writers/registry-writer.js +409 -0
  42. package/_bmad/bme/_team-factory/module-help.csv +3 -0
  43. package/_bmad/bme/_team-factory/schemas/schema-independent.json +147 -0
  44. package/_bmad/bme/_team-factory/schemas/schema-sequential.json +242 -0
  45. package/_bmad/bme/_team-factory/templates/team-spec-template.yaml +86 -0
  46. package/_bmad/bme/_team-factory/workflows/add-team/step-01-scope.md +105 -0
  47. package/_bmad/bme/_team-factory/workflows/add-team/step-02-connect.md +110 -0
  48. package/_bmad/bme/_team-factory/workflows/add-team/step-03-review.md +116 -0
  49. package/_bmad/bme/_team-factory/workflows/add-team/step-04-generate.md +160 -0
  50. package/_bmad/bme/_team-factory/workflows/add-team/step-05-validate.md +146 -0
  51. package/_bmad/bme/_team-factory/workflows/step-00-route.md +76 -0
  52. package/_bmad/bme/_vortex/config.yaml +4 -4
  53. package/package.json +12 -7
  54. package/scripts/convoke-doctor.js +172 -1
  55. package/scripts/install-gyre-agents.js +0 -0
  56. package/scripts/lib/artifact-utils.js +521 -13
  57. package/scripts/lib/portfolio/portfolio-engine.js +301 -34
  58. package/scripts/lib/portfolio/rules/artifact-chain-rule.js +33 -3
  59. package/scripts/lib/portfolio/rules/conflict-resolver.js +22 -0
  60. package/scripts/migrate-artifacts.js +69 -10
  61. package/scripts/portability/catalog-generator.js +353 -0
  62. package/scripts/portability/classify-skills.js +646 -0
  63. package/scripts/portability/convoke-export.js +522 -0
  64. package/scripts/portability/export-engine.js +1133 -0
  65. package/scripts/portability/generate-adapters.js +79 -0
  66. package/scripts/portability/manifest-csv.js +147 -0
  67. package/scripts/portability/seed-catalog-repo.js +427 -0
  68. package/scripts/portability/templates/canonical-example.md +102 -0
  69. package/scripts/portability/templates/canonical-format.md +218 -0
  70. package/scripts/portability/templates/readme-template.md +72 -0
  71. package/scripts/portability/test-constants.js +42 -0
  72. package/scripts/portability/validate-classification.js +529 -0
  73. package/scripts/portability/validate-exports.js +348 -0
  74. package/scripts/update/lib/agent-registry.js +35 -0
  75. package/scripts/update/lib/config-merger.js +140 -10
  76. package/scripts/update/lib/refresh-installation.js +293 -8
  77. package/scripts/update/lib/utils.js +27 -1
  78. package/scripts/update/lib/validator.js +114 -4
@@ -0,0 +1,353 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * catalog-generator.js — Story sp-3-1
4
+ *
5
+ * Generates a decision-tree catalog README from skill-manifest.csv and
6
+ * agent-manifest.csv. The catalog is organized by user intent ("I need to...")
7
+ * so consultants new to agentic tools can find the right skill quickly.
8
+ *
9
+ * Usage:
10
+ * node scripts/portability/catalog-generator.js # stdout
11
+ * node scripts/portability/catalog-generator.js --output <path>
12
+ * node scripts/portability/catalog-generator.js --help
13
+ *
14
+ * Read-only on the source tree — reads two CSV manifests, writes one file
15
+ * (or stdout).
16
+ */
17
+
18
+ 'use strict';
19
+
20
+ const fs = require('fs');
21
+ const path = require('path');
22
+ const { findProjectRoot } = require('../update/lib/utils');
23
+ const { readManifest } = require('./manifest-csv');
24
+ const { resolvePersonaSummary, loadAgentManifest } = require('./export-engine');
25
+
26
+ // =============================================================================
27
+ // CONSTANTS
28
+ // =============================================================================
29
+
30
+ const INTENT_TO_HEADING = {
31
+ 'think-through-problem': 'I need to think through a problem',
32
+ 'define-what-to-build': 'I need to define what to build',
33
+ 'review-something': 'I need to review something',
34
+ 'write-documentation': 'I need to write documentation',
35
+ 'plan-your-work': 'I need to plan my work',
36
+ 'test-your-code': 'I need to test my code',
37
+ 'discover-product-fit': 'I need to discover product-market fit',
38
+ 'assess-readiness': 'I need to assess production readiness',
39
+ 'meta-platform': null, // excluded from catalog
40
+ };
41
+
42
+ const TIER_BADGES = {
43
+ standalone: '**✅ Ready to use**',
44
+ 'light-deps': '**📦 Needs setup**',
45
+ pipeline: '**🔒 Framework only** (Requires full Convoke installation)',
46
+ };
47
+
48
+ // Intent display order: standalone-heavy intents first, pipeline-only last
49
+ const INTENT_ORDER = [
50
+ 'think-through-problem',
51
+ 'define-what-to-build',
52
+ 'review-something',
53
+ 'write-documentation',
54
+ 'plan-your-work',
55
+ 'test-your-code',
56
+ 'discover-product-fit',
57
+ 'assess-readiness',
58
+ ];
59
+
60
+ // =============================================================================
61
+ // HELPERS
62
+ // =============================================================================
63
+
64
+ /**
65
+ * Truncate description to first sentence (period + space) or 120 chars.
66
+ */
67
+ function truncateDescription(desc) {
68
+ if (!desc) return '';
69
+ const periodIdx = desc.indexOf('. ');
70
+ if (periodIdx > 0 && periodIdx < 120) {
71
+ return desc.slice(0, periodIdx + 1);
72
+ }
73
+ if (desc.length <= 120) return desc;
74
+ return desc.slice(0, 120) + '...';
75
+ }
76
+
77
+ /**
78
+ * Render a single skill entry line.
79
+ */
80
+ function renderSkillEntry(skill) {
81
+ const icon = skill.icon || '🔧';
82
+ const badge = TIER_BADGES[skill.tier] || skill.tier;
83
+ const desc = truncateDescription(skill.description);
84
+ const link = `[→ instructions](./${skill.name}/)`;
85
+ return `- ${icon} **${skill.personaName}** — ${desc} ${badge} ${link}`;
86
+ }
87
+
88
+ // =============================================================================
89
+ // CATALOG GENERATION
90
+ // =============================================================================
91
+
92
+ function generateCatalog(projectRoot) {
93
+ // Load manifests
94
+ const skillManifestPath = path.join(projectRoot, '_bmad', '_config', 'skill-manifest.csv');
95
+ const { header, rows } = readManifest(skillManifestPath);
96
+ const agents = loadAgentManifest(projectRoot);
97
+
98
+ const nameIdx = header.indexOf('name');
99
+ const tierIdx = header.indexOf('tier');
100
+ const intentIdx = header.indexOf('intent');
101
+ const descIdx = header.indexOf('description');
102
+
103
+ // Dedupe by skill name (first row wins)
104
+ const seen = new Set();
105
+ const skills = [];
106
+ for (const row of rows) {
107
+ const name = row[nameIdx];
108
+ if (seen.has(name)) continue;
109
+ seen.add(name);
110
+
111
+ const intent = row[intentIdx] || 'unknown';
112
+ const tier = row[tierIdx] || 'unknown';
113
+
114
+ // Skip meta-platform
115
+ if (intent === 'meta-platform') continue;
116
+
117
+ const persona = resolvePersonaSummary(name, agents);
118
+ skills.push({
119
+ name,
120
+ tier,
121
+ intent,
122
+ description: row[descIdx] || '',
123
+ personaName: persona.name,
124
+ icon: persona.icon,
125
+ });
126
+ }
127
+
128
+ // Count by tier
129
+ const standaloneCount = skills.filter((s) => s.tier === 'standalone').length;
130
+ const lightDepsCount = skills.filter((s) => s.tier === 'light-deps').length;
131
+ const pipelineCount = skills.filter((s) => s.tier === 'pipeline').length;
132
+ const mainBodyCount = standaloneCount + lightDepsCount;
133
+
134
+ // Group by intent
135
+ const byIntent = {};
136
+ for (const skill of skills) {
137
+ if (!byIntent[skill.intent]) byIntent[skill.intent] = [];
138
+ byIntent[skill.intent].push(skill);
139
+ }
140
+ // Sort skills alphabetically within each intent
141
+ for (const intent of Object.keys(byIntent)) {
142
+ byIntent[intent].sort((a, b) => a.name.localeCompare(b.name));
143
+ }
144
+
145
+ // Warn on unknown intents
146
+ for (const intent of Object.keys(byIntent)) {
147
+ if (!(intent in INTENT_TO_HEADING)) {
148
+ process.stderr.write(`Warning: unknown intent "${intent}" — using fallback heading\n`);
149
+ }
150
+ }
151
+
152
+ // === Render ===
153
+ const lines = [];
154
+
155
+ // Header
156
+ lines.push('# Convoke Skills Catalog');
157
+ lines.push('');
158
+ lines.push('> Find the right AI skill for your task. Browse by what you\'re trying to do.');
159
+ lines.push('');
160
+ lines.push('## How to use a skill');
161
+ lines.push('');
162
+ lines.push('1. Find your intent below — what are you trying to do?');
163
+ lines.push('2. Pick a skill marked **✅ Ready to use**');
164
+ lines.push('3. Copy the skill folder into your project\'s `.claude/skills/` directory');
165
+ lines.push('');
166
+ lines.push('### Tier legend');
167
+ lines.push('');
168
+ lines.push('- **✅ Ready to use** — standalone skill, just copy and go');
169
+ lines.push('- **📦 Needs setup** — includes templates/config that need minor configuration');
170
+ lines.push('- **🔒 Framework only** — requires full Convoke installation');
171
+ lines.push('');
172
+ lines.push(
173
+ `**${mainBodyCount} skills in this catalog** (${standaloneCount} ready to use, ${lightDepsCount} need setup) | ${pipelineCount} framework-only skills listed below`
174
+ );
175
+ lines.push('');
176
+ lines.push('---');
177
+ lines.push('');
178
+
179
+ // Main body: Tier 1 + Tier 2 skills grouped by intent
180
+ for (const intent of INTENT_ORDER) {
181
+ const heading = INTENT_TO_HEADING[intent];
182
+ if (!heading) continue; // meta-platform excluded
183
+
184
+ const intentSkills = (byIntent[intent] || []).filter(
185
+ (s) => s.tier === 'standalone' || s.tier === 'light-deps'
186
+ );
187
+ if (intentSkills.length === 0) continue;
188
+
189
+ lines.push(`## ${heading}`);
190
+ lines.push('');
191
+ for (const skill of intentSkills) {
192
+ lines.push(renderSkillEntry(skill));
193
+ }
194
+ lines.push('');
195
+ }
196
+
197
+ // Render any unknown-intent skills with fallback heading (spec AC #2)
198
+ for (const intent of Object.keys(byIntent)) {
199
+ if (intent in INTENT_TO_HEADING) continue; // already rendered above
200
+ const intentSkills = byIntent[intent].filter(
201
+ (s) => s.tier === 'standalone' || s.tier === 'light-deps'
202
+ );
203
+ if (intentSkills.length === 0) continue;
204
+ lines.push(`## I need to: ${intent}`);
205
+ lines.push('');
206
+ for (const skill of intentSkills) {
207
+ lines.push(renderSkillEntry(skill));
208
+ }
209
+ lines.push('');
210
+ }
211
+
212
+ // Collapsed section: Tier 3 pipeline skills
213
+ const pipelineSkills = skills.filter((s) => s.tier === 'pipeline');
214
+ if (pipelineSkills.length > 0) {
215
+ lines.push('---');
216
+ lines.push('');
217
+ lines.push('<details>');
218
+ lines.push('<summary><strong>Framework-only skills (requires Convoke installation)</strong></summary>');
219
+ lines.push('');
220
+
221
+ // Group pipeline skills by intent too
222
+ const pipelineByIntent = {};
223
+ for (const skill of pipelineSkills) {
224
+ if (!pipelineByIntent[skill.intent]) pipelineByIntent[skill.intent] = [];
225
+ pipelineByIntent[skill.intent].push(skill);
226
+ }
227
+
228
+ for (const intent of INTENT_ORDER) {
229
+ const heading = INTENT_TO_HEADING[intent];
230
+ if (!heading) continue;
231
+ const intentSkills = pipelineByIntent[intent] || [];
232
+ if (intentSkills.length === 0) continue;
233
+
234
+ lines.push(`### ${heading}`);
235
+ lines.push('');
236
+ for (const skill of intentSkills) {
237
+ lines.push(renderSkillEntry(skill));
238
+ }
239
+ lines.push('');
240
+ }
241
+
242
+ // Also render unknown-intent pipeline skills
243
+ for (const intent of Object.keys(pipelineByIntent)) {
244
+ if (intent in INTENT_TO_HEADING) continue;
245
+ const unknownSkills = pipelineByIntent[intent] || [];
246
+ if (unknownSkills.length === 0) continue;
247
+ lines.push(`### I need to: ${intent}`);
248
+ lines.push('');
249
+ for (const skill of unknownSkills) {
250
+ lines.push(renderSkillEntry(skill));
251
+ }
252
+ lines.push('');
253
+ }
254
+
255
+ lines.push('</details>');
256
+ lines.push('');
257
+ }
258
+
259
+ // Footer
260
+ lines.push('---');
261
+ lines.push('');
262
+ lines.push(`*Generated by \`convoke-export\` — do not edit manually.*`);
263
+ lines.push(`*Generated on ${new Date().toISOString().slice(0, 10)}.*`);
264
+ lines.push('');
265
+ lines.push('For the full Convoke framework, see the [Convoke Agents repository](https://github.com/amalik/convoke-agents).');
266
+ lines.push('');
267
+
268
+ return lines.join('\n');
269
+ }
270
+
271
+ // =============================================================================
272
+ // CLI
273
+ // =============================================================================
274
+
275
+ function printHelp() {
276
+ process.stdout.write(
277
+ [
278
+ 'Usage: catalog-generator [options]',
279
+ '',
280
+ 'Generate a decision-tree skill catalog README from manifest data.',
281
+ '',
282
+ 'Options:',
283
+ ' --output <path> Write catalog to file (default: stdout)',
284
+ ' --help, -h Show this help message',
285
+ '',
286
+ 'Exit codes:',
287
+ ' 0 Success',
288
+ ' 1 Usage error',
289
+ ' 2 Manifest read failure',
290
+ '',
291
+ ].join('\n')
292
+ );
293
+ }
294
+
295
+ function main() {
296
+ const argv = process.argv.slice(2);
297
+
298
+ if (argv.includes('--help') || argv.includes('-h')) {
299
+ printHelp();
300
+ return 0;
301
+ }
302
+
303
+ let outputPath = null;
304
+ for (let i = 0; i < argv.length; i++) {
305
+ if (argv[i] === '--output') {
306
+ outputPath = argv[++i];
307
+ if (!outputPath) {
308
+ process.stderr.write('Error: --output requires a path argument\n');
309
+ return 1;
310
+ }
311
+ } else if (argv[i].startsWith('--')) {
312
+ process.stderr.write(`Unknown flag: ${argv[i]}. Run --help for usage.\n`);
313
+ return 1;
314
+ }
315
+ }
316
+
317
+ let projectRoot;
318
+ try {
319
+ projectRoot = findProjectRoot();
320
+ } catch (e) {
321
+ process.stderr.write(`Error: could not find project root — ${e.message}\n`);
322
+ return 2;
323
+ }
324
+
325
+ let catalog;
326
+ try {
327
+ catalog = generateCatalog(projectRoot);
328
+ } catch (e) {
329
+ process.stderr.write(`Error generating catalog: ${e.message}\n`);
330
+ return 2;
331
+ }
332
+
333
+ if (outputPath) {
334
+ try {
335
+ const dir = path.dirname(outputPath);
336
+ fs.mkdirSync(dir, { recursive: true });
337
+ fs.writeFileSync(outputPath, catalog);
338
+ } catch (e) {
339
+ process.stderr.write(`Error writing catalog: ${e.message}\n`);
340
+ return 2;
341
+ }
342
+ } else {
343
+ process.stdout.write(catalog);
344
+ }
345
+
346
+ return 0;
347
+ }
348
+
349
+ if (require.main === module) {
350
+ process.exit(main());
351
+ }
352
+
353
+ module.exports = { generateCatalog, main };