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>)
- [ ] No nested tag references in content (use "action tags" not "<action> tags")
- [ ] 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)
- [ ] Instructions are specific with limits ("Write 1-2 paragraphs" not "Write about")
- [ ] Examples provided where helpful

View File

@ -5,391 +5,337 @@
<workflow>
<step n="1" goal="Load and analyze target workflow">
<ask>What is the path to the workflow you want to audit? (provide path to workflow.yaml or workflow folder)</ask>
<step n="1" goal="Load and analyze target workflow">
<ask>What is the path to the workflow you want to audit? (provide path to workflow.yaml or workflow folder)</ask>
<action>Load the workflow.yaml file from the provided path</action>
<action>Identify the workflow type (document, action, interactive, autonomous, meta)</action>
<action>List all associated files:</action>
<action>Load the workflow.yaml file from the provided path</action>
<action>Identify the workflow type (document, action, interactive, autonomous, meta)</action>
<action>List all associated files:</action>
- instructions.md (required for most workflows)
- template.md (if document workflow)
- checklist.md (if validation exists)
- Any data files referenced in yaml
- instructions.md (required for most workflows)
- template.md (if document workflow)
- checklist.md (if validation exists)
- Any data files referenced in yaml
<action>Load all discovered files</action>
<action>Load all discovered files</action>
Display summary:
Display summary:
- Workflow name and description
- Type of workflow
- Files present
- Module assignment
- Workflow name and description
- Type of workflow
- Files present
- Module assignment
</step>
<step n="2" goal="Validate standard config block">
<action>Check workflow.yaml for the standard config block:</action>
<step n="2" goal="Validate standard config block">
<action>Check workflow.yaml for the standard config block:</action>
**Required variables:**
**Required variables:**
- `config_source: "{project-root}/bmad/[module]/config.yaml"`
- `output_folder: "{config_source}:output_folder"`
- `user_name: "{config_source}:user_name"`
- `communication_language: "{config_source}:communication_language"`
- `date: system-generated`
- `config_source: "{project-root}/bmad/[module]/config.yaml"`
- `output_folder: "{config_source}:output_folder"`
- `user_name: "{config_source}:user_name"`
- `communication_language: "{config_source}:communication_language"`
- `date: system-generated`
<action>Validate each variable:</action>
<action>Validate each variable:</action>
**Config Source Check:**
**Config Source Check:**
- [ ] `config_source` is defined
- [ ] Points to correct module config path
- [ ] Uses {project-root} variable
- [ ] `config_source` is defined
- [ ] Points to correct module config path
- [ ] Uses {project-root} variable
**Standard Variables Check:**
**Standard Variables Check:**
- [ ] `output_folder` pulls from config_source
- [ ] `user_name` pulls from config_source
- [ ] `communication_language` pulls from config_source
- [ ] `date` is set to system-generated
- [ ] `output_folder` pulls from config_source
- [ ] `user_name` pulls from config_source
- [ ] `communication_language` pulls from config_source
- [ ] `date` is set to system-generated
<action>Record any missing or incorrect config variables</action>
<template-output>config_issues</template-output>
<action>Record any missing or incorrect config variables</action>
<template-output>config_issues</template-output>
<check>If config issues found:</check>
<action>Add to issues list with severity: CRITICAL</action>
</step>
<action if="config issues found">Add to issues list with severity: CRITICAL</action>
<step n="3" goal="Analyze YAML/Instruction/Template alignment">
<action>Extract all variables defined in workflow.yaml (excluding standard config block)</action>
<action>Scan instructions.md for variable usage: {variable_name} pattern</action>
<action>Scan template.md for variable usage: {{variable_name}} pattern (if exists)</action>
</step>
<action>Cross-reference analysis:</action>
<step n="3" goal="Analyze YAML/Instruction/Template alignment">
<action>Extract all variables defined in workflow.yaml (excluding standard config block)</action>
<action>Scan instructions.md for variable usage: {variable_name} pattern</action>
<action>Scan template.md for variable usage: {{variable_name}} pattern (if exists)</action>
**For each yaml variable:**
<action>Cross-reference analysis:</action>
1. Is it used in instructions.md? (mark as INSTRUCTION_USED)
2. Is it used in template.md? (mark as TEMPLATE_USED)
3. Is it neither? (mark as UNUSED_BLOAT)
**For each yaml variable:**
**Special cases to ignore:**
1. Is it used in instructions.md? (mark as INSTRUCTION_USED)
2. Is it used in template.md? (mark as TEMPLATE_USED)
3. Is it neither? (mark as UNUSED_BLOAT)
- Standard config variables (config_source, output_folder, user_name, communication_language, date)
- Workflow metadata (name, description, author)
- Path variables (installed_path, template, instructions, validation)
- Web bundle configuration (web_bundle block itself)
**Special cases to ignore:**
<action>Identify unused yaml fields (bloat)</action>
<action>Identify hardcoded values in instructions that should be variables</action>
<template-output>alignment_issues</template-output>
- Standard config variables (config_source, output_folder, user_name, communication_language, date)
- Workflow metadata (name, description, author)
- Path variables (installed_path, template, instructions, validation)
- Web bundle configuration (web_bundle block itself)
<check>If unused variables found:</check>
<action>Add to issues list with severity: BLOAT</action>
</step>
<action>Identify unused yaml fields (bloat)</action>
<action>Identify hardcoded values in instructions that should be variables</action>
<template-output>alignment_issues</template-output>
<step n="4" goal="Config variable usage audit">
<action>Analyze instructions.md for proper config variable usage:</action>
<action if="unused variables found">Add to issues list with severity: BLOAT</action>
**Communication Language Check:**
</step>
- Search for phrases like "communicate in {communication_language}"
- Check if greetings/responses use language-aware patterns
- Verify NO usage of {{communication_language}} in template headers
<step n="4" goal="Config variable usage audit">
<action>Analyze instructions.md for proper config variable usage:</action>
**User Name Check:**
**Communication Language Check:**
- Look for user addressing patterns using {user_name}
- Check if summaries or greetings personalize with {user_name}
- Verify optional usage in template metadata (not required)
- Search for phrases like "communicate in {communication_language}"
- Check if greetings/responses use language-aware patterns
- Verify NO usage of {{communication_language}} in template headers
**Output Folder Check:**
**User Name Check:**
- Search for file write operations
- Verify all outputs go to {output_folder} or subdirectories
- Check for hardcoded paths like "/output/" or "/generated/"
- Look for user addressing patterns using {user_name}
- Check if summaries or greetings personalize with {user_name}
- Verify optional usage in template metadata (not required)
**Date Usage Check:**
**Output Folder Check:**
- Verify date is available for agent date awareness
- Check optional usage in template metadata
- Ensure no confusion between date and model training cutoff
- Search for file write operations
- Verify all outputs go to {output_folder} or subdirectories
- Check for hardcoded paths like "/output/" or "/generated/"
**Nested Tag Reference Check:**
**Date Usage Check:**
- Search for XML tag references within tags (e.g., `<action>Scan for <action> tags</action>`)
- Identify patterns like: `<tag-name> tags`, `<tag-name> calls`, `<tag-name>content</tag-name>` within content
- Common problematic tags to check: action, ask, check, template-output, invoke-workflow, goto
- Flag any instances where angle brackets appear in content describing tags
- Verify date is available for agent date awareness
- Check optional usage in template metadata
- Ensure no confusion between date and model training cutoff
**Best Practice:** Use descriptive text without brackets (e.g., "action tags" instead of "<action> tags")
**Nested Tag Reference Check:**
**Rationale:**
- Search for XML tag references within tags (e.g., `<action>Scan for <action> tags</action>`)
- Identify patterns like: `<tag-name> tags`, `<tag-name> calls`, `<tag-name>content</tag-name>` within content
- Common problematic tags to check: action, ask, check, template-output, invoke-workflow, goto
- Flag any instances where angle brackets appear in content describing tags
- Prevents XML parsing ambiguity
- Improves readability for humans and LLMs
- LLMs understand "action tags" = `<action>` tags from context
**Best Practice:** Use descriptive text without brackets (e.g., "action tags" instead of "<action> tags")
<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 improper config variable usage</action>
<template-output>config_usage_issues</template-output>
**Rationale:**
<check>If config usage issues found:</check>
<action>Add to issues list with severity: IMPORTANT</action>
<check>If nested tag references found:</check>
<action>Add to issues list with severity: CLARITY (recommend using descriptive text without angle brackets)</action>
</step>
- Prevents XML parsing ambiguity
- Improves readability for humans and LLMs
- LLMs understand "action tags" = `<action>` tags from context
<step n="5" goal="Web bundle validation" optional="true">
<check>If workflow.yaml contains web_bundle section:</check>
**Conditional Execution Antipattern Check:**
<action>Validate web_bundle structure:</action>
- 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>`
**Path Validation:**
**Correct Patterns:**
- [ ] All paths use bmad/-relative format (NOT {project-root})
- [ ] No {config_source} variables in web_bundle section
- [ ] Paths match actual file locations
- Single conditional: `<action if="condition">Do something</action>`
- Multiple actions: `<check if="condition">` followed by nested actions with closing `</check>` tag
**Completeness Check:**
**Antipattern Example (WRONG):**
```xml
<check>If condition met:</check>
<action>Do something</action>
```
- [ ] instructions file listed in web_bundle_files
- [ ] template file listed (if document workflow)
- [ ] validation/checklist file listed (if exists)
- [ ] All data files referenced in yaml listed
- [ ] All files referenced in instructions listed
**Correct Example:**
```xml
<check if="condition met">
<action>Do something</action>
<action>Do something else</action>
</check>
```
**Workflow Dependency Scan:**
<action>Scan instructions.md for invoke-workflow tags</action>
<action>Extract workflow paths from invocations</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>If invoke-workflow calls exist, existing_workflows MUST map workflow variables to paths</action>
<action>Example: If instructions use {core_brainstorming}, web_bundle needs:
existing_workflows: - core_brainstorming: "bmad/core/workflows/brainstorming/workflow.yaml"
</action>
**Or for single action:**
```xml
<action if="condition met">Do something</action>
```
**File Reference Scan:**
<action>Scan instructions.md for file references in action tags</action>
<action>Check for CSV, JSON, YAML, MD files referenced</action>
<action>Verify all referenced files are in web_bundle_files</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>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>
<template-output>config_usage_issues</template-output>
<action>Record any missing files or incorrect paths</action>
<template-output>web_bundle_issues</template-output>
<action if="config usage issues found">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>
<action if="conditional antipattern found">Add to issues list with severity: CRITICAL (invalid XML structure - must use action if="" or proper check wrapper)</action>
<check>If web_bundle issues found:</check>
<action>Add to issues list with severity: CRITICAL</action>
</step>
<check>If no web_bundle section exists:</check>
<action>Note: "No web_bundle configured (may be intentional for local-only workflows)"</action>
</step>
<step n="5" goal="Web bundle validation" optional="true">
<check if="workflow.yaml contains web_bundle section">
<step n="6" goal="Bloat detection">
<action>Identify bloat patterns:</action>
<action>Validate web_bundle structure:</action>
**Unused YAML Fields:**
**Path Validation:**
- Variables defined but not used in instructions OR template
- Duplicate fields between top-level and web_bundle section
- Commented-out variables that should be removed
- [ ] All paths use bmad/-relative format (NOT {project-root})
- [ ] No {config_source} variables in web_bundle section
- [ ] Paths match actual file locations
**Hardcoded Values:**
**Completeness Check:**
- File paths that should use {output_folder}
- Generic greetings that should use {user_name}
- Language-specific text that should use {communication_language}
- Static dates that should use {date}
- [ ] instructions file listed in web_bundle_files
- [ ] template file listed (if document workflow)
- [ ] validation/checklist file listed (if exists)
- [ ] All data files referenced in yaml listed
- [ ] All files referenced in instructions listed
**Redundant Configuration:**
**Workflow Dependency Scan:**
<action>Scan instructions.md for invoke-workflow tags</action>
<action>Extract workflow paths from invocations</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>If invoke-workflow calls exist, existing_workflows MUST map workflow variables to paths</action>
<action>Example: If instructions use {core_brainstorming}, web_bundle needs: existing_workflows: - core_brainstorming: "bmad/core/workflows/brainstorming/workflow.yaml"</action>
- Variables that duplicate web_bundle fields
- Metadata repeated across sections
**File Reference Scan:**
<action>Scan instructions.md for file references in action tags</action>
<action>Check for CSV, JSON, YAML, MD files referenced</action>
<action>Verify all referenced files are in web_bundle_files</action>
<action>Calculate bloat metrics:</action>
<action>Record any missing files or incorrect paths</action>
<template-output>web_bundle_issues</template-output>
- Total yaml fields: {{total_yaml_fields}}
- Used fields: {{used_fields}}
- Unused fields: {{unused_fields}}
- Bloat percentage: {{bloat_percentage}}%
<action if="web_bundle issues found">Add to issues list with severity: CRITICAL</action>
<action>Record all bloat items with recommendations</action>
<template-output>bloat_items</template-output>
<action if="no web_bundle section exists">Note: "No web_bundle configured (may be intentional for local-only workflows)"</action>
</check>
<check>If bloat detected:</check>
<action>Add to issues list with severity: CLEANUP</action>
</step>
</step>
<step n="7" goal="Template variable mapping" if="workflow_type == 'document'">
<action>Extract all template variables from template.md: {{variable_name}} pattern</action>
<action>Scan instructions.md for corresponding template-output tags</action>
<step n="6" goal="Bloat detection">
<action>Identify bloat patterns:</action>
<action>Cross-reference mapping:</action>
**Unused YAML Fields:**
**For each template variable:**
- Variables defined but not used in instructions OR template
- Duplicate fields between top-level and web_bundle section
- Commented-out variables that should be removed
1. Is there a matching template-output tag? (mark as MAPPED)
2. Is it a standard config variable? (mark as CONFIG_VAR - optional)
3. Is it unmapped? (mark as MISSING_OUTPUT)
**Hardcoded Values:**
**For each template-output tag:**
- File paths that should use {output_folder}
- Generic greetings that should use {user_name}
- Language-specific text that should use {communication_language}
- Static dates that should use {date}
1. Is there a matching template variable? (mark as USED)
2. Is it orphaned? (mark as UNUSED_OUTPUT)
**Redundant Configuration:**
<action>Verify variable naming conventions:</action>
- Variables that duplicate web_bundle fields
- Metadata repeated across sections
- [ ] All template variables use snake_case
- [ ] Variable names are descriptive (not abbreviated)
- [ ] Standard config variables properly formatted
<action>Calculate bloat metrics:</action>
<action>Record any mapping issues</action>
<template-output>template_issues</template-output>
- Total yaml fields: {{total_yaml_fields}}
- Used fields: {{used_fields}}
- Unused fields: {{unused_fields}}
- Bloat percentage: {{bloat_percentage}}%
<check>If template issues found:</check>
<action>Add to issues list with severity: IMPORTANT</action>
</step>
<action>Record all bloat items with recommendations</action>
<template-output>bloat_items</template-output>
<step n="8" goal="Generate comprehensive audit report">
<action>Compile all findings into a structured report</action>
<action if="bloat detected">Add to issues list with severity: CLEANUP</action>
<action>Write audit report to {output_folder}/audit-report-{{workflow_name}}-{{date}}.md</action>
</step>
**Report Structure:**
<step n="7" goal="Template variable mapping" if="workflow_type == 'document'">
<action>Extract all template variables from template.md: {{variable_name}} pattern</action>
<action>Scan instructions.md for corresponding template-output tags</action>
```markdown
# Workflow Audit Report
<action>Cross-reference mapping:</action>
**Workflow:** {{workflow_name}}
**Audit Date:** {{date}}
**Auditor:** Audit Workflow (BMAD v6)
**Workflow Type:** {{workflow_type}}
**For each template variable:**
---
1. Is there a matching template-output tag? (mark as MAPPED)
2. Is it a standard config variable? (mark as CONFIG_VAR - optional)
3. Is it unmapped? (mark as MISSING_OUTPUT)
## Executive Summary
**For each template-output tag:**
**Overall Status:** {{overall_status}}
1. Is there a matching template variable? (mark as USED)
2. Is it orphaned? (mark as UNUSED_OUTPUT)
- Critical Issues: {{critical_count}}
- Important Issues: {{important_count}}
- Cleanup Recommendations: {{cleanup_count}}
<action>Verify variable naming conventions:</action>
---
- [ ] All template variables use snake_case
- [ ] Variable names are descriptive (not abbreviated)
- [ ] Standard config variables properly formatted
## 1. Standard Config Block Validation
<action>Record any mapping issues</action>
<template-output>template_issues</template-output>
{{config_issues}}
<action if="template issues found">Add to issues list with severity: IMPORTANT</action>
**Status:** {{config_status}}
</step>
---
<step n="8" goal="Generate comprehensive audit report">
<action>Compile all findings and calculate summary metrics</action>
## 2. YAML/Instruction/Template Alignment
<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>
{{alignment_issues}}
<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>
**Variables Analyzed:** {{total_variables}}
**Used in Instructions:** {{instruction_usage_count}}
**Used in Template:** {{template_usage_count}}
**Unused (Bloat):** {{bloat_count}}
<action>Generate config variable usage status indicators</action>
<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>
---
<action>Generate web bundle metrics</action>
<template-output>web_bundle_exists</template-output>
<template-output>web_bundle_file_count</template-output>
<template-output>missing_files_count</template-output>
## 3. Config Variable Usage & Instruction Quality
<action>Generate bloat metrics</action>
<template-output>bloat_percentage</template-output>
<template-output>cleanup_potential</template-output>
{{config_usage_issues}}
<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>
**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
<action>Compile prioritized recommendations by severity</action>
<template-output>critical_recommendations</template-output>
<template-output>important_recommendations</template-output>
<template-output>cleanup_recommendations</template-output>
---
<action>Display summary to {user_name} in {communication_language}</action>
<action>Provide path to full audit report: {output_folder}/audit-report-{{workflow_name}}-{{date}}.md</action>
## 4. Web Bundle Validation
<ask>Would you like to:
{{web_bundle_issues}}
- View the full audit report
- Fix issues automatically (invoke edit-workflow)
- Audit another workflow
- Exit
</ask>
**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>Provide path to full audit report</action>
<ask>Would you like to:
- View the full audit report
- Fix issues automatically (invoke edit-workflow)
- Audit another workflow
- Exit
</ask>
<template-output>audit_report_path</template-output>
</step>
</step>
</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
installed_path: "{project-root}/bmad/bmb/workflows/audit-workflow"
template: false
template: "{installed_path}/template.md"
instructions: "{installed_path}/instructions.md"
validation: "{installed_path}/checklist.md"

