convoke-agents 2.0.1 → 2.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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [2.2.0] - 2026-03-14
11
+
12
+ ### Changed
13
+
14
+ - **Agent activation migrated from commands to skills** — `.claude/commands/bmad-agent-bme-*.md` replaced by `.claude/skills/bmad-agent-bme-{id}/SKILL.md` (BMAD v6.1.0 format)
15
+ - **Agent manifest uses v6.1.0 12-column schema** — BME agents now populate all fields including `canonicalId`, `module`, `communicationStyle`, `capabilities`
16
+ - **Removed redundant `createAgentManifest()`** from installer — `refreshInstallation()` is now the single code path for manifest generation
17
+
18
+ ### Added
19
+
20
+ - **`src/module.yaml`** — External module spec definition for future BMAD registration
21
+ - **Agent customize files** — `_bmad/_config/agents/bme-{name}.customize.yaml` generated on install (never overwritten)
22
+ - **Legacy command cleanup** — Automatically removes `.claude/commands/bmad-agent-bme-*` files from prior installs
23
+
24
+ ### Removed
25
+
26
+ - **`_bmad/bme/_config/module.yaml`** — Stale legacy file with deprecated agent references deleted
27
+
28
+ ---
29
+
10
30
  ## [2.0.0] - 2026-03-07
11
31
 
12
32
  ### Changed
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  Agent teams for complex systems
11
11
  ```
12
12
 
13
- [![Version](https://img.shields.io/badge/version-2.0.0-blue)](https://github.com/amalik/convoke-agents)
13
+ [![Version](https://img.shields.io/badge/version-2.0.1-blue)](https://github.com/amalik/convoke-agents)
14
14
  [![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
15
15
 
16
16
  </div>
@@ -155,7 +155,19 @@ Open `_bmad/bme/_vortex/config.yaml` and replace `{user}` with your name. Agents
155
155
 
156
156
  #### Activate an Agent
157
157
 
158
- **Claude Code / Terminal**
158
+ **Claude Code (skills)**
159
+
160
+ ```
161
+ /bmad-agent-bme-contextualization-expert # Emma 🎯
162
+ /bmad-agent-bme-discovery-empathy-expert # Isla 🔍
163
+ /bmad-agent-bme-research-convergence-specialist # Mila 🔬
164
+ /bmad-agent-bme-hypothesis-engineer # Liam 💡
165
+ /bmad-agent-bme-lean-experiments-specialist # Wade 🧪
166
+ /bmad-agent-bme-production-intelligence-specialist # Noah 📡
167
+ /bmad-agent-bme-learning-decision-expert # Max 🧭
168
+ ```
169
+
170
+ **Claude Code (terminal) / Other AI assistants**
159
171
 
160
172
  ```bash
161
173
  cat _bmad/bme/_vortex/agents/contextualization-expert.md # Emma 🎯
@@ -33,7 +33,7 @@ workflows:
33
33
  - learning-card
34
34
  - pivot-patch-persevere
35
35
  - vortex-navigation
36
- version: 1.6.2
36
+ version: 2.2.0
37
37
  user_name: '{user}'
38
38
  communication_language: en
39
39
  party_mode_enabled: true
@@ -56,9 +56,9 @@ cat _bmad/bme/_vortex/agents/contextualization-expert.md
56
56
 
57
57
  ---
58
58
 
59
- ### Method 2: Slash Command (BMAD Environments Only)
59
+ ### Method 2: Skill Activation (BMAD Environments Only)
60
60
 
61
- If your environment supports BMAD slash commands:
61
+ If your environment supports BMAD skills:
62
62
 
63
63
  ```
64
64
  /bmad-agent-bme-contextualization-expert
@@ -45,9 +45,9 @@ cat _bmad/bme/_vortex/agents/discovery-empathy-expert.md
45
45
 
46
46
  ---
47
47
 
48
- ### Method 2: Slash Command (BMAD Environments Only)
48
+ ### Method 2: Skill Activation (BMAD Environments Only)
49
49
 
50
- If your environment supports BMAD slash commands:
50
+ If your environment supports BMAD skills:
51
51
 
52
52
  ```
