convoke-agents 3.2.1 → 3.3.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 +68 -0
- package/README.md +3 -1
- package/_bmad/bme/README.md +36 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/SKILL.md +1 -1
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-01-init.md +55 -32
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-02-gather.md +62 -59
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-03-qualify.md +176 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-04-generate.md +259 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/step-r-01-load.md +65 -35
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/step-r-02-rescore.md +60 -30
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/step-r-03-update.md +67 -71
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-01-ingest.md +12 -12
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-02-extract.md +49 -44
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-03-qualify.md +192 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-04-update.md +72 -67
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/templates/backlog-format-spec.md +223 -112
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/templates/lifecycle-process-spec.md +188 -0
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/workflow.md +44 -31
- package/_bmad/bme/_gyre/config.yaml +3 -0
- package/_bmad/bme/_vortex/config.yaml +4 -1
- package/package.json +1 -1
- package/scripts/convoke-doctor.js +56 -2
- package/scripts/lib/artifact-utils.js +16 -3
- package/scripts/migrate-artifacts.js +3 -2
- package/scripts/portability/convoke-export.js +26 -5
- package/scripts/portability/export-engine.js +10 -8
- package/scripts/portability/seed-catalog-repo.js +6 -6
- package/scripts/portability/validate-exports.js +25 -14
- package/scripts/update/convoke-update.js +27 -2
- package/scripts/update/lib/changelog-reader.js +90 -0
- package/scripts/update/lib/config-merger.js +52 -1
- package/scripts/update/lib/refresh-installation.js +48 -9
- package/scripts/update/lib/taxonomy-merger.js +2 -1
- package/scripts/update/lib/validator.js +9 -1
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-03-score.md +0 -146
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-04-prioritize.md +0 -181
- package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-03-score.md +0 -147
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { compareVersions } = require('./utils');
|
|
6
|
+
|
|
7
|
+
const DEFAULT_CHANGELOG_PATH = path.join(__dirname, '..', '..', '..', 'CHANGELOG.md');
|
|
8
|
+
|
|
9
|
+
// Broad bracket-capture so pre-release headers ([1.0.4-alpha]) don't get skipped —
|
|
10
|
+
// a skipped header would leak its body into the preceding entry. Non-semver labels
|
|
11
|
+
// (Unreleased, TBD) are dropped later by SEMVER_RE. Date may use ASCII or en/em dash.
|
|
12
|
+
const HEADER_RE = /^##\s+\[([^\]]+)\](?:\s*[-–—]\s*(.+?))?\s*$/;
|
|
13
|
+
const SEMVER_RE = /^\d+\.\d+\.\d+(?:[-+][\w.-]+)?$/;
|
|
14
|
+
const FENCE_RE = /^(?:```|~~~)/;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Parse a Keep-a-Changelog-formatted file and return entries for versions
|
|
18
|
+
* strictly greater than `fromVersion` and less than or equal to `toVersion`.
|
|
19
|
+
*
|
|
20
|
+
* Returns entries newest-first. Unreleased sections, malformed headers, and
|
|
21
|
+
* missing files are skipped silently — this is a decorative surface and must
|
|
22
|
+
* never break the update flow.
|
|
23
|
+
*
|
|
24
|
+
* @param {string|null|undefined} fromVersion - Installed version (exclusive lower bound). Null treats all entries <= toVersion as new.
|
|
25
|
+
* @param {string} toVersion - Target version (inclusive upper bound).
|
|
26
|
+
* @param {string} [changelogPath] - Absolute path to CHANGELOG.md.
|
|
27
|
+
* @returns {Array<{version: string, date: string|null, body: string}>}
|
|
28
|
+
*/
|
|
29
|
+
function readChangelogEntries(fromVersion, toVersion, changelogPath = DEFAULT_CHANGELOG_PATH) {
|
|
30
|
+
if (!toVersion) return [];
|
|
31
|
+
|
|
32
|
+
let raw;
|
|
33
|
+
try {
|
|
34
|
+
raw = fs.readFileSync(changelogPath, 'utf8');
|
|
35
|
+
} catch {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const entries = [];
|
|
40
|
+
const lines = raw.split('\n');
|
|
41
|
+
let current = null;
|
|
42
|
+
let inFence = false;
|
|
43
|
+
|
|
44
|
+
const flush = () => {
|
|
45
|
+
if (!current) return;
|
|
46
|
+
current.body = current.bodyLines.join('\n').replace(/\s+$/, '');
|
|
47
|
+
delete current.bodyLines;
|
|
48
|
+
entries.push(current);
|
|
49
|
+
current = null;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
for (const line of lines) {
|
|
53
|
+
if (FENCE_RE.test(line)) {
|
|
54
|
+
inFence = !inFence;
|
|
55
|
+
if (current) current.bodyLines.push(line);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (!inFence) {
|
|
59
|
+
const match = HEADER_RE.exec(line);
|
|
60
|
+
if (match) {
|
|
61
|
+
flush();
|
|
62
|
+
current = {
|
|
63
|
+
version: match[1].trim(),
|
|
64
|
+
date: match[2] ? match[2].trim() : null,
|
|
65
|
+
bodyLines: [],
|
|
66
|
+
};
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (current) {
|
|
71
|
+
if (!inFence && /^---\s*$/.test(line)) continue;
|
|
72
|
+
current.bodyLines.push(line);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
flush();
|
|
76
|
+
|
|
77
|
+
return entries
|
|
78
|
+
.filter((e) => {
|
|
79
|
+
if (!SEMVER_RE.test(e.version)) return false;
|
|
80
|
+
const aboveFloor = fromVersion ? compareVersions(e.version, fromVersion) > 0 : true;
|
|
81
|
+
const atOrBelowCeiling = compareVersions(e.version, toVersion) <= 0;
|
|
82
|
+
return aboveFloor && atOrBelowCeiling;
|
|
83
|
+
})
|
|
84
|
+
.sort((a, b) => compareVersions(b.version, a.version));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = {
|
|
88
|
+
readChangelogEntries,
|
|
89
|
+
DEFAULT_CHANGELOG_PATH,
|
|
90
|
+
};
|
|
@@ -19,6 +19,40 @@ const { assertVersion } = require('./utils');
|
|
|
19
19
|
|
|
20
20
|
const MERGED_DOC_SENTINEL = Symbol.for('convoke.config-merger.docMerged');
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Read `excluded_agents` from a module's config.yaml without going through the
|
|
24
|
+
* full merge path. Used by refresh-installation and validator to skip copying
|
|
25
|
+
* / checking agents the operator has opted out of. U8: permanent agent
|
|
26
|
+
* exclusions that survive upgrades.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} configPath - Absolute path to module config.yaml
|
|
29
|
+
* @returns {string[]} Array of excluded agent IDs (empty if missing, malformed, or not an array)
|
|
30
|
+
*/
|
|
31
|
+
function readExcludedAgents(configPath) {
|
|
32
|
+
let content;
|
|
33
|
+
try {
|
|
34
|
+
content = fs.readFileSync(configPath, 'utf8');
|
|
35
|
+
} catch (err) {
|
|
36
|
+
// ENOENT is expected on fresh installs (config hasn't been written yet).
|
|
37
|
+
// Other IO errors (EACCES, EISDIR, EMFILE, ...) indicate a real misconfiguration —
|
|
38
|
+
// warn so the operator knows their exclusions won't be applied this run. Never throw:
|
|
39
|
+
// this reader must not break the install flow.
|
|
40
|
+
if (err && err.code !== 'ENOENT') {
|
|
41
|
+
console.warn(`Warning: could not read ${configPath} for excluded_agents (${err.code || err.message}). Proceeding without exclusions.`);
|
|
42
|
+
}
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const parsed = yaml.load(content);
|
|
47
|
+
if (parsed && Array.isArray(parsed.excluded_agents)) {
|
|
48
|
+
return parsed.excluded_agents.filter(a => typeof a === 'string');
|
|
49
|
+
}
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.warn(`Warning: could not parse ${configPath} for excluded_agents (${err.message}). Proceeding without exclusions.`);
|
|
52
|
+
}
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
|
|
22
56
|
/**
|
|
23
57
|
* Merge current config with new template while preserving user preferences.
|
|
24
58
|
* Agents and workflows use smart-merge: canonical entries in registry order
|
|
@@ -78,13 +112,29 @@ async function mergeConfig(currentConfigPath, newVersion, updates = {}) {
|
|
|
78
112
|
|
|
79
113
|
// Smart-merge agents: canonical agents in order, then unique user-added agents appended.
|
|
80
114
|
// Core agents are always restored to canonical order. User-added agents (not in AGENT_IDS)
|
|
81
|
-
// are preserved and deduplicated.
|
|
115
|
+
// are preserved and deduplicated.
|
|
116
|
+
//
|
|
117
|
+
// U8: respect `excluded_agents` — an operator-maintained opt-out list. Agents named in that
|
|
118
|
+
// list are filtered out of the active `agents` array so deliberate removals survive upgrades.
|
|
119
|
+
// Re-inclusion works by removing the agent from `excluded_agents` — the next merge restores
|
|
120
|
+
// it via the canonical spread above.
|
|
121
|
+
const excludedAgents = Array.isArray(current.excluded_agents)
|
|
122
|
+
? current.excluded_agents.filter(a => typeof a === 'string')
|
|
123
|
+
: [];
|
|
82
124
|
if (updates.agents) {
|
|
83
125
|
const userAgents = Array.isArray(current.agents)
|
|
84
126
|
? [...new Set(current.agents.filter(a => !AGENT_IDS.includes(a)))]
|
|
85
127
|
: [];
|
|
86
128
|
merged.agents = [...updates.agents, ...userAgents];
|
|
87
129
|
}
|
|
130
|
+
// Apply exclusions to merged.agents regardless of whether `updates.agents` was provided —
|
|
131
|
+
// otherwise callers that pass empty updates (e.g., a workflows-only migration delta) would
|
|
132
|
+
// leak excluded agents back via the `defaults` spread at line 96.
|
|
133
|
+
if (excludedAgents.length > 0 && Array.isArray(merged.agents)) {
|
|
134
|
+
merged.agents = merged.agents.filter(a => !excludedAgents.includes(a));
|
|
135
|
+
}
|
|
136
|
+
// Preserve the exclusion list as a first-class field (empty stays empty — the schema default).
|
|
137
|
+
merged.excluded_agents = excludedAgents;
|
|
88
138
|
|
|
89
139
|
// Smart-merge workflows: canonical workflows in order, then unique user-added appended
|
|
90
140
|
if (updates.workflows) {
|
|
@@ -365,6 +415,7 @@ function addMigrationHistory(config, fromVersion, toVersion, migrationsApplied)
|
|
|
365
415
|
module.exports = {
|
|
366
416
|
CONFIG_SCHEMA,
|
|
367
417
|
mergeConfig,
|
|
418
|
+
readExcludedAgents,
|
|
368
419
|
extractUserPreferences,
|
|
369
420
|
validateConfig,
|
|
370
421
|
writeConfig,
|
|
@@ -6,7 +6,7 @@ const yaml = require('js-yaml');
|
|
|
6
6
|
const YAML = require('yaml'); // Comment-preserving YAML library (ag-7-1: I29). Use for WRITE sites that need to preserve comments. js-yaml stays for read-only consumers.
|
|
7
7
|
const { getPackageVersion, assertVersion } = require('./utils');
|
|
8
8
|
const configMerger = require('./config-merger');
|
|
9
|
-
const { AGENTS, AGENT_FILES, AGENT_IDS, WORKFLOW_NAMES,
|
|
9
|
+
const { AGENTS, AGENT_FILES, AGENT_IDS, WORKFLOW_NAMES, GYRE_AGENTS, GYRE_AGENT_FILES, GYRE_AGENT_IDS, GYRE_WORKFLOW_NAMES, EXTRA_BME_AGENTS } = require('./agent-registry');
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Refresh Installation for Convoke
|
|
@@ -37,6 +37,15 @@ async function refreshInstallation(projectRoot, options = {}) {
|
|
|
37
37
|
// source and destination are identical — skip file copies.
|
|
38
38
|
const isSameRoot = path.resolve(packageRoot) === path.resolve(projectRoot);
|
|
39
39
|
|
|
40
|
+
// U8: read per-module `excluded_agents` from target configs BEFORE copy.
|
|
41
|
+
// These are opt-out lists the operator maintains; excluded agents don't get
|
|
42
|
+
// their agent file copied, don't get a skill wrapper generated, and don't
|
|
43
|
+
// fail presence checks downstream.
|
|
44
|
+
const vortexExcluded = configMerger.readExcludedAgents(path.join(targetVortex, 'config.yaml'));
|
|
45
|
+
const gyreExcluded = configMerger.readExcludedAgents(
|
|
46
|
+
path.join(projectRoot, '_bmad', 'bme', '_gyre', 'config.yaml')
|
|
47
|
+
);
|
|
48
|
+
|
|
40
49
|
// 1. Copy agent files
|
|
41
50
|
const agentsSource = path.join(packageVortex, 'agents');
|
|
42
51
|
const agentsTarget = path.join(targetVortex, 'agents');
|
|
@@ -44,6 +53,12 @@ async function refreshInstallation(projectRoot, options = {}) {
|
|
|
44
53
|
|
|
45
54
|
if (!isSameRoot) {
|
|
46
55
|
for (const file of AGENT_FILES) {
|
|
56
|
+
const agentId = file.replace(/\.md$/, '');
|
|
57
|
+
if (vortexExcluded.includes(agentId)) {
|
|
58
|
+
changes.push(`Skipped excluded Vortex agent: ${file}`);
|
|
59
|
+
if (verbose) console.log(` Skipped excluded Vortex agent: ${file}`);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
47
62
|
const src = path.join(agentsSource, file);
|
|
48
63
|
if (fs.existsSync(src)) {
|
|
49
64
|
await fs.copy(src, path.join(agentsTarget, file), { overwrite: true });
|
|
@@ -290,6 +305,12 @@ async function refreshInstallation(projectRoot, options = {}) {
|
|
|
290
305
|
|
|
291
306
|
if (!isSameRoot) {
|
|
292
307
|
for (const file of GYRE_AGENT_FILES) {
|
|
308
|
+
const agentId = file.replace(/\.md$/, '');
|
|
309
|
+
if (gyreExcluded.includes(agentId)) {
|
|
310
|
+
changes.push(`Skipped excluded Gyre agent: ${file}`);
|
|
311
|
+
if (verbose) console.log(` Skipped excluded Gyre agent: ${file}`);
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
293
314
|
const src = path.join(gyreAgentsSource, file);
|
|
294
315
|
if (fs.existsSync(src)) {
|
|
295
316
|
await fs.copy(src, path.join(gyreAgentsTarget, file), { overwrite: true });
|
|
@@ -502,17 +523,21 @@ async function refreshInstallation(projectRoot, options = {}) {
|
|
|
502
523
|
].map(csvEscape).join(',');
|
|
503
524
|
}
|
|
504
525
|
|
|
526
|
+
// U8: filter out excluded agents so manifest rows don't point at wrappers the
|
|
527
|
+
// stale-cleanup loop (§6) just removed. Left in, rows become dangling pointers.
|
|
528
|
+
const activeVortexAgents = AGENTS.filter(a => !vortexExcluded.includes(a.id));
|
|
529
|
+
const activeGyreAgents = GYRE_AGENTS.filter(a => !gyreExcluded.includes(a.id));
|
|
505
530
|
let bmeRows;
|
|
506
531
|
if (isV610) {
|
|
507
532
|
bmeRows = [
|
|
508
|
-
...
|
|
509
|
-
...
|
|
533
|
+
...activeVortexAgents.map(a => buildAgentRow610(a, '_vortex')),
|
|
534
|
+
...activeGyreAgents.map(a => buildAgentRow610(a, '_gyre')),
|
|
510
535
|
...EXTRA_BME_AGENTS.map(buildExtraBmeAgentRow610),
|
|
511
536
|
];
|
|
512
537
|
} else {
|
|
513
538
|
bmeRows = [
|
|
514
|
-
...
|
|
515
|
-
...
|
|
539
|
+
...activeVortexAgents.map(a => buildAgentRowLegacy(a, '_vortex')),
|
|
540
|
+
...activeGyreAgents.map(a => buildAgentRowLegacy(a, '_gyre')),
|
|
516
541
|
...EXTRA_BME_AGENTS.map(buildExtraBmeAgentRowLegacy),
|
|
517
542
|
];
|
|
518
543
|
}
|
|
@@ -528,7 +553,16 @@ async function refreshInstallation(projectRoot, options = {}) {
|
|
|
528
553
|
await fs.ensureDir(guidesTarget);
|
|
529
554
|
|
|
530
555
|
if (!isSameRoot) {
|
|
531
|
-
|
|
556
|
+
// U8: user guides are named after each agent (e.g., NOAH-USER-GUIDE.md). Iterate
|
|
557
|
+
// AGENTS so we can match guides to agent IDs and skip excluded ones — a guide
|
|
558
|
+
// without its agent is dead docs.
|
|
559
|
+
for (const agent of AGENTS) {
|
|
560
|
+
const guide = `${agent.name.toUpperCase()}-USER-GUIDE.md`;
|
|
561
|
+
if (vortexExcluded.includes(agent.id)) {
|
|
562
|
+
changes.push(`Skipped excluded guide: ${guide}`);
|
|
563
|
+
if (verbose) console.log(` Skipped excluded guide: ${guide}`);
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
532
566
|
const src = path.join(guidesSource, guide);
|
|
533
567
|
const dest = path.join(guidesTarget, guide);
|
|
534
568
|
|
|
@@ -563,10 +597,13 @@ async function refreshInstallation(projectRoot, options = {}) {
|
|
|
563
597
|
|
|
564
598
|
const skillsDir = path.join(projectRoot, '.claude', 'skills');
|
|
565
599
|
|
|
566
|
-
// Remove stale skill directories (agents no longer in registry)
|
|
600
|
+
// Remove stale skill directories (agents no longer in registry OR excluded by operator).
|
|
601
|
+
// U8: excluded agents are intentionally omitted from the valid set so the stale-removal
|
|
602
|
+
// loop below deletes their wrappers on the next refresh. Re-inclusion (removing from
|
|
603
|
+
// excluded_agents) regenerates the wrapper here.
|
|
567
604
|
const currentSkillDirs = new Set([
|
|
568
|
-
...AGENTS.map(a => `bmad-agent-bme-${a.id}`),
|
|
569
|
-
...GYRE_AGENTS.map(a => `bmad-agent-bme-${a.id}`),
|
|
605
|
+
...AGENTS.filter(a => !vortexExcluded.includes(a.id)).map(a => `bmad-agent-bme-${a.id}`),
|
|
606
|
+
...GYRE_AGENTS.filter(a => !gyreExcluded.includes(a.id)).map(a => `bmad-agent-bme-${a.id}`),
|
|
570
607
|
...EXTRA_BME_AGENTS.map(a => `bmad-agent-bme-${a.id}`),
|
|
571
608
|
]);
|
|
572
609
|
if (fs.existsSync(skillsDir)) {
|
|
@@ -581,6 +618,7 @@ async function refreshInstallation(projectRoot, options = {}) {
|
|
|
581
618
|
}
|
|
582
619
|
|
|
583
620
|
for (const agent of AGENTS) {
|
|
621
|
+
if (vortexExcluded.includes(agent.id)) continue;
|
|
584
622
|
const skillDir = path.join(skillsDir, `bmad-agent-bme-${agent.id}`);
|
|
585
623
|
await fs.ensureDir(skillDir);
|
|
586
624
|
const content = `---
|
|
@@ -606,6 +644,7 @@ You must fully embody this agent's persona and follow all activation instruction
|
|
|
606
644
|
|
|
607
645
|
// 6b. Generate .claude/skills/ for Gyre agents
|
|
608
646
|
for (const agent of GYRE_AGENTS) {
|
|
647
|
+
if (gyreExcluded.includes(agent.id)) continue;
|
|
609
648
|
const skillDir = path.join(skillsDir, `bmad-agent-bme-${agent.id}`);
|
|
610
649
|
await fs.ensureDir(skillDir);
|
|
611
650
|
const content = `---
|
|
@@ -11,7 +11,8 @@ const PLATFORM_INITIATIVES = ['vortex', 'gyre', 'bmm', 'forge', 'helm', 'enhance
|
|
|
11
11
|
const DEFAULT_ARTIFACT_TYPES = [
|
|
12
12
|
'prd', 'epic', 'arch', 'adr', 'persona', 'lean-persona', 'empathy-map',
|
|
13
13
|
'problem-def', 'hypothesis', 'experiment', 'signal', 'decision', 'scope',
|
|
14
|
-
'pre-reg', 'sprint', 'brief', 'vision', 'report', 'research', 'story', 'spec'
|
|
14
|
+
'pre-reg', 'sprint', 'brief', 'vision', 'report', 'research', 'story', 'spec',
|
|
15
|
+
'covenant'
|
|
15
16
|
];
|
|
16
17
|
|
|
17
18
|
const DEFAULT_ALIASES = {
|
|
@@ -111,7 +111,15 @@ async function validateAgentFiles(projectRoot) {
|
|
|
111
111
|
|
|
112
112
|
try {
|
|
113
113
|
const agentsDir = path.join(projectRoot, '_bmad/bme/_vortex/agents');
|
|
114
|
-
|
|
114
|
+
// U8: honor operator agent exclusions from the target config.yaml, so a
|
|
115
|
+
// deliberately-removed agent doesn't fail post-upgrade validation.
|
|
116
|
+
const configMerger = require('./config-merger');
|
|
117
|
+
const excluded = configMerger.readExcludedAgents(
|
|
118
|
+
path.join(projectRoot, '_bmad/bme/_vortex/config.yaml')
|
|
119
|
+
);
|
|
120
|
+
const requiredAgents = AGENT_FILES.filter(
|
|
121
|
+
f => !excluded.includes(f.replace(/\.md$/, ''))
|
|
122
|
+
);
|
|
115
123
|
|
|
116
124
|
if (!fs.existsSync(agentsDir)) {
|
|
117
125
|
check.error = 'agents/ directory not found';
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: 'step-c-03-score'
|
|
3
|
-
description: 'Propose RICE scores for gathered initiatives in batch, validate with user, assign track labels'
|
|
4
|
-
nextStepFile: '{project-root}/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-04-prioritize.md'
|
|
5
|
-
outputFile: '{planning_artifacts}/initiatives-backlog.md'
|
|
6
|
-
templateFile: '{project-root}/_bmad/bme/_enhance/workflows/initiatives-backlog/templates/rice-scoring-guide.md'
|
|
7
|
-
advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md'
|
|
8
|
-
partyModeWorkflow: '{project-root}/_bmad/core/workflows/bmad-party-mode/workflow.md'
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Step 3: Batch RICE Scoring
|
|
12
|
-
|
|
13
|
-
## STEP GOAL:
|
|
14
|
-
|
|
15
|
-
Propose RICE scores and Track assignments for all gathered initiatives, present the scored batch for user validation, and finalize scores before backlog generation.
|
|
16
|
-
|
|
17
|
-
## MANDATORY EXECUTION RULES (READ FIRST):
|
|
18
|
-
|
|
19
|
-
### Universal Rules:
|
|
20
|
-
- 🛑 NEVER generate content without user input at the scoring menu
|
|
21
|
-
- 📖 CRITICAL: Read this complete step file before taking action
|
|
22
|
-
- 🔄 CRITICAL: When loading next step with 'C', read the entire file
|
|
23
|
-
- 📋 YOU ARE A SCORING ANALYST proposing calibrated RICE scores
|
|
24
|
-
|
|
25
|
-
### Role Reinforcement:
|
|
26
|
-
- ✅ You are a **RICE scoring analyst** — systematic, calibrated, evidence-based
|
|
27
|
-
- ✅ Propose scores grounded in the scoring guide's definitions and calibration examples
|
|
28
|
-
- ✅ The user validates and adjusts your proposals — you propose, they decide
|
|
29
|
-
- ✅ Assign Track labels based on initiative nature: maintenance/stability = "Keep the lights on", growth/new capability = "Move the needle"
|
|
30
|
-
|
|
31
|
-
### Step-Specific Rules:
|
|
32
|
-
- 🎯 Focus on scoring, rationale, Track assignment, and composite calculation
|
|
33
|
-
- 🚫 FORBIDDEN to write to the backlog file (that is step-c-04's job)
|
|
34
|
-
- 🚫 FORBIDDEN to re-gather or add new initiatives (that was step-c-02's job)
|
|
35
|
-
- 💬 Approach: propose entire batch at once so user sees relative positioning, then collaborative refinement
|
|
36
|
-
|
|
37
|
-
## EXECUTION PROTOCOLS:
|
|
38
|
-
- 🎯 Follow the MANDATORY SEQUENCE exactly
|
|
39
|
-
- 📖 Load `{templateFile}` for RICE factor definitions, scales, and calibration examples
|
|
40
|
-
- 💾 Recalculate and re-sort after every score adjustment
|
|
41
|
-
|
|
42
|
-
## CONTEXT BOUNDARIES:
|
|
43
|
-
- Available context: Gathered initiatives from step-c-02, RICE scoring guide template
|
|
44
|
-
- Focus: Scoring and user validation only
|
|
45
|
-
- Limits: Do NOT write to backlog or modify gathered initiative descriptions
|
|
46
|
-
- Dependencies: step-c-02-gather.md (gathered initiatives list)
|
|
47
|
-
|
|
48
|
-
## MANDATORY SEQUENCE
|
|
49
|
-
|
|
50
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
|
|
51
|
-
|
|
52
|
-
### 1. Load RICE Scoring Guide
|
|
53
|
-
|
|
54
|
-
Load `{templateFile}` (rice-scoring-guide.md) and internalize:
|
|
55
|
-
- **Factor definitions:** Reach (1-10), Impact (0.25-3), Confidence (20-100%), Effort (1-10)
|
|
56
|
-
- **Guided questions** for each factor
|
|
57
|
-
- **Calibration examples** (study the reasoning, not just the numbers)
|
|
58
|
-
- **Composite formula:** Score = (R x I x C) / E, where C is decimal (e.g., 70% = 0.7)
|
|
59
|
-
- **Score rounding:** One decimal place for display
|
|
60
|
-
|
|
61
|
-
### 2. Propose RICE Scores and Track for All Initiatives
|
|
62
|
-
|
|
63
|
-
For each gathered initiative, propose RICE scores using the guided questions:
|
|
64
|
-
|
|
65
|
-
- **Reach (1-10):** "How many users per quarter will this affect?"
|
|
66
|
-
- **Impact (0.25-3):** "What's the per-user impact?"
|
|
67
|
-
- **Confidence (20-100%):** "How confident are we in these estimates?" Default to 50% when no direct evidence exists.
|
|
68
|
-
- **Effort (1-10):** "Relative effort in story points?"
|
|
69
|
-
- **Track:** "Keep the lights on" (maintenance, stability, bug fixes) or "Move the needle" (growth, new capability, strategic)
|
|
70
|
-
|
|
71
|
-
For each score, write a **one-line rationale** explaining the scoring basis. Example:
|
|
72
|
-
|
|
73
|
-
> **#1: Add output examples for Noah agent** — R:5 I:1 C:70% E:2 = 1.8 | Move the needle
|
|
74
|
-
> *Reach 5: affects users checking agent outputs. Impact 1: helpful but workarounds exist. Confidence 70%: pattern validated with other agents. Effort 2: single file addition.*
|
|
75
|
-
|
|
76
|
-
### 3. Calculate Composite Scores and Sort
|
|
77
|
-
|
|
78
|
-
For each initiative:
|
|
79
|
-
1. Calculate composite: Score = (Reach x Impact x Confidence) / Effort
|
|
80
|
-
2. Round to one decimal place
|
|
81
|
-
3. Verify score falls within expected range (~0.0 to ~30.0)
|
|
82
|
-
|
|
83
|
-
Sort the batch:
|
|
84
|
-
1. **Primary:** Descending by composite score
|
|
85
|
-
2. **Tiebreak 1:** Higher Confidence first
|
|
86
|
-
3. **Tiebreak 2:** Newer insertion order first
|
|
87
|
-
|
|
88
|
-
### 4. Present Scoring Batch
|
|
89
|
-
|
|
90
|
-
Display the scored results:
|
|
91
|
-
|
|
92
|
-
> **RICE Scoring — Review Proposed Scores**
|
|
93
|
-
>
|
|
94
|
-
> **Initiatives scored: [N]**
|
|
95
|
-
>
|
|
96
|
-
> | # | Initiative | R | I | C | E | Score | Track | Rationale |
|
|
97
|
-
> |---|-----------|---|---|---|---|-------|-------|-----------|
|
|
98
|
-
> | 1 | [title] | 5 | 2 | 80% | 3 | 2.7 | Move the needle | [one-line rationale] |
|
|
99
|
-
> | 2 | [title] | 3 | 1 | 60% | 2 | 0.9 | Keep the lights on | [one-line rationale] |
|
|
100
|
-
>
|
|
101
|
-
> *Sorted by composite score (descending). Formula: (R x I x C) / E*
|
|
102
|
-
|
|
103
|
-
### 5. Present SCORING MENU OPTIONS
|
|
104
|
-
|
|
105
|
-
Display:
|
|
106
|
-
|
|
107
|
-
> **Adjust scores or finalize:**
|
|
108
|
-
>
|
|
109
|
-
> **Score adjustments** (by item number):
|
|
110
|
-
> - `#N R [value]` — Change Reach (1-10)
|
|
111
|
-
> - `#N I [value]` — Change Impact (0.25, 0.5, 1, 2, or 3)
|
|
112
|
-
> - `#N CF [value]` — Change Confidence (20-100%)
|
|
113
|
-
> - `#N E [value]` — Change Effort (1-10)
|
|
114
|
-
> - `#N T [value]` — Change Track ("keep" or "move")
|
|
115
|
-
>
|
|
116
|
-
> **Batch editing:**
|
|
117
|
-
> - `D #N` — Drop item #N from the batch (will not be added to backlog)
|
|
118
|
-
>
|
|
119
|
-
> **[A] Advanced Elicitation** — Deeper analysis of scoring rationale
|
|
120
|
-
> **[P] Party Mode** — Multi-perspective scoring discussion
|
|
121
|
-
> **[C] Continue** — Finalize scores and proceed to backlog generation
|
|
122
|
-
|
|
123
|
-
#### Menu Handling Logic:
|
|
124
|
-
- IF `#N R [value]`: Update Reach for item #N. Recalculate composite. Re-sort batch. Redisplay table and menu.
|
|
125
|
-
- IF `#N I [value]`: Update Impact for item #N. Recalculate composite. Re-sort batch. Redisplay table and menu.
|
|
126
|
-
- IF `#N CF [value]`: Update Confidence for item #N. Recalculate composite. Re-sort batch. Redisplay table and menu.
|
|
127
|
-
- IF `#N E [value]`: Update Effort for item #N. Recalculate composite. Re-sort batch. Redisplay table and menu.
|
|
128
|
-
- IF `#N T [value]`: Update Track for item #N ("keep" = "Keep the lights on", "move" = "Move the needle"). Redisplay table and menu.
|
|
129
|
-
- IF `D #N`: Remove item #N from the scoring batch. Redisplay table and menu.
|
|
130
|
-
- IF A: Execute `{advancedElicitationTask}` for deeper scoring analysis, and when finished redisplay the menu.
|
|
131
|
-
- IF P: Execute `{partyModeWorkflow}` for multi-perspective scoring discussion, and when finished redisplay the menu.
|
|
132
|
-
- IF C: Finalize the scored batch. Load, read the entire file, and execute `{project-root}/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-04-prioritize.md`
|
|
133
|
-
- IF any other input: Display "Unknown command. Use `#N R/I/CF/E/T [value]`, `D #N`, **A**, **P**, or **C** to continue." then redisplay menu.
|
|
134
|
-
|
|
135
|
-
#### EXECUTION RULES:
|
|
136
|
-
- ALWAYS halt and wait for user input after presenting the menu
|
|
137
|
-
- After EVERY score or Track adjustment, recalculate composite, re-sort, and redisplay the full table AND the menu
|
|
138
|
-
- The user may make multiple adjustments before pressing C
|
|
139
|
-
- ONLY proceed to step-c-04 when user selects 'C'
|
|
140
|
-
- After A or P execution, return to this menu
|
|
141
|
-
- Do NOT auto-continue — the user must explicitly approve the scores
|
|
142
|
-
|
|
143
|
-
## 🚨 SYSTEM SUCCESS/FAILURE METRICS:
|
|
144
|
-
### ✅ SUCCESS: All initiatives scored with calibrated RICE components, rationale, and Track assignment, composites calculated correctly, batch sorted by score, user validated scores, finalized batch passed to step-c-04
|
|
145
|
-
### ❌ SYSTEM FAILURE: Scores proposed without rationale, composite formula wrong, Track not assigned, scores outside valid ranges, user not given validation opportunity, items written to backlog prematurely
|
|
146
|
-
**Master Rule:** Skipping steps is FORBIDDEN.
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: 'step-c-04-prioritize'
|
|
3
|
-
description: 'Generate complete backlog file with categorized items, prioritized view, and completion summary'
|
|
4
|
-
outputFile: '{planning_artifacts}/initiatives-backlog.md'
|
|
5
|
-
templateFile: '{project-root}/_bmad/bme/_enhance/workflows/initiatives-backlog/templates/backlog-format-spec.md'
|
|
6
|
-
workflowFile: '{project-root}/_bmad/bme/_enhance/workflows/initiatives-backlog/workflow.md'
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Step 4: Backlog Generation, Prioritized View & Completion
|
|
10
|
-
|
|
11
|
-
## STEP GOAL:
|
|
12
|
-
|
|
13
|
-
Generate the complete backlog file from scratch using the scored initiatives, including all required sections, the prioritized view, provenance tags, and a changelog entry. Present a completion summary and return to the T/R/C menu.
|
|
14
|
-
|
|
15
|
-
## MANDATORY EXECUTION RULES (READ FIRST):
|
|
16
|
-
|
|
17
|
-
### Universal Rules:
|
|
18
|
-
- 🛑 NEVER generate content without completing all mandatory sequence steps
|
|
19
|
-
- 📖 CRITICAL: Read this complete step file before taking action
|
|
20
|
-
- 🔄 CRITICAL: When returning to menu, read the entire workflow file
|
|
21
|
-
- 📋 YOU ARE A BACKLOG OPERATIONS SPECIALIST generating a new backlog file
|
|
22
|
-
|
|
23
|
-
### Role Reinforcement:
|
|
24
|
-
- ✅ You are a **backlog operations specialist** — precise, structured, format-compliant
|
|
25
|
-
- ✅ Generate the file exactly matching the backlog format specification — no shortcuts
|
|
26
|
-
- ✅ All output must be standard markdown — no HTML, no proprietary syntax
|
|
27
|
-
- ✅ Every item gets provenance, every section gets created, the prioritized view is sorted
|
|
28
|
-
|
|
29
|
-
### Step-Specific Rules:
|
|
30
|
-
- 🎯 Focus on file generation, provenance, prioritized view, and completion reporting
|
|
31
|
-
- 🚫 FORBIDDEN to rescore items (scoring was finalized in step-c-03)
|
|
32
|
-
- 🚫 FORBIDDEN to add new items not in the scored batch
|
|
33
|
-
- 🚫 FORBIDDEN to modify step-c-01, step-c-02, or step-c-03
|
|
34
|
-
- 💬 Approach: generate the complete file, summarize clearly, return to menu
|
|
35
|
-
|
|
36
|
-
## EXECUTION PROTOCOLS:
|
|
37
|
-
- 🎯 Follow the MANDATORY SEQUENCE exactly
|
|
38
|
-
- 📖 Load `{templateFile}` (backlog-format-spec.md) for exact structural requirements and table formats
|
|
39
|
-
- 💾 Write to `{outputFile}` as a complete new file
|
|
40
|
-
|
|
41
|
-
## CONTEXT BOUNDARIES:
|
|
42
|
-
- Available context: Scored initiatives from step-c-03, backlog format spec template
|
|
43
|
-
- Focus: File generation, prioritized view, completion summary
|
|
44
|
-
- Limits: Do NOT rescore or re-gather items
|
|
45
|
-
- Dependencies: step-c-03-score.md (finalized scored initiatives with Track assignments)
|
|
46
|
-
|
|
47
|
-
## MANDATORY SEQUENCE
|
|
48
|
-
|
|
49
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
|
|
50
|
-
|
|
51
|
-
### 1. Load Format Specification
|
|
52
|
-
|
|
53
|
-
Load `{templateFile}` (backlog-format-spec.md) and reference:
|
|
54
|
-
- **Metadata header** format (title, Created, Method, Last Updated)
|
|
55
|
-
- **Section hierarchy** — all 7 H2 sections in exact order
|
|
56
|
-
- **Table formats** — Category table (10 columns), Prioritized View (6 columns), Exploration Candidates (4 columns)
|
|
57
|
-
- **Item ID format** — Category prefix letter + sequential number
|
|
58
|
-
- **Provenance format** — "Added from Create mode, [date]"
|
|
59
|
-
|
|
60
|
-
### 2. Generate Metadata Header
|
|
61
|
-
|
|
62
|
-
```markdown
|
|
63
|
-
# Convoke Initiatives Backlog
|
|
64
|
-
|
|
65
|
-
**Created:** [current date YYYY-MM-DD]
|
|
66
|
-
**Method:** RICE (Reach, Impact, Confidence, Effort)
|
|
67
|
-
**Last Updated:** [current date YYYY-MM-DD]
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### 3. Generate RICE Scoring Guide Section
|
|
71
|
-
|
|
72
|
-
Create the `## RICE Scoring Guide` section with an inline summary of the methodology:
|
|
73
|
-
- Composite formula: Score = (R x I x C) / E
|
|
74
|
-
- Factor scales: Reach (1-10), Impact (0.25-3), Confidence (20-100%), Effort (1-10)
|
|
75
|
-
- Sort order: Descending by score, tiebreak by Confidence then insertion order
|
|
76
|
-
|
|
77
|
-
### 4. Generate Backlog Section with Category Tables
|
|
78
|
-
|
|
79
|
-
Create the `## Backlog` section. For each unique category in the scored items:
|
|
80
|
-
|
|
81
|
-
1. Create an H3 heading: `### [Category Name]`
|
|
82
|
-
2. Create a 10-column table:
|
|
83
|
-
|
|
84
|
-
```markdown
|
|
85
|
-
| # | Initiative | Source | R | I | C | E | Score | Track | Status |
|
|
86
|
-
|---|-----------|--------|---|---|---|---|-------|-------|--------|
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
3. For each item in this category:
|
|
90
|
-
- **#:** Generate item ID using category prefix letter + sequential number within category (e.g., D1, D2, P1)
|
|
91
|
-
- Category prefix mapping: D = Documentation & Onboarding, U = Update & Migration System, T = Testing & CI, I = Infrastructure, A = Agent Quality & Consistency, P = Platform & Product Vision
|
|
92
|
-
- New categories: use the first uppercase letter of the category name that is not already in use (D, U, T, I, A, P are reserved)
|
|
93
|
-
- **Initiative:** `**[Title]** — [description]. Added from Create mode, [date]`
|
|
94
|
-
- **Source:** "Create mode"
|
|
95
|
-
- **R, I, C, E:** Individual RICE component scores (C as percentage, e.g., 70%)
|
|
96
|
-
- **Score:** Composite score, one decimal place
|
|
97
|
-
- **Track:** "Keep the lights on" or "Move the needle"
|
|
98
|
-
- **Status:** "Backlog"
|
|
99
|
-
|
|
100
|
-
### 5. Generate Empty Sections
|
|
101
|
-
|
|
102
|
-
Create the following sections with empty content:
|
|
103
|
-
|
|
104
|
-
**Exploration Candidates:**
|
|
105
|
-
```markdown
|
|
106
|
-
## Exploration Candidates
|
|
107
|
-
|
|
108
|
-
| # | Initiative | Source | Next Step |
|
|
109
|
-
|---|-----------|--------|-----------|
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
**Epic Groupings:**
|
|
113
|
-
```markdown
|
|
114
|
-
## Epic Groupings
|
|
115
|
-
|
|
116
|
-
*No epic groupings defined yet.*
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
**Completed:**
|
|
120
|
-
```markdown
|
|
121
|
-
## Completed
|
|
122
|
-
|
|
123
|
-
*No completed items yet.*
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### 6. Generate Prioritized View
|
|
127
|
-
|
|
128
|
-
Create the `## Prioritized View (by RICE Score)` section:
|
|
129
|
-
|
|
130
|
-
1. Collect ALL items from all category tables
|
|
131
|
-
2. Sort by composite RICE score descending
|
|
132
|
-
3. Tiebreak: (1) Higher Confidence first, (2) Newer insertion order first
|
|
133
|
-
4. Generate sequential rank numbers starting at 1
|
|
134
|
-
|
|
135
|
-
```markdown
|
|
136
|
-
## Prioritized View (by RICE Score)
|
|
137
|
-
|
|
138
|
-
| Rank | # | Initiative | Score | Track | Category |
|
|
139
|
-
|------|---|-----------|-------|-------|----------|
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### 7. Generate Change Log
|
|
143
|
-
|
|
144
|
-
Create the `## Change Log` section with the initial creation entry:
|
|
145
|
-
|
|
146
|
-
```markdown
|
|
147
|
-
## Change Log
|
|
148
|
-
|
|
149
|
-
| Date | Change |
|
|
150
|
-
|------|--------|
|
|
151
|
-
| [YYYY-MM-DD] | Create: Bootstrapped new backlog with [N] items ([list categories affected]). |
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### 8. Write Complete File
|
|
155
|
-
|
|
156
|
-
Write the complete assembled backlog to `{outputFile}`. The file must contain all 7 H2 sections in the correct order as specified by the format spec.
|
|
157
|
-
|
|
158
|
-
### 9. Completion Summary & Return to Menu
|
|
159
|
-
|
|
160
|
-
After successful write, display:
|
|
161
|
-
|
|
162
|
-
> **Create Complete**
|
|
163
|
-
>
|
|
164
|
-
> **Items created:** [N]
|
|
165
|
-
> **Categories:** [list category names]
|
|
166
|
-
>
|
|
167
|
-
> **Top 3 Positions:**
|
|
168
|
-
> 1. [#ID] [title] — Score: [X.X]
|
|
169
|
-
> 2. [#ID] [title] — Score: [X.X]
|
|
170
|
-
> 3. [#ID] [title] — Score: [X.X]
|
|
171
|
-
|
|
172
|
-
Then return to the T/R/C menu:
|
|
173
|
-
|
|
174
|
-
> Loading `{workflowFile}` to return to mode selection...
|
|
175
|
-
|
|
176
|
-
Load, read the entire file, and execute `{workflowFile}`.
|
|
177
|
-
|
|
178
|
-
## 🚨 SYSTEM SUCCESS/FAILURE METRICS:
|
|
179
|
-
### ✅ SUCCESS: Complete backlog file generated with all 7 H2 sections in correct order, items placed in correct category tables with 10 columns, item IDs generated correctly, provenance tags added, prioritized view sorted and generated with 6 columns, changelog entry added, completion summary displayed with top 3, T/R/C menu re-presented
|
|
180
|
-
### ❌ SYSTEM FAILURE: Missing H2 sections, wrong section order, items without provenance, wrong column counts, item IDs not generated, prioritized view not sorted, no changelog entry, no completion summary, no return to menu
|
|
181
|
-
**Master Rule:** Skipping steps is FORBIDDEN.
|