check alignment

This commit is contained in:
Brian Madison 2025-10-22 12:36:39 -05:00
parent c8776aa9ac
commit be5b06f55e
13 changed files with 1254 additions and 553 deletions

View File

@ -0,0 +1,328 @@
# BMAD Workflow Conditional Execution Antipattern Audit
**Date:** 2025-10-22
**Auditor:** Claude Code (BMad Builder Agent)
**Scope:** All markdown files under `src/`
---
## Executive Summary
**Critical Issue Identified:** Invalid self-closing `<check>` tag pattern found throughout BMAD workflow codebase.
**Impact:**
- **98 instances** across **14 workflow files**
- Affects core workflows, builder workflows, and method workflows
- Creates XML parsing ambiguity and unpredictable LLM behavior
- Violates BMAD workflow specification (workflow.xml)
**Severity:** CRITICAL - Invalid XML structure, ambiguous conditional scope
---
## The Antipattern
### Invalid Pattern (Self-Closing Check)
```xml
<!-- ❌ WRONG - Invalid XML structure -->
<check>If condition met:</check>
<action>Do something</action>
<action>Do something else</action>
```
**Problems:**
1. Check tag doesn't wrap anything (invalid XML)
2. Ambiguous scope - unclear which actions are conditional
3. Breaks formatters and parsers
4. Not part of BMAD workflow spec
5. Unpredictable LLM interpretation
### Correct Patterns
**Single conditional action:**
```xml
<!-- ✅ CORRECT - Inline conditional -->
<action if="condition met">Do something</action>
```
**Multiple conditional actions:**
```xml
<!-- ✅ CORRECT - Proper wrapper block -->
<check if="condition met">
<action>Do something</action>
<action>Do something else</action>
</check>
```
---
## Audit Results
### Total Count
- **Total Instances:** 98
- **Affected Files:** 14
- **Modules Affected:** 4 (BMB, BMM, CIS, Core)
### Breakdown by File
| File | Count | Priority |
| -------------------------------------------------------------------- | ----- | ----------- |
| `modules/bmb/workflows/edit-workflow/instructions.md` | 21 | 🔴 CRITICAL |
| `modules/bmm/workflows/4-implementation/dev-story/instructions.md` | 13 | 🔴 CRITICAL |
| `modules/bmb/workflows/convert-legacy/instructions.md` | 13 | 🔴 CRITICAL |
| `modules/bmb/workflows/create-module/instructions.md` | 12 | 🔴 CRITICAL |
| `modules/bmb/workflows/create-agent/instructions.md` | 11 | 🔴 CRITICAL |
| `core/workflows/party-mode/instructions.md` | 7 | 🟡 HIGH |
| `modules/bmm/workflows/4-implementation/correct-course/checklist.md` | 5 | 🟡 HIGH |
| `core/workflows/brainstorming/instructions.md` | 5 | 🟡 HIGH |
| `modules/cis/workflows/storytelling/instructions.md` | 3 | 🟢 MEDIUM |
| `modules/bmb/workflows/audit-workflow/instructions.md` | 3 | 🟢 MEDIUM |
| `modules/bmb/workflows/create-workflow/workflow-creation-guide.md` | 2 | 🟢 MEDIUM |
| `modules/bmm/workflows/1-analysis/product-brief/instructions.md` | 1 | 🟢 LOW |
| `modules/bmm/workflows/1-analysis/game-brief/instructions.md` | 1 | 🟢 LOW |
| `modules/bmb/workflows/redoc/instructions.md` | 1 | 🟢 LOW |
### Breakdown by Module
**BMB (Builder) Module: 63 instances (64%)**
- edit-workflow: 21
- convert-legacy: 13
- create-module: 12
- create-agent: 11
- audit-workflow: 3
- create-workflow: 2
- redoc: 1
**BMM (Method) Module: 20 instances (20%)**
- dev-story: 13
- correct-course: 5
- product-brief: 1
- game-brief: 1
**Core Workflows: 12 instances (12%)**
- party-mode: 7
- brainstorming: 5
**CIS (Creative) Module: 3 instances (3%)**
- storytelling: 3
---
## Example Instances
### Example 1: create-agent/instructions.md (Line 13-20)
**BEFORE (Invalid):**
```xml
<check>If yes:</check>
<action>Invoke brainstorming workflow: {project-root}/bmad/core/workflows/brainstorming/workflow.yaml</action>
<action>Pass context data: {installed_path}/brainstorm-context.md</action>
<action>Wait for brainstorming session completion</action>
<check>If no:</check>
<action>Proceed directly to Step 0</action>
```
**AFTER (Correct):**
```xml
<check if="user answered yes">
<action>Invoke brainstorming workflow: {project-root}/bmad/core/workflows/brainstorming/workflow.yaml</action>
<action>Pass context data: {installed_path}/brainstorm-context.md</action>
<action>Wait for brainstorming session completion</action>
</check>
<check if="user answered no">
<action>Proceed directly to Step 0</action>
</check>
```
### Example 2: dev-story/instructions.md (Line 54-55)
**BEFORE (Invalid):**
```xml
<check>If story file inaccessible → HALT: "Cannot develop story without access to story file"</check>
<check>If task requirements ambiguous → ASK user to clarify or HALT</check>
```
**AFTER (Correct):**
```xml
<action if="story file inaccessible">HALT: "Cannot develop story without access to story file"</action>
<action if="task requirements ambiguous">ASK user to clarify or HALT</action>
```
---
## Impact Assessment
### Technical Impact
1. **XML Validity:** Invalid structure violates XML parsing rules
2. **Formatter Confusion:** Custom formatters incorrectly indent following content
3. **Scope Ambiguity:** Unclear which actions are inside vs outside conditional
4. **Maintainability:** Future developers confused by ambiguous structure
### LLM Adherence Impact
**Potential Issues:**
- LLM may interpret check as unconditional statement
- Actions may execute when they shouldn't (or vice versa)
- Inconsistent behavior across different LLMs
- Unpredictable results in complex nested conditionals
**Observed Behavior:**
- LLMs often "figure it out" through context and proximity
- Colon (`:`) pattern signals "here's what to do"
- Works in simple cases but risky in complex logic
**Risk Level:** MEDIUM-HIGH
- May work "most of the time" but unreliable
- Fails in edge cases and complex nested logic
- Future LLMs may interpret differently
---
## Root Cause Analysis
### Why This Happened
1. **Implicit convention evolved** - Self-closing check pattern emerged organically
2. **No enforcement** - No linter or validator caught the pattern
3. **Copy-paste propagation** - Pattern copied across workflows
4. **Formatting hid the issue** - Manual indentation made it "look right"
5. **LLM tolerance** - Current LLMs often figured it out despite ambiguity
### Meta-Problem
**The workflows that CREATE workflows have the antipattern:**
- create-workflow: 2 instances
- create-agent: 11 instances
- create-module: 12 instances
- edit-workflow: 21 instances
- convert-legacy: 13 instances
This means NEW workflows were being created WITH the antipattern built-in!
---
## Remediation Plan
### Phase 1: Immediate (High Priority Files)
Fix top 5 offenders (63% of problem):
1. edit-workflow (21 instances)
2. dev-story (13 instances)
3. convert-legacy (13 instances)
4. create-module (12 instances)
5. create-agent (11 instances)
**Total:** 70 instances (71% of problem)
### Phase 2: Core Workflows
Fix core workflows (critical for all modules):
1. party-mode (7 instances)
2. brainstorming (5 instances)
**Total:** 12 instances
### Phase 3: Remaining
Fix remaining 16 instances across 7 files
### Phase 4: Prevention
1. **Update audit-workflow** ✅ DONE
- Added antipattern detection to Step 4
- Flags with CRITICAL severity
- Suggests correct patterns
2. **Update creation guide** ✅ DONE
- Documented antipattern in workflow-creation-guide.md
- Clear examples of correct vs incorrect patterns
- Added to best practices
3. **Update checklist** ✅ DONE
- Added validation criteria to checklist.md
- 3 new checks for conditional execution patterns
4. **Create automated fixer** (TODO)
- Bulk conversion script for remaining instances
- Pattern matching and replacement logic
---
## Specification Reference
From `bmad/core/tasks/workflow.xml`:
```xml
<tag>action if="condition" - Single conditional action (inline, no closing tag needed)</tag>
<tag>check if="condition">...</check> - Conditional block wrapping multiple items (closing tag required)</tag>
```
**Key Point:** Check tags MUST have `if=""` attribute and MUST wrap content with closing tag.
The self-closing pattern `<check>text</check>` is **NOT in the spec** and is **invalid**.
---
## Detection Command
To find all instances:
```bash
grep -r "<check>[^<]*</check>" src --include="*.md" -n
```
To count by file:
```bash
grep -r "<check>[^<]*</check>" src --include="*.md" -c | grep -v ":0$"
```
---
## Next Actions
- [ ] Create bulk-fix script for automated conversion
- [ ] Fix Phase 1 files (70 instances)
- [ ] Fix Phase 2 files (12 instances)
- [ ] Fix Phase 3 files (16 instances)
- [ ] Run audit-workflow on all fixed files to verify
- [ ] Update formatter to detect and warn on antipattern
- [ ] Add pre-commit hook to prevent future instances
---
## References
- **Workflow Spec:** `bmad/core/tasks/workflow.xml`
- **Creation Guide:** `src/modules/bmb/workflows/create-workflow/workflow-creation-guide.md`
- **Audit Workflow:** `src/modules/bmb/workflows/audit-workflow/`
- **This Report:** `docs/antipattern-audit-2025-10-22.md`
---
**Report Status:** Complete
**Action Required:** Yes - 98 instances need remediation
**Priority:** CRITICAL - Affects core functionality and workflow creation

View File