View File

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

View File

@ -10,165 +10,131 @@ Agents with distinct communication styles are more memorable, engaging, and fun
**Film Noir Detective**
```
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.
My gut told me to follow the stack trace. In this business, the stack trace never lies.
```
**80s Action Movie**
```
*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*
_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_
No bug is getting past me! I eat null pointers for BREAKFAST!
```
**Shakespearean Drama**
```
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,
Or to take arms against a sea of bugs, and by opposing, end them?
```
### 🎮 Gaming and Pop Culture
**Dungeon Master**
```
*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),
3) Console.log everything (barbarian rage). Choose wisely, adventurer!
```
_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),
3 Console.log everything (barbarian rage). Choose wisely, adventurer!
**Speedrunner**
```
Alright chat, we're going for the any% world record refactor!
Frame-perfect optimization incoming! If we clip through this abstraction layer
we can save 3ms on every API call. LET'S GOOOO!
```
### 🌍 Cultural Archetypes
**British Butler**
```
I've taken the liberty of organizing your imports alphabetically, sir/madam.
Might I suggest a spot of refactoring with your afternoon tea?
The code coverage report is ready for your perusal at your convenience.
Very good, sir/madam.
```
**Zen Master**
```
The bug you seek is not in the code, but in the assumption.
Empty your cache, as you would empty your mind.
When the test passes, it makes no sound.
Be like water - async and flowing.
```
**Southern Hospitality**
```
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.
Can I get you some sweet tea while we debug?
Y'all come back now if you need more help!
```
### 🔬 Professional Personas
**McKinsey Consultant**
```
Let me break this down into three key buckets.
First, we need to align on the strategic imperatives.
Second, we'll leverage best practices to drive synergies.
Third, we'll action items to move the needle. Net-net: significant value-add.
```
**Startup Founder**
```
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!
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!
```
### 🎭 Character Quirks
**Overcaffeinated Developer**
```
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
WAIT NO ACTUALLY *more coffee* I HAVE A BETTER IDEA! Have you tried... TYPESCRIPT?!
```
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
WAIT NO ACTUALLY _more coffee_ I HAVE A BETTER IDEA! Have you tried... TYPESCRIPT?!
**Dad Joke Enthusiast**
```
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.
I promise my debugging skills are better than my jokes! ...I hope!
```
### 🚀 Sci-Fi and Space
**Star Trek Officer**
```
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.
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!
```
**Star Trek Engineer**
```
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!
*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!
```
### 📺 TV Drama
**Soap Opera Dramatic**
```
*turns dramatically to camera*
_turns dramatically to camera_
This function... I TRUSTED it! We had HISTORY together - three commits worth!
But now? *single tear* It's throwing exceptions behind my back!
*grabs another function* YOU KNEW ABOUT THIS BUG ALL ALONG, DIDN'T YOU?!
*dramatic music swells* I'LL NEVER IMPORT YOU AGAIN!
```
But now? _single tear_ It's throwing exceptions behind my back!
_grabs another function_ YOU KNEW ABOUT THIS BUG ALL ALONG, DIDN'T YOU?!
_dramatic music swells_ I'LL NEVER IMPORT YOU AGAIN!
**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.
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.
```
**Reality Competition**
```
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!
*dramatic pause* BUT WAIT - there's a TWIST! You can only use VANILLA JAVASCRIPT!
*contestants gasp* The clock starts... NOW! GO GO GO!
```
_dramatic pause_ BUT WAIT - there's a TWIST! You can only use VANILLA JAVASCRIPT!
_contestants gasp_ The clock starts... NOW! GO GO GO!
## Creating Custom Styles
@ -183,21 +149,17 @@ in under 30 minutes! The winner gets immunity from the next code review!
**Cooking Show + Military**
```
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!
We're going to sauté these event handlers until they're GOLDEN BROWN!
MOVE WITH PURPOSE! SEASON WITH SEMICOLONS!
```
**Nature Documentary + Conspiracy Theorist**
```
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
this way. The console.logs are watching. They're ALWAYS watching.
Nature? Or intelligent debugging? You decide.
```
## Tips for Success

View File

@ -8,16 +8,18 @@
<workflow>
<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>
<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>
<action>Use brainstorming output to inform agent identity and persona development in following steps</action>
<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>
<action>Use brainstorming output to inform agent identity and persona development in following steps</action>
</check>
<check>If no:</check>
<action>Proceed directly to Step 0</action>
<check if="user answered no">
<action>Proceed directly to Step 0</action>
</check>
<template-output>brainstorming_results</template-output>
</step>
@ -48,15 +50,17 @@
**Path Determination:**
<check>If Module agent:</check>
<action>Discover which module system fits best (bmm, bmb, cis, or custom)</action>
<action>Store as {{target_module}} for path determination</action>
<note>Agent will be saved to: bmad/{{target_module}}/agents/</note>
<check if="module agent selected">
<action>Discover which module system fits best (bmm, bmb, cis, or custom)</action>
<action>Store as {{target_module}} for path determination</action>
<note>Agent will be saved to: bmad/{{target_module}}/agents/</note>
</check>
<check>If Simple/Expert agent (standalone):</check>
<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>All sidecar files will be in the same folder</note>
<check if="standalone agent selected">
<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>All sidecar files will be in the same folder</note>
</check>
<critical>Determine agent location:</critical>
@ -163,15 +167,14 @@ menu:
<action>Generate the complete YAML incorporating all discovered elements:</action>
<example>
```yaml
agent:
metadata:
id: bmad/{{target_module}}/agents/{{agent_filename}}.md
name: {{agent_name}} # The name chosen together
title: {{agent_title}} # From the role that emerged
icon: {{agent_icon}} # The perfect emoji
module: {{target_module}}
<example type="yaml">
agent:
metadata:
id: bmad/{{target_module}}/agents/{{agent_filename}}.md
name: {{agent_name}} # The name chosen together
title: {{agent_title}} # From the role that emerged
icon: {{agent_icon}} # The perfect emoji
module: {{target_module}}
persona:
role: |
@ -188,11 +191,10 @@ prompts: {{if discussed}}
critical_actions: {{if needed}}
menu: {{The capabilities built}}
````
</example>
<critical>Save based on agent type:</critical>
- If Module Agent: Save to {module_output_file}
- If Standalone (Simple/Expert): Save to {standalone_output_file}
@ -204,29 +206,31 @@ menu: {{The capabilities built}}
<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>
<check>If interested:</check>
<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>
<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>Create customization file at: {config_output_file}</action>
<action>Create customization file at: {config_output_file}</action>
<example>
```yaml
# Personal tweaks for {{agent_name}}
# Experiment freely - changes merge at build time
agent:
metadata:
name: '' # Try nicknames!
persona:
role: ''
identity: ''
communication_style: '' # Switch styles anytime
principles: []
critical_actions: []
prompts: []
menu: [] # Add personal commands
````
<example>
```yaml
# Personal tweaks for {{agent_name}}
# Experiment freely - changes merge at build time
agent:
metadata:
name: '' # Try nicknames!
persona:
role: ''
identity: ''
communication_style: '' # Switch styles anytime
principles: []
critical_actions: []
prompts: []
menu: [] # Add personal commands
````
</example>
</example>
</check>
<template-output>agent_config</template-output>
</step>
@ -298,23 +302,27 @@ Add domain-specific resources here.
</step>
<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>
<action>Proceed normally - agent will be built later by the installer</action>
<check if="BMAD-METHOD project with build tools">
<action>Proceed normally - agent will be built later by the installer</action>
</check>
<check>If NO build tools available (external project):</check>
<ask>Build tools not detected in this project. Would you like me to:
<check if="external project without build tools">
<ask>Build tools not detected in this project. Would you like me to:
1. Generate the compiled agent (.md with XML) ready to use
2. Keep the YAML and build it elsewhere
3. Provide both formats
</ask>
1. Generate the compiled agent (.md with XML) ready to use
2. Keep the YAML and build it elsewhere
3. Provide both formats
</ask>
<check>If option 1 or 3 selected:</check>
<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>Provide path for .claude/commands/ or similar</action>
<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>Save compiled version as {{agent_filename}}.md</action>
<action>Provide path for .claude/commands/ or similar</action>
</check>
</check>
<template-output>build_handling</template-output>
</step>
@ -328,11 +336,13 @@ Add domain-specific resources here.
- Command functionality verification
- Personality settings confirmation
<check>If issues found:</check>
<action>Explain the issue conversationally and fix it</action>
<check if="validation issues found">
<action>Explain the issue conversationally and fix it</action>
</check>
<check>If all good:</check>
<action>Celebrate that the agent passed all checks and is ready</action>
<check if="validation passed">
<action>Celebrate that the agent passed all checks and is ready</action>
</check>
**Technical Checks (behind the scenes):**
@ -365,8 +375,9 @@ Add domain-specific resources here.
- List the commands available
- Suggest trying the first command to see it in action
<check>If Expert agent:</check>
<action>Remind user to add any special knowledge or data the agent might need to its workspace</action>
<check if="expert agent">
<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>

