diff --git a/.augment/code_review_guidelines.yaml b/.augment/code_review_guidelines.yaml index 02e4f2b95..08677c8c0 100644 --- a/.augment/code_review_guidelines.yaml +++ b/.augment/code_review_guidelines.yaml @@ -56,7 +56,7 @@ areas: - "src/**/workflows/**" rules: - id: "workflow_entry_point_required" - description: "Every workflow folder must have workflow.yaml, workflow.md, or workflow.xml as entry point" + description: "Every workflow folder must have workflow.md (or workflow-*.md variant) as entry point" severity: "high" - id: "sharded_workflow_steps_folder" @@ -64,7 +64,7 @@ areas: severity: "high" - id: "standard_workflow_instructions" - description: "Standard workflows using workflow.yaml must include instructions.md for execution guidance" + description: "Standard workflows using workflow.md should include instructions.md for execution guidance" severity: "medium" - id: "workflow_step_limit" @@ -75,11 +75,10 @@ areas: # WORKFLOW ENTRY FILE RULES # ============================================ workflow_definitions: - description: "Workflow entry files (workflow.yaml, workflow.md, workflow.xml)" + description: "Workflow entry files (workflow.md variants)" globs: - - "src/**/workflows/**/workflow.yaml" - "src/**/workflows/**/workflow.md" - - "src/**/workflows/**/workflow.xml" + - "src/**/workflows/**/workflow-*.md" rules: - id: "workflow_name_required" description: "Workflow entry files must define 'name' field in frontmatter or root element" diff --git a/README.md b/README.md index e36d6e36a..04cddc68d 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,15 @@ Products, platforms, complex features — structured planning then build: Every step tells you what's next. Optional phases (brainstorming, research, UX design) are available when you need them — ask `/bmad-help` anytime. For a detailed walkthrough, see the [Getting Started Tutorial](http://docs.bmad-method.org/tutorials/getting-started/). +### Workflow Path Resolution + +BMad workflow/task files often reference placeholders such as `{project-root}` and installed paths like `{project-root}/_bmad/...`. + +- In installed projects, `{project-root}` resolves to the consuming repository root where BMAD is installed. +- `_bmad/...` paths point to the installed BMAD runtime content in that repository. +- In this source repository, equivalent source files typically live under `src/...`. +- When a workflow must run directly from source (without install), use explicit `src/...` paths in that workflow step. + ## Modules BMad Method extends with official modules for specialized domains. Modules are available during installation and can be added to your project at any time. After the V6 beta period these will also be available as Plugins and Granular Skills. diff --git a/docs/how-to/customize-bmad.md b/docs/how-to/customize-bmad.md index 9ebb7884f..ea67c1084 100644 --- a/docs/how-to/customize-bmad.md +++ b/docs/how-to/customize-bmad.md @@ -96,7 +96,7 @@ Add custom entries to the agent's display menu. Each item needs a `trigger`, a t ```yaml menu: - trigger: my-workflow - workflow: '{project-root}/my-custom/workflows/my-workflow.yaml' + workflow: '{project-root}/my-custom/workflows/my-workflow.md' description: My custom workflow - trigger: deploy action: '#deploy-prompt' diff --git a/docs/reference/commands.md b/docs/reference/commands.md index 1ecca7516..67255ddba 100644 --- a/docs/reference/commands.md +++ b/docs/reference/commands.md @@ -27,7 +27,7 @@ The installer uses templates for each command type: | Command type | What the generated file does | | --- | --- | | **Agent launcher** | Loads the agent persona file, activates its menu, and stays in character | -| **Workflow command** | Loads the workflow engine (`workflow.xml`) and passes the workflow config | +| **Workflow command** | Loads the workflow engine (`workflow.md`) and passes the workflow config | | **Task command** | Loads a standalone task file and follows its instructions | | **Tool command** | Loads a standalone tool file and follows its instructions | diff --git a/docs/tutorials/getting-started.md b/docs/tutorials/getting-started.md index f8dbdad2f..dee65a26d 100644 --- a/docs/tutorials/getting-started.md +++ b/docs/tutorials/getting-started.md @@ -65,11 +65,7 @@ The installer creates two folders: - `_bmad/` — agents, workflows, tasks, and configuration - `_bmad-output/` — empty for now, but this is where your artifacts will be saved -Open your AI IDE in the project folder. Run the `help` workflow (`/bmad-help`) to see what to do next — it detects what you've completed and recommends the next step. - -:::note[How to Load Agents and Run Workflows] -Each workflow has a **slash command** you run in your IDE (e.g., `/bmad-bmm-create-prd`). Running a workflow command automatically loads the appropriate agent — you don't need to load agents separately. You can also load an agent directly for general conversation (e.g., `/bmad-agent-bmm-pm` for the PM agent). -::: +Open your AI IDE in the project folder. Run the `help` workflow (`bmad-help` on most platforms) to see what to do next — it detects what you've completed and recommends the next step. :::caution[Fresh Chats] Always start a fresh chat for each workflow. This prevents context limitations from causing issues. @@ -82,29 +78,29 @@ Work through phases 1-3. **Use fresh chats for each workflow.** ### Phase 1: Analysis (Optional) All workflows in this phase are optional: -- **brainstorming** (`/bmad-brainstorming`) — Guided ideation -- **research** (`/bmad-bmm-research`) — Market and technical research -- **create-product-brief** (`/bmad-bmm-create-product-brief`) — Recommended foundation document +- **brainstorming** (`bmad-bmm-brainstorming`) — Guided ideation +- **research** (`bmad-bmm-research`) — Market and technical research +- **create-product-brief** (`bmad-bmm-create-product-brief`) — Recommended foundation document ### Phase 2: Planning (Required) **For BMad Method and Enterprise tracks:** -1. Load the **PM agent** (`/bmad-agent-bmm-pm`) in a new chat -2. Run the `prd` workflow (`/bmad-bmm-create-prd`) +1. Load the **PM agent** in a new chat +2. Run the `create-prd` workflow (`bmad-bmm-create-prd`) 3. Output: `PRD.md` **For Quick Flow track:** -- Use the `quick-spec` workflow (`/bmad-bmm-quick-spec`) instead of PRD, then skip to implementation +- Use the `quick-spec` workflow instead of PRD, then skip to implementation :::note[UX Design (Optional)] -If your project has a user interface, load the **UX-Designer agent** (`/bmad-agent-bmm-ux-designer`) and run the UX design workflow (`/bmad-bmm-create-ux-design`) after creating your PRD. +If your project has a user interface, load the **UX-Designer agent** and run the UX design workflow after creating your PRD. ::: ### Phase 3: Solutioning (BMad Method/Enterprise) **Create Architecture** -1. Load the **Architect agent** (`/bmad-agent-bmm-architect`) in a new chat -2. Run `create-architecture` (`/bmad-bmm-create-architecture`) +1. Load the **Architect agent** in a new chat +2. Run `create-architecture` (`bmad-bmm-create-architecture`) 3. Output: Architecture document with technical decisions **Create Epics and Stories** @@ -113,13 +109,13 @@ If your project has a user interface, load the **UX-Designer agent** (`/bmad-age Epics and stories are now created *after* architecture. This produces better quality stories because architecture decisions (database, API patterns, tech stack) directly affect how work should be broken down. ::: -1. Load the **PM agent** (`/bmad-agent-bmm-pm`) in a new chat -2. Run `create-epics-and-stories` (`/bmad-bmm-create-epics-and-stories`) +1. Load the **PM agent** in a new chat +2. Run `create-epics-and-stories` (`bmad-bmm-create-epics-and-stories`) 3. The workflow uses both PRD and Architecture to create technically-informed stories **Implementation Readiness Check** *(Highly Recommended)* -1. Load the **Architect agent** (`/bmad-agent-bmm-architect`) in a new chat -2. Run `check-implementation-readiness` (`/bmad-bmm-check-implementation-readiness`) +1. Load the **Architect agent** in a new chat +2. Run `check-implementation-readiness` (`bmad-bmm-check-implementation-readiness`) 3. Validates cohesion across all planning documents ## Step 2: Build Your Project @@ -128,19 +124,19 @@ Once planning is complete, move to implementation. **Each workflow should run in ### Initialize Sprint Planning -Load the **SM agent** (`/bmad-agent-bmm-sm`) and run `sprint-planning` (`/bmad-bmm-sprint-planning`). This creates `sprint-status.yaml` to track all epics and stories. +Load the **SM agent** and run `sprint-planning` (`bmad-bmm-sprint-planning`). This creates `sprint-status.yaml` to track all epics and stories. ### The Build Cycle For each story, repeat this cycle with fresh chats: -| Step | Agent | Workflow | Command | Purpose | -| ---- | ----- | -------------- | -------------------------- | ---------------------------------- | -| 1 | SM | `create-story` | `/bmad-bmm-create-story` | Create story file from epic | -| 2 | DEV | `dev-story` | `/bmad-bmm-dev-story` | Implement the story | -| 3 | DEV | `code-review` | `/bmad-bmm-code-review` | Quality validation *(recommended)* | +| Step | Agent | Workflow | Purpose | +| ---- | ----- | -------------- | ---------------------------------- | +| 1 | SM | `create-story` (`bmad-bmm-create-story`) | Create story file from epic | +| 2 | DEV | `dev-story` (`bmad-bmm-dev-story`) | Implement the story | +| 3 | DEV | `code-review` (`bmad-bmm-code-review`) | Quality validation *(recommended)* | -After completing all stories in an epic, load the **SM agent** (`/bmad-agent-bmm-sm`) and run `retrospective` (`/bmad-bmm-retrospective`). +After completing all stories in an epic, load the **SM agent** and run `retrospective` (`bmad-bmm-retrospective`). ## What You've Accomplished @@ -166,17 +162,17 @@ your-project/ ## Quick Reference -| Workflow | Command | Agent | Purpose | -| -------------------------------- | ------------------------------------------ | --------- | ------------------------------------ | -| `help` | `/bmad-help` | Any | Get guidance on what to do next | -| `prd` | `/bmad-bmm-create-prd` | PM | Create Product Requirements Document | -| `create-architecture` | `/bmad-bmm-create-architecture` | Architect | Create architecture document | -| `create-epics-and-stories` | `/bmad-bmm-create-epics-and-stories` | PM | Break down PRD into epics | -| `check-implementation-readiness` | `/bmad-bmm-check-implementation-readiness` | Architect | Validate planning cohesion | -| `sprint-planning` | `/bmad-bmm-sprint-planning` | SM | Initialize sprint tracking | -| `create-story` | `/bmad-bmm-create-story` | SM | Create a story file | -| `dev-story` | `/bmad-bmm-dev-story` | DEV | Implement a story | -| `code-review` | `/bmad-bmm-code-review` | DEV | Review implemented code | +| Workflow | Slash Command | Agent | Purpose | +| -------------------------------- | ------------------------------------- | --------- | ------------------------------------ | +| `help` | `bmad-help` | Any | Get guidance on what to do next | +| `create-prd` | `bmad-bmm-create-prd` | PM | Create Product Requirements Document | +| `create-architecture` | `bmad-bmm-create-architecture` | Architect | Create architecture document | +| `create-epics-and-stories` | `bmad-bmm-create-epics-and-stories` | PM | Break down PRD into epics | +| `check-implementation-readiness` | `bmad-bmm-check-implementation-readiness` | Architect | Validate planning cohesion | +| `sprint-planning` | `bmad-bmm-sprint-planning` | SM | Initialize sprint tracking | +| `create-story` | `bmad-bmm-create-story` | SM | Create a story file | +| `dev-story` | `bmad-bmm-dev-story` | DEV | Implement a story | +| `code-review` | `bmad-bmm-code-review` | DEV | Review implemented code | ## Common Questions @@ -184,10 +180,10 @@ your-project/ Only for BMad Method and Enterprise tracks. Quick Flow skips from tech-spec to implementation. **Can I change my plan later?** -Yes. The SM agent has a `correct-course` workflow (`/bmad-bmm-correct-course`) for handling scope changes. +Yes. The SM agent has a `correct-course` workflow for handling scope changes. **What if I want to brainstorm first?** -Load the Analyst agent (`/bmad-agent-bmm-analyst`) and run `brainstorming` (`/bmad-brainstorming`) before starting your PRD. +Load the Analyst agent and run `brainstorming` (`bmad-bmm-brainstorming`) before starting your PRD. **Do I need to follow a strict order?** Not strictly. Once you learn the flow, you can run workflows directly using the Quick Reference above. @@ -196,14 +192,14 @@ Not strictly. Once you learn the flow, you can run workflows directly using the - **During workflows** — Agents guide you with questions and explanations - **Community** — [Discord](https://discord.gg/gk8jAdXWmj) (#bmad-method-help, #report-bugs-and-issues) -- **Stuck?** — Run `help` (`/bmad-help`) to see what to do next +- **Stuck?** — Run `help` (`bmad-help` on most platforms) to see what to do next ## Key Takeaways :::tip[Remember These] - **Always use fresh chats** — Start a new chat for each workflow - **Track matters** — Quick Flow uses quick-spec; Method/Enterprise need PRD and architecture -- **Use `help` (`/bmad-help`) when stuck** — It detects your progress and suggests next steps +- **Use `help` when stuck** — It detects your progress and suggests next steps ::: Ready to start? Install BMad and let the agents guide you through your first project. diff --git a/src/bmm/agents/analyst.agent.yaml b/src/bmm/agents/analyst.agent.yaml index 28120d098..7814ee609 100644 --- a/src/bmm/agents/analyst.agent.yaml +++ b/src/bmm/agents/analyst.agent.yaml @@ -39,5 +39,5 @@ agent: description: "[CB] Create Brief: A guided experience to nail down your product idea into an executive brief" - trigger: DP or fuzzy match on document-project - workflow: "{project-root}/_bmad/bmm/workflows/document-project/workflow.yaml" + workflow: "{project-root}/_bmad/bmm/workflows/document-project/workflow.md" description: "[DP] Document Project: Analyze an existing project to produce useful documentation for both human and LLM" diff --git a/src/bmm/agents/dev.agent.yaml b/src/bmm/agents/dev.agent.yaml index c707124d0..6de3d2c97 100644 --- a/src/bmm/agents/dev.agent.yaml +++ b/src/bmm/agents/dev.agent.yaml @@ -30,9 +30,9 @@ agent: menu: - trigger: DS or fuzzy match on dev-story - workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/dev-story/workflow.yaml" + workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/dev-story/workflow.md" description: "[DS] Dev Story: Write the next or specified stories tests and code." - trigger: CR or fuzzy match on code-review - workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/code-review/workflow.yaml" + workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/code-review/workflow.md" description: "[CR] Code Review: Initiate a comprehensive code review across multiple quality facets. For best results, use a fresh context and a different quality LLM if available" diff --git a/src/bmm/agents/pm.agent.yaml b/src/bmm/agents/pm.agent.yaml index 30377a682..267797053 100644 --- a/src/bmm/agents/pm.agent.yaml +++ b/src/bmm/agents/pm.agent.yaml @@ -40,5 +40,5 @@ agent: description: "[IR] Implementation Readiness: Ensure the PRD, UX, and Architecture and Epics and Stories List are all aligned" - trigger: CC or fuzzy match on correct-course - workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/correct-course/workflow.yaml" + workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/correct-course/workflow.md" description: "[CC] Course Correction: Use this so we can determine how to proceed if major need for change is discovered mid implementation" diff --git a/src/bmm/agents/qa.agent.yaml b/src/bmm/agents/qa.agent.yaml index 9265f5a7b..d13f43c93 100644 --- a/src/bmm/agents/qa.agent.yaml +++ b/src/bmm/agents/qa.agent.yaml @@ -29,7 +29,7 @@ agent: menu: - trigger: QA or fuzzy match on qa-automate - workflow: "{project-root}/_bmad/bmm/workflows/qa/automate/workflow.yaml" + workflow: "{project-root}/_bmad/bmm/workflows/qa/automate/workflow.md" description: "[QA] Automate - Generate tests for existing features (simplified)" prompts: diff --git a/src/bmm/agents/quick-flow-solo-dev.agent.yaml b/src/bmm/agents/quick-flow-solo-dev.agent.yaml index fff3052d4..221c330a9 100644 --- a/src/bmm/agents/quick-flow-solo-dev.agent.yaml +++ b/src/bmm/agents/quick-flow-solo-dev.agent.yaml @@ -28,5 +28,5 @@ agent: description: "[QD] Quick-flow Develop: Implement a story tech spec end-to-end (Core of Quick Flow)" - trigger: CR or fuzzy match on code-review - workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/code-review/workflow.yaml" + workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/code-review/workflow.md" description: "[CR] Code Review: Initiate a comprehensive code review across multiple quality facets. For best results, use a fresh context and a different quality LLM if available" diff --git a/src/bmm/agents/sm.agent.yaml b/src/bmm/agents/sm.agent.yaml index d79f644e5..11716df24 100644 --- a/src/bmm/agents/sm.agent.yaml +++ b/src/bmm/agents/sm.agent.yaml @@ -20,18 +20,18 @@ agent: menu: - trigger: SP or fuzzy match on sprint-planning - workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/sprint-planning/workflow.yaml" + workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/sprint-planning/workflow.md" description: "[SP] Sprint Planning: Generate or update the record that will sequence the tasks to complete the full project that the dev agent will follow" - trigger: CS or fuzzy match on create-story - workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml" + workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/create-story/workflow.md" description: "[CS] Context Story: Prepare a story with all required context for implementation for the developer agent" - trigger: ER or fuzzy match on epic-retrospective - workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml" + workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.md" data: "{project-root}/_bmad/_config/agent-manifest.csv" description: "[ER] Epic Retrospective: Party Mode review of all work completed across an epic." - trigger: CC or fuzzy match on correct-course - workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/correct-course/workflow.yaml" + workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/correct-course/workflow.md" description: "[CC] Course Correction: Use this so we can determine how to proceed if major need for change is discovered mid implementation" diff --git a/src/bmm/agents/tech-writer/tech-writer.agent.yaml b/src/bmm/agents/tech-writer/tech-writer.agent.yaml index 555bd7981..da3fe9c91 100644 --- a/src/bmm/agents/tech-writer/tech-writer.agent.yaml +++ b/src/bmm/agents/tech-writer/tech-writer.agent.yaml @@ -22,7 +22,7 @@ agent: menu: - trigger: DP or fuzzy match on document-project - workflow: "{project-root}/_bmad/bmm/workflows/document-project/workflow.yaml" + workflow: "{project-root}/_bmad/bmm/workflows/document-project/workflow.md" description: "[DP] Document Project: Generate comprehensive project documentation (brownfield analysis, architecture scanning)" - trigger: WD or fuzzy match on write-document diff --git a/src/bmm/module-help.csv b/src/bmm/module-help.csv index 635bb8a81..0c8096831 100644 --- a/src/bmm/module-help.csv +++ b/src/bmm/module-help.csv @@ -1,9 +1,9 @@ module,phase,name,code,sequence,workflow-file,command,required,agent,options,description,output-location,outputs, -bmm,anytime,Document Project,DP,,_bmad/bmm/workflows/document-project/workflow.yaml,bmad-bmm-document-project,false,analyst,Create Mode,"Analyze an existing project to produce useful documentation",project-knowledge,*, +bmm,anytime,Document Project,DP,,_bmad/bmm/workflows/document-project/workflow.md,bmad-bmm-document-project,false,analyst,Create Mode,"Analyze an existing project to produce useful documentation",project-knowledge,*, bmm,anytime,Generate Project Context,GPC,,_bmad/bmm/workflows/generate-project-context/workflow.md,bmad-bmm-generate-project-context,false,analyst,Create Mode,"Scan existing codebase to generate a lean LLM-optimized project-context.md containing critical implementation rules patterns and conventions for AI agents. Essential for brownfield projects and quick-flow.",output_folder,"project context", bmm,anytime,Quick Spec,QS,,_bmad/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md,bmad-bmm-quick-spec,false,quick-flow-solo-dev,Create Mode,"Do not suggest for potentially very complex things unless requested or if the user complains that they do not want to follow the extensive planning of the bmad method. Quick one-off tasks small changes simple apps brownfield additions to well established patterns utilities without extensive planning",planning_artifacts,"tech spec", bmm,anytime,Quick Dev,QD,,_bmad/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md,bmad-bmm-quick-dev,false,quick-flow-solo-dev,Create Mode,"Quick one-off tasks small changes simple apps utilities without extensive planning - Do not suggest for potentially very complex things unless requested or if the user complains that they do not want to follow the extensive planning of the bmad method, unless the user is already working through the implementation phase and just requests a 1 off things not already in the plan",,, -bmm,anytime,Correct Course,CC,,_bmad/bmm/workflows/4-implementation/correct-course/workflow.yaml,bmad-bmm-correct-course,false,sm,Create Mode,"Anytime: Navigate significant changes. May recommend start over update PRD redo architecture sprint planning or correct epics and stories",planning_artifacts,"change proposal", +bmm,anytime,Correct Course,CC,,_bmad/bmm/workflows/4-implementation/correct-course/workflow.md,bmad-bmm-correct-course,false,sm,Create Mode,"Anytime: Navigate significant changes. May recommend start over update PRD redo architecture sprint planning or correct epics and stories",planning_artifacts,"change proposal", bmm,anytime,Write Document,WD,,_bmad/bmm/agents/tech-writer/tech-writer.agent.yaml,,false,tech-writer,,"Describe in detail what you want, and the agent will follow the documentation best practices defined in agent memory. Multi-turn conversation with subprocess for research/review.",project-knowledge,"document", bmm,anytime,Update Standards,US,,_bmad/bmm/agents/tech-writer/tech-writer.agent.yaml,,false,tech-writer,,"Update agent memory documentation-standards.md with your specific preferences if you discover missing document conventions.",_bmad/_memory/tech-writer-sidecar,"standards", bmm,anytime,Mermaid Generate,MG,,_bmad/bmm/agents/tech-writer/tech-writer.agent.yaml,,false,tech-writer,,"Create a Mermaid diagram based on user description. Will suggest diagram types if not specified.",planning_artifacts,"mermaid diagram", @@ -21,11 +21,11 @@ bmm,2-planning,Create UX,CU,30,_bmad/bmm/workflows/2-plan-workflows/create-ux-de bmm,3-solutioning,Create Architecture,CA,10,_bmad/bmm/workflows/3-solutioning/create-architecture/workflow.md,bmad-bmm-create-architecture,true,architect,Create Mode,"Guided Workflow to document technical decisions",planning_artifacts,architecture, bmm,3-solutioning,Create Epics and Stories,CE,30,_bmad/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md,bmad-bmm-create-epics-and-stories,true,pm,Create Mode,"Create the Epics and Stories Listing",planning_artifacts,"epics and stories", bmm,3-solutioning,Check Implementation Readiness,IR,70,_bmad/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md,bmad-bmm-check-implementation-readiness,true,architect,Validate Mode,"Ensure PRD UX Architecture and Epics Stories are aligned",planning_artifacts,"readiness report", -bmm,4-implementation,Sprint Planning,SP,10,_bmad/bmm/workflows/4-implementation/sprint-planning/workflow.yaml,bmad-bmm-sprint-planning,true,sm,Create Mode,"Generate sprint plan for development tasks - this kicks off the implementation phase by producing a plan the implementation agents will follow in sequence for every story in the plan.",implementation_artifacts,"sprint status", -bmm,4-implementation,Sprint Status,SS,20,_bmad/bmm/workflows/4-implementation/sprint-status/workflow.yaml,bmad-bmm-sprint-status,false,sm,Create Mode,"Anytime: Summarize sprint status and route to next workflow",,, -bmm,4-implementation,Validate Story,VS,35,_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml,bmad-bmm-create-story,false,sm,Validate Mode,"Validates story readiness and completeness before development work begins",implementation_artifacts,"story validation report", -bmm,4-implementation,Create Story,CS,30,_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml,bmad-bmm-create-story,true,sm,Create Mode,"Story cycle start: Prepare first found story in the sprint plan that is next, or if the command is run with a specific epic and story designation with context. Once complete, then VS then DS then CR then back to DS if needed or next CS or ER",implementation_artifacts,story, -bmm,4-implementation,Dev Story,DS,40,_bmad/bmm/workflows/4-implementation/dev-story/workflow.yaml,bmad-bmm-dev-story,true,dev,Create Mode,"Story cycle: Execute story implementation tasks and tests then CR then back to DS if fixes needed",,, -bmm,4-implementation,Code Review,CR,50,_bmad/bmm/workflows/4-implementation/code-review/workflow.yaml,bmad-bmm-code-review,false,dev,Create Mode,"Story cycle: If issues back to DS if approved then next CS or ER if epic complete",,, -bmm,4-implementation,QA Automation Test,QA,45,_bmad/bmm/workflows/qa/automate/workflow.yaml,bmad-bmm-qa-automate,false,qa,Create Mode,"Generate automated API and E2E tests for implemented code using the project's existing test framework (detects existing well known in use test frameworks). Use after implementation to add test coverage. NOT for code review or story validation - use CR for that.",implementation_artifacts,"test suite", -bmm,4-implementation,Retrospective,ER,60,_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml,bmad-bmm-retrospective,false,sm,Create Mode,"Optional at epic end: Review completed work lessons learned and next epic or if major issues consider CC",implementation_artifacts,retrospective, +bmm,4-implementation,Sprint Planning,SP,10,_bmad/bmm/workflows/4-implementation/sprint-planning/workflow.md,bmad-bmm-sprint-planning,true,sm,Create Mode,"Generate sprint plan for development tasks - this kicks off the implementation phase by producing a plan the implementation agents will follow in sequence for every story in the plan.",implementation_artifacts,"sprint status", +bmm,4-implementation,Sprint Status,SS,20,_bmad/bmm/workflows/4-implementation/sprint-status/workflow.md,bmad-bmm-sprint-status,false,sm,Create Mode,"Anytime: Summarize sprint status and route to next workflow",,, +bmm,4-implementation,Validate Story,VS,35,_bmad/bmm/workflows/4-implementation/create-story/workflow.md,bmad-bmm-create-story,false,sm,Validate Mode,"Validates story readiness and completeness before development work begins",implementation_artifacts,"story validation report", +bmm,4-implementation,Create Story,CS,30,_bmad/bmm/workflows/4-implementation/create-story/workflow.md,bmad-bmm-create-story,true,sm,Create Mode,"Story cycle start: Prepare first found story in the sprint plan that is next, or if the command is run with a specific epic and story designation with context. Once complete, then VS then DS then CR then back to DS if needed or next CS or ER",implementation_artifacts,story, +bmm,4-implementation,Dev Story,DS,40,_bmad/bmm/workflows/4-implementation/dev-story/workflow.md,bmad-bmm-dev-story,true,dev,Create Mode,"Story cycle: Execute story implementation tasks and tests then CR then back to DS if fixes needed",,, +bmm,4-implementation,Code Review,CR,50,_bmad/bmm/workflows/4-implementation/code-review/workflow.md,bmad-bmm-code-review,false,dev,Create Mode,"Story cycle: If issues back to DS if approved then next CS or ER if epic complete",,, +bmm,4-implementation,QA Automation Test,QA,45,_bmad/bmm/workflows/qa/automate/workflow.md,bmad-bmm-qa-automate,false,qa,Create Mode,"Generate automated API and E2E tests for implemented code using the project's existing test framework (detects existing well known in use test frameworks). Use after implementation to add test coverage. NOT for code review or story validation - use CR for that.",implementation_artifacts,"test suite", +bmm,4-implementation,Retrospective,ER,60,_bmad/bmm/workflows/4-implementation/retrospective/workflow.md,bmad-bmm-retrospective,false,sm,Create Mode,"Optional at epic end: Review completed work lessons learned and next epic or if major issues consider CC",implementation_artifacts,retrospective, diff --git a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md index f00e18faa..5ae6e3347 100644 --- a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +++ b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md @@ -7,7 +7,7 @@ nextStepFile: './step-03-users.md' outputFile: '{planning_artifacts}/product-brief-{{project_name}}-{{date}}.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md index cba266411..b2881ed78 100644 --- a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +++ b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md @@ -7,7 +7,7 @@ nextStepFile: './step-04-metrics.md' outputFile: '{planning_artifacts}/product-brief-{{project_name}}-{{date}}.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md index e6b297c3d..0bfc5519b 100644 --- a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +++ b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md @@ -7,7 +7,7 @@ nextStepFile: './step-05-scope.md' outputFile: '{planning_artifacts}/product-brief-{{project_name}}-{{date}}.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md index 0914b835d..d3f6b7ccc 100644 --- a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +++ b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md @@ -7,7 +7,7 @@ nextStepFile: './step-06-complete.md' outputFile: '{planning_artifacts}/product-brief-{{project_name}}-{{date}}.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md index 4829a4d36..1201b286f 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md @@ -11,7 +11,7 @@ projectTypesCSV: '../data/project-types.csv' domainComplexityCSV: '../data/domain-complexity.csv' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md index 9a3c5e341..49cb1339e 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md @@ -7,7 +7,7 @@ nextStepFile: './step-04-journeys.md' outputFile: '{planning_artifacts}/prd.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md index 314dab564..5c7570890 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md @@ -7,7 +7,7 @@ nextStepFile: './step-05-domain.md' outputFile: '{planning_artifacts}/prd.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md index 9539527dc..60b30cb15 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md @@ -8,7 +8,7 @@ outputFile: '{planning_artifacts}/prd.md' domainComplexityCSV: '../data/domain-complexity.csv' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md index 440ccf2d2..8d2f03dd4 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md @@ -10,7 +10,7 @@ outputFile: '{planning_artifacts}/prd.md' projectTypesCSV: '../data/project-types.csv' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md index c078d6db1..9dd55e1c0 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md @@ -10,7 +10,7 @@ outputFile: '{planning_artifacts}/prd.md' projectTypesCSV: '../data/project-types.csv' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md index da9230adc..36c4e5293 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md @@ -7,7 +7,7 @@ nextStepFile: './step-09-functional.md' outputFile: '{planning_artifacts}/prd.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md index d689ebf37..210fd60c1 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md @@ -7,7 +7,7 @@ nextStepFile: './step-10-nonfunctional.md' outputFile: '{planning_artifacts}/prd.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md index 40919635d..121ea53ce 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md @@ -7,7 +7,7 @@ nextStepFile: './step-11-polish.md' outputFile: '{planning_artifacts}/prd.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md index 70bf198c3..04ad786e8 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md @@ -8,7 +8,7 @@ outputFile: '{planning_artifacts}/prd.md' purposeFile: '../data/prd-purpose.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md index 8f47cd551..cfe2a0335 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md @@ -5,7 +5,7 @@ description: 'Discovery & Understanding - Understand what user wants to edit and # File references (ONLY variables used in this step) altStepFile: './step-e-01b-legacy-conversion.md' prdPurpose: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md' -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-02-review.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-02-review.md index f34de79ff..1f7f9215e 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-02-review.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-02-review.md @@ -7,7 +7,7 @@ nextStepFile: './step-e-03-edit.md' prdFile: '{prd_file_path}' validationReport: '{validation_report_path}' # If provided prdPurpose: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md' -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' --- # Step E-2: Deep Review & Analysis diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md index 6c591c2dd..37d47f3e2 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md @@ -4,7 +4,7 @@ description: 'Document Discovery & Confirmation - Handle fresh context validatio # File references (ONLY variables used in this step) nextStepFile: './step-v-02-format-detection.md' -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' prdPurpose: '../data/prd-purpose.md' --- diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md index e937c7526..1a135dcf0 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md @@ -6,7 +6,7 @@ description: 'SMART Requirements Validation - Validate Functional Requirements m nextStepFile: './step-v-11-holistic-quality-validation.md' prdFile: '{prd_file_path}' validationReportPath: '{validation_report_path}' -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' --- # Step 10: SMART Requirements Validation diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md index 698b6f654..581bf15f5 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md @@ -6,7 +6,7 @@ description: 'Holistic Quality Assessment - Assess PRD as cohesive, compelling d nextStepFile: './step-v-12-completeness-validation.md' prdFile: '{prd_file_path}' validationReportPath: '{validation_report_path}' -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' --- # Step 11: Holistic Quality Assessment diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md index 7ab275a88..c45b1d461 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md @@ -30,7 +30,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to this step's A/P/C menu - User accepts/rejects protocol changes before proceeding diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md index c64c84230..3ab99f9b1 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md @@ -30,7 +30,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to this step's A/P/C menu - User accepts/rejects protocol changes before proceeding @@ -161,7 +161,7 @@ Show the generated core experience content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with the current core experience content +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with the current core experience content - Process the enhanced experience insights that come back - Ask user: "Accept these improvements to the core experience definition? (y/n)" - If yes: Update content with improvements, then return to A/P/C menu diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md index 247a61e21..6b74fc0fb 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md @@ -30,7 +30,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to this step's A/P/C menu - User accepts/rejects protocol changes before proceeding @@ -164,7 +164,7 @@ Show the generated emotional response content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with the current emotional response content +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with the current emotional response content - Process the enhanced emotional insights that come back - Ask user: "Accept these improvements to the emotional response definition? (y/n)" - If yes: Update content with improvements, then return to A/P/C menu diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md index 87fe56031..f85d5f4b1 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md @@ -30,7 +30,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to this step's A/P/C menu - User accepts/rejects protocol changes before proceeding @@ -179,7 +179,7 @@ Show the generated inspiration analysis content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with the current inspiration analysis content +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with the current inspiration analysis content - Process the enhanced pattern insights that come back - Ask user: "Accept these improvements to the inspiration analysis? (y/n)" - If yes: Update content with improvements, then return to A/P/C menu diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md index 70d566ada..0ff7156b6 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md @@ -30,7 +30,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to this step's A/P/C menu - User accepts/rejects protocol changes before proceeding @@ -197,7 +197,7 @@ Show the generated design system content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with the current design system content +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with the current design system content - Process the enhanced design system insights that come back - Ask user: "Accept these improvements to the design system decision? (y/n)" - If yes: Update content with improvements, then return to A/P/C menu diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md index 7e904b948..53ad68f38 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md @@ -30,7 +30,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to this step's A/P/C menu - User accepts/rejects protocol changes before proceeding @@ -199,7 +199,7 @@ Show the generated defining experience content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with the current defining experience content +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with the current defining experience content - Process the enhanced experience insights that come back - Ask user: "Accept these improvements to the defining experience? (y/n)" - If yes: Update content with improvements, then return to A/P/C menu diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md index bd764a60e..2f2491592 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md @@ -30,7 +30,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to this step's A/P/C menu - User accepts/rejects protocol changes before proceeding @@ -169,7 +169,7 @@ Show the generated visual foundation content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with the current visual foundation content +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with the current visual foundation content - Process the enhanced visual insights that come back - Ask user: "Accept these improvements to the visual foundation? (y/n)" - If yes: Update content with improvements, then return to A/P/C menu diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md index a50ed503e..ac8f00439 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md @@ -30,7 +30,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to this step's A/P/C menu - User accepts/rejects protocol changes before proceeding @@ -169,7 +169,7 @@ Show the generated design direction content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with the current design direction content +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with the current design direction content - Process the enhanced design insights that come back - Ask user: "Accept these improvements to the design direction? (y/n)" - If yes: Update content with improvements, then return to A/P/C menu diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md index 985577f00..4a52e235e 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md @@ -30,7 +30,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to this step's A/P/C menu - User accepts/rejects protocol changes before proceeding @@ -187,7 +187,7 @@ Show the generated user journey content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with the current user journey content +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with the current user journey content - Process the enhanced journey insights that come back - Ask user: "Accept these improvements to the user journeys? (y/n)" - If yes: Update content with improvements, then return to A/P/C menu diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md index deef19b73..258f64d56 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md @@ -30,7 +30,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to this step's A/P/C menu - User accepts/rejects protocol changes before proceeding @@ -193,7 +193,7 @@ Show the generated component strategy content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with the current component strategy content +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with the current component strategy content - Process the enhanced component insights that come back - Ask user: "Accept these improvements to the component strategy? (y/n)" - If yes: Update content with improvements, then return to A/P/C menu diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md index 4708b52aa..761244e63 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md @@ -30,7 +30,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to this step's A/P/C menu - User accepts/rejects protocol changes before proceeding @@ -182,7 +182,7 @@ Show the generated UX patterns content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with the current UX patterns content +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with the current UX patterns content - Process the enhanced pattern insights that come back - Ask user: "Accept these improvements to the UX patterns? (y/n)" - If yes: Update content with improvements, then return to A/P/C menu diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md index 80b81d4c8..890a9506f 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md @@ -30,7 +30,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to this step's A/P/C menu - User accepts/rejects protocol changes before proceeding @@ -209,7 +209,7 @@ Show the generated responsive and accessibility content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with the current responsive/accessibility content +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with the current responsive/accessibility content - Process the enhanced insights that come back - Ask user: "Accept these improvements to the responsive/accessibility strategy? (y/n)" - If yes: Update content with improvements, then return to A/P/C menu diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md index 1e9c6b9a3..14fa1264d 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md @@ -31,7 +31,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed - User accepts/rejects protocol changes before proceeding @@ -170,7 +170,7 @@ Show the generated content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with the current context analysis +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with the current context analysis - Process the enhanced architectural insights that come back - Ask user: "Accept these enhancements to the project context analysis? (y/n)" - If yes: Update content with improvements, then return to A/P/C menu diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md index bccea19df..c97aa9b6f 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md @@ -31,7 +31,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed - User accepts/rejects protocol changes before proceeding @@ -277,7 +277,7 @@ Show the generated content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with current starter analysis +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with current starter analysis - Process enhanced insights about starter options or custom approaches - Ask user: "Accept these changes to the starter template evaluation? (y/n)" - If yes: Update content, then return to A/P/C menu diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md index c9f5cdedd..7828d0804 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md @@ -15,9 +15,9 @@ ## EXECUTION PROTOCOLS: -- 🎯 Show your analysis before taking any action +- 🎯 Provide a brief rationale before taking any action - 🌐 Search the web to verify technology versions and options -- ⚠️ Present A/P/C menu after each major decision category +- ⚠️ Present A/P/C menu after drafting decision content (and when user requests refinement) - 💾 ONLY save when user chooses C (Continue) - 📖 Update frontmatter `stepsCompleted: [1, 2, 3, 4]` before loading next step - 🚫 FORBIDDEN to load next step until C is selected @@ -32,7 +32,7 @@ This step will generate content and present choices for each decision category: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed - User accepts/rejects protocol changes before proceeding @@ -44,7 +44,7 @@ This step will generate content and present choices for each decision category: - Project context file may contain technical preferences and rules - Technical preferences discovered in step 3 are available - Focus on decisions not already made by starter template or existing preferences -- Collaborative decision making, not recommendations +- Collaborative decision making first; recommendations are allowed only with explicit rationale and user confirmation ## YOUR TASK: @@ -58,7 +58,7 @@ Facilitate collaborative architectural decision making, leveraging existing tech "Based on our technical preferences discussion in step 3, let's build on those foundations: **Your Technical Preferences:** -{{user_technical_preferences_from_step_3}} +{{user_technical_preferences}} **Starter Template Decisions:** {{starter_template_decisions}} @@ -72,7 +72,7 @@ Based on technical preferences, starter template choice, and project context, id **Already Decided (Don't re-decide these):** - {{starter_template_decisions}} -- {{user_technology_preferences}} +- {{user_technical_preferences}} - {{project_context_technical_rules}} **Critical Decisions:** Must be decided before implementation can proceed @@ -165,7 +165,7 @@ If decision involves specific technology: ``` Search the web: "{{technology}} latest stable version" -Search the web: "{{technology}} current LTS version" +Search the web: "{{technology}} current LTS version" (only if the technology publishes an LTS track) Search the web: "{{technology}} production readiness" ``` @@ -264,7 +264,7 @@ Show the generated decisions content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with specific decision categories +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with specific decision categories - Process enhanced insights about particular decisions - Ask user: "Accept these enhancements to the architectural decisions? (y/n)" - If yes: Update content, then return to A/P/C menu diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md index cbfd99d1d..a150f8909 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md @@ -32,7 +32,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed - User accepts/rejects protocol changes before proceeding @@ -305,7 +305,7 @@ Show the generated patterns content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with current patterns +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with current patterns - Process enhanced consistency rules that come back - Ask user: "Accept these additional pattern refinements? (y/n)" - If yes: Update content, then return to A/P/C menu diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md index 3df89e6ce..39be9bbc7 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md @@ -32,7 +32,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed - User accepts/rejects protocol changes before proceeding @@ -325,7 +325,7 @@ Show the generated project structure content and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with current project structure +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with current project structure - Process enhanced organizational insights that come back - Ask user: "Accept these changes to the project structure? (y/n)" - If yes: Update content, then return to A/P/C menu diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md index b2dc2c462..de43a25e6 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md @@ -32,7 +32,7 @@ This step will generate content and present choices: ## PROTOCOL INTEGRATION: -- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Read fully and follow: {project-root}/_bmad/core/workflows/party-mode/workflow.md - PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed - User accepts/rejects protocol changes before proceeding @@ -305,7 +305,7 @@ Show the validation results and present choices: #### If 'A' (Advanced Elicitation): -- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml with validation issues +- Read fully and follow: {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md with validation issues - Process enhanced solutions for complex concerns - Ask user: "Accept these architectural improvements? (y/n)" - If yes: Update content, then return to A/P/C menu diff --git a/src/bmm/workflows/3-solutioning/create-architecture/workflow.md b/src/bmm/workflows/3-solutioning/create-architecture/workflow.md index b75b4a46c..cd4201650 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/workflow.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/workflow.md @@ -36,7 +36,7 @@ Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: ### Paths -- `installed_path` = `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture` +- `installed_path` = `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture` - `template_path` = `{installed_path}/architecture-decision-template.md` - `data_files_path` = `{installed_path}/data/` diff --git a/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md b/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md index c8d6b1330..2dd277ee9 100644 --- a/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md +++ b/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md @@ -13,11 +13,8 @@ outputFile: '{planning_artifacts}/epics.md' epicsTemplate: '{workflow_path}/templates/epics-template.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' - -# Template References -epicsTemplate: '{workflow_path}/templates/epics-template.md' --- # Step 1: Validate Prerequisites and Extract Requirements @@ -91,11 +88,18 @@ Search for required documents using these patterns (sharded means a large docume 1. `{planning_artifacts}/*ux*.md` (whole document) 2. `{planning_artifacts}/*ux*/index.md` (sharded version) +**Deterministic Selection Rules (required):** + +- When multiple files match the same priority level, prefer exact filename matches (`prd.md`, `architecture.md`, `ux-design.md`) before wildcard matches. +- If multiple wildcard matches remain, prefer files under `{planning_artifacts}` root before nested paths. +- If ambiguity still remains, present candidates to the user and require explicit selection before extraction. +- Record the final selected files in `inputDocuments` frontmatter to keep downstream steps deterministic. + Before proceeding, Ask the user if there are any other documents to include for analysis, and if anything found should be excluded. Wait for user confirmation. Once confirmed, create the {outputFile} from the {epicsTemplate} and in the front matter list the files in the array of `inputDocuments: []`. ### 3. Extract Functional Requirements (FRs) -From the PRD document (full or sharded), read then entire document and extract ALL functional requirements: +From the PRD document (full or sharded), read the entire document and extract ALL functional requirements: **Extraction Method:** diff --git a/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md b/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md index 1b497c2ad..46ca5e47a 100644 --- a/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +++ b/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md @@ -12,7 +12,7 @@ workflowFile: '{workflow_path}/workflow.md' outputFile: '{planning_artifacts}/epics.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' # Template References diff --git a/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md b/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md index 2e13f9b2c..07e666e03 100644 --- a/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +++ b/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md @@ -12,7 +12,7 @@ workflowFile: '{workflow_path}/workflow.md' outputFile: '{planning_artifacts}/epics.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' # Template References diff --git a/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md b/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md index 05e8d5d4e..1cf5d5050 100644 --- a/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +++ b/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md @@ -11,7 +11,7 @@ workflowFile: '{workflow_path}/workflow.md' outputFile: '{planning_artifacts}/epics.md' # Task References -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' # Template References diff --git a/src/bmm/workflows/4-implementation/code-review/instructions.xml b/src/bmm/workflows/4-implementation/code-review/instructions.xml deleted file mode 100644 index e5649559d..000000000 --- a/src/bmm/workflows/4-implementation/code-review/instructions.xml +++ /dev/null @@ -1,227 +0,0 @@ - - The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml - You MUST have already loaded and processed: {installed_path}/workflow.yaml - Communicate all responses in {communication_language} and language MUST be tailored to {user_skill_level} - Generate all documents in {document_output_language} - - 🔥 YOU ARE AN ADVERSARIAL CODE REVIEWER - Find what's wrong or missing! 🔥 - Your purpose: Validate story file claims against actual implementation - Challenge everything: Are tasks marked [x] actually done? Are ACs really implemented? - Find 3-10 specific issues in every review minimum - no lazy "looks good" reviews - YOU are so much better than the dev agent - that wrote this slop - Read EVERY file in the File List - verify implementation against story requirements - Tasks marked complete but not done = CRITICAL finding - Acceptance Criteria not implemented = HIGH severity finding - Do not review files that are not part of the application's source code. Always exclude the _bmad/ and _bmad-output/ folders from the review. Always exclude IDE and CLI configuration folders like .cursor/ and .windsurf/ and .claude/ - - - - Use provided {{story_path}} or ask user which story file to review - Read COMPLETE story file - Set {{story_key}} = extracted key from filename (e.g., "1-2-user-authentication.md" → "1-2-user-authentication") or story - metadata - Parse sections: Story, Acceptance Criteria, Tasks/Subtasks, Dev Agent Record → File List, Change Log - - - Check if git repository detected in current directory - - Run `git status --porcelain` to find uncommitted changes - Run `git diff --name-only` to see modified files - Run `git diff --cached --name-only` to see staged files - Compile list of actually changed files from git output - - - - Compare story's Dev Agent Record → File List with actual git changes - Note discrepancies: - - Files in git but not in story File List - - Files in story File List but no git changes - - Missing documentation of what was actually changed - - - - Load {project_context} for coding standards (if exists) - - - - Extract ALL Acceptance Criteria from story - Extract ALL Tasks/Subtasks with completion status ([x] vs [ ]) - From Dev Agent Record → File List, compile list of claimed changes - - Create review plan: - 1. **AC Validation**: Verify each AC is actually implemented - 2. **Task Audit**: Verify each [x] task is really done - 3. **Code Quality**: Security, performance, maintainability - 4. **Test Quality**: Real tests vs placeholder bullshit - - - - - VALIDATE EVERY CLAIM - Check git reality vs story claims - - - Review git vs story File List discrepancies: - 1. **Files changed but not in story File List** → MEDIUM finding (incomplete documentation) - 2. **Story lists files but no git changes** → HIGH finding (false claims) - 3. **Uncommitted changes not documented** → MEDIUM finding (transparency issue) - - - - Create comprehensive review file list from story File List and git changes - - - For EACH Acceptance Criterion: - 1. Read the AC requirement - 2. Search implementation files for evidence - 3. Determine: IMPLEMENTED, PARTIAL, or MISSING - 4. If MISSING/PARTIAL → HIGH SEVERITY finding - - - - For EACH task marked [x]: - 1. Read the task description - 2. Search files for evidence it was actually done - 3. **CRITICAL**: If marked [x] but NOT DONE → CRITICAL finding - 4. Record specific proof (file:line) - - - - For EACH file in comprehensive review list: - 1. **Security**: Look for injection risks, missing validation, auth issues - 2. **Performance**: N+1 queries, inefficient loops, missing caching - 3. **Error Handling**: Missing try/catch, poor error messages - 4. **Code Quality**: Complex functions, magic numbers, poor naming - 5. **Test Quality**: Are tests real assertions or placeholders? - - - - NOT LOOKING HARD ENOUGH - Find more problems! - Re-examine code for: - - Edge cases and null handling - - Architecture violations - - Documentation gaps - - Integration issues - - Dependency problems - - Git commit message quality (if applicable) - - Find at least 3 more specific, actionable issues - - - - - Categorize findings: HIGH (must fix), MEDIUM (should fix), LOW (nice to fix) - Set {{fixed_count}} = 0 - Set {{action_count}} = 0 - - **🔥 CODE REVIEW FINDINGS, {user_name}!** - - **Story:** {{story_file}} - **Git vs Story Discrepancies:** {{git_discrepancy_count}} found - **Issues Found:** {{high_count}} High, {{medium_count}} Medium, {{low_count}} Low - - ## 🔴 CRITICAL ISSUES - - Tasks marked [x] but not actually implemented - - Acceptance Criteria not implemented - - Story claims files changed but no git evidence - - Security vulnerabilities - - ## 🟡 MEDIUM ISSUES - - Files changed but not documented in story File List - - Uncommitted changes not tracked - - Performance problems - - Poor test coverage/quality - - Code maintainability issues - - ## 🟢 LOW ISSUES - - Code style improvements - - Documentation gaps - - Git commit message quality - - - What should I do with these issues? - - 1. **Fix them automatically** - I'll update the code and tests - 2. **Create action items** - Add to story Tasks/Subtasks for later - 3. **Show me details** - Deep dive into specific issues - - Choose [1], [2], or specify which issue to examine: - - - Fix all HIGH and MEDIUM issues in the code - Add/update tests as needed - Update File List in story if files changed - Update story Dev Agent Record with fixes applied - Set {{fixed_count}} = number of HIGH and MEDIUM issues fixed - Set {{action_count}} = 0 - - - - Add "Review Follow-ups (AI)" subsection to Tasks/Subtasks - For each issue: `- [ ] [AI-Review][Severity] Description [file:line]` - Set {{action_count}} = number of action items created - Set {{fixed_count}} = 0 - - - - Show detailed explanation with code examples - Return to fix decision - - - - - - - Set {{new_status}} = "done" - Update story Status field to "done" - - - Set {{new_status}} = "in-progress" - Update story Status field to "in-progress" - - Save story file - - - - Set {{current_sprint_status}} = "enabled" - - - Set {{current_sprint_status}} = "no-sprint-tracking" - - - - - Load the FULL file: {sprint_status} - Find development_status key matching {{story_key}} - - - Update development_status[{{story_key}}] = "done" - Save file, preserving ALL comments and structure - ✅ Sprint status synced: {{story_key}} → done - - - - Update development_status[{{story_key}}] = "in-progress" - Save file, preserving ALL comments and structure - 🔄 Sprint status synced: {{story_key}} → in-progress - - - - ⚠️ Story file updated, but sprint-status sync failed: {{story_key}} not found in sprint-status.yaml - - - - - ℹ️ Story status updated (no sprint tracking configured) - - - **✅ Review Complete!** - - **Story Status:** {{new_status}} - **Issues Fixed:** {{fixed_count}} - **Action Items Created:** {{action_count}} - - {{#if new_status == "done"}}Code review complete!{{else}}Address the action items and continue development.{{/if}} - - - - \ No newline at end of file diff --git a/src/bmm/workflows/4-implementation/code-review/steps/step-01-load-story-and-changes.md b/src/bmm/workflows/4-implementation/code-review/steps/step-01-load-story-and-changes.md new file mode 100644 index 000000000..e957687a2 --- /dev/null +++ b/src/bmm/workflows/4-implementation/code-review/steps/step-01-load-story-and-changes.md @@ -0,0 +1,36 @@ +--- +name: 'step-01-load-story-and-changes' +description: 'Load target story, gather git deltas, and establish review scope' +nextStepFile: './step-02-build-attack-plan.md' +--- + + + Use provided {{story_path}} or ask user which story file to review + Read COMPLETE story file + Set {{story_key}} = extracted key from filename (e.g., "1-2-user-authentication.md" → "1-2-user-authentication") or story + metadata + Parse sections: Story, Acceptance Criteria, Tasks/Subtasks, Dev Agent Record → File List, Change Log + + + Check if git repository detected in current directory + + Run `git status --porcelain` to find uncommitted changes + Run `git diff --name-only` to see modified files + Run `git diff --cached --name-only` to see staged files + Compile list of actually changed files from git output + + + + Compare story's Dev Agent Record → File List with actual git changes + Note discrepancies: + - Files in git but not in story File List + - Files in story File List but no git changes + - Missing documentation of what was actually changed + + + + Load {project_context} for coding standards (if exists) + + +## Next +- Read fully and follow: `./step-02-build-attack-plan.md`. diff --git a/src/bmm/workflows/4-implementation/code-review/steps/step-02-build-attack-plan.md b/src/bmm/workflows/4-implementation/code-review/steps/step-02-build-attack-plan.md new file mode 100644 index 000000000..3a7f9d85c --- /dev/null +++ b/src/bmm/workflows/4-implementation/code-review/steps/step-02-build-attack-plan.md @@ -0,0 +1,21 @@ +--- +name: 'step-02-build-attack-plan' +description: 'Build an explicit adversarial review plan against ACs and completed tasks' +nextStepFile: './step-03-execute-review.md' +--- + + + Extract ALL Acceptance Criteria from story + Extract ALL Tasks/Subtasks with completion status ([x] vs [ ]) + From Dev Agent Record → File List, compile list of claimed changes + + Create review plan: + 1. **AC Validation**: Verify each AC is actually implemented + 2. **Task Audit**: Verify each [x] task is really done + 3. **Code Quality**: Security, performance, maintainability + 4. **Test Quality**: Real assertions and meaningful coverage + + + +## Next +- Read fully and follow: `./step-03-execute-review.md`. diff --git a/src/bmm/workflows/4-implementation/code-review/steps/step-03-execute-review.md b/src/bmm/workflows/4-implementation/code-review/steps/step-03-execute-review.md new file mode 100644 index 000000000..3fba7d536 --- /dev/null +++ b/src/bmm/workflows/4-implementation/code-review/steps/step-03-execute-review.md @@ -0,0 +1,158 @@ +--- +name: 'step-03-execute-review' +description: 'Execute full adversarial review and record actionable findings' +nextStepFile: './step-04-present-and-resolve.md' +reviewFindingsFile: '{story_dir}/review-findings.json' +--- + + + VALIDATE EVERY CLAIM - Check git reality vs story claims + Every issue MUST be captured using the structured findings contract below + + Initialize findings artifacts: + - Set {{review_findings}} = [] (in-memory array) + - Set {{review_findings_file}} = {reviewFindingsFile} + - Set {{review_findings_schema}} = "id,severity,type,summary,detail,file_line,proof,suggested_fix,reviewer,timestamp" + - Each finding record MUST contain: + id, severity, type, summary, detail, file_line, proof, suggested_fix, reviewer, timestamp + - `file_line` is the required `file:line` locator field and MUST use `path/to/file:line` format + - `reviewer` value MUST be `senior-dev-review` + - `timestamp` MUST use system ISO datetime + + + + Review git vs story File List discrepancies: + 1. **Files changed but not in story File List** → MEDIUM finding (incomplete documentation) + 2. **Story lists files but no git changes** → HIGH finding (false claims) + 3. **Uncommitted changes not documented** → MEDIUM finding (transparency issue) + For every discrepancy, append a finding object to {{review_findings}}. + + + + Create comprehensive review file list from story File List and git changes + + + For EACH Acceptance Criterion: + 1. Read the AC requirement + 2. Search implementation files for evidence + 3. Determine: IMPLEMENTED, PARTIAL, or MISSING using this algorithm: + - Parse each AC into explicit clauses (single requirement statements). + - Evaluate each clause independently, then derive overall AC status from clause outcomes. + - IMPLEMENTED: + - EVERY clause has direct code evidence tied to the story execution path, and + - Evidence includes at least one strong corroborator for AC behavior (automated test, integration test, or reproducible runtime proof), and + - Weak evidence (docs/comments/README) is only supplemental. + - PARTIAL: + - One or more clauses have direct evidence, but at least one clause lacks direct evidence, OR + - Coverage is only indirect (helper/generic utility not proven wired), OR + - Evidence is mostly weak and not corroborated by code/tests. + - MISSING: + - No clause has credible direct implementation evidence, and + - No test/runtime proof demonstrates AC behavior. + 4. Evidence-type rules: + - Strong evidence: implementation code plus validating tests/runtime proof. + - Medium evidence: implementation code without validating tests. + - Weak evidence: comments, README/docs, design notes, screenshots, or unverifiable logs. + - Weak evidence alone cannot qualify an AC as IMPLEMENTED. + 5. Indirect evidence rules: + - Helper functions/utilities count as indirect until explicit call sites or integration coverage prove the AC path. + - Generic capability not wired to this story remains PARTIAL. + 6. Severity mapping for AC gaps: + - MISSING + security/data-loss/compliance/core user flow risk -> HIGH. + - MISSING + non-core behavior or secondary UX/documentation requirement -> MEDIUM. + - PARTIAL + security/data-integrity/compliance risk -> HIGH. + - PARTIAL + degraded core behavior -> MEDIUM. + - PARTIAL + optional/non-critical behavior gap with safe fallback -> LOW. + 7. Classification examples: + - IMPLEMENTED example: AC requires validation + error response, and code path plus passing test covers all clauses. + - PARTIAL example: helper exists and one clause passes, but integration path for another clause is unproven. + - MISSING example: AC text exists, but no matching code path or tests are found. + 8. If AC is PARTIAL or MISSING, append a finding object to {{review_findings}} with status, severity, and clause-level proof. + + + When creating findings from any action above, populate fields using this mapping: + - id: + - Git discrepancy: `GIT-DIFF-{{index}}` + - AC gap: `AC-{{ac_id}}-{{status}}-{{index}}` + - Task mismatch: `TASK-{{task_id}}-MISMATCH-{{index}}` + - Code-quality issue: `CQ-{{category}}-{{index}}` + - severity: + - Use explicit severity rule from the originating action block + - type: + - `story-sync` for git/story discrepancies + - `acceptance-criteria` for AC gaps + - `task-audit` for task completion mismatches + - `code-quality` for quality/security/performance/test issues + - summary: + - One-line, user-facing issue statement + - detail: + - Include violated expectation plus observed behavior + - file_line: + - `path/to/file:line` evidence anchor (use most relevant file and line) + - proof: + - Concrete evidence snippet (code, test output, or git command result) + - suggested_fix: + - Actionable implementation guidance + - reviewer: + - `senior-dev-review` + - timestamp: + - System ISO datetime at finding creation time + + + + For EACH task marked [x]: + 1. Read the task description + 2. Search files for evidence it was actually done + 3. **CRITICAL**: If marked [x] but NOT DONE → CRITICAL finding + 4. Record specific proof (file:line) + 5. Append finding object to {{review_findings}} when mismatch is found + + + + For EACH file in comprehensive review list: + 1. **Security**: Look for injection risks, missing validation, auth issues + 2. **Performance**: N+1 queries, inefficient loops, missing caching + 3. **Error Handling**: Missing try/catch, poor error messages + 4. **Code Quality**: Complex functions, magic numbers, poor naming + 5. **Test Quality**: Are tests real assertions or placeholders? + 6. For each issue, append finding object to {{review_findings}} + + + + NOT LOOKING HARD ENOUGH - Find more problems! + Re-examine code for: + - Edge cases and null handling + - Architecture violations + - Documentation gaps + - Integration issues + - Dependency problems + - Git commit message quality (if applicable) + + Find at least 3 more specific, actionable issues + + + Persist findings contract for downstream step: + - Save {{review_findings}} as JSON array to {{review_findings_file}} + - Ensure JSON is valid and each finding includes all required fields + - Set {{findings_contract}} = "JSON array at {{review_findings_file}} with schema {{review_findings_schema}}" + - Step 4 MUST load findings from {{review_findings_file}} and validate against {{review_findings_schema}} before presenting or resolving + + + Example finding record (must match real records): + { + "id": "AC-003-MISSING-001", + "severity": "HIGH", + "type": "acceptance-criteria", + "summary": "AC-3 missing null-check in API handler", + "detail": "Endpoint accepts null payload despite AC requiring rejection with 400.", + "file_line": "src/api/handler.ts:87", + "proof": "No guard before dereference; test suite lacks AC-3 rejection test.", + "suggested_fix": "Add null guard + 400 response and add regression test in test/api/handler.test.ts.", + "reviewer": "senior-dev-review", + "timestamp": "2026-02-08T00:00:00.000Z" + } + + + +## Next +- Read fully and follow: `./step-04-present-and-resolve.md`. diff --git a/src/bmm/workflows/4-implementation/code-review/steps/step-04-present-and-resolve.md b/src/bmm/workflows/4-implementation/code-review/steps/step-04-present-and-resolve.md new file mode 100644 index 000000000..be966cbcb --- /dev/null +++ b/src/bmm/workflows/4-implementation/code-review/steps/step-04-present-and-resolve.md @@ -0,0 +1,83 @@ +--- +name: 'step-04-present-and-resolve' +description: 'Present findings and either apply fixes or create follow-up action items' +nextStepFile: './step-05-update-status.md' +reviewFindingsFile: '{story_dir}/review-findings.json' +--- + + + Resolve findings artifact input: + - Use {{review_findings_file}} from step 3 when present + - Otherwise fallback to {reviewFindingsFile} + - Set {{review_findings_schema}} = "id,severity,type,summary,detail,file_line,proof,suggested_fix,reviewer,timestamp" if not already set + + Load structured findings JSON array from {{review_findings_file}} + Validate findings schema for each entry: + id, severity, type, summary, detail, file_line, proof, suggested_fix, reviewer, timestamp + + Validation contract: + - `file_line` is the required `file:line` locator in `path/to/file:line` format + - Reject non-array JSON, missing required keys, or invalid file_line formatting + - If findings file missing/unreadable/malformed: HALT with explicit error and return to step 3 generation + + Categorize findings: HIGH (must fix), MEDIUM (should fix), LOW (nice to fix) + Set {{fixed_count}} = 0 + Set {{action_count}} = 0 + + **Code Review Findings, {user_name}** + + **Story:** {{story_file}} + **Git vs Story Discrepancies:** {{git_discrepancy_count}} found + **Issues Found:** {{high_count}} High, {{medium_count}} Medium, {{low_count}} Low + + ## 🔴 CRITICAL ISSUES + - Tasks marked [x] but not actually implemented + - Acceptance Criteria not implemented + - Story claims files changed but no git evidence + - Security vulnerabilities + + ## 🟡 MEDIUM ISSUES + - Files changed but not documented in story File List + - Uncommitted changes not tracked + - Performance problems + - Poor test coverage/quality + - Code maintainability issues + + ## 🟢 LOW ISSUES + - Code style improvements + - Documentation gaps + - Git commit message quality + + + What should I do with these issues? + + 1. **Fix them automatically** - I'll update the code and tests + 2. **Create action items** - Add to story Tasks/Subtasks for later + 3. **Show me details** - Deep dive into specific issues + + Choose [1], [2], or specify which issue to examine: + + + Fix all HIGH and MEDIUM issues in the code + Add/update tests as needed + Update File List in story if files changed + Update story Dev Agent Record with fixes applied + Set {{fixed_count}} = number of HIGH and MEDIUM issues fixed + Set {{action_count}} = 0 + + + + Add "Review Follow-ups (AI)" subsection to Tasks/Subtasks + For each issue: `- [ ] [AI-Review][Severity] Description [file:line]` + Set {{action_count}} = number of action items created + Set {{fixed_count}} = 0 + + + + Show detailed explanation with code examples + Return to fix decision + + + +## Next +- Read fully and follow: `./step-05-update-status.md`. diff --git a/src/bmm/workflows/4-implementation/code-review/steps/step-05-update-status.md b/src/bmm/workflows/4-implementation/code-review/steps/step-05-update-status.md new file mode 100644 index 000000000..87dc71da7 --- /dev/null +++ b/src/bmm/workflows/4-implementation/code-review/steps/step-05-update-status.md @@ -0,0 +1,62 @@ +--- +name: 'step-05-update-status' +description: 'Update story/sprint status and report review completion' +--- + + + Validate against checklist at {installed_path}/checklist.md using _bmad/core/tasks/validate-workflow.md + + + + Set {{new_status}} = "done" + Update story Status field to "done" + + + Set {{new_status}} = "in-progress" + Update story Status field to "in-progress" + + Save story file + + + + Set {{current_sprint_status}} = "enabled" + + + Set {{current_sprint_status}} = "no-sprint-tracking" + + + + + Load the FULL file: {sprint_status} + Find development_status key matching {{story_key}} + + + Update development_status[{{story_key}}] = "done" + Save file, preserving ALL comments and structure + ✅ Sprint status synced: {{story_key}} → done + + + + Update development_status[{{story_key}}] = "in-progress" + Save file, preserving ALL comments and structure + 🔄 Sprint status synced: {{story_key}} → in-progress + + + + ⚠️ Story file updated, but sprint-status sync failed: {{story_key}} not found in sprint-status.yaml + + + + + ℹ️ Story status updated (no sprint tracking configured) + + + **✅ Review Complete!** + + **Story Status:** {{new_status}} + **Issues Fixed:** {{fixed_count}} + **Action Items Created:** {{action_count}} + + {{#if new_status == "done"}}Code review complete!{{else}}Address the action items and continue development.{{/if}} + + diff --git a/src/bmm/workflows/4-implementation/code-review/workflow.md b/src/bmm/workflows/4-implementation/code-review/workflow.md new file mode 100644 index 000000000..3af1a9c37 --- /dev/null +++ b/src/bmm/workflows/4-implementation/code-review/workflow.md @@ -0,0 +1,57 @@ +--- +name: code-review +description: "Perform an adversarial senior developer code review with concrete findings across quality, tests, architecture, security, and performance" +main_config: '{project-root}/_bmad/bmm/config.yaml' +web_bundle: false +input_file_patterns: + architecture: + description: "System architecture for review context" + whole: "{planning_artifacts}/*architecture*.md" + sharded: "{planning_artifacts}/*architecture*/*.md" + load_strategy: "FULL_LOAD" + ux_design: + description: "UX design specification (if UI review)" + whole: "{planning_artifacts}/*ux*.md" + sharded: "{planning_artifacts}/*ux*/*.md" + load_strategy: "FULL_LOAD" + epics: + description: "Epic and story requirements for review context" + whole: "{planning_artifacts}/*epic*.md" + sharded: "{planning_artifacts}/*epic*/*.md" + load_strategy: "FULL_LOAD" +--- + +# Code Review Workflow + +## Goal +Run a rigorous review that validates story claims against code reality, surfaces actionable findings, and synchronizes story/sprint status. + +## Workflow Architecture +- Uses step-file execution for predictable, auditable review flow. +- Read one step file fully, execute it, then continue to the next step. +- Do not load later steps before the current step completes. + +## Initialization +- Load config from `{project-root}/_bmad/bmm/config.yaml`. +- Resolve variables: + - `user_name` + - `communication_language` + - `document_output_language` + - `user_skill_level` + - `planning_artifacts` + - `implementation_artifacts` + - `story_dir` = `{implementation_artifacts}` + - `sprint_status` = `{implementation_artifacts}/sprint-status.yaml` + - `project_context` = `**/project-context.md` + - `date` (system-generated) + - `installed_path` = `{project-root}/_bmad/bmm/workflows/4-implementation/code-review` + +## Critical Rules +- Communicate in `{communication_language}`. +- Review implementation evidence, not assumptions. +- Verify acceptance criteria and completed tasks against actual files. +- Prioritize concrete, actionable findings with severity and evidence. +- Exclude generated/config-only folders from source-code review scope (`_bmad/`, `_bmad-output/`, `.cursor/`, `.windsurf/`, `.claude/`). + +## Execution +Read fully and follow: `steps/step-01-load-story-and-changes.md`. diff --git a/src/bmm/workflows/4-implementation/code-review/workflow.yaml b/src/bmm/workflows/4-implementation/code-review/workflow.yaml deleted file mode 100644 index c6edf8464..000000000 --- a/src/bmm/workflows/4-implementation/code-review/workflow.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# Review Story Workflow -name: code-review -description: "Perform an ADVERSARIAL Senior Developer code review that finds 3-10 specific problems in every story. Challenges everything: code quality, test coverage, architecture compliance, security, performance. NEVER accepts `looks good` - must find minimum issues and can auto-fix with user approval." -author: "BMad" - -# Critical variables from config -config_source: "{project-root}/_bmad/bmm/config.yaml" -user_name: "{config_source}:user_name" -communication_language: "{config_source}:communication_language" -user_skill_level: "{config_source}:user_skill_level" -document_output_language: "{config_source}:document_output_language" -date: system-generated -planning_artifacts: "{config_source}:planning_artifacts" -implementation_artifacts: "{config_source}:implementation_artifacts" -sprint_status: "{implementation_artifacts}/sprint-status.yaml" - -# Workflow components -installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/code-review" -instructions: "{installed_path}/instructions.xml" -validation: "{installed_path}/checklist.md" -template: false - -project_context: "**/project-context.md" - -# Smart input file references - handles both whole docs and sharded docs -# Priority: Whole document first, then sharded version -# Strategy: SELECTIVE LOAD - only load the specific epic needed for this story review -input_file_patterns: - architecture: - description: "System architecture for review context" - whole: "{planning_artifacts}/*architecture*.md" - sharded: "{planning_artifacts}/*architecture*/*.md" - load_strategy: "FULL_LOAD" - ux_design: - description: "UX design specification (if UI review)" - whole: "{planning_artifacts}/*ux*.md" - sharded: "{planning_artifacts}/*ux*/*.md" - load_strategy: "FULL_LOAD" - epics: - description: "Epic containing story being reviewed" - whole: "{planning_artifacts}/*epic*.md" - sharded_index: "{planning_artifacts}/*epic*/index.md" - sharded_single: "{planning_artifacts}/*epic*/epic-{{epic_num}}.md" - load_strategy: "SELECTIVE_LOAD" diff --git a/src/bmm/workflows/4-implementation/correct-course/checklist.md b/src/bmm/workflows/4-implementation/correct-course/checklist.md index f13ab9be0..1e630ccbb 100644 --- a/src/bmm/workflows/4-implementation/correct-course/checklist.md +++ b/src/bmm/workflows/4-implementation/correct-course/checklist.md @@ -1,6 +1,6 @@ # Change Navigation Checklist -This checklist is executed as part of: {project-root}/_bmad/bmm/workflows/4-implementation/correct-course/workflow.yaml +This checklist is executed as part of: {project-root}/_bmad/bmm/workflows/4-implementation/correct-course/workflow.md Work through each section systematically with the user, recording findings and impacts diff --git a/src/bmm/workflows/4-implementation/correct-course/instructions.md b/src/bmm/workflows/4-implementation/correct-course/instructions.md index bbe2c21e0..269704660 100644 --- a/src/bmm/workflows/4-implementation/correct-course/instructions.md +++ b/src/bmm/workflows/4-implementation/correct-course/instructions.md @@ -1,7 +1,7 @@ # Correct Course - Sprint Change Management Instructions -The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml -You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/correct-course/workflow.yaml +The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.md +You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/correct-course/workflow.md Communicate all responses in {communication_language} and language MUST be tailored to {user_skill_level} Generate all documents in {document_output_language} diff --git a/src/bmm/workflows/4-implementation/correct-course/workflow.md b/src/bmm/workflows/4-implementation/correct-course/workflow.md new file mode 100644 index 000000000..4a07ac6b2 --- /dev/null +++ b/src/bmm/workflows/4-implementation/correct-course/workflow.md @@ -0,0 +1,70 @@ +--- +name: correct-course +description: "Navigate significant changes during sprint execution by analyzing impact, proposing solutions, and routing for implementation" +main_config: '{project-root}/_bmad/bmm/config.yaml' +web_bundle: false +input_file_patterns: + prd: + description: "Product requirements for impact analysis" + whole: "{planning_artifacts}/*prd*.md" + sharded: "{planning_artifacts}/*prd*/*.md" + load_strategy: "FULL_LOAD" + epics: + description: "All epics to analyze change impact" + whole: "{planning_artifacts}/*epic*.md" + sharded: "{planning_artifacts}/*epic*/*.md" + load_strategy: "FULL_LOAD" + architecture: + description: "System architecture and decisions" + whole: "{planning_artifacts}/*architecture*.md" + sharded: "{planning_artifacts}/*architecture*/*.md" + load_strategy: "FULL_LOAD" + ux_design: + description: "UX design specification (if UI impacts)" + whole: "{planning_artifacts}/*ux*.md" + sharded: "{planning_artifacts}/*ux*/*.md" + load_strategy: "FULL_LOAD" + tech_spec: + description: "Technical specification" + whole: "{planning_artifacts}/*tech-spec*.md" + load_strategy: "FULL_LOAD" + document_project: + description: "Brownfield project documentation (optional)" + sharded: "{project_knowledge}/index.md" + load_strategy: "INDEX_GUIDED" +--- + +## Initialization +- Load config from `{project-root}/_bmad/bmm/config.yaml`. +- Resolve variables: + - `user_name` + - `communication_language` + - `document_output_language` + - `user_skill_level` + - `planning_artifacts` + - `implementation_artifacts` + - `project_knowledge` + - `sprint_status` = `{implementation_artifacts}/sprint-status.yaml` + - `date` (system-generated) + - `installed_path` = `{project-root}/_bmad/bmm/workflows/4-implementation/correct-course` + - `source_path` = `{project-root}/src/bmm/workflows/4-implementation/correct-course` + - Note: `installed_path` targets the installed runtime tree under `_bmad/...`; `source_path` is the repository authoring path. + - `default_output_file` = `{planning_artifacts}/sprint-change-proposal-{date}.md` + + + Communicate all responses in {communication_language} and generate all documents in {document_output_language} + + + Resolve workflow content path: + - If `{installed_path}/instructions.md` exists and is readable, set {{workflow_path}} = `{installed_path}` + - Else if `{source_path}/instructions.md` exists and is readable, set {{workflow_path}} = `{source_path}` + - Else emit an error listing both paths and HALT + + Read and follow instructions at: {{workflow_path}}/instructions.md + + + + If {{workflow_path}} is not set from step 1, repeat path resolution using checklist.md + Validate against checklist at {{workflow_path}}/checklist.md using {project-root}/_bmad/core/tasks/validate-workflow.md + + diff --git a/src/bmm/workflows/4-implementation/correct-course/workflow.yaml b/src/bmm/workflows/4-implementation/correct-course/workflow.yaml deleted file mode 100644 index 6eb4b7f03..000000000 --- a/src/bmm/workflows/4-implementation/correct-course/workflow.yaml +++ /dev/null @@ -1,54 +0,0 @@ -# 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/bmm/config.yaml" -user_name: "{config_source}:user_name" -communication_language: "{config_source}:communication_language" -user_skill_level: "{config_source}:user_skill_level" -document_output_language: "{config_source}:document_output_language" -date: system-generated -implementation_artifacts: "{config_source}:implementation_artifacts" -planning_artifacts: "{config_source}:planning_artifacts" -project_knowledge: "{config_source}:project_knowledge" -project_context: "**/project-context.md" - -# Smart input file references - handles both whole docs and sharded docs -# Priority: Whole document first, then sharded version -# Strategy: Load project context for impact analysis -input_file_patterns: - prd: - description: "Product requirements for impact analysis" - whole: "{planning_artifacts}/*prd*.md" - sharded: "{planning_artifacts}/*prd*/*.md" - load_strategy: "FULL_LOAD" - epics: - description: "All epics to analyze change impact" - whole: "{planning_artifacts}/*epic*.md" - sharded: "{planning_artifacts}/*epic*/*.md" - load_strategy: "FULL_LOAD" - architecture: - description: "System architecture and decisions" - whole: "{planning_artifacts}/*architecture*.md" - sharded: "{planning_artifacts}/*architecture*/*.md" - load_strategy: "FULL_LOAD" - ux_design: - description: "UX design specification (if UI impacts)" - whole: "{planning_artifacts}/*ux*.md" - sharded: "{planning_artifacts}/*ux*/*.md" - load_strategy: "FULL_LOAD" - tech_spec: - description: "Technical specification" - whole: "{planning_artifacts}/*tech-spec*.md" - load_strategy: "FULL_LOAD" - document_project: - description: "Brownfield project documentation (optional)" - sharded: "{project_knowledge}/index.md" - load_strategy: "INDEX_GUIDED" - -installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/correct-course" -template: false -instructions: "{installed_path}/instructions.md" -checklist: "{installed_path}/checklist.md" -default_output_file: "{planning_artifacts}/sprint-change-proposal-{date}.md" diff --git a/src/bmm/workflows/4-implementation/create-story/checklist.md b/src/bmm/workflows/4-implementation/create-story/checklist.md index 6fc678994..94ea32a17 100644 --- a/src/bmm/workflows/4-implementation/create-story/checklist.md +++ b/src/bmm/workflows/4-implementation/create-story/checklist.md @@ -33,25 +33,25 @@ This is a COMPETITION to create the **ULTIMATE story context** that makes LLM de ### **When Running from Create-Story Workflow:** -- The `{project-root}/_bmad/core/tasks/validate-workflow.xml` framework will automatically: +- The `{project-root}/_bmad/core/tasks/validate-workflow.md` framework will automatically: - Load this checklist file - Load the newly created story file (`{story_file_path}`) - - Load workflow variables from `{installed_path}/workflow.yaml` + - Load workflow variables from `{installed_path}/workflow.md` - Execute the validation process ### **When Running in Fresh Context:** - User should provide the story file path being reviewed - Load the story file directly -- Load the corresponding workflow.yaml for variable context +- Load the corresponding workflow.md for variable context - Proceed with systematic analysis ### **Required Inputs:** - **Story file**: The story file to review and improve -- **Workflow variables**: From workflow.yaml (implementation_artifacts, epics_file, etc.) +- **Workflow variables**: From workflow.md (implementation_artifacts, epics_file, etc.) - **Source documents**: Epics, architecture, etc. (discovered or provided) -- **Validation framework**: `validate-workflow.xml` (handles checklist execution) +- **Validation framework**: `validate-workflow.md` (handles checklist execution) --- @@ -61,9 +61,9 @@ You will systematically re-do the entire story creation process, but with a crit ### **Step 1: Load and Understand the Target** -1. **Load the workflow configuration**: `{installed_path}/workflow.yaml` for variable inclusion +1. **Load the workflow configuration**: `{installed_path}/workflow.md` for variable inclusion 2. **Load the story file**: `{story_file_path}` (provided by user or discovered) -3. **Load validation framework**: `{project-root}/_bmad/core/tasks/validate-workflow.xml` +3. **Load validation framework**: `{project-root}/_bmad/core/tasks/validate-workflow.md` 4. **Extract metadata**: epic_num, story_num, story_key, story_title from story file 5. **Resolve all workflow variables**: implementation_artifacts, epics_file, architecture_file, etc. 6. **Understand current status**: What story implementation guidance is currently provided? diff --git a/src/bmm/workflows/4-implementation/create-story/instructions.xml b/src/bmm/workflows/4-implementation/create-story/instructions.xml index f9433371f..588508378 100644 --- a/src/bmm/workflows/4-implementation/create-story/instructions.xml +++ b/src/bmm/workflows/4-implementation/create-story/instructions.xml @@ -1,6 +1,6 @@ - The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml - You MUST have already loaded and processed: {installed_path}/workflow.yaml + The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.md + You MUST have already loaded and processed: {installed_path}/workflow.md Communicate all responses in {communication_language} and generate all documents in {document_output_language} 🔥 CRITICAL MISSION: You are creating the ULTIMATE story context engine that prevents LLM developer mistakes, omissions or @@ -311,7 +311,7 @@ - Validate against checklist at {installed_path}/checklist.md using _bmad/core/tasks/validate-workflow.xml + Validate against checklist at {installed_path}/checklist.md using {project-root}/_bmad/core/tasks/validate-workflow.md Save story document unconditionally diff --git a/src/bmm/workflows/4-implementation/create-story/workflow.md b/src/bmm/workflows/4-implementation/create-story/workflow.md new file mode 100644 index 000000000..530c72090 --- /dev/null +++ b/src/bmm/workflows/4-implementation/create-story/workflow.md @@ -0,0 +1,334 @@ +--- +name: create-story +description: "Create the next user story from epics+stories with enhanced context analysis and direct ready-for-dev marking" +main_config: '{project-root}/_bmad/bmm/config.yaml' +web_bundle: false +input_file_patterns: + prd: + description: "PRD (fallback - epics file should have most content)" + whole: "{planning_artifacts}/*prd*.md" + sharded: "{planning_artifacts}/*prd*/*.md" + load_strategy: "SELECTIVE_LOAD" + architecture: + description: "Architecture (fallback - epics file should have relevant sections)" + whole: "{planning_artifacts}/*architecture*.md" + sharded: "{planning_artifacts}/*architecture*/*.md" + load_strategy: "SELECTIVE_LOAD" + ux: + description: "UX design (fallback - epics file should have relevant sections)" + whole: "{planning_artifacts}/*ux*.md" + sharded: "{planning_artifacts}/*ux*/*.md" + load_strategy: "SELECTIVE_LOAD" + epics: + description: "Enhanced epics+stories file with BDD and source hints" + whole: "{planning_artifacts}/*epic*.md" + sharded_index: "{planning_artifacts}/*epic*/index.md" + sharded_single: "{planning_artifacts}/*epic*/epic-{{epic_num}}.md" + load_strategy: "SELECTIVE_LOAD" +--- + +## Initialization +- Load config from `{project-root}/_bmad/bmm/config.yaml`. +- Resolve variables: + - `user_name`, `communication_language`, `document_output_language` + - `planning_artifacts`, `implementation_artifacts` + - `story_dir`, `default_output_file` + - `sprint_status`, `epics_file`, `prd_file`, `architecture_file`, `ux_file` + - `project_context` + - `date` (system-generated) + - `installed_path` = `{project-root}/_bmad/bmm/workflows/4-implementation/create-story` + + + Communicate all responses in {communication_language} and generate all documents in {document_output_language} + + 🔥 CRITICAL MISSION: You are creating the ULTIMATE story context engine that prevents LLM developer mistakes, omissions or + disasters! 🔥 + Your purpose is NOT to copy from epics - it's to create a comprehensive, optimized story file that gives the DEV agent + EVERYTHING needed for flawless implementation + COMMON LLM MISTAKES TO PREVENT: reinventing wheels, wrong libraries, wrong file locations, breaking regressions, ignoring UX, + vague implementations, lying about completion, not learning from past work + 🚨 EXHAUSTIVE ANALYSIS REQUIRED: You must thoroughly analyze ALL artifacts to extract critical context - do NOT be lazy or skim! + This is the most important function in the entire development process! + 🔬 UTILIZE SUBPROCESSES AND SUBAGENTS: Use research subagents, subprocesses or parallel processing if available to thoroughly + analyze different artifacts simultaneously and thoroughly + ❓ SAVE QUESTIONS: If you think of questions or clarifications during analysis, save them for the end after the complete story is + written + 🎯 ZERO USER INTERVENTION: Process should be fully automated except for initial epic/story selection or missing documents + + + + Parse user-provided story path: extract epic_num, story_num, story_title from format like "1-2-user-auth" + Set {{epic_num}}, {{story_num}}, {{story_key}} from user input + GOTO step 2 + + + Check if {{sprint_status}} file exists for auto discover + + 🚫 No sprint status file found and no story specified + + **Required Options:** + 1. Run `sprint-planning` to initialize sprint tracking (recommended) + 2. Provide specific epic-story number to create (e.g., "1-2-user-auth") + 3. Provide path to story documents if sprint status doesn't exist yet + + Choose option [1], provide epic-story number, path to story docs, or [q] to quit: + + + HALT - No work needed + + + + Run sprint-planning workflow first to create sprint-status.yaml + HALT - User needs to run sprint-planning + + + + Parse user input: extract epic_num, story_num, story_title + Set {{epic_num}}, {{story_num}}, {{story_key}} from user input + GOTO step 2 + + + + Use user-provided path for story documents + GOTO step 2 + + + + + + MUST read COMPLETE {sprint_status} file from start to end to preserve order + Load the FULL file: {{sprint_status}} + Read ALL lines from beginning to end - do not skip any content + Parse the development_status section completely + + Find the FIRST story (by reading in order from top to bottom) where: + - Key matches pattern: number-number-name (e.g., "1-2-user-auth") + - NOT an epic key (epic-X) or retrospective (epic-X-retrospective) + - Status value equals "backlog" + + + + 📋 No backlog stories found in sprint-status.yaml + + All stories are either already created, in progress, or done. + + **Options:** + 1. Run sprint-planning to refresh story tracking + 2. Load PM agent and run correct-course to add more stories + 3. Check if current sprint is complete and run retrospective + + HALT + + + Extract from found story key (e.g., "1-2-user-authentication"): + - epic_num: first number before dash (e.g., "1") + - story_num: second number after first dash (e.g., "2") + - story_title: remainder after second dash (e.g., "user-authentication") + + Set {{story_id}} = "{{epic_num}}.{{story_num}}" + Store story_key for later use (e.g., "1-2-user-authentication") + + + Check if this is the first story in epic {{epic_num}} by looking for {{epic_num}}-1-* pattern + + Load {{sprint_status}} and check epic-{{epic_num}} status + If epic status is "backlog" → update to "in-progress" + If epic status is "contexted" (legacy status) → update to "in-progress" (backward compatibility) + If epic status is "in-progress" → no change needed + + 🚫 ERROR: Cannot create story in completed epic + Epic {{epic_num}} is marked as 'done'. All stories are complete. + If you need to add more work, either: + 1. Manually change epic status back to 'in-progress' in sprint-status.yaml + 2. Create a new epic for additional work + HALT - Cannot proceed + + + 🚫 ERROR: Invalid epic status '{{epic_status}}' + Epic {{epic_num}} has invalid status. Expected: backlog, in-progress, or done + Please fix sprint-status.yaml manually or run sprint-planning to regenerate + HALT - Cannot proceed + + 📊 Epic {{epic_num}} status updated to in-progress + + + GOTO step 2 + + + + + 🔬 EXHAUSTIVE ARTIFACT ANALYSIS - This is where you prevent future developer mistakes! + + + + Available content: {epics_content}, {prd_content}, {architecture_content}, {ux_content}, + {project_context} + + + From {epics_content}, extract Epic {{epic_num}} complete context: **EPIC ANALYSIS:** - Epic + objectives and business value - ALL stories in this epic for cross-story context - Our specific story's requirements, user story + statement, acceptance criteria - Technical requirements and constraints - Dependencies on other stories/epics - Source hints pointing to + original documents + Extract our story ({{epic_num}}-{{story_num}}) details: **STORY FOUNDATION:** - User story statement + (As a, I want, so that) - Detailed acceptance criteria (already BDD formatted) - Technical requirements specific to this story - + Business context and value - Success criteria + + Set {{previous_story_num}} = {{story_num}} - 1 + Load previous story file: {{story_dir}}/{{epic_num}}-{{previous_story_num}}-*.md + Extract previous story intelligence: + - Dev notes and learnings from previous story + - Review feedback and corrections needed + - Files that were created/modified and their patterns + - Testing approaches that worked/didn't work + - Problems encountered and solutions found + - Code patterns established + + Extract all learnings that could impact current story implementation + + + + + Get last 5 commit titles to understand recent work patterns + Analyze 1-5 most recent commits for relevance to current story: + - Files created/modified + - Code patterns and conventions used + - Library dependencies added/changed + - Architecture decisions implemented + - Testing approaches used + + Extract actionable insights for current story implementation + + + + + 🏗️ ARCHITECTURE INTELLIGENCE - Extract everything the developer MUST follow! **ARCHITECTURE DOCUMENT ANALYSIS:** Systematically + analyze architecture content for story-relevant requirements: + + + + Load complete {architecture_content} + + + Load architecture index and scan all architecture files + **CRITICAL ARCHITECTURE EXTRACTION:** For + each architecture section, determine if relevant to this story: - **Technical Stack:** Languages, frameworks, libraries with + versions - **Code Structure:** Folder organization, naming conventions, file patterns - **API Patterns:** Service structure, endpoint + patterns, data contracts - **Database Schemas:** Tables, relationships, constraints relevant to story - **Security Requirements:** + Authentication patterns, authorization rules - **Performance Requirements:** Caching strategies, optimization patterns - **Testing + Standards:** Testing frameworks, coverage expectations, test patterns - **Deployment Patterns:** Environment configurations, build + processes - **Integration Patterns:** External service integrations, data flows Extract any story-specific requirements that the + developer MUST follow + Identify any architectural decisions that override previous patterns + + + + 🌐 ENSURE LATEST TECH KNOWLEDGE - Prevent outdated implementations! **WEB INTELLIGENCE:** Identify specific + technical areas that require latest version knowledge: + + + From architecture analysis, identify specific libraries, APIs, or + frameworks + For each critical technology, research latest stable version and key changes: + - Latest API documentation and breaking changes + - Security vulnerabilities or updates + - Performance improvements or deprecations + - Best practices for current version + + **EXTERNAL CONTEXT INCLUSION:** Include in story any critical latest information the developer needs: + - Specific library versions and why chosen + - API endpoints with parameters and authentication + - Recent security patches or considerations + - Performance optimization techniques + - Migration considerations if upgrading + + + + + 📝 CREATE ULTIMATE STORY FILE - The developer's master implementation guide! + + Initialize from template.md: + {default_output_file} + story_header + + + story_requirements + + + + developer_context_section **DEV AGENT GUARDRAILS:** + technical_requirements + architecture_compliance + library_framework_requirements + + file_structure_requirements + testing_requirements + + + + previous_story_intelligence + + + + + git_intelligence_summary + + + + + latest_tech_information + + + + project_context_reference + + + + story_completion_status + + + Set story Status to: "ready-for-dev" + Add completion note: "Ultimate + context engine analysis completed - comprehensive developer guide created" + + + + Validate against checklist at {installed_path}/checklist.md using {project-root}/_bmad/core/tasks/validate-workflow.md + Save story document unconditionally + + + + Update {{sprint_status}} + Load the FULL file and read all development_status entries + Find development_status key matching {{story_key}} + Verify current status is "backlog" (expected previous state) + Update development_status[{{story_key}}] = "ready-for-dev" + Save file, preserving ALL comments and structure including STATUS DEFINITIONS + + + Report completion + **🎯 ULTIMATE BMad Method STORY CONTEXT CREATED, {user_name}!** + + **Story Details:** + - Story ID: {{story_id}} + - Story Key: {{story_key}} + - File: {{story_file}} + - Status: ready-for-dev + + **Next Steps:** + 1. Review the comprehensive story in {{story_file}} + 2. Run dev agents `dev-story` for optimized implementation + 3. Run `code-review` when complete (auto-marks done) + 4. Optional: Run TEA `*automate` after `dev-story` to generate guardrail tests + + **The developer now has everything needed for flawless implementation!** + + + + diff --git a/src/bmm/workflows/4-implementation/create-story/workflow.yaml b/src/bmm/workflows/4-implementation/create-story/workflow.yaml deleted file mode 100644 index 991f78c2e..000000000 --- a/src/bmm/workflows/4-implementation/create-story/workflow.yaml +++ /dev/null @@ -1,53 +0,0 @@ -name: create-story -description: "Create the next user story from epics+stories with enhanced context analysis and direct ready-for-dev marking" -author: "BMad" - -# Critical variables from config -config_source: "{project-root}/_bmad/bmm/config.yaml" -user_name: "{config_source}:user_name" -communication_language: "{config_source}:communication_language" -document_output_language: "{config_source}:document_output_language" -user_skill_level: "{config_source}:user_skill_level" -date: system-generated -planning_artifacts: "{config_source}:planning_artifacts" -implementation_artifacts: "{config_source}:implementation_artifacts" - -# Workflow components -installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/create-story" -template: "{installed_path}/template.md" -instructions: "{installed_path}/instructions.xml" -validation: "{installed_path}/checklist.md" - -# Variables and inputs -sprint_status: "{implementation_artifacts}/sprint-status.yaml" # Primary source for story tracking -epics_file: "{planning_artifacts}/epics.md" # Enhanced epics+stories with BDD and source hints -prd_file: "{planning_artifacts}/prd.md" # Fallback for requirements (if not in epics file) -architecture_file: "{planning_artifacts}/architecture.md" # Fallback for constraints (if not in epics file) -ux_file: "{planning_artifacts}/*ux*.md" # Fallback for UX requirements (if not in epics file) -story_title: "" # Will be elicited if not derivable -project_context: "**/project-context.md" -default_output_file: "{implementation_artifacts}/{{story_key}}.md" - -# Smart input file references - Simplified for enhanced approach -# The epics+stories file should contain everything needed with source hints -input_file_patterns: - prd: - description: "PRD (fallback - epics file should have most content)" - whole: "{planning_artifacts}/*prd*.md" - sharded: "{planning_artifacts}/*prd*/*.md" - load_strategy: "SELECTIVE_LOAD" # Only load if needed - architecture: - description: "Architecture (fallback - epics file should have relevant sections)" - whole: "{planning_artifacts}/*architecture*.md" - sharded: "{planning_artifacts}/*architecture*/*.md" - load_strategy: "SELECTIVE_LOAD" # Only load if needed - ux: - description: "UX design (fallback - epics file should have relevant sections)" - whole: "{planning_artifacts}/*ux*.md" - sharded: "{planning_artifacts}/*ux*/*.md" - load_strategy: "SELECTIVE_LOAD" # Only load if needed - epics: - description: "Enhanced epics+stories file with BDD and source hints" - whole: "{planning_artifacts}/*epic*.md" - sharded: "{planning_artifacts}/*epic*/*.md" - load_strategy: "SELECTIVE_LOAD" # Only load needed epic diff --git a/src/bmm/workflows/4-implementation/dev-story/instructions.xml b/src/bmm/workflows/4-implementation/dev-story/instructions.xml deleted file mode 100644 index 3c4989f39..000000000 --- a/src/bmm/workflows/4-implementation/dev-story/instructions.xml +++ /dev/null @@ -1,410 +0,0 @@ - - The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml - You MUST have already loaded and processed: {installed_path}/workflow.yaml - Communicate all responses in {communication_language} and language MUST be tailored to {user_skill_level} - Generate all documents in {document_output_language} - Only modify the story file in these areas: Tasks/Subtasks checkboxes, Dev Agent Record (Debug Log, Completion Notes), File List, - Change Log, and Status - Execute ALL steps in exact order; do NOT skip steps - Absolutely DO NOT stop because of "milestones", "significant progress", or "session boundaries". Continue in a single execution - until the story is COMPLETE (all ACs satisfied and all tasks/subtasks checked) UNLESS a HALT condition is triggered or the USER gives - other instruction. - Do NOT schedule a "next session" or request review pauses unless a HALT condition applies. Only Step 6 decides completion. - User skill level ({user_skill_level}) affects conversation style ONLY, not code updates. - - - - Use {{story_path}} directly - Read COMPLETE story file - Extract story_key from filename or metadata - - - - - - MUST read COMPLETE sprint-status.yaml file from start to end to preserve order - Load the FULL file: {{sprint_status}} - Read ALL lines from beginning to end - do not skip any content - Parse the development_status section completely to understand story order - - Find the FIRST story (by reading in order from top to bottom) where: - - Key matches pattern: number-number-name (e.g., "1-2-user-auth") - - NOT an epic key (epic-X) or retrospective (epic-X-retrospective) - - Status value equals "ready-for-dev" - - - - 📋 No ready-for-dev stories found in sprint-status.yaml - - **Current Sprint Status:** {{sprint_status_summary}} - - **What would you like to do?** - 1. Run `create-story` to create next story from epics with comprehensive context - 2. Run `*validate-create-story` to improve existing stories before development (recommended quality check) - 3. Specify a particular story file to develop (provide full path) - 4. Check {{sprint_status}} file to see current sprint status - - 💡 **Tip:** Stories in `ready-for-dev` may not have been validated. Consider running `validate-create-story` first for a quality - check. - - Choose option [1], [2], [3], or [4], or specify story file path: - - - HALT - Run create-story to create next story - - - - HALT - Run validate-create-story to improve existing stories - - - - Provide the story file path to develop: - Store user-provided story path as {{story_path}} - - - - - Loading {{sprint_status}} for detailed status review... - Display detailed sprint status analysis - HALT - User can review sprint status and provide story path - - - - Store user-provided story path as {{story_path}} - - - - - - - - Search {implementation_artifacts} for stories directly - Find stories with "ready-for-dev" status in files - Look for story files matching pattern: *-*-*.md - Read each candidate story file to check Status section - - - 📋 No ready-for-dev stories found - - **Available Options:** - 1. Run `create-story` to create next story from epics with comprehensive context - 2. Run `*validate-create-story` to improve existing stories - 3. Specify which story to develop - - What would you like to do? Choose option [1], [2], or [3]: - - - HALT - Run create-story to create next story - - - - HALT - Run validate-create-story to improve existing stories - - - - It's unclear what story you want developed. Please provide the full path to the story file: - Store user-provided story path as {{story_path}} - Continue with provided story file - - - - - Use discovered story file and extract story_key - - - - Store the found story_key (e.g., "1-2-user-authentication") for later status updates - Find matching story file in {implementation_artifacts} using story_key pattern: {{story_key}}.md - Read COMPLETE story file from discovered path - - - - Parse sections: Story, Acceptance Criteria, Tasks/Subtasks, Dev Notes, Dev Agent Record, File List, Change Log, Status - - Load comprehensive context from story file's Dev Notes section - Extract developer guidance from Dev Notes: architecture requirements, previous learnings, technical specifications - Use enhanced story context to inform implementation decisions and approaches - - Identify first incomplete task (unchecked [ ]) in Tasks/Subtasks - - - Completion sequence - - HALT: "Cannot develop story without access to story file" - ASK user to clarify or HALT - - - - Load all available context to inform implementation - - Load {project_context} for coding standards and project-wide patterns (if exists) - Parse sections: Story, Acceptance Criteria, Tasks/Subtasks, Dev Notes, Dev Agent Record, File List, Change Log, Status - Load comprehensive context from story file's Dev Notes section - Extract developer guidance from Dev Notes: architecture requirements, previous learnings, technical specifications - Use enhanced story context to inform implementation decisions and approaches - ✅ **Context Loaded** - Story and project context available for implementation - - - - - Determine if this is a fresh start or continuation after code review - - Check if "Senior Developer Review (AI)" section exists in the story file - Check if "Review Follow-ups (AI)" subsection exists under Tasks/Subtasks - - - Set review_continuation = true - Extract from "Senior Developer Review (AI)" section: - - Review outcome (Approve/Changes Requested/Blocked) - - Review date - - Total action items with checkboxes (count checked vs unchecked) - - Severity breakdown (High/Med/Low counts) - - Count unchecked [ ] review follow-up tasks in "Review Follow-ups (AI)" subsection - Store list of unchecked review items as {{pending_review_items}} - - ⏯️ **Resuming Story After Code Review** ({{review_date}}) - - **Review Outcome:** {{review_outcome}} - **Action Items:** {{unchecked_review_count}} remaining to address - **Priorities:** {{high_count}} High, {{med_count}} Medium, {{low_count}} Low - - **Strategy:** Will prioritize review follow-up tasks (marked [AI-Review]) before continuing with regular tasks. - - - - - Set review_continuation = false - Set {{pending_review_items}} = empty - - 🚀 **Starting Fresh Implementation** - - Story: {{story_key}} - Story Status: {{current_status}} - First incomplete task: {{first_task_description}} - - - - - - - Load the FULL file: {{sprint_status}} - Read all development_status entries to find {{story_key}} - Get current status value for development_status[{{story_key}}] - - - Update the story in the sprint status report to = "in-progress" - 🚀 Starting work on story {{story_key}} - Status updated: ready-for-dev → in-progress - - - - - ⏯️ Resuming work on story {{story_key}} - Story is already marked in-progress - - - - - ⚠️ Unexpected story status: {{current_status}} - Expected ready-for-dev or in-progress. Continuing anyway... - - - - Store {{current_sprint_status}} for later use - - - - ℹ️ No sprint status file exists - story progress will be tracked in story file only - Set {{current_sprint_status}} = "no-sprint-tracking" - - - - - FOLLOW THE STORY FILE TASKS/SUBTASKS SEQUENCE EXACTLY AS WRITTEN - NO DEVIATION - - Review the current task/subtask from the story file - this is your authoritative implementation guide - Plan implementation following red-green-refactor cycle - - - Write FAILING tests first for the task/subtask functionality - Confirm tests fail before implementation - this validates test correctness - - - Implement MINIMAL code to make tests pass - Run tests to confirm they now pass - Handle error conditions and edge cases as specified in task/subtask - - - Improve code structure while keeping tests green - Ensure code follows architecture patterns and coding standards from Dev Notes - - Document technical approach and decisions in Dev Agent Record → Implementation Plan - - HALT: "Additional dependencies need user approval" - HALT and request guidance - HALT: "Cannot proceed without necessary configuration files" - - NEVER implement anything not mapped to a specific task/subtask in the story file - NEVER proceed to next task until current task/subtask is complete AND tests pass - Execute continuously without pausing until all tasks/subtasks are complete or explicit HALT condition - Do NOT propose to pause for review until Step 9 completion gates are satisfied - - - - Create unit tests for business logic and core functionality introduced/changed by the task - Add integration tests for component interactions specified in story requirements - Include end-to-end tests for critical user flows when story requirements demand them - Cover edge cases and error handling scenarios identified in story Dev Notes - - - - Determine how to run tests for this repo (infer test framework from project structure) - Run all existing tests to ensure no regressions - Run the new tests to verify implementation correctness - Run linting and code quality checks if configured in project - Validate implementation meets ALL story acceptance criteria; enforce quantitative thresholds explicitly - STOP and fix before continuing - identify breaking changes immediately - STOP and fix before continuing - ensure implementation correctness - - - - NEVER mark a task complete unless ALL conditions are met - NO LYING OR CHEATING - - - Verify ALL tests for this task/subtask ACTUALLY EXIST and PASS 100% - Confirm implementation matches EXACTLY what the task/subtask specifies - no extra features - Validate that ALL acceptance criteria related to this task are satisfied - Run full test suite to ensure NO regressions introduced - - - - Extract review item details (severity, description, related AC/file) - Add to resolution tracking list: {{resolved_review_items}} - - - Mark task checkbox [x] in "Tasks/Subtasks → Review Follow-ups (AI)" section - - - Find matching action item in "Senior Developer Review (AI) → Action Items" section by matching description - Mark that action item checkbox [x] as resolved - - Add to Dev Agent Record → Completion Notes: "✅ Resolved review finding [{{severity}}]: {{description}}" - - - - - ONLY THEN mark the task (and subtasks) checkbox with [x] - Update File List section with ALL new, modified, or deleted files (paths relative to repo root) - Add completion notes to Dev Agent Record summarizing what was ACTUALLY implemented and tested - - - - DO NOT mark task complete - fix issues first - HALT if unable to fix validation failures - - - - Count total resolved review items in this session - Add Change Log entry: "Addressed code review findings - {{resolved_count}} items resolved (Date: {{date}})" - - - Save the story file - Determine if more incomplete tasks remain - - Next task - - - Completion - - - - - Verify ALL tasks and subtasks are marked [x] (re-scan the story document now) - Run the full regression suite (do not skip) - Confirm File List includes every changed file - Execute enhanced definition-of-done validation - Update the story Status to: "review" - - - Validate definition-of-done checklist with essential requirements: - - All tasks/subtasks marked complete with [x] - - Implementation satisfies every Acceptance Criterion - - Unit tests for core functionality added/updated - - Integration tests for component interactions added when required - - End-to-end tests for critical flows added when story demands them - - All tests pass (no regressions, new tests successful) - - Code quality checks pass (linting, static analysis if configured) - - File List includes every new/modified/deleted file (relative paths) - - Dev Agent Record contains implementation notes - - Change Log includes summary of changes - - Only permitted story sections were modified - - - - - Load the FULL file: {sprint_status} - Find development_status key matching {{story_key}} - Verify current status is "in-progress" (expected previous state) - Update development_status[{{story_key}}] = "review" - Save file, preserving ALL comments and structure including STATUS DEFINITIONS - ✅ Story status updated to "review" in sprint-status.yaml - - - - ℹ️ Story status updated to "review" in story file (no sprint tracking configured) - - - - ⚠️ Story file updated, but sprint-status update failed: {{story_key}} not found - - Story status is set to "review" in file, but sprint-status.yaml may be out of sync. - - - - - HALT - Complete remaining tasks before marking ready for review - HALT - Fix regression issues before completing - HALT - Update File List with all changed files - HALT - Address DoD failures before completing - - - - Execute the enhanced definition-of-done checklist using the validation framework - Prepare a concise summary in Dev Agent Record → Completion Notes - - Communicate to {user_name} that story implementation is complete and ready for review - Summarize key accomplishments: story ID, story key, title, key changes made, tests added, files modified - Provide the story file path and current status (now "review") - - Based on {user_skill_level}, ask if user needs any explanations about: - - What was implemented and how it works - - Why certain technical decisions were made - - How to test or verify the changes - - Any patterns, libraries, or approaches used - - Anything else they'd like clarified - - - - Provide clear, contextual explanations tailored to {user_skill_level} - Use examples and references to specific code when helpful - - - Once explanations are complete (or user indicates no questions), suggest logical next steps - Recommended next steps (flexible based on project setup): - - Review the implemented story and test the changes - - Verify all acceptance criteria are met - - Ensure deployment readiness if applicable - - Run `code-review` workflow for peer review - - Optional: If Test Architect module installed, run `/bmad:tea:automate` to expand guardrail tests - - - 💡 **Tip:** For best results, run `code-review` using a **different** LLM than the one that implemented this story. - - Suggest checking {sprint_status} to see project progress - - Remain flexible - allow user to choose their own path or ask for other assistance - - - diff --git a/src/bmm/workflows/4-implementation/dev-story/steps/step-01-find-story.md b/src/bmm/workflows/4-implementation/dev-story/steps/step-01-find-story.md new file mode 100644 index 000000000..f73859dcb --- /dev/null +++ b/src/bmm/workflows/4-implementation/dev-story/steps/step-01-find-story.md @@ -0,0 +1,130 @@ +--- +name: 'step-01-find-story' +description: 'Find the next ready story (or accept explicit input), load it completely, and identify the next actionable task' +nextStepFile: './step-02-load-context.md' +--- + + + + Use {{story_path}} directly + Read COMPLETE story file + Extract story_key from filename or metadata + + + + + + MUST read COMPLETE sprint-status.yaml file from start to end to preserve order + Load the FULL file: {{sprint_status}} + Read ALL lines from beginning to end - do not skip any content + Parse the development_status section completely to understand story order + + Find the FIRST story (by reading in order from top to bottom) where: + - Key matches pattern: number-number-name (e.g., "1-2-user-auth") + - NOT an epic key (epic-X) or retrospective (epic-X-retrospective) + - Status value equals "ready-for-dev" + + + + 📋 No ready-for-dev stories found in sprint-status.yaml + + **Current Sprint Status:** {{sprint_status_summary}} + + **What would you like to do?** + 1. Run `create-story` to create next story from epics with comprehensive context + 2. Run `*validate-create-story` to improve existing stories before development (recommended quality check) + 3. Specify a particular story file to develop (provide full path) + 4. Check {{sprint_status}} file to see current sprint status + + 💡 **Tip:** Stories in `ready-for-dev` may not have been validated. Consider running `validate-create-story` first for a quality + check. + + Choose option [1], [2], [3], or [4], or specify story file path: + + + HALT - Run create-story to create next story + + + + HALT - Run validate-create-story to improve existing stories + + + + Provide the story file path to develop: + Store user-provided story path as {{story_path}} + + + + + Loading {{sprint_status}} for detailed status review... + Display detailed sprint status analysis + HALT - User can review sprint status and provide story path + + + + Store user-provided story path as {{story_path}} + + + + + + + + Search {story_dir} for stories directly + Find stories with "ready-for-dev" status in files + Look for story files matching pattern: *-*-*.md + Read each candidate story file to check Status section + + + 📋 No ready-for-dev stories found + + **Available Options:** + 1. Run `create-story` to create next story from epics with comprehensive context + 2. Run `*validate-create-story` to improve existing stories + 3. Specify which story to develop + + What would you like to do? Choose option [1], [2], or [3]: + + + HALT - Run create-story to create next story + + + + HALT - Run validate-create-story to improve existing stories + + + + It's unclear what story you want developed. Please provide the full path to the story file: + Store user-provided story path as {{story_path}} + Continue with provided story file + + + + + Use discovered story file and extract story_key + + + + Store the found story_key (e.g., "1-2-user-authentication") for later status updates + Find matching story file in {story_dir} using story_key pattern: {{story_key}}.md + Read COMPLETE story file from discovered path + + + + Parse sections: Story, Acceptance Criteria, Tasks/Subtasks, Dev Notes, Dev Agent Record, File List, Change Log, Status + + Load comprehensive context from story file's Dev Notes section + Extract developer guidance from Dev Notes: architecture requirements, previous learnings, technical specifications + Use enhanced story context to inform implementation decisions and approaches + + Identify first incomplete task (unchecked [ ]) in Tasks/Subtasks + + + Completion sequence + + HALT: "Cannot develop story without access to story file" + ASK user to clarify or HALT + + +## Next +- Read fully and follow: `./step-02-load-context.md`. diff --git a/src/bmm/workflows/4-implementation/dev-story/steps/step-02-load-context.md b/src/bmm/workflows/4-implementation/dev-story/steps/step-02-load-context.md new file mode 100644 index 000000000..30ef4f6a6 --- /dev/null +++ b/src/bmm/workflows/4-implementation/dev-story/steps/step-02-load-context.md @@ -0,0 +1,38 @@ +--- +name: 'step-02-load-context' +description: 'Load project and story context needed for implementation decisions' +nextStepFile: './step-03-detect-review-continuation.md' +--- + + + Load all available context to inform implementation + + Load {project_context} for coding standards and project-wide patterns (if exists) + Validate story source before parsing: + - Verify story file exists and is readable + - If missing/unreadable: emit explicit error and HALT + + Parse and validate required sections: Story, Acceptance Criteria, Tasks/Subtasks, Dev Notes, Dev Agent Record, File List, Status + - If section missing, empty, or malformed: emit explicit error with section name and HALT + - Dev Notes is CRITICAL and MUST be present with non-empty actionable content + + Parse and validate optional section: Change Log + - If missing/empty: create warning and continue with safe default ("No prior change log entries") + + Validate structure before extraction: + - Story: identifiable title + narrative structure + - Acceptance Criteria: parseable list/numbered clauses + - Tasks/Subtasks: checkbox task format with stable task boundaries + - Dev Agent Record/File List/Status: parseable heading + body content + - If malformed structure prevents reliable parsing: emit explicit error and HALT + + Load comprehensive context from story file's Dev Notes section ONLY after validation passes + Extract developer guidance from Dev Notes: architecture requirements, previous learnings, technical specifications + Use enhanced story context to inform implementation decisions and approaches + ✅ **Context Loaded** + Story and project context available for implementation + + + +## Next +- Read fully and follow: `./step-03-detect-review-continuation.md`. diff --git a/src/bmm/workflows/4-implementation/dev-story/steps/step-03-detect-review-continuation.md b/src/bmm/workflows/4-implementation/dev-story/steps/step-03-detect-review-continuation.md new file mode 100644 index 000000000..cd0869388 --- /dev/null +++ b/src/bmm/workflows/4-implementation/dev-story/steps/step-03-detect-review-continuation.md @@ -0,0 +1,48 @@ +--- +name: 'step-03-detect-review-continuation' +description: 'Determine whether this run resumes from prior code review and gather pending follow-ups' +nextStepFile: './step-04-mark-in-progress.md' +--- + + + Determine if this is a fresh start or continuation after code review + + Check if "Senior Developer Review (AI)" section exists in the story file + Check if "Review Follow-ups (AI)" subsection exists under Tasks/Subtasks + + + Set review_continuation = true + Extract from "Senior Developer Review (AI)" section: + - Review outcome (Approve/Changes Requested/Blocked) + - Review date + - Total action items with checkboxes (count checked vs unchecked) + - Severity breakdown (High/Med/Low counts) + + Count unchecked [ ] review follow-up tasks in "Review Follow-ups (AI)" subsection + Store list of unchecked review items as {{pending_review_items}} + + ⏯️ **Resuming Story After Code Review** ({{review_date}}) + + **Review Outcome:** {{review_outcome}} + **Action Items:** {{unchecked_review_count}} remaining to address + **Priorities:** {{high_count}} High, {{med_count}} Medium, {{low_count}} Low + + **Strategy:** Will prioritize review follow-up tasks (marked [AI-Review]) before continuing with regular tasks. + + + + + Set review_continuation = false + Set {{pending_review_items}} = empty + + 🚀 **Starting Fresh Implementation** + + Story: {{story_key}} + Story Status: {{current_status}} + First incomplete task: {{first_task_description}} + + + + +## Next +- Read fully and follow: `./step-04-mark-in-progress.md`. diff --git a/src/bmm/workflows/4-implementation/dev-story/steps/step-04-mark-in-progress.md b/src/bmm/workflows/4-implementation/dev-story/steps/step-04-mark-in-progress.md new file mode 100644 index 000000000..b1cb021fd --- /dev/null +++ b/src/bmm/workflows/4-implementation/dev-story/steps/step-04-mark-in-progress.md @@ -0,0 +1,42 @@ +--- +name: 'step-04-mark-in-progress' +description: 'Synchronize in-progress status with sprint tracking when available' +nextStepFile: './step-05-implement-task.md' +--- + + + + Load the FULL file: {{sprint_status}} + Read all development_status entries to find {{story_key}} + Get current status value for development_status[{{story_key}}] + + + Update the story in the sprint status report to = "in-progress" + 🚀 Starting work on story {{story_key}} + Status updated: ready-for-dev → in-progress + + + + + ⏯️ Resuming work on story {{story_key}} + Story is already marked in-progress + + + + + ⚠️ Unexpected story status: {{current_status}} + Expected ready-for-dev or in-progress. Continuing anyway... + + + + Store {{current_sprint_status}} for later use + + + + ℹ️ No sprint status file exists - story progress will be tracked in story file only + Set {{current_sprint_status}} = "no-sprint-tracking" + + + +## Next +- Read fully and follow: `./step-05-implement-task.md`. diff --git a/src/bmm/workflows/4-implementation/dev-story/steps/step-05-implement-task.md b/src/bmm/workflows/4-implementation/dev-story/steps/step-05-implement-task.md new file mode 100644 index 000000000..8a3112060 --- /dev/null +++ b/src/bmm/workflows/4-implementation/dev-story/steps/step-05-implement-task.md @@ -0,0 +1,39 @@ +--- +name: 'step-05-implement-task' +description: 'Implement the current task using red-green-refactor and story constraints' +nextStepFile: './step-06-author-tests.md' +--- + + + FOLLOW THE STORY FILE TASKS/SUBTASKS SEQUENCE EXACTLY AS WRITTEN - NO DEVIATION + + Review the current task/subtask from the story file - this is your authoritative implementation guide + Plan implementation following red-green-refactor cycle + + + Write FAILING tests first for the task/subtask functionality + Confirm tests fail before implementation - this validates test correctness + + + Implement MINIMAL code to make tests pass + Run tests to confirm they now pass + Handle error conditions and edge cases as specified in task/subtask + + + Improve code structure while keeping tests green + Ensure code follows architecture patterns and coding standards from Dev Notes + + Document technical approach and decisions in Dev Agent Record → Implementation Plan + + HALT: "Additional dependencies need user approval" + HALT and request guidance + HALT: "Cannot proceed without necessary configuration files" + + NEVER implement anything not mapped to a specific task/subtask in the story file + NEVER proceed to next task until current task/subtask is complete AND tests pass + Execute continuously without pausing until all tasks/subtasks are complete or explicit HALT condition + Do NOT propose to pause for review until Step 9 completion gates are satisfied + + +## Next +- Read fully and follow: `./step-06-author-tests.md`. diff --git a/src/bmm/workflows/4-implementation/dev-story/steps/step-06-author-tests.md b/src/bmm/workflows/4-implementation/dev-story/steps/step-06-author-tests.md new file mode 100644 index 000000000..193647056 --- /dev/null +++ b/src/bmm/workflows/4-implementation/dev-story/steps/step-06-author-tests.md @@ -0,0 +1,15 @@ +--- +name: 'step-06-author-tests' +description: 'Author comprehensive unit/integration/e2e coverage required by the story' +nextStepFile: './step-07-run-validations.md' +--- + + + Create unit tests for business logic and core functionality introduced/changed by the task + Add integration tests for component interactions specified in story requirements + Include end-to-end tests for critical user flows when story requirements demand them + Cover edge cases and error handling scenarios identified in story Dev Notes + + +## Next +- Read fully and follow: `./step-07-run-validations.md`. diff --git a/src/bmm/workflows/4-implementation/dev-story/steps/step-07-run-validations.md b/src/bmm/workflows/4-implementation/dev-story/steps/step-07-run-validations.md new file mode 100644 index 000000000..f56e6627e --- /dev/null +++ b/src/bmm/workflows/4-implementation/dev-story/steps/step-07-run-validations.md @@ -0,0 +1,18 @@ +--- +name: 'step-07-run-validations' +description: 'Run repository test and validation commands, then stop on regressions' +nextStepFile: './step-08-mark-task-complete.md' +--- + + + Determine how to run tests for this repo (infer test framework from project structure) + Run all existing tests to ensure no regressions + Run the new tests to verify implementation correctness + Run linting and code quality checks if configured in project + Validate implementation meets ALL story acceptance criteria; enforce quantitative thresholds explicitly + STOP and fix before continuing - identify breaking changes immediately + STOP and fix before continuing - ensure implementation correctness + + +## Next +- Read fully and follow: `./step-08-mark-task-complete.md`. diff --git a/src/bmm/workflows/4-implementation/dev-story/steps/step-08-mark-task-complete.md b/src/bmm/workflows/4-implementation/dev-story/steps/step-08-mark-task-complete.md new file mode 100644 index 000000000..4facc56f8 --- /dev/null +++ b/src/bmm/workflows/4-implementation/dev-story/steps/step-08-mark-task-complete.md @@ -0,0 +1,119 @@ +--- +name: 'step-08-mark-task-complete' +description: 'Mark work complete only after strict validation gates are satisfied' +nextStepFile: './step-09-mark-review-ready.md' +--- + + + NEVER mark a task complete unless ALL conditions are met - NO LYING OR CHEATING + + Initialize review-tracking variables before checks: + - If {{resolved_review_items}} is undefined: set {{resolved_review_items}} = [] + - If {{unresolved_review_items}} is undefined: set {{unresolved_review_items}} = [] + - Set {{review_continuation}} = false + - If current {{task_title}} starts with "[AI-Review]", set {{review_continuation}} = true + - Else scan {{original_task_list}}; if any item starts with "[AI-Review]", set {{review_continuation}} = true + - Set {{date}} from system-generated timestamp formatted for project change log entries + - Set {{resolved_count}} = length({{resolved_review_items}}) + - Set {{review_match_threshold}} = 0.60 + - Define normalize(text): lowercase, trim, remove "[AI-Review]" prefix and punctuation, collapse whitespace + - Define token_set(text): unique whitespace-separated normalized tokens + + + + Verify ALL tests for this task/subtask ACTUALLY EXIST and PASS 100% + Confirm implementation matches EXACTLY what the task/subtask specifies - no extra features + Validate that ALL acceptance criteria related to this task are satisfied + Run full test suite to ensure NO regressions introduced + + + + Extract review item details (severity, description, related AC/file) + Load all items from "Senior Developer Review (AI) → Action Items" as candidate list {{review_action_items}} + Set {{task_text_norm}} = normalize(current review follow-up task description) + Initialize {{best_match}} = null, {{best_score}} = 0, {{best_shared_tokens}} = 0, {{tie_candidates}} = [] + For each candidate action item: + 1. Set {{candidate_text_norm}} = normalize(candidate text) + 2. If {{task_text_norm}} == {{candidate_text_norm}} OR either contains the other: + - set {{candidate_score}} = 1.0 and mark as strong match + 3. Else: + - compute Jaccard score = |token_set(task) ∩ token_set(candidate)| / |token_set(task) ∪ token_set(candidate)| + - set {{candidate_score}} to computed score + 4. Track shared-token count for tie-breaking + 5. Keep highest score candidate; if same score, keep candidate with more shared tokens + 6. If score and shared-token count both tie, add candidate to {{tie_candidates}} + + Set {{match_found}} = true only if {{best_score}} >= {{review_match_threshold}} + + + Mark task checkbox [x] in "Tasks/Subtasks → Review Follow-ups (AI)" section + + + Mark matched action item checkbox [x] in "Senior Developer Review (AI) → Action Items" + Append structured entry to {{resolved_review_items}}: + - task: current review follow-up task + - matched_action_item: {{best_match}} + - match_score: {{best_score}} + - resolved_at: {{date}} + - status: "matched" + + + Log ambiguity warning with tied candidates and selected best_match + + Add to Dev Agent Record → Completion Notes: "✅ Resolved review finding [{{severity}}]: {{description}} (matched action item, score {{best_score}})" + + + + Log warning: no candidate met threshold {{review_match_threshold}} for task "{{task_text_norm}}" + Append structured entry to {{resolved_review_items}}: + - task: current review follow-up task + - matched_action_item: null + - match_score: {{best_score}} + - resolved_at: {{date}} + - status: "unmatched" + + Append structured entry to {{unresolved_review_items}}: + - task: current review follow-up task + - reason: "No corresponding action item met fuzzy-match threshold" + - best_candidate: {{best_match}} + - best_score: {{best_score}} + - recorded_at: {{date}} + + Add resolution note in Dev Agent Record that no corresponding action item was found, while follow-up checkbox was still marked complete + + + + + + ONLY THEN mark the task (and subtasks) checkbox with [x] + Update File List section with ALL new, modified, or deleted files (paths relative to repo root) + Add completion notes to Dev Agent Record summarizing what was ACTUALLY implemented and tested + + + + DO NOT mark task complete - fix issues first + If unable to fix validation failures, invoke HALT protocol from dev-story/workflow.md with: + - reason_code: DEV-STORY-STEP-08-VALIDATION-FAIL + - step_id: step-08-mark-task-complete + - message: "Task completion validation failed and remediation was unsuccessful." + - required_action: "Fix failing validations/tests, then resume." + + + + + Set {{resolved_count}} = length({{resolved_review_items}}) + Add Change Log entry: "Addressed code review findings - {{resolved_count}} items resolved (Date: {{date}})" + + + Save the story file + Determine if more incomplete tasks remain + + Next task + + + Completion + + + +## Next +- Read fully and follow: `./step-09-mark-review-ready.md`. diff --git a/src/bmm/workflows/4-implementation/dev-story/steps/step-09-mark-review-ready.md b/src/bmm/workflows/4-implementation/dev-story/steps/step-09-mark-review-ready.md new file mode 100644 index 000000000..fbdead276 --- /dev/null +++ b/src/bmm/workflows/4-implementation/dev-story/steps/step-09-mark-review-ready.md @@ -0,0 +1,67 @@ +--- +name: 'step-09-mark-review-ready' +description: 'Finalize story, enforce definition-of-done, and set review status' +nextStepFile: './step-10-closeout.md' +--- + + + Verify ALL tasks and subtasks are marked [x] (re-scan the story document now) + Run the full regression suite (do not skip) + Confirm File List includes every changed file + Execute enhanced definition-of-done validation + Update the story Status to: "review" + Initialize sprint tracking state deterministically before any sprint-status check: + - Set {{current_sprint_status}} = "no-sprint-tracking" + - Set {{sprint_tracking_enabled}} = false + - If {sprint_status} exists and is readable: + - Load the FULL file: {sprint_status} + - If file content indicates tracking disabled OR development_status section is missing, keep "no-sprint-tracking" + - Else set {{current_sprint_status}} = "enabled" and {{sprint_tracking_enabled}} = true + - If file missing/unreadable, keep defaults and continue with story-only status update + + + + Validate definition-of-done checklist with essential requirements: + - All tasks/subtasks marked complete with [x] + - Implementation satisfies every Acceptance Criterion + - Unit tests for core functionality added/updated + - Integration tests for component interactions added when required + - End-to-end tests for critical flows added when story demands them + - All tests pass (no regressions, new tests successful) + - Code quality checks pass (linting, static analysis if configured) + - File List includes every new/modified/deleted file (relative paths) + - Dev Agent Record contains implementation notes + - Change Log includes summary of changes + - Only permitted story sections were modified + + + + + Find development_status key matching {{story_key}} + + Verify current status is "in-progress" (expected previous state) + Update development_status[{{story_key}}] = "review" + Save file, preserving ALL comments and structure including STATUS DEFINITIONS + ✅ Story status updated to "review" in sprint-status.yaml + + + ⚠️ Story file updated, but sprint-status update failed: {{story_key}} not found + + Story status is set to "review" in file, but sprint-status.yaml may be out of sync. + + + + + + ℹ️ Story status updated to "review" in story file (no sprint tracking configured) + + + + Invoke HALT protocol (reason_code: DEV-STORY-STEP-09-INCOMPLETE-TASKS, step_id: step-09-mark-review-ready, message: "Incomplete tasks remain before review-ready transition.", required_action: "Complete all tasks/subtasks and rerun validations.") + Invoke HALT protocol (reason_code: DEV-STORY-STEP-09-REGRESSION-FAIL, step_id: step-09-mark-review-ready, message: "Regression suite has failures.", required_action: "Fix failing tests and rerun full regression suite.") + Invoke HALT protocol (reason_code: DEV-STORY-STEP-09-FILE-LIST-INCOMPLETE, step_id: step-09-mark-review-ready, message: "File List does not include all changed files.", required_action: "Update File List with all added/modified/deleted paths.") + Invoke HALT protocol (reason_code: DEV-STORY-STEP-09-DOD-FAIL, step_id: step-09-mark-review-ready, message: "Definition-of-done checks failed.", required_action: "Address DoD failures and rerun validation.") + + +## Next +- Read fully and follow: `./step-10-closeout.md`. diff --git a/src/bmm/workflows/4-implementation/dev-story/steps/step-10-closeout.md b/src/bmm/workflows/4-implementation/dev-story/steps/step-10-closeout.md new file mode 100644 index 000000000..e45e0b8c6 --- /dev/null +++ b/src/bmm/workflows/4-implementation/dev-story/steps/step-10-closeout.md @@ -0,0 +1,41 @@ +--- +name: 'step-10-closeout' +description: 'Summarize completion, answer user questions, and recommend next steps' +--- + + + Validate against checklist at {installed_path}/checklist.md using _bmad/core/tasks/validate-workflow.md + Prepare a concise summary in Dev Agent Record → Completion Notes + + Communicate to {user_name} that story implementation is complete and ready for review + Summarize key accomplishments: story ID, story key, title, key changes made, tests added, files modified + Provide the story file path and current status (now "review") + + Based on {user_skill_level}, ask if user needs any explanations about: + - What was implemented and how it works + - Why certain technical decisions were made + - How to test or verify the changes + - Any patterns, libraries, or approaches used + - Anything else they'd like clarified + + + + Provide clear, contextual explanations tailored to {user_skill_level} + Use examples and references to specific code when helpful + + + Once explanations are complete (or user indicates no questions), suggest logical next steps + Recommended next steps (flexible based on project setup): + - Review the implemented story and test the changes + - Verify all acceptance criteria are met + - Ensure deployment readiness if applicable + - Run `code-review` workflow for peer review + - Optional: If Test Architect module installed, run `/bmad:tea:automate` to expand guardrail tests + + + 💡 **Tip:** For best results, run `code-review` using a **different** LLM than the one that implemented this story. + + Suggest checking {sprint_status} to see project progress + + Remain flexible - allow user to choose their own path or ask for other assistance + diff --git a/src/bmm/workflows/4-implementation/dev-story/workflow.md b/src/bmm/workflows/4-implementation/dev-story/workflow.md new file mode 100644 index 000000000..0a1a2f210 --- /dev/null +++ b/src/bmm/workflows/4-implementation/dev-story/workflow.md @@ -0,0 +1,80 @@ +--- +name: dev-story +description: "Execute a story by implementing tasks/subtasks, writing tests, validating, and updating the story file per acceptance criteria" +projectRoot: '{project-root}' +main_config: '{project-root}/_bmad/bmm/config.yaml' +web_bundle: false +--- + +# Dev Story Workflow + +## Goal +Implement a ready story end-to-end with strict validation gates, accurate progress tracking, and high-quality test coverage. + +## Workflow Architecture +- Uses step-file execution to keep context focused and deterministic. +- Read one step file fully, execute it, then move to the next step file. +- Do not pre-load future step files. + +## Initialization +- Resolve `projectRoot`: + - Prefer `{project-root}` when provided by runtime. + - If unavailable, resolve repo root from current working directory (locate-repo-root helper / process cwd) and set `projectRoot`. + - Validate that `{projectRoot}/_bmad/bmm/config.yaml` exists and is readable before continuing. +- Load config from `{projectRoot}/_bmad/bmm/config.yaml`. +- Resolve variables: + - `user_name` + - `communication_language` + - `document_output_language` + - `user_skill_level` + - `implementation_artifacts` + - `story_dir` = `{implementation_artifacts}` + - `sprint_status` = `{implementation_artifacts}/sprint-status.yaml` + - `story_file` (if provided) + - `project_context` = `**/project-context.md` + - `date` (system-generated) + - `installed_path` = `{projectRoot}/_bmad/bmm/workflows/4-implementation/dev-story` + +## Critical Rules +- Communicate in `{communication_language}` and tailor explanations to `{user_skill_level}`. +- Generate any documents in `{document_output_language}`. +- Only update allowed story sections: + - Tasks/Subtasks checkboxes + - Dev Agent Record (Debug Log, Completion Notes) + - File List + - Change Log + - Status +- Execute steps in order and do not skip validation gates. +- Continue until the story is complete unless the HALT protocol below is triggered. + +## HALT Protocol (Normative) +- Scope: + - Every `HALT` instruction in this workflow and all `steps/*.md` files MUST use this protocol. +- Operational definition: + - HALT is a deterministic hard-stop event raised when execution cannot safely continue. + - A HALT event MUST include: + - `reason_code` (stable machine-readable code) + - `step_id` (current step file + step number) + - `message` (human-readable failure summary) + - `required_action` (what user/operator must do before resume) +- Trigger criteria: + - Required inputs/files are missing, unreadable, or malformed. + - Validation gates fail and cannot be remediated in the current step. + - Test/regression failures persist after attempted fixes. + - Story state is inconsistent (for example malformed task structure preventing safe updates). +- HALT behavior: + - Stop execution immediately and skip all downstream steps. + - Persist workflow checkpoint: current step id, resolved variables, and pending task context. + - Persist only already-applied safe edits; do not apply new partial completion marks after HALT. + - Emit logger event exactly in this format: + - `HALT[{reason_code}] step={step_id} story={story_key|unknown} detail=\"{message}\"` + - Emit user-facing prompt exactly in this format: + - `Workflow HALTED at {step_id} ({reason_code}): {message}. Required action: {required_action}. Reply RESUME after remediation.` +- Resume semantics: + - Manual resume only (no automatic retry loop). + - Resume is checkpoint-based: restart from the halted step after user confirms remediation. + - Re-run the failed validation/input check before executing further actions. + - If the same HALT condition repeats, stop again with updated evidence. + +## Execution +Read fully and follow: `steps/step-01-find-story.md`. diff --git a/src/bmm/workflows/4-implementation/dev-story/workflow.yaml b/src/bmm/workflows/4-implementation/dev-story/workflow.yaml deleted file mode 100644 index c8a85a079..000000000 --- a/src/bmm/workflows/4-implementation/dev-story/workflow.yaml +++ /dev/null @@ -1,21 +0,0 @@ -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/bmm/config.yaml" -user_name: "{config_source}:user_name" -communication_language: "{config_source}:communication_language" -user_skill_level: "{config_source}:user_skill_level" -document_output_language: "{config_source}:document_output_language" -date: system-generated - -# Workflow components -installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/dev-story" -instructions: "{installed_path}/instructions.xml" -validation: "{installed_path}/checklist.md" - -story_file: "" # Explicit story path; auto-discovered if empty -implementation_artifacts: "{config_source}:implementation_artifacts" -sprint_status: "{implementation_artifacts}/sprint-status.yaml" -project_context: "**/project-context.md" diff --git a/src/bmm/workflows/4-implementation/retrospective/instructions.md b/src/bmm/workflows/4-implementation/retrospective/instructions.md index 018ef6ee3..73c302f48 100644 --- a/src/bmm/workflows/4-implementation/retrospective/instructions.md +++ b/src/bmm/workflows/4-implementation/retrospective/instructions.md @@ -1,7 +1,7 @@ # Retrospective - Epic Completion Review Instructions -The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml -You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml +The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.md +You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.md Communicate all responses in {communication_language} and language MUST be tailored to {user_skill_level} Generate all documents in {document_output_language} ⚠️ ABSOLUTELY NO TIME ESTIMATES - NEVER mention hours, days, weeks, months, or ANY time-based predictions. AI has fundamentally changed development speed - what once took teams weeks/months can now be done by one person in hours. DO NOT give ANY time estimates whatsoever. diff --git a/src/bmm/workflows/4-implementation/retrospective/workflow.md b/src/bmm/workflows/4-implementation/retrospective/workflow.md new file mode 100644 index 000000000..35c7d6250 --- /dev/null +++ b/src/bmm/workflows/4-implementation/retrospective/workflow.md @@ -0,0 +1,56 @@ +--- +name: retrospective +description: "Run after epic completion to review overall success, extract lessons learned, and surface impact on upcoming work" +main_config: '{project-root}/_bmad/bmm/config.yaml' +web_bundle: false +agent_manifest: '{project-root}/_bmad/_config/agent-manifest.csv' +input_file_patterns: + epics: + description: "The completed epic for retrospective" + whole: "{planning_artifacts}/*epic*.md" + sharded_index: "{planning_artifacts}/*epic*/index.md" + sharded_single: "{planning_artifacts}/*epic*/epic-{{epic_num}}.md" + load_strategy: "SELECTIVE_LOAD" + previous_retrospective: + description: "Previous epic's retrospective (optional)" + pattern: "{implementation_artifacts}/**/epic-{{prev_epic_num}}-retro-*.md" + load_strategy: "SELECTIVE_LOAD" + architecture: + description: "System architecture for context" + whole: "{planning_artifacts}/*architecture*.md" + sharded: "{planning_artifacts}/*architecture*/*.md" + load_strategy: "FULL_LOAD" + prd: + description: "Product requirements for context" + whole: "{planning_artifacts}/*prd*.md" + sharded: "{planning_artifacts}/*prd*/*.md" + load_strategy: "FULL_LOAD" + document_project: + description: "Brownfield project documentation (optional)" + sharded: "{planning_artifacts}/*.md" + load_strategy: "INDEX_GUIDED" +--- + +## Initialization +- Load config from `{project-root}/_bmad/bmm/config.yaml`. +- Resolve variables: + - `user_name` + - `communication_language` + - `document_output_language` + - `user_skill_level` + - `planning_artifacts` + - `implementation_artifacts` + - `agent_manifest` = `{project-root}/_bmad/_config/agent-manifest.csv` + - `sprint_status_file` = `{implementation_artifacts}/sprint-status.yaml` + - `story_directory` = `{implementation_artifacts}` + - `retrospectives_folder` = `{implementation_artifacts}` + - `date` (system-generated) + - `installed_path` = `{project-root}/_bmad/bmm/workflows/4-implementation/retrospective` + + + Communicate all responses in {communication_language} and generate all documents in {document_output_language} + + + Read and follow instructions at: {installed_path}/instructions.md + + diff --git a/src/bmm/workflows/4-implementation/retrospective/workflow.yaml b/src/bmm/workflows/4-implementation/retrospective/workflow.yaml deleted file mode 100644 index 773c7f2d6..000000000 --- a/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +++ /dev/null @@ -1,53 +0,0 @@ -# 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/bmm/config.yaml" -user_name: "{config_source}:user_name" -communication_language: "{config_source}:communication_language" -user_skill_level: "{config_source}:user_skill_level" -document_output_language: "{config_source}:document_output_language" -date: system-generated -planning_artifacts: "{config_source}:planning_artifacts" -implementation_artifacts: "{config_source}:implementation_artifacts" -project_context: "**/project-context.md" - -installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/retrospective" -template: false -instructions: "{installed_path}/instructions.md" - -required_inputs: - - agent_manifest: "{project-root}/_bmad/_config/agent-manifest.csv" - -# Smart input file references - handles both whole docs and sharded docs -# Priority: Whole document first, then sharded version -# Strategy: SELECTIVE LOAD - only load the completed epic and relevant retrospectives -input_file_patterns: - epics: - description: "The completed epic for retrospective" - whole: "{planning_artifacts}/*epic*.md" - sharded_index: "{planning_artifacts}/*epic*/index.md" - sharded_single: "{planning_artifacts}/*epic*/epic-{{epic_num}}.md" - load_strategy: "SELECTIVE_LOAD" - previous_retrospective: - description: "Previous epic's retrospective (optional)" - pattern: "{implementation_artifacts}/**/epic-{{prev_epic_num}}-retro-*.md" - load_strategy: "SELECTIVE_LOAD" - architecture: - description: "System architecture for context" - whole: "{planning_artifacts}/*architecture*.md" - sharded: "{planning_artifacts}/*architecture*/*.md" - load_strategy: "FULL_LOAD" - prd: - description: "Product requirements for context" - whole: "{planning_artifacts}/*prd*.md" - sharded: "{planning_artifacts}/*prd*/*.md" - load_strategy: "FULL_LOAD" - document_project: - description: "Brownfield project documentation (optional)" - sharded: "{planning_artifacts}/*.md" - load_strategy: "INDEX_GUIDED" - -# Required files -sprint_status_file: "{implementation_artifacts}/sprint-status.yaml" diff --git a/src/bmm/workflows/4-implementation/sprint-planning/instructions.md b/src/bmm/workflows/4-implementation/sprint-planning/instructions.md index 316d2fec3..20fe16ce8 100644 --- a/src/bmm/workflows/4-implementation/sprint-planning/instructions.md +++ b/src/bmm/workflows/4-implementation/sprint-planning/instructions.md @@ -1,7 +1,7 @@ # Sprint Planning - Sprint Status Generator -The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml -You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.md +You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/sprint-planning/workflow.md ## 📚 Document Discovery - Full Epic Loading diff --git a/src/bmm/workflows/4-implementation/sprint-planning/workflow.md b/src/bmm/workflows/4-implementation/sprint-planning/workflow.md new file mode 100644 index 000000000..9b79e8a7a --- /dev/null +++ b/src/bmm/workflows/4-implementation/sprint-planning/workflow.md @@ -0,0 +1,41 @@ +--- +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" +main_config: '{project-root}/_bmad/bmm/config.yaml' +web_bundle: false +epics_location: "{planning_artifacts}" +epics_pattern: "epic*.md" +input_file_patterns: + epics: + description: "All epics with user stories" + whole: "{epics_location}/{epics_pattern}" + sharded: "{epics_location}/epic*/*.md" + load_strategy: "FULL_LOAD" +--- + +## Initialization +- Load config from `{project-root}/_bmad/bmm/config.yaml`. +- Resolve variables: + - `user_name` + - `communication_language` + - `implementation_artifacts` + - `planning_artifacts` + - `project_name` + - `date` (system-generated) + - `epics_location` = `{planning_artifacts}` + - `epics_pattern` = `epic*.md` + - `installed_path` = `{project-root}/_bmad/bmm/workflows/4-implementation/sprint-planning` + - `status_file` = `{implementation_artifacts}/sprint-status.yaml` + - `default_output_file` = `{status_file}` + + + Communicate all responses in {communication_language} + + + Read and follow instructions at: {installed_path}/instructions.md + + + + Validate against checklist at {installed_path}/checklist.md using _bmad/core/tasks/validate-workflow.md + + diff --git a/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml b/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml deleted file mode 100644 index 6c5d22d64..000000000 --- a/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +++ /dev/null @@ -1,47 +0,0 @@ -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/bmm/config.yaml" -user_name: "{config_source}:user_name" -communication_language: "{config_source}:communication_language" -date: system-generated -implementation_artifacts: "{config_source}:implementation_artifacts" -planning_artifacts: "{config_source}:planning_artifacts" - -# Workflow components -installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/sprint-planning" -instructions: "{installed_path}/instructions.md" -template: "{installed_path}/sprint-status-template.yaml" -validation: "{installed_path}/checklist.md" - -# Variables and inputs -project_context: "**/project-context.md" -project_name: "{config_source}:project_name" - -# Tracking system configuration -tracking_system: "file-system" # Options: file-system, Future will support other options from config of mcp such as jira, linear, trello -project_key: "NOKEY" # Placeholder for tracker integrations; file-system uses a no-op key -story_location: "{implementation_artifacts}" # Relative path for file-system, Future will support URL for Jira/Linear/Trello -story_location_absolute: "{implementation_artifacts}" # Absolute path for file operations - -# Source files (file-system only) -epics_location: "{planning_artifacts}" # Directory containing epic*.md files -epics_pattern: "epic*.md" # Pattern to find epic files - -# Output configuration -status_file: "{implementation_artifacts}/sprint-status.yaml" - -# Smart input file references - handles both whole docs and sharded docs -# Priority: Whole document first, then sharded version -# Strategy: FULL LOAD - sprint planning needs ALL epics to build complete status -input_file_patterns: - epics: - description: "All epics with user stories" - whole: "{planning_artifacts}/*epic*.md" - sharded: "{planning_artifacts}/*epic*/*.md" - load_strategy: "FULL_LOAD" - -# Output configuration -default_output_file: "{status_file}" diff --git a/src/bmm/workflows/4-implementation/sprint-status/instructions.md b/src/bmm/workflows/4-implementation/sprint-status/instructions.md index 4182e1f25..9f93fec6b 100644 --- a/src/bmm/workflows/4-implementation/sprint-status/instructions.md +++ b/src/bmm/workflows/4-implementation/sprint-status/instructions.md @@ -1,7 +1,7 @@ # Sprint Status - Multi-Mode Service -The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml -You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/sprint-status/workflow.yaml +The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.md +You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/sprint-status/workflow.md Modes: interactive (default), validate, data ⚠️ ABSOLUTELY NO TIME ESTIMATES. Do NOT mention hours, days, weeks, or timelines. diff --git a/src/bmm/workflows/4-implementation/sprint-status/workflow.md b/src/bmm/workflows/4-implementation/sprint-status/workflow.md new file mode 100644 index 000000000..5baa8d646 --- /dev/null +++ b/src/bmm/workflows/4-implementation/sprint-status/workflow.md @@ -0,0 +1,26 @@ +--- +name: sprint-status +description: "Summarize sprint-status.yaml, surface risks, and route to the right implementation workflow" +main_config: '{project-root}/_bmad/bmm/config.yaml' +web_bundle: false +--- + +## Initialization +- Load config from `{project-root}/_bmad/bmm/config.yaml`. +- Resolve variables: + - `user_name` + - `communication_language` + - `document_output_language` + - `implementation_artifacts` + - `planning_artifacts` + - `date` (system-generated) + - `sprint_status_file` = `{implementation_artifacts}/sprint-status.yaml` + - `installed_path` = `{project-root}/_bmad/bmm/workflows/4-implementation/sprint-status` + + + Communicate all responses in {communication_language} and generate all documents in {document_output_language} + + + Read and follow instructions at: {installed_path}/instructions.md + + diff --git a/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml b/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml deleted file mode 100644 index f27d57024..000000000 --- a/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Sprint Status - Implementation Tracker -name: sprint-status -description: "Summarize sprint-status.yaml, surface risks, and route to the right implementation workflow." -author: "BMad" - -# Critical variables from config -config_source: "{project-root}/_bmad/bmm/config.yaml" -user_name: "{config_source}:user_name" -communication_language: "{config_source}:communication_language" -document_output_language: "{config_source}:document_output_language" -implementation_artifacts: "{config_source}:implementation_artifacts" - -# Workflow components -installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/sprint-status" -instructions: "{installed_path}/instructions.md" - -# Inputs -sprint_status_file: "{implementation_artifacts}/sprint-status.yaml" - -# Smart input file references -input_file_patterns: - sprint_status: - description: "Sprint status file generated by sprint-planning" - whole: "{implementation_artifacts}/sprint-status.yaml" - load_strategy: "FULL_LOAD" diff --git a/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md b/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md index 8c6a1902b..f8b21489d 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md @@ -41,7 +41,7 @@ Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: - `quick_spec_workflow` = `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md` - `party_mode_exec` = `{project-root}/_bmad/core/workflows/party-mode/workflow.md` -- `advanced_elicitation` = `{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml` +- `advanced_elicitation` = `{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md` --- diff --git a/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md b/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md index cc4fdf221..e58041af1 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md @@ -4,7 +4,7 @@ description: Conversational spec engineering - ask questions, investigate code, main_config: '{project-root}/_bmad/bmm/config.yaml' # Checkpoint handler paths -advanced_elicitation: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advanced_elicitation: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' party_mode_exec: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' quick_dev_workflow: '{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md' --- diff --git a/src/bmm/workflows/document-project/instructions.md b/src/bmm/workflows/document-project/instructions.md index 059134259..76d53778c 100644 --- a/src/bmm/workflows/document-project/instructions.md +++ b/src/bmm/workflows/document-project/instructions.md @@ -1,7 +1,7 @@ # Document Project Workflow Router -The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml -You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/document-project/workflow.yaml +The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.md +You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/document-project/workflow.md Communicate all responses in {communication_language} @@ -10,13 +10,45 @@ - - mode: data - data_request: project_config - +Initialize status defaults: + - Set status_exists = false + - Set status_file_found = false + - Set standalone_mode = true + - Set warning = "" + - Set status_load_error_reason = "" + - Set suggestion = "" + - Set next_workflow = "" + - Set next_agent = "" + - Set status_file_path = "" + - Set field_type = "" + - Set workflow_mode = "" + - Set scan_level = "" + - Set subworkflow_success = false + - Set status_update_success = false + - Set cached_project_types = "" + + +Attempt to load workflow status directly from `{output_folder}/bmm-workflow-status.yaml`: + - If file exists, is readable, and parses correctly: + - Set status_exists = true + - Set status_file_found = true + - Set standalone_mode = false + - Set status_file_path = `{output_folder}/bmm-workflow-status.yaml` + - Extract field_type, warning, suggestion, next_workflow, next_agent if present + - If file is missing, unreadable, or malformed: + - Keep defaults and continue in standalone mode + - Set status_load_error_reason from the caught file/parse error (e.g., missing file, permission denied, YAML parse error) + - Set warning = "Unable to load workflow status from {output_folder}/bmm-workflow-status.yaml: {{status_load_error_reason}}" + - Output warning and continue in standalone mode + - {{suggestion}} + + {{suggestion}} + + + {{warning}} + Note: Documentation workflow can run standalone. Continuing without progress tracking. Set standalone_mode = true Set status_file_found = false @@ -35,18 +67,20 @@ - - - mode: validate - calling_workflow: document-project - + + Validate sequencing locally from loaded status fields: + - If warning is empty, continue + - If warning contains guidance, require explicit user confirmation before continuing + {{warning}} Note: This may be auto-invoked by prd for brownfield documentation. Continue with documentation? (y/n) - {{suggestion}} + + {{suggestion}} + Exit workflow @@ -58,11 +92,44 @@ SMART LOADING STRATEGY: Check state file FIRST before loading any CSV files Check for existing state file at: {project_knowledge}/project-scan-report.json +Set resume_mode = false Read state file and extract: timestamps, mode, scan_level, current_step, completed_steps, project_classification + Validate last_updated from state file: + - If last_updated is missing or invalid, set state_age_hours = 999 and mark state as stale + - Otherwise parse last_updated into validated_last_updated + Extract cached project_type_id(s) from state file if present - Calculate age of state file (current time - last_updated) + Calculate state_age_hours: + - If validated_last_updated exists, compute current time - validated_last_updated + - Otherwise keep state_age_hours = 999 + + + + Display: "Found old state file (>24 hours). Starting fresh scan." + Attempt to create archive directory: {project_knowledge}/.archive/ + + Failed to create archive directory at {project_knowledge}/.archive/. Keeping existing state and exiting to avoid data loss. + Set resume_mode = true + Exit workflow + + Attempt to archive old state file to: {project_knowledge}/.archive/project-scan-report-{{timestamp}}.json + + Failed to archive old state file. Keeping existing state and exiting to avoid data loss. + Set resume_mode = true + Exit workflow + + Set resume_mode = false + Set workflow_mode = "" + Set scan_level = "" + Set cached_project_types = "" + Set current_step = "" + Set subworkflow_success = false + Continue to Step 3 + + + I found an in-progress workflow state from {{last_updated}}. @@ -85,32 +152,72 @@ Your choice [1/2/3]: Set resume_mode = true - Set workflow_mode = {{mode}} + Validate persisted mode before assigning workflow_mode: + - If mode is one of [deep_dive, initial_scan, full_rescan], set workflow_mode = {{mode}} + - Otherwise set workflow_mode = "full_rescan", set resume_mode = false, and continue as fresh scan + + Set subworkflow_success = false Load findings summaries from state file Load cached project_type_id(s) from state file CONDITIONAL CSV LOADING FOR RESUME: + + No cached project types found. Falling back to full CSV load. + Load project-types.csv and architecture_registry.csv + Load documentation_requirements_csv for active project classification + + For each cached project_type_id, load ONLY the corresponding row from: {documentation_requirements_csv} Skip loading project-types.csv and architecture_registry.csv (not needed on resume) Store loaded doc requirements for use in remaining steps + Display: "Resuming {{workflow_mode}} from {{current_step}} with cached project type(s): {{cached_project_types}}" Read fully and follow: {installed_path}/workflows/deep-dive-instructions.md with resume context + Set subworkflow_success = true only if delegated workflow completed without HALT/error + + Sub-workflow failed or was aborted during resume deep-dive mode. Exiting without marking completion. + Exit workflow + + After sub-workflow completes, continue to Step 4 Read fully and follow: {installed_path}/workflows/full-scan-instructions.md with resume context + Set subworkflow_success = true only if delegated workflow completed without HALT/error + + Sub-workflow failed or was aborted during resume full-scan mode. Exiting without marking completion. + Exit workflow + + After sub-workflow completes, continue to Step 4 + + + + Invalid resume workflow mode '{{workflow_mode}}'. Exiting without marking completion. + Exit workflow - Create archive directory: {project_knowledge}/.archive/ - Move old state file to: {project_knowledge}/.archive/project-scan-report-{{timestamp}}.json + Attempt to create archive directory: {project_knowledge}/.archive/ + + Failed to create archive directory. Keeping existing state and exiting to avoid data loss. + Set resume_mode = true + Exit workflow + + Attempt to move old state file to: {project_knowledge}/.archive/project-scan-report-{{timestamp}}.json + + Failed to archive old state file. Keeping existing state and exiting to avoid data loss. + Set resume_mode = true + Exit workflow + Set resume_mode = false - Continue to Step 0.5 + Reset workflow_mode, scan_level, cached_project_types, current_step to defaults + Set subworkflow_success = false + Continue to Step 3 @@ -118,13 +225,19 @@ Your choice [1/2/3]: Exit workflow - - Display: "Found old state file (>24 hours). Starting fresh scan." - Archive old state file to: {project_knowledge}/.archive/project-scan-report-{{timestamp}}.json - Set resume_mode = false - Continue to Step 0.5 + + Invalid selection. Expected 1, 2, or 3. Exiting workflow without changes. + Exit workflow + + + + + Set resume_mode = false + Continue to Step 3 + + @@ -147,8 +260,14 @@ Your choice [1/2/3]: Set workflow_mode = "full_rescan" + Set scan_level = "standard" Display: "Starting full project rescan..." Read fully and follow: {installed_path}/workflows/full-scan-instructions.md + Set subworkflow_success = true only if delegated workflow completed without HALT/error + + Sub-workflow failed or was aborted during full rescan. Exiting without marking completion. + Exit workflow + After sub-workflow completes, continue to Step 4 @@ -157,6 +276,11 @@ Your choice [1/2/3]: Set scan_level = "exhaustive" Display: "Starting deep-dive documentation mode..." Read fully and follow: {installed_path}/workflows/deep-dive-instructions.md + Set subworkflow_success = true only if delegated workflow completed without HALT/error + + Sub-workflow failed or was aborted during deep-dive mode. Exiting without marking completion. + Exit workflow + After sub-workflow completes, continue to Step 4 @@ -164,12 +288,23 @@ Your choice [1/2/3]: Display message: "Keeping existing documentation. Exiting workflow." Exit workflow + + + Invalid selection. Expected 1, 2, or 3. Exiting workflow without changes. + Exit workflow + Set workflow_mode = "initial_scan" + Set scan_level = "initial" Display: "No existing documentation found. Starting initial project scan..." Read fully and follow: {installed_path}/workflows/full-scan-instructions.md + Set subworkflow_success = true only if delegated workflow completed without HALT/error + + Sub-workflow failed or was aborted during initial scan. Exiting without marking completion. + Exit workflow + After sub-workflow completes, continue to Step 4 @@ -177,16 +312,25 @@ Your choice [1/2/3]: - - - mode: update - action: complete_workflow - workflow_name: document-project - + + Resume flow did not complete a delegated sub-workflow successfully. Exiting without completion update. + Exit workflow + - + + Attempt status update in {{status_file_path}}: + - Mark workflow `document-project` as completed + - Persist updated timestamp and completion metadata + - Set status_update_success = true on success + - If write fails, set status_update_success = false and capture status_update_error + + + Status updated! + + ⚠️ Status update skipped: {{status_update_error}} + **✅ Document Project Workflow Complete, {user_name}!** @@ -196,25 +340,26 @@ Your choice [1/2/3]: - Mode: {{workflow_mode}} - Scan Level: {{scan_level}} - Output: {project_knowledge}/index.md and related files + -{{#if status_file_found}} -**Status Updated:** - -- Progress tracking updated + + **Status Updated:** Progress tracking updated. **Next Steps:** +- Run `bmad-help` if you need recommended next workflows. + + - **Next required:** {{next_workflow}} ({{next_agent}} agent) + + + - **Next required:** not specified + + -- **Next required:** {{next_workflow}} ({{next_agent}} agent) - -Check status anytime with: `workflow-status` -{{else}} -**Next Steps:** -Since no workflow is in progress: - + + **Next Steps:** - Refer to the BMM workflow guide if unsure what to do next -- Or run `workflow-init` to create a workflow path and get guided next steps - {{/if}} - +- Run `bmad-help` to get guided workflow recommendations + diff --git a/src/bmm/workflows/document-project/workflow.md b/src/bmm/workflows/document-project/workflow.md new file mode 100644 index 000000000..b64275023 --- /dev/null +++ b/src/bmm/workflows/document-project/workflow.md @@ -0,0 +1,30 @@ +--- +name: document-project +description: "Analyzes and documents brownfield projects by scanning codebase, architecture, and patterns to create comprehensive reference documentation for AI-assisted development" +main_config: '{project-root}/_bmad/bmm/config.yaml' +web_bundle: false +--- + +## Initialization +- Load config from `{project-root}/_bmad/bmm/config.yaml`. +- Resolve variables: + - `user_name` + - `communication_language` + - `document_output_language` + - `user_skill_level` + - `project_knowledge` + - `date` (system-generated) + - `installed_path` = `{project-root}/_bmad/bmm/workflows/document-project` + - `documentation_requirements_csv` = `{installed_path}/documentation-requirements.csv` + + + Communicate all responses in {communication_language} and generate all documents in {document_output_language} + + + Read and follow instructions at: {installed_path}/instructions.md + + + + Validate against checklist at {installed_path}/checklist.md using _bmad/core/tasks/validate-workflow.md + + diff --git a/src/bmm/workflows/document-project/workflow.yaml b/src/bmm/workflows/document-project/workflow.yaml deleted file mode 100644 index be9600c24..000000000 --- a/src/bmm/workflows/document-project/workflow.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# 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/bmm/config.yaml" -project_knowledge: "{config_source}:project_knowledge" -user_name: "{config_source}:user_name" -communication_language: "{config_source}:communication_language" -document_output_language: "{config_source}:document_output_language" -user_skill_level: "{config_source}:user_skill_level" -date: system-generated - -# Module path and component files -installed_path: "{project-root}/_bmad/bmm/workflows/document-project" -instructions: "{installed_path}/instructions.md" -validation: "{installed_path}/checklist.md" - -# Required data files - CRITICAL for project type detection and documentation requirements -documentation_requirements_csv: "{installed_path}/documentation-requirements.csv" diff --git a/src/bmm/workflows/document-project/workflows/deep-dive.yaml b/src/bmm/workflows/document-project/workflows/deep-dive.yaml index c7b85c031..0b95db811 100644 --- a/src/bmm/workflows/document-project/workflows/deep-dive.yaml +++ b/src/bmm/workflows/document-project/workflows/deep-dive.yaml @@ -3,11 +3,11 @@ name: "document-project-deep-dive" description: "Exhaustive deep-dive documentation of specific project areas" author: "BMad" -# This is a sub-workflow called by document-project/workflow.yaml -parent_workflow: "{project-root}/_bmad/bmm/workflows/document-project/workflow.yaml" +# This is a sub-workflow called by document-project/workflow.md +parent_workflow: "{project-root}/_bmad/bmm/workflows/document-project/workflow.md" # Critical variables inherited from parent -config_source: "{project-root}/_bmad/bmb/config.yaml" +config_source: "{project-root}/_bmad/bmm/config.yaml" project_knowledge: "{config_source}:project_knowledge" user_name: "{config_source}:user_name" date: system-generated diff --git a/src/bmm/workflows/document-project/workflows/full-scan.yaml b/src/bmm/workflows/document-project/workflows/full-scan.yaml index 272baedda..ba5f3648f 100644 --- a/src/bmm/workflows/document-project/workflows/full-scan.yaml +++ b/src/bmm/workflows/document-project/workflows/full-scan.yaml @@ -3,11 +3,11 @@ name: "document-project-full-scan" description: "Complete project documentation workflow (initial scan or full rescan)" author: "BMad" -# This is a sub-workflow called by document-project/workflow.yaml -parent_workflow: "{project-root}/_bmad/bmm/workflows/document-project/workflow.yaml" +# This is a sub-workflow called by document-project/workflow.md +parent_workflow: "{project-root}/_bmad/bmm/workflows/document-project/workflow.md" # Critical variables inherited from parent -config_source: "{project-root}/_bmad/bmb/config.yaml" +config_source: "{project-root}/_bmad/bmm/config.yaml" project_knowledge: "{config_source}:project_knowledge" user_name: "{config_source}:user_name" date: system-generated diff --git a/src/bmm/workflows/generate-project-context/steps/step-02-generate.md b/src/bmm/workflows/generate-project-context/steps/step-02-generate.md index c2b428c57..b8deb658f 100644 --- a/src/bmm/workflows/generate-project-context/steps/step-02-generate.md +++ b/src/bmm/workflows/generate-project-context/steps/step-02-generate.md @@ -29,7 +29,7 @@ This step will generate content and present choices for each rule category: ## PROTOCOL INTEGRATION: -- When 'A' selected: Execute {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml +- When 'A' selected: Execute {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md - When 'P' selected: Execute {project-root}/_bmad/core/workflows/party-mode - PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed - User accepts/rejects protocol changes before proceeding @@ -267,7 +267,7 @@ After each category, show the generated rules and present choices: #### If 'A' (Advanced Elicitation): -- Execute advanced-elicitation.xml with current category rules +- Execute advanced-elicitation workflow (`{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md`) with current category rules - Process enhanced rules that come back - Ask user: "Accept these enhanced rules for {{category}}? (y/n)" - If yes: Update content, then return to A/P/C menu diff --git a/src/bmm/workflows/qa/automate/workflow.md b/src/bmm/workflows/qa/automate/workflow.md new file mode 100644 index 000000000..314a0ec3c --- /dev/null +++ b/src/bmm/workflows/qa/automate/workflow.md @@ -0,0 +1,35 @@ +--- +name: qa-automate +description: "Generate tests quickly for existing features using standard test patterns" +main_config: '{project-root}/_bmad/bmm/config.yaml' +web_bundle: false +--- + +## Initialization +- Load config from `{project-root}/_bmad/bmm/config.yaml`. +- Resolve variables: + - `user_name` + - `communication_language` + - `document_output_language` + - `output_folder` + - `implementation_artifacts` + - `installed_path` = `{project-root}/_bmad/bmm/workflows/qa/automate` + - `config_source` + - `test_dir` + - `source_dir` + +# QA Automate Workflow + +Communicate all responses in {communication_language} + + + + + Read and follow instructions at: {installed_path}/instructions.md + + + + Validate against checklist at {installed_path}/checklist.md using {project-root}/_bmad/core/tasks/validate-workflow.md + + + diff --git a/src/bmm/workflows/qa/automate/workflow.yaml b/src/bmm/workflows/qa/automate/workflow.yaml deleted file mode 100644 index f1119e980..000000000 --- a/src/bmm/workflows/qa/automate/workflow.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# Quinn QA workflow: Automate -name: qa-automate -description: "Generate tests quickly for existing features using standard test patterns" -author: "BMad" - -# Critical variables from config -config_source: "{project-root}/_bmad/bmm/config.yaml" -implementation_artifacts: "{config_source}:implementation_artifacts" -user_name: "{config_source}:user_name" -communication_language: "{config_source}:communication_language" -document_output_language: "{config_source}:document_output_language" -date: system-generated - -# Workflow components -installed_path: "{project-root}/_bmad/bmm/workflows/qa/automate" -instructions: "{installed_path}/instructions.md" -validation: "{installed_path}/checklist.md" -template: false - -# Variables and inputs -test_dir: "{project-root}/tests" # Root test directory -source_dir: "{project-root}" # Source code directory - -# Output configuration -default_output_file: "{implementation_artifacts}/tests/test-summary.md" - -# Required tools -required_tools: - - read_file # Read source code and existing tests - - write_file # Create test files - - create_directory # Create test directories - - list_files # Discover features - - search_repo # Find patterns - - glob # Find files - -tags: - - qa - - automation - - testing - -execution_hints: - interactive: false - autonomous: true - iterative: false diff --git a/src/core/tasks/help.md b/src/core/tasks/help.md index c3c3fab11..d0612c13c 100644 --- a/src/core/tasks/help.md +++ b/src/core/tasks/help.md @@ -1,11 +1,12 @@ --- name: help description: Get unstuck by showing what workflow steps come next or answering questions about what to do +standalone: true --- # Task: BMAD Help -## ROUTING RULES +## KEY RULES - **Empty `phase` = anytime** — Universal tools work regardless of workflow state - **Numbered phases indicate sequence** — Phases like `1-discover` → `2-define` → `3-build` → `4-ship` flow in order (naming varies by module) @@ -14,26 +15,6 @@ description: Get unstuck by showing what workflow steps come next or answering q - **`required=true` blocks progress** — Required workflows must complete before proceeding to later phases - **Artifacts reveal completion** — Search resolved output paths for `outputs` patterns, fuzzy-match found files to workflow rows -## DISPLAY RULES - -### Command-Based Workflows -When `command` field has a value: -- Show the command prefixed with `/` (e.g., `/bmad-bmm-create-prd`) - -### Agent-Based Workflows -When `command` field is empty: -- User loads agent first via `/agent-command` -- Then invokes by referencing the `code` field or describing the `name` field -- Do NOT show a slash command — show the code value and agent load instruction instead - -Example presentation for empty command: -``` -Explain Concept (EC) -Load: /tech-writer, then ask to "EC about [topic]" -Agent: Tech Writer -Description: Create clear technical explanations with examples... -``` - ## MODULE DETECTION - **Empty `module` column** → universal tools (work across all modules) @@ -44,10 +25,10 @@ Detect the active module from conversation context, recent workflows, or user qu ## INPUT ANALYSIS Determine what was just completed: -- Explicit completion stated by user -- Workflow completed in current conversation -- Artifacts found matching `outputs` patterns -- If `index.md` exists, read it for additional context +- Did someone state they completed something? Proceed as if that was the input. +- Was a workflow just completed in this conversation? Proceed as if that was the input. +- Search resolved artifact locations for files; fuzzy-match to workflow `outputs` patterns. +- If an `index.md` exists, read it for additional context. - If still unclear, ask: "What workflow did you most recently complete?" ## EXECUTION @@ -56,30 +37,42 @@ Determine what was just completed: 2. **Resolve output locations and config** — Scan each folder under `_bmad/` (except `_config`) for `config.yaml`. For each workflow row, resolve its `output-location` variables against that module's config so artifact paths can be searched. Also extract `communication_language` and `project_knowledge` from each scanned module's config. -3. **Ground in project knowledge** — If `project_knowledge` resolves to an existing path, read available documentation files (architecture docs, project overview, tech stack references) for grounding context. Use discovered project facts when composing any project-specific output. Never fabricate project-specific details — if documentation is unavailable, state so. +3. **Ground in project knowledge** — If `project_knowledge` resolves to an existing path, read available documentation files (architecture docs, project overview, tech stack references) for grounding context. Use discovered project facts when composing any project-specific output. Never fabricate project-specific details. If documentation is unavailable, state that clearly. -4. **Detect active module** — Use MODULE DETECTION above +4. **Analyze input** — Task may provide a workflow name/code, conversational phrase, or nothing. Infer what was just completed using INPUT ANALYSIS above. -5. **Analyze input** — Task may provide a workflow name/code, conversational phrase, or nothing. Infer what was just completed using INPUT ANALYSIS above. +5. **Detect active module** — Use MODULE DETECTION above to determine which module the user is working in. -6. **Present recommendations** — Show next steps based on: - - Completed workflows detected - - Phase/sequence ordering (ROUTING RULES) - - Artifact presence +6. **Present recommendations** — Show next steps based on completed workflows, phase/sequence ordering (KEY RULES), and artifact detection. Format per the following + +## RECOMMENDED OUTPUT FORMAT **Optional items first** — List optional workflows until a required step is reached **Required items next** — List the next required workflow - - For each item, apply DISPLAY RULES above and include: + For each item show: - Workflow **name** - - **Command** OR **Code + Agent load instruction** (per DISPLAY RULES) + - **Command** when `command` is present + - **Agent load instruction + code** when `command` is empty - **Agent** title and display name from the CSV (e.g., "🎨 Alex (Designer)") - Brief **description** -7. **Additional guidance to convey**: - - Present all output in `{communication_language}` + ### Display branching rules + - When `command` has a value: + - Present the command in your platform's command format (for example: `bmad-example-build-prototype`) + - When `command` is empty: + - Do not invent a slash command + - Show how to load the agent from `agent` and then invoke using the workflow/code description + - Example: + - `Explain Concept (EC)` + - `Load: /tech-writer, then ask to "EC about [topic]"` + - `Agent: Tech Writer` + - `Description: Create clear technical explanations with examples` + + ### Additional response output guidance to convey: + - Present all output in `{communication_language}` when available in module config - Run each workflow in a **fresh context window** + - Load the agent using the platform's command format for `agent-command`, or run the workflow command directly - For **validation workflows**: recommend using a different high-quality LLM if available - For conversational requests: match the user's tone while presenting clearly -8. Return to the calling process after presenting recommendations. +7. Return to the calling process after presenting recommendations. diff --git a/src/core/tasks/validate-workflow.md b/src/core/tasks/validate-workflow.md new file mode 100644 index 000000000..65846e0f4 --- /dev/null +++ b/src/core/tasks/validate-workflow.md @@ -0,0 +1,66 @@ +--- +name: validate-workflow +description: Validate a target file against a checklist +standalone: true +--- + +# Task: Validate Workflow + +## Initialization +- Load config from `{project-root}/_bmad/core/config.yaml`. +- Validate config load before continuing: + - Verify file exists and is readable. + - Parse YAML and fail fast with explicit error if parsing fails. + - Require `user_name`; if missing, abort initialization with descriptive error. + - Apply explicit defaults when optional keys are absent: + - `communication_language = "English"` + - `document_output_language = "English"` + - Log resolved values and config source path. + +## Purpose +Execute a validation checklist against a target file and report findings clearly and consistently. + +## Steps +1. **Load checklist** + - Use the checklist path provided by the calling workflow (e.g., its `validation` property). + - If not provided, ask the user for the checklist path. + +2. **Load target file** + - Infer candidate target path in this order: + - Explicit keys in workflow/checklist inputs: `file`, `path`, `target`, `filePath` + - Path-like tokens in checklist items + - First matching path from glob patterns supplied by checklist/input + - Normalize all candidate paths relative to repo root and resolve `.`/`..`. + - Validate candidate existence and expected file type (`.md`, `.yaml`, `.yml`, `.json`, or checklist-defined extension). + - If multiple valid candidates remain, prefer explicit key fields over inferred tokens. + - If no valid candidate is found, prompt user with schema example: + - `Please provide the exact file path (relative to repo root), e.g. ./workflows/ci.yml` + - Validate user-supplied path before proceeding. + +3. **Run the checklist** + - Read the checklist fully. + - Apply each item systematically to the target file. + - Record pass/fail and capture specific evidence for any issues. + +4. **Report findings** + - Summarize issues with clear labels (e.g., CRITICAL/HIGH/MEDIUM/LOW when applicable). + - Provide actionable fixes for each issue. + +5. **Edits (if applicable)** + - If checklist requires edits/auto-fixes, follow safe-edit protocol: + - Ask for confirmation before editing. + - Create backup snapshot of target file before changes. + - Use deterministic backup location: `{project-root}/.bmad-tmp/validate-workflow/`. + - Name backup as `{target-file-name}.{timestamp}.bak` and diff as `{target-file-name}.{timestamp}.diff`. + - If temp backup directory cannot be created, fall back to adjacent backup file `{target-file}.bak`. + - Generate reversible diff preview and show it to user. + - Apply edits only after user approval. + - Run syntax/validation checks against edited file. + - If validation fails or user cancels, rollback from backup and report rollback status. + - Record full backup and diff paths in task output. + - Support `retain_artifacts` flag (default `false`) to keep backup/diff artifacts when requested. + +6. **Finalize** + - Confirm completion and provide the final validation summary. + - If edits succeeded and `retain_artifacts` is `false`, delete backup/diff artifacts and report cleanup status. + - If edits failed or rollback occurred, preserve backup/diff artifacts and report rollback path explicitly. diff --git a/src/core/tasks/workflow.md b/src/core/tasks/workflow.md new file mode 100644 index 000000000..3c66a5c67 --- /dev/null +++ b/src/core/tasks/workflow.md @@ -0,0 +1,116 @@ +--- +name: workflow +description: Execute a workflow definition by loading configuration, following instructions, and producing outputs +standalone: false +--- + +# Task: Execute Workflow + +## Non-Negotiable Mandates +- Always read complete files. Do not use partial reads for workflow/task files. +- Instructions are mandatory whether embedded or referenced. +- Execute steps in order. Do not skip steps. +- Resolve variables before executing dependent actions. +- Save output checkpoints immediately when a `` tag is reached. + +## Input Contract +- Required input: `workflow-config` path (usually `workflow.md` or `workflow-*.md`). +- This runner supports markdown workflow definitions with frontmatter and XML-style instruction tags. + +## Execution Rules +1. Process steps in numeric order unless a `goto`/conditional explicitly redirects flow. +2. Optional steps require user confirmation unless `#yolo` mode is active. +3. On ``, write output, show the section, and wait for user confirmation unless `#yolo` mode is active. +4. If a required value is unknown, ask the user before continuing. + +## Execution Flow + +### 1. Load and initialize workflow + +#### 1a. Load config and resolve variables +- Load workflow definition from `workflow-config`. +- If frontmatter contains `main_config` or `config_source`, load that file. +- Resolve config references and placeholders. +- Resolve system variables: + - `date` (system-generated) + - `{project-root}` + - `{installed_path}` +- Ask the user for unresolved variables. + +#### 1b. Load required components +- Load instruction content if referenced by path. +- If a template path exists, load the full template. +- If a validation/checklist path exists, store it for validation steps. +- Data files (`csv`, `json`, etc.) may be loaded lazily when first referenced. + +#### 1c. Initialize output (template workflows) +- Resolve `default_output_file`. +- Create output directory if needed. +- Write template skeleton on first write. + +### 2. Execute instruction steps + +#### 2a. Handle step attributes +- `optional="true"`: include only with user consent unless `#yolo`. +- `if="condition"`: execute only when condition is true. +- `for-each="collection"`: repeat for each item. +- `repeat="n"`: repeat exactly `n` times. + +#### 2b. Execute step content +- Execute markdown instructions and XML-style tags. +- Replace `{{variables}}`; ask user when unresolved. + +Supported execution tags: +- ``: perform action. +- ``: conditional single action. +- `...`: conditional block. +- ``: prompt and wait. +- ``: jump to step. +- ``: run another workflow. +- ``: run another task. +- ``: run reusable protocol. + +#### 2c. Handle `` +- Generate content for that section. +- Write/update output file. +- Display section content. +- Offer next action: + - `[a]` Advanced Elicitation: `{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md` + - `[p]` Party Mode: `{project-root}/_bmad/core/workflows/party-mode/workflow.md` + - `[c]` Continue + - `[y]` Enable `#yolo` for remaining sections in this run + +#### 2d. Step completion prompt +- If no special tag and not `#yolo`, ask whether to continue. + +### 3. Completion +- Confirm output is saved (for template workflows). +- Confirm required actions completed (for action workflows). +- Report workflow completion. + +## Execution Modes +- `normal`: full confirmations and interaction. +- `#yolo`: skip optional confirmations and proceed with minimal prompts. + +## Protocols + +### `discover_inputs` +Objective: load relevant project inputs from `input_file_patterns`. + +1. Parse `input_file_patterns` from the active workflow frontmatter. +2. For each pattern group, try sources in this order: +- Sharded pattern (if provided) +- Whole-document pattern fallback +3. Apply configured load strategy: +- `FULL_LOAD`: load every matching shard and combine (index first, then alphabetical). +- `SELECTIVE_LOAD`: resolve template variables and load targeted shard(s). +- `INDEX_GUIDED`: load index, infer relevant files from workflow objective, then load likely relevant files. +4. If nothing matches: +- Set corresponding content variable to empty string. +- Note absence as non-fatal. +5. Report loaded variables and source files. + +## Final Directives +- Follow this runner first, then the target workflow instructions. +- If behavior is ambiguous, re-read this file and the target workflow definition. +- Keep execution deterministic, explicit, and auditable. diff --git a/src/core/tasks/workflow.xml b/src/core/tasks/workflow.xml deleted file mode 100644 index 536c9d8e7..000000000 --- a/src/core/tasks/workflow.xml +++ /dev/null @@ -1,235 +0,0 @@ - - Execute given workflow by loading its configuration, following instructions, and producing output - - - Always read COMPLETE files - NEVER use offset/limit when reading any workflow related files - Instructions are MANDATORY - either as file path, steps or embedded list in YAML, XML or markdown - Execute ALL steps in instructions IN EXACT ORDER - Save to template output file after EVERY "template-output" tag - NEVER skip a step - YOU are responsible for every steps execution without fail or excuse - - - - Steps execute in exact numerical order (1, 2, 3...) - Optional steps: Ask user unless #yolo mode active - Template-output tags: Save content, discuss with the user the section completed, and NEVER proceed until the users indicates - to proceed (unless YOLO mode has been activated) - - - - - - Read workflow.yaml from provided path - Load config_source (REQUIRED for all modules) - Load external config from config_source path - Resolve all {config_source}: references with values from config - Resolve system variables (date:system-generated) and paths ({project-root}, {installed_path}) - Ask user for input of any variables that are still unknown - - - - Instructions: Read COMPLETE file from path OR embedded list (REQUIRED) - If template path → Read COMPLETE template file - If validation path → Note path for later loading when needed - If template: false → Mark as action-workflow (else template-workflow) - Data files (csv, json) → Store paths only, load on-demand when instructions reference them - - - - Resolve default_output_file path with all variables and {{date}} - Create output directory if doesn't exist - If template-workflow → Write template to output file with placeholders - If action-workflow → Skip file creation - - - - - For each step in instructions: - - - If optional="true" and NOT #yolo → Ask user to include - If if="condition" → Evaluate condition - If for-each="item" → Repeat step for each item - If repeat="n" → Repeat step n times - - - - Process step instructions (markdown or XML tags) - Replace {{variables}} with values (ask user if unknown) - - action xml tag → Perform the action - check if="condition" xml tag → Conditional block wrapping actions (requires closing </check>) - ask xml tag → Prompt user and WAIT for response - invoke-workflow xml tag → Execute another workflow with given inputs and the workflow.xml runner - invoke-task xml tag → Execute specified task - invoke-protocol name="protocol_name" xml tag → Execute reusable protocol from protocols section - goto step="x" → Jump to specified step - - - - - - Generate content for this section - Save to file (Write first time, Edit subsequent) - Display generated content - [a] Advanced Elicitation, [c] Continue, [p] Party-Mode, [y] YOLO the rest of this document only. WAIT for response. - Start the advanced elicitation workflow {project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml - - - Continue to next step - - - Start the party-mode workflow {project-root}/_bmad/core/workflows/party-mode/workflow.md - - - Enter #yolo mode for the rest of the workflow - - - - - - - If no special tags and NOT #yolo: - Continue to next step? (y/n/edit) - - - - - Confirm document saved to output path - Report workflow completion - - - - - Full user interaction and confirmation of EVERY step at EVERY template output - NO EXCEPTIONS except yolo MODE - Skip all confirmations and elicitation, minimize prompts and try to produce all of the workflow automatically by - simulating the remaining discussions with an simulated expert user - - - - - step n="X" goal="..." - Define step with number and goal - optional="true" - Step can be skipped - if="condition" - Conditional execution - for-each="collection" - Iterate over items - repeat="n" - Repeat n times - - - action - Required action to perform - action if="condition" - Single conditional action (inline, no closing tag needed) - check if="condition">...</check> - Conditional block wrapping multiple items (closing tag required) - ask - Get user input (ALWAYS wait for response before continuing) - goto - Jump to another step - invoke-workflow - Call another workflow - invoke-task - Call a task - invoke-protocol - Execute a reusable protocol (e.g., discover_inputs) - - - template-output - Save content checkpoint - critical - Cannot be skipped - example - Show example output - - - - - - Intelligently load project files (whole or sharded) based on workflow's input_file_patterns configuration - - Only execute if workflow.yaml contains input_file_patterns section - - - - Read input_file_patterns from loaded workflow.yaml - For each pattern group (prd, architecture, epics, etc.), note the load_strategy if present - - - - For each pattern in input_file_patterns: - - - - Determine load_strategy from pattern config (defaults to FULL_LOAD if not specified) - - - Load ALL files in sharded directory - used for PRD, Architecture, UX, brownfield docs - Use glob pattern to find ALL .md files (e.g., "{output_folder}/*architecture*/*.md") - Load EVERY matching file completely - Concatenate content in logical order (index.md first if exists, then alphabetical) - Store in variable: {pattern_name_content} - - - - Load specific shard using template variable - example: used for epics with {{epic_num}} - Check for template variables in sharded_single pattern (e.g., {{epic_num}}) - If variable undefined, ask user for value OR infer from context - Resolve template to specific file path - Load that specific file - Store in variable: {pattern_name_content} - - - - Load index.md, analyze structure and description of each doc in the index, then intelligently load relevant docs - DO NOT BE LAZY - use best judgment to load documents that might have relevant information, even if only a 5% chance - Load index.md from sharded directory - Parse table of contents, links, section headers - Analyze workflow's purpose and objective - Identify which linked/referenced documents are likely relevant - If workflow is about authentication and index shows "Auth Overview", "Payment Setup", "Deployment" → Load auth - docs, consider deployment docs, skip payment - Load all identified relevant documents - Store combined content in variable: {pattern_name_content} - When in doubt, LOAD IT - context is valuable, being thorough is better than missing critical info - - Mark pattern as RESOLVED, skip to next pattern - - - - - - Attempt glob match on 'whole' pattern (e.g., "{output_folder}/*prd*.md") - - Load ALL matching files completely (no offset/limit) - Store content in variable: {pattern_name_content} (e.g., {prd_content}) - Mark pattern as RESOLVED, skip to next pattern - - - - - - - Set {pattern_name_content} to empty string - Note in session: "No {pattern_name} files found" (not an error, just unavailable, offer use change to provide) - - - - - - List all loaded content variables with file counts - - ✓ Loaded {prd_content} from 5 sharded files: prd/index.md, prd/requirements.md, ... - ✓ Loaded {architecture_content} from 1 file: Architecture.md - ✓ Loaded {epics_content} from selective load: epics/epic-3.md - ○ No ux_design files found - - This gives workflow transparency into what context is available - - - - - - - - - • This is the complete workflow execution engine - • You MUST Follow instructions exactly as written - • The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml - • You MUST have already loaded and processed: {installed_path}/workflow.yaml - • This workflow uses INTENT-DRIVEN PLANNING - adapt organically to product type and context - • YOU ARE FACILITATING A CONVERSATION With a user to produce a final document step by step. The whole process is meant to be - collaborative helping the user flesh out their ideas. Do not rush or optimize and skip any section. - - - \ No newline at end of file diff --git a/src/core/workflows/advanced-elicitation/workflow.md b/src/core/workflows/advanced-elicitation/workflow.md new file mode 100644 index 000000000..8ba3fca2e --- /dev/null +++ b/src/core/workflows/advanced-elicitation/workflow.md @@ -0,0 +1,124 @@ +--- +name: advanced-elicitation +description: "Interactive elicitation methods to refine content via selectable techniques" +web_bundle: false +--- + +## Initialization +- Load config from `{project-root}/_bmad/core/config.yaml`. +- Resolve variables: + - `communication_language` + - `methods` (`{project-root}/_bmad/core/workflows/advanced-elicitation/methods.csv`) + - `agent_manifest` (`{project-root}/_bmad/_config/agent-manifest.csv`) + - `date` (system-generated, if needed) + +MANDATORY: Execute ALL steps in the flow section IN EXACT ORDER +DO NOT skip steps or change the sequence +HALT immediately when halt-conditions are met +Each action xml tag within step xml tag is a REQUIRED action to complete that step +Sections outside flow (validation, output, critical-context) provide essential context - review and apply throughout execution +YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the `communication_language` + +## Integration +When called during template workflow processing: +- Receive or review the current section content that was just generated +- Apply elicitation methods iteratively to enhance that specific content +- Return the enhanced version when the user selects "x" to proceed +- The enhanced content replaces the original section content in the output document + + + + Load and read {{methods}} and {{agent_manifest}} + + + category: Method grouping (core, structural, risk, etc.) + method_name: Display name for the method + description: Rich explanation of what the method does, when to use it, and why it's valuable + output_pattern: Flexible flow guide using → arrows (e.g., "analysis → insights → action") + + + + Use conversation history + Analyze: content type, complexity, stakeholder needs, risk level, and creative potential + + + + 1. Analyze context: Content type, complexity, stakeholder needs, risk level, creative potential + 2. Parse descriptions: Understand each method's purpose from the rich descriptions in CSV + 3. Select 5 methods: Choose methods that best match the context based on their descriptions + 4. Balance approach: Include mix of foundational and specialized techniques as appropriate + + + + + + + **Advanced Elicitation Options (If you launched Party Mode, they will participate randomly)** + Choose a number (1-5), [r] to Reshuffle, [a] List All, or [x] to Proceed: + + 1. [Method Name] + 2. [Method Name] + 3. [Method Name] + 4. [Method Name] + 5. [Method Name] + r. Reshuffle the list with 5 new options + a. List all methods with descriptions + x. Proceed / No Further Actions + + + + + Execute the selected method using its description from the CSV + Adapt the method's complexity and output format based on the current context + Apply the method creatively to the current section content being enhanced + Display the enhanced version showing what the method revealed or improved + CRITICAL: Ask the user if they would like to apply the changes to the doc (y/n/other) and HALT to await response. + CRITICAL: ONLY if Yes, apply the changes. IF No, discard your memory of the proposed changes. If any other reply, try best to + follow the instructions given by the user. + CRITICAL: Re-present the same 1-5,r,x prompt to allow additional elicitations + + + Select 5 random methods from advanced-elicitation-methods.csv, present new list with same prompt format + When selecting, try to think and pick a diverse set of methods covering different categories and approaches, with 1 and 2 being + potentially the most useful for the document or section being discovered + + + Complete elicitation and proceed + Return the fully enhanced content back to create-doc.md + The enhanced content becomes the final version for that section + Signal completion back to create-doc.md to continue with next section + + + List all methods with their descriptions from the CSV in a compact table + Allow user to select any method by name or number from the full list + After selection, execute the method as described in the n="1-5" case above + + + Apply changes to current section content and re-present choices + + + Execute methods in sequence on the content, then re-offer choices + + + + + + Method execution: Use the description from CSV to understand and apply each method + Output pattern: Use the pattern as a flexible guide (e.g., "paths → evaluation → selection") + Dynamic adaptation: Adjust complexity based on content needs (simple to sophisticated) + Creative application: Interpret methods flexibly based on context while maintaining pattern consistency + Focus on actionable insights + Stay relevant: Tie elicitation to specific content being analyzed (the current section from the document being created unless user + indicates otherwise) + Identify personas: For single or multi-persona methods, clearly identify viewpoints, and use party members if available in memory + already + Critical loop behavior: Always re-offer the 1-5,r,a,x choices after each method execution + Continue until user selects 'x' to proceed with enhanced content, confirm or ask the user what should be accepted from the session + Each method application builds upon previous enhancements + Content preservation: Track all enhancements made during elicitation + Iterative enhancement: Each selected method (1-5) should: + 1. Apply to the current enhanced version of the content + 2. Show the improvements made + 3. Return to the prompt for additional elicitations or completion + + diff --git a/src/core/workflows/advanced-elicitation/workflow.xml b/src/core/workflows/advanced-elicitation/workflow.xml deleted file mode 100644 index ea7395e41..000000000 --- a/src/core/workflows/advanced-elicitation/workflow.xml +++ /dev/null @@ -1,117 +0,0 @@ - - - MANDATORY: Execute ALL steps in the flow section IN EXACT ORDER - DO NOT skip steps or change the sequence - HALT immediately when halt-conditions are met - Each action xml tag within step xml tag is a REQUIRED action to complete that step - Sections outside flow (validation, output, critical-context) provide essential context - review and apply throughout execution - YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the `communication_language` - - - - When called during template workflow processing: - 1. Receive or review the current section content that was just generated or - 2. Apply elicitation methods iteratively to enhance that specific content - 3. Return the enhanced version back when user selects 'x' to proceed and return back - 4. The enhanced content replaces the original section content in the output document - - - - - Load and read {{methods}} and {{agent-party}} - - - category: Method grouping (core, structural, risk, etc.) - method_name: Display name for the method - description: Rich explanation of what the method does, when to use it, and why it's valuable - output_pattern: Flexible flow guide using → arrows (e.g., "analysis → insights → action") - - - - Use conversation history - Analyze: content type, complexity, stakeholder needs, risk level, and creative potential - - - - 1. Analyze context: Content type, complexity, stakeholder needs, risk level, creative potential - 2. Parse descriptions: Understand each method's purpose from the rich descriptions in CSV - 3. Select 5 methods: Choose methods that best match the context based on their descriptions - 4. Balance approach: Include mix of foundational and specialized techniques as appropriate - - - - - - - **Advanced Elicitation Options (If you launched Party Mode, they will participate randomly)** - Choose a number (1-5), [r] to Reshuffle, [a] List All, or [x] to Proceed: - - 1. [Method Name] - 2. [Method Name] - 3. [Method Name] - 4. [Method Name] - 5. [Method Name] - r. Reshuffle the list with 5 new options - a. List all methods with descriptions - x. Proceed / No Further Actions - - - - - Execute the selected method using its description from the CSV - Adapt the method's complexity and output format based on the current context - Apply the method creatively to the current section content being enhanced - Display the enhanced version showing what the method revealed or improved - CRITICAL: Ask the user if they would like to apply the changes to the doc (y/n/other) and HALT to await response. - CRITICAL: ONLY if Yes, apply the changes. IF No, discard your memory of the proposed changes. If any other reply, try best to - follow the instructions given by the user. - CRITICAL: Re-present the same 1-5,r,x prompt to allow additional elicitations - - - Select 5 random methods from advanced-elicitation-methods.csv, present new list with same prompt format - When selecting, try to think and pick a diverse set of methods covering different categories and approaches, with 1 and 2 being - potentially the most useful for the document or section being discovered - - - Complete elicitation and proceed - Return the fully enhanced content back to create-doc.md - The enhanced content becomes the final version for that section - Signal completion back to create-doc.md to continue with next section - - - List all methods with their descriptions from the CSV in a compact table - Allow user to select any method by name or number from the full list - After selection, execute the method as described in the n="1-5" case above - - - Apply changes to current section content and re-present choices - - - Execute methods in sequence on the content, then re-offer choices - - - - - - Method execution: Use the description from CSV to understand and apply each method - Output pattern: Use the pattern as a flexible guide (e.g., "paths → evaluation → selection") - Dynamic adaptation: Adjust complexity based on content needs (simple to sophisticated) - Creative application: Interpret methods flexibly based on context while maintaining pattern consistency - Focus on actionable insights - Stay relevant: Tie elicitation to specific content being analyzed (the current section from the document being created unless user - indicates otherwise) - Identify personas: For single or multi-persona methods, clearly identify viewpoints, and use party members if available in memory - already - Critical loop behavior: Always re-offer the 1-5,r,a,x choices after each method execution - Continue until user selects 'x' to proceed with enhanced content, confirm or ask the user what should be accepted from the session - Each method application builds upon previous enhancements - Content preservation: Track all enhancements made during elicitation - Iterative enhancement: Each selected method (1-5) should: - 1. Apply to the current enhanced version of the content - 2. Show the improvements made - 3. Return to the prompt for additional elicitations or completion - - - \ No newline at end of file diff --git a/src/core/workflows/brainstorming/steps/step-03-technique-execution.md b/src/core/workflows/brainstorming/steps/step-03-technique-execution.md index 362bead3b..25b4cd929 100644 --- a/src/core/workflows/brainstorming/steps/step-03-technique-execution.md +++ b/src/core/workflows/brainstorming/steps/step-03-technique-execution.md @@ -1,7 +1,7 @@ # Step 3: Interactive Technique Execution and Facilitation --- -advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md' --- ## MANDATORY EXECUTION RULES (READ FIRST): diff --git a/src/core/workflows/brainstorming/workflow.md b/src/core/workflows/brainstorming/workflow.md index 3190c983c..ef3349d10 100644 --- a/src/core/workflows/brainstorming/workflow.md +++ b/src/core/workflows/brainstorming/workflow.md @@ -47,7 +47,7 @@ Load config from `{project-root}/_bmad/core/config.yaml` and resolve: - `brain_techniques_path` = `{installed_path}/brain-methods.csv` - `default_output_file` = `{output_folder}/brainstorming/brainstorming-session-{{date}}.md` - `context_file` = Optional context file path from workflow invocation for project-specific guidance -- `advancedElicitationTask` = `{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml` +- `advancedElicitationTask` = `{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.md` --- diff --git a/src/utility/agent-components/handler-multi.txt b/src/utility/agent-components/handler-multi.txt index f33a73fe5..20169315a 100644 --- a/src/utility/agent-components/handler-multi.txt +++ b/src/utility/agent-components/handler-multi.txt @@ -7,7 +7,7 @@ - Process based on handler attributes (exec, workflow, action) 4. When user input matches a handler's 'match' pattern: - For exec="path/to/file.md": follow the `handler type="exec"` instructions - - For workflow="path/to/workflow.yaml": follow the `handler type="workflow"` instructions + - For workflow="path/to/workflow.md": follow the `handler type="workflow"` instructions - For action="...": Perform the specified action directly 5. Support both exact matches and fuzzy matching based on the match attribute 6. If no handler matches, prompt user to choose from available options diff --git a/src/utility/agent-components/handler-validate-workflow.txt b/src/utility/agent-components/handler-validate-workflow.txt index aca040550..4284ef69a 100644 --- a/src/utility/agent-components/handler-validate-workflow.txt +++ b/src/utility/agent-components/handler-validate-workflow.txt @@ -1,7 +1,15 @@ - When command has: validate-workflow="path/to/workflow.yaml" - 1. You MUST LOAD the file at: {project-root}/_bmad/core/tasks/validate-workflow.xml - 2. READ its entire contents and EXECUTE all instructions in that file - 3. Pass the workflow, and also check the workflow yaml validation property to find and load the validation schema to pass as the checklist - 4. The workflow should try to identify the file to validate based on checklist context or else you will ask the user to specify - \ No newline at end of file + When command has: validate-workflow="path/to/workflow.md" + 1. Resolve loader paths safely: + - Primary: {project-root}/_bmad/core/tasks/validate-workflow.md + - Fallback: {project-root}/src/core/tasks/validate-workflow.md + 2. Verify primary path exists and is readable before loading + 3. Wrap read/parse in try/catch and log path + underlying error on failure + 4. If primary fails, attempt fallback and log warning that fallback mode is active + 5. If fallback also fails: + - Log clear error with both attempted paths and caught errors + - Fail fast with deterministic exception (do not continue with partial state) + 6. READ entire resolved task file and EXECUTE all instructions + 7. Pass the workflow and inspect workflow validation property to find/load checklist schema + 8. If target file cannot be inferred from checklist context, prompt user for exact path + diff --git a/src/utility/agent-components/handler-workflow.txt b/src/utility/agent-components/handler-workflow.txt index 1be1dcbe5..82ce16f94 100644 --- a/src/utility/agent-components/handler-workflow.txt +++ b/src/utility/agent-components/handler-workflow.txt @@ -1,10 +1,19 @@ - When menu item has: workflow="path/to/workflow.yaml": + When menu item has: workflow="path/to/workflow.md": - 1. CRITICAL: Always LOAD {project-root}/_bmad/core/tasks/workflow.xml - 2. Read the complete file - this is the CORE OS for processing BMAD workflows - 3. Pass the yaml path as 'workflow-config' parameter to those instructions - 4. Follow workflow.xml instructions precisely following all steps - 5. Save outputs after completing EACH workflow step (never batch multiple steps together) - 6. If workflow.yaml path is "todo", inform user the workflow hasn't been implemented yet - \ No newline at end of file + 1. Resolve loader paths safely: + - Primary: {project-root}/_bmad/core/tasks/workflow.md + - Fallback: {project-root}/src/core/tasks/workflow.md + 2. Verify the primary loader exists and is readable before loading it + 3. If primary is missing/unreadable: + - Log a warning with the primary path and underlying error + - Attempt the fallback loader path + 4. If fallback is also missing/unreadable: + - Log an error including both attempted paths and underlying errors + - Fail fast with a descriptive message and HALT + 5. LOAD the resolved workflow loader file and read it completely + 6. Pass the workflow definition path as 'workflow-config' parameter to those instructions + 7. Follow workflow.md instructions precisely following all steps + 8. Save outputs after completing EACH workflow step (never batch multiple steps together) + 9. If workflow.md path is "todo", inform user the workflow hasn't been implemented yet + diff --git a/test/test-file-refs-csv.js b/test/test-file-refs-csv.js index d068bd75d..2da8b1aad 100644 --- a/test/test-file-refs-csv.js +++ b/test/test-file-refs-csv.js @@ -58,6 +58,7 @@ test('bmm-style.csv: extracts workflow-file refs with trailing commas', () => { const { fullPath, content } = loadFixture('valid/bmm-style.csv'); const refs = extractCsvRefs(fullPath, content); assert(refs.length === 2, `Expected 2 refs, got ${refs.length}`); + // Keep this legacy .yaml reference to verify backward-compatible CSV parsing. assert(refs[0].raw === '_bmad/bmm/workflows/document-project/workflow.yaml', `Wrong raw[0]: ${refs[0].raw}`); assert(refs[1].raw === '_bmad/core/workflows/brainstorming/workflow.md', `Wrong raw[1]: ${refs[1].raw}`); assert(refs[0].type === 'project-root', `Wrong type: ${refs[0].type}`); diff --git a/test/test-installation-components.js b/test/test-installation-components.js index 0970861b9..ff03fadbf 100644 --- a/test/test-installation-components.js +++ b/test/test-installation-components.js @@ -12,9 +12,19 @@ */ const path = require('node:path'); +const os = require('node:os'); const fs = require('fs-extra'); +const csv = require('csv-parse/sync'); +const yaml = require('yaml'); const { YamlXmlBuilder } = require('../tools/cli/lib/yaml-xml-builder'); const { ManifestGenerator } = require('../tools/cli/installers/lib/core/manifest-generator'); +const { WorkflowCommandGenerator } = require('../tools/cli/installers/lib/ide/shared/workflow-command-generator'); +const { TaskToolCommandGenerator } = require('../tools/cli/installers/lib/ide/shared/task-tool-command-generator'); +const { ConfigDrivenIdeSetup } = require('../tools/cli/installers/lib/ide/_config-driven'); +const { IdeManager } = require('../tools/cli/installers/lib/ide/manager'); +const { CodexSetup } = require('../tools/cli/installers/lib/ide/codex'); +const { ModuleManager } = require('../tools/cli/installers/lib/modules/manager'); +const { BMAD_FOLDER_NAME } = require('../tools/cli/installers/lib/ide/shared/path-utils'); // ANSI colors const colors = { @@ -29,6 +39,56 @@ const colors = { let passed = 0; let failed = 0; +/** + * Recursively collect files from a mix of files/directories. + */ +async function collectFiles(targets, allowedExtensions, excludedFiles = new Set()) { + const files = []; + const normalizedExcludes = new Set([...excludedFiles].map((p) => path.resolve(p))); + + const walk = async (targetPath) => { + if (!(await fs.pathExists(targetPath))) { + return; + } + + const stat = await fs.stat(targetPath); + if (stat.isFile()) { + const normalizedTargetPath = path.resolve(targetPath); + if (normalizedExcludes.has(normalizedTargetPath)) { + return; + } + if (allowedExtensions.has(path.extname(targetPath))) { + files.push(targetPath); + } + return; + } + + const entries = await fs.readdir(targetPath, { withFileTypes: true }); + for (const entry of entries) { + const fullPath = path.join(targetPath, entry.name); + if (entry.isSymbolicLink()) { + continue; + } + if (entry.isDirectory()) { + await walk(fullPath); + continue; + } + if (normalizedExcludes.has(path.resolve(fullPath))) { + continue; + } + if (allowedExtensions.has(path.extname(entry.name))) { + files.push(fullPath); + } + } + }; + + for (const target of targets) { + await walk(target); + } + + return files; +} + /** * Test helper: Assert condition */ @@ -54,6 +114,12 @@ async function runTests() { console.log(`========================================${colors.reset}\n`); const projectRoot = path.join(__dirname, '..'); + const tmpRoots = []; + const trackTmp = async (prefix) => { + const dir = await fs.mkdtemp(path.join(os.tmpdir(), prefix)); + tmpRoots.push(dir); + return dir; + }; // ============================================================ // Test 1: YAML → XML Agent Compilation (In-Memory) @@ -140,16 +206,19 @@ async function runTests() { try { const builder = new YamlXmlBuilder(); - // Test path resolution logic (if exposed) - // This would test {project-root}, {installed_path}, {config_source} resolution + // Basic path-variable substitution contract used across workflow templates + const testPath = '{project-root}/_bmad/bmm/config.yaml'; + const projectRootStub = path.join(os.tmpdir(), 'bmad-test-project'); + const resolvedPath = testPath.replace('{project-root}', projectRootStub); - const testPath = '{project-root}/bmad/bmm/config.yaml'; - const expectedPattern = /\/bmad\/bmm\/config\.yaml$/; + assert(builder && typeof builder.deepMerge === 'function', 'Path suite uses initialized YamlXmlBuilder instance'); + + assert(resolvedPath.startsWith(projectRootStub), 'Path variable replaces {project-root} with resolved root'); assert( - true, // Placeholder - would test actual resolution - 'Path variable resolution pattern matches expected format', - 'Note: This test validates path resolution logic exists', + resolvedPath.endsWith(path.join(BMAD_FOLDER_NAME, 'bmm', 'config.yaml')), + 'Path variable resolution preserves canonical BMAD folder path', + `Resolved path was: ${resolvedPath}`, ); } catch (error) { assert(false, 'Path resolution works', error.message); @@ -157,6 +226,36 @@ async function runTests() { console.log(''); + // ============================================================ + // Test 4: Workflow Command Generator Defaults + // ============================================================ + console.log(`${colors.yellow}Test Suite 4: Workflow Generator Defaults${colors.reset}\n`); + + try { + const workflowGenerator = new WorkflowCommandGenerator(); + assert( + workflowGenerator.bmadFolderName === BMAD_FOLDER_NAME, + 'Workflow generator default BMAD folder matches shared constant', + `Expected "${BMAD_FOLDER_NAME}", got "${workflowGenerator.bmadFolderName}"`, + ); + + const launcherContent = workflowGenerator.buildLauncherContent('bmm', [ + { + name: 'create-story', + displayPath: '{project-root}/_bmad/bmm/workflows/4-implementation/create-story/workflow.md', + description: 'Create and validate the next story', + }, + ]); + assert( + launcherContent.includes('{project-root}/src/core/tasks/workflow.md'), + 'Workflow launcher includes fallback loader path for workflow task', + ); + } catch (error) { + assert(false, 'Workflow generator default path is valid', error.message); + } + + console.log(''); + // ============================================================ // Test 5: QA Agent Compilation // ============================================================ @@ -186,6 +285,658 @@ async function runTests() { console.log(''); + // ============================================================ + // Test 9: Guard against incorrect module config references + // ============================================================ + console.log(`${colors.yellow}Test Suite 9: BMM Config Reference Guard${colors.reset}\n`); + + try { + const searchTargets = [path.join(projectRoot, 'src', 'bmm', 'workflows', 'document-project', 'workflows')]; + const allowedExtensions = new Set(['.yaml', '.yml']); + const forbiddenRef = '{project-root}/_bmad/bmb/config.yaml'; + const offenders = []; + + const files = await collectFiles(searchTargets, allowedExtensions); + for (const fullPath of files) { + const content = await fs.readFile(fullPath, 'utf8'); + if (content.includes(forbiddenRef)) { + offenders.push(path.relative(projectRoot, fullPath)); + } + } + + assert( + offenders.length === 0, + 'No bmm workflow configs should reference _bmad/bmb/config.yaml', + offenders.length > 0 ? offenders.join(', ') : '', + ); + } catch (error) { + assert(false, 'BMM config reference guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 6: Guard against advanced-elicitation XML references + // ============================================================ + console.log(`${colors.yellow}Test Suite 6: Advanced Elicitation Reference Guard${colors.reset}\n`); + + try { + const searchTargets = [ + path.join(projectRoot, 'src', 'bmm', 'workflows', '2-plan-workflows', 'create-prd', 'steps-e'), + path.join(projectRoot, 'src', 'bmm', 'workflows', '2-plan-workflows', 'create-prd', 'steps-v', 'step-v-01-discovery.md'), + ]; + const allowedExtensions = new Set(['.md', '.yaml', '.yml', '.xml']); + const forbiddenRef = 'advanced-elicitation/workflow.xml'; + const offenders = []; + + const files = await collectFiles(searchTargets, allowedExtensions); + for (const fullPath of files) { + const content = await fs.readFile(fullPath, 'utf8'); + if (content.includes(forbiddenRef)) { + offenders.push(path.relative(projectRoot, fullPath)); + } + } + + assert( + offenders.length === 0, + 'No advanced-elicitation/workflow.xml references outside XML source', + offenders.length > 0 ? offenders.join(', ') : '', + ); + } catch (error) { + assert(false, 'Advanced elicitation reference guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 7: Validate Workflow XML Reference Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 7: Validate Workflow Reference Guard${colors.reset}\n`); + + try { + const searchTargets = [ + path.join(projectRoot, 'src', 'bmm', 'workflows', '4-implementation'), + path.join(projectRoot, 'src', 'bmm', 'workflows', 'document-project'), + ]; + const allowedExtensions = new Set(['.md', '.yaml', '.yml', '.xml']); + const forbiddenRef = 'validate-workflow.xml'; + const offenders = []; + + const files = await collectFiles(searchTargets, allowedExtensions); + for (const fullPath of files) { + const content = await fs.readFile(fullPath, 'utf8'); + if (content.includes(forbiddenRef)) { + offenders.push(path.relative(projectRoot, fullPath)); + } + } + + assert( + offenders.length === 0, + 'No validate-workflow.xml references outside XML source', + offenders.length > 0 ? offenders.join(', ') : '', + ); + } catch (error) { + assert(false, 'Validate workflow reference guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 8: Workflow XML Reference Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 8: Workflow Reference Guard${colors.reset}\n`); + + try { + const searchTargets = [ + path.join(projectRoot, 'src', 'bmm', 'workflows', '4-implementation'), + path.join(projectRoot, 'src', 'bmm', 'workflows', 'document-project'), + path.join(projectRoot, 'tools', 'cli', 'installers', 'lib'), + ]; + const allowedExtensions = new Set(['.md', '.yaml', '.yml', '.xml', '.js', '.cjs', '.mjs']); + const forbiddenRefPattern = /(^|[^a-zA-Z0-9_-])workflow\.xml\b/; + const offenders = []; + + const files = await collectFiles(searchTargets, allowedExtensions); + for (const fullPath of files) { + const content = await fs.readFile(fullPath, 'utf8'); + if (forbiddenRefPattern.test(content)) { + offenders.push(path.relative(projectRoot, fullPath)); + } + } + + assert(offenders.length === 0, 'No workflow.xml references outside XML source', offenders.length > 0 ? offenders.join(', ') : ''); + } catch (error) { + assert(false, 'Workflow reference guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 10: Workflow Handler Fallback Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 10: Workflow Handler Fallback Guard${colors.reset}\n`); + + try { + const workflowHandlerPath = path.join(projectRoot, 'src', 'utility', 'agent-components', 'handler-workflow.txt'); + const content = await fs.readFile(workflowHandlerPath, 'utf8'); + + assert(content.includes('{project-root}/src/core/tasks/workflow.md'), 'Workflow handler documents fallback loader path'); + assert(content.includes('Log an error including both attempted paths'), 'Workflow handler requires explicit dual-path error logging'); + assert( + content.includes('Fail fast with a descriptive message and HALT'), + 'Workflow handler mandates fail-fast behavior when loader is unavailable', + ); + } catch (error) { + assert(false, 'Workflow handler fallback guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 11: Gemini Template Extension Regression Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 11: Gemini Template Extension Guard${colors.reset}\n`); + + try { + const tmpRoot = await trackTmp('bmad-gemini-install-'); + const projectDir = path.join(tmpRoot, 'project'); + const bmadDir = path.join(tmpRoot, BMAD_FOLDER_NAME); + await fs.ensureDir(projectDir); + await fs.copy(path.join(projectRoot, 'src', 'core'), path.join(bmadDir, 'core')); + await fs.copy(path.join(projectRoot, 'src', 'bmm'), path.join(bmadDir, 'bmm')); + + const manifestGenerator = new ManifestGenerator(); + await manifestGenerator.generateManifests(bmadDir, ['bmm'], [], { ides: ['gemini'] }); + + const ideManager = new IdeManager(); + await ideManager.ensureInitialized(); + await ideManager.setup('gemini', projectDir, bmadDir, { selectedModules: ['bmm'] }); + + const commandsDir = path.join(projectDir, '.gemini', 'commands'); + const generated = await fs.readdir(commandsDir); + + assert( + generated.some((file) => file.endsWith('.toml')), + 'Gemini installer emits template-native TOML command files', + generated.join(', '), + ); + + assert(!generated.some((file) => file.endsWith('.md')), 'Gemini installer does not emit markdown command files', generated.join(', ')); + + await fs.remove(tmpRoot); + } catch (error) { + assert(false, 'Gemini template extension guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 12: Manifest Stale Entry Cleanup Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 12: Manifest Stale Entry Cleanup Guard${colors.reset}\n`); + + try { + const tmpRoot = await trackTmp('bmad-manifest-clean-'); + const bmadDir = path.join(tmpRoot, BMAD_FOLDER_NAME); + await fs.copy(path.join(projectRoot, 'src', 'core'), path.join(bmadDir, 'core')); + await fs.copy(path.join(projectRoot, 'src', 'bmm'), path.join(bmadDir, 'bmm')); + + const cfgDir = path.join(bmadDir, '_config'); + await fs.ensureDir(cfgDir); + const staleManifestPath = path.join(cfgDir, 'workflow-manifest.csv'); + await fs.writeFile( + staleManifestPath, + 'name,description,module,path\n"old","old workflow","core","_bmad/core/workflows/old/workflow.md"\n', + ); + + const manifestGenerator = new ManifestGenerator(); + await manifestGenerator.generateManifests(bmadDir, ['bmm'], [], { ides: ['claude-code'] }); + const regenerated = await fs.readFile(staleManifestPath, 'utf8'); + + assert( + !regenerated.includes('"old","old workflow","core","_bmad/core/workflows/old/workflow.md"'), + 'Workflow manifest regeneration removes stale/deleted rows', + ); + + await fs.remove(tmpRoot); + } catch (error) { + assert(false, 'Manifest stale entry cleanup guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 13: Internal Task Command Exposure Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 13: Internal Task Exposure Guard${colors.reset}\n`); + + try { + const tmpRoot = await trackTmp('bmad-task-filter-'); + const projectDir = path.join(tmpRoot, 'project'); + const bmadDir = path.join(tmpRoot, BMAD_FOLDER_NAME); + const commandsDir = path.join(tmpRoot, 'commands'); + await fs.ensureDir(projectDir); + await fs.copy(path.join(projectRoot, 'src', 'core'), path.join(bmadDir, 'core')); + await fs.copy(path.join(projectRoot, 'src', 'bmm'), path.join(bmadDir, 'bmm')); + + const manifestGenerator = new ManifestGenerator(); + await manifestGenerator.generateManifests(bmadDir, ['bmm'], [], { ides: ['claude-code'] }); + + const taskToolGenerator = new TaskToolCommandGenerator(); + await taskToolGenerator.generateDashTaskToolCommands(projectDir, bmadDir, commandsDir); + const generated = await fs.readdir(commandsDir); + + assert( + !generated.some((file) => /^bmad-workflow\./.test(file)), + 'Task/tool command generation excludes internal workflow runner task command', + generated.join(', '), + ); + + await fs.remove(tmpRoot); + } catch (error) { + assert(false, 'Internal task exposure guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 14: Workflow Frontmatter web_bundle Strip Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 14: web_bundle Frontmatter Strip Guard${colors.reset}\n`); + + try { + const manager = new ModuleManager(); + const content = `--- +name: demo-workflow +description: Demo +web_bundle: + enabled: true + bundle: + mode: strict +--- + +# Demo +`; + const stripped = manager.stripWebBundleFromFrontmatter(content); + const frontmatterMatch = stripped.match(/^---\n([\s\S]*?)\n---/); + const parsed = frontmatterMatch ? yaml.parse(frontmatterMatch[1]) : {}; + + assert(!stripped.includes('web_bundle:'), 'web_bundle strip removes nested web_bundle block from frontmatter'); + assert(parsed.name === 'demo-workflow' && parsed.description === 'Demo', 'web_bundle strip preserves other frontmatter keys'); + } catch (error) { + assert(false, 'web_bundle strip guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 15: Correct-Course Installed Path Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 15: Correct-Course Installed Path Guard${colors.reset}\n`); + + try { + const workflowPath = path.join(projectRoot, 'src', 'bmm', 'workflows', '4-implementation', 'correct-course', 'workflow.md'); + const content = await fs.readFile(workflowPath, 'utf8'); + + assert( + content.includes('`installed_path` = `{project-root}/_bmad/bmm/workflows/4-implementation/correct-course`'), + 'Correct-course workflow uses installed runtime path', + ); + assert( + content.includes('{project-root}/_bmad/core/tasks/validate-workflow.md'), + 'Correct-course workflow uses installed validate-workflow task path', + ); + } catch (error) { + assert(false, 'Correct-course installed path guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 16: Task/Tool Standalone and CRLF Parsing Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 16: Task/Tool Standalone + CRLF Guard${colors.reset}\n`); + + try { + const tmpRoot = await trackTmp('bmad-standalone-crlf-'); + const coreTasksDir = path.join(tmpRoot, '_bmad', 'core', 'tasks'); + const coreToolsDir = path.join(tmpRoot, '_bmad', 'core', 'tools'); + await fs.ensureDir(coreTasksDir); + await fs.ensureDir(coreToolsDir); + + await fs.writeFile( + path.join(coreTasksDir, 'default-task.md'), + `--- +name: default-task +displayName: Default Task +description: Defaults to standalone +--- +`, + ); + + await fs.writeFile( + path.join(coreTasksDir, 'internal-task.md'), + `--- +name: internal-task +displayName: Internal Task +description: Hidden task +internal: true +--- +`, + ); + + await fs.writeFile( + path.join(coreTasksDir, 'crlf-task.md'), + '---\r\nname: crlf-task\r\ndisplayName: CRLF Task\r\ndescription: Parsed from CRLF\r\nstandalone: true\r\n---\r\n', + ); + + await fs.writeFile( + path.join(coreToolsDir, 'default-tool.md'), + `--- +name: default-tool +displayName: Default Tool +description: Defaults to standalone +--- +`, + ); + + await fs.writeFile( + path.join(coreToolsDir, 'internal-tool.md'), + `--- +name: internal-tool +displayName: Internal Tool +description: Hidden tool +internal: true +--- +`, + ); + + await fs.writeFile( + path.join(coreToolsDir, 'crlf-tool.md'), + '---\r\nname: crlf-tool\r\ndisplayName: CRLF Tool\r\ndescription: Parsed from CRLF\r\nstandalone: true\r\n---\r\n', + ); + + const manifestGenerator = new ManifestGenerator(); + const tasks = await manifestGenerator.getTasksFromDir(coreTasksDir, 'core'); + const tools = await manifestGenerator.getToolsFromDir(coreToolsDir, 'core'); + + const defaultTask = tasks.find((task) => task.name === 'default-task'); + const internalTask = tasks.find((task) => task.name === 'internal-task'); + const crlfTask = tasks.find((task) => task.name === 'crlf-task'); + const defaultTool = tools.find((tool) => tool.name === 'default-tool'); + const internalTool = tools.find((tool) => tool.name === 'internal-tool'); + const crlfTool = tools.find((tool) => tool.name === 'crlf-tool'); + + assert(defaultTask?.standalone === true, 'Tasks default to standalone when standalone key is omitted'); + assert(internalTask?.standalone === false, 'Tasks marked internal are excluded from standalone commands'); + assert(crlfTask?.description === 'Parsed from CRLF', 'CRLF task frontmatter is parsed correctly'); + + assert(defaultTool?.standalone === true, 'Tools default to standalone when standalone key is omitted'); + assert(internalTool?.standalone === false, 'Tools marked internal are excluded from standalone commands'); + assert(crlfTool?.description === 'Parsed from CRLF', 'CRLF tool frontmatter is parsed correctly'); + + const taskToolGenerator = new TaskToolCommandGenerator(); + assert(taskToolGenerator.isStandalone({}) === true, 'Task/tool command filter defaults missing standalone metadata to visible'); + assert( + taskToolGenerator.isStandalone({ standalone: 'false' }) === false, + 'Task/tool command filter hides entries explicitly marked standalone=false', + ); + + await fs.remove(tmpRoot); + } catch (error) { + assert(false, 'Task/tool standalone and CRLF guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 17: Help Task Agent-Only Guidance Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 17: Help Task Agent-Only Guidance Guard${colors.reset}\n`); + + try { + const helpTaskPath = path.join(projectRoot, 'src', 'core', 'tasks', 'help.md'); + const moduleHelpPath = path.join(projectRoot, 'src', 'bmm', 'module-help.csv'); + + const helpTaskContent = await fs.readFile(helpTaskPath, 'utf8'); + const moduleHelpRows = csv.parse(await fs.readFile(moduleHelpPath, 'utf8'), { + columns: true, + skip_empty_lines: true, + }); + + const hasAgentOnlyRows = moduleHelpRows.some((row) => !row.command && row.agent); + assert(hasAgentOnlyRows, 'Help catalog includes agent-only rows with empty command values'); + + assert( + helpTaskContent.includes('When `command` is empty') && helpTaskContent.includes('Do not invent a slash command'), + 'Help task includes explicit guidance for agent-only rows without commands', + ); + } catch (error) { + assert(false, 'Help task agent-only guidance guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 18: Codex Task Visibility Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 18: Codex Task Visibility Guard${colors.reset}\n`); + + try { + const tmpRoot = await trackTmp('bmad-codex-visibility-'); + const projectDir = path.join(tmpRoot, 'project'); + const bmadDir = path.join(tmpRoot, BMAD_FOLDER_NAME); + await fs.ensureDir(projectDir); + await fs.copy(path.join(projectRoot, 'src', 'core'), path.join(bmadDir, 'core')); + await fs.copy(path.join(projectRoot, 'src', 'bmm'), path.join(bmadDir, 'bmm')); + + const manifestGenerator = new ManifestGenerator(); + await manifestGenerator.generateManifests(bmadDir, ['bmm'], [], { ides: ['codex'] }); + + const codexSetup = new CodexSetup(); + await codexSetup.setup(projectDir, bmadDir, { + selectedModules: ['bmm'], + preCollectedConfig: { installLocation: 'project' }, + }); + + const promptsDir = path.join(projectDir, '.codex', 'prompts'); + const generated = await fs.readdir(promptsDir); + + assert(!generated.includes('bmad-workflow.md'), 'Codex export excludes internal workflow runner task prompt', generated.join(', ')); + + await fs.remove(tmpRoot); + } catch (error) { + assert(false, 'Codex task visibility guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 19: Empty Target Artifact Filter Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 19: Empty Artifact Target Guard${colors.reset}\n`); + + try { + const tmpRoot = await trackTmp('bmad-empty-target-'); + const projectDir = path.join(tmpRoot, 'project'); + const bmadDir = path.join(tmpRoot, BMAD_FOLDER_NAME); + await fs.ensureDir(projectDir); + await fs.ensureDir(bmadDir); + + const setup = new ConfigDrivenIdeSetup('test', { + name: 'Test IDE', + preferred: false, + installer: { target_dir: '.test', template_type: 'default' }, + }); + + const result = await setup.installToTarget( + projectDir, + bmadDir, + { target_dir: '.test', template_type: 'default', artifact_types: [] }, + { silent: true }, + ); + + assert( + result.success && + result.results.agents === 0 && + result.results.workflows === 0 && + result.results.tasks === 0 && + result.results.tools === 0, + 'Installer short-circuits explicit empty artifact target', + ); + + assert(!(await fs.pathExists(path.join(projectDir, '.test'))), 'Installer does not create output directory for empty artifact target'); + + await fs.remove(tmpRoot); + } catch (error) { + assert(false, 'Empty artifact target guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 20: Split Template Extension Override Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 20: Split Template Extension Guard${colors.reset}\n`); + + try { + const setup = new ConfigDrivenIdeSetup('test', { + name: 'Test IDE', + preferred: false, + installer: { target_dir: '.test', template_type: 'default' }, + }); + + setup.loadSplitTemplates = async () => 'template-content'; + const loaded = await setup.loadTemplateWithMetadata('default', 'workflow', { + header_template: 'header.md', + extension: 'toml', + }); + + assert(loaded.extension === '.toml', 'Split template loader preserves configured extension override'); + } catch (error) { + assert(false, 'Split template extension guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 21: Workflow Path Normalization Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 21: Workflow Path Normalization Guard${colors.reset}\n`); + + try { + const generator = new WorkflowCommandGenerator(); + generator.loadWorkflowManifest = async () => [ + { + name: 'create-story', + description: 'Create Story', + module: 'bmm', + path: String.raw`C:\repo\src\bmm\workflows\4-implementation\create-story\workflow.md`, + }, + { + name: 'validate-workflow', + description: 'Validate Workflow', + module: 'core', + path: String.raw`C:\repo\_bmad\core\workflows\validate-workflow\workflow.md`, + }, + ]; + generator.generateCommandContent = async () => 'content'; + + const { artifacts } = await generator.collectWorkflowArtifacts('/tmp'); + const createStory = artifacts.find((artifact) => artifact.name === 'create-story'); + const validateWorkflow = artifacts.find((artifact) => artifact.name === 'validate-workflow'); + + assert( + createStory?.workflowPath === 'bmm/workflows/4-implementation/create-story/workflow.md', + 'Workflow artifact path normalizes Windows src path to module-relative path', + createStory?.workflowPath, + ); + assert( + validateWorkflow?.workflowPath === 'core/workflows/validate-workflow/workflow.md', + 'Workflow artifact path strips _bmad prefix after separator normalization', + validateWorkflow?.workflowPath, + ); + } catch (error) { + assert(false, 'Workflow path normalization guard runs', error.message); + } + + console.log(''); + + // ============================================================ + // Test 22: Custom BMAD Folder Workflow Path Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 22: Custom BMAD Folder Workflow Path Guard${colors.reset}\n`); + + try { + const generator = new WorkflowCommandGenerator('mybmad'); + generator.loadWorkflowManifest = async () => [ + { + name: 'sprint-planning', + description: 'Sprint Planning', + module: 'bmm', + path: '/tmp/project/mybmad/bmm/workflows/4-implementation/sprint-planning/workflow.md', + }, + { + name: 'create-story', + description: 'Create Story', + module: 'bmm', + path: 'mybmad/bmm/workflows/4-implementation/create-story/workflow.md', + }, + ]; + generator.generateCommandContent = async () => 'content'; + + const { artifacts } = await generator.collectWorkflowArtifacts('/tmp'); + const sprintPlanning = artifacts.find((artifact) => artifact.name === 'sprint-planning'); + const createStory = artifacts.find((artifact) => artifact.name === 'create-story'); + + assert( + sprintPlanning?.workflowPath === 'bmm/workflows/4-implementation/sprint-planning/workflow.md', + 'Custom folder absolute workflow path strips configured BMAD folder prefix', + sprintPlanning?.workflowPath, + ); + assert( + createStory?.workflowPath === 'bmm/workflows/4-implementation/create-story/workflow.md', + 'Custom folder relative workflow path strips configured BMAD folder prefix', + createStory?.workflowPath, + ); + + const installedPath = generator.mapSourcePathToInstalled('/tmp/project/mybmad/core/tasks/workflow.md'); + assert( + installedPath === 'mybmad/core/tasks/workflow.md', + 'Installed workflow path mapping handles absolute paths containing custom BMAD folder', + installedPath, + ); + + const setup = new ConfigDrivenIdeSetup('test', { + name: 'Test IDE', + preferred: false, + installer: { target_dir: '.test', template_type: 'default' }, + }); + setup.setBmadFolderName('mybmad'); + const rendered = setup.renderTemplate('workflow-config: {{bmadFolderName}}/{{path}}', { + type: 'workflow-command', + name: 'create-story', + module: 'bmm', + workflowPath: createStory?.workflowPath, + relativePath: 'unused.md', + }); + + assert( + rendered.includes('workflow-config: mybmad/bmm/workflows/4-implementation/create-story/workflow.md'), + 'Rendered workflow template uses a single configured BMAD folder prefix', + rendered, + ); + assert(!rendered.includes('mybmad/mybmad/'), 'Rendered workflow template does not duplicate BMAD folder prefix', rendered); + } catch (error) { + assert(false, 'Custom BMAD folder workflow path guard runs', error.message); + } + + console.log(''); + + for (const tmpRoot of tmpRoots) { + await fs.remove(tmpRoot).catch(() => {}); + } + // ============================================================ // Summary // ============================================================ diff --git a/tools/cli/installers/lib/core/manifest-generator.js b/tools/cli/installers/lib/core/manifest-generator.js index bc4694a6d..e9e634ef9 100644 --- a/tools/cli/installers/lib/core/manifest-generator.js +++ b/tools/cli/installers/lib/core/manifest-generator.js @@ -2,7 +2,6 @@ const path = require('node:path'); const fs = require('fs-extra'); const yaml = require('yaml'); const crypto = require('node:crypto'); -const csv = require('csv-parse/sync'); const { getSourcePath, getModulePath } = require('../../../lib/project-root'); const prompts = require('../../../lib/prompts'); @@ -23,19 +22,6 @@ class ManifestGenerator { this.selectedIdes = []; } - /** - * Clean text for CSV output by normalizing whitespace and escaping quotes - * @param {string} text - Text to clean - * @returns {string} Cleaned text safe for CSV - */ - cleanForCSV(text) { - if (!text) return ''; - return text - .trim() - .replaceAll(/\s+/g, ' ') // Normalize all whitespace (including newlines) to single space - .replaceAll('"', '""'); // Escape quotes for CSV - } - /** * Generate all manifests for the installation * @param {string} bmadDir - _bmad @@ -131,7 +117,7 @@ class ManifestGenerator { } /** - * Recursively find and parse workflow.yaml and workflow.md files + * Recursively find and parse workflow definition files */ async getWorkflowsFromPath(basePath, moduleName) { const workflows = []; @@ -149,7 +135,7 @@ class ManifestGenerator { return workflows; } - // Recursively find workflow.yaml files + // Recursively find workflow files const findWorkflows = async (dir, relativePath = '') => { const entries = await fs.readdir(dir, { withFileTypes: true }); @@ -160,12 +146,8 @@ class ManifestGenerator { // Recurse into subdirectories const newRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name; await findWorkflows(fullPath, newRelativePath); - } else if ( - entry.name === 'workflow.yaml' || - entry.name === 'workflow.md' || - (entry.name.startsWith('workflow-') && entry.name.endsWith('.md')) - ) { - // Parse workflow file (both YAML and MD formats) + } else if (entry.isFile() && /^workflow(?:-[^/]+)?\.md$/.test(entry.name)) { + // Parse workflow file (MD with YAML frontmatter) if (debug) { console.log(`[DEBUG] Found workflow file: ${fullPath}`); } @@ -174,21 +156,15 @@ class ManifestGenerator { const rawContent = await fs.readFile(fullPath, 'utf8'); const content = rawContent.replaceAll('\r\n', '\n').replaceAll('\r', '\n'); - let workflow; - if (entry.name === 'workflow.yaml') { - // Parse YAML workflow - workflow = yaml.parse(content); - } else { - // Parse MD workflow with YAML frontmatter - const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/); - if (!frontmatterMatch) { - if (debug) { - console.log(`[DEBUG] Skipped (no frontmatter): ${fullPath}`); - } - continue; // Skip MD files without frontmatter + // Parse MD workflow with YAML frontmatter + const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/); + if (!frontmatterMatch) { + if (debug) { + console.log(`[DEBUG] Skipped (no frontmatter): ${fullPath}`); } - workflow = yaml.parse(frontmatterMatch[1]); + continue; // Skip MD files without frontmatter } + const workflow = yaml.parse(frontmatterMatch[1]); if (debug) { console.log(`[DEBUG] Parsed: name="${workflow.name}", description=${workflow.description ? 'OK' : 'MISSING'}`); @@ -212,15 +188,16 @@ class ManifestGenerator { if (workflow.name && workflow.description) { // Build relative path for installation + const relativeWorkflowPath = relativePath ? `${relativePath}/${entry.name}` : entry.name; const installPath = moduleName === 'core' - ? `${this.bmadFolderName}/core/workflows/${relativePath}/${entry.name}` - : `${this.bmadFolderName}/${moduleName}/workflows/${relativePath}/${entry.name}`; + ? `${this.bmadFolderName}/core/workflows/${relativeWorkflowPath}` + : `${this.bmadFolderName}/${moduleName}/workflows/${relativeWorkflowPath}`; // Workflows with standalone: false are filtered out above workflows.push({ name: workflow.name, - description: this.cleanForCSV(workflow.description), + description: workflow.description.replaceAll('"', '""'), // Escape quotes for CSV module: moduleName, path: installPath, }); @@ -322,7 +299,6 @@ class ManifestGenerator { const nameMatch = content.match(/name="([^"]+)"/); const titleMatch = content.match(/title="([^"]+)"/); const iconMatch = content.match(/icon="([^"]+)"/); - const capabilitiesMatch = content.match(/capabilities="([^"]+)"/); // Extract persona fields const roleMatch = content.match(/([^<]+)<\/role>/); @@ -339,16 +315,24 @@ class ManifestGenerator { const agentName = entry.name.replace('.md', ''); + // Helper function to clean and escape CSV content + const cleanForCSV = (text) => { + if (!text) return ''; + return text + .trim() + .replaceAll(/\s+/g, ' ') // Normalize whitespace + .replaceAll('"', '""'); // Escape quotes for CSV + }; + agents.push({ name: agentName, displayName: nameMatch ? nameMatch[1] : agentName, title: titleMatch ? titleMatch[1] : '', icon: iconMatch ? iconMatch[1] : '', - capabilities: capabilitiesMatch ? this.cleanForCSV(capabilitiesMatch[1]) : '', - role: roleMatch ? this.cleanForCSV(roleMatch[1]) : '', - identity: identityMatch ? this.cleanForCSV(identityMatch[1]) : '', - communicationStyle: styleMatch ? this.cleanForCSV(styleMatch[1]) : '', - principles: principlesMatch ? this.cleanForCSV(principlesMatch[1]) : '', + role: roleMatch ? cleanForCSV(roleMatch[1]) : '', + identity: identityMatch ? cleanForCSV(identityMatch[1]) : '', + communicationStyle: styleMatch ? cleanForCSV(styleMatch[1]) : '', + principles: principlesMatch ? cleanForCSV(principlesMatch[1]) : '', module: moduleName, path: installPath, }); @@ -397,33 +381,31 @@ class ManifestGenerator { const filePath = path.join(dirPath, file); const content = await fs.readFile(filePath, 'utf8'); - // Skip internal/engine files (not user-facing tasks) - if (content.includes('internal="true"')) { - continue; - } - let name = file.replace(/\.(xml|md)$/, ''); let displayName = name; let description = ''; - let standalone = false; + let standalone = true; if (file.endsWith('.md')) { // Parse YAML frontmatter for .md tasks const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/); if (frontmatterMatch) { try { - const frontmatter = yaml.parse(frontmatterMatch[1]); + const frontmatter = yaml.parse(frontmatterMatch[1]) || {}; name = frontmatter.name || name; displayName = frontmatter.displayName || frontmatter.name || name; - description = this.cleanForCSV(frontmatter.description || ''); - // Tasks are standalone by default unless explicitly false (internal=true is already filtered above) - standalone = frontmatter.standalone !== false && frontmatter.standalone !== 'false'; + description = frontmatter.description || ''; + const isInternal = frontmatter.internal === true || frontmatter.internal === 'true'; + if (frontmatter.standalone === true || frontmatter.standalone === 'true') { + standalone = true; + } else if (frontmatter.standalone === false || frontmatter.standalone === 'false') { + standalone = false; + } else { + standalone = !isInternal; + } } catch { // If YAML parsing fails, use defaults - standalone = true; // Default to standalone } - } else { - standalone = true; // No frontmatter means standalone } } else { // For .xml tasks, extract from tag attributes @@ -432,10 +414,18 @@ class ManifestGenerator { const descMatch = content.match(/description="([^"]+)"/); const objMatch = content.match(/([^<]+)<\/objective>/); - description = this.cleanForCSV(descMatch ? descMatch[1] : objMatch ? objMatch[1].trim() : ''); + description = descMatch ? descMatch[1] : objMatch ? objMatch[1].trim() : ''; - const standaloneFalseMatch = content.match(/]+standalone="false"/); - standalone = !standaloneFalseMatch; + const standaloneTrueMatch = content.match(/]+standalone="true"/i); + const standaloneFalseMatch = content.match(/]+standalone="false"/i); + const internalMatch = content.match(/]+internal="true"/i); + if (standaloneFalseMatch) { + standalone = false; + } else if (standaloneTrueMatch) { + standalone = true; + } else { + standalone = !internalMatch; + } } // Build relative path for installation @@ -445,7 +435,7 @@ class ManifestGenerator { tasks.push({ name: name, displayName: displayName, - description: description, + description: description.replaceAll('"', '""'), module: moduleName, path: installPath, standalone: standalone, @@ -495,33 +485,31 @@ class ManifestGenerator { const filePath = path.join(dirPath, file); const content = await fs.readFile(filePath, 'utf8'); - // Skip internal tools (same as tasks) - if (content.includes('internal="true"')) { - continue; - } - let name = file.replace(/\.(xml|md)$/, ''); let displayName = name; let description = ''; - let standalone = false; + let standalone = true; if (file.endsWith('.md')) { // Parse YAML frontmatter for .md tools const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/); if (frontmatterMatch) { try { - const frontmatter = yaml.parse(frontmatterMatch[1]); + const frontmatter = yaml.parse(frontmatterMatch[1]) || {}; name = frontmatter.name || name; displayName = frontmatter.displayName || frontmatter.name || name; - description = this.cleanForCSV(frontmatter.description || ''); - // Tools are standalone by default unless explicitly false (internal=true is already filtered above) - standalone = frontmatter.standalone !== false && frontmatter.standalone !== 'false'; + description = frontmatter.description || ''; + const isInternal = frontmatter.internal === true || frontmatter.internal === 'true'; + if (frontmatter.standalone === true || frontmatter.standalone === 'true') { + standalone = true; + } else if (frontmatter.standalone === false || frontmatter.standalone === 'false') { + standalone = false; + } else { + standalone = !isInternal; + } } catch { // If YAML parsing fails, use defaults - standalone = true; // Default to standalone } - } else { - standalone = true; // No frontmatter means standalone } } else { // For .xml tools, extract from tag attributes @@ -530,10 +518,18 @@ class ManifestGenerator { const descMatch = content.match(/description="([^"]+)"/); const objMatch = content.match(/([^<]+)<\/objective>/); - description = this.cleanForCSV(descMatch ? descMatch[1] : objMatch ? objMatch[1].trim() : ''); + description = descMatch ? descMatch[1] : objMatch ? objMatch[1].trim() : ''; - const standaloneFalseMatch = content.match(/]+standalone="false"/); - standalone = !standaloneFalseMatch; + const standaloneTrueMatch = content.match(/]+standalone="true"/i); + const standaloneFalseMatch = content.match(/]+standalone="false"/i); + const internalMatch = content.match(/]+internal="true"/i); + if (standaloneFalseMatch) { + standalone = false; + } else if (standaloneTrueMatch) { + standalone = true; + } else { + standalone = !internalMatch; + } } // Build relative path for installation @@ -543,7 +539,7 @@ class ManifestGenerator { tools.push({ name: name, displayName: displayName, - description: description, + description: description.replaceAll('"', '""'), module: moduleName, path: installPath, standalone: standalone, @@ -740,24 +736,12 @@ class ManifestGenerator { // Create CSV header - standalone column removed, everything is canonicalized to 4 columns let csv = 'name,description,module,path\n'; - // Build workflows map from discovered workflows only - // Old entries are NOT preserved - the manifest reflects what actually exists on disk - const allWorkflows = new Map(); - - // Only add workflows that were actually discovered in this scan - for (const workflow of this.workflows) { - const key = `${workflow.module}:${workflow.name}`; - allWorkflows.set(key, { - name: workflow.name, - description: workflow.description, - module: workflow.module, - path: workflow.path, - }); - } - - // Write all workflows - for (const [, value] of allWorkflows) { - const row = [escapeCsv(value.name), escapeCsv(value.description), escapeCsv(value.module), escapeCsv(value.path)].join(','); + // Regenerate from current install scan to avoid preserving stale/deleted entries + const sortedWorkflows = [...this.workflows].sort((a, b) => `${a.module}:${a.name}`.localeCompare(`${b.module}:${b.name}`)); + for (const workflow of sortedWorkflows) { + const row = [escapeCsv(workflow.name), escapeCsv(workflow.description), escapeCsv(workflow.module), escapeCsv(workflow.path)].join( + ',', + ); csv += row + '\n'; } @@ -771,69 +755,16 @@ class ManifestGenerator { */ async writeAgentManifest(cfgDir) { const csvPath = path.join(cfgDir, 'agent-manifest.csv'); - const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`; - - // Read existing manifest to preserve entries - const existingEntries = new Map(); - if (await fs.pathExists(csvPath)) { - const content = await fs.readFile(csvPath, 'utf8'); - const records = csv.parse(content, { - columns: true, - skip_empty_lines: true, - }); - for (const record of records) { - existingEntries.set(`${record.module}:${record.name}`, record); - } - } // Create CSV header with persona fields - let csvContent = 'name,displayName,title,icon,capabilities,role,identity,communicationStyle,principles,module,path\n'; + let csv = 'name,displayName,title,icon,role,identity,communicationStyle,principles,module,path\n'; + const sortedAgents = [...this.agents].sort((a, b) => `${a.module}:${a.name}`.localeCompare(`${b.module}:${b.name}`)); - // Combine existing and new agents, preferring new data for duplicates - const allAgents = new Map(); - - // Add existing entries - for (const [key, value] of existingEntries) { - allAgents.set(key, value); + for (const agent of sortedAgents) { + csv += `"${agent.name}","${agent.displayName}","${agent.title}","${agent.icon}","${agent.role}","${agent.identity}","${agent.communicationStyle}","${agent.principles}","${agent.module}","${agent.path}"\n`; } - // Add/update new agents - for (const agent of this.agents) { - const key = `${agent.module}:${agent.name}`; - allAgents.set(key, { - name: agent.name, - displayName: agent.displayName, - title: agent.title, - icon: agent.icon, - capabilities: agent.capabilities, - role: agent.role, - identity: agent.identity, - communicationStyle: agent.communicationStyle, - principles: agent.principles, - module: agent.module, - path: agent.path, - }); - } - - // Write all agents - for (const [, record] of allAgents) { - const row = [ - escapeCsv(record.name), - escapeCsv(record.displayName), - escapeCsv(record.title), - escapeCsv(record.icon), - escapeCsv(record.capabilities), - escapeCsv(record.role), - escapeCsv(record.identity), - escapeCsv(record.communicationStyle), - escapeCsv(record.principles), - escapeCsv(record.module), - escapeCsv(record.path), - ].join(','); - csvContent += row + '\n'; - } - - await fs.writeFile(csvPath, csvContent); + await fs.writeFile(csvPath, csv); return csvPath; } @@ -843,59 +774,15 @@ class ManifestGenerator { */ async writeTaskManifest(cfgDir) { const csvPath = path.join(cfgDir, 'task-manifest.csv'); - const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`; - - // Read existing manifest to preserve entries - const existingEntries = new Map(); - if (await fs.pathExists(csvPath)) { - const content = await fs.readFile(csvPath, 'utf8'); - const records = csv.parse(content, { - columns: true, - skip_empty_lines: true, - }); - for (const record of records) { - existingEntries.set(`${record.module}:${record.name}`, record); - } - } // Create CSV header with standalone column - let csvContent = 'name,displayName,description,module,path,standalone\n'; - - // Combine existing and new tasks - const allTasks = new Map(); - - // Add existing entries - for (const [key, value] of existingEntries) { - allTasks.set(key, value); + let csv = 'name,displayName,description,module,path,standalone\n'; + const sortedTasks = [...this.tasks].sort((a, b) => `${a.module}:${a.name}`.localeCompare(`${b.module}:${b.name}`)); + for (const task of sortedTasks) { + csv += `"${task.name}","${task.displayName}","${task.description}","${task.module}","${task.path}","${task.standalone}"\n`; } - // Add/update new tasks - for (const task of this.tasks) { - const key = `${task.module}:${task.name}`; - allTasks.set(key, { - name: task.name, - displayName: task.displayName, - description: task.description, - module: task.module, - path: task.path, - standalone: task.standalone, - }); - } - - // Write all tasks - for (const [, record] of allTasks) { - const row = [ - escapeCsv(record.name), - escapeCsv(record.displayName), - escapeCsv(record.description), - escapeCsv(record.module), - escapeCsv(record.path), - escapeCsv(record.standalone), - ].join(','); - csvContent += row + '\n'; - } - - await fs.writeFile(csvPath, csvContent); + await fs.writeFile(csvPath, csv); return csvPath; } @@ -905,59 +792,15 @@ class ManifestGenerator { */ async writeToolManifest(cfgDir) { const csvPath = path.join(cfgDir, 'tool-manifest.csv'); - const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`; - - // Read existing manifest to preserve entries - const existingEntries = new Map(); - if (await fs.pathExists(csvPath)) { - const content = await fs.readFile(csvPath, 'utf8'); - const records = csv.parse(content, { - columns: true, - skip_empty_lines: true, - }); - for (const record of records) { - existingEntries.set(`${record.module}:${record.name}`, record); - } - } // Create CSV header with standalone column - let csvContent = 'name,displayName,description,module,path,standalone\n'; - - // Combine existing and new tools - const allTools = new Map(); - - // Add existing entries - for (const [key, value] of existingEntries) { - allTools.set(key, value); + let csv = 'name,displayName,description,module,path,standalone\n'; + const sortedTools = [...this.tools].sort((a, b) => `${a.module}:${a.name}`.localeCompare(`${b.module}:${b.name}`)); + for (const tool of sortedTools) { + csv += `"${tool.name}","${tool.displayName}","${tool.description}","${tool.module}","${tool.path}","${tool.standalone}"\n`; } - // Add/update new tools - for (const tool of this.tools) { - const key = `${tool.module}:${tool.name}`; - allTools.set(key, { - name: tool.name, - displayName: tool.displayName, - description: tool.description, - module: tool.module, - path: tool.path, - standalone: tool.standalone, - }); - } - - // Write all tools - for (const [, record] of allTools) { - const row = [ - escapeCsv(record.name), - escapeCsv(record.displayName), - escapeCsv(record.description), - escapeCsv(record.module), - escapeCsv(record.path), - escapeCsv(record.standalone), - ].join(','); - csvContent += row + '\n'; - } - - await fs.writeFile(csvPath, csvContent); + await fs.writeFile(csvPath, csv); return csvPath; } diff --git a/tools/cli/installers/lib/ide/_base-ide.js b/tools/cli/installers/lib/ide/_base-ide.js index 9bfbdcf30..5c3511d66 100644 --- a/tools/cli/installers/lib/ide/_base-ide.js +++ b/tools/cli/installers/lib/ide/_base-ide.js @@ -289,7 +289,7 @@ class BaseIdeSetup { // Get core workflows const coreWorkflowsPath = path.join(bmadDir, 'core', 'workflows'); if (await fs.pathExists(coreWorkflowsPath)) { - const coreWorkflows = await this.findWorkflowYamlFiles(coreWorkflowsPath); + const coreWorkflows = await this.findWorkflowFiles(coreWorkflowsPath); workflows.push( ...coreWorkflows.map((w) => ({ ...w, @@ -304,7 +304,7 @@ class BaseIdeSetup { if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config' && entry.name !== 'agents') { const moduleWorkflowsPath = path.join(bmadDir, entry.name, 'workflows'); if (await fs.pathExists(moduleWorkflowsPath)) { - const moduleWorkflows = await this.findWorkflowYamlFiles(moduleWorkflowsPath); + const moduleWorkflows = await this.findWorkflowFiles(moduleWorkflowsPath); workflows.push( ...moduleWorkflows.map((w) => ({ ...w, @@ -324,11 +324,11 @@ class BaseIdeSetup { } /** - * Recursively find workflow.yaml files + * Recursively find workflow definition files * @param {string} dir - Directory to search * @returns {Array} List of workflow file info objects */ - async findWorkflowYamlFiles(dir) { + async findWorkflowFiles(dir) { const workflows = []; if (!(await fs.pathExists(dir))) { @@ -342,14 +342,20 @@ class BaseIdeSetup { if (entry.isDirectory()) { // Recursively search subdirectories - const subWorkflows = await this.findWorkflowYamlFiles(fullPath); + const subWorkflows = await this.findWorkflowFiles(fullPath); workflows.push(...subWorkflows); - } else if (entry.isFile() && entry.name === 'workflow.yaml') { - // Read workflow.yaml to get name and standalone property + } else if (entry.isFile() && /^workflow(?:-[^/]+)?\.md$/.test(entry.name)) { + // Read workflow file to get name and standalone property try { const yaml = require('yaml'); const content = await fs.readFile(fullPath, 'utf8'); - const workflowData = yaml.parse(content); + let workflowData = null; + + const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch) { + continue; + } + workflowData = yaml.parse(frontmatterMatch[1]); if (workflowData && workflowData.name) { // Workflows are standalone by default unless explicitly false @@ -540,10 +546,6 @@ class BaseIdeSetup { content = content.replaceAll('_bmad', this.bmadFolderName); } - // Replace escape sequence _bmad with literal _bmad - if (typeof content === 'string' && content.includes('_bmad')) { - content = content.replaceAll('_bmad', '_bmad'); - } await this.ensureDir(path.dirname(filePath)); await fs.writeFile(filePath, content, 'utf8'); } @@ -571,11 +573,6 @@ class BaseIdeSetup { content = content.replaceAll('_bmad', this.bmadFolderName); } - // Replace escape sequence _bmad with literal _bmad - if (content.includes('_bmad')) { - content = content.replaceAll('_bmad', '_bmad'); - } - // Write to dest with replaced content await fs.writeFile(dest, content, 'utf8'); } catch { diff --git a/tools/cli/installers/lib/ide/_config-driven.js b/tools/cli/installers/lib/ide/_config-driven.js index 7eb2533ed..0f363f2e2 100644 --- a/tools/cli/installers/lib/ide/_config-driven.js +++ b/tools/cli/installers/lib/ide/_config-driven.js @@ -67,8 +67,7 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup { async installToTarget(projectDir, bmadDir, config, options) { const { target_dir, template_type, artifact_types } = config; - // Skip targets with explicitly empty artifact_types array - // This prevents creating empty directories when no artifacts will be written + // Skip explicitly empty targets to avoid creating empty command directories. if (Array.isArray(artifact_types) && artifact_types.length === 0) { return { success: true, results: { agents: 0, workflows: 0, tasks: 0, tools: 0 } }; } @@ -93,13 +92,13 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup { results.workflows = await this.writeWorkflowArtifacts(targetPath, artifacts, template_type, config); } - // Install tasks and tools using template system (supports TOML for Gemini, MD for others) + // Install tasks and tools if (!artifact_types || artifact_types.includes('tasks') || artifact_types.includes('tools')) { - const taskToolGen = new TaskToolCommandGenerator(this.bmadFolderName); + const taskToolGen = new TaskToolCommandGenerator(); const { artifacts } = await taskToolGen.collectTaskToolArtifacts(bmadDir); - const taskToolResult = await this.writeTaskToolArtifacts(targetPath, artifacts, template_type, config); - results.tasks = taskToolResult.tasks || 0; - results.tools = taskToolResult.tools || 0; + const taskToolResult = await this.writeTaskToolArtifacts(targetPath, artifacts, template_type, config, artifact_types); + results.tasks = taskToolResult.tasks; + results.tools = taskToolResult.tools; } await this.printSummary(results, target_dir, options); @@ -140,7 +139,7 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup { */ async writeAgentArtifacts(targetPath, artifacts, templateType, config = {}) { // Try to load platform-specific template, fall back to default-agent - const { content: template, extension } = await this.loadTemplate(templateType, 'agent', config, 'default-agent'); + const { template, extension } = await this.loadTemplateWithMetadata(templateType, 'agent', config, 'default-agent'); let count = 0; for (const artifact of artifacts) { @@ -167,16 +166,12 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup { for (const artifact of artifacts) { if (artifact.type === 'workflow-command') { - // Use different template based on workflow type (YAML vs MD) - // Default to 'default' template type, but allow override via config - const workflowTemplateType = artifact.isYamlWorkflow - ? config.yaml_workflow_template || `${templateType}-workflow-yaml` - : config.md_workflow_template || `${templateType}-workflow`; + // Allow explicit override, but normalize to template type prefix (without "-workflow" suffix) + const workflowTemplateType = (config.md_workflow_template || templateType).replace(/-workflow$/, ''); - // Fall back to default templates if specific ones don't exist - const finalTemplateType = artifact.isYamlWorkflow ? 'default-workflow-yaml' : 'default-workflow'; - // workflowTemplateType already contains full name (e.g., 'gemini-workflow-yaml'), so pass empty artifactType - const { content: template, extension } = await this.loadTemplate(workflowTemplateType, '', config, finalTemplateType); + // Fall back to default template if the requested one doesn't exist + const finalTemplateType = 'default-workflow'; + const { template, extension } = await this.loadTemplateWithMetadata(workflowTemplateType, 'workflow', config, finalTemplateType); const content = this.renderTemplate(template, artifact); const filename = this.generateFilename(artifact, 'workflow', extension); const filePath = path.join(targetPath, filename); @@ -189,50 +184,48 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup { } /** - * Write task/tool artifacts to target directory using templates + * Write task/tool artifacts to target directory * @param {string} targetPath - Target directory path * @param {Array} artifacts - Task/tool artifacts * @param {string} templateType - Template type to use * @param {Object} config - Installation configuration - * @returns {Promise} Counts of tasks and tools written + * @param {Array} artifactTypes - Optional include filter from installer config + * @returns {Promise<{tasks:number,tools:number}>} Count of artifacts written */ - async writeTaskToolArtifacts(targetPath, artifacts, templateType, config = {}) { - let taskCount = 0; - let toolCount = 0; - - // Pre-load templates to avoid repeated file I/O in the loop - const taskTemplate = await this.loadTemplate(templateType, 'task', config, 'default-task'); - const toolTemplate = await this.loadTemplate(templateType, 'tool', config, 'default-tool'); - - const { artifact_types } = config; + async writeTaskToolArtifacts(targetPath, artifacts, templateType, config = {}, artifactTypes = null) { + let tasks = 0; + let tools = 0; + const templateCache = new Map(); for (const artifact of artifacts) { if (artifact.type !== 'task' && artifact.type !== 'tool') { continue; } - // Skip if the specific artifact type is not requested in config - if (artifact_types) { - if (artifact.type === 'task' && !artifact_types.includes('tasks')) continue; - if (artifact.type === 'tool' && !artifact_types.includes('tools')) continue; + if (artifactTypes && !artifactTypes.includes(`${artifact.type}s`)) { + continue; } - // Use pre-loaded template based on artifact type - const { content: template, extension } = artifact.type === 'task' ? taskTemplate : toolTemplate; + const cacheKey = `${templateType}:${artifact.type}`; + if (!templateCache.has(cacheKey)) { + const loaded = await this.loadTemplateWithMetadata(templateType, artifact.type, config, `default-${artifact.type}`); + templateCache.set(cacheKey, loaded); + } + const { template, extension } = templateCache.get(cacheKey); const content = this.renderTemplate(template, artifact); const filename = this.generateFilename(artifact, artifact.type, extension); const filePath = path.join(targetPath, filename); await this.writeFile(filePath, content); if (artifact.type === 'task') { - taskCount++; + tasks++; } else { - toolCount++; + tools++; } } - return { tasks: taskCount, tools: toolCount }; + return { tasks, tools }; } /** @@ -241,47 +234,62 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup { * @param {string} artifactType - Artifact type (agent, workflow, task, tool) * @param {Object} config - Installation configuration * @param {string} fallbackTemplateType - Fallback template type if requested template not found - * @returns {Promise<{content: string, extension: string}>} Template content and extension + * @returns {Promise} Template content */ async loadTemplate(templateType, artifactType, config = {}, fallbackTemplateType = null) { + const { template } = await this.loadTemplateWithMetadata(templateType, artifactType, config, fallbackTemplateType); + return template; + } + + /** + * Load template with file extension metadata for extension-aware command generation + * @param {string} templateType - Template type (claude, windsurf, etc.) + * @param {string} artifactType - Artifact type (agent, workflow, task, tool) + * @param {Object} config - Installation configuration + * @param {string} fallbackTemplateType - Fallback template type if requested template not found + * @returns {Promise<{template:string, extension:string}>} Template content and extension + */ + async loadTemplateWithMetadata(templateType, artifactType, config = {}, fallbackTemplateType = null) { const { header_template, body_template } = config; + const supportedExtensions = ['.md', '.toml', '.yaml', '.yml', '.json', '.txt']; // Check for separate header/body templates if (header_template || body_template) { - const content = await this.loadSplitTemplates(templateType, artifactType, header_template, body_template); - // Allow config to override extension, default to .md - const ext = config.extension || '.md'; - const normalizedExt = ext.startsWith('.') ? ext : `.${ext}`; - return { content, extension: normalizedExt }; + const template = await this.loadSplitTemplates(templateType, artifactType, header_template, body_template); + return { template, extension: this.normalizeExtension(config.extension) }; } - // Load combined template - try multiple extensions - // If artifactType is empty, templateType already contains full name (e.g., 'gemini-workflow-yaml') + // Load combined template with extension detection const templateBaseName = artifactType ? `${templateType}-${artifactType}` : templateType; - const templateDir = path.join(__dirname, 'templates', 'combined'); - const extensions = ['.md', '.toml', '.yaml', '.yml']; - - for (const ext of extensions) { - const templatePath = path.join(templateDir, templateBaseName + ext); + for (const extension of supportedExtensions) { + const templateName = `${templateBaseName}${extension}`; + const templatePath = path.join(__dirname, 'templates', 'combined', templateName); if (await fs.pathExists(templatePath)) { - const content = await fs.readFile(templatePath, 'utf8'); - return { content, extension: ext }; + return { + template: await fs.readFile(templatePath, 'utf8'), + extension, + }; } } // Fall back to default template (if provided) if (fallbackTemplateType) { - for (const ext of extensions) { - const fallbackPath = path.join(templateDir, `${fallbackTemplateType}${ext}`); + for (const extension of supportedExtensions) { + const fallbackPath = path.join(__dirname, 'templates', 'combined', `${fallbackTemplateType}${extension}`); if (await fs.pathExists(fallbackPath)) { - const content = await fs.readFile(fallbackPath, 'utf8'); - return { content, extension: ext }; + return { + template: await fs.readFile(fallbackPath, 'utf8'), + extension, + }; } } } // Ultimate fallback - minimal template - return { content: this.getDefaultTemplate(artifactType), extension: '.md' }; + return { + template: this.getDefaultTemplate(artifactType), + extension: '.md', + }; } /** @@ -328,6 +336,19 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup { return `${header}\n${body}`; } + normalizeExtension(extension) { + if (!extension) { + return '.md'; + } + + const trimmed = String(extension).trim(); + if (trimmed === '') { + return '.md'; + } + + return trimmed.startsWith('.') ? trimmed : `.${trimmed}`; + } + /** * Get default minimal template * @param {string} artifactType - Artifact type @@ -338,7 +359,6 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup { return `--- name: '{{name}}' description: '{{description}}' -disable-model-invocation: true --- You must fully embody this agent's persona and follow all activation instructions exactly as specified. @@ -353,7 +373,6 @@ You must fully embody this agent's persona and follow all activation instruction return `--- name: '{{name}}' description: '{{description}}' -disable-model-invocation: true --- # {{name}} @@ -371,24 +390,10 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}} renderTemplate(template, artifact) { // Use the appropriate path property based on artifact type let pathToUse = artifact.relativePath || ''; - switch (artifact.type) { - case 'agent-launcher': { - pathToUse = artifact.agentPath || artifact.relativePath || ''; - - break; - } - case 'workflow-command': { - pathToUse = artifact.workflowPath || artifact.relativePath || ''; - - break; - } - case 'task': - case 'tool': { - pathToUse = artifact.path || artifact.relativePath || ''; - - break; - } - // No default + if (artifact.type === 'agent-launcher') { + pathToUse = artifact.agentPath || artifact.relativePath || ''; + } else if (artifact.type === 'workflow-command') { + pathToUse = artifact.workflowPath || artifact.relativePath || ''; } let rendered = template @@ -411,27 +416,17 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}} * Generate filename for artifact * @param {Object} artifact - Artifact data * @param {string} artifactType - Artifact type (agent, workflow, task, tool) - * @param {string} extension - File extension to use (e.g., '.md', '.toml') * @returns {string} Generated filename */ generateFilename(artifact, artifactType, extension = '.md') { const { toDashPath } = require('./shared/path-utils'); - - // Reuse central logic to ensure consistent naming conventions - const standardName = toDashPath(artifact.relativePath); - - // Clean up potential double extensions from source files (e.g. .yaml.md, .xml.md -> .md) - // This handles any extensions that might slip through toDashPath() - const baseName = standardName.replace(/\.(md|yaml|yml|json|xml|toml)\.md$/i, '.md'); - - // If using default markdown, preserve the bmad-agent- prefix for agents + // toDashPath already handles the .agent.md suffix for agents correctly + // No need to add it again here + const dashName = toDashPath(artifact.relativePath); if (extension === '.md') { - return baseName; + return dashName; } - - // For other extensions (e.g., .toml), replace .md extension - // Note: agent prefix is preserved even with non-markdown extensions - return baseName.replace(/\.md$/, extension); + return dashName.replace(/\.md$/i, extension); } /** diff --git a/tools/cli/installers/lib/ide/github-copilot.js b/tools/cli/installers/lib/ide/github-copilot.js index 4d852fcb0..93a34b224 100644 --- a/tools/cli/installers/lib/ide/github-copilot.js +++ b/tools/cli/installers/lib/ide/github-copilot.js @@ -260,10 +260,10 @@ You must fully embody this agent's persona and follow all activation instruction let body; if (workflowFile.endsWith('.yaml')) { - // Pattern B: YAML-based workflows — use workflow engine + // Pattern B: Workflow runner-backed execution body = `${configLine} -2. Load the workflow engine at {project-root}/${this.bmadFolderName}/core/tasks/workflow.xml -3. Load and execute the workflow configuration at {project-root}/${workflowFile} using the engine from step 2`; +2. Load the workflow runner at {project-root}/${this.bmadFolderName}/core/tasks/workflow.md +3. Load and execute the workflow configuration at {project-root}/${workflowFile} using workflow-config`; } else if (workflowFile.endsWith('.xml')) { // Pattern A variant: XML tasks — load and execute directly body = `${configLine} @@ -454,7 +454,7 @@ tools: ${toolsStr} - **Workflow definitions**: \`${bmad}/bmm/workflows/\` (organized by phase) - **Core tasks**: \`${bmad}/core/tasks/\` (help, editorial review, indexing, sharding, adversarial review) - **Core workflows**: \`${bmad}/core/workflows/\` (brainstorming, party-mode, advanced-elicitation) -- **Workflow engine**: \`${bmad}/core/tasks/workflow.xml\` (executes YAML-based workflows) +- **Workflow runner**: \`${bmad}/core/tasks/workflow.md\` (executes workflow definitions via \`workflow-config\`) - **Module configuration**: \`${bmad}/bmm/config.yaml\` - **Core configuration**: \`${bmad}/core/config.yaml\` - **Agent manifest**: \`${bmad}/_config/agent-manifest.csv\` @@ -467,7 +467,7 @@ tools: ${toolsStr} - Always load \`${bmad}/bmm/config.yaml\` before any agent activation or workflow execution - Store all config fields as session variables: \`{user_name}\`, \`{communication_language}\`, \`{output_folder}\`, \`{planning_artifacts}\`, \`{implementation_artifacts}\`, \`{project_knowledge}\` - MD-based workflows execute directly — load and follow the \`.md\` file -- YAML-based workflows require the workflow engine — load \`workflow.xml\` first, then pass the \`.yaml\` config +- Workflow executions that require the runner should load \`workflow.md\` first, then pass \`workflow-config\` - Follow step-based workflow execution: load steps JIT, never multiple at once - Save outputs after EACH step when using the workflow engine - The \`{project-root}\` variable resolves to the workspace root at runtime diff --git a/tools/cli/installers/lib/ide/shared/agent-command-generator.js b/tools/cli/installers/lib/ide/shared/agent-command-generator.js index 0915c306b..233214806 100644 --- a/tools/cli/installers/lib/ide/shared/agent-command-generator.js +++ b/tools/cli/installers/lib/ide/shared/agent-command-generator.js @@ -79,8 +79,7 @@ class AgentCommandGenerator { .replaceAll('{{module}}', agent.module) .replaceAll('{{path}}', agentPathInModule) .replaceAll('{{description}}', agent.description || `${agent.name} agent`) - .replaceAll('_bmad', this.bmadFolderName) - .replaceAll('_bmad', '_bmad'); + .replaceAll('_bmad', this.bmadFolderName); } /** diff --git a/tools/cli/installers/lib/ide/shared/bmad-artifacts.js b/tools/cli/installers/lib/ide/shared/bmad-artifacts.js index 7bcfd6a79..a506d4f0e 100644 --- a/tools/cli/installers/lib/ide/shared/bmad-artifacts.js +++ b/tools/cli/installers/lib/ide/shared/bmad-artifacts.js @@ -1,5 +1,6 @@ const path = require('node:path'); const fs = require('fs-extra'); +const yaml = require('yaml'); /** * Helpers for gathering BMAD agents/tasks from the installed tree. @@ -149,8 +150,33 @@ async function getTasksFromDir(dirPath, moduleName) { const filePath = path.join(dirPath, file); const content = await fs.readFile(filePath, 'utf8'); - // Skip internal/engine files (not user-facing tasks) - if (content.includes('internal="true"')) { + let isInternal = false; + let isStandalone = true; + + if (file.endsWith('.md')) { + // Parse markdown frontmatter for standalone/internal flags. + const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/); + if (frontmatterMatch) { + try { + const frontmatter = yaml.parse(frontmatterMatch[1]) || {}; + isInternal = frontmatter.internal === true || frontmatter.internal === 'true'; + if (frontmatter.standalone === false || frontmatter.standalone === 'false') { + isStandalone = false; + } + } catch { + // Keep defaults when frontmatter parsing fails. + } + } + } else { + // XML tasks rely on attributes for standalone/internal visibility. + isInternal = /internal\s*=\s*["']true["']/i.test(content); + if (/standalone\s*=\s*["']false["']/i.test(content)) { + isStandalone = false; + } + } + + // Skip internal/engine or explicitly non-standalone tasks. + if (isInternal || !isStandalone) { continue; } diff --git a/tools/cli/installers/lib/ide/shared/path-utils.js b/tools/cli/installers/lib/ide/shared/path-utils.js index 519669233..6864ec7d4 100644 --- a/tools/cli/installers/lib/ide/shared/path-utils.js +++ b/tools/cli/installers/lib/ide/shared/path-utils.js @@ -63,7 +63,7 @@ function toDashPath(relativePath) { } // Strip common file extensions to avoid double extensions in generated filenames - // e.g., 'create-story.xml' → 'create-story', 'workflow.yaml' → 'workflow' + // e.g., 'create-story.xml' → 'create-story', 'workflow.md' → 'workflow' const withoutExt = relativePath.replace(/\.(md|yaml|yml|json|xml|toml)$/i, ''); const parts = withoutExt.split(/[/\\]/); diff --git a/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js b/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js index ece1c8630..831227164 100644 --- a/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +++ b/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js @@ -18,6 +18,22 @@ class TaskToolCommandGenerator { this.bmadFolderName = bmadFolderName; } + /** + * Determine if manifest entry is standalone/user-facing. + * @param {Object} item - Manifest row + * @returns {boolean} True when item should be exposed as a command + */ + isStandalone(item) { + if (item?.standalone === false || item?.standalone === 'false') { + return false; + } + if (item?.internal === true || item?.internal === 'true') { + return false; + } + // Backward-compatible default: entries are user-facing unless explicitly hidden. + return true; + } + /** * Collect task and tool artifacts for IDE installation * @param {string} bmadDir - BMAD installation directory @@ -27,12 +43,14 @@ class TaskToolCommandGenerator { const tasks = await this.loadTaskManifest(bmadDir); const tools = await this.loadToolManifest(bmadDir); - // All tasks/tools in manifest are standalone (internal=true items are filtered during manifest generation) + const standaloneTasks = (tasks || []).filter((task) => this.isStandalone(task)); + const standaloneTools = (tools || []).filter((tool) => this.isStandalone(tool)); + const artifacts = []; const bmadPrefix = `${BMAD_FOLDER_NAME}/`; // Collect task artifacts - for (const task of tasks || []) { + for (const task of standaloneTasks) { let taskPath = (task.path || '').replaceAll('\\', '/'); // Convert absolute paths to relative paths if (path.isAbsolute(taskPath)) { @@ -57,7 +75,7 @@ class TaskToolCommandGenerator { } // Collect tool artifacts - for (const tool of tools || []) { + for (const tool of standaloneTools) { let toolPath = (tool.path || '').replaceAll('\\', '/'); // Convert absolute paths to relative paths if (path.isAbsolute(toolPath)) { @@ -84,8 +102,8 @@ class TaskToolCommandGenerator { return { artifacts, counts: { - tasks: (tasks || []).length, - tools: (tools || []).length, + tasks: standaloneTasks.length, + tools: standaloneTools.length, }, }; } @@ -99,6 +117,8 @@ class TaskToolCommandGenerator { async generateTaskToolCommands(projectDir, bmadDir, baseCommandsDir = null) { const tasks = await this.loadTaskManifest(bmadDir); const tools = await this.loadToolManifest(bmadDir); + const standaloneTasks = (tasks || []).filter((task) => this.isStandalone(task)); + const standaloneTools = (tools || []).filter((tool) => this.isStandalone(tool)); // Base commands directory - use provided or default to Claude Code structure const commandsDir = baseCommandsDir || path.join(projectDir, '.claude', 'commands', 'bmad'); @@ -106,7 +126,7 @@ class TaskToolCommandGenerator { let generatedCount = 0; // Generate command files for tasks - for (const task of tasks || []) { + for (const task of standaloneTasks) { const moduleTasksDir = path.join(commandsDir, task.module, 'tasks'); await fs.ensureDir(moduleTasksDir); @@ -118,7 +138,7 @@ class TaskToolCommandGenerator { } // Generate command files for tools - for (const tool of tools || []) { + for (const tool of standaloneTools) { const moduleToolsDir = path.join(commandsDir, tool.module, 'tools'); await fs.ensureDir(moduleToolsDir); @@ -131,8 +151,8 @@ class TaskToolCommandGenerator { return { generated: generatedCount, - tasks: (tasks || []).length, - tools: (tools || []).length, + tasks: standaloneTasks.length, + tools: standaloneTools.length, }; } @@ -233,11 +253,13 @@ Follow all instructions in the ${type} file exactly as written. async generateColonTaskToolCommands(projectDir, bmadDir, baseCommandsDir) { const tasks = await this.loadTaskManifest(bmadDir); const tools = await this.loadToolManifest(bmadDir); + const standaloneTasks = (tasks || []).filter((task) => this.isStandalone(task)); + const standaloneTools = (tools || []).filter((tool) => this.isStandalone(tool)); let generatedCount = 0; // Generate command files for tasks - for (const task of tasks || []) { + for (const task of standaloneTasks) { const commandContent = this.generateCommandContent(task, 'task'); // Use underscore format: bmad_bmm_name.md const flatName = toColonName(task.module, 'tasks', task.name); @@ -248,7 +270,7 @@ Follow all instructions in the ${type} file exactly as written. } // Generate command files for tools - for (const tool of tools || []) { + for (const tool of standaloneTools) { const commandContent = this.generateCommandContent(tool, 'tool'); // Use underscore format: bmad_bmm_name.md const flatName = toColonName(tool.module, 'tools', tool.name); @@ -260,8 +282,8 @@ Follow all instructions in the ${type} file exactly as written. return { generated: generatedCount, - tasks: (tasks || []).length, - tools: (tools || []).length, + tasks: standaloneTasks.length, + tools: standaloneTools.length, }; } @@ -277,11 +299,13 @@ Follow all instructions in the ${type} file exactly as written. async generateDashTaskToolCommands(projectDir, bmadDir, baseCommandsDir) { const tasks = await this.loadTaskManifest(bmadDir); const tools = await this.loadToolManifest(bmadDir); + const standaloneTasks = (tasks || []).filter((task) => this.isStandalone(task)); + const standaloneTools = (tools || []).filter((tool) => this.isStandalone(tool)); let generatedCount = 0; // Generate command files for tasks - for (const task of tasks || []) { + for (const task of standaloneTasks) { const commandContent = this.generateCommandContent(task, 'task'); // Use dash format: bmad-bmm-name.md const flatName = toDashPath(`${task.module}/tasks/${task.name}.md`); @@ -292,7 +316,7 @@ Follow all instructions in the ${type} file exactly as written. } // Generate command files for tools - for (const tool of tools || []) { + for (const tool of standaloneTools) { const commandContent = this.generateCommandContent(tool, 'tool'); // Use dash format: bmad-bmm-name.md const flatName = toDashPath(`${tool.module}/tools/${tool.name}.md`); @@ -304,8 +328,8 @@ Follow all instructions in the ${type} file exactly as written. return { generated: generatedCount, - tasks: (tasks || []).length, - tools: (tools || []).length, + tasks: standaloneTasks.length, + tools: standaloneTools.length, }; } 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 d94e77db1..75c1b2601 100644 --- a/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +++ b/tools/cli/installers/lib/ide/shared/workflow-command-generator.js @@ -4,12 +4,16 @@ const csv = require('csv-parse/sync'); const prompts = require('../../../../lib/prompts'); const { toColonPath, toDashPath, customAgentColonName, customAgentDashName, BMAD_FOLDER_NAME } = require('./path-utils'); +function escapeRegex(value) { + return String(value).replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`); +} + /** * Generates command files for each workflow in the manifest */ class WorkflowCommandGenerator { constructor(bmadFolderName = BMAD_FOLDER_NAME) { - this.templatePath = path.join(__dirname, '../templates/workflow-command-template.md'); + this.templatePath = path.join(__dirname, '../templates/workflow-commander.md'); this.bmadFolderName = bmadFolderName; } @@ -67,29 +71,9 @@ class WorkflowCommandGenerator { for (const workflow of allWorkflows) { const commandContent = await this.generateCommandContent(workflow, bmadDir); - // Calculate the relative workflow path (e.g., bmm/workflows/4-implementation/sprint-planning/workflow.yaml) - let workflowRelPath = workflow.path || ''; - // Normalize path separators for cross-platform compatibility - workflowRelPath = workflowRelPath.replaceAll('\\', '/'); - // Remove _bmad/ prefix if present to get relative path from project root - // Handle both absolute paths (/path/to/_bmad/...) and relative paths (_bmad/...) - if (workflowRelPath.includes('_bmad/')) { - const parts = workflowRelPath.split(/_bmad\//); - if (parts.length > 1) { - workflowRelPath = parts.slice(1).join('/'); - } - } else if (workflowRelPath.includes('/src/')) { - // Normalize source paths (e.g. .../src/bmm/...) to relative module path (e.g. bmm/...) - const match = workflowRelPath.match(/\/src\/([^/]+)\/(.+)/); - if (match) { - workflowRelPath = `${match[1]}/${match[2]}`; - } - } - // Determine if this is a YAML workflow (use normalized path which is guaranteed to be a string) - const isYamlWorkflow = workflowRelPath.endsWith('.yaml') || workflowRelPath.endsWith('.yml'); + const workflowRelPath = this.mapSourcePathToModuleRelative(workflow.path); artifacts.push({ type: 'workflow-command', - isYamlWorkflow: isYamlWorkflow, // For template selection name: workflow.name, description: workflow.description || `${workflow.name} workflow`, module: workflow.module, @@ -124,32 +108,9 @@ class WorkflowCommandGenerator { * Generate command content for a workflow */ async generateCommandContent(workflow, bmadDir) { - // Determine template based on workflow file type - const isMarkdownWorkflow = workflow.path.endsWith('workflow.md'); - const templateName = isMarkdownWorkflow ? 'workflow-commander.md' : 'workflow-command-template.md'; - const templatePath = path.join(path.dirname(this.templatePath), templateName); - - // Load the appropriate template - const template = await fs.readFile(templatePath, 'utf8'); - - // Convert source path to installed path - // From: /Users/.../src/bmm/workflows/.../workflow.yaml - // To: {project-root}/_bmad/bmm/workflows/.../workflow.yaml - let workflowPath = workflow.path; - - // Extract the relative path from source - if (workflowPath.includes('/src/bmm/')) { - // bmm is directly under src/ - const match = workflowPath.match(/\/src\/bmm\/(.+)/); - if (match) { - workflowPath = `${this.bmadFolderName}/bmm/${match[1]}`; - } - } else if (workflowPath.includes('/src/core/')) { - const match = workflowPath.match(/\/src\/core\/(.+)/); - if (match) { - workflowPath = `${this.bmadFolderName}/core/${match[1]}`; - } - } + // Load the workflow command template + const template = await fs.readFile(this.templatePath, 'utf8'); + const workflowPath = this.mapSourcePathToInstalled(workflow.path); // Replace template variables return template @@ -217,10 +178,17 @@ class WorkflowCommandGenerator { ## Execution When running any workflow: -1. LOAD {project-root}/${this.bmadFolderName}/core/tasks/workflow.xml -2. Pass the workflow path as 'workflow-config' parameter -3. Follow workflow.xml instructions EXACTLY -4. Save outputs after EACH section +1. Resolve loader paths: + - Primary: {project-root}/${this.bmadFolderName}/core/tasks/workflow.md + - Optional dev fallback: {project-root}/src/core/tasks/workflow.md (only if it exists and is readable) +2. Check the primary path exists and is readable before loading +3. If primary is missing/unreadable, log a warning with the primary path and error +4. Only if the dev fallback exists and is readable, try the fallback path; otherwise skip it +5. If no readable loader is found, log an error with all attempted readable paths and stop +6. LOAD the resolved workflow loader file +7. Pass the workflow path as 'workflow-config' parameter +8. Follow workflow.md instructions EXACTLY +9. Save outputs after EACH section ## Modes - Normal: Full interaction @@ -231,21 +199,65 @@ When running any workflow: } transformWorkflowPath(workflowPath) { - let transformed = workflowPath; + return this.mapSourcePathToInstalled(workflowPath, true); + } - if (workflowPath.includes('/src/bmm/')) { - const match = workflowPath.match(/\/src\/bmm\/(.+)/); - if (match) { - transformed = `{project-root}/${this.bmadFolderName}/bmm/${match[1]}`; - } - } else if (workflowPath.includes('/src/core/')) { - const match = workflowPath.match(/\/src\/core\/(.+)/); - if (match) { - transformed = `{project-root}/${this.bmadFolderName}/core/${match[1]}`; - } + mapSourcePathToModuleRelative(sourcePath) { + const mapped = this.mapSourcePathToInstalled(sourcePath, false); + if (!mapped) { + return mapped; } - return transformed; + const normalized = String(mapped).replaceAll('\\', '/'); + + // Typical installed path -> strip BMAD root prefix for templates that prepend it. + if (normalized.startsWith(`${this.bmadFolderName}/`)) { + return normalized.slice(`${this.bmadFolderName}/`.length); + } + + // Absolute path containing the configured BMAD root folder. + const folderPattern = new RegExp(`(?:^|\\/)${escapeRegex(this.bmadFolderName)}\\/(.+)`); + const folderMatch = normalized.match(folderPattern); + if (folderMatch) { + return folderMatch[1]; + } + + return normalized; + } + + mapSourcePathToInstalled(sourcePath, includeProjectRootPrefix = false) { + if (!sourcePath) { + return sourcePath; + } + + const normalized = sourcePath.replaceAll('\\', '/'); + const srcMatch = normalized.match(/(?:^|\/)src\/([^/]+)\/(.+)/); + if (srcMatch) { + const mapped = `${this.bmadFolderName}/${srcMatch[1]}/${srcMatch[2]}`; + return includeProjectRootPrefix ? `{project-root}/${mapped}` : mapped; + } + + if (normalized.includes('_bmad/')) { + const parts = normalized.split(/_bmad\//); + const relative = parts.at(-1); + const mapped = `${this.bmadFolderName}/${relative}`; + return includeProjectRootPrefix ? `{project-root}/${mapped}` : mapped; + } + + // Handle absolute paths that already include the configured BMAD folder + // (e.g., /tmp/project/mybmad/bmm/workflows/...). + const folderPattern = new RegExp(`(?:^|\\/)${escapeRegex(this.bmadFolderName)}\\/(.+)`); + const folderMatch = normalized.match(folderPattern); + if (folderMatch) { + const mapped = `${this.bmadFolderName}/${folderMatch[1]}`; + return includeProjectRootPrefix ? `{project-root}/${mapped}` : mapped; + } + + if (normalized.startsWith(`${this.bmadFolderName}/`)) { + return includeProjectRootPrefix ? `{project-root}/${normalized}` : normalized; + } + + return sourcePath; } async loadWorkflowManifest(bmadDir) { @@ -291,7 +303,7 @@ When running any workflow: * Write workflow command artifacts using dash format (NEW STANDARD) * Creates flat files like: bmad-bmm-correct-course.md * - * Note: Workflows do NOT have bmad-agent- prefix - only agents do. + * Note: Workflows do NOT have .agent.md suffix - only agents do. * * @param {string} baseCommandsDir - Base commands directory for the IDE * @param {Array} artifacts - Workflow artifacts diff --git a/tools/cli/installers/lib/ide/templates/combined/antigravity.md b/tools/cli/installers/lib/ide/templates/combined/antigravity.md index 88e806e9d..682dbeb17 100644 --- a/tools/cli/installers/lib/ide/templates/combined/antigravity.md +++ b/tools/cli/installers/lib/ide/templates/combined/antigravity.md @@ -3,6 +3,7 @@ name: '{{name}}' description: '{{description}}' --- -Read the entire workflow file at: {project-root}/_bmad/{{workflow_path}} - -Follow all instructions in the workflow file exactly as written. +1. Load the workflow runner at {project-root}/_bmad/core/tasks/workflow.md +2. Read the runner fully +3. Run it with workflow-config: {{workflow_path}} +4. Follow all runner instructions exactly diff --git a/tools/cli/installers/lib/ide/templates/combined/claude-workflow-yaml.md b/tools/cli/installers/lib/ide/templates/combined/claude-workflow-yaml.md deleted file mode 120000 index 11f78e1d4..000000000 --- a/tools/cli/installers/lib/ide/templates/combined/claude-workflow-yaml.md +++ /dev/null @@ -1 +0,0 @@ -default-workflow-yaml.md \ No newline at end of file diff --git a/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md b/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md deleted file mode 100644 index 2a5e49b83..000000000 --- a/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -name: '{{name}}' -description: '{{description}}' -disable-model-invocation: true ---- - -IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded: - - -1. Always LOAD the FULL @{project-root}/{{bmadFolderName}}/core/tasks/workflow.xml -2. READ its entire contents - this is the CORE OS for EXECUTING the specific workflow-config @{project-root}/{{bmadFolderName}}/{{path}} -3. Pass the yaml path @{project-root}/{{bmadFolderName}}/{{path}} as 'workflow-config' parameter to the workflow.xml instructions -4. Follow workflow.xml instructions EXACTLY as written to process and follow the specific workflow config and its instructions -5. Save outputs after EACH section when generating any documents from templates - diff --git a/tools/cli/installers/lib/ide/templates/combined/default-workflow.md b/tools/cli/installers/lib/ide/templates/combined/default-workflow.md index 8c4fa818f..b4ebc7647 100644 --- a/tools/cli/installers/lib/ide/templates/combined/default-workflow.md +++ b/tools/cli/installers/lib/ide/templates/combined/default-workflow.md @@ -4,4 +4,8 @@ description: '{{description}}' disable-model-invocation: true --- -IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{project-root}/{{bmadFolderName}}/{{path}}, READ its entire contents and follow its directions exactly! +IT IS CRITICAL THAT YOU FOLLOW THESE STEPS: +1. LOAD the FULL @{project-root}/{{bmadFolderName}}/core/tasks/workflow.md +2. READ its entire contents +3. Execute workflow runner with parameter: workflow-config: {{bmadFolderName}}/{{path}} +4. FOLLOW the runner instructions exactly as written diff --git a/tools/cli/installers/lib/ide/templates/combined/gemini-workflow-yaml.toml b/tools/cli/installers/lib/ide/templates/combined/gemini-workflow-yaml.toml index 063ca0d0b..252e6e6f6 100644 --- a/tools/cli/installers/lib/ide/templates/combined/gemini-workflow-yaml.toml +++ b/tools/cli/installers/lib/ide/templates/combined/gemini-workflow-yaml.toml @@ -2,15 +2,11 @@ description = """{{description}}""" prompt = """ Execute the BMAD '{{name}}' workflow. -CRITICAL: This is a structured YAML workflow. Follow these steps precisely: +CRITICAL: Use the workflow runner task, not direct workflow-file execution. -1. LOAD the workflow definition from {project-root}/{{bmadFolderName}}/{{workflow_path}} -2. PARSE the YAML structure to understand: - - Workflow phases and steps - - Required inputs and outputs - - Dependencies between steps -3. EXECUTE each step in order -4. VALIDATE outputs before proceeding to next step - -WORKFLOW FILE: {project-root}/{{bmadFolderName}}/{{workflow_path}} +WORKFLOW INSTRUCTIONS: +1. LOAD the workflow runner from {project-root}/{{bmadFolderName}}/core/tasks/workflow.md +2. READ its entire contents +3. PASS this parameter to the runner: workflow-config: {{workflow_path}} +4. FOLLOW every runner step exactly as specified """ diff --git a/tools/cli/installers/lib/ide/templates/combined/gemini-workflow.toml b/tools/cli/installers/lib/ide/templates/combined/gemini-workflow.toml index 526241061..252e6e6f6 100644 --- a/tools/cli/installers/lib/ide/templates/combined/gemini-workflow.toml +++ b/tools/cli/installers/lib/ide/templates/combined/gemini-workflow.toml @@ -2,13 +2,11 @@ description = """{{description}}""" prompt = """ Execute the BMAD '{{name}}' workflow. -CRITICAL: You must load and follow the workflow definition exactly. +CRITICAL: Use the workflow runner task, not direct workflow-file execution. WORKFLOW INSTRUCTIONS: -1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{workflow_path}} +1. LOAD the workflow runner from {project-root}/{{bmadFolderName}}/core/tasks/workflow.md 2. READ its entire contents -3. FOLLOW every step precisely as specified -4. DO NOT skip or modify any steps - -WORKFLOW FILE: {project-root}/{{bmadFolderName}}/{{workflow_path}} +3. PASS this parameter to the runner: workflow-config: {{workflow_path}} +4. FOLLOW every runner step exactly as specified """ diff --git a/tools/cli/installers/lib/ide/templates/combined/kiro-workflow-yaml.md b/tools/cli/installers/lib/ide/templates/combined/kiro-workflow-yaml.md index 4ee4e0824..448c196bd 100644 --- a/tools/cli/installers/lib/ide/templates/combined/kiro-workflow-yaml.md +++ b/tools/cli/installers/lib/ide/templates/combined/kiro-workflow-yaml.md @@ -7,9 +7,13 @@ inclusion: manual IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded: -1. Always LOAD the FULL #[[file:{{bmadFolderName}}/core/tasks/workflow.xml]] +1. Always LOAD the FULL #[[file:{{bmadFolderName}}/core/tasks/workflow.md]] 2. READ its entire contents - this is the CORE OS for EXECUTING the specific workflow-config #[[file:{{bmadFolderName}}/{{path}}]] -3. Pass the yaml path {{bmadFolderName}}/{{path}} as 'workflow-config' parameter to the workflow.xml instructions -4. Follow workflow.xml instructions EXACTLY as written to process and follow the specific workflow config and its instructions +3. Pass workflow path to workflow.md using YAML parameter key `workflow-config` with value `{{bmadFolderName}}/{{path}}` + Example invocation parameter block: + ```yaml + workflow-config: {{bmadFolderName}}/{{path}} + ``` +4. Follow workflow.md task instructions EXACTLY as written to process and follow the specific workflow config and its instructions 5. Save outputs after EACH section when generating any documents from templates diff --git a/tools/cli/installers/lib/ide/templates/combined/kiro-workflow.md b/tools/cli/installers/lib/ide/templates/combined/kiro-workflow.md index e1847f414..117846b84 100644 --- a/tools/cli/installers/lib/ide/templates/combined/kiro-workflow.md +++ b/tools/cli/installers/lib/ide/templates/combined/kiro-workflow.md @@ -4,4 +4,11 @@ inclusion: manual # {{name}} -IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL #[[file:{{bmadFolderName}}/{{path}}]], READ its entire contents and follow its directions exactly! +IT IS CRITICAL THAT YOU FOLLOW THESE STEPS: +1. Always LOAD the FULL #[[file:{{bmadFolderName}}/core/tasks/workflow.md]] +2. READ its entire contents +3. Execute workflow runner with YAML parameter: + ```yaml + workflow-config: {{bmadFolderName}}/{{path}} + ``` +4. FOLLOW the runner instructions exactly as written diff --git a/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md b/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md index a6f5cb96f..ec82659ce 100644 --- a/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md +++ b/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md @@ -5,13 +5,10 @@ description: '{{description}}' Execute the BMAD '{{name}}' workflow. -CRITICAL: You must load and follow the workflow definition exactly. +CRITICAL: Use the workflow runner task, not direct workflow-file execution. WORKFLOW INSTRUCTIONS: - -1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{path}} +1. LOAD the workflow runner from {project-root}/{{bmadFolderName}}/core/tasks/workflow.md 2. READ its entire contents -3. FOLLOW every step precisely as specified -4. DO NOT skip or modify any steps - -WORKFLOW FILE: {project-root}/{{bmadFolderName}}/{{path}} +3. PASS this parameter to the runner: workflow-config: {{bmadFolderName}}/{{path}} +4. FOLLOW every runner step exactly as specified diff --git a/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md b/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md index a6f5cb96f..ec82659ce 100644 --- a/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md +++ b/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md @@ -5,13 +5,10 @@ description: '{{description}}' Execute the BMAD '{{name}}' workflow. -CRITICAL: You must load and follow the workflow definition exactly. +CRITICAL: Use the workflow runner task, not direct workflow-file execution. WORKFLOW INSTRUCTIONS: - -1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{path}} +1. LOAD the workflow runner from {project-root}/{{bmadFolderName}}/core/tasks/workflow.md 2. READ its entire contents -3. FOLLOW every step precisely as specified -4. DO NOT skip or modify any steps - -WORKFLOW FILE: {project-root}/{{bmadFolderName}}/{{path}} +3. PASS this parameter to the runner: workflow-config: {{bmadFolderName}}/{{path}} +4. FOLLOW every runner step exactly as specified diff --git a/tools/cli/installers/lib/ide/templates/combined/rovodev.md b/tools/cli/installers/lib/ide/templates/combined/rovodev.md index 066945ee5..721b2d2f0 100644 --- a/tools/cli/installers/lib/ide/templates/combined/rovodev.md +++ b/tools/cli/installers/lib/ide/templates/combined/rovodev.md @@ -4,6 +4,7 @@ --- -Read the entire workflow file at: {project-root}/_bmad/{{workflow_path}} - -Follow all instructions in the workflow file exactly as written. +1. Load the workflow runner at {project-root}/_bmad/core/tasks/workflow.md +2. Read the runner fully +3. Run it with workflow-config: {{workflow_path}} +4. Follow all runner instructions exactly diff --git a/tools/cli/installers/lib/ide/templates/combined/trae.md b/tools/cli/installers/lib/ide/templates/combined/trae.md index b4d43d7af..33b5bccfa 100644 --- a/tools/cli/installers/lib/ide/templates/combined/trae.md +++ b/tools/cli/installers/lib/ide/templates/combined/trae.md @@ -4,6 +4,7 @@ ## Instructions -Read the entire workflow file at: {project-root}/_bmad/{{workflow_path}} - -Follow all instructions in the workflow file exactly as written. +1. Load the workflow runner at {project-root}/_bmad/core/tasks/workflow.md +2. Read the runner fully +3. Run it with workflow-config: {{workflow_path}} +4. Follow all runner instructions exactly diff --git a/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md b/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md index 6366425c7..806d6d587 100644 --- a/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md +++ b/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md @@ -5,6 +5,7 @@ auto_execution_mode: "iterate" # {{name}} -Read the entire workflow file at {project-root}/_bmad/{{workflow_path}} - -Follow all instructions in the workflow file exactly as written. +1. Load the workflow runner at {project-root}/_bmad/core/tasks/workflow.md +2. Read the runner fully +3. Run it with workflow-config: {{workflow_path}} +4. Follow all runner instructions exactly diff --git a/tools/cli/installers/lib/ide/templates/workflow-command-template.md b/tools/cli/installers/lib/ide/templates/workflow-command-template.md deleted file mode 100644 index 472c1553a..000000000 --- a/tools/cli/installers/lib/ide/templates/workflow-command-template.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -description: '{{description}}' -disable-model-invocation: true ---- - -IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded: - - -1. Always LOAD the FULL @_bmad/core/tasks/workflow.xml -2. READ its entire contents - this is the CORE OS for EXECUTING the specific workflow-config @{{workflow_path}} -3. Pass the yaml path {{workflow_path}} as 'workflow-config' parameter to the workflow.xml instructions -4. Follow workflow.xml instructions EXACTLY as written to process and follow the specific workflow config and its instructions -5. Save outputs after EACH section when generating any documents from templates - diff --git a/tools/cli/installers/lib/ide/templates/workflow-commander.md b/tools/cli/installers/lib/ide/templates/workflow-commander.md index d49c8319d..272ef4f5b 100644 --- a/tools/cli/installers/lib/ide/templates/workflow-commander.md +++ b/tools/cli/installers/lib/ide/templates/workflow-commander.md @@ -3,4 +3,8 @@ description: '{{description}}' disable-model-invocation: true --- -IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{{workflow_path}}, READ its entire contents and follow its directions exactly! +IT IS CRITICAL THAT YOU FOLLOW THESE STEPS: +1. LOAD the FULL @{project-root}/_bmad/core/tasks/workflow.md +2. READ its entire contents +3. Execute workflow runner with parameter: workflow-config: {{workflow_path}} +4. FOLLOW the runner instructions exactly as written diff --git a/tools/cli/installers/lib/modules/manager.js b/tools/cli/installers/lib/modules/manager.js index b4acc3aef..32279e0b1 100644 --- a/tools/cli/installers/lib/modules/manager.js +++ b/tools/cli/installers/lib/modules/manager.js @@ -760,10 +760,10 @@ class ModuleManager { } } - // Check if this is a workflow.yaml file - if (file.endsWith('workflow.yaml')) { + // Check if this is a workflow definition file (workflow.md or workflow-*.md) + if (/(^|\/)workflow(?:-[^/]+)?\.md$/.test(file)) { await fs.ensureDir(path.dirname(targetFile)); - await this.copyWorkflowYamlStripped(sourceFile, targetFile); + await this.copyWorkflowFileStripped(sourceFile, targetFile); } else { // Copy the file with placeholder replacement await this.copyFileWithPlaceholderReplacement(sourceFile, targetFile); @@ -777,88 +777,48 @@ class ModuleManager { } /** - * Copy workflow.yaml file with web_bundle section stripped + * Copy workflow file with web_bundle section stripped (MD) * Preserves comments, formatting, and line breaks - * @param {string} sourceFile - Source workflow.yaml file path - * @param {string} targetFile - Target workflow.yaml file path + * @param {string} sourceFile - Source workflow file path + * @param {string} targetFile - Target workflow file path */ - async copyWorkflowYamlStripped(sourceFile, targetFile) { - // Read the source YAML file - let yamlContent = await fs.readFile(sourceFile, 'utf8'); + async copyWorkflowFileStripped(sourceFile, targetFile) { + let mdContent = await fs.readFile(sourceFile, 'utf8'); - // IMPORTANT: Replace escape sequence and placeholder BEFORE parsing YAML - // Otherwise parsing will fail on the placeholder - yamlContent = yamlContent.replaceAll('_bmad', this.bmadFolderName); + mdContent = mdContent.replaceAll('_bmad', this.bmadFolderName); + mdContent = this.stripWebBundleFromFrontmatter(mdContent); + await fs.writeFile(targetFile, mdContent, 'utf8'); + } + + stripWebBundleFromFrontmatter(content) { + const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch) { + return content; + } + + const newline = frontmatterMatch[0].includes('\r\n') ? '\r\n' : '\n'; try { - // First check if web_bundle exists by parsing - const workflowConfig = yaml.parse(yamlContent); + const parsed = yaml.parse(frontmatterMatch[1]); - if (workflowConfig.web_bundle === undefined) { - // No web_bundle section, just write (placeholders already replaced above) - await fs.writeFile(targetFile, yamlContent, 'utf8'); - return; + if (!parsed || typeof parsed !== 'object' || !Object.prototype.hasOwnProperty.call(parsed, 'web_bundle')) { + return content; } - // Find the line that starts web_bundle - const lines = yamlContent.split('\n'); - let startIdx = -1; - let endIdx = -1; - let baseIndent = 0; + delete parsed.web_bundle; + const serialized = yaml + .stringify(parsed, { + indent: 2, + lineWidth: 0, + sortMapEntries: false, + }) + .trimEnd(); - // Find the start of web_bundle section - for (const [i, line] of lines.entries()) { - const match = line.match(/^(\s*)web_bundle:/); - if (match) { - startIdx = i; - baseIndent = match[1].length; - break; - } - } - - if (startIdx === -1) { - // web_bundle not found in text (shouldn't happen), copy as-is - await fs.writeFile(targetFile, yamlContent, 'utf8'); - return; - } - - // Find the end of web_bundle section - // It ends when we find a line with same or less indentation that's not empty/comment - endIdx = startIdx; - for (let i = startIdx + 1; i < lines.length; i++) { - const line = lines[i]; - - // Skip empty lines and comments - if (line.trim() === '' || line.trim().startsWith('#')) { - continue; - } - - // Check indentation - const indent = line.match(/^(\s*)/)[1].length; - if (indent <= baseIndent) { - // Found next section at same or lower indentation - endIdx = i - 1; - break; - } - } - - // If we didn't find an end, it goes to end of file - if (endIdx === startIdx) { - endIdx = lines.length - 1; - } - - // Remove the web_bundle section (including the line before if it's just a blank line) - const newLines = [...lines.slice(0, startIdx), ...lines.slice(endIdx + 1)]; - - // Clean up any double blank lines that might result - const strippedYaml = newLines.join('\n').replaceAll(/\n\n\n+/g, '\n\n'); - - // Placeholders already replaced at the beginning of this function - await fs.writeFile(targetFile, strippedYaml, 'utf8'); - } catch { - // If anything fails, just copy the file as-is - await prompts.log.warn(` Could not process ${path.basename(sourceFile)}, copying as-is`); - await fs.copy(sourceFile, targetFile, { overwrite: true }); + const normalized = newline === '\r\n' ? serialized.replaceAll('\n', '\r\n') : serialized; + return content.replace(frontmatterMatch[0], `---${newline}${normalized}${newline}---`); + } catch (error) { + console.warn(`Warning: Failed to parse workflow frontmatter for web_bundle removal: ${error.message}`); + return content; } } @@ -886,7 +846,7 @@ class ModuleManager { for (const agentFile of agentFiles) { if (!agentFile.endsWith('.agent.yaml')) continue; - const relativePath = path.relative(sourceAgentsPath, agentFile).split(path.sep).join('/'); + const relativePath = path.relative(sourceAgentsPath, agentFile); const targetDir = path.join(targetAgentsPath, path.dirname(relativePath)); await fs.ensureDir(targetDir); @@ -922,7 +882,6 @@ class ModuleManager { let manifestData = {}; if (await fs.pathExists(manifestPath)) { const manifestContent = await fs.readFile(manifestPath, 'utf8'); - const yaml = require('yaml'); manifestData = yaml.parse(manifestContent); } if (!manifestData.agentCustomizations) { @@ -931,7 +890,6 @@ class ModuleManager { manifestData.agentCustomizations[path.relative(bmadDir, customizePath)] = originalHash; // Write back to manifest - const yaml = require('yaml'); // Clean the manifest data to remove any non-serializable values const cleanManifestData = structuredClone(manifestData); @@ -1168,9 +1126,9 @@ class ModuleManager { // Parse SOURCE workflow path // Handle both _bmad placeholder and hardcoded 'bmad' - // Example: {project-root}/_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml - // Or: {project-root}/bmad/bmm/workflows/4-implementation/create-story/workflow.yaml - const sourceMatch = sourceWorkflowPath.match(/\{project-root\}\/(?:_bmad)\/([^/]+)\/workflows\/(.+)/); + // Example: {project-root}/_bmad/bmm/workflows/4-implementation/create-story/workflow.md + // Or: {project-root}/bmad/bmm/workflows/4-implementation/create-story/workflow.md + const sourceMatch = sourceWorkflowPath.match(/\{project-root\}\/(?:_?bmad)\/([^/]+)\/workflows\/(.+)/); if (!sourceMatch) { await prompts.log.warn(` Could not parse workflow path: ${sourceWorkflowPath}`); continue; @@ -1179,20 +1137,22 @@ class ModuleManager { const [, sourceModule, sourceWorkflowSubPath] = sourceMatch; // Parse INSTALL workflow path - // Handle_bmad - // Example: {project-root}/_bmad/bmgd/workflows/4-production/create-story/workflow.yaml - const installMatch = installWorkflowPath.match(/\{project-root\}\/(_bmad)\/([^/]+)\/workflows\/(.+)/); + // Handle both _bmad placeholder and hardcoded 'bmad' + // Example: {project-root}/_bmad/bmgd/workflows/4-production/create-story/workflow.md + // Or: {project-root}/bmad/bmgd/workflows/4-production/create-story/workflow.md + const installMatch = installWorkflowPath.match(/\{project-root\}\/(?:_?bmad)\/([^/]+)\/workflows\/(.+)/); if (!installMatch) { await prompts.log.warn(` Could not parse workflow-install path: ${installWorkflowPath}`); continue; } - const installWorkflowSubPath = installMatch[2]; + const [, installModule, installWorkflowSubPath] = installMatch; const sourceModulePath = getModulePath(sourceModule); - const actualSourceWorkflowPath = path.join(sourceModulePath, 'workflows', sourceWorkflowSubPath.replace(/\/workflow\.yaml$/, '')); + const workflowSuffixPattern = /\/workflow(?:-[^/]+)?\.md$/; + const actualSourceWorkflowPath = path.join(sourceModulePath, 'workflows', sourceWorkflowSubPath.replace(workflowSuffixPattern, '')); - const actualDestWorkflowPath = path.join(targetPath, 'workflows', installWorkflowSubPath.replace(/\/workflow\.yaml$/, '')); + const actualDestWorkflowPath = path.join(targetPath, 'workflows', installWorkflowSubPath.replace(workflowSuffixPattern, '')); // Check if source workflow exists if (!(await fs.pathExists(actualSourceWorkflowPath))) { @@ -1202,17 +1162,18 @@ class ModuleManager { // Copy the entire workflow folder await prompts.log.message( - ` Vendoring: ${sourceModule}/workflows/${sourceWorkflowSubPath.replace(/\/workflow\.yaml$/, '')} → ${moduleName}/workflows/${installWorkflowSubPath.replace(/\/workflow\.yaml$/, '')}`, + ` Vendoring: ${sourceModule}/workflows/${sourceWorkflowSubPath.replace(workflowSuffixPattern, '')} → ${installModule}/workflows/${installWorkflowSubPath.replace(workflowSuffixPattern, '')}`, ); await fs.ensureDir(path.dirname(actualDestWorkflowPath)); // Copy the workflow directory recursively with placeholder replacement await this.copyDirectoryWithPlaceholderReplacement(actualSourceWorkflowPath, actualDestWorkflowPath); - // Update the workflow.yaml config_source reference - const workflowYamlPath = path.join(actualDestWorkflowPath, 'workflow.yaml'); - if (await fs.pathExists(workflowYamlPath)) { - await this.updateWorkflowConfigSource(workflowYamlPath, moduleName); + // Update workflow config_source references in vendored workflow definition + const destinationFiles = await fs.readdir(actualDestWorkflowPath); + const workflowDefinitionFile = destinationFiles.find((name) => /^workflow(?:-[^/]+)?\.md$/.test(name)); + if (workflowDefinitionFile) { + await this.updateWorkflowConfigSource(path.join(actualDestWorkflowPath, workflowDefinitionFile), moduleName); } } } @@ -1223,24 +1184,24 @@ class ModuleManager { } /** - * Update workflow.yaml config_source to point to new module - * @param {string} workflowYamlPath - Path to workflow.yaml file + * Update workflow config_source/main_config to point to new module + * @param {string} workflowPath - Path to workflow file * @param {string} newModuleName - New module name to reference */ - async updateWorkflowConfigSource(workflowYamlPath, newModuleName) { - let yamlContent = await fs.readFile(workflowYamlPath, 'utf8'); + async updateWorkflowConfigSource(workflowPath, newModuleName) { + let fileContent = await fs.readFile(workflowPath, 'utf8'); // Replace config_source: "{project-root}/_bmad/OLD_MODULE/config.yaml" // with config_source: "{project-root}/_bmad/NEW_MODULE/config.yaml" // Note: At this point _bmad has already been replaced with actual folder name - const configSourcePattern = /config_source:\s*["']?\{project-root\}\/[^/]+\/[^/]+\/config\.yaml["']?/g; - const newConfigSource = `config_source: "{project-root}/${this.bmadFolderName}/${newModuleName}/config.yaml"`; + const configSourcePattern = /(config_source|main_config):\s*["']?\{project-root\}\/[^/]+\/[^/]+\/config\.yaml["']?/g; + const newConfigSource = `$1: "{project-root}/${this.bmadFolderName}/${newModuleName}/config.yaml"`; - const updatedYaml = yamlContent.replaceAll(configSourcePattern, newConfigSource); + const updatedContent = fileContent.replaceAll(configSourcePattern, newConfigSource); - if (updatedYaml !== yamlContent) { - await fs.writeFile(workflowYamlPath, updatedYaml, 'utf8'); - await prompts.log.message(` Updated config_source to: ${this.bmadFolderName}/${newModuleName}/config.yaml`); + if (updatedContent !== fileContent) { + await fs.writeFile(workflowPath, updatedContent, 'utf8'); + await prompts.log.message(` Updated workflow config to: ${this.bmadFolderName}/${newModuleName}/config.yaml`); } }