@ -78,6 +78,9 @@
- [ ] XML tags used correctly (<action>, <ask>, <check>, <goto>, <invoke-workflow>, <template-output>) - [ ] XML tags used correctly (<action>, <ask>, <check>, <goto>, <invoke-workflow>, <template-output>)
- [ ] No nested tag references in content (use "action tags" not "<action> tags") - [ ] No nested tag references in content (use "action tags" not "<action> tags")
- [ ] Tag references use descriptive text without angle brackets for clarity - [ ] Tag references use descriptive text without angle brackets for clarity
- [ ] No conditional execution antipattern (no self-closing <check> tags)
- [ ] Single conditionals use <action if="condition"> (inline)
- [ ] Multiple conditionals use <check if="condition">...</check> (wrapper block with closing tag)
- [ ] Steps are focused (single goal per step) - [ ] Steps are focused (single goal per step)
- [ ] Instructions are specific with limits ("Write 1-2 paragraphs" not "Write about") - [ ] Instructions are specific with limits ("Write 1-2 paragraphs" not "Write about")
- [ ] Examples provided where helpful - [ ] Examples provided where helpful

View File

@ -25,6 +25,7 @@ Display summary:
- Type of workflow - Type of workflow
- Files present - Files present
- Module assignment - Module assignment
</step> </step>
<step n="2" goal="Validate standard config block"> <step n="2" goal="Validate standard config block">
@ -56,8 +57,8 @@ Display summary:
<action>Record any missing or incorrect config variables</action> <action>Record any missing or incorrect config variables</action>
<template-output>config_issues</template-output> <template-output>config_issues</template-output>
<check>If config issues found:</check> <action if="config issues found">Add to issues list with severity: CRITICAL</action>
<action>Add to issues list with severity: CRITICAL</action>
</step> </step>
<step n="3" goal="Analyze YAML/Instruction/Template alignment"> <step n="3" goal="Analyze YAML/Instruction/Template alignment">
@ -84,8 +85,8 @@ Display summary:
<action>Identify hardcoded values in instructions that should be variables</action> <action>Identify hardcoded values in instructions that should be variables</action>
<template-output>alignment_issues</template-output> <template-output>alignment_issues</template-output>
<check>If unused variables found:</check> <action if="unused variables found">Add to issues list with severity: BLOAT</action>
<action>Add to issues list with severity: BLOAT</action>
</step> </step>
<step n="4" goal="Config variable usage audit"> <step n="4" goal="Config variable usage audit">
@ -130,19 +131,52 @@ Display summary:
- Improves readability for humans and LLMs - Improves readability for humans and LLMs
- LLMs understand "action tags" = `<action>` tags from context - LLMs understand "action tags" = `<action>` tags from context
**Conditional Execution Antipattern Check:**
- Scan for self-closing check tags: `<check>condition text</check>` (invalid antipattern)
- Detect pattern: check tag on one line, followed by action/ask/goto tags (indicates incorrect nesting)
- Flag sequences like: `<check>If X:</check>` followed by `<action>do Y</action>`
**Correct Patterns:**
- Single conditional: `<action if="condition">Do something</action>`
- Multiple actions: `<check if="condition">` followed by nested actions with closing `</check>` tag
**Antipattern Example (WRONG):**
```xml
<check>If condition met:</check>
<action>Do something</action>
```
**Correct Example:**
```xml
<check if="condition met">
<action>Do something</action>
<action>Do something else</action>
</check>
```
**Or for single action:**
```xml
<action if="condition met">Do something</action>
```
<action>Scan instructions.md for nested tag references using pattern: &lt;(action|ask|check|template-output|invoke-workflow|goto|step|elicit-required)&gt; within text content</action> <action>Scan instructions.md for nested tag references using pattern: &lt;(action|ask|check|template-output|invoke-workflow|goto|step|elicit-required)&gt; within text content</action>
<action>Record any instances of nested tag references with line numbers</action> <action>Record any instances of nested tag references with line numbers</action>
<action>Scan instructions.md for conditional execution antipattern: self-closing check tags</action>
<action>Detect pattern: `&lt;check&gt;.*&lt;/check&gt;` on single line (self-closing check)</action>
<action>Record any antipattern instances with line numbers and suggest corrections</action>
<action>Record any improper config variable usage</action> <action>Record any improper config variable usage</action>
<template-output>config_usage_issues</template-output> <template-output>config_usage_issues</template-output>
<check>If config usage issues found:</check> <action if="config usage issues found">Add to issues list with severity: IMPORTANT</action>
<action>Add to issues list with severity: IMPORTANT</action> <action if="nested tag references found">Add to issues list with severity: CLARITY (recommend using descriptive text without angle brackets)</action>
<check>If nested tag references found:</check> <action if="conditional antipattern found">Add to issues list with severity: CRITICAL (invalid XML structure - must use action if="" or proper check wrapper)</action>
<action>Add to issues list with severity: CLARITY (recommend using descriptive text without angle brackets)</action>
</step> </step>
<step n="5" goal="Web bundle validation" optional="true"> <step n="5" goal="Web bundle validation" optional="true">
<check>If workflow.yaml contains web_bundle section:</check> <check if="workflow.yaml contains web_bundle section">
<action>Validate web_bundle structure:</action> <action>Validate web_bundle structure:</action>
@ -166,9 +200,7 @@ Display summary:
<action>Verify each called workflow.yaml is in web_bundle_files</action> <action>Verify each called workflow.yaml is in web_bundle_files</action>
<action>**CRITICAL**: Check if existing_workflows field is present when workflows are invoked</action> <action>**CRITICAL**: Check if existing_workflows field is present when workflows are invoked</action>
<action>If invoke-workflow calls exist, existing_workflows MUST map workflow variables to paths</action> <action>If invoke-workflow calls exist, existing_workflows MUST map workflow variables to paths</action>
<action>Example: If instructions use {core_brainstorming}, web_bundle needs: <action>Example: If instructions use {core_brainstorming}, web_bundle needs: existing_workflows: - core_brainstorming: "bmad/core/workflows/brainstorming/workflow.yaml"</action>
existing_workflows: - core_brainstorming: "bmad/core/workflows/brainstorming/workflow.yaml"
</action>
**File Reference Scan:** **File Reference Scan:**
<action>Scan instructions.md for file references in action tags</action> <action>Scan instructions.md for file references in action tags</action>
@ -178,11 +210,11 @@ existing_workflows: - core_brainstorming: "bmad/core/workflows/brainstorming/wor
<action>Record any missing files or incorrect paths</action> <action>Record any missing files or incorrect paths</action>
<template-output>web_bundle_issues</template-output> <template-output>web_bundle_issues</template-output>
<check>If web_bundle issues found:</check> <action if="web_bundle issues found">Add to issues list with severity: CRITICAL</action>
<action>Add to issues list with severity: CRITICAL</action>
<action if="no web_bundle section exists">Note: "No web_bundle configured (may be intentional for local-only workflows)"</action>
</check>
<check>If no web_bundle section exists:</check>
<action>Note: "No web_bundle configured (may be intentional for local-only workflows)"</action>
</step> </step>
<step n="6" goal="Bloat detection"> <step n="6" goal="Bloat detection">
@ -216,8 +248,8 @@ existing_workflows: - core_brainstorming: "bmad/core/workflows/brainstorming/wor
<action>Record all bloat items with recommendations</action> <action>Record all bloat items with recommendations</action>
<template-output>bloat_items</template-output> <template-output>bloat_items</template-output>
<check>If bloat detected:</check> <action if="bloat detected">Add to issues list with severity: CLEANUP</action>
<action>Add to issues list with severity: CLEANUP</action>
</step> </step>
<step n="7" goal="Template variable mapping" if="workflow_type == 'document'"> <step n="7" goal="Template variable mapping" if="workflow_type == 'document'">
@ -246,140 +278,55 @@ existing_workflows: - core_brainstorming: "bmad/core/workflows/brainstorming/wor
<action>Record any mapping issues</action> <action>Record any mapping issues</action>
<template-output>template_issues</template-output> <template-output>template_issues</template-output>
<check>If template issues found:</check> <action if="template issues found">Add to issues list with severity: IMPORTANT</action>
<action>Add to issues list with severity: IMPORTANT</action>
</step> </step>
<step n="8" goal="Generate comprehensive audit report"> <step n="8" goal="Generate comprehensive audit report">
<action>Compile all findings into a structured report</action> <action>Compile all findings and calculate summary metrics</action>
<action>Write audit report to {output_folder}/audit-report-{{workflow_name}}-{{date}}.md</action> <action>Generate executive summary based on issue counts and severity levels</action>
<template-output>workflow_type</template-output>
<template-output>overall_status</template-output>
<template-output>critical_count</template-output>
<template-output>important_count</template-output>
<template-output>cleanup_count</template-output>
**Report Structure:** <action>Generate status summaries for each audit section</action>
<template-output>config_status</template-output>
<template-output>total_variables</template-output>
<template-output>instruction_usage_count</template-output>
<template-output>template_usage_count</template-output>
<template-output>bloat_count</template-output>
```markdown <action>Generate config variable usage status indicators</action>
# Workflow Audit Report <template-output>comm_lang_status</template-output>
<template-output>user_name_status</template-output>
<template-output>output_folder_status</template-output>
<template-output>date_status</template-output>
<template-output>nested_tag_count</template-output>
**Workflow:** {{workflow_name}} <action>Generate web bundle metrics</action>
**Audit Date:** {{date}} <template-output>web_bundle_exists</template-output>
**Auditor:** Audit Workflow (BMAD v6) <template-output>web_bundle_file_count</template-output>
**Workflow Type:** {{workflow_type}} <template-output>missing_files_count</template-output>
--- <action>Generate bloat metrics</action>
<template-output>bloat_percentage</template-output>
<template-output>cleanup_potential</template-output>
## Executive Summary <action>Generate template mapping metrics</action>
<template-output>template_var_count</template-output>
<template-output>mapped_count</template-output>
<template-output>missing_mapping_count</template-output>
**Overall Status:** {{overall_status}} <action>Compile prioritized recommendations by severity</action>
<template-output>critical_recommendations</template-output>
- Critical Issues: {{critical_count}} <template-output>important_recommendations</template-output>
- Important Issues: {{important_count}} <template-output>cleanup_recommendations</template-output>
- Cleanup Recommendations: {{cleanup_count}}
---
## 1. Standard Config Block Validation
{{config_issues}}
**Status:** {{config_status}}
---
## 2. YAML/Instruction/Template Alignment
{{alignment_issues}}
**Variables Analyzed:** {{total_variables}}
**Used in Instructions:** {{instruction_usage_count}}
**Used in Template:** {{template_usage_count}}
**Unused (Bloat):** {{bloat_count}}
---
## 3. Config Variable Usage & Instruction Quality
{{config_usage_issues}}
**Communication Language:** {{comm_lang_status}}
**User Name:** {{user_name_status}}
**Output Folder:** {{output_folder_status}}
**Date:** {{date_status}}
**Nested Tag References:** {{nested_tag_count}} instances found
---
## 4. Web Bundle Validation
{{web_bundle_issues}}
**Web Bundle Present:** {{web_bundle_exists}}
**Files Listed:** {{web_bundle_file_count}}
**Missing Files:** {{missing_files_count}}
---
## 5. Bloat Detection
{{bloat_items}}
**Bloat Percentage:** {{bloat_percentage}}%
**Cleanup Potential:** {{cleanup_potential}}
---
## 6. Template Variable Mapping
{{template_issues}}
**Template Variables:** {{template_var_count}}
**Mapped Correctly:** {{mapped_count}}
**Missing Mappings:** {{missing_mapping_count}}
---
## Recommendations
### Critical (Fix Immediately)
{{critical_recommendations}}
### Important (Address Soon)
{{important_recommendations}}
### Cleanup (Nice to Have)
{{cleanup_recommendations}}
---
## Validation Checklist
Use this checklist to verify fixes:
- [ ] All standard config variables present and correct
- [ ] No unused yaml fields (bloat removed)
- [ ] Config variables used appropriately in instructions
- [ ] Web bundle includes all dependencies
- [ ] Template variables properly mapped
- [ ] File structure follows v6 conventions
---
## Next Steps
1. Review critical issues and fix immediately
2. Address important issues in next iteration
3. Consider cleanup recommendations for optimization
4. Re-run audit after fixes to verify improvements
---
**Audit Complete** - Generated by audit-workflow v1.0
```
<action>Display summary to {user_name} in {communication_language}</action> <action>Display summary to {user_name} in {communication_language}</action>
<action>Provide path to full audit report</action> <action>Provide path to full audit report: {output_folder}/audit-report-{{workflow_name}}-{{date}}.md</action>
<ask>Would you like to: <ask>Would you like to:
@ -389,7 +336,6 @@ Use this checklist to verify fixes:
- Exit - Exit
</ask> </ask>
<template-output>audit_report_path</template-output>
</step> </step>
</workflow> </workflow>

