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.
Files changed (37) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +3 -1
  3. package/_bmad/bme/README.md +36 -0
  4. package/_bmad/bme/_enhance/workflows/initiatives-backlog/SKILL.md +1 -1
  5. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-01-init.md +55 -32
  6. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-02-gather.md +62 -59
  7. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-03-qualify.md +176 -0
  8. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-04-generate.md +259 -0
  9. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/step-r-01-load.md +65 -35
  10. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/step-r-02-rescore.md +60 -30
  11. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/step-r-03-update.md +67 -71
  12. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-01-ingest.md +12 -12
  13. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-02-extract.md +49 -44
  14. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-03-qualify.md +192 -0
  15. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-04-update.md +72 -67
  16. package/_bmad/bme/_enhance/workflows/initiatives-backlog/templates/backlog-format-spec.md +223 -112
  17. package/_bmad/bme/_enhance/workflows/initiatives-backlog/templates/lifecycle-process-spec.md +188 -0
  18. package/_bmad/bme/_enhance/workflows/initiatives-backlog/workflow.md +44 -31
  19. package/_bmad/bme/_gyre/config.yaml +3 -0
  20. package/_bmad/bme/_vortex/config.yaml +4 -1
  21. package/package.json +1 -1
  22. package/scripts/convoke-doctor.js +56 -2
  23. package/scripts/lib/artifact-utils.js +16 -3
  24. package/scripts/migrate-artifacts.js +3 -2
  25. package/scripts/portability/convoke-export.js +26 -5
  26. package/scripts/portability/export-engine.js +10 -8
  27. package/scripts/portability/seed-catalog-repo.js +6 -6
  28. package/scripts/portability/validate-exports.js +25 -14
  29. package/scripts/update/convoke-update.js +27 -2
  30. package/scripts/update/lib/changelog-reader.js +90 -0
  31. package/scripts/update/lib/config-merger.js +52 -1
  32. package/scripts/update/lib/refresh-installation.js +48 -9
  33. package/scripts/update/lib/taxonomy-merger.js +2 -1
  34. package/scripts/update/lib/validator.js +9 -1
  35. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-03-score.md +0 -146
  36. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-04-prioritize.md +0 -181
  37. 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. Deliberately removed core agents are restored on upgrade.
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, USER_GUIDES, GYRE_AGENTS, GYRE_AGENT_FILES, GYRE_AGENT_IDS, GYRE_WORKFLOW_NAMES, EXTRA_BME_AGENTS } = require('./agent-registry');
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
- ...AGENTS.map(a => buildAgentRow610(a, '_vortex')),
509
- ...GYRE_AGENTS.map(a => buildAgentRow610(a, '_gyre')),
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
- ...AGENTS.map(a => buildAgentRowLegacy(a, '_vortex')),
515
- ...GYRE_AGENTS.map(a => buildAgentRowLegacy(a, '_gyre')),
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
- for (const guide of USER_GUIDES) {
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
- const requiredAgents = AGENT_FILES;
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.