53
53
  /bmad-agent-bme-discovery-empathy-expert
@@ -57,9 +57,9 @@ cat _bmad/bme/_vortex/agents/hypothesis-engineer.md
57
57
 
58
58
  ---
59
59
 
60
- ### Method 2: Slash Command (BMAD Environments Only)
60
+ ### Method 2: Skill Activation (BMAD Environments Only)
61
61
 
62
- If your environment supports BMAD slash commands:
62
+ If your environment supports BMAD skills:
63
63
 
64
64
  ```
65
65
  /bmad-agent-bme-hypothesis-engineer
@@ -44,9 +44,9 @@ cat _bmad/bme/_vortex/agents/learning-decision-expert.md
44
44
 
45
45
  ---
46
46
 
47
- ### Method 2: Slash Command (BMAD Environments Only)
47
+ ### Method 2: Skill Activation (BMAD Environments Only)
48
48
 
49
- If your environment supports BMAD slash commands:
49
+ If your environment supports BMAD skills:
50
50
 
51
51
  ```
52
52
  /bmad-agent-bme-learning-decision-expert
@@ -56,9 +56,9 @@ cat _bmad/bme/_vortex/agents/research-convergence-specialist.md
56
56
 
57
57
  ---
58
58
 
59
- ### Method 2: Slash Command (BMAD Environments Only)
59
+ ### Method 2: Skill Activation (BMAD Environments Only)
60
60
 
61
- If your environment supports BMAD slash commands:
61
+ If your environment supports BMAD skills:
62
62
 
63
63
  ```
64
64
  /bmad-agent-bme-research-convergence-specialist
@@ -58,9 +58,9 @@ cat _bmad/bme/_vortex/agents/production-intelligence-specialist.md
58
58
 
59
59
  ---
60
60
 
61
- ### Method 2: Slash Command (BMAD Environments Only)
61
+ ### Method 2: Skill Activation (BMAD Environments Only)
62
62
 
63
- If your environment supports BMAD slash commands:
63
+ If your environment supports BMAD skills:
64
64
 
65
65
  ```
66
66
  /bmad-agent-bme-production-intelligence-specialist
@@ -57,9 +57,9 @@ cat _bmad/bme/_vortex/agents/lean-experiments-specialist.md
57
57
 
58
58
  ---
59
59
 
60
- ### Method 2: Slash Command (BMAD Environments Only)
60
+ ### Method 2: Skill Activation (BMAD Environments Only)
61
61
 
62
- If your environment supports BMAD slash commands:
62
+ If your environment supports BMAD skills:
63
63
 