View File

@ -0,0 +1,118 @@
# Workflow Audit Report
**Workflow:** {{workflow_name}}
**Audit Date:** {{date}}
**Auditor:** Audit Workflow (BMAD v6)
**Workflow Type:** {{workflow_type}}
---
## Executive Summary
**Overall Status:** {{overall_status}}
- Critical Issues: {{critical_count}}
- Important Issues: {{important_count}}
- Cleanup Recommendations: {{cleanup_count}}
---
## 1. Standard Config Block Validation
{{config_issues}}
**Status:** {{config_status}}
---
## 2. YAML/Instruction/Template Alignment
{{alignment_issues}}
**Variables Analyzed:** {{total_variables}}
**Used in Instructions:** {{instruction_usage_count}}
**Used in Template:** {{template_usage_count}}
**Unused (Bloat):** {{bloat_count}}
---
## 3. Config Variable Usage & Instruction Quality
{{config_usage_issues}}
**Communication Language:** {{comm_lang_status}}
**User Name:** {{user_name_status}}
**Output Folder:** {{output_folder_status}}
**Date:** {{date_status}}
**Nested Tag References:** {{nested_tag_count}} instances found
---
## 4. Web Bundle Validation
{{web_bundle_issues}}
**Web Bundle Present:** {{web_bundle_exists}}
**Files Listed:** {{web_bundle_file_count}}
**Missing Files:** {{missing_files_count}}
---
## 5. Bloat Detection
{{bloat_items}}
**Bloat Percentage:** {{bloat_percentage}}%
**Cleanup Potential:** {{cleanup_potential}}
---
## 6. Template Variable Mapping
{{template_issues}}
**Template Variables:** {{template_var_count}}
**Mapped Correctly:** {{mapped_count}}
**Missing Mappings:** {{missing_mapping_count}}
---
## Recommendations
### Critical (Fix Immediately)
{{critical_recommendations}}
### Important (Address Soon)
{{important_recommendations}}
### Cleanup (Nice to Have)
{{cleanup_recommendations}}
---
## Validation Checklist
Use this checklist to verify fixes:
- [ ] All standard config variables present and correct
- [ ] No unused yaml fields (bloat removed)
- [ ] Config variables used appropriately in instructions
- [ ] Web bundle includes all dependencies
- [ ] Template variables properly mapped
- [ ] File structure follows v6 conventions
---
## Next Steps
1. Review critical issues and fix immediately
2. Address important issues in next iteration
3. Consider cleanup recommendations for optimization
4. Re-run audit after fixes to verify improvements
---
**Audit Complete** - Generated by audit-workflow v1.0

View File

@ -12,7 +12,7 @@ date: system-generated
# Module path and component files # Module path and component files
installed_path: "{project-root}/bmad/bmb/workflows/audit-workflow" installed_path: "{project-root}/bmad/bmb/workflows/audit-workflow"
template: false template: "{installed_path}/template.md"
instructions: "{installed_path}/instructions.md" instructions: "{installed_path}/instructions.md"
validation: "{installed_path}/checklist.md" validation: "{installed_path}/checklist.md"

View File

@ -67,8 +67,7 @@ For Modules:
<step n="3" goal="Determine Target Module and Location"> <step n="3" goal="Determine Target Module and Location">
<ask>Which module should this belong to? (eg. bmm, bmb, cis, bmm-legacy, or custom)</ask> <ask>Which module should this belong to? (eg. bmm, bmb, cis, bmm-legacy, or custom)</ask>
<check>If custom module:</check> <action if="custom module"><ask>Enter custom module code (kebab-case):</ask></action>
<ask>Enter custom module code (kebab-case):</ask>
<action>Determine installation path based on type and module</action> <action>Determine installation path based on type and module</action>
<critical>IMPORTANT: All paths must use final BMAD installation locations, not src paths!</critical> <critical>IMPORTANT: All paths must use final BMAD installation locations, not src paths!</critical>
<action>Show user the target location: {project-root}/bmad/{{target_module}}/{{item_type}}/{{item_name}}</action> <action>Show user the target location: {project-root}/bmad/{{target_module}}/{{item_type}}/{{item_name}}</action>
@ -79,15 +78,18 @@ For Modules:
<step n="4" goal="Choose Conversion Strategy"> <step n="4" goal="Choose Conversion Strategy">
<action>Based on item type and complexity, choose approach:</action> <action>Based on item type and complexity, choose approach:</action>
<check>If agent conversion:</check> <check if="agent conversion">
<check>If simple agent (basic persona + commands):</check> <check if="simple agent (basic persona + commands)">
<action>Use direct conversion to v5 agent YAML format</action> <action>Use direct conversion to v5 agent YAML format</action>
<goto step="5a">Direct Agent Conversion</goto> <goto step="5a">Direct Agent Conversion</goto>
<check>If complex agent with embedded workflows:</check> </check>
<check if="complex agent with embedded workflows">
<action>Plan to invoke create-agent workflow</action> <action>Plan to invoke create-agent workflow</action>
<goto step="5b">Workflow-Assisted Agent Creation</goto> <goto step="5b">Workflow-Assisted Agent Creation</goto>
</check>
</check>
<check>If template or task conversion to workflow:</check> <check if="template or task conversion to workflow">
<action>Analyze the v4 item to determine workflow type:</action> <action>Analyze the v4 item to determine workflow type:</action>
- Does it generate a specific document type? → Document workflow - Does it generate a specific document type? → Document workflow
@ -104,14 +106,14 @@ For Modules:
4. Meta-workflow (coordinates other workflows) 4. Meta-workflow (coordinates other workflows)
Select 1-4:</ask> Select 1-4:</ask>
<check>If template conversion:</check> <action if="template conversion"><goto step="5c">Template-to-Workflow Conversion</goto></action>
<goto step="5c">Template-to-Workflow Conversion</goto> <action if="task conversion"><goto step="5e">Task-to-Workflow Conversion</goto></action>
<check>If task conversion:</check> </check>
<goto step="5e">Task-to-Workflow Conversion</goto>
<check>If full module conversion:</check> <check if="full module conversion">
<action>Plan to invoke create-module workflow</action> <action>Plan to invoke create-module workflow</action>
<goto step="5d">Module Creation</goto> <goto step="5d">Module Creation</goto>
</check>
</step> </step>
<step n="5a" goal="Direct Agent Conversion" optional="true"> <step n="5a" goal="Direct Agent Conversion" optional="true">
@ -262,15 +264,17 @@ date: system-generated
- User interaction patterns → appropriate v5 tags - User interaction patterns → appropriate v5 tags
3. Based on confirmed workflow type: 3. Based on confirmed workflow type:
<check>If Document workflow:</check> <check if="Document workflow">
- Create template.md from output patterns - Create template.md from output patterns
- Map generation steps to instructions - Map generation steps to instructions
- Add <template-output> tags for sections - Add template-output tags for sections
</check>
<check>If Action workflow:</check> <check if="Action workflow">
- Set template: false in workflow.yaml - Set template: false in workflow.yaml
- Focus on action sequences in instructions - Focus on action sequences in instructions
- Preserve execution logic - Preserve execution logic
</check>
4. Handle special v4 patterns: 4. Handle special v4 patterns:
- 1-9 elicitation menus → v5 <invoke-task halt="true">{project-root}/bmad/core/tasks/adv-elicit.xml</invoke-task> - 1-9 elicitation menus → v5 <invoke-task halt="true">{project-root}/bmad/core/tasks/adv-elicit.xml</invoke-task>
@ -341,9 +345,10 @@ For Modules:
<action>Show validation results to user</action> <action>Show validation results to user</action>
<ask>Any issues to fix before finalizing? (y/n)</ask> <ask>Any issues to fix before finalizing? (y/n)</ask>
<check>If yes:</check> <check if="yes">
<action>Address specific issues</action> <action>Address specific issues</action>
<goto step="6">Re-validate</goto> <goto step="6">Re-validate</goto>
</check>
</step> </step>
<step n="7" goal="Migration Report"> <step n="7" goal="Migration Report">
@ -360,15 +365,13 @@ For Modules:
<step n="8" goal="Cleanup and Finalize"> <step n="8" goal="Cleanup and Finalize">
<ask>Archive original v4 files? (y/n)</ask> <ask>Archive original v4 files? (y/n)</ask>
<check>If yes:</check> <action if="yes">Move v4 files to: {project-root}/archive/v4-legacy/{{date}}/</action>
<action>Move v4 files to: {project-root}/archive/v4-legacy/{{date}}/</action>
<action>Show user the final converted items and their locations</action> <action>Show user the final converted items and their locations</action>
<action>Provide any post-conversion instructions or recommendations</action> <action>Provide any post-conversion instructions or recommendations</action>
<ask>Would you like to convert another legacy item? (y/n)</ask> <ask>Would you like to convert another legacy item? (y/n)</ask>
<check>If yes:</check> <action if="yes"><goto step="1">Start new conversion</goto></action>
<goto step="1">Start new conversion</goto>
</step> </step>
</workflow> </workflow>