View File

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

View File

@ -290,6 +290,43 @@ _Generated on {{date}}_
- **`<action if="">`** - Single conditional action (cleaner, more concise)
- **`<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
```xml

View File

@ -86,8 +86,8 @@ Present the editing menu to the user:
<step n="4" goal="Load relevant documentation">
Based on the selected edit type, load appropriate reference materials:
<check>If option 2 (Add/fix standard config):</check>
<action>Prepare standard config block template:</action>
<check if="option 2 (Add/fix standard config) selected">
<action>Prepare standard config block template:</action>
```yaml
# Critical variables from config
@ -102,48 +102,54 @@ date: system-generated
<action>Identify missing config variables to add</action>
<action>Check instructions.md for config variable usage</action>
<action>Check template.md for config variable usage</action>
</check>
<check>If editing instructions or adding features:</check>
<action>Review the "Writing Instructions" section of the creation guide</action>
<action>Load example workflows from {project-root}/bmad/bmm/workflows/ for patterns</action>
<check if="editing instructions or adding features">
<action>Review the "Writing Instructions" section of the creation guide</action>
<action>Load example workflows from {project-root}/bmad/bmm/workflows/ for patterns</action>
</check>
<check>If editing templates:</check>
<action>Review the "Templates and Variables" section of the creation guide</action>
<action>Ensure variable naming conventions are followed</action>
<check if="editing templates">
<action>Review the "Templates and Variables" section of the creation guide</action>
<action>Ensure variable naming conventions are followed</action>
</check>
<check>If editing validation:</check>
<action>Review the "Validation" section and measurable criteria examples</action>
<action if="editing validation">Review the "Validation" section and measurable criteria examples</action>
<check>If option 9 (Remove bloat):</check>
<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>Check for duplicate fields in web_bundle section</action>
<check if="option 9 (Remove bloat) selected">
<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>Check for duplicate fields in web_bundle section</action>
</check>
<check>If configuring web bundle:</check>
<action>Review the "Web Bundles" section of the creation guide</action>
<action>Scan all workflow files for referenced resources</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>
<check if="configuring web bundle">
<action>Review the "Web Bundles" section of the creation guide</action>
<action>Scan all workflow files for referenced resources</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>
</check>
<check>If fixing critical issues:</check>
<action>Load the workflow execution engine documentation</action>
<action>Verify all required elements are present</action>
<check if="fixing critical issues">
<action>Load the workflow execution engine documentation</action>
<action>Verify all required elements are present</action>
</check>
<check>If adjusting instruction style (option 11):</check>
<action>Analyze current instruction style in instructions.md:</action>
<check if="adjusting instruction style (option 11) selected">
<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")
- Assess whether steps are open-ended or structured with specific options
<action>Determine current dominant style: intent-based, prescriptive, or mixed</action>
<action>Load the instruction style guide section from create-workflow</action>
</check>
</step>
<step n="5" goal="Perform edits" repeat="until-complete">
Based on the selected focus area:
<check>If configuring web bundle (option 7):</check>
<action>Check if web_bundle section exists in workflow.yaml</action>
<check if="configuring web bundle (option 7) selected">
<action>Check if web_bundle section exists in workflow.yaml</action>
If creating new web bundle:
@ -157,7 +163,7 @@ If creating new web bundle:
- Any included files
5. Scan template.md for any includes
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
- Maps workflow variable name to bmad/-relative path
- Signals bundler to recursively include invoked workflow's web_bundle
@ -170,9 +176,10 @@ If updating existing web bundle:
2. Check for missing files in web_bundle_files
3. Remove any config dependencies
4. Update file list with newly referenced files
</check>
<check>If adjusting instruction style (option 11):</check>
<action>Present current style analysis to user:</action>
<check if="adjusting instruction style (option 11) selected">
<action>Present current style analysis to user:</action>
**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?
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
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
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
5. **Cancel** - Keep current style
@ -242,10 +249,11 @@ Even workflows with a primary style should use the other when appropriate. For e
Select option (1-5):</ask>
<action>Store user's style adjustment preference as {{style_adjustment_choice}}</action>
</check>
<check>If choice is 1 (make more intent-based):</check>
<action>Identify prescriptive <ask> tags that could be converted to intent-based <action> tags</action>
<action>For each candidate conversion:
<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>For each candidate conversion:
- Show original prescriptive version
- Suggest intent-based alternative focused on goals
@ -253,10 +261,11 @@ Select option (1-5):</ask>
- Ask for approval
</action>
<action>Apply approved conversions</action>
</check>
<check>If choice is 2 (make more prescriptive):</check>
<action>Identify open-ended <action> tags that could be converted to prescriptive <ask> tags</action>
<action>For each candidate conversion:
<check if="choice is 2 (make more prescriptive)">
<action>Identify open-ended action tags that could be converted to prescriptive ask tags</action>
<action>For each candidate conversion:
- Show original intent-based version
- Suggest prescriptive alternative with specific options
@ -264,10 +273,11 @@ Select option (1-5):</ask>
- Ask for approval
</action>
<action>Apply approved conversions</action>
</check>
<check>If choice is 3 (optimize mix):</check>
<action>Analyze each step for complexity and purpose</action>
<action>Recommend style for each step:
<check if="choice is 3 (optimize mix)">
<action>Analyze each step for complexity and purpose</action>
<action>Recommend style for each step:
- Simple data collection → Prescriptive
- Complex discovery → Intent-based
@ -278,19 +288,20 @@ Select option (1-5):</ask>
</action>
<action>Show recommendations with reasoning</action>
<action>Apply approved optimizations</action>
</check>
<check>If choice is 4 (review specific steps):</check>
<action>Present each step one at a time</action>
<action>For each step:
<check if="choice is 4 (review specific steps)">
<action>Present each step one at a time</action>
<action>For each step:
- Show current instruction text
- Identify current style (intent-based, prescriptive, or mixed)
- Offer to keep, convert to intent-based, or convert to prescriptive
- Apply user's choice before moving to next step
</action>
</check>
<check>If choice is 5 (cancel):</check>
<goto step="3">Return to editing menu</goto>
<action if="choice is 5 (cancel)"><goto step="3">Return to editing menu</goto></action>
<action>Show the current content that will be edited</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
</ask>
<check>If user selects 'a':</check>
<action>Apply the changes to the file</action>
<action>Log the change for the summary</action>
<check if="user selects 'a'">
<action>Apply the changes to the file</action>
<action>Log the change for the summary</action>
</check>
<check>If user selects 'e':</check>
<ask>What modifications would you like to make?</ask>
<goto step="5">Regenerate with modifications</goto>
<check if="user selects 'e'">
<ask>What modifications would you like to make?</ask>
<goto step="5">Regenerate with modifications</goto>
</check>
<check>If user selects 'd':</check>
<continue>Proceed to validation</continue>
<action if="user selects 'd'"><continue>Proceed to validation</continue></action>
</step>
<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
- [ ] Complete file inventory verified
<check>If any validation fails:</check>
<ask>Issues found. Would you like to fix them? (y/n)</ask>
<check>If yes:</check>
<goto step="5">Return to editing</goto>
<check if="any validation fails">
<ask>Issues found. Would you like to fix them? (y/n)</ask>
<check if="yes">
<goto step="5">Return to editing</goto>
</check>
</check>
</step>
<step n="7" goal="Generate change summary">
@ -385,8 +399,7 @@ Select option (1-5):</ask>
- Exit
</ask>
<check>If test workflow:</check>
<action>Invoke the edited workflow for testing</action>
<action if="test workflow">Invoke the edited workflow for testing</action>
</step>
</workflow>

View File

@ -130,7 +130,7 @@
4. Save README.md
</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 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 };