64
64
  ```
65
65
  /bmad-agent-bme-lean-experiments-specialist
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "convoke-agents",
3
- "version": "2.0.1",
3
+ "version": "2.2.0",
4
4
  "description": "Agent teams for complex systems, compatible with BMad Method",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -11,7 +11,8 @@
11
11
  "UPDATE-GUIDE.md",
12
12
  "CHANGELOG.md",
13
13
  "LICENSE",
14
- "README.md"
14
+ "README.md",
15
+ "src/"
15
16
  ],
16
17
  "bin": {
17
18
  "convoke-install-vortex": "scripts/install-vortex-agents.js",
@@ -522,13 +522,13 @@ async function runAudit(opts = {}) {
522
522
  const content = fs.readFileSync(absPath, 'utf8');
523
523
  allDocsContent.push(content);
524
524
 
525
- // Skip stale-reference checks for CHANGELOG — historical entries
526
- // (e.g., "Added 4 agents" in v1.0) are accurate for their time period
525
+ // Skip stale-reference and broken-path checks for CHANGELOG — historical entries
526
+ // reference files that may have been deleted or renamed in past versions
527
527
  if (relPath !== 'CHANGELOG.md') {
528
528
  allFindings.push(...checkStaleReferences(content, relPath));
529
+ allFindings.push(...checkBrokenPaths(content, relPath, projectRoot));
529
530
  }
530
531
  allFindings.push(...checkBrokenLinks(content, relPath, projectRoot));
531
- allFindings.push(...checkBrokenPaths(content, relPath, projectRoot));
532
532
  allFindings.push(...checkIncompleteAgentTables(content, relPath));
533
533
  allFindings.push(...checkInternalNamingLeaks(content, relPath));
534
534
  allFindings.push(...checkStaleBrandReferences(content, relPath));
@@ -29,7 +29,7 @@ function printBanner() {
29
29
  }
30
30
 
31
31
  function checkPrerequisites(projectRoot) {
32
- console.log(`${CYAN}[1/6]${RESET} Checking prerequisites...`);
32
+ console.log(`${CYAN}[1/5]${RESET} Checking prerequisites...`);
33
33
 
34
34
  const bmadDir = path.join(projectRoot, '_bmad');
35
35
 
@@ -53,7 +53,7 @@ function checkPrerequisites(projectRoot) {
53
53
  }
54
54
 
55
55
  function archiveDeprecatedWorkflows(projectRoot) {
56
- console.log(`${CYAN}[2/6]${RESET} Archiving deprecated workflows...`);
56
+ console.log(`${CYAN}[2/5]${RESET} Archiving deprecated workflows...`);
57
57
 
58
58
  const sourceDir = path.join(__dirname, '..', '_bmad', 'bme', '_vortex');
59
59
  const targetDir = path.join(projectRoot, '_bmad', 'bme', '_vortex');
@@ -94,32 +94,8 @@ function cleanupLegacyFiles(projectRoot) {
94
94
  console.log(`${GREEN} ✓${RESET} Legacy cleanup complete`);
95
95
  }
96
96
 
97
- function csvEscape(value) {
98
- return `"${String(value).replace(/"/g, '""')}"`;
99
- }
100
-
101
- function createAgentManifest(projectRoot) {
102
- console.log(`${CYAN}[3/6]${RESET} Creating agent manifest...`);
103
-
104
- const manifestPath = path.join(projectRoot, '_bmad', '_config', 'agent-manifest.csv');
105
- fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
106
-
107
- const header = '"agent_id","name","title","icon","role","identity","communication_style","expertise","submodule","path"\n';
108
- const rows = AGENTS.map(a => {
109
- const p = a.persona;
110
- return [
111
- a.id, a.name, a.title, a.icon,
112
- p.role, p.identity, p.communication_style, p.expertise,
113
- 'bme', `_bmad/bme/_vortex/agents/${a.id}.md`,
114
- ].map(csvEscape).join(',');
115
- }).join('\n') + '\n';
116
-
117
- fs.writeFileSync(manifestPath, header + rows);
118
- console.log(`${GREEN} ✓${RESET} Created agent-manifest.csv`);
119
- }
120
-
121
97
  function createOutputDirectory(projectRoot) {
122
- console.log(`${CYAN}[4/6]${RESET} Setting up output directory...`);
98
+ console.log(`${CYAN}[3/5]${RESET} Setting up output directory...`);
123
99
 
124
100
  const outputDir = path.join(projectRoot, '_bmad-output', 'vortex-artifacts');
125
101
  fs.mkdirSync(outputDir, { recursive: true });
@@ -128,10 +104,11 @@ function createOutputDirectory(projectRoot) {
128
104
  }
129
105
 
130
106
  function verifyInstallation(projectRoot) {
131
- console.log(`${CYAN}[6/6]${RESET} Verifying installation...`);
107
+ console.log(`${CYAN}[5/5]${RESET} Verifying installation...`);
132
108
 
133
109
  const checks = [
134
110
  ...AGENTS.map(a => ({ path: `_bmad/bme/_vortex/agents/${a.id}.md`, name: `${a.name} agent file` })),
111
+ ...AGENTS.map(a => ({ path: `.claude/skills/bmad-agent-bme-${a.id}/SKILL.md`, name: `${a.name} skill` })),
135
112
  { path: '_bmad/bme/_vortex/config.yaml', name: 'Configuration file' },
136
113
  ];
137
114
 
@@ -174,11 +151,14 @@ function printSuccess() {
174
151
  console.log(` ${YELLOW}1.${RESET} Personalize your config:`);
175
152
  console.log(` Edit ${CYAN}_bmad/bme/_vortex/config.yaml${RESET} and replace ${YELLOW}{user}${RESET} with your name`);
176
153
  console.log('');
177
- console.log(` ${YELLOW}2.${RESET} Activate an agent by reading their file:`);
154
+ console.log(` ${YELLOW}2.${RESET} Activate an agent (skill) in Claude Code:`);
178
155
  for (const agent of AGENTS) {
179
- console.log(` ${CYAN}cat _bmad/bme/_vortex/agents/${agent.id}.md${RESET} (${agent.name})`);
156
+ console.log(` ${CYAN}/bmad-agent-bme-${agent.id}${RESET} (${agent.name})`);
180
157
  }
181
158
  console.log('');
159
+ console.log(` ${YELLOW}3.${RESET} Or read the agent file directly:`);
160
+ console.log(` ${CYAN}cat _bmad/bme/_vortex/agents/{agent-id}.md${RESET}`);
161
+ console.log('');
182
162
  }
183
163
 
184
164
  async function main() {
@@ -189,11 +169,10 @@ async function main() {
189
169
  printBanner();
190
170
  checkPrerequisites(projectRoot);
191
171
  archiveDeprecatedWorkflows(projectRoot);
192
- createAgentManifest(projectRoot);
193
172
  createOutputDirectory(projectRoot);
194
173
 
195
- // Use refreshInstallation for agents, workflows, config, and user guides
196
- console.log(`${CYAN}[5/6]${RESET} Installing agents, workflows, config, and guides...`);
174
+ // Use refreshInstallation for agents, workflows, config, guides, manifest, and skills
175
+ console.log(`${CYAN}[4/5]${RESET} Installing agents, workflows, config, and guides...`);
197
176
  await refreshInstallation(projectRoot, { backupGuides: false });
198
177
  console.log(`${GREEN} ✓${RESET} Installation refreshed`);
199
178
 
@@ -112,31 +112,96 @@ async function refreshInstallation(projectRoot, options = {}) {
112
112
  return `"${String(value).replace(/"/g, '""')}"`;
113
113
  }
114
114
 
115
- const header = '"agent_id","name","title","icon","role","identity","communication_style","expertise","submodule","path"';
115
+ function parseCSVRow(row) {
116
+ const fields = [];
117
+ let current = '';
118
+ let inQuotes = false;
119
+ for (let i = 0; i < row.length; i++) {
120
+ const ch = row[i];
121
+ if (inQuotes) {
122
+ if (ch === '"' && row[i + 1] === '"') {
123
+ current += '"';
124
+ i++;
125
+ } else if (ch === '"') {
126
+ inQuotes = false;
127
+ } else {
128
+ current += ch;
129
+ }
130
+ } else if (ch === '"') {
131
+ inQuotes = true;
132
+ } else if (ch === ',') {
133
+ fields.push(current);
134
+ current = '';
135
+ } else {
136
+ current += ch;
137
+ }
138
+ }
139
+ fields.push(current);
140
+ return fields;
141
+ }
116
142
 
117
- // Read existing non-bme rows to preserve them
143
+ const V610_HEADER = 'name,displayName,title,icon,capabilities,role,identity,communicationStyle,principles,module,path,canonicalId';
144
+ // Detect schema from existing manifest or default to v6.1.0
145
+ let header;
146
+ let isV610 = true;
118
147
  let preservedRows = [];
148
+
119
149
  if (fs.existsSync(manifestPath)) {
120
150
  const existing = (await fs.readFile(manifestPath, 'utf8')).trim().split('\n');
121
- // Skip header, keep rows where submodule is NOT bme
151
+ header = existing[0];
152
+ isV610 = header.startsWith('name,') || header.includes('canonicalId');
153
+
154
+ // Filter out bme rows, preserve everything else
122
155
  preservedRows = existing.slice(1).filter(row => {
123
- // submodule is the 9th field (index 8) in the CSV
124
- const fields = row.match(/"([^"]*(?:""[^"]*)*)"/g);
125
- if (!fields || fields.length < 9) return true; // keep unrecognised rows
126
- const submodule = fields[8].replace(/^"|"$/g, '');
127
- return submodule !== 'bme';
156
+ if (!row.trim()) return false;
157
+ if (isV610) {
158
+ // v6.1.0: module is column 10 (index 9) handle quoted CSV fields
159
+ const parsed = parseCSVRow(row);
160
+ if (!parsed || parsed.length < 10) return true;
161
+ return parsed[9] !== 'bme';
162
+ } else {
163
+ // Legacy: submodule is column 9 (index 8) — quoted CSV
164
+ const fields = row.match(/"([^"]*(?:""[^"]*)*)"/g);
165
+ if (!fields || fields.length < 9) return true;
166
+ const submodule = fields[8].replace(/^"|"$/g, '');
167
+ return submodule !== 'bme';
168
+ }
128
169
  });
170
+ } else {
171
+ header = V610_HEADER;
172
+ isV610 = true;
129
173
  }
130
174
 
131
- // Build fresh bme rows from registry
132
- const bmeRows = AGENTS.map(a => {
133
- const p = a.persona;
134
- return [
135
- a.id, a.name, a.title, a.icon,
136
- p.role, p.identity, p.communication_style, p.expertise,
137
- 'bme', `_bmad/bme/_vortex/agents/${a.id}.md`,
138
- ].map(csvEscape).join(',');
139
- });
175
+ // Build fresh bme rows matching the detected schema
176
+ let bmeRows;
177
+ if (isV610) {
178
+ bmeRows = AGENTS.map(a => {
179
+ const p = a.persona;
180
+ return [
181
+ csvEscape(a.name), // name
182
+ csvEscape(''), // displayName
183
+ csvEscape(a.title), // title
184
+ csvEscape(a.icon), // icon
185
+ csvEscape(''), // capabilities
186
+ csvEscape(p.role), // role
187
+ csvEscape(p.identity), // identity
188
+ csvEscape(p.communication_style), // communicationStyle
189
+ csvEscape(p.expertise), // principles
190
+ csvEscape('bme'), // module
191
+ csvEscape(`_bmad/bme/_vortex/agents/${a.id}.md`), // path
192
+ csvEscape(`bmad-agent-bme-${a.id}`), // canonicalId
193
+ ].join(',');
194
+ });
195
+ } else {
196
+ bmeRows = AGENTS.map(a => {
197
+ const p = a.persona;
198
+ return [
199
+ a.id, a.name, a.title, a.icon,
200
+ p.role, p.identity, p.communication_style, p.expertise,
201
+ 'bme', `_bmad/bme/_vortex/agents/${a.id}.md`,
202
+ ].map(csvEscape).join(',');
203
+ });
204
+ }
140
205
 
141
206
  const allRows = [...preservedRows, ...bmeRows].join('\n') + '\n';
142
207
  await fs.writeFile(manifestPath, header + '\n' + allRows, 'utf8');
@@ -171,6 +236,98 @@ async function refreshInstallation(projectRoot, options = {}) {
171
236
  if (verbose) console.log(' Skipped guide copy (dev environment)');
172
237
  }
173
238
 
239
+ // 6. Clean up legacy .claude/commands/ and generate .claude/skills/ for each agent
240
+ const commandsDir = path.join(projectRoot, '.claude', 'commands');
241
+ if (fs.existsSync(commandsDir)) {
242
+ const legacyCommands = (await fs.readdir(commandsDir)).filter(f => f.startsWith('bmad-agent-bme-'));
243
+ for (const file of legacyCommands) {
244
+ await fs.remove(path.join(commandsDir, file));
245
+ changes.push(`Removed legacy command: ${file}`);
246
+ if (verbose) console.log(` Removed legacy command: ${file}`);
247
+ }
248
+ }
249
+
250
+ const skillsDir = path.join(projectRoot, '.claude', 'skills');
251
+
252
+ // Remove stale skill directories (agents no longer in registry)
253
+ const currentSkillDirs = new Set(AGENTS.map(a => `bmad-agent-bme-${a.id}`));
254
+ if (fs.existsSync(skillsDir)) {
255
+ const existingSkills = (await fs.readdir(skillsDir)).filter(d => d.startsWith('bmad-agent-bme-'));
256
+ for (const dir of existingSkills) {
257
+ if (!currentSkillDirs.has(dir)) {
258
+ await fs.remove(path.join(skillsDir, dir));
259
+ changes.push(`Removed stale skill: ${dir}`);
260
+ if (verbose) console.log(` Removed stale skill: ${dir}`);
261
+ }
262
+ }
263
+ }
264
+
265
+ for (const agent of AGENTS) {
266
+ const skillDir = path.join(skillsDir, `bmad-agent-bme-${agent.id}`);
267
+ await fs.ensureDir(skillDir);
268
+ const content = `---
269
+ name: bmad-agent-bme-${agent.id}
270
+ description: ${agent.id} agent
271
+ ---
272
+
273
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
274
+
275
+ <agent-activation CRITICAL="TRUE">
276
+ 1. LOAD the FULL agent file from {project-root}/_bmad/bme/_vortex/agents/${agent.id}.md
277
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
278
+ 3. FOLLOW every step in the <activation> section precisely
279
+ 4. DISPLAY the welcome/greeting as instructed
280
+ 5. PRESENT the numbered menu
281
+ 6. WAIT for user input before proceeding
282
+ </agent-activation>
283
+ `;
284
+ await fs.writeFile(path.join(skillDir, 'SKILL.md'), content, 'utf8');
285
+ changes.push(`Refreshed skill: bmad-agent-bme-${agent.id}/SKILL.md`);
286
+ if (verbose) console.log(` Refreshed skill: bmad-agent-bme-${agent.id}/SKILL.md`);
287
+ }
288
+
289
+ // 7. Generate agent customize files (only if they don't already exist)
290
+ const customizeDir = path.join(projectRoot, '_bmad', '_config', 'agents');
291
+ await fs.ensureDir(customizeDir);
292
+
293
+ const CUSTOMIZE_TEMPLATE = `# Agent Customization
294
+ # Customize any section below - all are optional
295
+
296
+ # Override agent name
297
+ agent:
298
+ metadata:
299
+ name: ""
300
+
301
+ # Replace entire persona (not merged)
302
+ persona:
303
+ role: ""
304
+ identity: ""
305
+ communication_style: ""
306
+ principles: []
307
+
308
+ # Add custom critical actions (appended after standard config loading)
309
+ critical_actions: []
310
+
311
+ # Add persistent memories for the agent
312
+ memories: []
313
+
314
+ # Add custom menu items (appended to base menu)
315
+ menu: []
316
+
317
+ # Add custom prompts (for action="#id" handlers)
318
+ prompts: []
319
+ `;
320
+
321
+ for (const agent of AGENTS) {
322
+ const filename = `bme-${agent.name.toLowerCase()}.customize.yaml`;
323
+ const filePath = path.join(customizeDir, filename);
324
+ if (!fs.existsSync(filePath)) {
325
+ await fs.writeFile(filePath, CUSTOMIZE_TEMPLATE, 'utf8');
326
+ changes.push(`Created customize file: ${filename}`);
327
+ if (verbose) console.log(` Created customize file: ${filename}`);
328
+ }
329
+ }
330
+
174
331
  return changes;
175
332
  }
176
333
 
@@ -0,0 +1,6 @@
1
+ code: bme
2
+ name: "Convoke: Vortex Discovery Framework"
3
+ header: "Convoke — Vortex Discovery Framework"
4
+ subheader: "7 AI agents for product discovery based on the Shiftup Innovation Vortex"
5
+ description: "Domain-specialized agent teams for structured product discovery: Contextualize, Empathize, Synthesize, Hypothesize, Externalize, Sensitize, Systematize"
6
+ default_selected: false