From 229fb8240bf04840344446ffda03da5d58736ba5 Mon Sep 17 00:00:00 2001 From: Alex Verkhovsky Date: Fri, 21 Nov 2025 11:34:58 -0700 Subject: [PATCH] feat: implement workflow yaml validation and schema --- package.json | 4 +- .../workflows/brainstorming/workflow.yaml | 2 - src/core/workflows/party-mode/workflow.yaml | 2 - .../workflows/audit-workflow/workflow.yaml | 1 - .../workflows/convert-legacy/workflow.yaml | 1 - .../bmb/workflows/create-agent/workflow.yaml | 2 - .../bmb/workflows/create-module/workflow.yaml | 1 - .../workflow-template/workflow.yaml | 2 - .../workflows/create-workflow/workflow.yaml | 1 - .../bmb/workflows/edit-agent/workflow.yaml | 1 - .../bmb/workflows/edit-module/workflow.yaml | 1 - .../bmb/workflows/edit-workflow/workflow.yaml | 1 - .../bmb/workflows/module-brief/workflow.yaml | 1 - .../brainstorm-game/workflow.yaml | 2 - .../1-preproduction/game-brief/workflow.yaml | 2 - .../bmgd/workflows/2-design/gdd/workflow.yaml | 2 - .../2-design/narrative/workflow.yaml | 2 - .../game-architecture/workflow.yaml | 2 - .../4-production/code-review/workflow.yaml | 1 - .../4-production/correct-course/workflow.yaml | 1 - .../4-production/create-story/workflow.yaml | 1 - .../4-production/dev-story/workflow.yaml | 1 - .../epic-tech-context/workflow.yaml | 1 - .../4-production/retrospective/workflow.yaml | 1 - .../sprint-planning/workflow.yaml | 1 - .../4-production/story-context/workflow.yaml | 1 - .../4-production/story-done/workflow.yaml | 1 - .../4-production/story-ready/workflow.yaml | 1 - .../brainstorm-project/workflow.yaml | 2 - .../1-analysis/domain-research/workflow.yaml | 2 - .../1-analysis/product-brief/workflow.yaml | 2 - .../1-analysis/research/workflow.yaml | 2 - .../create-ux-design/workflow.yaml | 2 - .../2-plan-workflows/prd/workflow.yaml | 2 - .../2-plan-workflows/tech-spec/workflow.yaml | 1 - .../3-solutioning/architecture/workflow.yaml | 2 - .../create-epics-and-stories/workflow.yaml | 2 - .../implementation-readiness/workflow.yaml | 1 - .../code-review/workflow.yaml | 1 - .../correct-course/workflow.yaml | 1 - .../create-story/workflow.yaml | 1 - .../4-implementation/dev-story/workflow.yaml | 1 - .../epic-tech-context/workflow.yaml | 1 - .../retrospective/workflow.yaml | 1 - .../sprint-planning/workflow.yaml | 1 - .../story-context/workflow.yaml | 1 - .../4-implementation/story-done/workflow.yaml | 1 - .../story-ready/workflow.yaml | 1 - .../diagrams/create-dataflow/workflow.yaml | 1 - .../diagrams/create-diagram/workflow.yaml | 1 - .../diagrams/create-flowchart/workflow.yaml | 1 - .../diagrams/create-wireframe/workflow.yaml | 1 - .../workflows/document-project/workflow.yaml | 2 - .../bmm/workflows/testarch/atdd/workflow.yaml | 1 - .../workflows/testarch/automate/workflow.yaml | 1 - .../bmm/workflows/testarch/ci/workflow.yaml | 1 - .../testarch/framework/workflow.yaml | 1 - .../testarch/nfr-assess/workflow.yaml | 1 - .../testarch/test-design/workflow.yaml | 1 - .../testarch/test-review/workflow.yaml | 1 - .../workflows/testarch/trace/workflow.yaml | 1 - .../workflow-status/init/workflow.yaml | 1 - .../workflows/workflow-status/workflow.yaml | 1 - .../workflows/design-thinking/workflow.yaml | 2 - .../innovation-strategy/workflow.yaml | 2 - .../workflows/problem-solving/workflow.yaml | 2 - .../cis/workflows/storytelling/workflow.yaml | 2 - .../invalid/invalid-name-format.workflow.yaml | 9 + .../invalid-standalone-type.workflow.yaml | 10 + .../invalid-template-true.workflow.yaml | 8 + .../invalid-web-bundle-true.workflow.yaml | 8 + .../malformed-config-ref.workflow.yaml | 10 + .../invalid/missing-description.workflow.yaml | 8 + .../missing-instructions.workflow.yaml | 8 + .../invalid/missing-name.workflow.yaml | 8 + .../invalid/unclosed-brace.workflow.yaml | 9 + .../invalid/unknown-config-var.workflow.yaml | 10 + .../invalid/unknown-placeholder.workflow.yaml | 8 + .../valid/complex.workflow.yaml | 41 ++ .../valid/minimal.workflow.yaml | 7 + test/test-workflow-schema.js | 301 ++++++++++++ .../ide/shared/workflow-command-generator.js | 3 +- tools/schema/workflow.js | 449 ++++++++++++++++++ tools/validate-workflow-schema.js | 165 +++++++ 84 files changed, 1062 insertions(+), 92 deletions(-) create mode 100644 test/fixtures/workflow-schema/invalid/invalid-name-format.workflow.yaml create mode 100644 test/fixtures/workflow-schema/invalid/invalid-standalone-type.workflow.yaml create mode 100644 test/fixtures/workflow-schema/invalid/invalid-template-true.workflow.yaml create mode 100644 test/fixtures/workflow-schema/invalid/invalid-web-bundle-true.workflow.yaml create mode 100644 test/fixtures/workflow-schema/invalid/malformed-config-ref.workflow.yaml create mode 100644 test/fixtures/workflow-schema/invalid/missing-description.workflow.yaml create mode 100644 test/fixtures/workflow-schema/invalid/missing-instructions.workflow.yaml create mode 100644 test/fixtures/workflow-schema/invalid/missing-name.workflow.yaml create mode 100644 test/fixtures/workflow-schema/invalid/unclosed-brace.workflow.yaml create mode 100644 test/fixtures/workflow-schema/invalid/unknown-config-var.workflow.yaml create mode 100644 test/fixtures/workflow-schema/invalid/unknown-placeholder.workflow.yaml create mode 100644 test/fixtures/workflow-schema/valid/complex.workflow.yaml create mode 100644 test/fixtures/workflow-schema/valid/minimal.workflow.yaml create mode 100644 test/test-workflow-schema.js create mode 100644 tools/schema/workflow.js create mode 100644 tools/validate-workflow-schema.js diff --git a/package.json b/package.json index 314d5c66..5ce045d9 100644 --- a/package.json +++ b/package.json @@ -43,9 +43,9 @@ "test": "npm run test:schemas && npm run test:install && npm run validate:bundles && npm run validate:schemas && npm run lint && npm run format:check", "test:coverage": "c8 --reporter=text --reporter=html npm run test:schemas", "test:install": "node test/test-installation-components.js", - "test:schemas": "node test/test-agent-schema.js", + "test:schemas": "node test/test-agent-schema.js && node test/test-workflow-schema.js", "validate:bundles": "node tools/validate-bundles.js", - "validate:schemas": "node tools/validate-agent-schema.js" + "validate:schemas": "node tools/validate-agent-schema.js && node tools/validate-workflow-schema.js" }, "lint-staged": { "*.{js,cjs,mjs}": [ diff --git a/src/core/workflows/brainstorming/workflow.yaml b/src/core/workflows/brainstorming/workflow.yaml index 4697f4d4..a23d62fd 100644 --- a/src/core/workflows/brainstorming/workflow.yaml +++ b/src/core/workflows/brainstorming/workflow.yaml @@ -1,7 +1,6 @@ # Brainstorming Session Workflow Configuration name: "brainstorming" description: "Facilitate interactive brainstorming sessions using diverse creative techniques. This workflow facilitates interactive brainstorming sessions using diverse creative techniques. The session is highly interactive, with the AI acting as a facilitator to guide the user through various ideation methods to generate and refine creative solutions." -author: "BMad" # Critical variables load from config_source config_source: "{project-root}/{bmad_folder}/cis/config.yaml" @@ -27,7 +26,6 @@ standalone: true web_bundle: name: "brainstorming" description: "Facilitate interactive brainstorming sessions using diverse creative techniques. This workflow facilitates interactive brainstorming sessions using diverse creative techniques. The session is highly interactive, with the AI acting as a facilitator to guide the user through various ideation methods to generate and refine creative solutions." - author: "BMad" template: "{bmad_folder}/core/workflows/brainstorming/template.md" instructions: "{bmad_folder}/core/workflows/brainstorming/instructions.md" brain_techniques: "{bmad_folder}/core/workflows/brainstorming/brain-methods.csv" diff --git a/src/core/workflows/party-mode/workflow.yaml b/src/core/workflows/party-mode/workflow.yaml index f31a7bb8..758865a7 100644 --- a/src/core/workflows/party-mode/workflow.yaml +++ b/src/core/workflows/party-mode/workflow.yaml @@ -1,7 +1,6 @@ # Party Mode - Multi-Agent Group Discussion Workflow name: "party-mode" description: "Orchestrates group discussions between all installed BMAD agents, enabling natural multi-agent conversations" -author: "BMad" # Critical data sources - manifest and config overrides agent_manifest: "{project-root}/{bmad_folder}/_cfg/agent-manifest.csv" @@ -20,7 +19,6 @@ standalone: true web_bundle: name: "party-mode" description: "Orchestrates group discussions between all installed BMAD agents, enabling natural multi-agent conversations" - author: "BMad" instructions: "{bmad_folder}/core/workflows/party-mode/instructions.md" agent_manifest: "{bmad_folder}/_cfg/agent-manifest.csv" web_bundle_files: diff --git a/src/modules/bmb/workflows/audit-workflow/workflow.yaml b/src/modules/bmb/workflows/audit-workflow/workflow.yaml index b01c55cc..00ba8190 100644 --- a/src/modules/bmb/workflows/audit-workflow/workflow.yaml +++ b/src/modules/bmb/workflows/audit-workflow/workflow.yaml @@ -1,7 +1,6 @@ # Audit Workflow Configuration name: "audit-workflow" description: "Comprehensive workflow quality audit - validates structure, config standards, variable usage, bloat detection, and web_bundle completeness. Performs deep analysis of workflow.yaml, instructions.md, template.md, and web_bundle configuration against BMAD v6 standards." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmb/config.yaml" diff --git a/src/modules/bmb/workflows/convert-legacy/workflow.yaml b/src/modules/bmb/workflows/convert-legacy/workflow.yaml index c2cc40a5..5307655a 100644 --- a/src/modules/bmb/workflows/convert-legacy/workflow.yaml +++ b/src/modules/bmb/workflows/convert-legacy/workflow.yaml @@ -1,7 +1,6 @@ # Convert Legacy - BMAD v4 to v6 Converter Configuration name: "convert-legacy" description: "Converts legacy BMAD v4 or similar items (agents, workflows, modules) to BMad Core compliant format with proper structure and conventions" -author: "BMad" # Critical variables load from config_source config_source: "{project-root}/{bmad_folder}/bmb/config.yaml" diff --git a/src/modules/bmb/workflows/create-agent/workflow.yaml b/src/modules/bmb/workflows/create-agent/workflow.yaml index 5710ac05..1eb46623 100644 --- a/src/modules/bmb/workflows/create-agent/workflow.yaml +++ b/src/modules/bmb/workflows/create-agent/workflow.yaml @@ -1,7 +1,6 @@ # Build Agent Workflow Configuration name: create-agent description: "Interactive workflow to build BMAD Core compliant agents (YAML source compiled to .md during install) with optional brainstorming, persona development, and command structure" -author: "BMad" # Critical variables load from config_source config_source: "{project-root}/{bmad_folder}/bmb/config.yaml" @@ -42,7 +41,6 @@ standalone: true web_bundle: name: "create-agent" description: "Interactive workflow to build BMAD Core compliant agents (simple, expert, or module types) with optional brainstorming for agent ideas, proper persona development, activation rules, and command structure" - author: "BMad" web_bundle_files: - "{bmad_folder}/bmb/workflows/create-agent/instructions.md" - "{bmad_folder}/bmb/workflows/create-agent/checklist.md" diff --git a/src/modules/bmb/workflows/create-module/workflow.yaml b/src/modules/bmb/workflows/create-module/workflow.yaml index a47bdbfb..04273508 100644 --- a/src/modules/bmb/workflows/create-module/workflow.yaml +++ b/src/modules/bmb/workflows/create-module/workflow.yaml @@ -1,7 +1,6 @@ # Build Module Workflow Configuration name: create-module description: "Interactive workflow to build complete BMAD modules with agents, workflows, tasks, and installation infrastructure" -author: "BMad" # Critical variables load from config_source config_source: "{project-root}/{bmad_folder}/bmb/config.yaml" diff --git a/src/modules/bmb/workflows/create-workflow/workflow-template/workflow.yaml b/src/modules/bmb/workflows/create-workflow/workflow-template/workflow.yaml index 7792e61e..222861d4 100644 --- a/src/modules/bmb/workflows/create-workflow/workflow-template/workflow.yaml +++ b/src/modules/bmb/workflows/create-workflow/workflow-template/workflow.yaml @@ -1,7 +1,6 @@ # {TITLE} Workflow Template Configuration name: "{WORKFLOW_CODE}" description: "{WORKFLOW_DESCRIPTION}" -author: "BMad" # Critical variables load from config_source # Add Additional Config Pulled Variables Here @@ -37,7 +36,6 @@ required_tools: #optional, can be omitted web_bundle: #optional, can be omitted name: "{WORKFLOW_CODE}" description: "{WORKFLOW_DESCRIPTION}" - author: "BMad" # Core workflow files (paths relative to {bmad_folder}/ root) instructions: "{bmad_folder}/{module-code}/workflows/{workflow-code}/instructions.md" diff --git a/src/modules/bmb/workflows/create-workflow/workflow.yaml b/src/modules/bmb/workflows/create-workflow/workflow.yaml index 45b0f165..0e271acc 100644 --- a/src/modules/bmb/workflows/create-workflow/workflow.yaml +++ b/src/modules/bmb/workflows/create-workflow/workflow.yaml @@ -1,7 +1,6 @@ # Build Workflow - Workflow Builder Configuration name: create-workflow description: "Interactive workflow builder that guides creation of new BMAD workflows with proper structure and validation for optimal human-AI collaboration. Includes optional brainstorming phase for workflow ideas and design." -author: "BMad Builder" # Critical variables config_source: "{project-root}/{bmad_folder}/bmb/config.yaml" diff --git a/src/modules/bmb/workflows/edit-agent/workflow.yaml b/src/modules/bmb/workflows/edit-agent/workflow.yaml index 499da63c..67cd6245 100644 --- a/src/modules/bmb/workflows/edit-agent/workflow.yaml +++ b/src/modules/bmb/workflows/edit-agent/workflow.yaml @@ -1,7 +1,6 @@ # Edit Agent - Agent Editor Configuration name: "edit-agent" description: "Edit existing BMAD agents while following all best practices and conventions" -author: "BMad" # Critical variables load from config_source config_source: "{project-root}/{bmad_folder}/bmb/config.yaml" diff --git a/src/modules/bmb/workflows/edit-module/workflow.yaml b/src/modules/bmb/workflows/edit-module/workflow.yaml index ae1d2868..d439cbff 100644 --- a/src/modules/bmb/workflows/edit-module/workflow.yaml +++ b/src/modules/bmb/workflows/edit-module/workflow.yaml @@ -1,7 +1,6 @@ # Edit Module - Module Editor Configuration name: "edit-module" description: "Edit existing BMAD modules (structure, agents, workflows, documentation) while following all best practices" -author: "BMad" # Critical variables load from config_source config_source: "{project-root}/{bmad_folder}/bmb/config.yaml" diff --git a/src/modules/bmb/workflows/edit-workflow/workflow.yaml b/src/modules/bmb/workflows/edit-workflow/workflow.yaml index e49c6c93..f7b9c837 100644 --- a/src/modules/bmb/workflows/edit-workflow/workflow.yaml +++ b/src/modules/bmb/workflows/edit-workflow/workflow.yaml @@ -1,7 +1,6 @@ # Edit Workflow - Workflow Editor Configuration name: "edit-workflow" description: "Edit existing BMAD workflows while following all best practices and conventions" -author: "BMad" # Critical variables load from config_source config_source: "{project-root}/{bmad_folder}/bmb/config.yaml" diff --git a/src/modules/bmb/workflows/module-brief/workflow.yaml b/src/modules/bmb/workflows/module-brief/workflow.yaml index fad6e479..4d3576ff 100644 --- a/src/modules/bmb/workflows/module-brief/workflow.yaml +++ b/src/modules/bmb/workflows/module-brief/workflow.yaml @@ -1,7 +1,6 @@ # Module Brief Workflow Configuration name: module-brief description: "Create a comprehensive Module Brief that serves as the blueprint for building new BMAD modules using strategic analysis and creative vision" -author: "BMad Builder" # Critical variables config_source: "{project-root}/{bmad_folder}/bmb/config.yaml" diff --git a/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/workflow.yaml b/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/workflow.yaml index 468a8bb1..f631cee6 100644 --- a/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/workflow.yaml +++ b/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/workflow.yaml @@ -1,7 +1,6 @@ # Brainstorm Game Workflow Configuration name: "brainstorm-game" description: "Facilitate game brainstorming sessions by orchestrating the CIS brainstorming workflow with game-specific context, guidance, and additional game design techniques." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" @@ -29,7 +28,6 @@ standalone: true web_bundle: name: "brainstorm-game" description: "Facilitate game brainstorming sessions by orchestrating the CIS brainstorming workflow with game-specific context, guidance, and additional game design techniques." - author: "BMad" instructions: "{bmad_folder}/bmgd/workflows/1-preproduction/brainstorm-game/instructions.md" template: false web_bundle_files: diff --git a/src/modules/bmgd/workflows/1-preproduction/game-brief/workflow.yaml b/src/modules/bmgd/workflows/1-preproduction/game-brief/workflow.yaml index 13db2b3c..e37323cd 100644 --- a/src/modules/bmgd/workflows/1-preproduction/game-brief/workflow.yaml +++ b/src/modules/bmgd/workflows/1-preproduction/game-brief/workflow.yaml @@ -1,7 +1,6 @@ # Game Brief - Interactive Workflow Configuration name: game-brief description: "Interactive game brief creation workflow that guides users through defining their game vision with multiple input sources and conversational collaboration" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" @@ -26,7 +25,6 @@ standalone: true web_bundle: name: "game-brief" description: "Interactive game brief creation workflow that guides users through defining their game vision with multiple input sources and conversational collaboration" - author: "BMad" instructions: "{bmad_folder}/bmgd/workflows/1-preproduction/game-brief/instructions.md" validation: "{bmad_folder}/bmgd/workflows/1-preproduction/game-brief/checklist.md" template: "{bmad_folder}/bmgd/workflows/1-preproduction/game-brief/template.md" diff --git a/src/modules/bmgd/workflows/2-design/gdd/workflow.yaml b/src/modules/bmgd/workflows/2-design/gdd/workflow.yaml index ee4644df..ef7fc958 100644 --- a/src/modules/bmgd/workflows/2-design/gdd/workflow.yaml +++ b/src/modules/bmgd/workflows/2-design/gdd/workflow.yaml @@ -1,7 +1,6 @@ # Game Design Document (GDD) Workflow name: gdd description: "Game Design Document workflow for all game project levels - from small prototypes to full AAA games. Generates comprehensive GDD with game mechanics, systems, progression, and implementation guidance." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" @@ -49,7 +48,6 @@ standalone: true web_bundle: name: "gdd" description: "Game Design Document workflow for all game project levels - from small prototypes to full AAA games. Generates comprehensive GDD with game mechanics, systems, progression, and implementation guidance." - author: "BMad" instructions: "{bmad_folder}/bmgd/workflows/2-design/gdd/instructions-gdd.md" web_bundle_files: - "{bmad_folder}/bmgd/workflows/2-design/gdd/instructions-gdd.md" diff --git a/src/modules/bmgd/workflows/2-design/narrative/workflow.yaml b/src/modules/bmgd/workflows/2-design/narrative/workflow.yaml index 2bfd7991..f2e0f08b 100644 --- a/src/modules/bmgd/workflows/2-design/narrative/workflow.yaml +++ b/src/modules/bmgd/workflows/2-design/narrative/workflow.yaml @@ -1,7 +1,6 @@ # Narrative Design Workflow name: narrative description: "Narrative design workflow for story-driven games and applications. Creates comprehensive narrative documentation including story structure, character arcs, dialogue systems, and narrative implementation guidance." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" @@ -25,7 +24,6 @@ standalone: true web_bundle: name: "narrative" description: "Narrative design workflow for story-driven games and applications. Creates comprehensive narrative documentation including story structure, character arcs, dialogue systems, and narrative implementation guidance." - author: "BMad" instructions: "{bmad_folder}/bmgd/workflows/2-design/narrative/instructions-narrative.md" web_bundle_files: - "{bmad_folder}/bmgd/workflows/2-design/narrative/instructions-narrative.md" diff --git a/src/modules/bmgd/workflows/3-technical/game-architecture/workflow.yaml b/src/modules/bmgd/workflows/3-technical/game-architecture/workflow.yaml index 0f5c5f5c..45270fe2 100644 --- a/src/modules/bmgd/workflows/3-technical/game-architecture/workflow.yaml +++ b/src/modules/bmgd/workflows/3-technical/game-architecture/workflow.yaml @@ -1,7 +1,6 @@ # Game Architecture Workflow Configuration name: game-architecture description: "Collaborative game architecture workflow for AI-agent consistency. Intelligent, adaptive conversation that produces a decision-focused game architecture document covering engine, systems, networking, and technical design optimized for game development." -author: "BMad" # Critical variables config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" @@ -53,7 +52,6 @@ pattern_categories: "{installed_path}/pattern-categories.csv" default_output_file: "{output_folder}/game-architecture.md" # Workflow metadata -version: "1.3.2" replaces: "architecture" paradigm: "facilitation-driven" execution_time: "30-90 minutes depending on user skill level" diff --git a/src/modules/bmgd/workflows/4-production/code-review/workflow.yaml b/src/modules/bmgd/workflows/4-production/code-review/workflow.yaml index 972363fe..6d2f897c 100644 --- a/src/modules/bmgd/workflows/4-production/code-review/workflow.yaml +++ b/src/modules/bmgd/workflows/4-production/code-review/workflow.yaml @@ -1,7 +1,6 @@ # Review Story Workflow name: code-review description: "Perform a Senior Developer code review on a completed story flagged Ready for Review, leveraging story-context, epic tech-spec, repo docs, MCP servers for latest best-practices, and web search as fallback. Appends structured review notes to the story." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" diff --git a/src/modules/bmgd/workflows/4-production/correct-course/workflow.yaml b/src/modules/bmgd/workflows/4-production/correct-course/workflow.yaml index 7f4850b6..ae08516f 100644 --- a/src/modules/bmgd/workflows/4-production/correct-course/workflow.yaml +++ b/src/modules/bmgd/workflows/4-production/correct-course/workflow.yaml @@ -1,7 +1,6 @@ # Correct Course - Sprint Change Management Workflow name: "correct-course" description: "Navigate significant changes during sprint execution by analyzing impact, proposing solutions, and routing for implementation" -author: "BMad Method" config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" output_folder: "{config_source}:output_folder" diff --git a/src/modules/bmgd/workflows/4-production/create-story/workflow.yaml b/src/modules/bmgd/workflows/4-production/create-story/workflow.yaml index 6846d9ed..a324c85c 100644 --- a/src/modules/bmgd/workflows/4-production/create-story/workflow.yaml +++ b/src/modules/bmgd/workflows/4-production/create-story/workflow.yaml @@ -1,6 +1,5 @@ name: create-story description: "Create the next user story markdown from epics/PRD and architecture, using a standard template and saving to the stories folder" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" diff --git a/src/modules/bmgd/workflows/4-production/dev-story/workflow.yaml b/src/modules/bmgd/workflows/4-production/dev-story/workflow.yaml index e7f530c1..8c832f51 100644 --- a/src/modules/bmgd/workflows/4-production/dev-story/workflow.yaml +++ b/src/modules/bmgd/workflows/4-production/dev-story/workflow.yaml @@ -1,6 +1,5 @@ name: dev-story description: "Execute a story by implementing tasks/subtasks, writing tests, validating, and updating the story file per acceptance criteria" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" diff --git a/src/modules/bmgd/workflows/4-production/epic-tech-context/workflow.yaml b/src/modules/bmgd/workflows/4-production/epic-tech-context/workflow.yaml index b9119098..91cc6892 100644 --- a/src/modules/bmgd/workflows/4-production/epic-tech-context/workflow.yaml +++ b/src/modules/bmgd/workflows/4-production/epic-tech-context/workflow.yaml @@ -1,6 +1,5 @@ name: epic-tech-context description: "Generate a comprehensive Technical Specification from PRD and Architecture with acceptance criteria and traceability mapping" -author: "BMAD BMM" # Critical variables config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" diff --git a/src/modules/bmgd/workflows/4-production/retrospective/workflow.yaml b/src/modules/bmgd/workflows/4-production/retrospective/workflow.yaml index 797564ac..2925b957 100644 --- a/src/modules/bmgd/workflows/4-production/retrospective/workflow.yaml +++ b/src/modules/bmgd/workflows/4-production/retrospective/workflow.yaml @@ -1,7 +1,6 @@ # Retrospective - Epic Completion Review Workflow name: "retrospective" description: "Run after epic completion to review overall success, extract lessons learned, and explore if new information emerged that might impact the next epic" -author: "BMad" config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" output_folder: "{config_source}:output_folder" diff --git a/src/modules/bmgd/workflows/4-production/sprint-planning/workflow.yaml b/src/modules/bmgd/workflows/4-production/sprint-planning/workflow.yaml index f0c2a6f5..06f8fc8b 100644 --- a/src/modules/bmgd/workflows/4-production/sprint-planning/workflow.yaml +++ b/src/modules/bmgd/workflows/4-production/sprint-planning/workflow.yaml @@ -1,6 +1,5 @@ name: sprint-planning description: "Generate and manage the sprint status tracking file for Phase 4 implementation, extracting all epics and stories from epic files and tracking their status through the development lifecycle" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" diff --git a/src/modules/bmgd/workflows/4-production/story-context/workflow.yaml b/src/modules/bmgd/workflows/4-production/story-context/workflow.yaml index ced3e654..b6c1de78 100644 --- a/src/modules/bmgd/workflows/4-production/story-context/workflow.yaml +++ b/src/modules/bmgd/workflows/4-production/story-context/workflow.yaml @@ -1,7 +1,6 @@ # Story Context Creation Workflow name: story-context description: "Assemble a dynamic Story Context XML by pulling latest documentation and existing code/library artifacts relevant to a drafted story" -author: "BMad" # Critical variables config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" diff --git a/src/modules/bmgd/workflows/4-production/story-done/workflow.yaml b/src/modules/bmgd/workflows/4-production/story-done/workflow.yaml index 3b4f60e9..a560184c 100644 --- a/src/modules/bmgd/workflows/4-production/story-done/workflow.yaml +++ b/src/modules/bmgd/workflows/4-production/story-done/workflow.yaml @@ -1,7 +1,6 @@ # Story Done Workflow (DEV Agent) name: story-done description: "Marks a story as done (DoD complete) and moves it from its current status → DONE in the status file. Advances the story queue. Simple status-update workflow with no searching required." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" diff --git a/src/modules/bmgd/workflows/4-production/story-ready/workflow.yaml b/src/modules/bmgd/workflows/4-production/story-ready/workflow.yaml index 3b63de0e..fb61eb16 100644 --- a/src/modules/bmgd/workflows/4-production/story-ready/workflow.yaml +++ b/src/modules/bmgd/workflows/4-production/story-ready/workflow.yaml @@ -1,7 +1,6 @@ # Story Ready Workflow (SM Agent) name: story-ready description: "Marks a drafted story as ready for development and moves it from TODO → IN PROGRESS in the status file. Simple status-update workflow with no searching required." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmgd/config.yaml" diff --git a/src/modules/bmm/workflows/1-analysis/brainstorm-project/workflow.yaml b/src/modules/bmm/workflows/1-analysis/brainstorm-project/workflow.yaml index 427f8e13..04f2fddf 100644 --- a/src/modules/bmm/workflows/1-analysis/brainstorm-project/workflow.yaml +++ b/src/modules/bmm/workflows/1-analysis/brainstorm-project/workflow.yaml @@ -1,7 +1,6 @@ # Brainstorm Project Workflow Configuration name: "brainstorm-project" description: "Facilitate project brainstorming sessions by orchestrating the CIS brainstorming workflow with project-specific context and guidance." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" @@ -28,7 +27,6 @@ standalone: true web_bundle: name: "brainstorm-project" description: "Facilitate project brainstorming sessions by orchestrating the CIS brainstorming workflow with project-specific context and guidance." - author: "BMad" instructions: "{bmad_folder}/bmm/workflows/1-analysis/brainstorm-project/instructions.md" template: false web_bundle_files: diff --git a/src/modules/bmm/workflows/1-analysis/domain-research/workflow.yaml b/src/modules/bmm/workflows/1-analysis/domain-research/workflow.yaml index 6592ed9a..09cfbb5f 100644 --- a/src/modules/bmm/workflows/1-analysis/domain-research/workflow.yaml +++ b/src/modules/bmm/workflows/1-analysis/domain-research/workflow.yaml @@ -1,7 +1,6 @@ # Domain Research Workflow Configuration name: domain-research description: "Collaborative exploration of domain-specific requirements, regulations, and patterns for complex projects" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" @@ -29,7 +28,6 @@ standalone: true web_bundle: name: "domain-research" description: "Collaborative exploration of domain-specific requirements, regulations, and patterns for complex projects" - author: "BMad" # Core workflow files ({bmad_folder}/-relative paths) instructions: "{bmad_folder}/bmm/workflows/1-analysis/domain-research/instructions.md" diff --git a/src/modules/bmm/workflows/1-analysis/product-brief/workflow.yaml b/src/modules/bmm/workflows/1-analysis/product-brief/workflow.yaml index d94b4dc2..15de41a9 100644 --- a/src/modules/bmm/workflows/1-analysis/product-brief/workflow.yaml +++ b/src/modules/bmm/workflows/1-analysis/product-brief/workflow.yaml @@ -1,7 +1,6 @@ # Product Brief - Interactive Workflow Configuration name: product-brief description: "Interactive product brief creation workflow that guides users through defining their product vision with multiple input sources and conversational collaboration" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" @@ -47,7 +46,6 @@ standalone: true web_bundle: name: "product-brief" description: "Interactive product brief creation workflow that guides users through defining their product vision with multiple input sources and conversational collaboration" - author: "BMad" instructions: "{bmad_folder}/bmm/workflows/1-analysis/product-brief/instructions.md" validation: "{bmad_folder}/bmm/workflows/1-analysis/product-brief/checklist.md" template: "{bmad_folder}/bmm/workflows/1-analysis/product-brief/template.md" diff --git a/src/modules/bmm/workflows/1-analysis/research/workflow.yaml b/src/modules/bmm/workflows/1-analysis/research/workflow.yaml index f1e0ca5e..b92c08f3 100644 --- a/src/modules/bmm/workflows/1-analysis/research/workflow.yaml +++ b/src/modules/bmm/workflows/1-analysis/research/workflow.yaml @@ -1,7 +1,6 @@ # Research Workflow - Multi-Type Research System name: research description: "Adaptive research workflow supporting multiple research types: market research, deep research prompt generation, technical/architecture evaluation, competitive intelligence, user research, and domain analysis" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" @@ -46,7 +45,6 @@ standalone: true web_bundle: name: "research" description: "Adaptive research workflow supporting multiple research types: market research, deep research prompt generation, technical/architecture evaluation, competitive intelligence, user research, and domain analysis" - author: "BMad" instructions: "{bmad_folder}/bmm/workflows/1-analysis/research/instructions-router.md" # Router loads specific instruction sets validation: "{bmad_folder}/bmm/workflows/1-analysis/research/checklist.md" web_bundle_files: diff --git a/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml b/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml index ea7bf45d..993eda40 100644 --- a/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml +++ b/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml @@ -1,7 +1,6 @@ # Create UX Design Workflow Configuration name: create-ux-design description: "Collaborative UX design facilitation workflow that creates exceptional user experiences through visual exploration and informed decision-making. Unlike template-driven approaches, this workflow facilitates discovery, generates visual options, and collaboratively designs the UX with the user at every step." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" @@ -62,7 +61,6 @@ standalone: true web_bundle: name: "create-ux-design" description: "Collaborative UX design facilitation workflow that creates exceptional user experiences through visual exploration and informed decision-making. Unlike template-driven approaches, this workflow facilitates discovery, generates visual options, and collaboratively designs the UX with the user at every step." - author: "BMad" # Core workflow files ({bmad_folder}/-relative paths) instructions: "{bmad_folder}/bmm/workflows/2-plan-workflows/create-ux-design/instructions.md" diff --git a/src/modules/bmm/workflows/2-plan-workflows/prd/workflow.yaml b/src/modules/bmm/workflows/2-plan-workflows/prd/workflow.yaml index b6ad6e47..1413964d 100644 --- a/src/modules/bmm/workflows/2-plan-workflows/prd/workflow.yaml +++ b/src/modules/bmm/workflows/2-plan-workflows/prd/workflow.yaml @@ -1,7 +1,6 @@ # Product Requirements Document (PRD) Workflow name: prd description: "Unified PRD workflow for BMad Method and Enterprise Method tracks. Produces strategic PRD and tactical epic breakdown. Hands off to architecture workflow for technical design. Note: Quick Flow track uses tech-spec workflow." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" @@ -54,7 +53,6 @@ standalone: true web_bundle: name: "prd" description: "Unified PRD workflow for BMad Method and Enterprise Method tracks. Produces strategic PRD and tactical epic breakdown. Hands off to architecture workflow for technical design. Note: Quick Flow track uses tech-spec workflow." - author: "BMad" instructions: "{bmad_folder}/bmm/workflows/2-plan-workflows/prd/instructions.md" validation: "{bmad_folder}/bmm/workflows/2-plan-workflows/prd/checklist.md" web_bundle_files: diff --git a/src/modules/bmm/workflows/2-plan-workflows/tech-spec/workflow.yaml b/src/modules/bmm/workflows/2-plan-workflows/tech-spec/workflow.yaml index bee1df7c..ae2e8bb8 100644 --- a/src/modules/bmm/workflows/2-plan-workflows/tech-spec/workflow.yaml +++ b/src/modules/bmm/workflows/2-plan-workflows/tech-spec/workflow.yaml @@ -1,7 +1,6 @@ # Technical Specification name: tech-spec description: "Technical specification workflow for quick-flow projects. Creates focused tech spec and generates epic + stories (1 story for simple changes, 2-5 stories for features). Tech-spec only - no PRD needed." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/3-solutioning/architecture/workflow.yaml b/src/modules/bmm/workflows/3-solutioning/architecture/workflow.yaml index a88e017a..17f133f5 100644 --- a/src/modules/bmm/workflows/3-solutioning/architecture/workflow.yaml +++ b/src/modules/bmm/workflows/3-solutioning/architecture/workflow.yaml @@ -1,7 +1,6 @@ # Architecture Workflow Configuration name: architecture description: "Collaborative architectural decision facilitation for AI-agent consistency. Replaces template-driven architecture with intelligent, adaptive conversation that produces a decision-focused architecture document optimized for preventing agent conflicts." -author: "BMad" # Critical variables config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" @@ -56,7 +55,6 @@ standalone: true web_bundle: name: "architecture" description: "Collaborative architectural decision facilitation for AI-agent consistency. Replaces template-driven architecture with intelligent, adaptive conversation that produces a decision-focused architecture document optimized for preventing agent conflicts." - author: "BMad" # Core workflow files ({bmad_folder}/-relative paths) instructions: "{bmad_folder}/bmm/workflows/3-solutioning/architecture/instructions.md" diff --git a/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.yaml b/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.yaml index fc777cfb..15ac3a50 100644 --- a/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.yaml +++ b/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.yaml @@ -1,7 +1,6 @@ # Epic and Story Decomposition Workflow name: create-epics-and-stories description: "Transform PRD requirements into bite-sized stories organized into deliverable functional epics. This workflow takes a Product Requirements Document (PRD) and breaks it down into epics and user stories that can be easily assigned to development teams. It ensures that all functional requirements are captured in a structured format, making it easier for teams to understand and implement the necessary features." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" @@ -55,7 +54,6 @@ standalone: true web_bundle: name: "create-epics-and-stories" description: "Transform PRD requirements into bite-sized stories organized in epics for 200k context dev agents" - author: "BMad" instructions: "{bmad_folder}/bmm/workflows/3-solutioning/create-epics-and-stories/instructions.md" template: "{bmad_folder}/bmm/workflows/3-solutioning/create-epics-and-stories/epics-template.md" web_bundle_files: diff --git a/src/modules/bmm/workflows/3-solutioning/implementation-readiness/workflow.yaml b/src/modules/bmm/workflows/3-solutioning/implementation-readiness/workflow.yaml index bbb7a715..be7bfd30 100644 --- a/src/modules/bmm/workflows/3-solutioning/implementation-readiness/workflow.yaml +++ b/src/modules/bmm/workflows/3-solutioning/implementation-readiness/workflow.yaml @@ -1,7 +1,6 @@ # Implementation Readiness - Workflow Configuration name: implementation-readiness description: "Validate that PRD, UX Design, Architecture, Epics and Stories are complete and aligned before Phase 4 implementation. Ensures all artifacts cover the MVP requirements with no gaps or contradictions." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/4-implementation/code-review/workflow.yaml b/src/modules/bmm/workflows/4-implementation/code-review/workflow.yaml index 17b018ca..fe6d341c 100644 --- a/src/modules/bmm/workflows/4-implementation/code-review/workflow.yaml +++ b/src/modules/bmm/workflows/4-implementation/code-review/workflow.yaml @@ -1,7 +1,6 @@ # Review Story Workflow name: code-review description: "Perform a Senior Developer code review on a completed story flagged Ready for Review, leveraging story-context, epic tech-spec, repo docs, MCP servers for latest best-practices, and web search as fallback. Appends structured review notes to the story." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/4-implementation/correct-course/workflow.yaml b/src/modules/bmm/workflows/4-implementation/correct-course/workflow.yaml index 16e1ff0c..2aa2c8bb 100644 --- a/src/modules/bmm/workflows/4-implementation/correct-course/workflow.yaml +++ b/src/modules/bmm/workflows/4-implementation/correct-course/workflow.yaml @@ -1,7 +1,6 @@ # Correct Course - Sprint Change Management Workflow name: "correct-course" description: "Navigate significant changes during sprint execution by analyzing impact, proposing solutions, and routing for implementation" -author: "BMad Method" config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" output_folder: "{config_source}:output_folder" diff --git a/src/modules/bmm/workflows/4-implementation/create-story/workflow.yaml b/src/modules/bmm/workflows/4-implementation/create-story/workflow.yaml index f1a1dcc8..9fdf1b54 100644 --- a/src/modules/bmm/workflows/4-implementation/create-story/workflow.yaml +++ b/src/modules/bmm/workflows/4-implementation/create-story/workflow.yaml @@ -1,6 +1,5 @@ name: create-story description: "Create the next user story markdown from epics/PRD and architecture, using a standard template and saving to the stories folder" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/4-implementation/dev-story/workflow.yaml b/src/modules/bmm/workflows/4-implementation/dev-story/workflow.yaml index 8ed19149..2de54320 100644 --- a/src/modules/bmm/workflows/4-implementation/dev-story/workflow.yaml +++ b/src/modules/bmm/workflows/4-implementation/dev-story/workflow.yaml @@ -1,6 +1,5 @@ name: dev-story description: "Execute a story by implementing tasks/subtasks, writing tests, validating, and updating the story file per acceptance criteria" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/4-implementation/epic-tech-context/workflow.yaml b/src/modules/bmm/workflows/4-implementation/epic-tech-context/workflow.yaml index 91a8b593..1fca08b4 100644 --- a/src/modules/bmm/workflows/4-implementation/epic-tech-context/workflow.yaml +++ b/src/modules/bmm/workflows/4-implementation/epic-tech-context/workflow.yaml @@ -1,6 +1,5 @@ name: epic-tech-context description: "Generate a comprehensive Technical Specification from PRD and Architecture with acceptance criteria and traceability mapping" -author: "BMAD BMM" # Critical variables config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml b/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml index 716bb544..0817a7d8 100644 --- a/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml +++ b/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml @@ -1,7 +1,6 @@ # Retrospective - Epic Completion Review Workflow name: "retrospective" description: "Run after epic completion to review overall success, extract lessons learned, and explore if new information emerged that might impact the next epic" -author: "BMad" config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" output_folder: "{config_source}:output_folder" diff --git a/src/modules/bmm/workflows/4-implementation/sprint-planning/workflow.yaml b/src/modules/bmm/workflows/4-implementation/sprint-planning/workflow.yaml index e0309e68..baf3e1e3 100644 --- a/src/modules/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +++ b/src/modules/bmm/workflows/4-implementation/sprint-planning/workflow.yaml @@ -1,6 +1,5 @@ name: sprint-planning description: "Generate and manage the sprint status tracking file for Phase 4 implementation, extracting all epics and stories from epic files and tracking their status through the development lifecycle" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/4-implementation/story-context/workflow.yaml b/src/modules/bmm/workflows/4-implementation/story-context/workflow.yaml index 7cbc2657..50869d43 100644 --- a/src/modules/bmm/workflows/4-implementation/story-context/workflow.yaml +++ b/src/modules/bmm/workflows/4-implementation/story-context/workflow.yaml @@ -1,7 +1,6 @@ # Story Context Creation Workflow name: story-context description: "Assemble a dynamic Story Context XML by pulling latest documentation and existing code/library artifacts relevant to a drafted story" -author: "BMad" # Critical variables config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/4-implementation/story-done/workflow.yaml b/src/modules/bmm/workflows/4-implementation/story-done/workflow.yaml index 1b0108eb..8f36385e 100644 --- a/src/modules/bmm/workflows/4-implementation/story-done/workflow.yaml +++ b/src/modules/bmm/workflows/4-implementation/story-done/workflow.yaml @@ -1,7 +1,6 @@ # Story Done Workflow (DEV Agent) name: story-done description: "Marks a story as done (DoD complete) and moves it from its current status → DONE in the status file. Advances the story queue. Simple status-update workflow with no searching required." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/4-implementation/story-ready/workflow.yaml b/src/modules/bmm/workflows/4-implementation/story-ready/workflow.yaml index 1370eecb..8ee1a6d1 100644 --- a/src/modules/bmm/workflows/4-implementation/story-ready/workflow.yaml +++ b/src/modules/bmm/workflows/4-implementation/story-ready/workflow.yaml @@ -1,7 +1,6 @@ # Story Ready Workflow (SM Agent) name: story-ready description: "Marks a drafted story as ready for development and moves it from TODO → IN PROGRESS in the status file. Simple status-update workflow with no searching required." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/diagrams/create-dataflow/workflow.yaml b/src/modules/bmm/workflows/diagrams/create-dataflow/workflow.yaml index 2532c408..b5d4c68f 100644 --- a/src/modules/bmm/workflows/diagrams/create-dataflow/workflow.yaml +++ b/src/modules/bmm/workflows/diagrams/create-dataflow/workflow.yaml @@ -1,6 +1,5 @@ name: create-excalidraw-dataflow description: "Create data flow diagrams (DFD) in Excalidraw format" -author: "BMad" # Config values config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/diagrams/create-diagram/workflow.yaml b/src/modules/bmm/workflows/diagrams/create-diagram/workflow.yaml index 8013d85d..fff6107a 100644 --- a/src/modules/bmm/workflows/diagrams/create-diagram/workflow.yaml +++ b/src/modules/bmm/workflows/diagrams/create-diagram/workflow.yaml @@ -1,6 +1,5 @@ name: create-excalidraw-diagram description: "Create system architecture diagrams, ERDs, UML diagrams, or general technical diagrams in Excalidraw format" -author: "BMad" # Config values config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/diagrams/create-flowchart/workflow.yaml b/src/modules/bmm/workflows/diagrams/create-flowchart/workflow.yaml index 475b2d80..a3ca8846 100644 --- a/src/modules/bmm/workflows/diagrams/create-flowchart/workflow.yaml +++ b/src/modules/bmm/workflows/diagrams/create-flowchart/workflow.yaml @@ -1,6 +1,5 @@ name: create-excalidraw-flowchart description: "Create a flowchart visualization in Excalidraw format for processes, pipelines, or logic flows" -author: "BMad" # Config values config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/diagrams/create-wireframe/workflow.yaml b/src/modules/bmm/workflows/diagrams/create-wireframe/workflow.yaml index a426ec6d..8788fe80 100644 --- a/src/modules/bmm/workflows/diagrams/create-wireframe/workflow.yaml +++ b/src/modules/bmm/workflows/diagrams/create-wireframe/workflow.yaml @@ -1,6 +1,5 @@ name: create-excalidraw-wireframe description: "Create website or app wireframes in Excalidraw format" -author: "BMad" # Config values config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/document-project/workflow.yaml b/src/modules/bmm/workflows/document-project/workflow.yaml index 7249d969..63e188b4 100644 --- a/src/modules/bmm/workflows/document-project/workflow.yaml +++ b/src/modules/bmm/workflows/document-project/workflow.yaml @@ -1,8 +1,6 @@ # Document Project Workflow Configuration name: "document-project" -version: "1.2.0" description: "Analyzes and documents brownfield projects by scanning codebase, architecture, and patterns to create comprehensive reference documentation for AI-assisted development" -author: "BMad" # Critical variables config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/testarch/atdd/workflow.yaml b/src/modules/bmm/workflows/testarch/atdd/workflow.yaml index 4e6991f2..d2caa6da 100644 --- a/src/modules/bmm/workflows/testarch/atdd/workflow.yaml +++ b/src/modules/bmm/workflows/testarch/atdd/workflow.yaml @@ -1,7 +1,6 @@ # Test Architect workflow: atdd name: testarch-atdd description: "Generate failing acceptance tests before implementation using TDD red-green-refactor cycle" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/testarch/automate/workflow.yaml b/src/modules/bmm/workflows/testarch/automate/workflow.yaml index c2704542..17168c0e 100644 --- a/src/modules/bmm/workflows/testarch/automate/workflow.yaml +++ b/src/modules/bmm/workflows/testarch/automate/workflow.yaml @@ -1,7 +1,6 @@ # Test Architect workflow: automate name: testarch-automate description: "Expand test automation coverage after implementation or analyze existing codebase to generate comprehensive test suite" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/testarch/ci/workflow.yaml b/src/modules/bmm/workflows/testarch/ci/workflow.yaml index 03b09493..2b9d3793 100644 --- a/src/modules/bmm/workflows/testarch/ci/workflow.yaml +++ b/src/modules/bmm/workflows/testarch/ci/workflow.yaml @@ -1,7 +1,6 @@ # Test Architect workflow: ci name: testarch-ci description: "Scaffold CI/CD quality pipeline with test execution, burn-in loops, and artifact collection" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/testarch/framework/workflow.yaml b/src/modules/bmm/workflows/testarch/framework/workflow.yaml index 3ccefdfa..65a4b42e 100644 --- a/src/modules/bmm/workflows/testarch/framework/workflow.yaml +++ b/src/modules/bmm/workflows/testarch/framework/workflow.yaml @@ -1,7 +1,6 @@ # Test Architect workflow: framework name: testarch-framework description: "Initialize production-ready test framework architecture (Playwright or Cypress) with fixtures, helpers, and configuration" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/testarch/nfr-assess/workflow.yaml b/src/modules/bmm/workflows/testarch/nfr-assess/workflow.yaml index 66754945..cfa9ff70 100644 --- a/src/modules/bmm/workflows/testarch/nfr-assess/workflow.yaml +++ b/src/modules/bmm/workflows/testarch/nfr-assess/workflow.yaml @@ -1,7 +1,6 @@ # Test Architect workflow: nfr-assess name: testarch-nfr description: "Assess non-functional requirements (performance, security, reliability, maintainability) before release with evidence-based validation" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/testarch/test-design/workflow.yaml b/src/modules/bmm/workflows/testarch/test-design/workflow.yaml index 2915ae40..7c25e4fc 100644 --- a/src/modules/bmm/workflows/testarch/test-design/workflow.yaml +++ b/src/modules/bmm/workflows/testarch/test-design/workflow.yaml @@ -1,7 +1,6 @@ # Test Architect workflow: test-design name: testarch-test-design description: "Dual-mode workflow: (1) System-level testability review in Solutioning phase, or (2) Epic-level test planning in Implementation phase. Auto-detects mode based on project phase." -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/testarch/test-review/workflow.yaml b/src/modules/bmm/workflows/testarch/test-review/workflow.yaml index 86a8b297..b00bed52 100644 --- a/src/modules/bmm/workflows/testarch/test-review/workflow.yaml +++ b/src/modules/bmm/workflows/testarch/test-review/workflow.yaml @@ -1,7 +1,6 @@ # Test Architect workflow: test-review name: testarch-test-review description: "Review test quality using comprehensive knowledge base and best practices validation" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/testarch/trace/workflow.yaml b/src/modules/bmm/workflows/testarch/trace/workflow.yaml index cbd35e0c..5b170014 100644 --- a/src/modules/bmm/workflows/testarch/trace/workflow.yaml +++ b/src/modules/bmm/workflows/testarch/trace/workflow.yaml @@ -1,7 +1,6 @@ # Test Architect workflow: trace (enhanced with gate decision) name: testarch-trace description: "Generate requirements-to-tests traceability matrix, analyze coverage, and make quality gate decision (PASS/CONCERNS/FAIL/WAIVED)" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/workflow-status/init/workflow.yaml b/src/modules/bmm/workflows/workflow-status/init/workflow.yaml index 13073936..99d0dbf7 100644 --- a/src/modules/bmm/workflows/workflow-status/init/workflow.yaml +++ b/src/modules/bmm/workflows/workflow-status/init/workflow.yaml @@ -1,7 +1,6 @@ # Workflow Init - Initial Project Setup name: workflow-init description: "Initialize a new BMM project by determining level, type, and creating workflow path" -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/bmm/workflows/workflow-status/workflow.yaml b/src/modules/bmm/workflows/workflow-status/workflow.yaml index 761d41c0..8501457d 100644 --- a/src/modules/bmm/workflows/workflow-status/workflow.yaml +++ b/src/modules/bmm/workflows/workflow-status/workflow.yaml @@ -1,7 +1,6 @@ # Workflow Status - Master Router and Status Tracker name: workflow-status description: 'Lightweight status checker - answers "what should I do now?" for any agent. Reads YAML status file for workflow tracking. Use workflow-init for new projects.' -author: "BMad" # Critical variables from config config_source: "{project-root}/{bmad_folder}/bmm/config.yaml" diff --git a/src/modules/cis/workflows/design-thinking/workflow.yaml b/src/modules/cis/workflows/design-thinking/workflow.yaml index 5befcde1..b3ec983f 100644 --- a/src/modules/cis/workflows/design-thinking/workflow.yaml +++ b/src/modules/cis/workflows/design-thinking/workflow.yaml @@ -1,7 +1,6 @@ # Design Thinking Workflow Configuration name: "design-thinking" description: "Guide human-centered design processes using empathy-driven methodologies. This workflow walks through the design thinking phases - Empathize, Define, Ideate, Prototype, and Test - to create solutions deeply rooted in user needs." -author: "BMad" # Critical variables load from config_source config_source: "{project-root}/{bmad_folder}/cis/config.yaml" @@ -29,7 +28,6 @@ standalone: true web_bundle: name: "design-thinking" description: "Guide human-centered design processes using empathy-driven methodologies. This workflow walks through the design thinking phases - Empathize, Define, Ideate, Prototype, and Test - to create solutions deeply rooted in user needs." - author: "BMad" instructions: "{bmad_folder}/cis/workflows/design-thinking/instructions.md" template: "{bmad_folder}/cis/workflows/design-thinking/template.md" web_bundle_files: diff --git a/src/modules/cis/workflows/innovation-strategy/workflow.yaml b/src/modules/cis/workflows/innovation-strategy/workflow.yaml index 5cd86b87..2edfe2fb 100644 --- a/src/modules/cis/workflows/innovation-strategy/workflow.yaml +++ b/src/modules/cis/workflows/innovation-strategy/workflow.yaml @@ -1,7 +1,6 @@ # Innovation Strategy Workflow Configuration name: "innovation-strategy" description: "Identify disruption opportunities and architect business model innovation. This workflow guides strategic analysis of markets, competitive dynamics, and business model innovation to uncover sustainable competitive advantages and breakthrough opportunities." -author: "BMad" # Critical variables load from config_source config_source: "{project-root}/{bmad_folder}/cis/config.yaml" @@ -29,7 +28,6 @@ standalone: true web_bundle: name: "innovation-strategy" description: "Identify disruption opportunities and architect business model innovation. This workflow guides strategic analysis of markets, competitive dynamics, and business model innovation to uncover sustainable competitive advantages and breakthrough opportunities." - author: "BMad" instructions: "{bmad_folder}/cis/workflows/innovation-strategy/instructions.md" template: "{bmad_folder}/cis/workflows/innovation-strategy/template.md" web_bundle_files: diff --git a/src/modules/cis/workflows/problem-solving/workflow.yaml b/src/modules/cis/workflows/problem-solving/workflow.yaml index 18d36dd2..ac950e6f 100644 --- a/src/modules/cis/workflows/problem-solving/workflow.yaml +++ b/src/modules/cis/workflows/problem-solving/workflow.yaml @@ -1,7 +1,6 @@ # Problem Solving Workflow Configuration name: "problem-solving" description: "Apply systematic problem-solving methodologies to crack complex challenges. This workflow guides through problem diagnosis, root cause analysis, creative solution generation, evaluation, and implementation planning using proven frameworks." -author: "BMad" # Critical variables load from config_source config_source: "{project-root}/{bmad_folder}/cis/config.yaml" @@ -29,7 +28,6 @@ standalone: true web_bundle: name: "problem-solving" description: "Apply systematic problem-solving methodologies to crack complex challenges. This workflow guides through problem diagnosis, root cause analysis, creative solution generation, evaluation, and implementation planning using proven frameworks." - author: "BMad" instructions: "{bmad_folder}/cis/workflows/problem-solving/instructions.md" template: "{bmad_folder}/cis/workflows/problem-solving/template.md" web_bundle_files: diff --git a/src/modules/cis/workflows/storytelling/workflow.yaml b/src/modules/cis/workflows/storytelling/workflow.yaml index 4e3bff42..942a918a 100644 --- a/src/modules/cis/workflows/storytelling/workflow.yaml +++ b/src/modules/cis/workflows/storytelling/workflow.yaml @@ -1,7 +1,6 @@ # Storytelling Workflow Configuration name: "storytelling" description: "Craft compelling narratives using proven story frameworks and techniques. This workflow guides users through structured narrative development, applying appropriate story frameworks to create emotionally resonant and engaging stories for any purpose." -author: "BMad" # Critical variables load from config_source config_source: "{project-root}/{bmad_folder}/cis/config.yaml" @@ -29,7 +28,6 @@ standalone: true web_bundle: name: "storytelling" description: "Craft compelling narratives using proven story frameworks and techniques. This workflow guides users through structured narrative development, applying appropriate story frameworks to create emotionally resonant and engaging stories for any purpose." - author: "BMad" instructions: "{bmad_folder}/cis/workflows/storytelling/instructions.md" template: "{bmad_folder}/cis/workflows/storytelling/template.md" web_bundle_files: diff --git a/test/fixtures/workflow-schema/invalid/invalid-name-format.workflow.yaml b/test/fixtures/workflow-schema/invalid/invalid-name-format.workflow.yaml new file mode 100644 index 00000000..f6e942ba --- /dev/null +++ b/test/fixtures/workflow-schema/invalid/invalid-name-format.workflow.yaml @@ -0,0 +1,9 @@ +# Expected: FAIL +# Error code: custom +# Error path: name +# Error message: kebab-case + +name: InvalidWorkflow_Name +description: Workflow with invalid name format +author: Test Author +instructions: "{project-root}/path/to/instructions.md" diff --git a/test/fixtures/workflow-schema/invalid/invalid-standalone-type.workflow.yaml b/test/fixtures/workflow-schema/invalid/invalid-standalone-type.workflow.yaml new file mode 100644 index 00000000..72249609 --- /dev/null +++ b/test/fixtures/workflow-schema/invalid/invalid-standalone-type.workflow.yaml @@ -0,0 +1,10 @@ +# Expected: FAIL +# Error code: invalid_type +# Error path: standalone +# Error message: boolean + +name: test-workflow +description: Test workflow +author: Test Author +instructions: "{project-root}/path/to/instructions.md" +standalone: "yes" diff --git a/test/fixtures/workflow-schema/invalid/invalid-template-true.workflow.yaml b/test/fixtures/workflow-schema/invalid/invalid-template-true.workflow.yaml new file mode 100644 index 00000000..5f8784d7 --- /dev/null +++ b/test/fixtures/workflow-schema/invalid/invalid-template-true.workflow.yaml @@ -0,0 +1,8 @@ +# Expected: FAIL +# Error code: invalid_union +# Error message: Invalid input + +name: test-workflow +description: Test workflow +instructions: "{project-root}/path/instructions.md" +template: true diff --git a/test/fixtures/workflow-schema/invalid/invalid-web-bundle-true.workflow.yaml b/test/fixtures/workflow-schema/invalid/invalid-web-bundle-true.workflow.yaml new file mode 100644 index 00000000..445d19d9 --- /dev/null +++ b/test/fixtures/workflow-schema/invalid/invalid-web-bundle-true.workflow.yaml @@ -0,0 +1,8 @@ +# Expected: FAIL +# Error code: invalid_union +# Error message: Invalid input + +name: test-workflow +description: Test workflow +instructions: "{project-root}/path/instructions.md" +web_bundle: true diff --git a/test/fixtures/workflow-schema/invalid/malformed-config-ref.workflow.yaml b/test/fixtures/workflow-schema/invalid/malformed-config-ref.workflow.yaml new file mode 100644 index 00000000..14d02c34 --- /dev/null +++ b/test/fixtures/workflow-schema/invalid/malformed-config-ref.workflow.yaml @@ -0,0 +1,10 @@ +# Expected: FAIL +# Error code: custom +# Error message: Malformed config reference + +name: test-workflow +description: Test workflow with malformed config reference +author: Test Author +instructions: "{project-root}/path/instructions.md" +config_source: "{project-root}/.bmad/config.yaml" +output_folder: "{config_source}output_folder" diff --git a/test/fixtures/workflow-schema/invalid/missing-description.workflow.yaml b/test/fixtures/workflow-schema/invalid/missing-description.workflow.yaml new file mode 100644 index 00000000..a2417006 --- /dev/null +++ b/test/fixtures/workflow-schema/invalid/missing-description.workflow.yaml @@ -0,0 +1,8 @@ +# Expected: FAIL +# Error code: invalid_type +# Error path: description +# Error message: expected string, received undefined + +name: test-workflow +author: Test Author +instructions: "{project-root}/path/to/instructions.md" diff --git a/test/fixtures/workflow-schema/invalid/missing-instructions.workflow.yaml b/test/fixtures/workflow-schema/invalid/missing-instructions.workflow.yaml new file mode 100644 index 00000000..dcc29c4c --- /dev/null +++ b/test/fixtures/workflow-schema/invalid/missing-instructions.workflow.yaml @@ -0,0 +1,8 @@ +# Expected: FAIL +# Error code: invalid_type +# Error path: instructions +# Error message: expected string, received undefined + +name: test-workflow +description: Test workflow +author: Test Author diff --git a/test/fixtures/workflow-schema/invalid/missing-name.workflow.yaml b/test/fixtures/workflow-schema/invalid/missing-name.workflow.yaml new file mode 100644 index 00000000..61b0e349 --- /dev/null +++ b/test/fixtures/workflow-schema/invalid/missing-name.workflow.yaml @@ -0,0 +1,8 @@ +# Expected: FAIL +# Error code: invalid_type +# Error path: name +# Error message: expected string, received undefined + +description: Missing name field +author: Test Author +instructions: "{project-root}/path/to/instructions.md" diff --git a/test/fixtures/workflow-schema/invalid/unclosed-brace.workflow.yaml b/test/fixtures/workflow-schema/invalid/unclosed-brace.workflow.yaml new file mode 100644 index 00000000..b0b012b9 --- /dev/null +++ b/test/fixtures/workflow-schema/invalid/unclosed-brace.workflow.yaml @@ -0,0 +1,9 @@ +# Expected: FAIL +# Error code: custom +# Error message: unclosed braces + +name: test-workflow +description: Test workflow with unclosed brace +author: Test Author +instructions: "{project-root}/path/instructions.md" +output_folder: "{project-root/docs" diff --git a/test/fixtures/workflow-schema/invalid/unknown-config-var.workflow.yaml b/test/fixtures/workflow-schema/invalid/unknown-config-var.workflow.yaml new file mode 100644 index 00000000..f2db59eb --- /dev/null +++ b/test/fixtures/workflow-schema/invalid/unknown-config-var.workflow.yaml @@ -0,0 +1,10 @@ +# Expected: FAIL +# Error code: custom +# Error message: Unknown config variable + +name: test-workflow +description: Test workflow with typo in config variable +author: Test Author +instructions: "{project-root}/path/instructions.md" +config_source: "{project-root}/.bmad/config.yaml" +output_folder: "{config_source}:ouput_folder" diff --git a/test/fixtures/workflow-schema/invalid/unknown-placeholder.workflow.yaml b/test/fixtures/workflow-schema/invalid/unknown-placeholder.workflow.yaml new file mode 100644 index 00000000..179fee6f --- /dev/null +++ b/test/fixtures/workflow-schema/invalid/unknown-placeholder.workflow.yaml @@ -0,0 +1,8 @@ +# Expected: FAIL +# Error code: custom +# Error message: Unknown path placeholder + +name: test-workflow +description: Test workflow with typo in placeholder +author: Test Author +instructions: "{project-rot}/path/instructions.md" diff --git a/test/fixtures/workflow-schema/valid/complex.workflow.yaml b/test/fixtures/workflow-schema/valid/complex.workflow.yaml new file mode 100644 index 00000000..bd17d48e --- /dev/null +++ b/test/fixtures/workflow-schema/valid/complex.workflow.yaml @@ -0,0 +1,41 @@ +# Expected: PASS +# Valid complex workflow with all optional fields + +name: complex-workflow +description: A complex workflow with all features +standalone: true +template: "{installed_path}/template.md" +instructions: "{installed_path}/instructions.md" +validation: "{installed_path}/checklist.md" +config_source: "{project-root}/.bmad/bmm/config.yaml" +installed_path: "{project-root}/.bmad/bmm/workflows/complex-workflow" +default_output_file: "{output_folder}/output.md" +autonomous: false + +input_file_patterns: + architecture: + description: "System architecture" + whole: "{output_folder}/*architecture*.md" + sharded: "{output_folder}/*architecture*/*.md" + load_strategy: "FULL_LOAD" + epics: + description: "Epic files" + sharded_single: "{output_folder}/*epic*/epic-{{epic_num}}.md" + load_strategy: "SELECTIVE_LOAD" + +exit_triggers: + - "*exit" + - "*quit" + +web_bundle: + name: "complex-workflow" + description: "Web bundle for complex workflow" + instructions: "{bmad_folder}/workflows/complex/instructions.md" + web_bundle_files: + - "{bmad_folder}/workflows/complex/instructions.md" + - "{bmad_folder}/workflows/complex/template.md" + +# Custom workflow variables +output_folder: "{config_source}:output_folder" +user_name: "{config_source}:user_name" +date: system-generated diff --git a/test/fixtures/workflow-schema/valid/minimal.workflow.yaml b/test/fixtures/workflow-schema/valid/minimal.workflow.yaml new file mode 100644 index 00000000..f37e4096 --- /dev/null +++ b/test/fixtures/workflow-schema/valid/minimal.workflow.yaml @@ -0,0 +1,7 @@ +# Expected: PASS +# Valid minimal workflow with only required fields + +name: minimal-workflow +description: A minimal valid workflow +author: Test Author +instructions: "{project-root}/path/to/instructions.md" diff --git a/test/test-workflow-schema.js b/test/test-workflow-schema.js new file mode 100644 index 00000000..22e5b5d8 --- /dev/null +++ b/test/test-workflow-schema.js @@ -0,0 +1,301 @@ +/** + * Workflow Schema Validation Test Runner + * + * Runs all test fixtures and verifies expected outcomes. + * Reports pass/fail for each test and overall coverage statistics. + * + * Usage: node test/test-workflow-schema.js + * Exit codes: 0 = all tests pass, 1 = test failures + * + * TODO: Extract shared test utilities (parseTestMetadata, validateError, parsePathString, colors) + * into a common test helper module to reduce duplication with test-agent-schema.js + */ + +const fs = require('node:fs'); +const path = require('node:path'); +const yaml = require('js-yaml'); +const { validateWorkflowFile } = require('../tools/schema/workflow.js'); +const { glob } = require('glob'); + +// ANSI color codes +const colors = { + reset: '\u001B[0m', + green: '\u001B[32m', + red: '\u001B[31m', + yellow: '\u001B[33m', + blue: '\u001B[34m', + cyan: '\u001B[36m', + dim: '\u001B[2m', +}; + +/** + * Parse test metadata from YAML comments + * @param {string} filePath + * @returns {{shouldPass: boolean, errorExpectation?: object}} + */ +function parseTestMetadata(filePath) { + const content = fs.readFileSync(filePath, 'utf8'); + const lines = content.split('\n'); + + let shouldPass = true; + const errorExpectation = {}; + + for (const line of lines) { + if (line.includes('Expected: PASS')) { + shouldPass = true; + } else if (line.includes('Expected: FAIL')) { + shouldPass = false; + } + + // Parse error metadata + const codeMatch = line.match(/^# Error code: (.+)$/); + if (codeMatch) { + errorExpectation.code = codeMatch[1].trim(); + } + + const pathMatch = line.match(/^# Error path: (.+)$/); + if (pathMatch) { + errorExpectation.path = pathMatch[1].trim(); + } + + const messageMatch = line.match(/^# Error message: (.+)$/); + if (messageMatch) { + errorExpectation.message = messageMatch[1].trim(); + } + } + + return { + shouldPass, + errorExpectation: Object.keys(errorExpectation).length > 0 ? errorExpectation : null, + }; +} + +/** + * Convert dot-notation path string to array + * e.g., "name" => ["name"] + */ +function parsePathString(pathString) { + return pathString + .replaceAll(/\[(\d+)\]/g, '.$1') + .split('.') + .map((part) => { + const num = parseInt(part, 10); + return isNaN(num) ? part : num; + }); +} + +/** + * Validate error against expectations + * @param {object} error - Zod error issue + * @param {object} expectation - Expected error structure + * @returns {{valid: boolean, reason?: string}} + */ +function validateError(error, expectation) { + if (expectation.code && error.code !== expectation.code) { + return { valid: false, reason: `Expected code "${expectation.code}", got "${error.code}"` }; + } + + if (expectation.path) { + const expectedPath = parsePathString(expectation.path); + const actualPath = error.path; + + if (JSON.stringify(expectedPath) !== JSON.stringify(actualPath)) { + return { + valid: false, + reason: `Expected path ${JSON.stringify(expectedPath)}, got ${JSON.stringify(actualPath)}`, + }; + } + } + + if (expectation.message && !error.message.includes(expectation.message)) { + return { + valid: false, + reason: `Expected message to include "${expectation.message}", got "${error.message}"`, + }; + } + + return { valid: true }; +} + +/** + * Run a single test case + * @param {string} filePath + * @returns {{passed: boolean, message: string}} + */ +function runTest(filePath) { + const metadata = parseTestMetadata(filePath); + const { shouldPass, errorExpectation } = metadata; + + try { + const fileContent = fs.readFileSync(filePath, 'utf8'); + let workflowData; + + try { + workflowData = yaml.load(fileContent); + } catch (parseError) { + if (shouldPass) { + return { + passed: false, + message: `Expected PASS but got YAML parse error: ${parseError.message}`, + }; + } + return { + passed: true, + message: 'Got expected YAML parse error', + }; + } + + const result = validateWorkflowFile(filePath, workflowData); + + if (result.success && shouldPass) { + return { + passed: true, + message: 'Validation passed as expected', + }; + } + + if (!result.success && !shouldPass) { + const actualError = result.error.issues[0]; + + if (errorExpectation) { + const validation = validateError(actualError, errorExpectation); + + if (!validation.valid) { + return { + passed: false, + message: `Error validation failed: ${validation.reason}`, + }; + } + + return { + passed: true, + message: `Got expected error (${errorExpectation.code}): ${actualError.message}`, + }; + } + + return { + passed: true, + message: `Got expected validation error: ${actualError?.message}`, + }; + } + + if (result.success && !shouldPass) { + return { + passed: false, + message: 'Expected validation to FAIL but it PASSED', + }; + } + + if (!result.success && shouldPass) { + return { + passed: false, + message: `Expected validation to PASS but it FAILED: ${result.error.issues[0]?.message}`, + }; + } + + return { + passed: false, + message: 'Unexpected test state', + }; + } catch (error) { + return { + passed: false, + message: `Test execution error: ${error.message}`, + }; + } +} + +/** + * Main test runner + */ +async function main() { + console.log(`${colors.cyan}╔═══════════════════════════════════════════════════════════╗${colors.reset}`); + console.log(`${colors.cyan}║ Workflow Schema Validation Test Suite ║${colors.reset}`); + console.log(`${colors.cyan}╚═══════════════════════════════════════════════════════════╝${colors.reset}\n`); + + // Find all test fixtures + const testFiles = await glob('test/fixtures/workflow-schema/**/*.workflow.yaml', { + cwd: path.join(__dirname, '..'), + absolute: true, + }); + + if (testFiles.length === 0) { + console.log(`${colors.yellow}⚠️ No test fixtures found${colors.reset}`); + process.exit(0); + } + + console.log(`Found ${colors.cyan}${testFiles.length}${colors.reset} test fixture(s)\n`); + + // Group tests by category + const categories = {}; + for (const testFile of testFiles) { + const relativePath = path.relative(path.join(__dirname, 'fixtures/workflow-schema'), testFile); + const parts = relativePath.split(path.sep); + const validInvalid = parts[0]; // 'valid' or 'invalid' + const category = parts[1] || 'general'; // category folder or 'general' + + const categoryKey = `${validInvalid}/${category}`; + if (!categories[categoryKey]) { + categories[categoryKey] = []; + } + categories[categoryKey].push(testFile); + } + + // Run tests by category + let totalTests = 0; + let passedTests = 0; + const failures = []; + + for (const [categoryKey, files] of Object.entries(categories).sort()) { + const [validInvalid, category] = categoryKey.split('/'); + const categoryLabel = category.replaceAll('-', ' ').toUpperCase(); + const validLabel = validInvalid === 'valid' ? '✅' : '❌'; + + console.log(`${colors.blue}${validLabel} ${categoryLabel} (${validInvalid})${colors.reset}`); + + for (const testFile of files) { + totalTests++; + const testName = path.basename(testFile, '.workflow.yaml'); + const result = runTest(testFile); + + if (result.passed) { + passedTests++; + console.log(` ${colors.green}✓${colors.reset} ${testName} ${colors.dim}${result.message}${colors.reset}`); + } else { + console.log(` ${colors.red}✗${colors.reset} ${testName} ${colors.red}${result.message}${colors.reset}`); + failures.push({ + file: path.relative(process.cwd(), testFile), + message: result.message, + }); + } + } + console.log(''); + } + + // Summary + console.log(`${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}`); + console.log(`${colors.cyan}Test Results:${colors.reset}`); + console.log(` Total: ${totalTests}`); + console.log(` Passed: ${colors.green}${passedTests}${colors.reset}`); + console.log(` Failed: ${passedTests === totalTests ? colors.green : colors.red}${totalTests - passedTests}${colors.reset}`); + console.log(`${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}\n`); + + // Report failures + if (failures.length > 0) { + console.log(`${colors.red}❌ FAILED TESTS:${colors.reset}\n`); + for (const failure of failures) { + console.log(`${colors.red}✗${colors.reset} ${failure.file}`); + console.log(` ${failure.message}\n`); + } + process.exit(1); + } + + console.log(`${colors.green}✨ All tests passed!${colors.reset}\n`); + process.exit(0); +} + +// Run +main().catch((error) => { + console.error(`${colors.red}Fatal error:${colors.reset}`, error); + process.exit(1); +}); 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 39c2c2e0..c8915aea 100644 --- a/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +++ b/tools/cli/installers/lib/ide/shared/workflow-command-generator.js @@ -127,8 +127,7 @@ class WorkflowCommandGenerator { .replaceAll('{{description}}', workflow.description) .replaceAll('{{workflow_path}}', workflowPath) .replaceAll('{bmad_folder}', this.bmadFolderName) - .replaceAll('{{interactive}}', workflow.interactive) - .replaceAll('{{author}}', workflow.author || 'BMAD'); + .replaceAll('{{interactive}}', workflow.interactive); } /** diff --git a/tools/schema/workflow.js b/tools/schema/workflow.js new file mode 100644 index 00000000..21dc63c3 --- /dev/null +++ b/tools/schema/workflow.js @@ -0,0 +1,449 @@ +// Zod schema definition for workflow.yaml files +const { z } = require('zod'); + +const KEBAB_CASE_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/; + +// Public API --------------------------------------------------------------- + +/** + * Validate a workflow YAML payload against the schema. + * Exposed as the single public entry point, so callers do not reach into schema internals. + * + * @param {string} filePath Path to the workflow file (for error reporting). + * @param {unknown} workflowYaml Parsed YAML content. + * @returns {object} Result with success, data/error, and warnings array + */ +function validateWorkflowFile(filePath, workflowYaml) { + const schema = workflowSchema(); + const result = schema.safeParse(workflowYaml); + const warnings = collectUnknownFieldWarnings(workflowYaml); + return { ...result, warnings }; +} + +module.exports = { validateWorkflowFile }; + +// Canonical lists of known variable references (extracted from 65 real workflows) +// These are used to validate variable references and catch typos + +const KNOWN_PATH_PLACEHOLDERS = [ + 'agent_filename', + 'bmad_folder', + 'custom_agent_location', + 'custom_module_location', + 'custom_workflow_location', + 'date', + 'epic_id', + 'epic_num', + 'game_name', + 'installed_path', + 'item_name', + 'item_type', + 'module_code', + 'output_folder', + 'path', + 'prev_epic_num', + 'project-root', + 'project_name', + 'reference_agents', + 'research_type', + 'shared_path', + 'sprint_artifacts', + 'status_file', + 'story_dir', + 'story_id', + 'story_key', + 'story_path', + 'target_module', + 'test_dir', + 'timestamp', + 'workflow_name', + 'workflow_template_path', +]; + +const KNOWN_CONFIG_VARIABLES = [ + 'communication_language', + 'custom_agent_location', + 'custom_module_location', + 'custom_workflow_location', + 'document_output_language', + 'game_dev_experience', + 'output_folder', + 'project_name', + 'sprint_artifacts', + 'user_name', + 'user_skill_level', +]; + +const KNOWN_TEMPLATE_VARIABLES = [ + 'agent_filename', + 'date', + 'epic_id', + 'epic_num', + 'game_name', + 'item_name', + 'item_type', + 'module_code', + 'prev_epic_num', + 'project_name', + 'research_type', + 'story_key', + 'target_module', + 'workflow_name', +]; + +// Internal helpers --------------------------------------------------------- + +/** + * Build a Zod schema for validating a single workflow definition. + * + * @returns {import('zod').ZodSchema} Configured Zod schema instance. + */ +function workflowSchema() { + return z + .object({ + name: createKebabCaseString('name'), + description: createNonEmptyString('description'), + standalone: z.boolean().optional(), + template: z.union([z.literal(false), z.string()]).optional(), + instructions: createNonEmptyString('instructions'), + validation: z.string().optional(), + config_source: z.string().optional(), + installed_path: z.string().optional(), + output_folder: z.string().optional(), + user_name: z.string().optional(), + communication_language: z.string().optional(), + date: z.string().optional(), + brain_techniques: z.string().optional(), + validation_output_file: z.string().optional(), + required_tools: z.array(z.union([z.string(), z.object({ description: z.string().optional() }).catchall(z.unknown())])).optional(), + default_output_file: z.string().optional(), + autonomous: z.boolean().optional(), + web_bundle: z.union([z.literal(false), buildWebBundleSchema()]).optional(), + input_file_patterns: z.record(z.string(), buildInputFilePatternSchema()).optional(), + exit_triggers: z.array(createNonEmptyString('exit_triggers[]')).optional(), + + // Common optional fields (often injected variables or context) + document_output_language: z.string().optional(), + user_skill_level: z.string().optional(), + sprint_artifacts: z.string().optional(), + sprint_status: z.string().optional(), + game_dev_experience: z.string().optional(), + variables: z.record(z.string(), z.unknown()).optional(), + checklist: z.string().optional(), + story_dir: z.string().optional(), + story_file: z.string().optional(), + context_file: z.string().optional(), + game_types_csv: z.string().optional(), + game_type_guides: z.string().optional(), + game_context: z.string().optional(), + game_brain_methods: z.string().optional(), + core_brainstorming: z.string().optional(), + decision_catalog: z.string().optional(), + architecture_patterns: z.string().optional(), + pattern_categories: z.string().optional(), + replaces: z.string().optional(), + paradigm: z.string().optional(), + execution_time: z.string().optional(), + features: z.array(z.string()).optional(), + project_context: z.string().optional(), + + // Additional common fields + tags: z.array(z.string()).optional(), + execution_hints: z.record(z.string(), z.unknown()).optional(), + project_name: z.string().optional(), + library: z.string().optional(), + helpers: z.string().optional(), + templates: z.string().optional(), + json_validation: z.string().optional(), + shared_path: z.string().optional(), + }) + .catchall(z.unknown()) // Allow unknown fields for dynamic workflow variables + .superRefine((data, ctx) => { + // Validate variable references in all string values + validateVariableReferences(data, [], ctx); + }); +} + +/** + * Schema for web_bundle object when it's not a boolean. + */ +function buildWebBundleSchema() { + return z + .object({ + name: createNonEmptyString('web_bundle.name').optional(), + description: createNonEmptyString('web_bundle.description').optional(), + instructions: createNonEmptyString('web_bundle.instructions').optional(), + web_bundle_files: z.array(createNonEmptyString('web_bundle.web_bundle_files[]')).optional(), + validation: z.string().optional(), + template: z.union([z.literal(false), z.string()]).optional(), + existing_workflows: z.array(z.unknown()).optional(), + }) + .catchall(z.unknown()); // Allow custom fields like agent_manifest, author, etc. +} + +/** + * Schema for individual input_file_patterns entries. + */ +function buildInputFilePatternSchema() { + return z + .object({ + description: createNonEmptyString('input_file_patterns[].description').optional(), + whole: z.string().optional(), + sharded: z.string().optional(), + sharded_index: z.string().optional(), + sharded_single: z.string().optional(), + pattern: z.string().optional(), // Legacy support + load_strategy: z.enum(['FULL_LOAD', 'SELECTIVE_LOAD', 'INDEX_GUIDED']).optional(), + }) + .strict(); // Warn about unknown fields - patterns have a defined schema +} + +/** + * Recursively validate variable references in all string values. + * Checks for: + * 1. Malformed syntax (unclosed braces, invalid patterns) + * 2. Unknown placeholders/variables (warns about potential typos) + * + * @param {any} obj - Object to validate + * @param {Array} path - Current path in object tree + * @param {import('zod').RefinementCtx} ctx - Zod context for adding issues + */ +function collectUnknownFieldWarnings(workflowYaml) { + const warnings = []; + if (typeof workflowYaml === 'object' && workflowYaml !== null) { + const knownFields = new Set([ + 'name', + 'description', + 'standalone', + 'template', + 'instructions', + 'validation', + 'config_source', + 'installed_path', + 'output_folder', + 'user_name', + 'communication_language', + 'date', + 'brain_techniques', + 'validation_output_file', + 'required_tools', + 'default_output_file', + 'autonomous', + 'web_bundle', + 'input_file_patterns', + 'exit_triggers', + // Added common fields + 'document_output_language', + 'user_skill_level', + 'sprint_artifacts', + 'sprint_status', + 'game_dev_experience', + 'variables', + 'checklist', + 'story_dir', + 'story_file', + 'context_file', + 'game_types_csv', + 'game_type_guides', + 'game_context', + 'game_brain_methods', + 'core_brainstorming', + 'decision_catalog', + 'architecture_patterns', + 'pattern_categories', + 'replaces', + 'paradigm', + 'execution_time', + 'features', + 'project_context', + // Additional common fields + 'tags', + 'execution_hints', + 'project_name', + 'library', + 'helpers', + 'templates', + 'json_validation', + 'shared_path', + ]); + for (const key of Object.keys(workflowYaml)) { + if (!knownFields.has(key)) { + warnings.push({ + path: [key], + message: `Unknown field '${key}' - not in workflow schema. This may be a workflow-specific variable or a typo.`, + }); + } + } + // web_bundle unknown fields + if (workflowYaml.web_bundle && typeof workflowYaml.web_bundle === 'object') { + const knownWebBundleFields = new Set([ + 'name', + 'description', + 'instructions', + 'web_bundle_files', + 'validation', + 'template', + 'existing_workflows', + ]); + for (const key of Object.keys(workflowYaml.web_bundle)) { + if (!knownWebBundleFields.has(key)) { + warnings.push({ + path: ['web_bundle', key], + message: `Unknown field 'web_bundle.${key}' - not in web_bundle schema. This may be a custom field or a typo.`, + }); + } + } + } + // input_file_patterns unknown fields + if (workflowYaml.input_file_patterns && typeof workflowYaml.input_file_patterns === 'object') { + const knownPatternFields = new Set([ + 'description', + 'whole', + 'sharded', + 'sharded_index', + 'sharded_single', + 'load_strategy', + 'pattern', + ]); + for (const [patternName, pattern] of Object.entries(workflowYaml.input_file_patterns)) { + if (typeof pattern === 'object' && pattern !== null) { + for (const key of Object.keys(pattern)) { + if (!knownPatternFields.has(key)) { + warnings.push({ + path: ['input_file_patterns', patternName, key], + message: `Unknown field 'input_file_patterns.${patternName}.${key}' - not in pattern schema. This may be a typo.`, + }); + } + } + } + } + } + } + return warnings; +} + +/** + * Recursively validate variable references in all string values. + * + * @param {any} data - Data to validate + * @param {Array} path - Current path + * @param {import('zod').RefinementCtx} ctx - Zod context + */ +function validateVariableReferences(data, path, ctx) { + if (typeof data === 'string') { + validateStringReferences(data, path, ctx); + return; + } + + if (Array.isArray(data)) { + for (const [index, item] of data.entries()) { + validateVariableReferences(item, [...path, index], ctx); + } + return; + } + + if (typeof data === 'object' && data !== null) { + for (const [key, value] of Object.entries(data)) { + validateVariableReferences(value, [...path, key], ctx); + } + } +} + +/** + * Validate variable references in a single string value. + */ +function validateStringReferences(str, path, ctx) { + // Check for unclosed braces + const openBraces = (str.match(/\{/g) || []).length; + const closeBraces = (str.match(/\}/g) || []).length; + if (openBraces !== closeBraces) { + ctx.addIssue({ + code: 'custom', + path, + message: `Malformed variable reference: unclosed braces (${openBraces} open, ${closeBraces} close)`, + }); + return; + } + + // Extract and validate path placeholders: {placeholder} + const pathPlaceholderMatches = str.matchAll(/\{([a-z][a-z0-9_-]*)\}/g); + for (const match of pathPlaceholderMatches) { + const placeholder = match[1]; + // Skip config_source as it's a special keyword + if (placeholder === 'config_source') continue; + + if (!KNOWN_PATH_PLACEHOLDERS.includes(placeholder)) { + ctx.addIssue({ + code: 'custom', + path, + message: `Unknown path placeholder: {${placeholder}} - possible typo? Known placeholders: ${KNOWN_PATH_PLACEHOLDERS.slice(0, 5).join(', ')}...`, + }); + } + } + + // Extract and validate config variables: {config_source}:variable + const configMatches = str.matchAll(/\{config_source\}:([a-z][a-z0-9_]*)/g); + for (const match of configMatches) { + const variable = match[1]; + if (!KNOWN_CONFIG_VARIABLES.includes(variable)) { + ctx.addIssue({ + code: 'custom', + path, + message: `Unknown config variable: {config_source}:${variable} - possible typo? Known variables: ${KNOWN_CONFIG_VARIABLES.slice(0, 5).join(', ')}...`, + }); + } + } + + // Extract and validate template variables: {{variable}} + const templateMatches = str.matchAll(/\{\{([a-z][a-z0-9_]*)\}\}/g); + for (const match of templateMatches) { + const variable = match[1]; + if (!KNOWN_TEMPLATE_VARIABLES.includes(variable)) { + ctx.addIssue({ + code: 'custom', + path, + message: `Unknown template variable: {{${variable}}} - possible typo? Known variables: ${KNOWN_TEMPLATE_VARIABLES.slice(0, 5).join(', ')}...`, + }); + } + } + + // Check for malformed config_source references (missing colon) + if (str.includes('{config_source}') && !/\{config_source\}:[a-z]/.test(str)) { + const malformedMatch = str.match(/\{config_source\}([^:]|$)/); + if (malformedMatch) { + ctx.addIssue({ + code: 'custom', + path, + message: 'Malformed config reference: {config_source} must be followed by :variable_name', + }); + } + } +} + +// Primitive validators ----------------------------------------------------- + +/** + * Create a validator for non-empty strings. + * @param {string} label Field label for error messages. + */ +function createNonEmptyString(label) { + return z.string().refine((value) => value.trim().length > 0, { + message: `${label} must be a non-empty string`, + }); +} + +/** + * Create a validator for kebab-case strings. + * @param {string} label Field label for error messages. + */ +function createKebabCaseString(label) { + return z.string().refine( + (value) => { + const trimmed = value.trim(); + return trimmed.length > 0 && KEBAB_CASE_PATTERN.test(trimmed); + }, + { + message: `${label} must be kebab-case (lowercase words separated by hyphen)`, + }, + ); +} diff --git a/tools/validate-workflow-schema.js b/tools/validate-workflow-schema.js new file mode 100644 index 00000000..2548450f --- /dev/null +++ b/tools/validate-workflow-schema.js @@ -0,0 +1,165 @@ +/** + * Workflow Schema Validator CLI + * + * Scans all *.workflow.yaml files in src/ + * and validates them against the Zod schema. + * + * Usage: node tools/validate-workflow-schema.js [project_root] + * Exit codes: 0 = success, 1 = validation failures + * + * Optional argument: + * project_root - Directory to scan (defaults to BMAD repo root) + */ + +const { glob } = require('glob'); +const yaml = require('js-yaml'); +const fs = require('node:fs'); +const path = require('node:path'); +const { validateWorkflowFile } = require('./schema/workflow.js'); + +/** + * Main validation routine + * @param {string} [customProjectRoot] - Optional project root to scan (for testing) + */ +async function main(customProjectRoot) { + console.log('🔍 Scanning for workflow files...\n'); + + // Determine project root: use custom path if provided, otherwise default to repo root + const project_root = customProjectRoot || path.join(__dirname, '..'); + + // Find all workflow files + const workflowFiles = await glob('src/**/workflow.yaml', { + cwd: project_root, + absolute: true, + ignore: ['**/node_modules/**', '**/workflow-template/**'], // Exclude templates and node_modules + }); + + if (workflowFiles.length === 0) { + console.log('❌ No workflow files found. This likely indicates a configuration error.'); + console.log(' Expected to find workflow.yaml files in src/'); + process.exit(1); + } + + console.log(`Found ${workflowFiles.length} workflow file(s)\n`); + + const errors = []; + const warnings = []; + + // Validate each file + for (const filePath of workflowFiles) { + const relativePath = path.relative(process.cwd(), filePath); + + try { + const fileContent = fs.readFileSync(filePath, 'utf8'); + const workflowData = yaml.load(fileContent); + + const result = validateWorkflowFile(relativePath, workflowData); + + if (result.success) { + // Filter out "Unknown field" warnings from the per-file output + const relevantWarnings = (result.warnings || []).filter((w) => !w.message.startsWith('Unknown field')); + + if (relevantWarnings.length > 0) { + console.log(`⚠️ ${relativePath} (passed with warnings)`); + warnings.push({ + file: relativePath, + issues: relevantWarnings, + }); + } else { + console.log(`✅ ${relativePath}`); + } + + // Still collect ALL warnings (including unknown fields) for the summary + if (result.warnings && result.warnings.length > 0) { + const unknownFieldWarnings = result.warnings.filter((w) => w.message.startsWith('Unknown field')); + if (unknownFieldWarnings.length > 0) { + warnings.push({ + file: relativePath, + issues: unknownFieldWarnings, + silent: true, // Mark as silent so we don't double-print in the loop below if mixed + }); + } + } + } else { + errors.push({ + file: relativePath, + issues: result.error.issues, + }); + } + } catch (error) { + errors.push({ + file: relativePath, + issues: [ + { + code: 'parse_error', + message: `Failed to parse YAML: ${error.message}`, + path: [], + }, + ], + }); + } + } + + // Report warnings + if (warnings.length > 0) { + const unknownFields = new Map(); + + for (const { file, issues } of warnings) { + for (const issue of issues) { + const pathString = issue.path.length > 0 ? issue.path.join('.') : '(root)'; + // Only aggregate "Unknown field" warnings + if (issue.message.startsWith('Unknown field')) { + if (!unknownFields.has(pathString)) { + unknownFields.set(pathString, []); + } + unknownFields.get(pathString).push(file); + } else { + // Print non-unknown-field warnings immediately (e.g. malformed vars) + console.log(`\n⚠️ Warning in ${file}:`); + console.log(` Path: ${pathString}`); + console.log(` Message: ${issue.message}`); + } + } + } + + if (unknownFields.size > 0) { + console.log('\nℹ️ Unknown Fields Summary (not in schema, possibly custom variables):'); + const sortedFields = [...unknownFields.entries()].sort((a, b) => a[0].localeCompare(b[0])); + + for (const [field, files] of sortedFields) { + console.log(` - ${field} (${files.length} files)`); + } + console.log('\n (Run with --verbose to see specific files for each field)'); + } + } + + // Report errors + if (errors.length > 0) { + console.log('\n❌ Validation failed for the following files:\n'); + + for (const { file, issues } of errors) { + console.log(`\n📄 ${file}`); + for (const issue of issues) { + const pathString = issue.path.length > 0 ? issue.path.join('.') : '(root)'; + console.log(` Path: ${pathString}`); + console.log(` Error: ${issue.message}`); + if (issue.code) { + console.log(` Code: ${issue.code}`); + } + } + } + + console.log(`\n\n💥 ${errors.length} file(s) failed validation`); + process.exit(1); + } + + console.log(`\n✨ All ${workflowFiles.length} workflow file(s) passed validation!\n`); + process.exit(0); +} + +// Run with optional command-line argument for project root +const customProjectRoot = process.argv[2]; +main(customProjectRoot).catch((error) => { + console.error('Fatal error:', error); + process.exit(1); +});