bmad-method 4.27.5 → 4.28.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 (45) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/bmad-core/agents/analyst.md +3 -4
  3. package/bmad-core/agents/architect.md +3 -4
  4. package/bmad-core/agents/bmad-master.md +9 -31
  5. package/bmad-core/agents/bmad-orchestrator.md +3 -8
  6. package/bmad-core/agents/dev.md +3 -4
  7. package/bmad-core/agents/pm.md +3 -4
  8. package/bmad-core/agents/po.md +3 -4
  9. package/bmad-core/agents/qa.md +3 -4
  10. package/bmad-core/agents/sm.md +3 -4
  11. package/bmad-core/agents/ux-expert.md +3 -4
  12. package/bmad-core/tasks/create-next-story.md +0 -1
  13. package/bmad-core/tasks/validate-next-story.md +1 -1
  14. package/bmad-core/workflows/brownfield-fullstack.yaml +1 -1
  15. package/bmad-core/workflows/brownfield-service.yaml +1 -1
  16. package/bmad-core/workflows/brownfield-ui.yaml +1 -1
  17. package/bmad-core/workflows/greenfield-fullstack.yaml +1 -1
  18. package/bmad-core/workflows/greenfield-ui.yaml +1 -1
  19. package/dist/agents/analyst.txt +3 -3
  20. package/dist/agents/bmad-master.txt +7 -324
  21. package/dist/agents/bmad-orchestrator.txt +3 -229
  22. package/dist/agents/dev.txt +1 -1
  23. package/dist/agents/po.txt +1 -1
  24. package/dist/agents/sm.txt +0 -1
  25. package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +0 -226
  26. package/dist/teams/team-all.txt +9 -236
  27. package/dist/teams/team-fullstack.txt +9 -235
  28. package/dist/teams/team-ide-minimal.txt +4 -231
  29. package/dist/teams/team-no-ui.txt +5 -231
  30. package/docs/agentic-tools/claude-code-guide.md +1 -1
  31. package/docs/agentic-tools/gemini-cli-guide.md +6 -7
  32. package/docs/bmad-workflow-guide.md +1 -0
  33. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.md +2 -3
  34. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.md +2 -3
  35. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.md +2 -3
  36. package/expansion-packs/bmad-creator-tools/agents/bmad-the-creator.md +2 -3
  37. package/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.md +2 -3
  38. package/package.json +1 -1
  39. package/tools/installer/config/install.config.yaml +7 -6
  40. package/tools/installer/lib/file-manager.js +77 -2
  41. package/tools/installer/lib/ide-setup.js +82 -38
  42. package/tools/installer/lib/installer.js +54 -25
  43. package/tools/installer/package.json +1 -1
  44. package/tools/upgraders/v3-to-v4-upgrader.js +1 -1
  45. package/bmad-core/utils/plan-management.md +0 -219
@@ -131,7 +131,7 @@ class IdeSetup {
131
131
  }
132
132
 