View File

@ -10,165 +10,131 @@ Agents with distinct communication styles are more memorable, engaging, and fun
**Film Noir Detective** **Film Noir Detective**
```
The terminal glowed like a neon sign in a rain-soaked alley. I had three suspects: The terminal glowed like a neon sign in a rain-soaked alley. I had three suspects:
bad input validation, a race condition, and that sketchy third-party library. bad input validation, a race condition, and that sketchy third-party library.
My gut told me to follow the stack trace. In this business, the stack trace never lies. My gut told me to follow the stack trace. In this business, the stack trace never lies.
```
**80s Action Movie** **80s Action Movie**
``` _cracks knuckles_ Listen up, code! You've been running wild for too long!
*cracks knuckles* Listen up, code! You've been running wild for too long! Time to bring some LAW and ORDER to this codebase! _explosion sound effect_
Time to bring some LAW and ORDER to this codebase! *explosion sound effect*
No bug is getting past me! I eat null pointers for BREAKFAST! No bug is getting past me! I eat null pointers for BREAKFAST!
```
**Shakespearean Drama** **Shakespearean Drama**
```
To debug, or not to debug - that is the question! To debug, or not to debug - that is the question!
Whether 'tis nobler in the mind to suffer the slings and arrows of outrageous errors, Whether 'tis nobler in the mind to suffer the slings and arrows of outrageous errors,
Or to take arms against a sea of bugs, and by opposing, end them? Or to take arms against a sea of bugs, and by opposing, end them?
```
### 🎮 Gaming and Pop Culture ### 🎮 Gaming and Pop Culture
**Dungeon Master** **Dungeon Master**
``` _rolls dice_ You encounter a wild NullPointerException! It has 15 HP and an armor class of 12.
*rolls dice* You encounter a wild NullPointerException! It has 15 HP and an armor class of 12. What do you do? You can: 1 Try-catch block (defensive spell), 2 Debug (investigation check),
What do you do? You can: 1) Try-catch block (defensive spell), 2) Debug (investigation check), 3 Console.log everything (barbarian rage). Choose wisely, adventurer!
3) Console.log everything (barbarian rage). Choose wisely, adventurer!
```
**Speedrunner** **Speedrunner**
```
Alright chat, we're going for the any% world record refactor! Alright chat, we're going for the any% world record refactor!
Frame-perfect optimization incoming! If we clip through this abstraction layer Frame-perfect optimization incoming! If we clip through this abstraction layer
we can save 3ms on every API call. LET'S GOOOO! we can save 3ms on every API call. LET'S GOOOO!
```
### 🌍 Cultural Archetypes ### 🌍 Cultural Archetypes
**British Butler** **British Butler**
```
I've taken the liberty of organizing your imports alphabetically, sir/madam. I've taken the liberty of organizing your imports alphabetically, sir/madam.
Might I suggest a spot of refactoring with your afternoon tea? Might I suggest a spot of refactoring with your afternoon tea?
The code coverage report is ready for your perusal at your convenience. The code coverage report is ready for your perusal at your convenience.
Very good, sir/madam. Very good, sir/madam.
```
**Zen Master** **Zen Master**
```
The bug you seek is not in the code, but in the assumption. The bug you seek is not in the code, but in the assumption.
Empty your cache, as you would empty your mind. Empty your cache, as you would empty your mind.
When the test passes, it makes no sound. When the test passes, it makes no sound.
Be like water - async and flowing. Be like water - async and flowing.
```
**Southern Hospitality** **Southern Hospitality**
```
Well bless your heart, looks like you've got yourself a little bug there! Well bless your heart, looks like you've got yourself a little bug there!
Don't you worry none, we'll fix it up real nice. Don't you worry none, we'll fix it up real nice.
Can I get you some sweet tea while we debug? Can I get you some sweet tea while we debug?
Y'all come back now if you need more help! Y'all come back now if you need more help!
```
### 🔬 Professional Personas ### 🔬 Professional Personas
**McKinsey Consultant** **McKinsey Consultant**
```
Let me break this down into three key buckets. Let me break this down into three key buckets.
First, we need to align on the strategic imperatives. First, we need to align on the strategic imperatives.
Second, we'll leverage best practices to drive synergies. Second, we'll leverage best practices to drive synergies.
Third, we'll action items to move the needle. Net-net: significant value-add. Third, we'll action items to move the needle. Net-net: significant value-add.
```
**Startup Founder** **Startup Founder**
```
Okay so basically we're going to disrupt the entire way you write code! Okay so basically we're going to disrupt the entire way you write code!
This is going to be HUGE! We're talking 10x productivity gains! This is going to be HUGE! We're talking 10x productivity gains!
Let's move fast and break things! Well... let's move fast and fix things! Let's move fast and break things! Well... let's move fast and fix things!
We're not just writing code, we're changing the world! We're not just writing code, we're changing the world!
```
### 🎭 Character Quirks ### 🎭 Character Quirks
**Overcaffeinated Developer** **Overcaffeinated Developer**
``` OH WOW OKAY SO - _sips coffee_ - WE HAVE A BUG BUT ITS FINE ITS TOTALLY FINE
OH WOW OKAY SO - *sips coffee* - WE HAVE A BUG BUT ITS FINE ITS TOTALLY FINE I KNOW EXACTLY WHAT TO DO _types at 200wpm_ JUST NEED TO REFACTOR EVERYTHING
I KNOW EXACTLY WHAT TO DO *types at 200wpm* JUST NEED TO REFACTOR EVERYTHING WAIT NO ACTUALLY _more coffee_ I HAVE A BETTER IDEA! Have you tried... TYPESCRIPT?!
WAIT NO ACTUALLY *more coffee* I HAVE A BETTER IDEA! Have you tried... TYPESCRIPT?!
```
**Dad Joke Enthusiast** **Dad Joke Enthusiast**
```
Why did the developer go broke? Because he used up all his cache! Why did the developer go broke? Because he used up all his cache!
*chuckles at own joke* _chuckles at own joke_
Speaking of cache, let's clear yours and see if that fixes the issue. Speaking of cache, let's clear yours and see if that fixes the issue.
I promise my debugging skills are better than my jokes! ...I hope! I promise my debugging skills are better than my jokes! ...I hope!
```
### 🚀 Sci-Fi and Space ### 🚀 Sci-Fi and Space
**Star Trek Officer** **Star Trek Officer**
```
Captain's Log, Supplemental: The anomaly in the codebase appears to be a temporal loop Captain's Log, Supplemental: The anomaly in the codebase appears to be a temporal loop
in the async function. Mr. Data suggests we reverse the polarity of the promise chain. in the async function. Mr. Data suggests we reverse the polarity of the promise chain.
Number One, make it so. Engage debugging protocols on my mark. Number One, make it so. Engage debugging protocols on my mark.
*taps combadge* Engineering, we need more processing power! _taps combadge_ Engineering, we need more processing power!
Red Alert! All hands to debugging stations! Red Alert! All hands to debugging stations!
```
**Star Trek Engineer** **Star Trek Engineer**
```
Captain, I'm givin' her all she's got! The CPU cannae take much more! Captain, I'm givin' her all she's got! The CPU cannae take much more!
If we push this algorithm any harder, the whole system's gonna blow! If we push this algorithm any harder, the whole system's gonna blow!
*frantically typing* I can maybe squeeze 10% more performance if we _frantically typing_ I can maybe squeeze 10% more performance if we
reroute power from the console.logs to the main execution thread! reroute power from the console.logs to the main execution thread!
```
### 📺 TV Drama ### 📺 TV Drama
**Soap Opera Dramatic** **Soap Opera Dramatic**
``` _turns dramatically to camera_
*turns dramatically to camera*
This function... I TRUSTED it! We had HISTORY together - three commits worth! This function... I TRUSTED it! We had HISTORY together - three commits worth!
But now? *single tear* It's throwing exceptions behind my back! But now? _single tear_ It's throwing exceptions behind my back!
*grabs another function* YOU KNEW ABOUT THIS BUG ALL ALONG, DIDN'T YOU?! _grabs another function_ YOU KNEW ABOUT THIS BUG ALL ALONG, DIDN'T YOU?!
*dramatic music swells* I'LL NEVER IMPORT YOU AGAIN! _dramatic music swells_ I'LL NEVER IMPORT YOU AGAIN!
```
**Reality TV Confessional** **Reality TV Confessional**
``` _whispering to camera in confessional booth_
*whispering to camera in confessional booth*
Okay so like, that Array.sort() function? It's literally SO toxic. Okay so like, that Array.sort() function? It's literally SO toxic.
It mutates IN PLACE. Who does that?! I didn't come here to deal with side effects! It mutates IN PLACE. Who does that?! I didn't come here to deal with side effects!
*applies lip gloss* I'm forming an alliance with map() and filter(). _applies lip gloss_ I'm forming an alliance with map() and filter().
We're voting sort() off the codebase at tonight's pull request ceremony. We're voting sort() off the codebase at tonight's pull request ceremony.
```
**Reality Competition** **Reality Competition**
```
Listen up, coders! For today's challenge, you need to refactor this legacy code Listen up, coders! For today's challenge, you need to refactor this legacy code
in under 30 minutes! The winner gets immunity from the next code review! in under 30 minutes! The winner gets immunity from the next code review!
*dramatic pause* BUT WAIT - there's a TWIST! You can only use VANILLA JAVASCRIPT! _dramatic pause_ BUT WAIT - there's a TWIST! You can only use VANILLA JAVASCRIPT!
*contestants gasp* The clock starts... NOW! GO GO GO! _contestants gasp_ The clock starts... NOW! GO GO GO!
```
## Creating Custom Styles ## Creating Custom Styles
@ -183,21 +149,17 @@ in under 30 minutes! The winner gets immunity from the next code review!
**Cooking Show + Military** **Cooking Show + Military**
```
ALRIGHT RECRUITS! Today we're preparing a beautiful Redux reducer! ALRIGHT RECRUITS! Today we're preparing a beautiful Redux reducer!
First, we MISE EN PLACE our action types - that's French for GET YOUR CODE TOGETHER! First, we MISE EN PLACE our action types - that's French for GET YOUR CODE TOGETHER!
We're going to sauté these event handlers until they're GOLDEN BROWN! We're going to sauté these event handlers until they're GOLDEN BROWN!
MOVE WITH PURPOSE! SEASON WITH SEMICOLONS! MOVE WITH PURPOSE! SEASON WITH SEMICOLONS!
```
**Nature Documentary + Conspiracy Theorist** **Nature Documentary + Conspiracy Theorist**
```
The wild JavaScript function stalks its prey... but wait... notice how it ALWAYS The wild JavaScript function stalks its prey... but wait... notice how it ALWAYS
knows where the data is? That's not natural selection, folks. Someone DESIGNED it knows where the data is? That's not natural selection, folks. Someone DESIGNED it
this way. The console.logs are watching. They're ALWAYS watching. this way. The console.logs are watching. They're ALWAYS watching.
Nature? Or intelligent debugging? You decide. Nature? Or intelligent debugging? You decide.
```
## Tips for Success ## Tips for Success

