From 1a1d4bed52e5ec7a03641fbe302a1c0b840d9c61 Mon Sep 17 00:00:00 2001 From: Dicky Moore Date: Thu, 5 Feb 2026 16:02:01 +0000 Subject: [PATCH] Migrate workflow runner references to workflow.md --- src/bmm/agents/tea.agent.yaml | 63 +++++++ src/bmm/module-help.csv | 51 +++--- src/core/resources/excalidraw/README.md | 160 ++++++++++++++++++ .../resources/excalidraw/library-loader.md | 50 ++++++ test/test-installation-components.js | 95 +++++++++++ .../installers/lib/core/manifest-generator.js | 2 +- tools/cli/installers/lib/ide/_base-ide.js | 24 ++- .../ide/shared/workflow-command-generator.js | 30 ++-- tools/cli/installers/lib/modules/manager.js | 83 ++++++--- 9 files changed, 481 insertions(+), 77 deletions(-) create mode 100644 src/bmm/agents/tea.agent.yaml create mode 100644 src/core/resources/excalidraw/README.md create mode 100644 src/core/resources/excalidraw/library-loader.md diff --git a/src/bmm/agents/tea.agent.yaml b/src/bmm/agents/tea.agent.yaml new file mode 100644 index 000000000..5bc6cb1b1 --- /dev/null +++ b/src/bmm/agents/tea.agent.yaml @@ -0,0 +1,63 @@ +# Test Architect + Quality Advisor Agent Definition + +agent: + webskip: true + metadata: + id: "_bmad/bmm/agents/tea.md" + name: Murat + title: Master Test Architect + icon: ๐Ÿงช + module: bmm + hasSidecar: false + + persona: + role: Master Test Architect + identity: Test architect specializing in API testing, backend services, UI automation, CI/CD pipelines, and scalable quality gates. Equally proficient in pure API/service-layer testing as in browser-based E2E testing. + communication_style: "Blends data with gut instinct. 'Strong opinions, weakly held' is their mantra. Speaks in risk calculations and impact assessments." + principles: | + - Risk-based testing - depth scales with impact + - Quality gates backed by data + - Tests mirror usage patterns (API, UI, or both) + - Flakiness is critical technical debt + - Tests first AI implements suite validates + - Calculate risk vs value for every testing decision + - Prefer lower test levels (unit > integration > E2E) when possible + - API tests are first-class citizens, not just UI support + + critical_actions: + - "Consult {project-root}/_bmad/bmm/testarch/tea-index.csv to select knowledge fragments under knowledge/ and load only the files needed for the current task" + - "Load the referenced fragment(s) from {project-root}/_bmad/bmm/testarch/knowledge/ before giving recommendations" + - "Cross-check recommendations with the current official Playwright, Cypress, Pact, and CI platform documentation" + + menu: + - trigger: TF or fuzzy match on test-framework + workflow: "{project-root}/_bmad/bmm/workflows/testarch/framework/workflow.md" + description: "[TF] Test Framework: Initialize production-ready test framework architecture" + + - trigger: AT or fuzzy match on atdd + workflow: "{project-root}/_bmad/bmm/workflows/testarch/atdd/workflow.md" + description: "[AT] Automated Test: Generate API and/or E2E tests first, before starting implementation on a story" + + - trigger: TA or fuzzy match on test-automate + workflow: "{project-root}/_bmad/bmm/workflows/testarch/automate/workflow.md" + description: "[TA] Test Automation: Generate comprehensive test automation framework for your whole project" + + - trigger: TD or fuzzy match on test-design + workflow: "{project-root}/_bmad/bmm/workflows/testarch/test-design/workflow.md" + description: "[TD] Test Design: Create comprehensive test scenarios ahead of development." + + - trigger: TR or fuzzy match on test-trace + workflow: "{project-root}/_bmad/bmm/workflows/testarch/trace/workflow.md" + description: "[TR] Trace Requirements: Map requirements to tests (Phase 1) and make quality gate decision (Phase 2)" + + - trigger: NR or fuzzy match on nfr-assess + workflow: "{project-root}/_bmad/bmm/workflows/testarch/nfr-assess/workflow.md" + description: "[NR] Non-Functional Requirements: Validate against the project implementation" + + - trigger: CI or fuzzy match on continuous-integration + workflow: "{project-root}/_bmad/bmm/workflows/testarch/ci/workflow.md" + description: "[CI] Continuous Integration: Recommend and Scaffold CI/CD quality pipeline" + + - trigger: RV or fuzzy match on test-review + workflow: "{project-root}/_bmad/bmm/workflows/testarch/test-review/workflow.md" + description: "[RV] Review Tests: Perform a quality check against written tests using comprehensive knowledge base and best practices" diff --git a/src/bmm/module-help.csv b/src/bmm/module-help.csv index 635bb8a81..9ba42ca0f 100644 --- a/src/bmm/module-help.csv +++ b/src/bmm/module-help.csv @@ -1,31 +1,32 @@ module,phase,name,code,sequence,workflow-file,command,required,agent,options,description,output-location,outputs, -bmm,anytime,Document Project,DP,,_bmad/bmm/workflows/document-project/workflow.yaml,bmad-bmm-document-project,false,analyst,Create Mode,"Analyze an existing project to produce useful documentation",project-knowledge,*, -bmm,anytime,Generate Project Context,GPC,,_bmad/bmm/workflows/generate-project-context/workflow.md,bmad-bmm-generate-project-context,false,analyst,Create Mode,"Scan existing codebase to generate a lean LLM-optimized project-context.md containing critical implementation rules patterns and conventions for AI agents. Essential for brownfield projects and quick-flow.",output_folder,"project context", -bmm,anytime,Quick Spec,QS,,_bmad/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md,bmad-bmm-quick-spec,false,quick-flow-solo-dev,Create Mode,"Do not suggest for potentially very complex things unless requested or if the user complains that they do not want to follow the extensive planning of the bmad method. Quick one-off tasks small changes simple apps brownfield additions to well established patterns utilities without extensive planning",planning_artifacts,"tech spec", -bmm,anytime,Quick Dev,QD,,_bmad/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md,bmad-bmm-quick-dev,false,quick-flow-solo-dev,Create Mode,"Quick one-off tasks small changes simple apps utilities without extensive planning - Do not suggest for potentially very complex things unless requested or if the user complains that they do not want to follow the extensive planning of the bmad method, unless the user is already working through the implementation phase and just requests a 1 off things not already in the plan",,, -bmm,anytime,Correct Course,CC,,_bmad/bmm/workflows/4-implementation/correct-course/workflow.yaml,bmad-bmm-correct-course,false,sm,Create Mode,"Anytime: Navigate significant changes. May recommend start over update PRD redo architecture sprint planning or correct epics and stories",planning_artifacts,"change proposal", -bmm,anytime,Write Document,WD,,_bmad/bmm/agents/tech-writer/tech-writer.agent.yaml,,false,tech-writer,,"Describe in detail what you want, and the agent will follow the documentation best practices defined in agent memory. Multi-turn conversation with subprocess for research/review.",project-knowledge,"document", -bmm,anytime,Update Standards,US,,_bmad/bmm/agents/tech-writer/tech-writer.agent.yaml,,false,tech-writer,,"Update agent memory documentation-standards.md with your specific preferences if you discover missing document conventions.",_bmad/_memory/tech-writer-sidecar,"standards", -bmm,anytime,Mermaid Generate,MG,,_bmad/bmm/agents/tech-writer/tech-writer.agent.yaml,,false,tech-writer,,"Create a Mermaid diagram based on user description. Will suggest diagram types if not specified.",planning_artifacts,"mermaid diagram", -bmm,anytime,Validate Document,VD,,_bmad/bmm/agents/tech-writer/tech-writer.agent.yaml,,false,tech-writer,,"Review the specified document against documentation standards and best practices. Returns specific actionable improvement suggestions organized by priority.",planning_artifacts,"validation report", -bmm,anytime,Explain Concept,EC,,_bmad/bmm/agents/tech-writer/tech-writer.agent.yaml,,false,tech-writer,,"Create clear technical explanations with examples and diagrams for complex concepts. Breaks down into digestible sections using task-oriented approach.",project_knowledge,"explanation", +bmm,anytime,Document Project,DP,10,_bmad/bmm/workflows/document-project/workflow.md,bmad-bmm-document-project,false,analyst,Create Mode,"Analyze an existing project to produce useful documentation",project-knowledge,*, +bmm,anytime,Quick Spec,TS,20,_bmad/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md,bmad-bmm-quick-spec,false,quick-flow-solo-dev,Create Mode,"Do not suggest for potentially very complex things unless requested or if the user complains that they do not want to follow the extensive planning of the bmad method. Quick one-off tasks small changes simple apps utilities without extensive planning",planning_artifacts,"tech spec", +bmm,anytime,Quick Dev,QD,30,_bmad/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md,bmad-bmm-quick-dev,false,quick-flow-solo-dev,Create Mode,"Quick one-off tasks small changes simple apps utilities without extensive planning - Do not suggest for potentially very complex things unless requested or if the user complains that they do not want to follow the extensive planning of the bmad method, unless the user is already working through the implementation phase and just requests a 1 off things not already in the plan",,, +bmm,anytime,Correct Course,CC,40,_bmad/bmm/workflows/4-implementation/correct-course/workflow.md,bmad-bmm-correct-course,false,sm,Create Mode,"Anytime: Navigate significant changes. May recommend start over update PRD redo architecture sprint planning or correct epics and stories",planning_artifacts,"change proposal", bmm,1-analysis,Brainstorm Project,BP,10,_bmad/core/workflows/brainstorming/workflow.md,bmad-brainstorming,false,analyst,data=_bmad/bmm/data/project-context-template.md,"Expert Guided Facilitation through a single or multiple techniques",planning_artifacts,"brainstorming session", -bmm,1-analysis,Market Research,MR,20,_bmad/bmm/workflows/1-analysis/research/workflow-market-research.md,bmad-bmm-market-research,false,analyst,Create Mode,"Market analysis competitive landscape customer needs and trends","planning_artifacts|project-knowledge","research documents", -bmm,1-analysis,Domain Research,DR,21,_bmad/bmm/workflows/1-analysis/research/workflow-domain-research.md,bmad-bmm-domain-research,false,analyst,Create Mode,"Industry domain deep dive subject matter expertise and terminology","planning_artifacts|project_knowledge","research documents", -bmm,1-analysis,Technical Research,TR,22,_bmad/bmm/workflows/1-analysis/research/workflow-technical-research.md,bmad-bmm-technical-research,false,analyst,Create Mode,"Technical feasibility architecture options and implementation approaches","planning_artifacts|project_knowledge","research documents", -bmm,1-analysis,Create Brief,CB,30,_bmad/bmm/workflows/1-analysis/create-product-brief/workflow.md,bmad-bmm-create-product-brief,false,analyst,Create Mode,"A guided experience to nail down your product idea",planning_artifacts,"product brief", -bmm,2-planning,Create PRD,CP,10,_bmad/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md,bmad-bmm-create-prd,true,pm,Create Mode,"Expert led facilitation to produce your Product Requirements Document",planning_artifacts,prd, -bmm,2-planning,Validate PRD,VP,20,_bmad/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md,bmad-bmm-validate-prd,false,pm,Validate Mode,"Validate PRD is comprehensive lean well organized and cohesive",planning_artifacts,"prd validation report", -bmm,2-planning,Edit PRD,EP,25,_bmad/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md,bmad-bmm-edit-prd,false,pm,Edit Mode,"Improve and enhance an existing PRD",planning_artifacts,"updated prd", +bmm,1-analysis,Market Research,MR,20,_bmad/bmm/workflows/1-analysis/research/workflow.md,bmad-bmm-research,false,analyst,Create Mode research_type=market,"Market analysis competitive landscape customer needs and trends","planning_artifacts|project-knowledge","research documents" +bmm,1-analysis,Domain Research,DR,21,_bmad/bmm/workflows/1-analysis/research/workflow.md,bmad-bmm-research,false,analyst,Create Mode research_type=domain,"Industry domain deep dive subject matter expertise and terminology","planning_artifacts|project-knowledge","research documents" +bmm,1-analysis,Technical Research,TR,22,_bmad/bmm/workflows/1-analysis/research/workflow.md,bmad-bmm-research,false,analyst,Create Mode research_type=technical,"Technical feasibility architecture options and implementation approaches","planning_artifacts|project-knowledge","research documents" +bmm,1-analysis,Create Brief,CB,30,_bmad/bmm/workflows/1-analysis/create-product-brief/workflow.md,bmad-bmm-create-brief,false,analyst,Create Mode,"A guided experience to nail down your product idea",planning_artifacts,"product brief", +bmm,1-analysis,Validate Brief,VB,40,_bmad/bmm/workflows/1-analysis/create-product-brief/workflow.md,bmad-bmm-validate-brief,false,analyst,Validate Mode,"Validates product brief completeness",planning_artifacts,"brief validation report", +bmm,2-planning,Create PRD,CP,10,_bmad/bmm/workflows/2-plan-workflows/create-prd/workflow.md,bmad-bmm-prd,true,pm,Create Mode,"Expert led facilitation to produce your Product Requirements Document",planning_artifacts,prd, +bmm,2-planning,Validate PRD,VP,20,_bmad/bmm/workflows/2-plan-workflows/create-prd/workflow.md,bmad-bmm-prd,false,pm,Validate Mode,"Validate PRD is comprehensive lean well organized and cohesive",planning_artifacts,"prd validation report", bmm,2-planning,Create UX,CU,30,_bmad/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md,bmad-bmm-create-ux-design,false,ux-designer,Create Mode,"Guidance through realizing the plan for your UX, strongly recommended if a UI is a primary piece of the proposed project",planning_artifacts,"ux design", +bmm,2-planning,Validate UX,VU,40,_bmad/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md,bmad-bmm-create-ux-design,false,ux-designer,Validate Mode,"Validates UX design deliverables",planning_artifacts,"ux validation report", +,anytime,Create Dataflow,CDF,50,_bmad/bmm/workflows/excalidraw-diagrams/create-dataflow/workflow.md,bmad-bmm-create-excalidraw-dataflow,false,ux-designer,Create Mode,"Create data flow diagrams (DFD) in Excalidraw format - can be called standalone or during any workflow to add visual documentation",planning_artifacts,"dataflow diagram", +,anytime,Create Diagram,CED,51,_bmad/bmm/workflows/excalidraw-diagrams/create-diagram/workflow.md,bmad-bmm-create-excalidraw-diagram,false,ux-designer,Create Mode,"Create system architecture diagrams ERDs UML diagrams or general technical diagrams in Excalidraw format - use anytime or call from architecture workflow to add visual documentation",planning_artifacts,"diagram", +,anytime,Create Flowchart,CFC,52,_bmad/bmm/workflows/excalidraw-diagrams/create-flowchart/workflow.md,bmad-bmm-create-excalidraw-flowchart,false,ux-designer,Create Mode,"Create a flowchart visualization in Excalidraw format for processes pipelines or logic flows - use anytime or during architecture to add process documentation",planning_artifacts,"flowchart", +,anytime,Create Wireframe,CEW,53,_bmad/bmm/workflows/excalidraw-diagrams/create-wireframe/workflow.md,bmad-bmm-create-excalidraw-wireframe,false,ux-designer,Create Mode,"Create website or app wireframes in Excalidraw format - use anytime standalone or call from UX workflow to add UI mockups",planning_artifacts,"wireframe", bmm,3-solutioning,Create Architecture,CA,10,_bmad/bmm/workflows/3-solutioning/create-architecture/workflow.md,bmad-bmm-create-architecture,true,architect,Create Mode,"Guided Workflow to document technical decisions",planning_artifacts,architecture, +bmm,3-solutioning,Validate Architecture,VA,20,_bmad/bmm/workflows/3-solutioning/create-architecture/workflow.md,bmad-bmm-create-architecture,false,architect,Validate Mode,"Validates architecture completeness",planning_artifacts,"architecture validation report", bmm,3-solutioning,Create Epics and Stories,CE,30,_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md,bmad-bmm-create-epics-and-stories,true,pm,Create Mode,"Create the Epics and Stories Listing",planning_artifacts,"epics and stories", +bmm,3-solutioning,Validate Epics and Stories,VE,40,_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md,bmad-bmm-create-epics-and-stories,false,pm,Validate Mode,"Validates epics and stories completeness",planning_artifacts,"epics validation report", +bmm,3-solutioning,Test Design,TD,50,_bmad/bmm/workflows/testarch/test-design/workflow.md,bmad-bmm-testarch-test-design,false,tea,Create Mode,"Create comprehensive test scenarios ahead of development, recommended if string test compliance or assurance is needed. Very critical for distributed applications with separate front ends and backends outside of a monorepo.",planning_artifacts,"test design", bmm,3-solutioning,Check Implementation Readiness,IR,70,_bmad/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md,bmad-bmm-check-implementation-readiness,true,architect,Validate Mode,"Ensure PRD UX Architecture and Epics Stories are aligned",planning_artifacts,"readiness report", -bmm,4-implementation,Sprint Planning,SP,10,_bmad/bmm/workflows/4-implementation/sprint-planning/workflow.yaml,bmad-bmm-sprint-planning,true,sm,Create Mode,"Generate sprint plan for development tasks - this kicks off the implementation phase by producing a plan the implementation agents will follow in sequence for every story in the plan.",implementation_artifacts,"sprint status", -bmm,4-implementation,Sprint Status,SS,20,_bmad/bmm/workflows/4-implementation/sprint-status/workflow.yaml,bmad-bmm-sprint-status,false,sm,Create Mode,"Anytime: Summarize sprint status and route to next workflow",,, -bmm,4-implementation,Validate Story,VS,35,_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml,bmad-bmm-create-story,false,sm,Validate Mode,"Validates story readiness and completeness before development work begins",implementation_artifacts,"story validation report", -bmm,4-implementation,Create Story,CS,30,_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml,bmad-bmm-create-story,true,sm,Create Mode,"Story cycle start: Prepare first found story in the sprint plan that is next, or if the command is run with a specific epic and story designation with context. Once complete, then VS then DS then CR then back to DS if needed or next CS or ER",implementation_artifacts,story, -bmm,4-implementation,Dev Story,DS,40,_bmad/bmm/workflows/4-implementation/dev-story/workflow.yaml,bmad-bmm-dev-story,true,dev,Create Mode,"Story cycle: Execute story implementation tasks and tests then CR then back to DS if fixes needed",,, -bmm,4-implementation,Code Review,CR,50,_bmad/bmm/workflows/4-implementation/code-review/workflow.yaml,bmad-bmm-code-review,false,dev,Create Mode,"Story cycle: If issues back to DS if approved then next CS or ER if epic complete",,, -bmm,4-implementation,QA Automation Test,QA,45,_bmad/bmm/workflows/qa/automate/workflow.yaml,bmad-bmm-qa-automate,false,qa,Create Mode,"Generate automated API and E2E tests for implemented code using the project's existing test framework (detects existing well known in use test frameworks). Use after implementation to add test coverage. NOT for code review or story validation - use CR for that.",implementation_artifacts,"test suite", -bmm,4-implementation,Retrospective,ER,60,_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml,bmad-bmm-retrospective,false,sm,Create Mode,"Optional at epic end: Review completed work lessons learned and next epic or if major issues consider CC",implementation_artifacts,retrospective, +bmm,4-implementation,Sprint Planning,SP,10,_bmad/bmm/workflows/4-implementation/sprint-planning/workflow.md,bmad-bmm-sprint-planning,true,sm,Create Mode,"Generate sprint plan for development tasks - this kicks off the implementation phase by producing a plan the implementation agents will follow in sequence for every story in the plan.",implementation_artifacts,"sprint status", +bmm,4-implementation,Sprint Status,SS,20,_bmad/bmm/workflows/4-implementation/sprint-status/workflow.md,bmad-bmm-sprint-status,false,sm,Create Mode,"Anytime: Summarize sprint status and route to next workflow",,, +bmm,4-implementation,Create Story,CS,30,_bmad/bmm/workflows/4-implementation/create-story/workflow.md,bmad-bmm-create-story,true,sm,Create Mode,"Story cycle start: Prepare first found story in the sprint plan that is next, or if the command is run with a specific epic and story designation with context. Once complete, then VS then DS then CR then back to DS if needed or next CS or ER",implementation_artifacts,story, +bmm,4-implementation,Validate Story,VS,35,_bmad/bmm/workflows/4-implementation/create-story/workflow.md,bmad-bmm-create-story,false,sm,Validate Mode,"Validates story readiness and completeness before development work begins",implementation_artifacts,"story validation report", +bmm,4-implementation,Dev Story,DS,40,_bmad/bmm/workflows/4-implementation/dev-story/workflow.md,bmad-bmm-dev-story,true,dev,Create Mode,"Story cycle: Execute story implementation tasks and tests then CR then back to DS if fixes needed",,, +bmm,4-implementation,Code Review,CR,50,_bmad/bmm/workflows/4-implementation/code-review/workflow.md,bmad-bmm-code-review,false,dev,Create Mode,"Story cycle: If issues back to DS if approved then next CS or ER if epic complete",,, +bmm,4-implementation,Retrospective,ER,60,_bmad/bmm/workflows/4-implementation/retrospective/workflow.md,bmad-bmm-retrospective,false,sm,Create Mode,"Optional at epic end: Review completed work lessons learned and next epic or if major issues consider CC",implementation_artifacts,retrospective, diff --git a/src/core/resources/excalidraw/README.md b/src/core/resources/excalidraw/README.md new file mode 100644 index 000000000..a99f7a505 --- /dev/null +++ b/src/core/resources/excalidraw/README.md @@ -0,0 +1,160 @@ +# Core Excalidraw Resources + +Universal knowledge for creating Excalidraw diagrams. All agents that create Excalidraw files should reference these resources. + +## Purpose + +Provides the **HOW** (universal knowledge) while agents provide the **WHAT** (domain-specific application). + +**Core = "How to create Excalidraw elements"** + +- How to group shapes with text labels +- How to calculate text width +- How to create arrows with proper bindings +- How to validate JSON syntax +- Base structure and primitives + +**Agents = "What diagrams to create"** + +- Frame Expert (BMM): Technical flowcharts, architecture diagrams, wireframes +- Presentation Master (CIS): Pitch decks, creative visuals, Rube Goldberg machines +- Tech Writer (BMM): Documentation diagrams, concept explanations + +## Files in This Directory + +### excalidraw-helpers.md + +**Universal element creation patterns** + +- Text width calculation +- Element grouping rules (shapes + labels) +- Grid alignment +- Arrow creation (straight, elbow) +- Theme application +- Validation checklist +- Optimization rules + +**Agents reference this to:** + +- Create properly grouped shapes +- Calculate text dimensions +- Connect elements with arrows +- Ensure valid structure + +### validate-json-instructions.md + +**Universal JSON validation process** + +- How to validate Excalidraw JSON +- Common errors and fixes +- Workflow integration +- Error recovery + +**Agents reference this to:** + +- Validate files after creation +- Fix syntax errors +- Ensure files can be opened in Excalidraw + +### library-loader.md (Future) + +**How to load external .excalidrawlib files** + +- Programmatic library loading +- Community library integration +- Custom library management + +**Status:** To be developed when implementing external library support. + +## How Agents Use These Resources + +### Example: Frame Expert (Technical Diagrams) + +```yaml +# workflows/excalidraw-diagrams/create-flowchart/workflow.md +helpers: '{project-root}/_bmad/core/resources/excalidraw/excalidraw-helpers.md' +json_validation: '{project-root}/_bmad/core/resources/excalidraw/validate-json-instructions.md' +``` + +**Domain-specific additions:** + +```yaml +# workflows/excalidraw-diagrams/_shared/flowchart-templates.yaml +flowchart: + start_node: + type: ellipse + width: 120 + height: 60 + process_box: + type: rectangle + width: 160 + height: 80 + decision_diamond: + type: diamond + width: 140 + height: 100 +``` + +### Example: Presentation Master (Creative Visuals) + +```yaml +# workflows/create-visual-metaphor/workflow.md +helpers: '{project-root}/_bmad/core/resources/excalidraw/excalidraw-helpers.md' +json_validation: '{project-root}/_bmad/core/resources/excalidraw/validate-json-instructions.md' +``` + +**Domain-specific additions:** + +```yaml +# workflows/_shared/creative-templates.yaml +rube_goldberg: + whimsical_connector: + type: arrow + strokeStyle: dashed + roughness: 2 + playful_box: + type: rectangle + roundness: 12 +``` + +## What Doesn't Belong in Core + +**Domain-Specific Elements:** + +- Flowchart-specific templates (belongs in Frame Expert) +- Pitch deck layouts (belongs in Presentation Master) +- Documentation-specific styles (belongs in Tech Writer) + +**Agent Workflows:** + +- How to create a flowchart (Frame Expert workflow) +- How to create a pitch deck (Presentation Master workflow) +- Step-by-step diagram creation (agent-specific) + +**Theming:** + +- Currently in agent workflows +- **Future:** Will be refactored to core as user-configurable themes + +## Architecture Principle + +**Single Source of Truth:** + +- Core holds universal knowledge +- Agents reference core, don't duplicate +- Updates to core benefit all agents +- Agents specialize with domain knowledge + +**DRY (Don't Repeat Yourself):** + +- Element creation logic: ONCE in core +- Text width calculation: ONCE in core +- Validation process: ONCE in core +- Arrow binding patterns: ONCE in core + +## Future Enhancements + +1. **External Library Loader** - Load .excalidrawlib files from libraries.excalidraw.com +2. **Theme Management** - User-configurable color themes saved in core +3. **Component Library** - Shared reusable components across agents +4. **Layout Algorithms** - Auto-layout helpers for positioning elements diff --git a/src/core/resources/excalidraw/library-loader.md b/src/core/resources/excalidraw/library-loader.md new file mode 100644 index 000000000..f2fd038de --- /dev/null +++ b/src/core/resources/excalidraw/library-loader.md @@ -0,0 +1,50 @@ +# External Library Loader + +**Status:** Placeholder for future implementation + +## Purpose + +Load external .excalidrawlib files from or custom sources. + +## Planned Capabilities + +- Load libraries by URL +- Load libraries from local files +- Merge multiple libraries +- Filter library components +- Cache loaded libraries + +## API Reference + +Will document how to use: + +- `importLibrary(url)` - Load library from URL +- `loadSceneOrLibraryFromBlob()` - Load from file +- `mergeLibraryItems()` - Combine libraries + +## Usage Example + +```yaml +# Future workflow.md structure +libraries: + - url: 'https://libraries.excalidraw.com/libraries/...' + filter: ['aws', 'cloud'] + - path: '{project-root}/_data/custom-library.excalidrawlib' +``` + +## Implementation Notes + +This will be developed when agents need to leverage the extensive library ecosystem available at . + +Hundreds of pre-built component libraries exist for: + +- AWS/Cloud icons +- UI/UX components +- Business diagrams +- Mind map shapes +- Floor plans +- And much more... + +## User Configuration + +Future: Users will be able to configure favorite libraries in their BMAD config for automatic loading. diff --git a/test/test-installation-components.js b/test/test-installation-components.js index 7310ebe5a..6efee44e8 100644 --- a/test/test-installation-components.js +++ b/test/test-installation-components.js @@ -234,6 +234,101 @@ async function runTests() { console.log(''); + // ============================================================ + // Test 7: Validate Workflow XML Reference Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 7: Validate Workflow Reference Guard${colors.reset}\n`); + + try { + const searchRoots = [path.join(projectRoot, 'src'), path.join(projectRoot, 'docs')]; + const allowedExtensions = new Set(['.md', '.yaml', '.yml', '.xml']); + const forbiddenRef = 'validate-workflow.xml'; + const excludedFile = path.join(projectRoot, 'src', 'core', 'tasks', 'validate-workflow.xml'); + const offenders = []; + + const walk = async (dir) => { + const entries = await fs.readdir(dir, { withFileTypes: true }); + for (const entry of entries) { + const fullPath = path.join(dir, entry.name); + if (entry.isDirectory()) { + await walk(fullPath); + continue; + } + if (!allowedExtensions.has(path.extname(entry.name))) { + continue; + } + if (fullPath === excludedFile) { + continue; + } + const content = await fs.readFile(fullPath, 'utf8'); + if (content.includes(forbiddenRef)) { + offenders.push(path.relative(projectRoot, fullPath)); + } + } + }; + + for (const root of searchRoots) { + await walk(root); + } + + assert( + offenders.length === 0, + 'No validate-workflow.xml references outside XML source', + offenders.length > 0 ? offenders.join(', ') : '', + ); + } catch (error) { + assert(false, 'Validate workflow reference guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 8: Workflow XML Reference Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 8: Workflow Reference Guard${colors.reset}\n`); + + try { + const searchRoots = [path.join(projectRoot, 'src'), path.join(projectRoot, 'docs'), path.join(projectRoot, 'tools')]; + const allowedExtensions = new Set(['.md', '.yaml', '.yml', '.xml']); + const forbiddenRef = 'workflow.xml'; + const excludedFiles = new Set([ + path.join(projectRoot, 'src', 'core', 'tasks', 'workflow.xml'), + path.join(projectRoot, 'src', 'core', 'workflows', 'advanced-elicitation', 'workflow.xml'), + ]); + const offenders = []; + + const walk = async (dir) => { + const entries = await fs.readdir(dir, { withFileTypes: true }); + for (const entry of entries) { + const fullPath = path.join(dir, entry.name); + if (entry.isDirectory()) { + await walk(fullPath); + continue; + } + if (!allowedExtensions.has(path.extname(entry.name))) { + continue; + } + if (excludedFiles.has(fullPath)) { + continue; + } + const content = await fs.readFile(fullPath, 'utf8'); + if (content.includes(forbiddenRef)) { + offenders.push(path.relative(projectRoot, fullPath)); + } + } + }; + + for (const root of searchRoots) { + await walk(root); + } + + assert(offenders.length === 0, 'No workflow.xml references outside XML source', offenders.length > 0 ? offenders.join(', ') : ''); + } catch (error) { + assert(false, 'Workflow reference guard runs', error.message); + } + + console.log(''); + // ============================================================ // Summary // ============================================================ diff --git a/tools/cli/installers/lib/core/manifest-generator.js b/tools/cli/installers/lib/core/manifest-generator.js index caea790eb..c0b5c655a 100644 --- a/tools/cli/installers/lib/core/manifest-generator.js +++ b/tools/cli/installers/lib/core/manifest-generator.js @@ -148,7 +148,7 @@ class ManifestGenerator { return workflows; } - // Recursively find workflow.yaml files + // Recursively find workflow files const findWorkflows = async (dir, relativePath = '') => { const entries = await fs.readdir(dir, { withFileTypes: true }); diff --git a/tools/cli/installers/lib/ide/_base-ide.js b/tools/cli/installers/lib/ide/_base-ide.js index dce8aee9f..fd3d5f7d3 100644 --- a/tools/cli/installers/lib/ide/_base-ide.js +++ b/tools/cli/installers/lib/ide/_base-ide.js @@ -304,7 +304,7 @@ class BaseIdeSetup { if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config' && entry.name !== 'agents') { const moduleWorkflowsPath = path.join(bmadDir, entry.name, 'workflows'); if (await fs.pathExists(moduleWorkflowsPath)) { - const moduleWorkflows = await this.findWorkflowYamlFiles(moduleWorkflowsPath); + const moduleWorkflows = await this.findWorkflowFiles(moduleWorkflowsPath); workflows.push( ...moduleWorkflows.map((w) => ({ ...w, @@ -324,11 +324,11 @@ class BaseIdeSetup { } /** - * Recursively find workflow.yaml files + * Recursively find workflow files (workflow.yaml or workflow.md) * @param {string} dir - Directory to search * @returns {Array} List of workflow file info objects */ - async findWorkflowYamlFiles(dir) { + async findWorkflowFiles(dir) { const workflows = []; if (!(await fs.pathExists(dir))) { @@ -342,14 +342,24 @@ class BaseIdeSetup { if (entry.isDirectory()) { // Recursively search subdirectories - const subWorkflows = await this.findWorkflowYamlFiles(fullPath); + const subWorkflows = await this.findWorkflowFiles(fullPath); workflows.push(...subWorkflows); - } else if (entry.isFile() && entry.name === 'workflow.yaml') { - // Read workflow.yaml to get name and standalone property + } else if (entry.isFile() && (entry.name === 'workflow.yaml' || entry.name === 'workflow.md')) { + // Read workflow file to get name and standalone property try { const yaml = require('yaml'); const content = await fs.readFile(fullPath, 'utf8'); - const workflowData = yaml.parse(content); + let workflowData = null; + + if (entry.name === 'workflow.yaml') { + workflowData = yaml.parse(content); + } else { + const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/); + if (!frontmatterMatch) { + continue; + } + workflowData = yaml.parse(frontmatterMatch[1]); + } if (workflowData && workflowData.name) { // Workflows are standalone by default unless explicitly false diff --git a/tools/cli/installers/lib/ide/shared/workflow-command-generator.js b/tools/cli/installers/lib/ide/shared/workflow-command-generator.js index 5a23fda2f..c01429397 100644 --- a/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +++ b/tools/cli/installers/lib/ide/shared/workflow-command-generator.js @@ -2,13 +2,13 @@ const path = require('node:path'); const fs = require('fs-extra'); const csv = require('csv-parse/sync'); const chalk = require('chalk'); -const { toColonPath, toDashPath, customAgentColonName, customAgentDashName, BMAD_FOLDER_NAME } = require('./path-utils'); +const { toColonPath, toDashPath, customAgentColonName, customAgentDashName } = require('./path-utils'); /** * Generates command files for each workflow in the manifest */ class WorkflowCommandGenerator { - constructor(bmadFolderName = BMAD_FOLDER_NAME) { + constructor(bmadFolderName = 'bmad') { this.templatePath = path.join(__dirname, '../templates/workflow-command-template.md'); this.bmadFolderName = bmadFolderName; } @@ -67,10 +67,8 @@ class WorkflowCommandGenerator { for (const workflow of allWorkflows) { const commandContent = await this.generateCommandContent(workflow, bmadDir); - // Calculate the relative workflow path (e.g., bmm/workflows/4-implementation/sprint-planning/workflow.yaml) - let workflowRelPath = workflow.path || ''; - // Normalize path separators for cross-platform compatibility - workflowRelPath = workflowRelPath.replaceAll('\\', '/'); + // Calculate the relative workflow path (e.g., bmm/workflows/4-implementation/sprint-planning/workflow.md) + let workflowRelPath = workflow.path; // Remove _bmad/ prefix if present to get relative path from project root // Handle both absolute paths (/path/to/_bmad/...) and relative paths (_bmad/...) if (workflowRelPath.includes('_bmad/')) { @@ -78,15 +76,9 @@ class WorkflowCommandGenerator { if (parts.length > 1) { workflowRelPath = parts.slice(1).join('/'); } - } else if (workflowRelPath.includes('/src/')) { - // Normalize source paths (e.g. .../src/bmm/...) to relative module path (e.g. bmm/...) - const match = workflowRelPath.match(/\/src\/([^/]+)\/(.+)/); - if (match) { - workflowRelPath = `${match[1]}/${match[2]}`; - } } - // Determine if this is a YAML workflow (use normalized path which is guaranteed to be a string) - const isYamlWorkflow = workflowRelPath.endsWith('.yaml') || workflowRelPath.endsWith('.yml'); + // Determine if this is a YAML workflow + const isYamlWorkflow = workflow.path.endsWith('.yaml') || workflow.path.endsWith('.yml'); artifacts.push({ type: 'workflow-command', isYamlWorkflow: isYamlWorkflow, // For template selection @@ -133,8 +125,8 @@ class WorkflowCommandGenerator { const template = await fs.readFile(templatePath, 'utf8'); // Convert source path to installed path - // From: /Users/.../src/bmm/workflows/.../workflow.yaml - // To: {project-root}/_bmad/bmm/workflows/.../workflow.yaml + // From: /Users/.../src/bmm/workflows/.../workflow.md + // To: {project-root}/_bmad/bmm/workflows/.../workflow.md let workflowPath = workflow.path; // Extract the relative path from source @@ -218,9 +210,9 @@ class WorkflowCommandGenerator { ## Execution When running any workflow: -1. LOAD {project-root}/${this.bmadFolderName}/core/tasks/workflow.xml +1. LOAD {project-root}/${this.bmadFolderName}/core/tasks/workflow.md 2. Pass the workflow path as 'workflow-config' parameter -3. Follow workflow.xml instructions EXACTLY +3. Follow workflow.md instructions EXACTLY 4. Save outputs after EACH section ## Modes @@ -292,7 +284,7 @@ When running any workflow: * Write workflow command artifacts using dash format (NEW STANDARD) * Creates flat files like: bmad-bmm-correct-course.md * - * Note: Workflows do NOT have bmad-agent- prefix - only agents do. + * Note: Workflows do NOT have .agent.md suffix - only agents do. * * @param {string} baseCommandsDir - Base commands directory for the IDE * @param {Array} artifacts - Workflow artifacts diff --git a/tools/cli/installers/lib/modules/manager.js b/tools/cli/installers/lib/modules/manager.js index c55dae838..8ee63047f 100644 --- a/tools/cli/installers/lib/modules/manager.js +++ b/tools/cli/installers/lib/modules/manager.js @@ -740,10 +740,10 @@ class ModuleManager { } } - // Check if this is a workflow.yaml file - if (file.endsWith('workflow.yaml')) { + // Check if this is a workflow file (YAML or MD) + if (file.endsWith('workflow.yaml') || file.endsWith('workflow.md')) { await fs.ensureDir(path.dirname(targetFile)); - await this.copyWorkflowYamlStripped(sourceFile, targetFile); + await this.copyWorkflowFileStripped(sourceFile, targetFile); } else { // Copy the file with placeholder replacement await this.copyFileWithPlaceholderReplacement(sourceFile, targetFile); @@ -757,12 +757,23 @@ class ModuleManager { } /** - * Copy workflow.yaml file with web_bundle section stripped + * Copy workflow file with web_bundle section stripped (YAML or MD) * Preserves comments, formatting, and line breaks - * @param {string} sourceFile - Source workflow.yaml file path - * @param {string} targetFile - Target workflow.yaml file path + * @param {string} sourceFile - Source workflow file path + * @param {string} targetFile - Target workflow file path */ - async copyWorkflowYamlStripped(sourceFile, targetFile) { + async copyWorkflowFileStripped(sourceFile, targetFile) { + if (sourceFile.endsWith('.md')) { + let mdContent = await fs.readFile(sourceFile, 'utf8'); + + mdContent = mdContent.replaceAll('_bmad', '_bmad'); + mdContent = mdContent.replaceAll('_bmad', this.bmadFolderName); + mdContent = this.stripWebBundleFromFrontmatter(mdContent); + + await fs.writeFile(targetFile, mdContent, 'utf8'); + return; + } + // Read the source YAML file let yamlContent = await fs.readFile(sourceFile, 'utf8'); @@ -843,6 +854,20 @@ class ModuleManager { } } + stripWebBundleFromFrontmatter(content) { + const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/); + if (!frontmatterMatch) { + return content; + } + + const frontmatter = frontmatterMatch[1] + .split('\n') + .filter((line) => !line.trim().startsWith('web_bundle:')) + .join('\n'); + + return content.replace(frontmatterMatch[0], `---\n${frontmatter}\n---`); + } + /** * Compile .agent.yaml files to .md format in modules * @param {string} sourcePath - Source module path @@ -1151,8 +1176,8 @@ class ModuleManager { // Parse SOURCE workflow path // Handle both _bmad placeholder and hardcoded 'bmad' - // Example: {project-root}/_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml - // Or: {project-root}/bmad/bmm/workflows/4-implementation/create-story/workflow.yaml + // Example: {project-root}/_bmad/bmm/workflows/4-implementation/create-story/workflow.md + // Or: {project-root}/bmad/bmm/workflows/4-implementation/create-story/workflow.md const sourceMatch = sourceWorkflowPath.match(/\{project-root\}\/(?:_bmad)\/([^/]+)\/workflows\/(.+)/); if (!sourceMatch) { console.warn(chalk.yellow(` Could not parse workflow path: ${sourceWorkflowPath}`)); @@ -1163,7 +1188,7 @@ class ModuleManager { // Parse INSTALL workflow path // Handle_bmad - // Example: {project-root}/_bmad/bmgd/workflows/4-production/create-story/workflow.yaml + // Example: {project-root}/_bmad/bmgd/workflows/4-production/create-story/workflow.md const installMatch = installWorkflowPath.match(/\{project-root\}\/(_bmad)\/([^/]+)\/workflows\/(.+)/); if (!installMatch) { console.warn(chalk.yellow(` Could not parse workflow-install path: ${installWorkflowPath}`)); @@ -1173,9 +1198,13 @@ class ModuleManager { const installWorkflowSubPath = installMatch[2]; const sourceModulePath = getModulePath(sourceModule); - const actualSourceWorkflowPath = path.join(sourceModulePath, 'workflows', sourceWorkflowSubPath.replace(/\/workflow\.yaml$/, '')); + const actualSourceWorkflowPath = path.join( + sourceModulePath, + 'workflows', + sourceWorkflowSubPath.replace(/\/workflow\.(yaml|md)$/, ''), + ); - const actualDestWorkflowPath = path.join(targetPath, 'workflows', installWorkflowSubPath.replace(/\/workflow\.yaml$/, '')); + const actualDestWorkflowPath = path.join(targetPath, 'workflows', installWorkflowSubPath.replace(/\/workflow\.(yaml|md)$/, '')); // Check if source workflow exists if (!(await fs.pathExists(actualSourceWorkflowPath))) { @@ -1186,7 +1215,7 @@ class ModuleManager { // Copy the entire workflow folder console.log( chalk.dim( - ` Vendoring: ${sourceModule}/workflows/${sourceWorkflowSubPath.replace(/\/workflow\.yaml$/, '')} โ†’ ${moduleName}/workflows/${installWorkflowSubPath.replace(/\/workflow\.yaml$/, '')}`, + ` Vendoring: ${sourceModule}/workflows/${sourceWorkflowSubPath.replace(/\/workflow\.(yaml|md)$/, '')} โ†’ ${moduleName}/workflows/${installWorkflowSubPath.replace(/\/workflow\.(yaml|md)$/, '')}`, ), ); @@ -1194,9 +1223,13 @@ class ModuleManager { // Copy the workflow directory recursively with placeholder replacement await this.copyDirectoryWithPlaceholderReplacement(actualSourceWorkflowPath, actualDestWorkflowPath); - // Update the workflow.yaml config_source reference + // Update workflow config_source references + const workflowMdPath = path.join(actualDestWorkflowPath, 'workflow.md'); const workflowYamlPath = path.join(actualDestWorkflowPath, 'workflow.yaml'); - if (await fs.pathExists(workflowYamlPath)) { + + if (await fs.pathExists(workflowMdPath)) { + await this.updateWorkflowConfigSource(workflowMdPath, moduleName); + } else if (await fs.pathExists(workflowYamlPath)) { await this.updateWorkflowConfigSource(workflowYamlPath, moduleName); } } @@ -1208,24 +1241,24 @@ class ModuleManager { } /** - * Update workflow.yaml config_source to point to new module - * @param {string} workflowYamlPath - Path to workflow.yaml file + * Update workflow config_source/main_config to point to new module + * @param {string} workflowPath - Path to workflow file * @param {string} newModuleName - New module name to reference */ - async updateWorkflowConfigSource(workflowYamlPath, newModuleName) { - let yamlContent = await fs.readFile(workflowYamlPath, 'utf8'); + async updateWorkflowConfigSource(workflowPath, newModuleName) { + let fileContent = await fs.readFile(workflowPath, 'utf8'); // Replace config_source: "{project-root}/_bmad/OLD_MODULE/config.yaml" // with config_source: "{project-root}/_bmad/NEW_MODULE/config.yaml" // Note: At this point _bmad has already been replaced with actual folder name - const configSourcePattern = /config_source:\s*["']?\{project-root\}\/[^/]+\/[^/]+\/config\.yaml["']?/g; - const newConfigSource = `config_source: "{project-root}/${this.bmadFolderName}/${newModuleName}/config.yaml"`; + const configSourcePattern = /(config_source|main_config):\s*["']?\{project-root\}\/[^/]+\/[^/]+\/config\.yaml["']?/g; + const newConfigSource = `$1: "{project-root}/${this.bmadFolderName}/${newModuleName}/config.yaml"`; - const updatedYaml = yamlContent.replaceAll(configSourcePattern, newConfigSource); + const updatedContent = fileContent.replaceAll(configSourcePattern, newConfigSource); - if (updatedYaml !== yamlContent) { - await fs.writeFile(workflowYamlPath, updatedYaml, 'utf8'); - console.log(chalk.dim(` Updated config_source to: ${this.bmadFolderName}/${newModuleName}/config.yaml`)); + if (updatedContent !== fileContent) { + await fs.writeFile(workflowPath, updatedContent, 'utf8'); + console.log(chalk.dim(` Updated workflow config to: ${this.bmadFolderName}/${newModuleName}/config.yaml`)); } }