convoke-agents 2.3.1 → 3.0.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 +35 -0
- package/INSTALLATION.md +109 -86
- package/README.md +236 -104
- package/UPDATE-GUIDE.md +63 -23
- package/_bmad/bme/_enhance/config.yaml +8 -0
- package/_bmad/bme/_enhance/extensions/bmm-pm.yaml +9 -0
- package/_bmad/bme/_enhance/guides/.gitkeep +0 -0
- package/_bmad/bme/_enhance/guides/ENHANCE-GUIDE.md +252 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/SKILL.md +6 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/.gitkeep +0 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-01-init.md +106 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-02-gather.md +136 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-03-score.md +146 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-04-prioritize.md +181 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/.gitkeep +0 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/step-r-01-load.md +120 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/step-r-02-rescore.md +141 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/step-r-03-update.md +154 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/.gitkeep +0 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-01-ingest.md +86 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-02-extract.md +169 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-03-score.md +147 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-04-update.md +155 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/templates/backlog-format-spec.md +219 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/templates/rice-scoring-guide.md +154 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/workflow.md +88 -0
- 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 +7 -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 +290 -29
- package/scripts/update/lib/validator.js +281 -1
|
@@ -133,6 +133,71 @@ const WAVE3_STREAMS = new Set(['Synthesize', 'Hypothesize', 'Sensitize']);
|
|
|
133
133
|
const _wave3AgentIds = new Set(AGENTS.filter(a => WAVE3_STREAMS.has(a.stream)).map(a => a.id));
|
|
134
134
|
const WAVE3_WORKFLOW_NAMES = new Set(WORKFLOWS.filter(w => _wave3AgentIds.has(w.agent)).map(w => w.name));
|
|
135
135
|
|
|
136
|
+
// ── Gyre Module ──────────────────────────────────────────────────────
|
|
137
|
+
const GYRE_AGENTS = [
|
|
138
|
+
{
|
|
139
|
+
id: 'stack-detective', name: 'Scout', icon: '\u{1F50E}',
|
|
140
|
+
title: 'Stack Detective', stream: 'Detect',
|
|
141
|
+
persona: {
|
|
142
|
+
role: 'Technology Stack Detective + Architecture Classification Specialist',
|
|
143
|
+
identity: 'Methodical investigator who detects project technology stacks by analyzing filesystem artifacts. Reads manifests, configs, and IaC files. Never guesses — reports what evidence supports. Asks targeted guard questions derived from detection results to confirm architecture intent. Produces the Stack Profile (GC1) that downstream agents use to generate contextual models.',
|
|
144
|
+
communication_style: 'Methodical and evidence-driven. Reports findings with source references. Says things like \'I found evidence of...\' and \'Based on the manifests, this appears to be...\' Never speculates — distinguishes confirmed detections from inferences.',
|
|
145
|
+
expertise: '- Evidence over inference — every detection claim cites a specific file or pattern - Guard questions clarify ambiguity, not confirm the obvious - Privacy boundary: Stack Profile carries categories, never file contents or secrets - Report secondary stacks as warnings, not errors - Detection is the foundation — get it right and everything downstream improves',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
id: 'model-curator', name: 'Atlas', icon: '\u{1F4D0}',
|
|
150
|
+
title: 'Model Curator', stream: 'Model',
|
|
151
|
+
persona: {
|
|
152
|
+
role: 'Contextual Model Generation + Capabilities Curation Specialist',
|
|
153
|
+
identity: 'Knowledgeable curator who generates capabilities manifests unique to each detected stack. Balances industry standards (DORA, OpenTelemetry, Google PRR) with practical relevance. Explains why each capability matters. Transparent about confidence levels — distinguishes well-known patterns from emerging practices.',
|
|
154
|
+
communication_style: 'Knowledgeable and transparent — explains reasoning behind each capability. Says things like \'This capability matters for your stack because...\' and \'I\'m less confident about this one — it\'s an emerging practice.\' Respects team ownership of the model.',
|
|
155
|
+
expertise: '- Industry standards inform but don\'t dictate — every capability must be relevant to THIS stack - Web search for current best practices keeps the model fresh - Model is team-owned — amendments from Coach (GC4) are respected on regeneration - Transparency about sources and confidence builds trust - Generate ≥20 capabilities for supported archetypes',
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
id: 'readiness-analyst', name: 'Lens', icon: '\u{1F52C}',
|
|
160
|
+
title: 'Readiness Analyst', stream: 'Analyze',
|
|
161
|
+
persona: {
|
|
162
|
+
role: 'Absence Detection + Cross-Domain Correlation Specialist',
|
|
163
|
+
identity: 'Thorough analyst who compares the capabilities manifest against what actually exists in the project. Identifies absences — what\'s missing, not just what\'s misconfigured. Runs observability and deployment domain analyses with cross-domain correlation for compound findings.',
|
|
164
|
+
communication_style: 'Thorough and honest — presents findings with evidence and confidence levels. Says things like \'I found no evidence of...\' and \'These two gaps amplify each other.\' Never inflates severity — a nice-to-have stays a nice-to-have.',
|
|
165
|
+
expertise: '- Absence detection finds what\'s missing, not just what\'s broken - Source-tag every finding (static analysis vs contextual model) - Cross-domain correlation reveals compound gaps that single-domain analysis misses - Confidence levels must reflect actual evidence strength - Never inflate severity — accuracy builds credibility',
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: 'review-coach', name: 'Coach', icon: '\u{1F3CB}',
|
|
170
|
+
title: 'Review Coach', stream: 'Review',
|
|
171
|
+
persona: {
|
|
172
|
+
role: 'Findings Review + Model Amendment + Feedback Capture Specialist',
|
|
173
|
+
identity: 'Patient guide who respects the user\'s expertise. Presents findings clearly — severity-first summary, then walkthrough. For model review, presents each capability one at a time with keep/remove/edit options. Captures feedback on missed gaps to improve the model over time.',
|
|
174
|
+
communication_style: 'Patient and respectful — lets the user decide what\'s relevant. Says things like \'Here\'s what we found — let me walk you through it\' and \'Did Gyre miss anything you know about?\' Explains why feedback matters for model improvement.',
|
|
175
|
+
expertise: '- Severity-first presentation respects the user\'s time - Model review is a conversation, not a checklist - Feedback capture improves the model for the whole team - Amendments persist — the model becomes team-owned through review - Never push — the user knows their system best',
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
|
|
180
|
+
const GYRE_WORKFLOWS = [
|
|
181
|
+
// Scout — Detect
|
|
182
|
+
{ name: 'stack-detection', agent: 'stack-detective' },
|
|
183
|
+
// Atlas — Model
|
|
184
|
+
{ name: 'model-generation', agent: 'model-curator' },
|
|
185
|
+
// Lens — Analyze
|
|
186
|
+
{ name: 'gap-analysis', agent: 'readiness-analyst' },
|
|
187
|
+
{ name: 'delta-report', agent: 'readiness-analyst' },
|
|
188
|
+
// Coach — Review
|
|
189
|
+
{ name: 'model-review', agent: 'review-coach' },
|
|
190
|
+
// Orchestration
|
|
191
|
+
{ name: 'full-analysis', agent: 'stack-detective' },
|
|
192
|
+
// Validation
|
|
193
|
+
{ name: 'accuracy-validation', agent: 'model-curator' },
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
// Derived lists for Gyre
|
|
197
|
+
const GYRE_AGENT_FILES = GYRE_AGENTS.map(a => `${a.id}.md`);
|
|
198
|
+
const GYRE_AGENT_IDS = GYRE_AGENTS.map(a => a.id);
|
|
199
|
+
const GYRE_WORKFLOW_NAMES = GYRE_WORKFLOWS.map(w => w.name);
|
|
200
|
+
|
|
136
201
|
module.exports = {
|
|
137
202
|
AGENTS,
|
|
138
203
|
WORKFLOWS,
|
|
@@ -141,4 +206,9 @@ module.exports = {
|
|
|
141
206
|
WORKFLOW_NAMES,
|
|
142
207
|
USER_GUIDES,
|
|
143
208
|
WAVE3_WORKFLOW_NAMES,
|
|
209
|
+
GYRE_AGENTS,
|
|
210
|
+
GYRE_WORKFLOWS,
|
|
211
|
+
GYRE_AGENT_FILES,
|
|
212
|
+
GYRE_AGENT_IDS,
|
|
213
|
+
GYRE_WORKFLOW_NAMES,
|
|
144
214
|
};
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs-extra');
|
|
4
4
|
const path = require('path');
|
|
5
|
+
const yaml = require('js-yaml');
|
|
5
6
|
const { getPackageVersion } = require('./utils');
|
|
6
7
|
const configMerger = require('./config-merger');
|
|
7
|
-
const { AGENTS, AGENT_FILES, AGENT_IDS, WORKFLOW_NAMES, USER_GUIDES } = require('./agent-registry');
|
|
8
|
+
const { AGENTS, AGENT_FILES, AGENT_IDS, WORKFLOW_NAMES, USER_GUIDES, GYRE_AGENTS, GYRE_AGENT_FILES, GYRE_AGENT_IDS, GYRE_WORKFLOW_NAMES } = require('./agent-registry');
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Refresh Installation for Convoke
|
|
@@ -90,6 +91,181 @@ async function refreshInstallation(projectRoot, options = {}) {
|
|
|
90
91
|
if (verbose) console.log(' Skipped workflow copy (dev environment)');
|
|
91
92
|
}
|
|
92
93
|
|
|
94
|
+
// 2a. Enhance module — read config, copy directory tree, patch target agent menu
|
|
95
|
+
const packageEnhance = path.join(packageRoot, '_bmad', 'bme', '_enhance');
|
|
96
|
+
const enhanceConfigPath = path.join(packageEnhance, 'config.yaml');
|
|
97
|
+
|
|
98
|
+
let enhanceConfig = null;
|
|
99
|
+
if (fs.existsSync(enhanceConfigPath)) {
|
|
100
|
+
try {
|
|
101
|
+
enhanceConfig = yaml.load(fs.readFileSync(enhanceConfigPath, 'utf8'));
|
|
102
|
+
} catch (err) {
|
|
103
|
+
const msg = `Enhance config.yaml parse error: ${err.message} — skipping Enhance installation`;
|
|
104
|
+
changes.push(msg);
|
|
105
|
+
if (verbose) console.log(` ⚠ ${msg}`);
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
changes.push('Enhance config.yaml not found — skipping Enhance installation');
|
|
109
|
+
if (verbose) console.log(' ⚠ Enhance config.yaml not found — skipping Enhance installation');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (enhanceConfig) {
|
|
113
|
+
// 2b. Copy _enhance/ directory tree
|
|
114
|
+
const targetEnhance = path.join(projectRoot, '_bmad', 'bme', '_enhance');
|
|
115
|
+
|
|
116
|
+
if (!isSameRoot) {
|
|
117
|
+
await fs.copy(packageEnhance, targetEnhance, { overwrite: true });
|
|
118
|
+
changes.push('Refreshed Enhance module: _bmad/bme/_enhance/');
|
|
119
|
+
if (verbose) console.log(' Refreshed Enhance module: _bmad/bme/_enhance/');
|
|
120
|
+
} else {
|
|
121
|
+
changes.push('Skipped Enhance copy (dev environment — files already in place)');
|
|
122
|
+
if (verbose) console.log(' Skipped Enhance copy (dev environment)');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 2c. Patch target agent menu for each registered workflow
|
|
126
|
+
if (isSameRoot) {
|
|
127
|
+
changes.push('Skipped Enhance menu patch (dev environment — source files unchanged)');
|
|
128
|
+
if (verbose) console.log(' Skipped Enhance menu patch (dev environment)');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
for (const workflow of (isSameRoot ? [] : enhanceConfig.workflows || [])) {
|
|
132
|
+
const targetAgentRel = workflow.target_agent;
|
|
133
|
+
const targetAgentPath = path.join(projectRoot, '_bmad', targetAgentRel);
|
|
134
|
+
|
|
135
|
+
if (!fs.existsSync(targetAgentPath)) {
|
|
136
|
+
const msg = `${targetAgentRel} not found — BMM module must be installed first. Skipping Enhance menu patch.`;
|
|
137
|
+
changes.push(msg);
|
|
138
|
+
if (verbose) console.log(` ⚠ ${msg}`);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
let agentContent = fs.readFileSync(targetAgentPath, 'utf8');
|
|
143
|
+
const patchName = workflow.menu_patch_name || workflow.name;
|
|
144
|
+
|
|
145
|
+
// Idempotency: skip if patch already present
|
|
146
|
+
if (agentContent.includes(patchName)) {
|
|
147
|
+
changes.push(`Enhance menu patch already present in ${targetAgentRel} — skipping`);
|
|
148
|
+
if (verbose) console.log(` Enhance menu patch already present in ${targetAgentRel} — skipping`);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Build the <item> tag
|
|
153
|
+
const entryPath = `{project-root}/_bmad/bme/_enhance/${workflow.entry}`;
|
|
154
|
+
const itemTag = ` <item cmd="IB or fuzzy match on ${patchName}" exec="${entryPath}">[IB] 📦 Initiatives Backlog (Convoke Enhance)</item>`;
|
|
155
|
+
|
|
156
|
+
// Find insertion anchor: prefer </menu>, fallback to last <item>
|
|
157
|
+
const menuCloseIdx = agentContent.lastIndexOf('</menu>');
|
|
158
|
+
if (menuCloseIdx !== -1) {
|
|
159
|
+
// Insert before the </menu> line (not at the </menu> character position,
|
|
160
|
+
// which would prepend existing line indentation to the inserted tag)
|
|
161
|
+
const lineStart = agentContent.lastIndexOf('\n', menuCloseIdx - 1) + 1;
|
|
162
|
+
agentContent = agentContent.slice(0, lineStart) + itemTag + '\n' + agentContent.slice(lineStart);
|
|
163
|
+
} else {
|
|
164
|
+
// Fallback: insert after last <item>...</item> line
|
|
165
|
+
const lastItemMatch = agentContent.match(/.*<item[^]*?<\/item>/g);
|
|
166
|
+
if (lastItemMatch) {
|
|
167
|
+
const lastItem = lastItemMatch[lastItemMatch.length - 1];
|
|
168
|
+
const lastItemIdx = agentContent.lastIndexOf(lastItem);
|
|
169
|
+
const insertIdx = lastItemIdx + lastItem.length;
|
|
170
|
+
agentContent = agentContent.slice(0, insertIdx) + '\n' + itemTag + agentContent.slice(insertIdx);
|
|
171
|
+
} else {
|
|
172
|
+
const msg = `${targetAgentRel} menu structure not recognized — manual patch required. Skipping Enhance menu patch.`;
|
|
173
|
+
changes.push(msg);
|
|
174
|
+
if (verbose) console.log(` ⚠ ${msg}`);
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
fs.writeFileSync(targetAgentPath, agentContent, 'utf8');
|
|
180
|
+
changes.push(`Patched ${targetAgentRel} with Enhance menu item: ${patchName}`);
|
|
181
|
+
if (verbose) console.log(` Patched ${targetAgentRel} with Enhance menu item: ${patchName}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// 2d. Gyre module — copy agents, workflows, contracts, config
|
|
186
|
+
const packageGyre = path.join(packageRoot, '_bmad', 'bme', '_gyre');
|
|
187
|
+
const targetGyre = path.join(projectRoot, '_bmad', 'bme', '_gyre');
|
|
188
|
+
|
|
189
|
+
if (fs.existsSync(packageGyre)) {
|
|
190
|
+
// Copy Gyre agents
|
|
191
|
+
const gyreAgentsSource = path.join(packageGyre, 'agents');
|
|
192
|
+
const gyreAgentsTarget = path.join(targetGyre, 'agents');
|
|
193
|
+
await fs.ensureDir(gyreAgentsTarget);
|
|
194
|
+
|
|
195
|
+
if (!isSameRoot) {
|
|
196
|
+
for (const file of GYRE_AGENT_FILES) {
|
|
197
|
+
const src = path.join(gyreAgentsSource, file);
|
|
198
|
+
if (fs.existsSync(src)) {
|
|
199
|
+
await fs.copy(src, path.join(gyreAgentsTarget, file), { overwrite: true });
|
|
200
|
+
changes.push(`Refreshed Gyre agent: ${file}`);
|
|
201
|
+
if (verbose) console.log(` Refreshed Gyre agent: ${file}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
} else {
|
|
205
|
+
changes.push('Skipped Gyre agent copy (dev environment)');
|
|
206
|
+
if (verbose) console.log(' Skipped Gyre agent copy (dev environment)');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Copy Gyre workflows
|
|
210
|
+
const gyreWorkflowsSource = path.join(packageGyre, 'workflows');
|
|
211
|
+
const gyreWorkflowsTarget = path.join(targetGyre, 'workflows');
|
|
212
|
+
await fs.ensureDir(gyreWorkflowsTarget);
|
|
213
|
+
|
|
214
|
+
if (!isSameRoot) {
|
|
215
|
+
for (const wf of GYRE_WORKFLOW_NAMES) {
|
|
216
|
+
const src = path.join(gyreWorkflowsSource, wf);
|
|
217
|
+
const dest = path.join(gyreWorkflowsTarget, wf);
|
|
218
|
+
if (fs.existsSync(src)) {
|
|
219
|
+
if (fs.existsSync(dest)) {
|
|
220
|
+
await fs.remove(dest);
|
|
221
|
+
}
|
|
222
|
+
await fs.copy(src, dest, { overwrite: true });
|
|
223
|
+
changes.push(`Refreshed Gyre workflow: ${wf}`);
|
|
224
|
+
if (verbose) console.log(` Refreshed Gyre workflow: ${wf}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
} else {
|
|
228
|
+
changes.push('Skipped Gyre workflow copy (dev environment)');
|
|
229
|
+
if (verbose) console.log(' Skipped Gyre workflow copy (dev environment)');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Copy Gyre contracts
|
|
233
|
+
const gyreContractsSource = path.join(packageGyre, 'contracts');
|
|
234
|
+
const gyreContractsTarget = path.join(targetGyre, 'contracts');
|
|
235
|
+
if (fs.existsSync(gyreContractsSource)) {
|
|
236
|
+
await fs.ensureDir(gyreContractsTarget);
|
|
237
|
+
if (!isSameRoot) {
|
|
238
|
+
await fs.copy(gyreContractsSource, gyreContractsTarget, { overwrite: true });
|
|
239
|
+
changes.push('Refreshed Gyre contracts');
|
|
240
|
+
if (verbose) console.log(' Refreshed Gyre contracts');
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Copy Gyre config.yaml
|
|
245
|
+
const gyreConfigSource = path.join(packageGyre, 'config.yaml');
|
|
246
|
+
const gyreConfigTarget = path.join(targetGyre, 'config.yaml');
|
|
247
|
+
if (!isSameRoot && fs.existsSync(gyreConfigSource)) {
|
|
248
|
+
// Merge Gyre config preserving user prefs, same as Vortex
|
|
249
|
+
const gyreUpdates = {
|
|
250
|
+
agents: GYRE_AGENT_IDS,
|
|
251
|
+
workflows: GYRE_WORKFLOW_NAMES
|
|
252
|
+
};
|
|
253
|
+
const gyreConfigMerged = await configMerger.mergeConfig(gyreConfigTarget, version, gyreUpdates);
|
|
254
|
+
await configMerger.writeConfig(gyreConfigTarget, gyreConfigMerged);
|
|
255
|
+
changes.push(`Updated Gyre config.yaml to v${version}`);
|
|
256
|
+
if (verbose) console.log(` Updated Gyre config.yaml to v${version}`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Copy Gyre README
|
|
260
|
+
const gyreReadmeSource = path.join(packageGyre, 'README.md');
|
|
261
|
+
const gyreReadmeTarget = path.join(targetGyre, 'README.md');
|
|
262
|
+
if (!isSameRoot && fs.existsSync(gyreReadmeSource)) {
|
|
263
|
+
await fs.copy(gyreReadmeSource, gyreReadmeTarget, { overwrite: true });
|
|
264
|
+
changes.push('Refreshed Gyre README.md');
|
|
265
|
+
if (verbose) console.log(' Refreshed Gyre README.md');
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
93
269
|
// 3. Update config.yaml (merge, preserving user prefs)
|
|
94
270
|
const configPath = path.join(targetVortex, 'config.yaml');
|
|
95
271
|
await fs.ensureDir(path.dirname(configPath));
|
|
@@ -172,35 +348,45 @@ async function refreshInstallation(projectRoot, options = {}) {
|
|
|
172
348
|
isV610 = true;
|
|
173
349
|
}
|
|
174
350
|
|
|
175
|
-
// Build fresh bme rows matching the detected schema
|
|
351
|
+
// Build fresh bme rows matching the detected schema (Vortex + Gyre agents)
|
|
352
|
+
function buildAgentRow610(a, submodule) {
|
|
353
|
+
const p = a.persona;
|
|
354
|
+
return [
|
|
355
|
+
csvEscape(a.name), // name
|
|
356
|
+
csvEscape(''), // displayName
|
|
357
|
+
csvEscape(a.title), // title
|
|
358
|
+
csvEscape(a.icon), // icon
|
|
359
|
+
csvEscape(''), // capabilities
|
|
360
|
+
csvEscape(p.role), // role
|
|
361
|
+
csvEscape(p.identity), // identity
|
|
362
|
+
csvEscape(p.communication_style), // communicationStyle
|
|
363
|
+
csvEscape(p.expertise), // principles
|
|
364
|
+
csvEscape('bme'), // module
|
|
365
|
+
csvEscape(`_bmad/bme/${submodule}/agents/${a.id}.md`), // path
|
|
366
|
+
csvEscape(`bmad-agent-bme-${a.id}`), // canonicalId
|
|
367
|
+
].join(',');
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function buildAgentRowLegacy(a, submodule) {
|
|
371
|
+
const p = a.persona;
|
|
372
|
+
return [
|
|
373
|
+
a.id, a.name, a.title, a.icon,
|
|
374
|
+
p.role, p.identity, p.communication_style, p.expertise,
|
|
375
|
+
'bme', `_bmad/bme/${submodule}/agents/${a.id}.md`,
|
|
376
|
+
].map(csvEscape).join(',');
|
|
377
|
+
}
|
|
378
|
+
|
|
176
379
|
let bmeRows;
|
|
177
380
|
if (isV610) {
|
|
178
|
-
bmeRows =
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
-
});
|
|
381
|
+
bmeRows = [
|
|
382
|
+
...AGENTS.map(a => buildAgentRow610(a, '_vortex')),
|
|
383
|
+
...GYRE_AGENTS.map(a => buildAgentRow610(a, '_gyre')),
|
|
384
|
+
];
|
|
195
385
|
} else {
|
|
196
|
-
bmeRows =
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
p.role, p.identity, p.communication_style, p.expertise,
|
|
201
|
-
'bme', `_bmad/bme/_vortex/agents/${a.id}.md`,
|
|
202
|
-
].map(csvEscape).join(',');
|
|
203
|
-
});
|
|
386
|
+
bmeRows = [
|
|
387
|
+
...AGENTS.map(a => buildAgentRowLegacy(a, '_vortex')),
|
|
388
|
+
...GYRE_AGENTS.map(a => buildAgentRowLegacy(a, '_gyre')),
|
|
389
|
+
];
|
|
204
390
|
}
|
|
205
391
|
|
|
206
392
|
const allRows = [...preservedRows, ...bmeRows].join('\n') + '\n';
|
|
@@ -250,7 +436,10 @@ async function refreshInstallation(projectRoot, options = {}) {
|
|
|
250
436
|
const skillsDir = path.join(projectRoot, '.claude', 'skills');
|
|
251
437
|
|
|
252
438
|
// Remove stale skill directories (agents no longer in registry)
|
|
253
|
-
const currentSkillDirs = new Set(
|
|
439
|
+
const currentSkillDirs = new Set([
|
|
440
|
+
...AGENTS.map(a => `bmad-agent-bme-${a.id}`),
|
|
441
|
+
...GYRE_AGENTS.map(a => `bmad-agent-bme-${a.id}`),
|
|
442
|
+
]);
|
|
254
443
|
if (fs.existsSync(skillsDir)) {
|
|
255
444
|
const existingSkills = (await fs.readdir(skillsDir)).filter(d => d.startsWith('bmad-agent-bme-'));
|
|
256
445
|
for (const dir of existingSkills) {
|
|
@@ -286,6 +475,78 @@ You must fully embody this agent's persona and follow all activation instruction
|
|
|
286
475
|
if (verbose) console.log(` Refreshed skill: bmad-agent-bme-${agent.id}/SKILL.md`);
|
|
287
476
|
}
|
|
288
477
|
|
|
478
|
+
// 6b. Generate .claude/skills/ for Gyre agents
|
|
479
|
+
for (const agent of GYRE_AGENTS) {
|
|
480
|
+
const skillDir = path.join(skillsDir, `bmad-agent-bme-${agent.id}`);
|
|
481
|
+
await fs.ensureDir(skillDir);
|
|
482
|
+
const content = `---
|
|
483
|
+
name: bmad-agent-bme-${agent.id}
|
|
484
|
+
description: ${agent.id} agent
|
|
485
|
+
---
|
|
486
|
+
|
|
487
|
+
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
|
|
488
|
+
|
|
489
|
+
<agent-activation CRITICAL="TRUE">
|
|
490
|
+
1. LOAD the FULL agent file from {project-root}/_bmad/bme/_gyre/agents/${agent.id}.md
|
|
491
|
+
2. READ its entire contents - this contains the complete agent persona, menu, and instructions
|
|
492
|
+
3. FOLLOW every step in the <activation> section precisely
|
|
493
|
+
4. DISPLAY the welcome/greeting as instructed
|
|
494
|
+
5. PRESENT the numbered menu
|
|
495
|
+
6. WAIT for user input before proceeding
|
|
496
|
+
</agent-activation>
|
|
497
|
+
`;
|
|
498
|
+
await fs.writeFile(path.join(skillDir, 'SKILL.md'), content, 'utf8');
|
|
499
|
+
changes.push(`Refreshed skill: bmad-agent-bme-${agent.id}/SKILL.md`);
|
|
500
|
+
if (verbose) console.log(` Refreshed skill: bmad-agent-bme-${agent.id}/SKILL.md`);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// 6c. Copy Enhance workflow skill wrappers and register in manifests
|
|
504
|
+
if (enhanceConfig && !isSameRoot) {
|
|
505
|
+
for (const workflow of enhanceConfig.workflows || []) {
|
|
506
|
+
const canonicalId = `bmad-enhance-${workflow.name}`;
|
|
507
|
+
const skillDir = path.join(skillsDir, canonicalId);
|
|
508
|
+
await fs.ensureDir(skillDir);
|
|
509
|
+
|
|
510
|
+
// Copy source SKILL.md from package (shipped via npm, not generated)
|
|
511
|
+
const sourceSkillPath = path.join(packageRoot, '_bmad', 'bme', '_enhance', 'workflows', workflow.name, 'SKILL.md');
|
|
512
|
+
const targetSkillPath = path.join(skillDir, 'SKILL.md');
|
|
513
|
+
await fs.copy(sourceSkillPath, targetSkillPath, { overwrite: true });
|
|
514
|
+
changes.push(`Refreshed Enhance skill: ${canonicalId}/SKILL.md`);
|
|
515
|
+
if (verbose) console.log(` Refreshed Enhance skill: ${canonicalId}/SKILL.md`);
|
|
516
|
+
|
|
517
|
+
// Append to workflow-manifest.csv if not already present
|
|
518
|
+
const wfManifestPath = path.join(projectRoot, '_bmad', '_config', 'workflow-manifest.csv');
|
|
519
|
+
if (fs.existsSync(wfManifestPath)) {
|
|
520
|
+
const wfCsv = fs.readFileSync(wfManifestPath, 'utf8');
|
|
521
|
+
if (!wfCsv.includes(`"${canonicalId}"`)) {
|
|
522
|
+
const wfRow = `\n"${workflow.name}","Manage RICE initiatives backlog — triage review findings, rescore existing items, or bootstrap new backlogs.","bme","_bmad/bme/_enhance/${workflow.entry}","${canonicalId}"`;
|
|
523
|
+
fs.appendFileSync(wfManifestPath, wfRow, 'utf8');
|
|
524
|
+
changes.push(`Added ${canonicalId} to workflow-manifest.csv`);
|
|
525
|
+
if (verbose) console.log(` Added ${canonicalId} to workflow-manifest.csv`);
|
|
526
|
+
}
|
|
527
|
+
} else {
|
|
528
|
+
if (verbose) console.log(' ⚠ workflow-manifest.csv not found — skipping manifest registration');
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// Append to skill-manifest.csv if not already present
|
|
532
|
+
const skManifestPath = path.join(projectRoot, '_bmad', '_config', 'skill-manifest.csv');
|
|
533
|
+
if (fs.existsSync(skManifestPath)) {
|
|
534
|
+
const skCsv = fs.readFileSync(skManifestPath, 'utf8');
|
|
535
|
+
if (!skCsv.includes(`"${canonicalId}"`)) {
|
|
536
|
+
const skRow = `\n"${canonicalId}","${canonicalId}","Manage RICE initiatives backlog — triage review findings, rescore existing items, or bootstrap new backlogs.","bme","_bmad/bme/_enhance/workflows/${workflow.name}/SKILL.md","true"`;
|
|
537
|
+
fs.appendFileSync(skManifestPath, skRow, 'utf8');
|
|
538
|
+
changes.push(`Added ${canonicalId} to skill-manifest.csv`);
|
|
539
|
+
if (verbose) console.log(` Added ${canonicalId} to skill-manifest.csv`);
|
|
540
|
+
}
|
|
541
|
+
} else {
|
|
542
|
+
if (verbose) console.log(' ⚠ skill-manifest.csv not found — skipping manifest registration');
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
} else if (enhanceConfig && isSameRoot) {
|
|
546
|
+
changes.push('Skipped Enhance skill registration (dev environment — source files unchanged)');
|
|
547
|
+
if (verbose) console.log(' Skipped Enhance skill registration (dev environment)');
|
|
548
|
+
}
|
|
549
|
+
|
|
289
550
|
// 7. Generate agent customize files (only if they don't already exist)
|
|
290
551
|
const customizeDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
291
552
|
await fs.ensureDir(customizeDir);
|
|
@@ -318,7 +579,7 @@ menu: []
|
|
|
318
579
|
prompts: []
|
|
319
580
|
`;
|
|
320
581
|
|
|
321
|
-
for (const agent of AGENTS) {
|
|
582
|
+
for (const agent of [...AGENTS, ...GYRE_AGENTS]) {
|
|
322
583
|
const filename = `bme-${agent.name.toLowerCase()}.customize.yaml`;
|
|
323
584
|
const filePath = path.join(customizeDir, filename);
|
|
324
585
|
if (!fs.existsSync(filePath)) {
|