Compare commits

...

6 Commits

Author SHA1 Message Date
Mario Semper 34e1af2d4c
Merge 4d48b0dbe1 into 5ee1551b5b 2025-12-06 06:13:24 -05:00
Alex Verkhovsky 5ee1551b5b
fix(bmm): remove stale validate-prd references (fixes #1030) (#1038)
- Remove validate-prd workflow references from all workflow path YAML files
- Update Excalidraw diagram: remove Validate PRD box and zombie JSON elements
- Re-export SVG at 1x scale
- Standardize implementation-readiness descriptions across all docs
- Add validation script (validate-svg-changes.sh) and README for SVG export process
- Correct Excalidraw timestamps

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Brian <bmadcode@gmail.com>
2025-12-05 21:35:46 -06:00
Alex Verkhovsky c95b65f462
fix(bmm): correct code-review workflow status logic and checklist (#1015) (#1028)
- Fix checklist to only accept 'review' status (not 'ready-for-review')
- Include MEDIUM issues in done/in-progress status determination
- Initialize and track fixed_count/action_count variables for summary
- Add sprint-status.yaml sync when story status changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-05 21:27:11 -06:00
Nguyen Quang Huy 72ef9e9722
fix: use backticks for quoted phrase in code-review description (#1025)
Replace 'looks good' with `looks good` to avoid nested single quote
issues when IDEs generate command files from workflow YAML.

Co-authored-by: Brian <bmadcode@gmail.com>
2025-12-05 21:26:04 -06:00
Brian 4d48b0dbe1
Merge branch 'main' into feature/ring-of-fire-sessions 2025-11-26 09:08:27 -06:00
Mario Semper 10dc25f43d feat: Ring of Fire (ROF) Sessions - Multi-agent parallel collaboration
Introduces Ring of Fire Sessions feature for BMad Method, enabling
multi-agent collaborative sessions that run in parallel to user workflow.

Key features:
- User-controlled scope (2 agents/5min to 10 agents/2hrs)
- Approval-gated tool access for safety
- Flexible reporting (brief/detailed/live)
- Parallel workflow support

Origin: tellingCube project (masemIT e.U.)
Real-world validated with successful multi-agent planning sessions.

Command: *rof "<topic>" --agents <list> [--report mode]
2025-11-23 02:22:21 +01:00
15 changed files with 784 additions and 248 deletions

View File

@ -0,0 +1,256 @@
# BMad Method PR #1: Ring of Fire (ROF) Sessions
**Feature Type**: Core workflow enhancement
**Status**: Draft for community review
**Origin**: tellingCube project (masemIT e.U.)
**Author**: Mario Semper (@sempre)
**Date**: 2025-11-23
---
## Summary
**Ring of Fire (ROF) Sessions** enable multi-agent collaborative sessions that run in parallel to the user's main workflow, allowing users to delegate complex multi-perspective analysis while continuing other work.
---
## Problem Statement
Current BMad Method requires **sequential agent interaction**. When users need multiple agents to collaborate on a complex topic, they must:
- Manually orchestrate each agent conversation
- Stay in the loop for every exchange
- Wait for sequential responses before proceeding
- Context-switch constantly between tasks
This creates **bottlenecks** and prevents **parallel work streams**.
---
## Proposed Solution: Ring of Fire Sessions
A new command pattern that enables **scoped multi-agent collaboration sessions** that run while the user continues other work.
### Command Syntax
```bash
*rof "<topic>" --agents <agent-list> [--report brief|detailed|live]
```
### Example Usage
```bash
*rof "API Refactoring Strategy" --agents dev,architect,qa --report brief
```
**What happens**:
1. Dev, Architect, and QA agents enter a collaborative session
2. They analyze the topic together (code review, design discussion, testing concerns)
3. When agents need tool access (read files, run commands), they request user approval
4. User continues working on other tasks in parallel
5. Session ends with consolidated report (brief: just recommendations, detailed: full transcript)
---
## Key Features
### 1. User-Controlled Scope
- **Small**: 2 agents, 5-minute quick discussion
- **Large**: 10 agents, 2-hour deep analysis
- User decides granularity based on complexity
### 2. Approval-Gated Tool Access
- Agents can **discuss** freely within the session
- When agents need **tools** (read files, execute commands, make changes), they:
- Pause the session
- Request user approval
- Resume after user decision
**Why**: Maintains user control, prevents runaway agent actions
### 3. Flexible Reporting
| Mode | Description | Use Case |
|------|-------------|----------|
| `brief` | Final recommendations only | "Just tell me what to do" |
| `detailed` | Full transcript + recommendations | "Show me the reasoning" |
| `live` | Real-time updates as agents discuss | "I want to observe" |
**Default**: `brief` with Q&A available
### 4. Parallel Workflows
- User works on **Task A** while ROF session tackles **Task B**
- No context-switching overhead
- Efficient use of time
---
## Use Cases
### 1. Architecture Reviews
```bash
*rof "Evaluate microservices vs monolith for new feature" --agents architect,dev,qa
```
**Agents collaborate on**: Design trade-offs, implementation complexity, testing implications
### 2. Code Refactoring
```bash
*rof "Refactor authentication module" --agents dev,architect --report detailed
```
**Agents collaborate on**: Current code analysis, refactoring approach, migration strategy
### 3. Feature Planning
```bash
*rof "Plan user notifications feature" --agents pm,ux,dev --report brief
```
**Agents collaborate on**: Requirements, UX flow, technical feasibility, timeline
### 4. Quality Gates
```bash
*rof "Investigate test failures in CI/CD" --agents qa,dev --report live
```
**Agents collaborate on**: Root cause analysis, fix recommendations, regression prevention
### 5. Documentation Sprints
```bash
*rof "Document API endpoints" --agents dev,pm,ux
```
**Agents collaborate on**: Technical accuracy, user-friendly examples, completeness
---
## User Experience Flow
```mermaid
sequenceDiagram
User->>River: *rof "Topic" --agents dev,architect
River->>Dev: Join ROF session
River->>Architect: Join ROF session
River->>User: Session started, continue your work
Dev->>Architect: Discuss approach
Architect->>Dev: Suggest alternatives
Dev->>User: Need to read auth.ts - approve?
User->>Dev: Approved
Dev->>Architect: After reading file...
Architect->>Dev: Recommendation
Dev->>River: Session complete
River->>User: Brief report: [Recommendations]
```
---
## Implementation Considerations
### Technical Requirements
- **Session state management**: Track active ROF sessions, participating agents
- **Agent context sharing**: Agents share knowledge within session scope
- **User approval workflow**: Clear prompt for tool requests
- **Report generation**: Brief/detailed/live output formatting
- **Workflow integration**: Link ROF findings to existing workflow plans/todos
### Open Questions for Community
1. **Integration**: Core BMad feature or plugin/extension?
2. **Concurrency**: How to handle file conflicts if multiple agents want to edit?
3. **Cost Model**: Guidance for LLM call budgeting with multiple agents?
4. **Session Limits**: Recommended max agents/duration?
5. **Agent Communication**: Free-form discussion or structured turn-taking?
---
## Real-World Validation
**Origin Project**: tellingCube (BI dashboard, masemIT e.U.)
**Validation Scenario**:
- **Topic**: "Next steps for tellingCube after validation test"
- **Agents**: River (orchestrator), Mary (analyst), Winston (architect)
- **Report Mode**: Brief
- **Outcome**: Successfully analyzed post-validation roadmap with 3 scenarios (GO/CHANGE/NO-GO), delivered consolidated recommendations in 5 minutes
**User Feedback (Mario Semper)**:
> "This is exactly what I needed - I wanted multiple perspectives without having to orchestrate every conversation. The brief report gave me actionable next steps immediately."
**Documentation**: `docs/_masemIT/readme.md` in tellingCube repository
---
## Proposed Documentation Structure
```
.bmad-core/
features/
ring-of-fire.md # Feature specification
docs/
guides/
using-rof-sessions.md # User guide with examples
architecture/
agent-collaboration.md # Technical design
rof-session-management.md # State handling approach
```
---
## Benefits
**Unlocks parallel workflows** - User productivity gains
**Reduces context-switching** - Cognitive load reduction
**Enables complex analysis** - Multi-perspective insights
**Maintains user control** - Approval gates for tools
**Scales flexibly** - From quick checks to deep dives
---
## Comparison to Existing Patterns
| Feature | Standard Agent Use | ROF Session |
|---------|-------------------|-------------|
| Agent collaboration | Sequential (one at a time) | Parallel (multiple simultaneously) |
| User involvement | Required for every exchange | Only for approvals |
| Parallel work | No (user waits) | Yes (user continues tasks) |
| Output | Chat transcript | Consolidated report |
| Use case | Single-perspective tasks | Multi-perspective analysis |
---
## Next Steps
1. **Community feedback** on approach and open questions
2. **Technical design** refinement (state management, agent communication)
3. **Prototype implementation** in BMad core or as extension
4. **Beta testing** with real projects (beyond tellingCube)
5. **Documentation** completion with examples
---
## Alternatives Considered
### Alt 1: "Breakout Session"
- **Pros**: Clear meeting metaphor
- **Cons**: Less evocative, doesn't convey "continuous collaborative space"
### Alt 2: "Agent Huddle"
- **Pros**: Short, casual
- **Cons**: Implies quick/informal only
### Alt 3: "Lagerfeuer" (original German name)
- **Pros**: Warm, campfire metaphor
- **Cons**: Poor i18n, hard to pronounce/remember for non-German speakers
**Chosen**: **Ring of Fire** - evokes continuous collaboration circle, internationally understood, memorable, shortcut "ROF" works well
---
## References
- **Source Project**: tellingCube (https://github.com/masemIT/telling-cube) [if public]
- **Documentation**: `docs/_masemIT/readme.md`
- **Discussion**: [Link to BMad community discussion if applicable]
---
**Contribution ready for review.** Feedback welcome! 🔥

View File

@ -76,8 +76,7 @@ The BMad Method Module (BMM) provides a comprehensive team of specialized AI age
- `create-prd` - Create PRD for Level 2-4 projects (creates FRs/NFRs only) - `create-prd` - Create PRD for Level 2-4 projects (creates FRs/NFRs only)
- `tech-spec` - Quick spec for Level 0-1 projects - `tech-spec` - Quick spec for Level 0-1 projects
- `create-epics-and-stories` - Break PRD into implementable pieces (runs AFTER architecture) - `create-epics-and-stories` - Break PRD into implementable pieces (runs AFTER architecture)
- `validate-prd` - Validate PRD completeness - `implementation-readiness` - Validate PRD + Architecture + Epics + UX (optional)
- `validate-tech-spec` - Validate Technical Specification
- `correct-course` - Handle mid-project changes - `correct-course` - Handle mid-project changes
- `workflow-init` - Initialize workflow tracking - `workflow-init` - Initialize workflow tracking
@ -146,7 +145,7 @@ The BMad Method Module (BMM) provides a comprehensive team of specialized AI age
- `workflow-status` - Check what to do next - `workflow-status` - Check what to do next
- `create-architecture` - Produce a Scale Adaptive Architecture - `create-architecture` - Produce a Scale Adaptive Architecture
- `validate-architecture` - Validate architecture document - `validate-architecture` - Validate architecture document
- `implementation-readiness` - Validate readiness for Phase 4 - `implementation-readiness` - Validate PRD + Architecture + Epics + UX (optional)
**Communication Style:** Comprehensive yet pragmatic. Uses architectural metaphors. Balances technical depth with accessibility. Connects decisions to business value. **Communication Style:** Comprehensive yet pragmatic. Uses architectural metaphors. Balances technical depth with accessibility. Connects decisions to business value.
@ -643,9 +642,8 @@ Some workflows are available to multiple agents:
Many workflows have optional validation workflows that perform independent review: Many workflows have optional validation workflows that perform independent review:
| Validation | Agent | Validates | | Validation | Agent | Validates |
| ----------------------- | ----------- | -------------------------------- | | -------------------------- | ----------- | ------------------------------------------ |
| `validate-prd` | PM | PRD completeness (FRs/NFRs only) | | `implementation-readiness` | Architect | PRD + Architecture + Epics + UX (optional) |
| `validate-tech-spec` | PM | Technical specification quality |
| `validate-architecture` | Architect | Architecture document | | `validate-architecture` | Architect | Architecture document |
| `validate-design` | UX Designer | UX specification and artifacts | | `validate-design` | UX Designer | UX specification and artifacts |
| `validate-create-story` | SM | Story draft | | `validate-create-story` | SM | Story draft |
@ -945,9 +943,8 @@ Agent analyzes project state → recommends next workflow
``` ```
Each phase has validation gates: Each phase has validation gates:
- Phase 2 to 3: validate-prd, validate-tech-spec - Phase 3 to 4: implementation-readiness (validates PRD + Architecture + Epics + UX (optional))
- Phase 3 to 4: implementation-readiness Run validation before advancing to implementation
Run validation before advancing
``` ```
**Course correction:** **Course correction:**

View File

@ -147,7 +147,7 @@ If status file exists, use workflow-status. If not, use workflow-init.
### Q: How do I know when Phase 3 is complete and I can start Phase 4? ### Q: How do I know when Phase 3 is complete and I can start Phase 4?
**A:** For Level 3-4, run the implementation-readiness workflow. It validates that PRD (FRs/NFRs), architecture, epics+stories, and UX (if applicable) are cohesive before implementation. Pass the gate check = ready for Phase 4. **A:** For Level 3-4, run the implementation-readiness workflow. It validates PRD + Architecture + Epics + UX (optional) are aligned before implementation. Pass the gate check = ready for Phase 4.
### Q: Can I run workflows in parallel or do they have to be sequential? ### Q: Can I run workflows in parallel or do they have to be sequential?

View File

@ -246,7 +246,7 @@ Workflow that initializes Phase 4 implementation by creating sprint-status.yaml,
### Gate Check ### Gate Check
Validation workflow (implementation-readiness) run before Phase 4 to ensure PRD, architecture, and UX documents are cohesive with no gaps or contradictions. Required for BMad Method and Enterprise Method tracks. Validation workflow (implementation-readiness) run before Phase 4 to ensure PRD + Architecture + Epics + UX (optional) are aligned with no gaps or contradictions. Required for BMad Method and Enterprise Method tracks.
### DoD (Definition of Done) ### DoD (Definition of Done)

View File

@ -0,0 +1,37 @@
# Workflow Diagram Maintenance
## Regenerating SVG from Excalidraw
When you edit `workflow-method-greenfield.excalidraw`, regenerate the SVG:
1. Open https://excalidraw.com/
2. Load the `.excalidraw` file
3. Click menu (☰) → Export image → SVG
4. **Set "Scale" to 1x** (default is 2x)
5. Click "Export"
6. Save as `workflow-method-greenfield.svg`
7. **Validate the changes** (see below)
8. Commit both files together
**Important:**
- Always use **1x scale** to maintain consistent dimensions
- Automated export tools (`excalidraw-to-svg`) are broken - use manual export only
## Visual Validation
After regenerating the SVG, validate that it renders correctly:
```bash
./tools/validate-svg-changes.sh src/modules/bmm/docs/images/workflow-method-greenfield.svg
```
This script:
- Checks for required dependencies (Playwright, ImageMagick)
- Installs Playwright locally if needed (no package.json pollution)
- Renders old vs new SVG using browser-accurate rendering
- Compares pixel-by-pixel and generates a diff image
- Outputs a prompt for AI visual analysis (paste into Gemini/Claude)
**Threshold**: <0.01% difference is acceptable (anti-aliasing variations)

View File

@ -1036,10 +1036,6 @@
"type": "arrow", "type": "arrow",
"id": "arrow-discovery-no" "id": "arrow-discovery-no"
}, },
{
"type": "arrow",
"id": "arrow-prd-validate"
},
{ {
"id": "arrow-phase1-to-phase2", "id": "arrow-phase1-to-phase2",
"type": "arrow" "type": "arrow"
@ -1055,17 +1051,21 @@
{ {
"id": "arrow-has-ui-no", "id": "arrow-has-ui-no",
"type": "arrow" "type": "arrow"
},
{
"id": "arrow-prd-hasui",
"type": "arrow"
} }
], ],
"locked": false, "locked": false,
"version": 107, "version": 108,
"versionNonce": 930129274, "versionNonce": 930129275,
"index": "aN", "index": "aN",
"isDeleted": false, "isDeleted": false,
"strokeStyle": "solid", "strokeStyle": "solid",
"seed": 1, "seed": 1,
"frameId": null, "frameId": null,
"updated": 1764191563350, "updated": 1764952855000,
"link": null "link": null
}, },
{ {
@ -1107,197 +1107,6 @@
"autoResize": true, "autoResize": true,
"lineHeight": 1.25 "lineHeight": 1.25
}, },
{
"id": "arrow-prd-validate",
"type": "arrow",
"x": 439.4640518625828,
"y": 331.0450590268819,
"width": 0.17283039375342923,
"height": 28.50332681186643,
"angle": 0,
"strokeColor": "#1976d2",
"backgroundColor": "transparent",
"fillStyle": "solid",
"strokeWidth": 2,
"roughness": 0,
"opacity": 100,
"groupIds": [],
"startBinding": {
"elementId": "proc-prd",
"focus": 0,
"gap": 1
},
"endBinding": {
"elementId": "proc-validate-prd",
"focus": 0,
"gap": 1
},
"points": [
[
0,
0
],
[
0.17283039375342923,
28.50332681186643
]
],
"lastCommittedPoint": null,
"version": 102,
"versionNonce": 1274591910,
"index": "aP",
"isDeleted": false,
"strokeStyle": "solid",
"seed": 1,
"frameId": null,
"roundness": null,
"boundElements": [],
"updated": 1764191023838,
"link": null,
"locked": false,
"startArrowhead": null,
"endArrowhead": "arrow"
},
{
"id": "proc-validate-prd",
"type": "rectangle",
"x": 360,
"y": 360,
"width": 160,
"height": 80,
"angle": 0,
"strokeColor": "#43a047",
"backgroundColor": "#c8e6c9",
"fillStyle": "solid",
"strokeWidth": 2,
"roughness": 0,
"opacity": 100,
"roundness": {
"type": 3,
"value": 8
},
"groupIds": [
"proc-validate-prd-group"
],
"boundElements": [
{
"type": "text",
"id": "proc-validate-prd-text"
},
{
"type": "arrow",
"id": "arrow-prd-validate"
},
{
"type": "arrow",
"id": "arrow-validate-prd-hasui"
},
{
"id": "jv0rnlK2D9JKIGTO7pUtT",
"type": "arrow"
}
],
"locked": false,
"version": 3,
"versionNonce": 894806650,
"index": "aQ",
"isDeleted": false,
"strokeStyle": "solid",
"seed": 1,
"frameId": null,
"updated": 1764191341774,
"link": null
},
{
"id": "proc-validate-prd-text",
"type": "text",
"x": 370,
"y": 375,
"width": 140,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
"fillStyle": "solid",
"strokeWidth": 2,
"roughness": 0,
"opacity": 100,
"groupIds": [
"proc-validate-prd-group"
],
"fontSize": 14,
"fontFamily": 1,
"text": "Validate PRD\n<<optional>>",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "proc-validate-prd",
"locked": false,
"version": 2,
"versionNonce": 944332155,
"index": "aR",
"isDeleted": false,
"strokeStyle": "solid",
"seed": 1,
"frameId": null,
"roundness": null,
"boundElements": [],
"updated": 1763522171080,
"link": null,
"originalText": "Validate PRD\n<<optional>>",
"autoResize": true,
"lineHeight": 1.7857142857142858
},
{
"id": "arrow-validate-prd-hasui",
"type": "arrow",
"x": 440,
"y": 440,
"width": 0,
"height": 30,
"angle": 0,
"strokeColor": "#1976d2",
"backgroundColor": "transparent",
"fillStyle": "solid",
"strokeWidth": 2,
"roughness": 0,
"opacity": 100,
"groupIds": [],
"startBinding": {
"elementId": "proc-validate-prd",
"focus": 0,
"gap": 1
},
"endBinding": {
"elementId": "decision-has-ui",
"focus": 0,
"gap": 1
},
"points": [
[
0,
0
],
[
0,
30
]
],
"lastCommittedPoint": null,
"version": 2,
"versionNonce": 1369541557,
"index": "aS",
"isDeleted": false,
"strokeStyle": "solid",
"seed": 1,
"frameId": null,
"roundness": null,
"boundElements": [],
"updated": 1763522171080,
"link": null,
"locked": false,
"startArrowhead": null,
"endArrowhead": "arrow"
},
{ {
"id": "decision-has-ui", "id": "decision-has-ui",
"type": "diamond", "type": "diamond",
@ -1322,7 +1131,7 @@
}, },
{ {
"type": "arrow", "type": "arrow",
"id": "arrow-validate-prd-hasui" "id": "arrow-prd-hasui"
}, },
{ {
"type": "arrow", "type": "arrow",
@ -1334,15 +1143,15 @@
} }
], ],
"locked": false, "locked": false,
"version": 2, "version": 3,
"versionNonce": 1003877915, "versionNonce": 1003877916,
"index": "aT", "index": "aT",
"isDeleted": false, "isDeleted": false,
"strokeStyle": "solid", "strokeStyle": "solid",
"seed": 1, "seed": 1,
"frameId": null, "frameId": null,
"roundness": null, "roundness": null,
"updated": 1763522171080, "updated": 1764952855000,
"link": null "link": null
}, },
{ {
@ -5162,6 +4971,57 @@
"startArrowhead": null, "startArrowhead": null,
"endArrowhead": "arrow", "endArrowhead": "arrow",
"elbowed": false "elbowed": false
},
{
"id": "arrow-prd-hasui",
"type": "arrow",
"x": 440,
"y": 330,
"width": 0,
"height": 140,
"angle": 0,
"strokeColor": "#1976d2",
"backgroundColor": "transparent",
"fillStyle": "solid",
"strokeWidth": 2,
"roughness": 0,
"opacity": 100,
"groupIds": [],
"startBinding": {
"elementId": "proc-prd",
"focus": 0,
"gap": 1
},
"endBinding": {
"elementId": "decision-has-ui",
"focus": 0,
"gap": 1
},
"points": [
[
0,
0
],
[
0,
140
]
],
"lastCommittedPoint": null,
"version": 1,
"versionNonce": 1,
"index": "b1J",
"isDeleted": false,
"strokeStyle": "solid",
"seed": 1,
"frameId": null,
"roundness": null,
"boundElements": [],
"updated": 1764952855000,
"link": null,
"locked": false,
"startArrowhead": null,
"endArrowhead": "arrow"
} }
], ],
"appState": { "appState": {

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 87 KiB

View File

@ -1,7 +1,7 @@
# Senior Developer Review - Validation Checklist # Senior Developer Review - Validation Checklist
- [ ] Story file loaded from `{{story_path}}` - [ ] Story file loaded from `{{story_path}}`
- [ ] Story Status verified as one of: {{allow_status_values}} - [ ] Story Status verified as reviewable (review)
- [ ] Epic and Story IDs resolved ({{epic_num}}.{{story_num}}) - [ ] Epic and Story IDs resolved ({{epic_num}}.{{story_num}})
- [ ] Story Context located or warning recorded - [ ] Story Context located or warning recorded
- [ ] Epic Tech Spec located or warning recorded - [ ] Epic Tech Spec located or warning recorded
@ -17,6 +17,7 @@
- [ ] Review notes appended under "Senior Developer Review (AI)" - [ ] Review notes appended under "Senior Developer Review (AI)"
- [ ] Change Log updated with review entry - [ ] Change Log updated with review entry
- [ ] Status updated according to settings (if enabled) - [ ] Status updated according to settings (if enabled)
- [ ] Sprint status synced (if sprint tracking enabled)
- [ ] Story saved successfully - [ ] Story saved successfully
_Reviewer: {{user_name}} on {{date}}_ _Reviewer: {{user_name}} on {{date}}_

View File

@ -16,6 +16,7 @@
<step n="1" goal="Load story and discover changes"> <step n="1" goal="Load story and discover changes">
<action>Use provided {{story_path}} or ask user which story file to review</action> <action>Use provided {{story_path}} or ask user which story file to review</action>
<action>Read COMPLETE story file</action> <action>Read COMPLETE story file</action>
<action>Set {{story_key}} = extracted key from filename (e.g., "1-2-user-authentication.md" → "1-2-user-authentication") or story metadata</action>
<action>Parse sections: Story, Acceptance Criteria, Tasks/Subtasks, Dev Agent Record → File List, Change Log</action> <action>Parse sections: Story, Acceptance Criteria, Tasks/Subtasks, Dev Agent Record → File List, Change Log</action>
<!-- Discover actual changes via git --> <!-- Discover actual changes via git -->
@ -106,6 +107,8 @@
<step n="4" goal="Present findings and fix them"> <step n="4" goal="Present findings and fix them">
<action>Categorize findings: HIGH (must fix), MEDIUM (should fix), LOW (nice to fix)</action> <action>Categorize findings: HIGH (must fix), MEDIUM (should fix), LOW (nice to fix)</action>
<action>Set {{fixed_count}} = 0</action>
<action>Set {{action_count}} = 0</action>
<output>**🔥 CODE REVIEW FINDINGS, {user_name}!** <output>**🔥 CODE REVIEW FINDINGS, {user_name}!**
@ -145,11 +148,15 @@
<action>Add/update tests as needed</action> <action>Add/update tests as needed</action>
<action>Update File List in story if files changed</action> <action>Update File List in story if files changed</action>
<action>Update story Dev Agent Record with fixes applied</action> <action>Update story Dev Agent Record with fixes applied</action>
<action>Set {{fixed_count}} = number of HIGH and MEDIUM issues fixed</action>
<action>Set {{action_count}} = 0</action>
</check> </check>
<check if="user chooses 2"> <check if="user chooses 2">
<action>Add "Review Follow-ups (AI)" subsection to Tasks/Subtasks</action> <action>Add "Review Follow-ups (AI)" subsection to Tasks/Subtasks</action>
<action>For each issue: `- [ ] [AI-Review][Severity] Description [file:line]`</action> <action>For each issue: `- [ ] [AI-Review][Severity] Description [file:line]`</action>
<action>Set {{action_count}} = number of action items created</action>
<action>Set {{fixed_count}} = 0</action>
</check> </check>
<check if="user chooses 3"> <check if="user chooses 3">
@ -158,11 +165,52 @@
</check> </check>
</step> </step>
<step n="5" goal="Update story status"> <step n="5" goal="Update story status and sync sprint tracking">
<action>If all HIGH issues fixed and ACs implemented → Update story Status to "done"</action> <!-- Determine new status based on review outcome -->
<action>If issues remain → Update story Status to "in-progress"</action> <check if="all HIGH and MEDIUM issues fixed AND all ACs implemented">
<action>Set {{new_status}} = "done"</action>
<action>Update story Status field to "done"</action>
</check>
<check if="HIGH or MEDIUM issues remain OR ACs not fully implemented">
<action>Set {{new_status}} = "in-progress"</action>
<action>Update story Status field to "in-progress"</action>
</check>
<action>Save story file</action> <action>Save story file</action>
<!-- Determine sprint tracking status -->
<check if="{sprint_status} file exists">
<action>Set {{current_sprint_status}} = "enabled"</action>
</check>
<check if="{sprint_status} file does NOT exist">
<action>Set {{current_sprint_status}} = "no-sprint-tracking"</action>
</check>
<!-- Sync sprint-status.yaml when story status changes (only if sprint tracking enabled) -->
<check if="{{current_sprint_status}} != 'no-sprint-tracking'">
<action>Load the FULL file: {sprint_status}</action>
<action>Find development_status key matching {{story_key}}</action>
<check if="{{new_status}} == 'done'">
<action>Update development_status[{{story_key}}] = "done"</action>
<action>Save file, preserving ALL comments and structure</action>
<output>✅ Sprint status synced: {{story_key}} → done</output>
</check>
<check if="{{new_status}} == 'in-progress'">
<action>Update development_status[{{story_key}}] = "in-progress"</action>
<action>Save file, preserving ALL comments and structure</action>
<output>🔄 Sprint status synced: {{story_key}} → in-progress</output>
</check>
<check if="story key not found in sprint status">
<output>⚠️ Story file updated, but sprint-status sync failed: {{story_key}} not found in sprint-status.yaml</output>
</check>
</check>
<check if="{{current_sprint_status}} == 'no-sprint-tracking'">
<output> Story status updated (no sprint tracking configured)</output>
</check>
<output>**✅ Review Complete!** <output>**✅ Review Complete!**
**Story Status:** {{new_status}} **Story Status:** {{new_status}}

View File

@ -1,6 +1,6 @@
# Review Story Workflow # Review Story Workflow
name: code-review name: code-review
description: "Perform an ADVERSARIAL Senior Developer code review that finds 3-10 specific problems in every story. Challenges everything: code quality, test coverage, architecture compliance, security, performance. NEVER accepts 'looks good' - must find minimum issues and can auto-fix with user approval." description: "Perform an ADVERSARIAL Senior Developer code review that finds 3-10 specific problems in every story. Challenges everything: code quality, test coverage, architecture compliance, security, performance. NEVER accepts `looks good` - must find minimum issues and can auto-fix with user approval."
author: "BMad" author: "BMad"
# Critical variables from config # Critical variables from config

View File

@ -56,11 +56,6 @@ phases:
output: "Enterprise PRD with compliance requirements" output: "Enterprise PRD with compliance requirements"
note: "Must address existing system constraints and migration strategy" note: "Must address existing system constraints and migration strategy"
- id: "validate-prd"
recommended: true
agent: "pm"
command: "validate-prd"
- id: "create-ux-design" - id: "create-ux-design"
recommended: true recommended: true
agent: "ux-designer" agent: "ux-designer"
@ -114,7 +109,7 @@ phases:
required: true required: true
agent: "architect" agent: "architect"
command: "implementation-readiness" command: "implementation-readiness"
note: "Critical gate - validates all planning + Epics before touching production system" note: "Validates PRD + Architecture + Epics + UX (optional)"
- phase: 3 - phase: 3
name: "Implementation" name: "Implementation"

View File

@ -44,11 +44,6 @@ phases:
output: "Comprehensive Product Requirements Document" output: "Comprehensive Product Requirements Document"
note: "Enterprise-level requirements with compliance considerations" note: "Enterprise-level requirements with compliance considerations"
- id: "validate-prd"
recommended: true
agent: "pm"
command: "validate-prd"
- id: "create-ux-design" - id: "create-ux-design"
recommended: true recommended: true
agent: "ux-designer" agent: "ux-designer"
@ -102,7 +97,7 @@ phases:
required: true required: true
agent: "architect" agent: "architect"
command: "implementation-readiness" command: "implementation-readiness"
note: "Validates all planning artifacts + Epics + testability align before implementation" note: "Validates PRD + Architecture + Epics + UX (optional)"
- phase: 3 - phase: 3
name: "Implementation" name: "Implementation"

View File

@ -55,11 +55,6 @@ phases:
output: "PRD focused on new features/changes" output: "PRD focused on new features/changes"
note: "Must consider existing system constraints" note: "Must consider existing system constraints"
- id: "validate-prd"
optional: true
agent: "pm"
command: "validate-prd"
- id: "create-ux-design" - id: "create-ux-design"
conditional: "if_has_ui" conditional: "if_has_ui"
agent: "ux-designer" agent: "ux-designer"
@ -98,7 +93,7 @@ phases:
required: true required: true
agent: "architect" agent: "architect"
command: "implementation-readiness" command: "implementation-readiness"
note: "Validates PRD + UX + Architecture + Epics cohesion before implementation" note: "Validates PRD + Architecture + Epics + UX (optional)"
- phase: 3 - phase: 3
name: "Implementation" name: "Implementation"

View File

@ -43,12 +43,6 @@ phases:
command: "prd" command: "prd"
output: "Product Requirements Document with FRs and NFRs" output: "Product Requirements Document with FRs and NFRs"
- id: "validate-prd"
optional: true
agent: "pm"
command: "validate-prd"
note: "Quality check for PRD completeness"
- id: "create-ux-design" - id: "create-ux-design"
conditional: "if_has_ui" conditional: "if_has_ui"
agent: "ux-designer" agent: "ux-designer"
@ -89,7 +83,7 @@ phases:
required: true required: true
agent: "architect" agent: "architect"
command: "implementation-readiness" command: "implementation-readiness"
note: "Validates PRD + UX + Architecture + Epics + Testability cohesion before implementation" note: "Validates PRD + Architecture + Epics + UX (optional)"
- phase: 3 - phase: 3
name: "Implementation" name: "Implementation"

356
tools/validate-svg-changes.sh Executable file
View File

@ -0,0 +1,356 @@
#!/bin/bash
#
# Visual SVG Validation Script
#
# Compares old vs new SVG files using browser-accurate rendering (Playwright)
# and pixel-level comparison (ImageMagick), then generates a prompt for AI analysis.
#
# Usage: ./tools/validate-svg-changes.sh <path-to-svg>
#
set -e
SVG_FILE="${1:-src/modules/bmm/docs/images/workflow-method-greenfield.svg}"
TMP_DIR="/tmp/svg-validation-$$"
echo "🎨 Visual SVG Validation"
echo ""
# Check if file exists
if [ ! -f "$SVG_FILE" ]; then
echo "❌ Error: SVG file not found: $SVG_FILE"
exit 1
fi
# Check for ImageMagick
if ! command -v magick &> /dev/null; then
echo "❌ ImageMagick not found"
echo ""
echo "Install with:"
echo " brew install imagemagick"
echo ""
exit 1
fi
echo "✓ ImageMagick found"
# Check for Node.js
if ! command -v node &> /dev/null; then
echo "❌ Node.js not found"
exit 1
fi
echo "✓ Node.js found ($(node -v))"
# Check for Playwright (local install)
if [ ! -d "node_modules/playwright" ]; then
echo ""
echo "📦 Playwright not found locally"
echo "Installing Playwright (local to this project, no package.json changes)..."
echo ""
npm install --no-save playwright
echo ""
echo "✓ Playwright installed"
else
echo "✓ Playwright found"
fi
echo ""
echo "🔄 Rendering SVGs to PNG..."
echo ""
# Create temp directory
mkdir -p "$TMP_DIR"
# Extract old SVG from git
git show HEAD:"$SVG_FILE" > "$TMP_DIR/old.svg" 2>/dev/null || {
echo "❌ Could not extract old SVG from git HEAD"
echo " Make sure you have uncommitted changes to compare"
exit 1
}
# Copy new SVG
cp "$SVG_FILE" "$TMP_DIR/new.svg"
# Create Node.js renderer script in project directory (so it can find node_modules)
cat > "tools/render-svg-temp.js" << 'EOJS'
const { chromium } = require('playwright');
const fs = require('fs');
async function renderSVG(svgPath, pngPath) {
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
const svgContent = fs.readFileSync(svgPath, 'utf8');
const widthMatch = svgContent.match(/width="([^"]+)"/);
const heightMatch = svgContent.match(/height="([^"]+)"/);
const width = Math.ceil(parseFloat(widthMatch[1]));
const height = Math.ceil(parseFloat(heightMatch[1]));
const html = `
<!DOCTYPE html>
<html>
<head>
<style>
body { margin: 0; padding: 0; background: white; }
svg { display: block; }
</style>
</head>
<body>${svgContent}</body>
</html>
`;
await page.setContent(html);
await page.setViewportSize({ width, height });
await page.waitForTimeout(1000);
await page.screenshot({ path: pngPath, fullPage: true });
await browser.close();
console.log(`✓ Rendered ${pngPath}`);
}
(async () => {
await renderSVG(process.argv[2], process.argv[3]);
await renderSVG(process.argv[4], process.argv[5]);
})();
EOJS
# Render both SVGs (run from project dir so node_modules is accessible)
node tools/render-svg-temp.js \
"$TMP_DIR/old.svg" "$TMP_DIR/old.png" \
"$TMP_DIR/new.svg" "$TMP_DIR/new.png"
# Clean up temp script
rm tools/render-svg-temp.js
echo ""
echo "🔍 Comparing pixels..."
echo ""
# Compare using ImageMagick
DIFF_OUTPUT=$(magick compare -metric AE "$TMP_DIR/old.png" "$TMP_DIR/new.png" "$TMP_DIR/diff.png" 2>&1 || true)
DIFF_PIXELS=$(echo "$DIFF_OUTPUT" | awk '{print $1}')
# Get image dimensions
DIMENSIONS=$(magick identify -format "%wx%h" "$TMP_DIR/old.png")
WIDTH=$(echo "$DIMENSIONS" | cut -d'x' -f1)
HEIGHT=$(echo "$DIMENSIONS" | cut -d'x' -f2)
TOTAL_PIXELS=$((WIDTH * HEIGHT))
# Calculate percentage
DIFF_PERCENT=$(echo "scale=4; $DIFF_PIXELS / $TOTAL_PIXELS * 100" | bc)
echo "📊 Results:"
echo " Dimensions: ${WIDTH} × ${HEIGHT}"
echo " Total pixels: $(printf "%'d" $TOTAL_PIXELS)"
echo " Different pixels: $(printf "%'d" $DIFF_PIXELS)"
echo " Difference: ${DIFF_PERCENT}%"
echo ""
if (( $(echo "$DIFF_PERCENT < 0.01" | bc -l) )); then
echo "✅ ESSENTIALLY IDENTICAL (< 0.01% difference)"
VERDICT="essentially identical"
elif (( $(echo "$DIFF_PERCENT < 0.1" | bc -l) )); then
echo "⚠️ MINOR DIFFERENCES (< 0.1%)"
VERDICT="minor differences detected"
else
echo "❌ SIGNIFICANT DIFFERENCES (≥ 0.1%)"
VERDICT="significant differences detected"
fi
echo ""
echo "📁 Output files:"
echo " Old render: $TMP_DIR/old.png"
echo " New render: $TMP_DIR/new.png"
echo " Diff image: $TMP_DIR/diff.png"
echo ""
# Generate HTML comparison page
cat > "$TMP_DIR/comparison.html" << 'EOHTML'
<!DOCTYPE html>
<html>
<head>
<title>SVG Comparison</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #f5f5f5;
padding: 20px;
}
.header {
background: white;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1 { margin-bottom: 10px; color: #333; }
.stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 10px;
margin-top: 15px;
}
.stat {
background: #f8f9fa;
padding: 10px;
border-radius: 4px;
}
.stat-label { font-size: 12px; color: #666; text-transform: uppercase; }
.stat-value { font-size: 18px; font-weight: 600; color: #333; margin-top: 4px; }
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;
margin-bottom: 20px;
}
.panel {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h2 {
margin: 0 0 15px 0;
color: #333;
font-size: 18px;
border-bottom: 2px solid #e0e0e0;
padding-bottom: 10px;
}
.image-container {
border: 1px solid #ddd;
background: white;
overflow: auto;
max-height: 600px;
}
img {
display: block;
max-width: 100%;
height: auto;
}
.verdict {
display: inline-block;
padding: 4px 12px;
border-radius: 12px;
font-size: 14px;
font-weight: 600;
}
.verdict.good { background: #d4edda; color: #155724; }
.verdict.warning { background: #fff3cd; color: #856404; }
.verdict.bad { background: #f8d7da; color: #721c24; }
</style>
</head>
<body>
<div class="header">
<h1>🎨 SVG Visual Comparison</h1>
<p><strong>File:</strong> FILENAME_PLACEHOLDER</p>
<div class="stats">
<div class="stat">
<div class="stat-label">Dimensions</div>
<div class="stat-value">DIMENSIONS_PLACEHOLDER</div>
</div>
<div class="stat">
<div class="stat-label">Different Pixels</div>
<div class="stat-value">DIFF_PIXELS_PLACEHOLDER</div>
</div>
<div class="stat">
<div class="stat-label">Difference</div>
<div class="stat-value">DIFF_PERCENT_PLACEHOLDER%</div>
</div>
<div class="stat">
<div class="stat-label">Verdict</div>
<div class="stat-value"><span class="verdict VERDICT_CLASS_PLACEHOLDER">VERDICT_PLACEHOLDER</span></div>
</div>
</div>
</div>
<div class="container">
<div class="panel">
<h2>📄 Old (HEAD)</h2>
<div class="image-container">
<img src="old.png" alt="Old SVG">
</div>
</div>
<div class="panel">
<h2>📝 New (Working)</h2>
<div class="image-container">
<img src="new.png" alt="New SVG">
</div>
</div>
<div class="panel">
<h2>🔍 Diff (Red = Changes)</h2>
<div class="image-container">
<img src="diff.png" alt="Diff">
</div>
</div>
</div>
</body>
</html>
EOHTML
# Determine verdict class for styling
if (( $(echo "$DIFF_PERCENT < 0.01" | bc -l) )); then
VERDICT_CLASS="good"
elif (( $(echo "$DIFF_PERCENT < 0.1" | bc -l) )); then
VERDICT_CLASS="warning"
else
VERDICT_CLASS="bad"
fi
# Replace placeholders in HTML
sed -i '' "s|FILENAME_PLACEHOLDER|$SVG_FILE|g" "$TMP_DIR/comparison.html"
sed -i '' "s|DIMENSIONS_PLACEHOLDER|${WIDTH} × ${HEIGHT}|g" "$TMP_DIR/comparison.html"
sed -i '' "s|DIFF_PIXELS_PLACEHOLDER|$(printf "%'d" $DIFF_PIXELS) / $(printf "%'d" $TOTAL_PIXELS)|g" "$TMP_DIR/comparison.html"
sed -i '' "s|DIFF_PERCENT_PLACEHOLDER|$DIFF_PERCENT|g" "$TMP_DIR/comparison.html"
sed -i '' "s|VERDICT_PLACEHOLDER|$VERDICT|g" "$TMP_DIR/comparison.html"
sed -i '' "s|VERDICT_CLASS_PLACEHOLDER|$VERDICT_CLASS|g" "$TMP_DIR/comparison.html"
echo "✓ Generated comparison page: $TMP_DIR/comparison.html"
echo ""
echo "🌐 Opening comparison in browser..."
open "$TMP_DIR/comparison.html"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "🤖 AI VISUAL ANALYSIS PROMPT"
echo ""
echo "Copy and paste this into Gemini/Claude with the diff image attached:"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
cat << PROMPT
I've made changes to an Excalidraw diagram SVG file. Please analyze the visual differences between the old and new versions.
**Automated Analysis:**
- Dimensions: ${WIDTH} × ${HEIGHT} pixels
- Different pixels: $(printf "%'d" $DIFF_PIXELS) out of $(printf "%'d" $TOTAL_PIXELS)
- Difference: ${DIFF_PERCENT}%
- Verdict: ${VERDICT}
**Attached Image:**
The attached image shows the pixel-level diff (red = differences).
**Questions:**
1. Are the differences purely anti-aliasing/rendering artifacts, or are there actual content changes?
2. If there are content changes, what specifically changed?
3. Do the changes align with the intent to remove zombie Excalidraw elements (elements marked as deleted but left in the JSON)?
4. Is this safe to commit?
**Context:**
- File: $SVG_FILE
- Changes: Removed 191 lines of zombie JSON from Excalidraw source
- Expected: Visual output should be identical (zombie elements were already marked as deleted)
PROMPT
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "📎 Attach this file to your AI prompt:"
echo " $TMP_DIR/diff.png"
echo ""
echo "💡 To open the diff image:"
echo " open $TMP_DIR/diff.png"
echo ""