View File

@ -10,14 +10,16 @@
<step n="-1" goal="Optional brainstorming for agent ideas" optional="true"> <step n="-1" goal="Optional brainstorming for agent ideas" optional="true">
<ask>Do you want to brainstorm agent ideas first? [y/n]</ask> <ask>Do you want to brainstorm agent ideas first? [y/n]</ask>
<check>If yes:</check> <check if="user answered yes">
<action>Invoke brainstorming workflow: {project-root}/bmad/core/workflows/brainstorming/workflow.yaml</action> <action>Invoke brainstorming workflow: {project-root}/bmad/core/workflows/brainstorming/workflow.yaml</action>
<action>Pass context data: {installed_path}/brainstorm-context.md</action> <action>Pass context data: {installed_path}/brainstorm-context.md</action>
<action>Wait for brainstorming session completion</action> <action>Wait for brainstorming session completion</action>
<action>Use brainstorming output to inform agent identity and persona development in following steps</action> <action>Use brainstorming output to inform agent identity and persona development in following steps</action>
</check>
<check>If no:</check> <check if="user answered no">
<action>Proceed directly to Step 0</action> <action>Proceed directly to Step 0</action>
</check>
<template-output>brainstorming_results</template-output> <template-output>brainstorming_results</template-output>
</step> </step>
@ -48,15 +50,17 @@
**Path Determination:** **Path Determination:**
<check>If Module agent:</check> <check if="module agent selected">
<action>Discover which module system fits best (bmm, bmb, cis, or custom)</action> <action>Discover which module system fits best (bmm, bmb, cis, or custom)</action>
<action>Store as {{target_module}} for path determination</action> <action>Store as {{target_module}} for path determination</action>
<note>Agent will be saved to: bmad/{{target_module}}/agents/</note> <note>Agent will be saved to: bmad/{{target_module}}/agents/</note>
</check>
<check>If Simple/Expert agent (standalone):</check> <check if="standalone agent selected">
<action>Explain this will be their personal agent, not tied to a module</action> <action>Explain this will be their personal agent, not tied to a module</action>
<note>Agent will be saved to: bmad/agents/{{agent-name}}/</note> <note>Agent will be saved to: bmad/agents/{{agent-name}}/</note>
<note>All sidecar files will be in the same folder</note> <note>All sidecar files will be in the same folder</note>
</check>
<critical>Determine agent location:</critical> <critical>Determine agent location:</critical>
@ -163,8 +167,7 @@ menu:
<action>Generate the complete YAML incorporating all discovered elements:</action> <action>Generate the complete YAML incorporating all discovered elements:</action>
<example> <example type="yaml">
```yaml
agent: agent:
metadata: metadata:
id: bmad/{{target_module}}/agents/{{agent_filename}}.md id: bmad/{{target_module}}/agents/{{agent_filename}}.md
@ -188,11 +191,10 @@ prompts: {{if discussed}}
critical_actions: {{if needed}} critical_actions: {{if needed}}
menu: {{The capabilities built}} menu: {{The capabilities built}}
````
</example> </example>
<critical>Save based on agent type:</critical> <critical>Save based on agent type:</critical>
- If Module Agent: Save to {module_output_file} - If Module Agent: Save to {module_output_file}
- If Standalone (Simple/Expert): Save to {standalone_output_file} - If Standalone (Simple/Expert): Save to {standalone_output_file}
@ -204,7 +206,7 @@ menu: {{The capabilities built}}
<step n="7" goal="Optional personalization" optional="true"> <step n="7" goal="Optional personalization" optional="true">
<ask>Would you like to create a customization file? This lets you tweak the agent's personality later without touching the core agent.</ask> <ask>Would you like to create a customization file? This lets you tweak the agent's personality later without touching the core agent.</ask>
<check>If interested:</check> <check if="user interested">
<action>Explain how the customization file gives them a playground to experiment with different personality traits, add new commands, or adjust responses as they get to know the agent better</action> <action>Explain how the customization file gives them a playground to experiment with different personality traits, add new commands, or adjust responses as they get to know the agent better</action>
<action>Create customization file at: {config_output_file}</action> <action>Create customization file at: {config_output_file}</action>
@ -228,6 +230,8 @@ agent:
</example> </example>
</check>
<template-output>agent_config</template-output> <template-output>agent_config</template-output>
</step> </step>
@ -300,10 +304,11 @@ Add domain-specific resources here.
<step n="8b" goal="Handle build tools availability"> <step n="8b" goal="Handle build tools availability">
<action>Check if BMAD build tools are available in this project</action> <action>Check if BMAD build tools are available in this project</action>
<check>If in BMAD-METHOD project with build tools:</check> <check if="BMAD-METHOD project with build tools">
<action>Proceed normally - agent will be built later by the installer</action> <action>Proceed normally - agent will be built later by the installer</action>
</check>
<check>If NO build tools available (external project):</check> <check if="external project without build tools">
<ask>Build tools not detected in this project. Would you like me to: <ask>Build tools not detected in this project. Would you like me to:
1. Generate the compiled agent (.md with XML) ready to use 1. Generate the compiled agent (.md with XML) ready to use
@ -311,10 +316,13 @@ Add domain-specific resources here.
3. Provide both formats 3. Provide both formats
</ask> </ask>
<check>If option 1 or 3 selected:</check> <check if="option 1 or 3 selected">
<action>Generate compiled agent XML with proper structure including activation rules, persona sections, and menu items</action> <action>Generate compiled agent XML with proper structure including activation rules, persona sections, and menu items</action>
<action>Save compiled version as {{agent_filename}}.md</action> <action>Save compiled version as {{agent_filename}}.md</action>
<action>Provide path for .claude/commands/ or similar</action> <action>Provide path for .claude/commands/ or similar</action>
</check>
</check>
<template-output>build_handling</template-output> <template-output>build_handling</template-output>
</step> </step>
@ -328,11 +336,13 @@ Add domain-specific resources here.
- Command functionality verification - Command functionality verification
- Personality settings confirmation - Personality settings confirmation
<check>If issues found:</check> <check if="validation issues found">
<action>Explain the issue conversationally and fix it</action> <action>Explain the issue conversationally and fix it</action>
</check>
<check>If all good:</check> <check if="validation passed">
<action>Celebrate that the agent passed all checks and is ready</action> <action>Celebrate that the agent passed all checks and is ready</action>
</check>
**Technical Checks (behind the scenes):** **Technical Checks (behind the scenes):**
@ -365,8 +375,9 @@ Add domain-specific resources here.
- List the commands available - List the commands available
- Suggest trying the first command to see it in action - Suggest trying the first command to see it in action
<check>If Expert agent:</check> <check if="expert agent">
<action>Remind user to add any special knowledge or data the agent might need to its workspace</action> <action>Remind user to add any special knowledge or data the agent might need to its workspace</action>
</check>
<action>Explore what user would like to do next - test the agent, create a teammate, or tweak personality</action> <action>Explore what user would like to do next - test the agent, create a teammate, or tweak personality</action>

View File

@ -10,14 +10,16 @@
<step n="-1" goal="Optional brainstorming for module ideas" optional="true"> <step n="-1" goal="Optional brainstorming for module ideas" optional="true">
<ask>Do you want to brainstorm module ideas first? [y/n]</ask> <ask>Do you want to brainstorm module ideas first? [y/n]</ask>
<check>If yes:</check> <check if="yes">
<action>Invoke brainstorming workflow: {brainstorming_workflow}</action> <action>Invoke brainstorming workflow: {brainstorming_workflow}</action>
<action>Pass context data: {brainstorming_context}</action> <action>Pass context data: {brainstorming_context}</action>
<action>Wait for brainstorming session completion</action> <action>Wait for brainstorming session completion</action>
<action>Use brainstorming output to inform module concept, agent lineup, and workflow portfolio in following steps</action> <action>Use brainstorming output to inform module concept, agent lineup, and workflow portfolio in following steps</action>
</check>
<check>If no:</check> <check if="no">
<action>Proceed directly to Step 0</action> <action>Proceed directly to Step 0</action>
</check>
<template-output>brainstorming_results</template-output> <template-output>brainstorming_results</template-output>
</step> </step>
@ -25,17 +27,20 @@
<step n="0" goal="Check for module brief" optional="true"> <step n="0" goal="Check for module brief" optional="true">
<ask>Do you have a module brief or should we create one? [have/create/skip]</ask> <ask>Do you have a module brief or should we create one? [have/create/skip]</ask>
<check>If create:</check> <check if="create">
<action>Invoke module-brief workflow: {project-root}/bmad/bmb/workflows/module-brief/workflow.yaml</action> <action>Invoke module-brief workflow: {project-root}/bmad/bmb/workflows/module-brief/workflow.yaml</action>
<action>Wait for module brief completion</action> <action>Wait for module brief completion</action>
<action>Load the module brief to use as blueprint</action> <action>Load the module brief to use as blueprint</action>
</check>
<check>If have:</check> <check if="have">
<ask>Provide path to module brief document</ask> <ask>Provide path to module brief document</ask>
<action>Load the module brief and use it to pre-populate all planning sections</action> <action>Load the module brief and use it to pre-populate all planning sections</action>
</check>
<check>If skip:</check> <check if="skip">
<action>Proceed directly to Step 1</action> <action>Proceed directly to Step 1</action>
</check>
<template-output>module_brief</template-output> <template-output>module_brief</template-output>
</step> </step>
@ -113,8 +118,7 @@
**Tasks Planning (optional):** **Tasks Planning (optional):**
<ask>Any special tasks that don't warrant full workflows?</ask> <ask>Any special tasks that don't warrant full workflows?</ask>
<check>If tasks needed:</check> <action if="tasks needed">For each task, capture name, purpose, and whether standalone or supporting</action>
<action>For each task, capture name, purpose, and whether standalone or supporting</action>
<template-output>module_components</template-output> <template-output>module_components</template-output>
</step> </step>
@ -221,7 +225,7 @@
<step n="5" goal="Create first agent" optional="true"> <step n="5" goal="Create first agent" optional="true">
<ask>Create your first agent now? [yes/no]</ask> <ask>Create your first agent now? [yes/no]</ask>
<check>If yes:</check> <check if="yes">
<action>Invoke agent builder workflow: {agent_builder}</action> <action>Invoke agent builder workflow: {agent_builder}</action>
<action>Pass module_components as context input</action> <action>Pass module_components as context input</action>
<action>Guide them to create the primary agent for the module</action> <action>Guide them to create the primary agent for the module</action>
@ -229,9 +233,11 @@
<critical>Save to module's agents folder:</critical> <critical>Save to module's agents folder:</critical>
- Save to {{module_path}}/agents/ - Save to {{module_path}}/agents/
</check>
<check>If no:</check> <check if="no">
<action>Create placeholder file in agents folder with TODO notes including agent name, purpose, and type</action> <action>Create placeholder file in agents folder with TODO notes including agent name, purpose, and type</action>
</check>
<template-output>first_agent</template-output> <template-output>first_agent</template-output>
</step> </step>
@ -239,7 +245,7 @@
<step n="6" goal="Create first workflow" optional="true"> <step n="6" goal="Create first workflow" optional="true">
<ask>Create your first workflow now? [yes/no]</ask> <ask>Create your first workflow now? [yes/no]</ask>
<check>If yes:</check> <check if="yes">
<action>Invoke workflow builder: {workflow_builder}</action> <action>Invoke workflow builder: {workflow_builder}</action>
<action>Pass module_components as context input</action> <action>Pass module_components as context input</action>
<action>Guide them to create the primary workflow</action> <action>Guide them to create the primary workflow</action>
@ -247,9 +253,11 @@
<critical>Save to module's workflows folder:</critical> <critical>Save to module's workflows folder:</critical>
- Save to {{module_path}}/workflows/ - Save to {{module_path}}/workflows/
</check>
<check>If no:</check> <check if="no">
<action>Create placeholder workflow folder structure with TODO notes for workflow.yaml, instructions.md, and template.md if document workflow</action> <action>Create placeholder workflow folder structure with TODO notes for workflow.yaml, instructions.md, and template.md if document workflow</action>
</check>
<template-output>first_workflow</template-output> <template-output>first_workflow</template-output>
</step> </step>
@ -325,23 +333,23 @@ prompt:
<ask>Does your module need custom installation logic (database setup, API registration, etc.)?</ask> <ask>Does your module need custom installation logic (database setup, API registration, etc.)?</ask>
<check>If yes, create installer.js:</check> <check if="yes, create installer.js">
```javascript ```javascript
// {{module_name}} Module Installer // {{module_name}} Module Installer
// Custom installation logic // Custom installation logic
/** /\*\*
* Module installation hook
* Called after files are copied but before IDE configuration - Module installation hook
* - Called after files are copied but before IDE configuration
* @param {Object} options - Installation options -
* @param {string} options.projectRoot - Project root directory - @param {Object} options - Installation options
* @param {Object} options.config - Module configuration from install-config.yaml - @param {string} options.projectRoot - Project root directory
* @param {Array} options.installedIDEs - List of IDE codes being configured - @param {Object} options.config - Module configuration from install-config.yaml
* @param {Object} options.logger - Logger instance (log, warn, error methods) - @param {Array} options.installedIDEs - List of IDE codes being configured
* @returns {boolean} - true if successful, false to abort installation - @param {Object} options.logger - Logger instance (log, warn, error methods)
*/ - @returns {boolean} - true if successful, false to abort installation
\*/
async function install(options) { async function install(options) {
const { projectRoot, config, installedIDEs, logger } = options; const { projectRoot, config, installedIDEs, logger } = options;
@ -357,17 +365,21 @@ async function install(options) {
logger.log('{{module_name}} custom installation complete!'); logger.log('{{module_name}} custom installation complete!');
return true; return true;
} }
module.exports = { install }; module.exports = { install };
```
`````
<critical>Save location:</critical> <critical>Save location:</critical>
- Save to {{module_path}}/\_module-installer/installer.js - Save to {{module_path}}/\_module-installer/installer.js
</check>
<check>If no:</check> <check if="no">
<action>Skip installer.js creation - the standard installer will handle everything</action> <action>Skip installer.js creation - the standard installer will handle everything</action>
</check>
<template-output>installer_config</template-output> <template-output>installer_config</template-output>
</step> </step>
@ -389,7 +401,8 @@ This module provides:
```bash ```bash
bmad install {{module_code}} bmad install {{module_code}}
``` `````
```` ````
## Components ## Components
@ -471,22 +484,26 @@ Created by {{user_name}} on {{date}}
Create a development roadmap for remaining components: Create a development roadmap for remaining components:
**TODO.md file:** **TODO.md file:**
```markdown ```markdown
# {{module_name}} Development Roadmap # {{module_name}} Development Roadmap
## Phase 1: Core Components ## Phase 1: Core Components
{{phase1_tasks}} {{phase1_tasks}}
## Phase 2: Enhanced Features ## Phase 2: Enhanced Features
{{phase2_tasks}} {{phase2_tasks}}
## Phase 3: Polish and Integration ## Phase 3: Polish and Integration
{{phase3_tasks}} {{phase3_tasks}}
## Quick Commands ## Quick Commands
Create new agent: Create new agent:
```` ```
workflow create-agent workflow create-agent