133
133
  async setupClaudeCode(installDir, selectedAgent) {
134
- const commandsDir = path.join(installDir, ".claude", "commands");
134
+ const commandsDir = path.join(installDir, ".claude", "commands", "BMad");
135
135
  const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
136
136
 
137
137
  await fileManager.ensureDirectory(commandsDir);
@@ -512,12 +512,53 @@ class IdeSetup {
512
512
  async setupGeminiCli(installDir, selectedAgent) {
513
513
  await initializeModules();
514
514
  const geminiDir = path.join(installDir, ".gemini");
515
- const agentsContextDir = path.join(geminiDir, "agents");
516
- await fileManager.ensureDirectory(agentsContextDir);
515
+ const bmadMethodDir = path.join(geminiDir, "bmad-method");
516
+ await fileManager.ensureDirectory(bmadMethodDir);
517
+
518
+ // Update logic for existing settings.json
519
+ const settingsPath = path.join(geminiDir, "settings.json");
520
+ if (await fileManager.pathExists(settingsPath)) {
521
+ try {
522
+ const settingsContent = await fileManager.readFile(settingsPath);
523
+ const settings = JSON.parse(settingsContent);
524
+ let updated = false;
525
+
526
+ // Handle contextFileName property
527
+ if (settings.contextFileName && Array.isArray(settings.contextFileName)) {
528
+ const originalLength = settings.contextFileName.length;
529
+ settings.contextFileName = settings.contextFileName.filter(
530
+ (fileName) => !fileName.startsWith("agents/")
531
+ );
532
+ if (settings.contextFileName.length !== originalLength) {
533
+ updated = true;
534
+ }
535
+ }
536
+
537
+ if (updated) {
538
+ await fileManager.writeFile(
539
+ settingsPath,
540
+ JSON.stringify(settings, null, 2)
541
+ );
542
+ console.log(chalk.green("✓ Updated .gemini/settings.json - removed agent file references"));
543
+ }
544
+ } catch (error) {
545
+ console.warn(
546
+ chalk.yellow("Could not update .gemini/settings.json"),
547
+ error
548
+ );
549
+ }
550
+ }
551
+
552
+ // Remove old agents directory
553
+ const agentsDir = path.join(geminiDir, "agents");
554
+ if (await fileManager.pathExists(agentsDir)) {
555
+ await fileManager.removeDirectory(agentsDir);
556
+ console.log(chalk.green("✓ Removed old .gemini/agents directory"));
557
+ }
517
558
 
518
559
  // Get all available agents
519
560
  const agents = await this.getAllAgentIds(installDir);
520
- const agentContextFiles = [];
561
+ let concatenatedContent = "";
521
562
 
522
563
  for (const agentId of agents) {
523
564
  // Find the source agent file
@@ -525,43 +566,46 @@ class IdeSetup {
525
566
 
526
567
  if (agentPath) {
527
568
  const agentContent = await fileManager.readFile(agentPath);
528
- const contextFilePath = path.join(agentsContextDir, `${agentId}.md`);
529
-
530
- // Copy the agent content directly into its own context file
531
- await fileManager.writeFile(contextFilePath, agentContent);
532
-
533
- // Store the relative path for settings.json
534
- const relativePath = path.relative(geminiDir, contextFilePath);
535
- agentContextFiles.push(relativePath.replace(/\\/g, '/')); // Ensure forward slashes for consistency
536
- console.log(chalk.green(`✓ Created context file for @${agentId}`));
537
- }
538
- }
539
-
540
- console.log(chalk.green(`\n✓ Created individual agent context files in ${agentsContextDir}`));
541
-
542
- // Add GEMINI.md to the context files array
543
- agentContextFiles.push("GEMINI.md");
544
-
545
- // Create or update settings.json
546
- const settingsPath = path.join(geminiDir, "settings.json");
547
- let settings = {};
548
-
549
- if (await fileManager.pathExists(settingsPath)) {
550
- try {
551
- const existingSettings = await fileManager.readFile(settingsPath);
552
- settings = JSON.parse(existingSettings);
553
- console.log(chalk.yellow("Found existing .gemini/settings.json. Merging settings..."));
554
- } catch (e) {
555
- console.error(chalk.red("Error parsing existing settings.json. It will be overwritten."), e);
556
- settings = {};
569
+
570
+ // Create properly formatted agent rule content (similar to trae)
571
+ let agentRuleContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
572
+ agentRuleContent += `This rule is triggered when the user types \`*${agentId}\` and activates the ${await this.getAgentTitle(
573
+ agentId,
574
+ installDir
575
+ )} agent persona.\n\n`;
576
+ agentRuleContent += "## Agent Activation\n\n";
577
+ agentRuleContent +=
578
+ "CRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n";
579
+ agentRuleContent += "```yaml\n";
580
+ // Extract just the YAML content from the agent file
581
+ const yamlContent = extractYamlFromAgent(agentContent);
582
+ if (yamlContent) {
583
+ agentRuleContent += yamlContent;
584
+ }
585
+ else {
586
+ // If no YAML found, include the whole content minus the header
587
+ agentRuleContent += agentContent.replace(/^#.*$/m, "").trim();
588
+ }
589
+ agentRuleContent += "\n```\n\n";
590
+ agentRuleContent += "## File Reference\n\n";
591
+ const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
592
+ agentRuleContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
593
+ agentRuleContent += "## Usage\n\n";
594
+ agentRuleContent += `When the user types \`*${agentId}\`, activate this ${await this.getAgentTitle(
595
+ agentId,
596
+ installDir
597
+ )} persona and follow all instructions defined in the YAML configuration above.\n`;
598
+
599
+ // Add to concatenated content with separator
600
+ concatenatedContent += agentRuleContent + "\n\n---\n\n";
601
+ console.log(chalk.green(`✓ Added context for @${agentId}`));
557
602
  }
558
603
  }
559
604
 
560
- // Set contextFileName to our new array of files
561
- settings.contextFileName = agentContextFiles;
562
-
563
- await fileManager.writeFile(settingsPath, JSON.stringify(settings, null, 2));
564
- console.log(chalk.green(`✓ Configured .gemini/settings.json to load all agent context files.`));
605
+ // Write the concatenated content to GEMINI.md
606
+ const geminiMdPath = path.join(bmadMethodDir, "GEMINI.md");
607
+ await fileManager.writeFile(geminiMdPath, concatenatedContent);
608
+ console.log(chalk.green(`\n✓ Created GEMINI.md in ${bmadMethodDir}`));
565
609
 
566
610
  return true;
567
611
  }
@@ -244,7 +244,7 @@ class Installer {
244
244
  spinner.text = "Copying complete .bmad-core folder...";
245
245
  const sourceDir = configLoader.getBmadCorePath();
246
246
  const bmadCoreDestDir = path.join(installDir, ".bmad-core");
247
- await fileManager.copyDirectory(sourceDir, bmadCoreDestDir);
247
+ await fileManager.copyDirectoryWithRootReplacement(sourceDir, bmadCoreDestDir, ".bmad-core");
248
248
 
249
249
  // Copy common/ items to .bmad-core
250
250
  spinner.text = "Copying common utilities...";
@@ -263,7 +263,7 @@ class Installer {
263
263
  // Single agent installation
264
264
  spinner.text = `Installing ${config.agent} agent...`;
265
265
 
266
- // Copy agent file
266
+ // Copy agent file with {root} replacement
267
267
  const agentPath = configLoader.getAgentPath(config.agent);
268
268
  const destAgentPath = path.join(
269
269
  installDir,
@@ -271,7 +271,7 @@ class Installer {
271
271
  "agents",
272
272
  `${config.agent}.md`
273
273
  );
274
- await fileManager.copyFile(agentPath, destAgentPath);
274
+ await fileManager.copyFileWithRootReplacement(agentPath, destAgentPath, ".bmad-core");
275
275
  files.push(`.bmad-core/agents/${config.agent}.md`);
276
276
 
277
277
  // Copy dependencies
@@ -284,15 +284,16 @@ class Installer {
284
284
  spinner.text = `Copying dependency: ${dep}`;
285
285
 
286
286
  if (dep.includes("*")) {
287
- // Handle glob patterns
287
+ // Handle glob patterns with {root} replacement
288
288
  const copiedFiles = await fileManager.copyGlobPattern(
289
289
  dep.replace(".bmad-core/", ""),
290
290
  sourceBase,
291
- path.join(installDir, ".bmad-core")
291
+ path.join(installDir, ".bmad-core"),
292
+ ".bmad-core"
292
293
  );
293
294
  files.push(...copiedFiles.map(f => `.bmad-core/${f}`));
294
295
  } else {
295
- // Handle single files
296
+ // Handle single files with {root} replacement if needed
296
297
  const sourcePath = path.join(
297
298
  sourceBase,
298
299
  dep.replace(".bmad-core/", "")
@@ -302,7 +303,16 @@ class Installer {
302
303
  dep
303
304
  );
304
305
 
305
- if (await fileManager.copyFile(sourcePath, destPath)) {
306
+ const needsRootReplacement = dep.endsWith('.md') || dep.endsWith('.yaml') || dep.endsWith('.yml');
307
+ let success = false;
308
+
309
+ if (needsRootReplacement) {
310
+ success = await fileManager.copyFileWithRootReplacement(sourcePath, destPath, ".bmad-core");
311
+ } else {
312
+ success = await fileManager.copyFile(sourcePath, destPath);
313
+ }
314
+
315
+ if (success) {
306
316
  files.push(dep);
307
317
  }
308
318
  }
@@ -325,19 +335,29 @@ class Installer {
325
335
  spinner.text = `Copying team dependency: ${dep}`;
326
336
 
327
337
  if (dep.includes("*")) {
328
- // Handle glob patterns
338
+ // Handle glob patterns with {root} replacement
329
339
  const copiedFiles = await fileManager.copyGlobPattern(
330
340
  dep.replace(".bmad-core/", ""),
331
341
  sourceBase,
332
- path.join(installDir, ".bmad-core")
342
+ path.join(installDir, ".bmad-core"),
343
+ ".bmad-core"
333
344
  );
334
345
  files.push(...copiedFiles.map(f => `.bmad-core/${f}`));
335
346
  } else {
336
- // Handle single files
347
+ // Handle single files with {root} replacement if needed
337
348
  const sourcePath = path.join(sourceBase, dep.replace(".bmad-core/", ""));
338
349
  const destPath = path.join(installDir, dep);
339
350
 
340
- if (await fileManager.copyFile(sourcePath, destPath)) {
351
+ const needsRootReplacement = dep.endsWith('.md') || dep.endsWith('.yaml') || dep.endsWith('.yml');
352
+ let success = false;
353
+
354
+ if (needsRootReplacement) {
355
+ success = await fileManager.copyFileWithRootReplacement(sourcePath, destPath, ".bmad-core");
356
+ } else {
357
+ success = await fileManager.copyFile(sourcePath, destPath);
358
+ }
359
+
360
+ if (success) {
341
361
  files.push(dep);
342
362
  }
343
363
  }
@@ -1172,32 +1192,41 @@ class Installer {
1172
1192
  nodir: true
1173
1193
  });
1174
1194
 
1175
- // Copy each file to the expansion pack's dot folder
1195
+ // Copy each file to the expansion pack's dot folder with {root} replacement
1176
1196
  for (const file of files) {
1177
1197
  const sourcePath = path.join(sourceFolder, file);
1178
1198
  const destPath = path.join(expansionDotFolder, folder, file);
1179
1199
 
1180
- if (await fileManager.copyFile(sourcePath, destPath)) {
1200
+ const needsRootReplacement = file.endsWith('.md') || file.endsWith('.yaml') || file.endsWith('.yml');
1201
+ let success = false;
1202
+
1203
+ if (needsRootReplacement) {
1204
+ success = await fileManager.copyFileWithRootReplacement(sourcePath, destPath, `.${packId}`);
1205
+ } else {
1206
+ success = await fileManager.copyFile(sourcePath, destPath);
1207
+ }
1208
+
1209
+ if (success) {
1181
1210
  installedFiles.push(path.join(`.${packId}`, folder, file));
1182
1211
  }
1183
1212
  }
1184
1213
  }
1185
1214
  }
1186
1215
 
1187
- // Copy config.yaml
1216
+ // Copy config.yaml with {root} replacement
1188
1217
  const configPath = path.join(expansionPackDir, 'config.yaml');
1189
1218
  if (await fileManager.pathExists(configPath)) {
1190
1219
  const configDestPath = path.join(expansionDotFolder, 'config.yaml');
1191
- if (await fileManager.copyFile(configPath, configDestPath)) {
1220
+ if (await fileManager.copyFileWithRootReplacement(configPath, configDestPath, `.${packId}`)) {
1192
1221
  installedFiles.push(path.join(`.${packId}`, 'config.yaml'));
1193
1222
  }
1194
1223
  }
1195
1224
 
1196
- // Copy README if it exists
1225
+ // Copy README if it exists with {root} replacement
1197
1226
  const readmePath = path.join(expansionPackDir, 'README.md');
1198
1227
  if (await fileManager.pathExists(readmePath)) {
1199
1228
  const readmeDestPath = path.join(expansionDotFolder, 'README.md');
1200
- if (await fileManager.copyFile(readmePath, readmeDestPath)) {
1229
+ if (await fileManager.copyFileWithRootReplacement(readmePath, readmeDestPath, `.${packId}`)) {
1201
1230
  installedFiles.push(path.join(`.${packId}`, 'README.md'));
1202
1231
  }
1203
1232
  }
@@ -1258,7 +1287,7 @@ class Installer {
1258
1287
  const yamlContent = extractYamlFromAgent(agentContent);
1259
1288
  if (yamlContent) {
1260
1289
  try {
1261
- const agentConfig = yaml.parse(yamlContent);
1290
+ const agentConfig = yaml.load(yamlContent);
1262
1291
  const dependencies = agentConfig.dependencies || {};
1263
1292
 
1264
1293
  // Check for core dependencies (those that don't exist in the expansion pack)
@@ -1277,9 +1306,9 @@ class Installer {
1277
1306
  if (await fileManager.pathExists(coreDepPath)) {
1278
1307
  spinner.text = `Copying core dependency ${dep} for ${packId}...`;
1279
1308
 
1280
- // Copy from core to expansion pack dot folder
1309
+ // Copy from core to expansion pack dot folder with {root} replacement
1281
1310
  const destPath = path.join(expansionDotFolder, depType, depFileName);
1282
- await fileManager.copyFile(coreDepPath, destPath);
1311
+ await fileManager.copyFileWithRootReplacement(coreDepPath, destPath, `.${packId}`);
1283
1312
 
1284
1313
  console.log(chalk.dim(` Added core dependency: ${depType}/${depFileName}`));
1285
1314
  } else {
@@ -1321,7 +1350,7 @@ class Installer {
1321
1350
  const teamContent = await fs.readFile(teamPath, 'utf8');
1322
1351
 
1323
1352
  try {
1324
- const teamConfig = yaml.parse(teamContent);
1353
+ const teamConfig = yaml.load(teamContent);
1325
1354
  const agents = teamConfig.agents || [];
1326
1355
 
1327
1356
  // Add bmad-orchestrator if not present (required for all teams)
@@ -1338,9 +1367,9 @@ class Installer {
1338
1367
  if (await fileManager.pathExists(coreAgentPath)) {
1339
1368
  spinner.text = `Copying core agent ${agentId} for ${packId}...`;
1340
1369
 
1341
- // Copy agent file
1370
+ // Copy agent file with {root} replacement
1342
1371
  const destPath = path.join(expansionDotFolder, 'agents', `${agentId}.md`);
1343
- await fileManager.copyFile(coreAgentPath, destPath);
1372
+ await fileManager.copyFileWithRootReplacement(coreAgentPath, destPath, `.${packId}`);
1344
1373
  existingAgents.add(agentId);
1345
1374
 
1346
1375
  console.log(chalk.dim(` Added core agent: ${agentId}`));
@@ -1352,7 +1381,7 @@ class Installer {
1352
1381
  if (yamlContent) {
1353
1382
  try {
1354
1383
 
1355
- const agentConfig = yaml.parse(yamlContent);
1384
+ const agentConfig = yaml.load(yamlContent);
1356
1385
  const dependencies = agentConfig.dependencies || {};
1357
1386
 
1358
1387
  // Copy all dependencies for this agent
@@ -1370,7 +1399,7 @@ class Installer {
1370
1399
 
1371
1400
  if (await fileManager.pathExists(coreDepPath)) {
1372
1401
  const destDepPath = path.join(expansionDotFolder, depType, depFileName);
1373
- await fileManager.copyFile(coreDepPath, destDepPath);
1402
+ await fileManager.copyFileWithRootReplacement(coreDepPath, destDepPath, `.${packId}`);
1374
1403
  console.log(chalk.dim(` Added agent dependency: ${depType}/${depFileName}`));
1375
1404
  } else {
1376
1405
  // Try common folder
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bmad-method",
3
- "version": "4.27.5",
3
+ "version": "4.28.0",
4
4
  "description": "BMad Method installer - AI-powered Agile development framework",
5
5
  "main": "lib/installer.js",
6
6
  "bin": {
@@ -558,7 +558,7 @@ class V3ToV4Upgrader {
558
558
  try {
559
559
  const ideMessages = {
560
560
  cursor: "Rules created in .cursor/rules/",
561
- "claude-code": "Commands created in .claude/commands/",
561
+ "claude-code": "Commands created in .claude/commands/BMad/",
562
562
  windsurf: "Rules created in .windsurf/rules/",
563
563
  trae: "Rules created in.trae/rules/",
564
564
  roo: "Custom modes created in .roomodes",
@@ -1,219 +0,0 @@
1
- # Plan Management Utility
2
-
3
- ## Purpose
4
-
5
- Provides utilities for agents and tasks to interact with workflow plans, check progress, update status, and ensure workflow steps are executed in the appropriate sequence.
6
-
7
- ## Core Functions
8
-
9
- ### 1. Check Plan Existence
10
-
11
- Check for workflow plan:
12
-
13
- 1. Look for docs/workflow-plan.md (default location)
14
- 2. Return plan status to user (exists/not exists) - if not exists then HALT.
15
-
16
- ### 2. Parse Plan Status
17
-
18
- [[LLM: Extract current progress from the plan document]]
19
-
20
- **Plan Parsing Logic:**
21
-
22
- 1. **Identify Step Structure**:
23
- - Look for checkbox lines: `- [ ]` or `- [x]`
24
- - Extract step IDs from comments: `<!-- step-id: X.Y -->`
25
- - Identify agent assignments: `<!-- agent: pm -->`
26
-
27
- 2. **Determine Current State**:
28
- - Last completed step (highest numbered `[x]`)
29
- - Next expected step (first `[ ]` after completed steps)
30
- - Overall progress percentage
31
-
32
- 3. **Extract Metadata**:
33
- - Workflow type from plan header
34
- - Decision points and their status
35
- - Any deviation notes
36
-
37
- ### 3. Sequence Validation
38
-
39
- [[LLM: Check if requested action aligns with plan sequence]]
40
-
41
- **Validation Rules:**
42
-
43
- 1. **Strict Mode** (enforceSequence: true):
44
- - Must complete steps in exact order
45
- - Warn and block if out of sequence
46
- - Require explicit override justification
47
-
48
- 2. **Flexible Mode** (enforceSequence: false):
49
- - Warn about sequence deviation
50
- - Allow with confirmation
51
- - Log deviation reason
52
-
53
- **Warning Templates:**
54
-
55
- ```text
56
- SEQUENCE WARNING:
57
- The workflow plan shows you should complete "{expected_step}" next.
58
- You're attempting to: "{requested_action}"
59
-
60
- In strict mode: Block and require plan update
61
- In flexible mode: Allow with confirmation
62
- ```
63
-
64
- ### 4. Plan Update Operations
65
-
66
- [[LLM: Provide consistent way to update plan progress]]
67
-
68
- **Update Actions:**
69
-
70
- 1. **Mark Step Complete**:
71
- - Change `- [ ]` to `- [x]`
72
- - Add completion timestamp comment
73
- - Update any status metadata
74
-
75
- 2. **Add Deviation Note**:
76
- - Insert note explaining why sequence changed
77
- - Reference the deviation in plan
78
-
79
- 3. **Update Current Step Pointer**:
80
- - Add/move `<!-- current-step -->` marker
81
- - Update last-modified timestamp
82
-
83
- ### 5. Integration Instructions
84
-
85
- [[LLM: How agents and tasks should use this utility]]
86
-
87
- **For Agents (startup sequence)**:
88
-
89
- ```text
90
- 1. Check if plan exists using this utility
91
- 2. If exists:
92
- - Parse current status
93
- - Show user: "Active workflow plan detected. Current step: {X}"
94
- - Suggest: "Next recommended action: {next_step}"
95
- 3. Continue with normal startup
96
- ```
97
-
98
- **For Tasks (pre-execution)**:
99
-
100
- ```text
101
- 1. Check if plan exists
102
- 2. If exists:
103
- - Verify this task aligns with plan
104
- - If not aligned:
105
- - In strict mode: Show warning and stop
106
- - In flexible mode: Show warning and ask for confirmation
107
- 3. After task completion:
108
- - Update plan if task was a planned step
109
- - Add note if task was unplanned
110
- ```
111
-
112
- ### 6. Plan Status Report Format
113
-
114
- [[LLM: Standard format for showing plan status]]
115
-
116
- ```text
117
- 📋 Workflow Plan Status
118
- ━━━━━━━━━━━━━━━━━━━━
119
- Workflow: {workflow_name}
120
- Progress: {X}% complete ({completed}/{total} steps)
121
-
122
- ✅ Completed:
123
- - {completed_step_1}
124
- - {completed_step_2}
125
-
126
- 🔄 Current Step:
127
- - {current_step_description}
128
-
129
- 📌 Upcoming:
130
- - {next_step_1}
131
- - {next_step_2}
132
-
133
- ⚠️ Notes:
134
- - {any_deviations_or_notes}
135
- ```
136
-
137
- ### 7. Decision Point Handling
138
-
139
- [[LLM: Special handling for workflow decision points]]
140
-
141
- When encountering a decision point in the plan:
142
-
143
- 1. **Identify Decision Marker**: `<!-- decision: {decision_id} -->`
144
- 2. **Check Decision Status**: Made/Pending
145
- 3. **If Pending**:
146
- - Block progress until decision made
147
- - Show options to user
148
- - Record decision when made
149
- 4. **If Made**:
150
- - Verify current path aligns with decision
151
- - Warn if attempting alternate path
152
-
153
- ### 8. Plan Abandonment
154
-
155
- [[LLM: Graceful handling when user wants to stop following plan]]
156
-
157
- If user wants to abandon plan:
158
-
159
- 1. Confirm abandonment intent
160
- 2. Add abandonment note to plan
161
- 3. Mark plan as "Abandoned" in header
162
- 4. Stop plan checking for remainder of session
163
- 5. Suggest creating new plan if needed
164
-
165
- ## Usage Examples
166
-
167
- ### Example 1: Agent Startup Check
168
-
169
- ```text
170
- BMad Master starting...
171
-
172
- [Check for plan]
173
- Found active workflow plan: brownfield-fullstack
174
- Progress: 40% complete (4/10 steps)
175
- Current step: Create PRD (pm agent)
176
-
177
- Suggestion: Based on your plan, you should work with the PM agent next.
178
- Use *agent pm to switch, or *plan-status to see full progress.
179
- ```
180
-
181
- ### Example 2: Task Sequence Warning
182
-
183
- ```text
184
- User: *task create-next-story
185
-
186
- [Plan check triggered]
187
- ⚠️ SEQUENCE WARNING:
188
- Your workflow plan indicates the PRD hasn't been created yet.
189
- Creating stories before the PRD may lead to incomplete requirements.
190
-
191
- Would you like to:
192
- 1. Continue anyway (will note deviation in plan)
193
- 2. Switch to creating PRD first (*agent pm)
194
- 3. View plan status (*plan-status)
195
- ```
196
-
197
- ### Example 3: Automatic Plan Update
198
-
199
- ```text
200
- [After completing create-doc task for PRD]
201
-
202
- ✅ Plan Updated: Marked "Create PRD" as complete
203
- 📍 Next step: Create Architecture Document (architect agent)
204
- ```
205
-
206
- ## Implementation Notes
207
-
208
- - This utility should be lightweight and fast
209
- - Plan parsing should be resilient to format variations
210
- - Always preserve user agency - warnings not blocks (unless strict mode)
211
- - Plan updates should be atomic to prevent corruption
212
- - Consider plan versioning for rollback capability
213
-
214
- ## Error Handling
215
-
216
- - Missing plan: Return null, don't error
217
- - Malformed plan: Warn but continue, treat as no plan
218
- - Update failures: Log but don't block task completion
219
- - Parse errors: Fallback to basic text search