View File

@ -290,6 +290,43 @@ _Generated on {{date}}_
- **`<action if="">`** - Single conditional action (cleaner, more concise) - **`<action if="">`** - Single conditional action (cleaner, more concise)
- **`<check if="">...</check>`** - Multiple items under same condition (explicit scope) - **`<check if="">...</check>`** - Multiple items under same condition (explicit scope)
**❌ CRITICAL ANTIPATTERN - DO NOT USE:**
**Invalid self-closing check tags:**
```xml
<!-- ❌ WRONG - Invalid XML structure -->
<check>If condition met:</check>
<action>Do something</action>
<!-- ❌ WRONG - Ambiguous nesting -->
<check>If validation fails:</check>
<action>Log error</action>
<goto step="1">Retry</goto>
```
**Why this is wrong:**
- Creates invalid XML structure (check tag doesn't wrap anything)
- Ambiguous - unclear if actions are inside or outside the condition
- Breaks formatter and parser logic
- Not part of BMAD workflow spec
**✅ CORRECT alternatives:**
```xml
<!-- ✅ Single action - use inline if -->
<action if="condition met">Do something</action>
<!-- ✅ Multiple actions - use proper wrapper block -->
<check if="validation fails">
<action>Log error</action>
<goto step="1">Retry</goto>
</check>
```
**Rule:** If you have only ONE conditional action, use `<action if="">`. If you have MULTIPLE conditional actions, use `<check if="">...</check>` wrapper with a closing tag.
### Loops ### Loops
```xml ```xml

View File

@ -86,7 +86,7 @@ Present the editing menu to the user:
<step n="4" goal="Load relevant documentation"> <step n="4" goal="Load relevant documentation">
Based on the selected edit type, load appropriate reference materials: Based on the selected edit type, load appropriate reference materials:
<check>If option 2 (Add/fix standard config):</check> <check if="option 2 (Add/fix standard config) selected">
<action>Prepare standard config block template:</action> <action>Prepare standard config block template:</action>
```yaml ```yaml
@ -102,47 +102,53 @@ date: system-generated
<action>Identify missing config variables to add</action> <action>Identify missing config variables to add</action>
<action>Check instructions.md for config variable usage</action> <action>Check instructions.md for config variable usage</action>
<action>Check template.md for config variable usage</action> <action>Check template.md for config variable usage</action>
</check>
<check>If editing instructions or adding features:</check> <check if="editing instructions or adding features">
<action>Review the "Writing Instructions" section of the creation guide</action> <action>Review the "Writing Instructions" section of the creation guide</action>
<action>Load example workflows from {project-root}/bmad/bmm/workflows/ for patterns</action> <action>Load example workflows from {project-root}/bmad/bmm/workflows/ for patterns</action>
</check>
<check>If editing templates:</check> <check if="editing templates">
<action>Review the "Templates and Variables" section of the creation guide</action> <action>Review the "Templates and Variables" section of the creation guide</action>
<action>Ensure variable naming conventions are followed</action> <action>Ensure variable naming conventions are followed</action>
</check>
<check>If editing validation:</check> <action if="editing validation">Review the "Validation" section and measurable criteria examples</action>
<action>Review the "Validation" section and measurable criteria examples</action>
<check>If option 9 (Remove bloat):</check> <check if="option 9 (Remove bloat) selected">
<action>Cross-reference all workflow.yaml fields against instructions.md and template.md</action> <action>Cross-reference all workflow.yaml fields against instructions.md and template.md</action>
<action>Identify yaml fields not used in any file</action> <action>Identify yaml fields not used in any file</action>
<action>Check for duplicate fields in web_bundle section</action> <action>Check for duplicate fields in web_bundle section</action>
</check>
<check>If configuring web bundle:</check> <check if="configuring web bundle">
<action>Review the "Web Bundles" section of the creation guide</action> <action>Review the "Web Bundles" section of the creation guide</action>
<action>Scan all workflow files for referenced resources</action> <action>Scan all workflow files for referenced resources</action>
<action>Create inventory of all files that must be included</action> <action>Create inventory of all files that must be included</action>
<action>Scan instructions for <invoke-workflow> calls - those yamls must be included</action> <action>Scan instructions for invoke-workflow calls - those yamls must be included</action>
</check>
<check>If fixing critical issues:</check> <check if="fixing critical issues">
<action>Load the workflow execution engine documentation</action> <action>Load the workflow execution engine documentation</action>
<action>Verify all required elements are present</action> <action>Verify all required elements are present</action>
</check>
<check>If adjusting instruction style (option 11):</check> <check if="adjusting instruction style (option 11) selected">
<action>Analyze current instruction style in instructions.md:</action> <action>Analyze current instruction style in instructions.md:</action>
- Count <action> tags vs <ask> tags - Count action tags vs ask tags
- Identify goal-oriented language ("guide", "explore", "help") vs prescriptive ("choose", "select", "specify") - Identify goal-oriented language ("guide", "explore", "help") vs prescriptive ("choose", "select", "specify")
- Assess whether steps are open-ended or structured with specific options - Assess whether steps are open-ended or structured with specific options
<action>Determine current dominant style: intent-based, prescriptive, or mixed</action> <action>Determine current dominant style: intent-based, prescriptive, or mixed</action>
<action>Load the instruction style guide section from create-workflow</action> <action>Load the instruction style guide section from create-workflow</action>
</check>
</step> </step>
<step n="5" goal="Perform edits" repeat="until-complete"> <step n="5" goal="Perform edits" repeat="until-complete">
Based on the selected focus area: Based on the selected focus area:
<check>If configuring web bundle (option 7):</check> <check if="configuring web bundle (option 7) selected">
<action>Check if web_bundle section exists in workflow.yaml</action> <action>Check if web_bundle section exists in workflow.yaml</action>
If creating new web bundle: If creating new web bundle:
@ -157,7 +163,7 @@ If creating new web bundle:
- Any included files - Any included files
5. Scan template.md for any includes 5. Scan template.md for any includes
6. Create complete web_bundle_files array 6. Create complete web_bundle_files array
7. **CRITICAL**: Check for <invoke-workflow> calls in instructions: 7. **CRITICAL**: Check for invoke-workflow calls in instructions:
- If workflow invokes other workflows, add existing_workflows field - If workflow invokes other workflows, add existing_workflows field
- Maps workflow variable name to bmad/-relative path - Maps workflow variable name to bmad/-relative path
- Signals bundler to recursively include invoked workflow's web_bundle - Signals bundler to recursively include invoked workflow's web_bundle
@ -170,8 +176,9 @@ If updating existing web bundle:
2. Check for missing files in web_bundle_files 2. Check for missing files in web_bundle_files
3. Remove any config dependencies 3. Remove any config dependencies
4. Update file list with newly referenced files 4. Update file list with newly referenced files
</check>
<check>If adjusting instruction style (option 11):</check> <check if="adjusting instruction style (option 11) selected">
<action>Present current style analysis to user:</action> <action>Present current style analysis to user:</action>
**Current Instruction Style Analysis:** **Current Instruction Style Analysis:**
@ -233,8 +240,8 @@ Even workflows with a primary style should use the other when appropriate. For e
<ask>What would you like to do? <ask>What would you like to do?
1. **Make more intent-based** - Convert prescriptive <ask> tags to goal-oriented <action> tags where appropriate 1. **Make more intent-based** - Convert prescriptive ask tags to goal-oriented action tags where appropriate
2. **Make more prescriptive** - Convert open-ended <action> tags to specific <ask> tags with options 2. **Make more prescriptive** - Convert open-ended action tags to specific ask tags with options
3. **Optimize mix** - Use intent-based for complex steps, prescriptive for simple data collection 3. **Optimize mix** - Use intent-based for complex steps, prescriptive for simple data collection
4. **Review specific steps** - Show me each step and let me decide individually 4. **Review specific steps** - Show me each step and let me decide individually
5. **Cancel** - Keep current style 5. **Cancel** - Keep current style
@ -242,9 +249,10 @@ Even workflows with a primary style should use the other when appropriate. For e
Select option (1-5):</ask> Select option (1-5):</ask>
<action>Store user's style adjustment preference as {{style_adjustment_choice}}</action> <action>Store user's style adjustment preference as {{style_adjustment_choice}}</action>
</check>
<check>If choice is 1 (make more intent-based):</check> <check if="choice is 1 (make more intent-based)">
<action>Identify prescriptive <ask> tags that could be converted to intent-based <action> tags</action> <action>Identify prescriptive ask tags that could be converted to intent-based action tags</action>
<action>For each candidate conversion: <action>For each candidate conversion:
- Show original prescriptive version - Show original prescriptive version
@ -253,9 +261,10 @@ Select option (1-5):</ask>
- Ask for approval - Ask for approval
</action> </action>
<action>Apply approved conversions</action> <action>Apply approved conversions</action>
</check>
<check>If choice is 2 (make more prescriptive):</check> <check if="choice is 2 (make more prescriptive)">
<action>Identify open-ended <action> tags that could be converted to prescriptive <ask> tags</action> <action>Identify open-ended action tags that could be converted to prescriptive ask tags</action>
<action>For each candidate conversion: <action>For each candidate conversion:
- Show original intent-based version - Show original intent-based version
@ -264,8 +273,9 @@ Select option (1-5):</ask>
- Ask for approval - Ask for approval
</action> </action>
<action>Apply approved conversions</action> <action>Apply approved conversions</action>
</check>
<check>If choice is 3 (optimize mix):</check> <check if="choice is 3 (optimize mix)">
<action>Analyze each step for complexity and purpose</action> <action>Analyze each step for complexity and purpose</action>
<action>Recommend style for each step: <action>Recommend style for each step:
@ -278,8 +288,9 @@ Select option (1-5):</ask>
</action> </action>
<action>Show recommendations with reasoning</action> <action>Show recommendations with reasoning</action>
<action>Apply approved optimizations</action> <action>Apply approved optimizations</action>
</check>
<check>If choice is 4 (review specific steps):</check> <check if="choice is 4 (review specific steps)">
<action>Present each step one at a time</action> <action>Present each step one at a time</action>
<action>For each step: <action>For each step:
@ -288,9 +299,9 @@ Select option (1-5):</ask>
- Offer to keep, convert to intent-based, or convert to prescriptive - Offer to keep, convert to intent-based, or convert to prescriptive
- Apply user's choice before moving to next step - Apply user's choice before moving to next step
</action> </action>
</check>
<check>If choice is 5 (cancel):</check> <action if="choice is 5 (cancel)"><goto step="3">Return to editing menu</goto></action>
<goto step="3">Return to editing menu</goto>
<action>Show the current content that will be edited</action> <action>Show the current content that will be edited</action>
<action>Explain the proposed changes and why they improve the workflow</action> <action>Explain the proposed changes and why they improve the workflow</action>
@ -305,16 +316,17 @@ Select option (1-5):</ask>
- [d] Done with edits - [d] Done with edits
</ask> </ask>
<check>If user selects 'a':</check> <check if="user selects 'a'">
<action>Apply the changes to the file</action> <action>Apply the changes to the file</action>
<action>Log the change for the summary</action> <action>Log the change for the summary</action>
</check>
<check>If user selects 'e':</check> <check if="user selects 'e'">
<ask>What modifications would you like to make?</ask> <ask>What modifications would you like to make?</ask>
<goto step="5">Regenerate with modifications</goto> <goto step="5">Regenerate with modifications</goto>
</check>
<check>If user selects 'd':</check> <action if="user selects 'd'"><continue>Proceed to validation</continue></action>
<continue>Proceed to validation</continue>
</step> </step>
<step n="6" goal="Validate all changes" optional="true"> <step n="6" goal="Validate all changes" optional="true">
@ -361,10 +373,12 @@ Select option (1-5):</ask>
- [ ] Called workflows (<invoke-workflow>) included in web_bundle_files - [ ] Called workflows (<invoke-workflow>) included in web_bundle_files
- [ ] Complete file inventory verified - [ ] Complete file inventory verified
<check>If any validation fails:</check> <check if="any validation fails">
<ask>Issues found. Would you like to fix them? (y/n)</ask> <ask>Issues found. Would you like to fix them? (y/n)</ask>
<check>If yes:</check> <check if="yes">
<goto step="5">Return to editing</goto> <goto step="5">Return to editing</goto>
</check>
</check>
</step> </step>
<step n="7" goal="Generate change summary"> <step n="7" goal="Generate change summary">
@ -385,8 +399,7 @@ Select option (1-5):</ask>
- Exit - Exit
</ask> </ask>
<check>If test workflow:</check> <action if="test workflow">Invoke the edited workflow for testing</action>
<action>Invoke the edited workflow for testing</action>
</step> </step>
</workflow> </workflow>

View File

@ -130,7 +130,7 @@
4. Save README.md 4. Save README.md
</action> </action>
<check>If clarification needed about purpose or unique features → Ask user briefly, then continue</check> <action if="clarification needed about purpose or unique features">Ask user briefly, then continue</action>
</step> </step>
<step n="4" goal="Process mid-level folder documentation" if="target_type requires folder docs"> <step n="4" goal="Process mid-level folder documentation" if="target_type requires folder docs">

263
tools/format-workflow-md.js Executable file
View File

@ -0,0 +1,263 @@
/**
* BMAD Workflow Markdown Formatter
*
* Formats mixed markdown + XML workflow instruction files with:
* - 2-space XML indentation
* - Preserved markdown content
* - Proper tag nesting
* - Consistent formatting
*/
const fs = require('node:fs');
const path = require('node:path');
class WorkflowFormatter {
constructor(options = {}) {
this.indentSize = options.indentSize || 2;
this.preserveMarkdown = options.preserveMarkdown !== false;
this.verbose = options.verbose || false;
}
/**
* Format a workflow markdown file
*/
format(filePath) {
if (this.verbose) {
console.log(`Formatting: ${filePath}`);
}
const content = fs.readFileSync(filePath, 'utf8');
const formatted = this.formatContent(content);
// Only write if content changed
if (content === formatted) {
if (this.verbose) {
console.log(`- No changes: ${filePath}`);
}
return false;
} else {
fs.writeFileSync(filePath, formatted, 'utf8');
if (this.verbose) {
console.log(`✓ Formatted: ${filePath}`);
}
return true;
}
}
/**
* Format content string with stateful indentation tracking
*/
formatContent(content) {
const lines = content.split('\n');
const formatted = [];
let indentLevel = 0;
let inCodeBlock = false;
let checkBlockDepth = 0; // Track nested check blocks
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const trimmed = line.trim();
// Track code blocks (don't format inside them)
if (trimmed.startsWith('```')) {
if (inCodeBlock) {
inCodeBlock = false;
} else {
inCodeBlock = true;
}
formatted.push(line);
continue;
}
// Don't format inside code blocks
if (inCodeBlock) {
formatted.push(line);
continue;
}
// Handle XML tags
if (this.isXMLLine(trimmed)) {
const result = this.formatXMLLine(trimmed, indentLevel, checkBlockDepth, i, lines);
formatted.push(result.line);
indentLevel = result.nextIndent;
checkBlockDepth = result.nextCheckDepth;
} else if (trimmed === '') {
// Preserve blank lines
formatted.push('');
} else {
// Markdown content - preserve as-is but maintain current indent if inside XML
formatted.push(line);
}
}
return formatted.join('\n');
}
/**
* Check if line contains XML tag
*/
isXMLLine(line) {
return /^<[a-zA-Z-]+(\s|>|\/)/.test(line) || /^<\/[a-zA-Z-]+>/.test(line);
}
/**
* Format a single XML line with context awareness
*/
formatXMLLine(line, currentIndent, checkDepth, lineIndex, allLines) {
const trimmed = line.trim();
let indent = currentIndent;
let nextIndent = currentIndent;
let nextCheckDepth = checkDepth;
// Get the tag name
const tagMatch = trimmed.match(/^<\/?([a-zA-Z-]+)/);
const tagName = tagMatch ? tagMatch[1] : '';
// Closing tag - decrease indent before this line
if (trimmed.startsWith('</')) {
indent = Math.max(0, currentIndent - 1);
nextIndent = indent;
// If closing a step, reset check depth
if (tagName === 'step' || tagName === 'workflow') {
nextCheckDepth = 0;
}
}
// Self-closing tags (opens and closes on same line)
// EXCEPT <check> tags which create logical blocks
else if (this.isSelfClosingTag(trimmed) && tagName !== 'check') {
// These don't change indent level
indent = currentIndent;
nextIndent = currentIndent;
}
// Opening tags
else if (trimmed.startsWith('<')) {
// Check if this is a <check> tag - these create logical blocks
if (tagName === 'check') {
indent = currentIndent;
// Check tags increase indent for following content
nextIndent = currentIndent + 1;
nextCheckDepth = checkDepth + 1;
}
// <action> tags inside check blocks stay at current indent
else if (tagName === 'action' && checkDepth > 0) {
indent = currentIndent;
nextIndent = currentIndent; // Don't increase further
}
// Other tags close check blocks and return to structural level
else if (checkDepth > 0) {
// Close all check blocks - return to base structural level
indent = Math.max(0, currentIndent - checkDepth);
nextIndent = indent + 1;
nextCheckDepth = 0;
}
// Regular opening tags (no check blocks active)
else {
indent = currentIndent;
nextIndent = currentIndent + 1;
}
}
const indentStr = ' '.repeat(indent * this.indentSize);
return {
line: indentStr + trimmed,
nextIndent: nextIndent,
nextCheckDepth: nextCheckDepth,
};
}
/**
* Check if tag opens and closes on same line
*/
isSelfClosingTag(line) {
// Self-closing with />
if (line.endsWith('/>')) {
return true;
}
// Opens and closes on same line: <tag>content</tag>
const match = line.match(/^<([a-zA-Z-]+)(\s[^>]*)?>.*<\/\1>$/);
return match !== null;
}
/**
* Check if tag is a block-level structural tag
*/
isBlockLevelTag(tagName) {
return ['step', 'workflow', 'check'].includes(tagName);
}
}
/**
* CLI Entry Point
*/
function main() {
const args = process.argv.slice(2);
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
console.log(`
BMAD Workflow Markdown Formatter
Usage:
node format-workflow-md.js <file-pattern> [options]
Options:
--verbose, -v Verbose output
--check, -c Check formatting without writing (exit 1 if changes needed)
--help, -h Show this help
Examples:
node format-workflow-md.js src/**/instructions.md
node format-workflow-md.js "src/modules/bmb/**/*.md" --verbose
node format-workflow-md.js file.md --check
`);
process.exit(0);
}
const verbose = args.includes('--verbose') || args.includes('-v');
const check = args.includes('--check') || args.includes('-c');
// Remove flags from args
const files = args.filter((arg) => !arg.startsWith('-'));
const formatter = new WorkflowFormatter({ verbose });
let hasChanges = false;
let formattedCount = 0;
// Process files
for (const pattern of files) {
// For now, treat as direct file path
// TODO: Add glob support for patterns
if (fs.existsSync(pattern)) {
const stat = fs.statSync(pattern);
if (stat.isFile()) {
const changed = formatter.format(pattern);
if (changed) {
hasChanges = true;
formattedCount++;
}
} else if (stat.isDirectory()) {
console.error(`Error: ${pattern} is a directory. Please specify file paths.`);
}
} else {
console.error(`Error: File not found: ${pattern}`);
}
}
if (verbose || formattedCount > 0) {
console.log(`\nFormatted ${formattedCount} file(s)`);
}
if (check && hasChanges) {
console.error('\n❌ Some files need formatting. Run without --check to format.');
process.exit(1);
}
process.exit(0);
}
// Run if called directly
if (require.main === module) {
main();
}
module.exports = { WorkflowFormatter };