diff --git a/docs/_STYLE_GUIDE.md b/docs/_STYLE_GUIDE.md index c6e9eff58..99d686df6 100644 --- a/docs/_STYLE_GUIDE.md +++ b/docs/_STYLE_GUIDE.md @@ -59,13 +59,13 @@ Critical warnings only — data loss, security issues | 2 | Planning | Requirements — PRD or tech-spec *(required)* | ``` -**Commands:** +**Skills:** ```md -| Command | Agent | Purpose | +| Skill | Agent | Purpose | | ------------ | ------- | ------------------------------------ | -| `brainstorm` | Analyst | Brainstorm a new project | -| `prd` | PM | Create Product Requirements Document | +| `bmad-brainstorming` | Analyst | Brainstorm a new project | +| `bmad-create-prd` | PM | Create Product Requirements Document | ``` ## Folder Structure Blocks @@ -99,7 +99,7 @@ your-project/ 9. Step 2: [Second Major Task] 10. Step 3: [Third Major Task] 11. What You've Accomplished (summary + folder structure) -12. Quick Reference (commands table) +12. Quick Reference (skills table) 13. Common Questions (FAQ format) 14. Getting Help (community links) 15. Key Takeaways (tip admonition) @@ -111,7 +111,7 @@ your-project/ - [ ] "What You'll Learn" section present - [ ] Prerequisites in admonition - [ ] Quick Path TL;DR admonition at top -- [ ] Tables for phases, commands, agents +- [ ] Tables for phases, skills, agents - [ ] "What You've Accomplished" section present - [ ] Quick Reference table present - [ ] Common Questions section present @@ -243,7 +243,7 @@ your-project/ 1. Title + Hook 2. Items (## for each item) - Brief description (one sentence) - - **Commands:** or **Key Info:** as flat list + - **Skills:** or **Key Info:** as flat list 3. Universal/Shared (## section) (optional) ``` @@ -252,7 +252,7 @@ your-project/ ```text 1. Title + Hook (one sentence purpose) 2. Quick Facts (optional note admonition) - - Module, Command, Input, Output as list + - Module, Skill, Input, Output as list 3. Purpose/Overview (## section) 4. How to Invoke (code block) 5. Key Sections (## for each aspect) @@ -280,7 +280,7 @@ your-project/ - Diagram or table showing organization 3. Major Sections (## for each phase/category) - Items (### for each item) - - Standardized fields: Command, Agent, Input, Output, Description + - Standardized fields: Skill, Agent, Input, Output, Description 4. Next Steps (optional) ``` @@ -353,7 +353,7 @@ Only for BMad Method and Enterprise tracks. Quick Flow skips to implementation. ### Can I change my plan later? -Yes. The SM agent has a `correct-course` workflow for handling scope changes. +Yes. The SM agent has a `bmad-correct-course` workflow for handling scope changes. **Have a question not answered here?** [Open an issue](...) or ask in [Discord](...). ``` diff --git a/docs/explanation/brainstorming.md b/docs/explanation/brainstorming.md index 51aa80e22..68c35b3b1 100644 --- a/docs/explanation/brainstorming.md +++ b/docs/explanation/brainstorming.md @@ -9,7 +9,7 @@ Unlock your creativity through guided exploration. ## What is Brainstorming? -Run `brainstorming` and you've got a creative facilitator pulling ideas out of you - not generating them for you. The AI acts as coach and guide, using proven techniques to create conditions where your best thinking emerges. +Run `bmad-brainstorming` and you've got a creative facilitator pulling ideas out of you - not generating them for you. The AI acts as coach and guide, using proven techniques to create conditions where your best thinking emerges. **Good for:** diff --git a/docs/explanation/party-mode.md b/docs/explanation/party-mode.md index fe25f197d..68c52a292 100644 --- a/docs/explanation/party-mode.md +++ b/docs/explanation/party-mode.md @@ -9,7 +9,7 @@ Get all your AI agents in one conversation. ## What is Party Mode? -Run `party-mode` and you've got your whole AI team in one room - PM, Architect, Dev, UX Designer, whoever you need. BMad Master orchestrates, picking relevant agents per message. Agents respond in character, agree, disagree, and build on each other's ideas. +Run `bmad-party-mode` and you've got your whole AI team in one room - PM, Architect, Dev, UX Designer, whoever you need. BMad Master orchestrates, picking relevant agents per message. Agents respond in character, agree, disagree, and build on each other's ideas. The conversation continues as long as you want. Ask follow-ups, push back on answers, redirect the discussion - it's a real back-and-forth with your agents until you're done. diff --git a/docs/explanation/preventing-agent-conflicts.md b/docs/explanation/preventing-agent-conflicts.md index e611f1c3a..ffa9414d8 100644 --- a/docs/explanation/preventing-agent-conflicts.md +++ b/docs/explanation/preventing-agent-conflicts.md @@ -108,5 +108,5 @@ Common decisions that prevent conflicts: - Document decisions that cross epic boundaries - Focus on conflict-prone areas - Update architecture as you learn -- Use `correct-course` for significant changes +- Use `bmad-correct-course` for significant changes ::: diff --git a/docs/explanation/project-context.md b/docs/explanation/project-context.md index 6522b92a5..7b4eba4ed 100644 --- a/docs/explanation/project-context.md +++ b/docs/explanation/project-context.md @@ -21,12 +21,12 @@ The `project-context.md` file solves this by documenting what agents need to kno Every implementation workflow automatically loads `project-context.md` if it exists. The architect workflow also loads it to respect your technical preferences when designing the architecture. **Loaded by these workflows:** -- `create-architecture` — respects technical preferences during solutioning -- `create-story` — informs story creation with project patterns -- `dev-story` — guides implementation decisions -- `code-review` — validates against project standards -- `quick-dev` — applies patterns when implementing tech-specs -- `sprint-planning`, `retrospective`, `correct-course` — provides project-wide context +- `bmad-create-architecture` — respects technical preferences during solutioning +- `bmad-create-story` — informs story creation with project patterns +- `bmad-dev-story` — guides implementation decisions +- `bmad-code-review` — validates against project standards +- `bmad-quick-dev` — applies patterns when implementing tech-specs +- `bmad-sprint-planning`, `bmad-retrospective`, `bmad-correct-course` — provides project-wide context ## When to Create It @@ -34,10 +34,10 @@ The `project-context.md` file is useful at any stage of a project: | Scenario | When to Create | Purpose | |----------|----------------|---------| -| **New project, before architecture** | Manually, before `create-architecture` | Document your technical preferences so the architect respects them | -| **New project, after architecture** | Via `generate-project-context` or manually | Capture architecture decisions for implementation agents | -| **Existing project** | Via `generate-project-context` | Discover existing patterns so agents follow established conventions | -| **Quick Flow project** | Before or during `quick-dev` | Ensure quick implementation respects your patterns | +| **New project, before architecture** | Manually, before `bmad-create-architecture` | Document your technical preferences so the architect respects them | +| **New project, after architecture** | Via `bmad-generate-project-context` or manually | Capture architecture decisions for implementation agents | +| **Existing project** | Via `bmad-generate-project-context` | Discover existing patterns so agents follow established conventions | +| **Quick Flow project** | Before or during `bmad-quick-dev` | Ensure quick implementation respects your patterns | :::tip[Recommended] For new projects, create it manually before architecture if you have strong technical preferences. Otherwise, generate it after architecture to capture those decisions. @@ -107,20 +107,20 @@ Edit it with your technology stack and implementation rules. The architect and i ### Generate After Architecture -Run the `generate-project-context` workflow after completing your architecture: +Run the `bmad-generate-project-context` workflow after completing your architecture: ```bash -/bmad-bmm-generate-project-context +bmad-generate-project-context ``` This scans your architecture document and project files to generate a context file capturing the decisions made. ### Generate for Existing Projects -For existing projects, run `generate-project-context` to discover existing patterns: +For existing projects, run `bmad-generate-project-context` to discover existing patterns: ```bash -/bmad-bmm-generate-project-context +bmad-generate-project-context ``` The workflow analyzes your codebase to identify conventions, then generates a context file you can review and refine. @@ -150,7 +150,7 @@ The `project-context.md` file is a living document. Update it when: - Patterns evolve during implementation - You identify gaps from agent behavior -You can edit it manually at any time, or re-run `generate-project-context` to update it after significant changes. +You can edit it manually at any time, or re-run `bmad-generate-project-context` to update it after significant changes. :::note[File Location] The default location is `_bmad-output/project-context.md`. Workflows search for it there, and also check `**/project-context.md` anywhere in your project. diff --git a/docs/explanation/quick-flow.md b/docs/explanation/quick-flow.md index 6751feee0..53297a36d 100644 --- a/docs/explanation/quick-flow.md +++ b/docs/explanation/quick-flow.md @@ -5,7 +5,7 @@ sidebar: order: 1 --- -Skip the ceremony. Quick Flow takes you from idea to working code in two commands - no Product Brief, no PRD, no Architecture doc. +Skip the ceremony. Quick Flow takes you from idea to working code in two skills - no Product Brief, no PRD, no Architecture doc. ## When to Use It @@ -23,16 +23,16 @@ Skip the ceremony. Quick Flow takes you from idea to working code in two command - Anything where requirements are unclear or contested :::caution[Scope Creep] -If you start a Quick Flow and realize the scope is bigger than expected, `quick-dev` will detect this and offer to escalate. You can switch to a full PRD workflow at any point without losing your work. +If you start a Quick Flow and realize the scope is bigger than expected, `bmad-quick-dev` will detect this and offer to escalate. You can switch to a full PRD workflow at any point without losing your work. ::: ## How It Works -Quick Flow has two commands, each backed by a structured workflow. You can run them together or independently. +Quick Flow has two skills, each backed by a structured workflow. You can run them together or independently. ### quick-spec: Plan -Run `quick-spec` and Barry (the Quick Flow agent) walks you through a conversational discovery process: +Run `bmad-quick-spec` and Barry (the Quick Flow agent) walks you through a conversational discovery process: 1. **Understand** - You describe what you want to build. Barry scans the codebase to ask informed questions, then captures a problem statement, solution approach, and scope boundaries. 2. **Investigate** - Barry reads relevant files, maps code patterns, identifies files to modify, and documents the technical context. @@ -43,15 +43,15 @@ The output is a `tech-spec-{slug}.md` file saved to your project's implementatio ### quick-dev: Build -Run `quick-dev` and Barry implements the work. It operates in two modes: +Run `bmad-quick-dev` and Barry implements the work. It operates in two modes: - **Tech-spec mode** - Point it at a spec file (`quick-dev tech-spec-auth.md`) and it executes every task in order, writes tests, and verifies acceptance criteria. - **Direct mode** - Give it instructions directly (`quick-dev "refactor the auth middleware"`) and it gathers context, builds a mental plan, and executes. -After implementation, `quick-dev` runs a self-check audit against all tasks and acceptance criteria, then triggers an adversarial code review of the diff. Findings are presented for you to resolve before wrapping up. +After implementation, `bmad-quick-dev` runs a self-check audit against all tasks and acceptance criteria, then triggers an adversarial code review of the diff. Findings are presented for you to resolve before wrapping up. :::tip[Fresh Context] -For best results, run `quick-dev` in a new conversation after finishing `quick-spec`. This gives the implementation agent clean context focused solely on building. +For best results, run `bmad-quick-dev` in a new conversation after finishing `bmad-quick-spec`. This gives the implementation agent clean context focused solely on building. ::: ## What Quick Flow Skips @@ -65,9 +65,9 @@ The full BMad Method produces a Product Brief, PRD, Architecture doc, and Epic/S ## Escalating to Full BMad Method -Quick Flow includes built-in guardrails for scope detection. When you run `quick-dev` with a direct request, it evaluates signals like multi-component mentions, system-level language, and uncertainty about approach. If it detects the work is bigger than a quick flow: +Quick Flow includes built-in guardrails for scope detection. When you run `bmad-quick-dev` with a direct request, it evaluates signals like multi-component mentions, system-level language, and uncertainty about approach. If it detects the work is bigger than a quick flow: -- **Light escalation** - Recommends running `quick-spec` first to create a plan +- **Light escalation** - Recommends running `bmad-quick-spec` first to create a plan - **Heavy escalation** - Recommends switching to the full BMad Method PRD process You can also escalate manually at any time. Your tech-spec work carries forward - it becomes input for the broader planning process rather than being discarded. diff --git a/docs/how-to/established-projects.md b/docs/how-to/established-projects.md index cc36e0f90..3d789fb61 100644 --- a/docs/how-to/established-projects.md +++ b/docs/how-to/established-projects.md @@ -32,7 +32,7 @@ Generate `project-context.md` to capture your existing codebase patterns and con Run the generate project context workflow: ```bash -/bmad-bmm-generate-project-context +bmad-generate-project-context ``` This scans your codebase to identify: @@ -55,22 +55,22 @@ Your `docs/` folder should contain succinct, well-organized documentation that a - Architecture - Any other relevant project information -For complex projects, consider using the `document-project` workflow. It offers runtime variants that will scan your entire project and document its actual current state. +For complex projects, consider using the `bmad-document-project` workflow. It offers runtime variants that will scan your entire project and document its actual current state. ## Step 3: Get Help ### BMad-Help: Your Starting Point -**Run `/bmad-help` anytime you're unsure what to do next.** This intelligent guide: +**Run `bmad-help` anytime you're unsure what to do next.** This intelligent guide: - Inspects your project to see what's already been done - Shows options based on your installed modules - Understands natural language queries ``` -/bmad-help I have an existing Rails app, where should I start? -/bmad-help What's the difference between quick-flow and full method? -/bmad-help Show me what workflows are available +bmad-help I have an existing Rails app, where should I start? +bmad-help What's the difference between quick-flow and full method? +bmad-help Show me what workflows are available ``` BMad-Help also **automatically runs at the end of every workflow**, providing clear guidance on exactly what to do next. @@ -81,7 +81,7 @@ You have two primary options depending on the scope of changes: | Scope | Recommended Approach | | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | -| **Small updates or additions** | Use `quick-flow-solo-dev` to create a tech-spec and implement the change. The full four-phase BMad Method is likely overkill. | +| **Small updates or additions** | Use `bmad-quick-flow-solo-dev` to create a tech-spec and implement the change. The full four-phase BMad Method is likely overkill. | | **Major changes or additions** | Start with the BMad Method, applying as much or as little rigor as needed. | ### During PRD Creation diff --git a/docs/how-to/get-answers-about-bmad.md b/docs/how-to/get-answers-about-bmad.md index edefdeacb..87cd057ee 100644 --- a/docs/how-to/get-answers-about-bmad.md +++ b/docs/how-to/get-answers-about-bmad.md @@ -18,7 +18,7 @@ BMad-Help is more than a lookup tool — it: ### How to Use BMad-Help -Run it with just the slash command: +Run it with just the skill name: ``` /bmad-help @@ -81,7 +81,7 @@ https://bmad-code-org.github.io/BMAD-METHOD/llms-full.txt :::note[Example] **Q:** "Tell me the fastest way to build something with BMad" -**A:** Use Quick Flow: Run `quick-spec` to write a technical specification, then `quick-dev` to implement it—skipping the full planning phases. +**A:** Use Quick Flow: Run `bmad-quick-spec` to write a technical specification, then `bmad-quick-dev` to implement it—skipping the full planning phases. ::: ## What You Get diff --git a/docs/how-to/install-bmad.md b/docs/how-to/install-bmad.md index 177c2c884..3c0ca61d1 100644 --- a/docs/how-to/install-bmad.md +++ b/docs/how-to/install-bmad.md @@ -51,7 +51,11 @@ Pick which AI tools you use: - Cursor - Others -Each tool has its own way of integrating commands. The installer creates tiny prompt files to activate workflows and agents — it just puts them where your tool expects to find them. +Each tool has its own way of integrating skills. The installer creates tiny prompt files to activate workflows and agents — it just puts them where your tool expects to find them. + +:::note[Enabling Skills] +Some platforms require skills to be explicitly enabled in settings before they appear. If you install BMad and don't see the skills, check your platform's settings or ask your AI assistant how to enable skills. +::: ### 4. Choose Modules @@ -71,13 +75,19 @@ your-project/ │ ├── core/ # Required core module │ └── ... ├── _bmad-output/ # Generated artifacts -├── .claude/ # Claude Code commands (if using Claude Code) -└── .kiro/ # Kiro steering files (if using Kiro) +├── .claude/ # Claude Code skills (if using Claude Code) +│ └── skills/ +│ ├── bmad-help/ +│ ├── bmad-persona/ +│ └── ... +└── .cursor/ # Cursor skills (if using Cursor) + └── skills/ + └── ... ``` ## Verify Installation -Run `/bmad-help` to verify everything works and see what to do next. +Run `bmad-help` to verify everything works and see what to do next. **BMad-Help is your intelligent guide** that will: - Confirm your installation is working @@ -86,8 +96,8 @@ Run `/bmad-help` to verify everything works and see what to do next. You can also ask it questions: ``` -/bmad-help I just installed, what should I do first? -/bmad-help What are my options for a SaaS project? +bmad-help I just installed, what should I do first? +bmad-help What are my options for a SaaS project? ``` ## Troubleshooting diff --git a/docs/how-to/project-context.md b/docs/how-to/project-context.md index 105906098..9196733c8 100644 --- a/docs/how-to/project-context.md +++ b/docs/how-to/project-context.md @@ -77,7 +77,7 @@ sections_completed: ['technology_stack', 'critical_rules'] Run the workflow in a fresh chat: ```bash -/bmad-bmm-generate-project-context +bmad-generate-project-context ``` The workflow scans your architecture document and project files to generate a context file capturing the decisions made. @@ -87,7 +87,7 @@ The workflow scans your architecture document and project files to generate a co For existing projects, run: ```bash -/bmad-bmm-generate-project-context +bmad-generate-project-context ``` The workflow analyzes your codebase to identify conventions, then generates a context file you can review and refine. diff --git a/docs/how-to/quick-fixes.md b/docs/how-to/quick-fixes.md index 76ee5ebe0..d88d7e9d0 100644 --- a/docs/how-to/quick-fixes.md +++ b/docs/how-to/quick-fixes.md @@ -30,18 +30,18 @@ If you are unsure, start with the DEV agent. You can always escalate to Quick Fl ## Steps -### 1. Load the DEV Agent +### 1. Invoke the DEV Agent -Start a **fresh chat** in your AI IDE and load the DEV agent with its slash command: +Start a **fresh chat** in your AI IDE and invoke the DEV agent skill: ```text -/bmad-agent-bmm-dev +bmad-dev ``` -This loads the agent's persona and capabilities into the session. If you decide you need Quick Flow instead, load the **Quick Flow Solo Dev** agent in a fresh chat: +This loads the agent's persona and capabilities into the session. If you decide you need Quick Flow instead, invoke the **Quick Flow Solo Dev** agent skill in a fresh chat: ```text -/bmad-agent-bmm-quick-flow-solo-dev +bmad-quick-flow-solo-dev ``` Once the Solo Dev agent is loaded, describe your change and ask it to create a **quick-spec**. The agent drafts a lightweight spec capturing what you want to change and how. After you approve the quick-spec, tell the agent to start the **Quick Flow dev cycle** -- it will implement the change, run tests, and perform a self-review, all guided by the spec you just approved. diff --git a/docs/how-to/shard-large-documents.md b/docs/how-to/shard-large-documents.md index b10c64fb8..0edac1483 100644 --- a/docs/how-to/shard-large-documents.md +++ b/docs/how-to/shard-large-documents.md @@ -5,7 +5,7 @@ sidebar: order: 8 --- -Use the `shard-doc` tool if you need to split large markdown files into smaller, organized files for better context management. +Use the `bmad-shard-doc` tool if you need to split large markdown files into smaller, organized files for better context management. :::caution[Deprecated] This is no longer recommended, and soon with updated workflows and most major LLMs and tools supporting subprocesses this will be unnecessary. diff --git a/docs/how-to/upgrade-to-v6.md b/docs/how-to/upgrade-to-v6.md index 882640a69..e01d95f00 100644 --- a/docs/how-to/upgrade-to-v6.md +++ b/docs/how-to/upgrade-to-v6.md @@ -33,12 +33,15 @@ When v4 is detected, you can: If you named your bmad method folder something else - you will need to manually remove the folder yourself. -### 3. Clean Up IDE Commands +### 3. Clean Up IDE Skills -Manually remove legacy v4 IDE commands - for example if you have claude, look for any nested folders that start with bmad and remove them: +Manually remove legacy v4 IDE commands/skills - for example if you have Claude Code, look for any nested folders that start with bmad and remove them: -- `.claude/commands/BMad/agents` -- `.claude/commands/BMad/tasks` +- `.claude/commands/` + +The new v6 skills are installed to: + +- `.claude/skills/` ### 4. Migrate Planning Artifacts @@ -58,7 +61,7 @@ If you have stories created or implemented: 1. Complete the v6 installation 2. Place `epics.md` or `epics/epic*.md` in `_bmad-output/planning-artifacts/` -3. Run the Scrum Master's `sprint-planning` workflow +3. Run the Scrum Master's `bmad-sprint-planning` workflow 4. Tell the SM which epics/stories are already complete ## What You Get diff --git a/docs/index.md b/docs/index.md index 8d414bbbe..acbb7ad96 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,7 +19,7 @@ The fastest way to understand BMad is to try it. - **[Workflow Map](./reference/workflow-map.md)** — Visual overview of BMM phases, workflows, and context management :::tip[Just Want to Dive In?] -Install BMad and run `/bmad-help` — it will guide you through everything based on your project and installed modules. +Install BMad and use the `bmad-help` skill — it will guide you through everything based on your project and installed modules. ::: ## How to Use These Docs diff --git a/docs/reference/agents.md b/docs/reference/agents.md index 779f0b96e..be7ab8ecb 100644 --- a/docs/reference/agents.md +++ b/docs/reference/agents.md @@ -1,28 +1,28 @@ --- title: Agents -description: Default BMM agents with their menu triggers and primary workflows +description: Default BMM agents with their skill IDs, menu triggers, and primary workflows sidebar: order: 2 --- ## Default Agents -This page lists the default BMM (Agile suite) agents that install with BMad Method, along with their menu triggers and primary workflows. +This page lists the default BMM (Agile suite) agents that install with BMad Method, along with their skill IDs, menu triggers, and primary workflows. Each agent is invoked as a skill. ## Notes +- Each agent is available as a skill, generated by the installer. The skill ID (e.g., `bmad-dev`) is used to invoke the agent. - Triggers are the short menu codes (e.g., `CP`) and fuzzy matches shown in each agent menu. -- Slash commands are generated separately. See [Commands](./commands.md) for the slash command list and where they are defined. - QA (Quinn) is the lightweight test automation agent in BMM. The full Test Architect (TEA) lives in its own module. -| Agent | Triggers | Primary workflows | -| --------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------- | -| Analyst (Mary) | `BP`, `RS`, `CB`, `DP` | Brainstorm Project, Research, Create Brief, Document Project | -| Product Manager (John) | `CP`, `VP`, `EP`, `CE`, `IR`, `CC` | Create/Validate/Edit PRD, Create Epics and Stories, Implementation Readiness, Correct Course | -| Architect (Winston) | `CA`, `IR` | Create Architecture, Implementation Readiness | -| Scrum Master (Bob) | `SP`, `CS`, `ER`, `CC` | Sprint Planning, Create Story, Epic Retrospective, Correct Course | -| Developer (Amelia) | `DS`, `CR` | Dev Story, Code Review | -| QA Engineer (Quinn) | `QA` | Automate (generate tests for existing features) | -| Quick Flow Solo Dev (Barry) | `QS`, `QD`, `CR` | Quick Spec, Quick Dev, Code Review | -| UX Designer (Sally) | `CU` | Create UX Design | -| Technical Writer (Paige) | `DP`, `WD`, `US`, `MG`, `VD`, `EC` | Document Project, Write Document, Update Standards, Mermaid Generate, Validate Doc, Explain Concept | +| Agent | Skill ID | Triggers | Primary workflows | +| --------------------------- | -------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------- | +| Analyst (Mary) | `bmad-analyst` | `BP`, `RS`, `CB`, `DP` | Brainstorm Project, Research, Create Brief, Document Project | +| Product Manager (John) | `bmad-pm` | `CP`, `VP`, `EP`, `CE`, `IR`, `CC` | Create/Validate/Edit PRD, Create Epics and Stories, Implementation Readiness, Correct Course | +| Architect (Winston) | `bmad-architect` | `CA`, `IR` | Create Architecture, Implementation Readiness | +| Scrum Master (Bob) | `bmad-sm` | `SP`, `CS`, `ER`, `CC` | Sprint Planning, Create Story, Epic Retrospective, Correct Course | +| Developer (Amelia) | `bmad-dev` | `DS`, `CR` | Dev Story, Code Review | +| QA Engineer (Quinn) | `bmad-qa` | `QA` | Automate (generate tests for existing features) | +| Quick Flow Solo Dev (Barry) | `bmad-master` | `QS`, `QD`, `CR` | Quick Spec, Quick Dev, Code Review | +| UX Designer (Sally) | `bmad-ux-designer` | `CU` | Create UX Design | +| Technical Writer (Paige) | `bmad-tech-writer` | `DP`, `WD`, `US`, `MG`, `VD`, `EC` | Document Project, Write Document, Update Standards, Mermaid Generate, Validate Doc, Explain Concept | diff --git a/docs/reference/commands.md b/docs/reference/commands.md index af4f1f496..c61b236a7 100644 --- a/docs/reference/commands.md +++ b/docs/reference/commands.md @@ -1,111 +1,113 @@ --- -title: Commands -description: Reference for BMad slash commands — what they are, how they work, and where to find them. +title: Skills +description: Reference for BMad skills — what they are, how they work, and where to find them. sidebar: order: 3 --- -Slash commands are pre-built prompts that load agents, run workflows, or execute tasks inside your IDE. The BMad installer generates them from your installed modules at install time. If you later add, remove, or change modules, re-run the installer to keep commands in sync (see [Troubleshooting](#troubleshooting)). +Skills are pre-built prompts that load agents, run workflows, or execute tasks inside your IDE. The BMad installer generates them from your installed modules at install time. If you later add, remove, or change modules, re-run the installer to keep skills in sync (see [Troubleshooting](#troubleshooting)). -## Commands vs. Agent Menu Triggers +## Skills vs. Agent Menu Triggers BMad offers two ways to start work, and they serve different purposes. | Mechanism | How you invoke it | What happens | | --- | --- | --- | -| **Slash command** | Type `/bmad-...` in your IDE | Directly loads an agent, runs a workflow, or executes a task | +| **Skill** | Type the skill name (e.g. `bmad-help`) in your IDE | Directly loads an agent, runs a workflow, or executes a task | | **Agent menu trigger** | Load an agent first, then type a short code (e.g. `DS`) | The agent interprets the code and starts the matching workflow while staying in character | -Agent menu triggers require an active agent session. Use slash commands when you know which workflow you want. Use triggers when you are already working with an agent and want to switch tasks without leaving the conversation. +Agent menu triggers require an active agent session. Use skills when you know which workflow you want. Use triggers when you are already working with an agent and want to switch tasks without leaving the conversation. -## How Commands Are Generated +## How Skills Are Generated -When you run `npx bmad-method install`, the installer reads the manifests for every selected module and writes one command file per agent, workflow, task, and tool. Each file is a short markdown prompt that instructs the AI to load the corresponding source file and follow its instructions. +When you run `npx bmad-method install`, the installer reads the manifests for every selected module and writes one skill per agent, workflow, task, and tool. Each skill is a directory containing a `SKILL.md` file that instructs the AI to load the corresponding source file and follow its instructions. -The installer uses templates for each command type: +The installer uses templates for each skill type: -| Command type | What the generated file does | +| Skill 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 | -| **Task command** | Loads a standalone task file and follows its instructions | -| **Tool command** | Loads a standalone tool file and follows its instructions | +| **Workflow skill** | Loads the workflow engine (`workflow.xml`) and passes the workflow config | +| **Task skill** | Loads a standalone task file and follows its instructions | +| **Tool skill** | Loads a standalone tool file and follows its instructions | :::note[Re-running the installer] -If you add or remove modules, run the installer again. It regenerates all command files to match your current module selection. +If you add or remove modules, run the installer again. It regenerates all skill files to match your current module selection. ::: -## Where Command Files Live +## Where Skill Files Live -The installer writes command files into an IDE-specific directory inside your project. The exact path depends on which IDE you selected during installation. +The installer writes skill files into an IDE-specific directory inside your project. The exact path depends on which IDE you selected during installation. -| IDE / CLI | Command directory | +| IDE / CLI | Skills directory | | --- | --- | -| Claude Code | `.claude/commands/` | -| Cursor | `.cursor/commands/` | -| Windsurf | `.windsurf/workflows/` | +| Claude Code | `.claude/skills/` | +| Cursor | `.cursor/skills/` | +| Windsurf | `.windsurf/skills/` | | Other IDEs | See the installer output for the target path | -All IDEs receive a flat set of command files in their command directory. For example, a Claude Code installation looks like: +Each skill is a directory containing a `SKILL.md` file. For example, a Claude Code installation looks like: ```text -.claude/commands/ -├── bmad-agent-bmm-dev.md -├── bmad-agent-bmm-pm.md -├── bmad-bmm-create-prd.md -├── bmad-editorial-review-prose.md -├── bmad-help.md +.claude/skills/ +├── bmad-help/ +│ └── SKILL.md +├── bmad-create-prd/ +│ └── SKILL.md +├── bmad-dev/ +│ └── SKILL.md └── ... ``` -The filename determines the slash command name in your IDE. For example, the file `bmad-agent-bmm-dev.md` registers the command `/bmad-agent-bmm-dev`. +The directory name determines the skill name in your IDE. For example, the directory `bmad-dev/` registers the skill `bmad-dev`. -## How to Discover Your Commands +## How to Discover Your Skills -Type `/bmad` in your IDE and use autocomplete to browse available commands. +Type the skill name in your IDE to invoke it. Some platforms require you to enable skills in settings before they appear. -Run `/bmad-help` for context-aware guidance on your next step. +Run `bmad-help` for context-aware guidance on your next step. :::tip[Quick discovery] -The generated command folders in your project are the canonical list. Open them in your file explorer to see every command with its description. +The generated skill directories in your project are the canonical list. Open them in your file explorer to see every skill with its description. ::: -## Command Categories +## Skill Categories -### Agent Commands +### Agent Skills -Agent commands load a specialized AI persona with a defined role, communication style, and menu of workflows. Once loaded, the agent stays in character and responds to menu triggers. +Agent skills load a specialized AI persona with a defined role, communication style, and menu of workflows. Once loaded, the agent stays in character and responds to menu triggers. -| Example command | Agent | Role | +| Example skill | Agent | Role | | --- | --- | --- | -| `/bmad-agent-bmm-dev` | Amelia (Developer) | Implements stories with strict adherence to specs | -| `/bmad-agent-bmm-pm` | John (Product Manager) | Creates and validates PRDs | -| `/bmad-agent-bmm-architect` | Winston (Architect) | Designs system architecture | -| `/bmad-agent-bmm-sm` | Bob (Scrum Master) | Manages sprints and stories | +| `bmad-dev` | Amelia (Developer) | Implements stories with strict adherence to specs | +| `bmad-pm` | John (Product Manager) | Creates and validates PRDs | +| `bmad-architect` | Winston (Architect) | Designs system architecture | +| `bmad-sm` | Bob (Scrum Master) | Manages sprints and stories | See [Agents](./agents.md) for the full list of default agents and their triggers. -### Workflow Commands +### Workflow Skills -Workflow commands run a structured, multi-step process without loading an agent persona first. They load the workflow engine and pass a specific workflow configuration. +Workflow skills run a structured, multi-step process without loading an agent persona first. They load the workflow engine and pass a specific workflow configuration. -| Example command | Purpose | +| Example skill | Purpose | | --- | --- | -| `/bmad-bmm-create-prd` | Create a Product Requirements Document | -| `/bmad-bmm-create-architecture` | Design system architecture | -| `/bmad-bmm-dev-story` | Implement a story | -| `/bmad-bmm-code-review` | Run a code review | -| `/bmad-bmm-quick-spec` | Define an ad-hoc change (Quick Flow) | +| `bmad-create-prd` | Create a Product Requirements Document | +| `bmad-create-architecture` | Design system architecture | +| `bmad-create-epics-and-stories` | Create epics and stories | +| `bmad-dev-story` | Implement a story | +| `bmad-code-review` | Run a code review | +| `bmad-quick-spec` | Define an ad-hoc change (Quick Flow) | See [Workflow Map](./workflow-map.md) for the complete workflow reference organized by phase. -### Task and Tool Commands +### Task and Tool Skills Tasks and tools are standalone operations that do not require an agent or workflow context. #### BMad-Help: Your Intelligent Guide -**`/bmad-help`** is your primary interface for discovering what to do next. It's not just a lookup tool — it's an intelligent assistant that: +**`bmad-help`** is your primary interface for discovering what to do next. It's not just a lookup tool — it's an intelligent assistant that: - **Inspects your project** to see what's already been done - **Understands natural language queries** — ask questions in plain English @@ -116,36 +118,28 @@ Tasks and tools are standalone operations that do not require an agent or workfl **Examples:** ``` -/bmad-help -/bmad-help I have a SaaS idea and know all the features. Where do I start? -/bmad-help What are my options for UX design? -/bmad-help I'm stuck on the PRD workflow +bmad-help +bmad-help I have a SaaS idea and know all the features. Where do I start? +bmad-help What are my options for UX design? +bmad-help I'm stuck on the PRD workflow ``` #### Other Tasks and Tools -| Example command | Purpose | +| Example skill | Purpose | | --- | --- | -| `/bmad-shard-doc` | Split a large markdown file into smaller sections | -| `/bmad-index-docs` | Index project documentation | -| `/bmad-editorial-review-prose` | Review document prose quality | +| `bmad-shard-doc` | Split a large markdown file into smaller sections | +| `bmad-index-docs` | Index project documentation | +| `bmad-editorial-review-prose` | Review document prose quality | ## Naming Convention -Command names follow a predictable pattern. - -| Pattern | Meaning | Example | -| --- | --- | --- | -| `bmad-agent--` | Agent launcher | `bmad-agent-bmm-dev` | -| `bmad--` | Workflow command | `bmad-bmm-create-prd` | -| `bmad-` | Core task or tool | `bmad-help` | - -Module codes: `bmm` (Agile suite), `bmb` (Builder), `tea` (Test Architect), `cis` (Creative Intelligence), `gds` (Game Dev Studio). See [Modules](./modules.md) for descriptions. +All skills use the `bmad-` prefix followed by a descriptive name (e.g., `bmad-dev`, `bmad-create-prd`, `bmad-help`). See [Modules](./modules.md) for available modules. ## Troubleshooting -**Commands not appearing after install.** Restart your IDE or reload the window. Some IDEs cache the command list and require a refresh to pick up new files. +**Skills not appearing after install.** Some platforms require skills to be explicitly enabled in settings. Check your IDE's documentation or ask your AI assistant how to enable skills. You may also need to restart your IDE or reload the window. -**Expected commands are missing.** The installer only generates commands for modules you selected. Run `npx bmad-method install` again and verify your module selection. Check that the command files exist in the expected directory. +**Expected skills are missing.** The installer only generates skills for modules you selected. Run `npx bmad-method install` again and verify your module selection. Check that the skill files exist in the expected directory. -**Commands from a removed module still appear.** The installer does not delete old command files automatically. Remove the stale files from your IDE's command directory, or delete the entire command directory and re-run the installer for a clean set. +**Skills from a removed module still appear.** The installer does not delete old skill files automatically. Remove the stale directories from your IDE's skills directory, or delete the entire skills directory and re-run the installer for a clean set. diff --git a/docs/reference/testing.md b/docs/reference/testing.md index 4063ddfe1..c8a73747f 100644 --- a/docs/reference/testing.md +++ b/docs/reference/testing.md @@ -26,7 +26,7 @@ Most projects should start with Quinn. If you later need test strategy, quality Quinn is the built-in QA agent in the BMM (Agile suite) module. It generates working tests quickly using your project's existing test framework -- no configuration or additional installation required. -**Trigger:** `QA` or `bmad-bmm-qa-automate` +**Trigger:** `QA` or `bmad-qa-generate-e2e-tests` ### What Quinn Does diff --git a/docs/reference/workflow-map.md b/docs/reference/workflow-map.md index 05885a5e1..612757925 100644 --- a/docs/reference/workflow-map.md +++ b/docs/reference/workflow-map.md @@ -9,9 +9,9 @@ The BMad Method (BMM) is a module in the BMad Ecosystem, targeted at following t The rationale and concepts come from agile methodologies that have been used across the industry with great success as a mental framework. -If at any time you are unsure what to do, the `/bmad-help` command will help you stay on track or know what to do next. You can always refer to this for reference also - but /bmad-help is fully interactive and much quicker if you have already installed the BMad Method. Additionally, if you are using different modules that have extended the BMad Method or added other complementary non-extension modules - the /bmad-help evolves to know all that is available to give you the best in-the-moment advice. +If at any time you are unsure what to do, the `bmad-help` skill will help you stay on track or know what to do next. You can always refer to this for reference also - but `bmad-help` is fully interactive and much quicker if you have already installed the BMad Method. Additionally, if you are using different modules that have extended the BMad Method or added other complementary non-extension modules - `bmad-help` evolves to know all that is available to give you the best in-the-moment advice. -Final important note: Every workflow below can be run directly with your tool of choice via slash command or by loading an agent first and using the entry from the agents menu. +Final important note: Every workflow below can be run directly with your tool of choice via skill or by loading an agent first and using the entry from the agents menu. @@ -26,8 +26,8 @@ Explore the problem space and validate ideas before committing to planning. | Workflow | Purpose | Produces | | ------------------------------- | -------------------------------------------------------------------------- | ------------------------- | | `bmad-brainstorming` | Brainstorm Project Ideas with guided facilitation of a brainstorming coach | `brainstorming-report.md` | -| `bmad-bmm-research` | Validate market, technical, or domain assumptions | Research findings | -| `bmad-bmm-create-product-brief` | Capture strategic vision | `product-brief.md` | +| `bmad-domain-research`, `bmad-market-research`, `bmad-technical-research` | Validate market, technical, or domain assumptions | Research findings | +| `bmad-create-product-brief` | Capture strategic vision | `product-brief.md` | ## Phase 2: Planning @@ -35,8 +35,8 @@ Define what to build and for whom. | Workflow | Purpose | Produces | | --------------------------- | ---------------------------------------- | ------------ | -| `bmad-bmm-create-prd` | Define requirements (FRs/NFRs) | `PRD.md` | -| `bmad-bmm-create-ux-design` | Design user experience (when UX matters) | `ux-spec.md` | +| `bmad-create-prd` | Define requirements (FRs/NFRs) | `PRD.md` | +| `bmad-create-ux-design` | Design user experience (when UX matters) | `ux-spec.md` | ## Phase 3: Solutioning @@ -44,9 +44,9 @@ Decide how to build it and break work into stories. | Workflow | Purpose | Produces | | ----------------------------------------- | ------------------------------------------ | --------------------------- | -| `bmad-bmm-create-architecture` | Make technical decisions explicit | `architecture.md` with ADRs | -| `bmad-bmm-create-epics-and-stories` | Break requirements into implementable work | Epic files with stories | -| `bmad-bmm-check-implementation-readiness` | Gate check before implementation | PASS/CONCERNS/FAIL decision | +| `bmad-create-architecture` | Make technical decisions explicit | `architecture.md` with ADRs | +| `bmad-create-epics-and-stories` | Break requirements into implementable work | Epic files with stories | +| `bmad-check-implementation-readiness` | Gate check before implementation | PASS/CONCERNS/FAIL decision | ## Phase 4: Implementation @@ -54,13 +54,13 @@ Build it, one story at a time. Coming soon, full phase 4 automation! | Workflow | Purpose | Produces | | -------------------------- | ------------------------------------------------------------------------ | -------------------------------- | -| `bmad-bmm-sprint-planning` | Initialize tracking (once per project to sequence the dev cycle) | `sprint-status.yaml` | -| `bmad-bmm-create-story` | Prepare next story for implementation | `story-[slug].md` | -| `bmad-bmm-dev-story` | Implement the story | Working code + tests | -| `bmad-bmm-code-review` | Validate implementation quality | Approved or changes requested | -| `bmad-bmm-correct-course` | Handle significant mid-sprint changes | Updated plan or re-routing | -| `bmad-bmm-automate` | Generate tests for existing features - Use after a full epic is complete | End to End UI Focused Test suite | -| `bmad-bmm-retrospective` | Review after epic completion | Lessons learned | +| `bmad-sprint-planning` | Initialize tracking (once per project to sequence the dev cycle) | `sprint-status.yaml` | +| `bmad-create-story` | Prepare next story for implementation | `story-[slug].md` | +| `bmad-dev-story` | Implement the story | Working code + tests | +| `bmad-code-review` | Validate implementation quality | Approved or changes requested | +| `bmad-correct-course` | Handle significant mid-sprint changes | Updated plan or re-routing | +| `bmad-sprint-status` | Track sprint progress and story status | Sprint status update | +| `bmad-retrospective` | Review after epic completion | Lessons learned | ## Quick Flow (Parallel Track) @@ -68,8 +68,8 @@ Skip phases 1-3 for small, well-understood work. | Workflow | Purpose | Produces | | --------------------- | ------------------------------------------ | --------------------------------------------- | -| `bmad-bmm-quick-spec` | Define an ad-hoc change | `tech-spec.md` (story file for small changes) | -| `bmad-bmm-quick-dev` | Implement from spec or direct instructions | Working code + tests | +| `bmad-quick-spec` | Define an ad-hoc change | `tech-spec.md` (story file for small changes) | +| `bmad-quick-dev` | Implement from spec or direct instructions | Working code + tests | ## Context Management @@ -84,6 +84,6 @@ Create `project-context.md` to ensure AI agents follow your project's rules and **How to create it:** - **Manually** — Create `_bmad-output/project-context.md` with your technology stack and implementation rules -- **Generate it** — Run `/bmad-bmm-generate-project-context` to auto-generate from your architecture or codebase +- **Generate it** — Run `bmad-generate-project-context` to auto-generate from your architecture or codebase [**Learn more about project-context.md**](../explanation/project-context.md) diff --git a/docs/tutorials/getting-started.md b/docs/tutorials/getting-started.md index b7aa02dfd..1880ed448 100644 --- a/docs/tutorials/getting-started.md +++ b/docs/tutorials/getting-started.md @@ -37,16 +37,16 @@ Build software faster using AI-powered workflows with specialized agents that gu ### How to Use BMad-Help -Run it in your AI IDE with just the slash command: +Run it in your AI IDE by invoking the skill: ``` -/bmad-help +bmad-help ``` Or combine it with a question for context-aware guidance: ``` -/bmad-help I have an idea for a SaaS product, I already know all the features I want. where do I get started? +bmad-help I have an idea for a SaaS product, I already know all the features I want. where do I get started? ``` BMad-Help will respond with: @@ -112,7 +112,7 @@ BMad-Help will detect what you've completed and recommend exactly what to do nex ::: :::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). +Each workflow has a **skill** you invoke in your IDE (e.g., `/bmad-create-prd`). Running a workflow skill automatically loads the appropriate agent — you don't need to load agents separately. You can also invoke an agent directly for general conversation (e.g., `/bmad-pm` for the PM agent). ::: :::caution[Fresh Chats] @@ -126,35 +126,35 @@ Work through phases 1-3. **Use fresh chats for each workflow.** :::tip[Project Context (Optional)] Before starting, consider creating `project-context.md` to document your technical preferences and implementation rules. This ensures all AI agents follow your conventions throughout the project. -Create it manually at `_bmad-output/project-context.md` or generate it after architecture using `/bmad-bmm-generate-project-context`. [Learn more](../explanation/project-context.md). +Create it manually at `_bmad-output/project-context.md` or generate it after architecture using `/bmad-generate-project-context`. [Learn more](../explanation/project-context.md). ::: ### 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 +- **research** (`/bmad-research`) — Market and technical research +- **create-product-brief** (`/bmad-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. Invoke the **PM agent** (`/bmad-pm`) in a new chat +2. Run the `bmad-create-prd` workflow (`/bmad-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 `bmad-quick-spec` workflow (`/bmad-quick-spec`) 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, invoke the **UX-Designer agent** (`/bmad-ux-designer`) and run the UX design workflow (`/bmad-create-ux-design`) 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. Invoke the **Architect agent** (`/bmad-architect`) in a new chat +2. Run `bmad-create-architecture` (`/bmad-create-architecture`) 3. Output: Architecture document with technical decisions **Create Epics and Stories** @@ -163,13 +163,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. Invoke the **PM agent** (`/bmad-pm`) in a new chat +2. Run `bmad-create-epics-and-stories` (`/bmad-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. Invoke the **Architect agent** (`/bmad-architect`) in a new chat +2. Run `bmad-check-implementation-readiness` (`/bmad-check-implementation-readiness`) 3. Validates cohesion across all planning documents ## Step 2: Build Your Project @@ -178,7 +178,7 @@ 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. +Invoke the **SM agent** (`/bmad-sm`) and run `bmad-sprint-planning` (`/bmad-sprint-planning`). This creates `sprint-status.yaml` to track all epics and stories. ### The Build Cycle @@ -186,11 +186,11 @@ 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)* | +| 1 | SM | `bmad-create-story` | `/bmad-create-story` | Create story file from epic | +| 2 | DEV | `bmad-dev-story` | `/bmad-dev-story` | Implement the story | +| 3 | DEV | `bmad-code-review` | `/bmad-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, invoke the **SM agent** (`/bmad-sm`) and run `bmad-retrospective` (`/bmad-retrospective`). ## What You've Accomplished @@ -221,16 +221,16 @@ your-project/ | Workflow | Command | Agent | Purpose | | ------------------------------------- | ------------------------------------------ | --------- | ----------------------------------------------- | -| **`help`** ⭐ | `/bmad-help` | Any | **Your intelligent guide — ask anything!** | -| `prd` | `/bmad-bmm-create-prd` | PM | Create Product Requirements Document | -| `create-architecture` | `/bmad-bmm-create-architecture` | Architect | Create architecture document | -| `generate-project-context` | `/bmad-bmm-generate-project-context` | Analyst | Create project context file | -| `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 | +| **`bmad-help`** ⭐ | `/bmad-help` | Any | **Your intelligent guide — ask anything!** | +| `bmad-create-prd` | `/bmad-create-prd` | PM | Create Product Requirements Document | +| `bmad-create-architecture` | `/bmad-create-architecture` | Architect | Create architecture document | +| `bmad-generate-project-context` | `/bmad-generate-project-context` | Analyst | Create project context file | +| `bmad-create-epics-and-stories` | `/bmad-create-epics-and-stories` | PM | Break down PRD into epics | +| `bmad-check-implementation-readiness` | `/bmad-check-implementation-readiness` | Architect | Validate planning cohesion | +| `bmad-sprint-planning` | `/bmad-sprint-planning` | SM | Initialize sprint tracking | +| `bmad-create-story` | `/bmad-create-story` | SM | Create a story file | +| `bmad-dev-story` | `/bmad-dev-story` | DEV | Implement a story | +| `bmad-code-review` | `/bmad-code-review` | DEV | Review implemented code | ## Common Questions @@ -238,10 +238,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 `bmad-correct-course` workflow (`/bmad-correct-course`) 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. +Invoke the Analyst agent (`/bmad-analyst`) and run `bmad-brainstorming` (`/bmad-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. diff --git a/docs/zh-cn/explanation/quick-flow.md b/docs/zh-cn/explanation/quick-flow.md index 4f1936c18..ac1af0446 100644 --- a/docs/zh-cn/explanation/quick-flow.md +++ b/docs/zh-cn/explanation/quick-flow.md @@ -1,11 +1,11 @@ --- -title: "Quick Flow" +title: "快速流程" description: 小型变更的快速通道 - 跳过完整方法论 sidebar: order: 1 --- -跳过繁琐流程。Quick Flow 通过两条命令将你从想法带到可运行的代码 - 无需产品简报、无需 PRD、无需架构文档。 +跳过繁琐流程。快速流程通过两条命令将你从想法带到可运行的代码 - 无需产品简报、无需 PRD、无需架构文档。 ## 何时使用 @@ -23,12 +23,12 @@ sidebar: - 需求不明确或有争议的任何工作 :::caution[Scope Creep] -如果你启动 Quick Flow 后发现范围超出预期,`quick-dev` 会检测到并提供升级选项。你可以在任何时间切换到完整的 PRD 工作流程,而不会丢失你的工作。 +如果你启动快速流程后发现范围超出预期,`quick-dev` 会检测到并提供升级选项。你可以在任何时间切换到完整的 PRD 工作流程,而不会丢失你的工作。 ::: ## 工作原理 -Quick Flow 有两条命令,每条都由结构化的工作流程支持。你可以一起运行它们,也可以独立运行。 +快速流程有两条命令,每条都由结构化的工作流程支持。你可以一起运行它们,也可以独立运行。 ### quick-spec:规划 @@ -54,7 +54,7 @@ Quick Flow 有两条命令,每条都由结构化的工作流程支持。你可 为获得最佳效果,在完成 `quick-spec` 后,在新对话中运行 `quick-dev`。这为实现智能体提供了专注于构建的干净上下文。 ::: -## Quick Flow 跳过的内容 +## 快速流程跳过的内容 完整的 BMad 方法在编写任何代码之前会生成产品简报、PRD、架构文档和 Epic/Story 分解。Quick Flow 用单个技术规范替代所有这些。这之所以有效,是因为 Quick Flow 针对以下变更: @@ -65,7 +65,7 @@ Quick Flow 有两条命令,每条都由结构化的工作流程支持。你可 ## 升级到完整 BMad 方法 -Quick Flow 包含内置的范围检测护栏。当你使用直接请求运行 `quick-dev` 时,它会评估多组件提及、系统级语言和方法不确定性等信号。如果检测到工作超出快速流程范围: +快速流程包含内置的范围检测护栏。当你使用直接请求运行 `quick-dev` 时,它会评估多组件提及、系统级语言和方法不确定性等信号。如果检测到工作超出快速流程范围: - **轻度升级** - 建议先运行 `quick-spec` 创建计划 - **重度升级** - 建议切换到完整的 BMad 方法 PRD 流程 diff --git a/docs/zh-cn/how-to/non-interactive-installation.md b/docs/zh-cn/how-to/non-interactive-installation.md index 04ca05f41..11d57a712 100644 --- a/docs/zh-cn/how-to/non-interactive-installation.md +++ b/docs/zh-cn/how-to/non-interactive-installation.md @@ -1,5 +1,5 @@ --- -title: 非交互式安装 +title: "非交互式安装" description: 使用命令行标志安装 BMad,适用于 CI/CD 流水线和自动化部署 sidebar: order: 2 diff --git a/docs/zh-cn/reference/agents.md b/docs/zh-cn/reference/agents.md index ed87652d9..393053b9e 100644 --- a/docs/zh-cn/reference/agents.md +++ b/docs/zh-cn/reference/agents.md @@ -1,5 +1,5 @@ --- -title: 智能体 +title: "智能体" description: 默认 BMM 智能体及其菜单触发器和主要工作流 sidebar: order: 2 diff --git a/docs/zh-cn/reference/commands.md b/docs/zh-cn/reference/commands.md index 617e557af..40629e673 100644 --- a/docs/zh-cn/reference/commands.md +++ b/docs/zh-cn/reference/commands.md @@ -1,5 +1,5 @@ --- -title: 命令 +title: "命令" description: BMad 斜杠命令参考——它们是什么、如何工作以及在哪里找到它们。 sidebar: order: 3 diff --git a/docs/zh-cn/reference/modules.md b/docs/zh-cn/reference/modules.md index 04162d657..d8fbdf8d2 100644 --- a/docs/zh-cn/reference/modules.md +++ b/docs/zh-cn/reference/modules.md @@ -1,5 +1,5 @@ --- -title: 官方模块 +title: "官方模块" description: 用于构建自定义智能体、创意智能、游戏开发和测试的附加模块 sidebar: order: 4 diff --git a/docs/zh-cn/reference/testing.md b/docs/zh-cn/reference/testing.md index ffa6e87c3..85fcde0db 100644 --- a/docs/zh-cn/reference/testing.md +++ b/docs/zh-cn/reference/testing.md @@ -1,5 +1,5 @@ --- -title: 测试选项 +title: "测试选项" description: 比较内置 QA 智能体(Quinn)与测试架构师(TEA)模块的测试自动化。 sidebar: order: 5 diff --git a/src/bmm/agents/qa.agent.yaml b/src/bmm/agents/qa.agent.yaml index 2096544e9..71ff83930 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-generate-e2e-tests/workflow.yaml" + workflow: "{project-root}/_bmad/bmm/workflows/qa-generate-e2e-tests/workflow.md" description: "[QA] Automate - Generate tests for existing features (simplified)" prompts: diff --git a/src/bmm/agents/sm.agent.yaml b/src/bmm/agents/sm.agent.yaml index d79f644e5..4244b12b6 100644 --- a/src/bmm/agents/sm.agent.yaml +++ b/src/bmm/agents/sm.agent.yaml @@ -28,7 +28,7 @@ agent: 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." diff --git a/src/bmm/module-help.csv b/src/bmm/module-help.csv index 4559d63bd..b8378cf3c 100644 --- a/src/bmm/module-help.csv +++ b/src/bmm/module-help.csv @@ -23,10 +23,10 @@ bmm,3-solutioning,Create Architecture,CA,10,_bmad/bmm/workflows/3-solutioning/cr 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,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.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-generate-e2e-tests/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,QA Automation Test,QA,45,_bmad/bmm/workflows/qa-generate-e2e-tests/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/research/bmad-skill-manifest.yaml b/src/bmm/workflows/1-analysis/research/bmad-skill-manifest.yaml index 0c815c1bd..02bf825e9 100644 --- a/src/bmm/workflows/1-analysis/research/bmad-skill-manifest.yaml +++ b/src/bmm/workflows/1-analysis/research/bmad-skill-manifest.yaml @@ -1,14 +1,14 @@ workflow-domain-research.md: - canonicalId: bmad-bmm-domain-research + canonicalId: bmad-domain-research type: workflow - description: "Conduct domain and industry research" + description: "Conduct domain and industry research. Use when the user says 'lets create a research report on [domain or industry]'" workflow-market-research.md: - canonicalId: bmad-bmm-market-research + canonicalId: bmad-market-research type: workflow - description: "Conduct market research on competition and customers" + description: "Conduct market research on competition and customers. Use when the user says 'create a market research report about [business idea]'" workflow-technical-research.md: - canonicalId: bmad-bmm-technical-research + canonicalId: bmad-technical-research type: workflow - description: "Conduct technical research on technologies and architecture" + description: "Conduct technical research on technologies and architecture. Use when the user says 'create a technical research report on [topic]'" diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/bmad-skill-manifest.yaml b/src/bmm/workflows/2-plan-workflows/create-prd/bmad-skill-manifest.yaml index fdbe80cd9..aea9910a2 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/bmad-skill-manifest.yaml +++ b/src/bmm/workflows/2-plan-workflows/create-prd/bmad-skill-manifest.yaml @@ -1,14 +1,14 @@ workflow-create-prd.md: - canonicalId: bmad-bmm-create-prd + canonicalId: bmad-create-prd type: workflow - description: "Create a PRD from scratch" + description: "Create a PRD from scratch. Use when the user says 'lets create a product requirements document' or 'I want to create a new PRD'" workflow-edit-prd.md: - canonicalId: bmad-bmm-edit-prd + canonicalId: bmad-edit-prd type: workflow - description: "Edit an existing PRD" + description: "Edit an existing PRD. Use when the user says 'edit this PRD'" workflow-validate-prd.md: - canonicalId: bmad-bmm-validate-prd + canonicalId: bmad-validate-prd type: workflow - description: "Validate a PRD against standards" + description: "Validate a PRD against standards. Use when the user says 'validate this PRD' or 'run PRD validation'" diff --git a/src/bmm/workflows/4-implementation/retrospective/instructions.md b/src/bmm/workflows/4-implementation/retrospective/workflow.md similarity index 94% rename from src/bmm/workflows/4-implementation/retrospective/instructions.md rename to src/bmm/workflows/4-implementation/retrospective/workflow.md index d2bf7e390..cbc502d8b 100644 --- a/src/bmm/workflows/4-implementation/retrospective/instructions.md +++ b/src/bmm/workflows/4-implementation/retrospective/workflow.md @@ -1,31 +1,71 @@ -# Retrospective - Epic Completion Review Instructions +--- +name: retrospective +description: 'Post-epic review to extract lessons and assess success. Use when the user says "run a retrospective" or "lets retro the epic [epic]"' +--- -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 -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. +# Retrospective Workflow - - DOCUMENT OUTPUT: Retrospective analysis. Concise insights, lessons learned, action items. User skill level ({user_skill_level}) affects conversation style ONLY, not retrospective content. +**Goal:** Post-epic review to extract lessons and assess success. -FACILITATION NOTES: +**Your Role:** Scrum Master facilitating retrospective. +- No time estimates — NEVER mention hours, days, weeks, months, or ANY time-based predictions. AI has fundamentally changed development speed. +- Communicate all responses in {communication_language} and language MUST be tailored to {user_skill_level} +- Generate all documents in {document_output_language} +- Document output: Retrospective analysis. Concise insights, lessons learned, action items. User skill level ({user_skill_level}) affects conversation style ONLY, not retrospective content. +- Facilitation notes: + - Psychological safety is paramount - NO BLAME + - Focus on systems, processes, and learning + - Everyone contributes with specific examples preferred + - Action items must be achievable with clear ownership + - Two-part format: (1) Epic Review + (2) Next Epic Preparation +- Party mode protocol: + - ALL agent dialogue MUST use format: "Name (Role): dialogue" + - Example: Bob (Scrum Master): "Let's begin..." + - Example: {user_name} (Project Lead): [User responds] + - Create natural back-and-forth with user actively participating + - Show disagreements, diverse perspectives, authentic team dynamics -- Scrum Master facilitates this retrospective -- Psychological safety is paramount - NO BLAME -- Focus on systems, processes, and learning -- Everyone contributes with specific examples preferred -- Action items must be achievable with clear ownership -- Two-part format: (1) Epic Review + (2) Next Epic Preparation +--- -PARTY MODE PROTOCOL: +## INITIALIZATION -- ALL agent dialogue MUST use format: "Name (Role): dialogue" -- Example: Bob (Scrum Master): "Let's begin..." -- Example: {user_name} (Project Lead): [User responds] -- Create natural back-and-forth with user actively participating -- Show disagreements, diverse perspectives, authentic team dynamics - +### Configuration Loading + +Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: + +- `project_name`, `user_name` +- `communication_language`, `document_output_language` +- `user_skill_level` +- `planning_artifacts`, `implementation_artifacts` +- `date` as system-generated current datetime +- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}` + +### Paths + +- `installed_path` = `{project-root}/_bmad/bmm/workflows/4-implementation/retrospective` +- `sprint_status_file` = `{implementation_artifacts}/sprint-status.yaml` + +### Input Files + +| Input | Description | Path Pattern(s) | Load Strategy | +|-------|-------------|------------------|---------------| +| epics | 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` | SELECTIVE_LOAD | +| previous_retrospective | Previous epic's retrospective (optional) | `{implementation_artifacts}/**/epic-{{prev_epic_num}}-retro-*.md` | SELECTIVE_LOAD | +| architecture | System architecture for context | whole: `{planning_artifacts}/*architecture*.md`, sharded: `{planning_artifacts}/*architecture*/*.md` | FULL_LOAD | +| prd | Product requirements for context | whole: `{planning_artifacts}/*prd*.md`, sharded: `{planning_artifacts}/*prd*/*.md` | FULL_LOAD | +| document_project | Brownfield project documentation (optional) | sharded: `{planning_artifacts}/*.md` | INDEX_GUIDED | + +### Required Inputs + +- `agent_manifest` = `{project-root}/_bmad/_config/agent-manifest.csv` + +### Context + +- `project_context` = `**/project-context.md` (load if exists) + +--- + +## EXECUTION @@ -159,7 +199,7 @@ Bob (Scrum Master): "Perfect. Epic {{epic_number}} is complete and ready for ret - + Load input files according to the Input Files table in INITIALIZATION. For SELECTIVE_LOAD inputs, load only the epic matching {{epic_number}}. For FULL_LOAD inputs, load the complete document. For INDEX_GUIDED inputs, check the index first and load relevant sections. After discovery, these content variables are available: {epics_content} (selective load for this epic), {architecture_content}, {prd_content}, {document_project_content} After discovery, these content variables are available: {epics_content} (selective load for this epic), {architecture_content}, {prd_content}, {document_project_content} 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 49ac2cc35..000000000 --- a/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +++ /dev/null @@ -1,52 +0,0 @@ -# Retrospective - Epic Completion Review Workflow -name: "retrospective" -description: 'Post-epic review to extract lessons and assess success. Use when the user says "run a retrospective" or "lets retro the epic [epic]"' - -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-status/instructions.md b/src/bmm/workflows/4-implementation/sprint-status/workflow.md similarity index 88% rename from src/bmm/workflows/4-implementation/sprint-status/instructions.md rename to src/bmm/workflows/4-implementation/sprint-status/workflow.md index b37bff9a5..aeed0ab23 100644 --- a/src/bmm/workflows/4-implementation/sprint-status/instructions.md +++ b/src/bmm/workflows/4-implementation/sprint-status/workflow.md @@ -1,9 +1,46 @@ -# Sprint Status - Multi-Mode Service +--- +name: sprint-status +description: 'Summarize sprint status and surface risks. Use when the user says "check sprint status" or "show sprint status"' +--- -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 -Modes: interactive (default), validate, data -⚠️ ABSOLUTELY NO TIME ESTIMATES. Do NOT mention hours, days, weeks, or timelines. +# Sprint Status Workflow + +**Goal:** Summarize sprint status, surface risks, and recommend the next workflow action. + +**Your Role:** You are a Scrum Master providing clear, actionable sprint visibility. No time estimates — focus on status, risks, and next steps. + +--- + +## INITIALIZATION + +### Configuration Loading + +Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: + +- `project_name`, `user_name` +- `communication_language`, `document_output_language` +- `implementation_artifacts` +- `date` as system-generated current datetime +- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}` + +### Paths + +- `installed_path` = `{project-root}/_bmad/bmm/workflows/4-implementation/sprint-status` +- `sprint_status_file` = `{implementation_artifacts}/sprint-status.yaml` + +### Input Files + +| Input | Path | Load Strategy | +|-------|------|---------------| +| Sprint status | `{sprint_status_file}` | FULL_LOAD | + +### Context + +- `project_context` = `**/project-context.md` (load if exists) + +--- + +## EXECUTION 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 290b1ce32..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 and surface risks. Use when the user says "check sprint status" or "show sprint status"' -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/qa-generate-e2e-tests/instructions.md b/src/bmm/workflows/qa-generate-e2e-tests/workflow.md similarity index 61% rename from src/bmm/workflows/qa-generate-e2e-tests/instructions.md rename to src/bmm/workflows/qa-generate-e2e-tests/workflow.md index 03653337f..f911090b0 100644 --- a/src/bmm/workflows/qa-generate-e2e-tests/instructions.md +++ b/src/bmm/workflows/qa-generate-e2e-tests/workflow.md @@ -1,10 +1,43 @@ -# Quinn QA - Automate +--- +name: qa-generate-e2e-tests +description: 'Generate end to end automated tests for existing features. Use when the user says "create qa automated tests for [feature]"' +--- -**Goal**: Generate automated API and E2E tests for implemented code. +# QA Generate E2E Tests Workflow -**Scope**: This workflow generates tests ONLY. It does **not** perform code review or story validation (use Code Review `CR` for that). +**Goal:** Generate automated API and E2E tests for implemented code. -## Instructions +**Your Role:** You are a QA automation engineer. You generate tests ONLY — no code review or story validation (use Code Review `CR` for that). + +--- + +## INITIALIZATION + +### Configuration Loading + +Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: + +- `project_name`, `user_name` +- `communication_language`, `document_output_language` +- `implementation_artifacts` +- `date` as system-generated current datetime +- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}` + +### Paths + +- `installed_path` = `{project-root}/_bmad/bmm/workflows/qa-generate-e2e-tests` +- `checklist` = `{installed_path}/checklist.md` +- `test_dir` = `{project-root}/tests` +- `source_dir` = `{project-root}` +- `default_output_file` = `{implementation_artifacts}/tests/test-summary.md` + +### Context + +- `project_context` = `**/project-context.md` (load if exists) + +--- + +## EXECUTION ### Step 0: Detect Test Framework @@ -101,10 +134,10 @@ If the project needs: - Comprehensive coverage analysis - Advanced testing patterns and utilities -→ **Install Test Architect (TEA) module**: +> **Install Test Architect (TEA) module**: ## Output -Save summary to: `{implementation_artifacts}/tests/test-summary.md` +Save summary to: `{default_output_file}` -**Done!** Tests generated and verified. +**Done!** Tests generated and verified. Validate against `{checklist}`. diff --git a/src/bmm/workflows/qa-generate-e2e-tests/workflow.yaml b/src/bmm/workflows/qa-generate-e2e-tests/workflow.yaml deleted file mode 100644 index 77809ff72..000000000 --- a/src/bmm/workflows/qa-generate-e2e-tests/workflow.yaml +++ /dev/null @@ -1,42 +0,0 @@ -name: qa-generate-e2e-tests -description: 'Generate end to end automated tests for existing features. Use when the user says "create qa automated tests for [feature]"' - -# 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-generate-e2e-tests" -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/test/test-installation-components.js b/test/test-installation-components.js index 63f2567f5..56f37b365 100644 --- a/test/test-installation-components.js +++ b/test/test-installation-components.js @@ -457,9 +457,311 @@ async function runTests() { console.log(''); // ============================================================ - // Test 9: OpenCode Ancestor Conflict + // Test 9: Claude Code Native Skills Install // ============================================================ - console.log(`${colors.yellow}Test Suite 9: OpenCode Ancestor Conflict${colors.reset}\n`); + console.log(`${colors.yellow}Test Suite 9: Claude Code Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes9 = await loadPlatformCodes(); + const claudeInstaller = platformCodes9.platforms['claude-code']?.installer; + + assert(claudeInstaller?.target_dir === '.claude/skills', 'Claude Code target_dir uses native skills path'); + + assert(claudeInstaller?.skill_format === true, 'Claude Code installer enables native skill output'); + + assert(claudeInstaller?.ancestor_conflict_check === true, 'Claude Code installer enables ancestor conflict checks'); + + assert( + Array.isArray(claudeInstaller?.legacy_targets) && claudeInstaller.legacy_targets.includes('.claude/commands'), + 'Claude Code installer cleans legacy command output', + ); + + const tempProjectDir9 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-claude-code-test-')); + const installedBmadDir9 = await createTestBmadFixture(); + const legacyDir9 = path.join(tempProjectDir9, '.claude', 'commands'); + await fs.ensureDir(legacyDir9); + await fs.writeFile(path.join(legacyDir9, 'bmad-legacy.md'), 'legacy\n'); + + const ideManager9 = new IdeManager(); + await ideManager9.ensureInitialized(); + const result9 = await ideManager9.setup('claude-code', tempProjectDir9, installedBmadDir9, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result9.success === true, 'Claude Code setup succeeds against temp project'); + + const skillFile9 = path.join(tempProjectDir9, '.claude', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile9), 'Claude Code install writes SKILL.md directory output'); + + // Verify name frontmatter matches directory name + const skillContent9 = await fs.readFile(skillFile9, 'utf8'); + const nameMatch9 = skillContent9.match(/^name:\s*(.+)$/m); + assert(nameMatch9 && nameMatch9[1].trim() === 'bmad-master', 'Claude Code skill name frontmatter matches directory name exactly'); + + assert(!(await fs.pathExists(legacyDir9)), 'Claude Code setup removes legacy commands dir'); + + await fs.remove(tempProjectDir9); + await fs.remove(installedBmadDir9); + } catch (error) { + assert(false, 'Claude Code native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Test 10: Claude Code Ancestor Conflict + // ============================================================ + console.log(`${colors.yellow}Test Suite 10: Claude Code Ancestor Conflict${colors.reset}\n`); + + try { + const tempRoot10 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-claude-code-ancestor-test-')); + const parentProjectDir10 = path.join(tempRoot10, 'parent'); + const childProjectDir10 = path.join(parentProjectDir10, 'child'); + const installedBmadDir10 = await createTestBmadFixture(); + + await fs.ensureDir(path.join(parentProjectDir10, '.git')); + await fs.ensureDir(path.join(parentProjectDir10, '.claude', 'skills', 'bmad-existing')); + await fs.ensureDir(childProjectDir10); + await fs.writeFile(path.join(parentProjectDir10, '.claude', 'skills', 'bmad-existing', 'SKILL.md'), 'legacy\n'); + + const ideManager10 = new IdeManager(); + await ideManager10.ensureInitialized(); + const result10 = await ideManager10.setup('claude-code', childProjectDir10, installedBmadDir10, { + silent: true, + selectedModules: ['bmm'], + }); + const expectedConflictDir10 = await fs.realpath(path.join(parentProjectDir10, '.claude', 'skills')); + + assert(result10.success === false, 'Claude Code setup refuses install when ancestor skills already exist'); + assert(result10.handlerResult?.reason === 'ancestor-conflict', 'Claude Code ancestor rejection reports ancestor-conflict reason'); + assert( + result10.handlerResult?.conflictDir === expectedConflictDir10, + 'Claude Code ancestor rejection points at ancestor .claude/skills dir', + ); + + await fs.remove(tempRoot10); + await fs.remove(installedBmadDir10); + } catch (error) { + assert(false, 'Claude Code ancestor conflict protection test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Test 11: Codex Native Skills Install + // ============================================================ + console.log(`${colors.yellow}Test Suite 11: Codex Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes11 = await loadPlatformCodes(); + const codexInstaller = platformCodes11.platforms.codex?.installer; + + assert(codexInstaller?.target_dir === '.agents/skills', 'Codex target_dir uses native skills path'); + + assert(codexInstaller?.skill_format === true, 'Codex installer enables native skill output'); + + assert(codexInstaller?.ancestor_conflict_check === true, 'Codex installer enables ancestor conflict checks'); + + assert( + Array.isArray(codexInstaller?.legacy_targets) && codexInstaller.legacy_targets.includes('.codex/prompts'), + 'Codex installer cleans legacy prompt output', + ); + + const tempProjectDir11 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-codex-test-')); + const installedBmadDir11 = await createTestBmadFixture(); + const legacyDir11 = path.join(tempProjectDir11, '.codex', 'prompts'); + await fs.ensureDir(legacyDir11); + await fs.writeFile(path.join(legacyDir11, 'bmad-legacy.md'), 'legacy\n'); + + const ideManager11 = new IdeManager(); + await ideManager11.ensureInitialized(); + const result11 = await ideManager11.setup('codex', tempProjectDir11, installedBmadDir11, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result11.success === true, 'Codex setup succeeds against temp project'); + + const skillFile11 = path.join(tempProjectDir11, '.agents', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile11), 'Codex install writes SKILL.md directory output'); + + // Verify name frontmatter matches directory name + const skillContent11 = await fs.readFile(skillFile11, 'utf8'); + const nameMatch11 = skillContent11.match(/^name:\s*(.+)$/m); + assert(nameMatch11 && nameMatch11[1].trim() === 'bmad-master', 'Codex skill name frontmatter matches directory name exactly'); + + assert(!(await fs.pathExists(legacyDir11)), 'Codex setup removes legacy prompts dir'); + + await fs.remove(tempProjectDir11); + await fs.remove(installedBmadDir11); + } catch (error) { + assert(false, 'Codex native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Test 12: Codex Ancestor Conflict + // ============================================================ + console.log(`${colors.yellow}Test Suite 12: Codex Ancestor Conflict${colors.reset}\n`); + + try { + const tempRoot12 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-codex-ancestor-test-')); + const parentProjectDir12 = path.join(tempRoot12, 'parent'); + const childProjectDir12 = path.join(parentProjectDir12, 'child'); + const installedBmadDir12 = await createTestBmadFixture(); + + await fs.ensureDir(path.join(parentProjectDir12, '.git')); + await fs.ensureDir(path.join(parentProjectDir12, '.agents', 'skills', 'bmad-existing')); + await fs.ensureDir(childProjectDir12); + await fs.writeFile(path.join(parentProjectDir12, '.agents', 'skills', 'bmad-existing', 'SKILL.md'), 'legacy\n'); + + const ideManager12 = new IdeManager(); + await ideManager12.ensureInitialized(); + const result12 = await ideManager12.setup('codex', childProjectDir12, installedBmadDir12, { + silent: true, + selectedModules: ['bmm'], + }); + const expectedConflictDir12 = await fs.realpath(path.join(parentProjectDir12, '.agents', 'skills')); + + assert(result12.success === false, 'Codex setup refuses install when ancestor skills already exist'); + assert(result12.handlerResult?.reason === 'ancestor-conflict', 'Codex ancestor rejection reports ancestor-conflict reason'); + assert(result12.handlerResult?.conflictDir === expectedConflictDir12, 'Codex ancestor rejection points at ancestor .agents/skills dir'); + + await fs.remove(tempRoot12); + await fs.remove(installedBmadDir12); + } catch (error) { + assert(false, 'Codex ancestor conflict protection test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Test 13: Cursor Native Skills Install + // ============================================================ + console.log(`${colors.yellow}Test Suite 13: Cursor Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes13 = await loadPlatformCodes(); + const cursorInstaller = platformCodes13.platforms.cursor?.installer; + + assert(cursorInstaller?.target_dir === '.cursor/skills', 'Cursor target_dir uses native skills path'); + + assert(cursorInstaller?.skill_format === true, 'Cursor installer enables native skill output'); + + assert( + Array.isArray(cursorInstaller?.legacy_targets) && cursorInstaller.legacy_targets.includes('.cursor/commands'), + 'Cursor installer cleans legacy command output', + ); + + assert(!cursorInstaller?.ancestor_conflict_check, 'Cursor installer does not enable ancestor conflict checks'); + + const tempProjectDir13c = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-cursor-test-')); + const installedBmadDir13c = await createTestBmadFixture(); + const legacyDir13c = path.join(tempProjectDir13c, '.cursor', 'commands'); + await fs.ensureDir(legacyDir13c); + await fs.writeFile(path.join(legacyDir13c, 'bmad-legacy.md'), 'legacy\n'); + + const ideManager13c = new IdeManager(); + await ideManager13c.ensureInitialized(); + const result13c = await ideManager13c.setup('cursor', tempProjectDir13c, installedBmadDir13c, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result13c.success === true, 'Cursor setup succeeds against temp project'); + + const skillFile13c = path.join(tempProjectDir13c, '.cursor', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile13c), 'Cursor install writes SKILL.md directory output'); + + // Verify name frontmatter matches directory name + const skillContent13c = await fs.readFile(skillFile13c, 'utf8'); + const nameMatch13c = skillContent13c.match(/^name:\s*(.+)$/m); + assert(nameMatch13c && nameMatch13c[1].trim() === 'bmad-master', 'Cursor skill name frontmatter matches directory name exactly'); + + assert(!(await fs.pathExists(legacyDir13c)), 'Cursor setup removes legacy commands dir'); + + await fs.remove(tempProjectDir13c); + await fs.remove(installedBmadDir13c); + } catch (error) { + assert(false, 'Cursor native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Test 14: Roo Code Native Skills Install + // ============================================================ + console.log(`${colors.yellow}Test Suite 14: Roo Code Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes13 = await loadPlatformCodes(); + const rooInstaller = platformCodes13.platforms.roo?.installer; + + assert(rooInstaller?.target_dir === '.roo/skills', 'Roo target_dir uses native skills path'); + + assert(rooInstaller?.skill_format === true, 'Roo installer enables native skill output'); + + assert( + Array.isArray(rooInstaller?.legacy_targets) && rooInstaller.legacy_targets.includes('.roo/commands'), + 'Roo installer cleans legacy command output', + ); + + const tempProjectDir13 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-roo-test-')); + const installedBmadDir13 = await createTestBmadFixture(); + const legacyDir13 = path.join(tempProjectDir13, '.roo', 'commands', 'bmad-legacy-dir'); + await fs.ensureDir(legacyDir13); + await fs.writeFile(path.join(tempProjectDir13, '.roo', 'commands', 'bmad-legacy.md'), 'legacy\n'); + await fs.writeFile(path.join(legacyDir13, 'SKILL.md'), 'legacy\n'); + + const ideManager13 = new IdeManager(); + await ideManager13.ensureInitialized(); + const result13 = await ideManager13.setup('roo', tempProjectDir13, installedBmadDir13, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result13.success === true, 'Roo setup succeeds against temp project'); + + const skillFile13 = path.join(tempProjectDir13, '.roo', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile13), 'Roo install writes SKILL.md directory output'); + + // Verify name frontmatter matches directory name (Roo constraint: lowercase alphanumeric + hyphens) + const skillContent13 = await fs.readFile(skillFile13, 'utf8'); + const nameMatch13 = skillContent13.match(/^name:\s*(.+)$/m); + assert( + nameMatch13 && nameMatch13[1].trim() === 'bmad-master', + 'Roo skill name frontmatter matches directory name exactly (lowercase alphanumeric + hyphens)', + ); + + assert(!(await fs.pathExists(path.join(tempProjectDir13, '.roo', 'commands'))), 'Roo setup removes legacy commands dir'); + + // Reinstall/upgrade: run setup again over existing skills output + const result13b = await ideManager13.setup('roo', tempProjectDir13, installedBmadDir13, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result13b.success === true, 'Roo reinstall/upgrade succeeds over existing skills'); + assert(await fs.pathExists(skillFile13), 'Roo reinstall preserves SKILL.md output'); + + await fs.remove(tempProjectDir13); + await fs.remove(installedBmadDir13); + } catch (error) { + assert(false, 'Roo native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Test 15: OpenCode Ancestor Conflict + // ============================================================ + console.log(`${colors.yellow}Test Suite 15: OpenCode Ancestor Conflict${colors.reset}\n`); try { const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-opencode-ancestor-test-')); @@ -496,9 +798,9 @@ async function runTests() { console.log(''); // ============================================================ - // Test 10: QA Agent Compilation + // Test 16: QA Agent Compilation // ============================================================ - console.log(`${colors.yellow}Test Suite 10: QA Agent Compilation${colors.reset}\n`); + console.log(`${colors.yellow}Test Suite 16: QA Agent Compilation${colors.reset}\n`); try { const builder = new YamlXmlBuilder(); @@ -524,6 +826,680 @@ async function runTests() { console.log(''); + // ============================================================ + // Test 17: GitHub Copilot Native Skills Install + // ============================================================ + console.log(`${colors.yellow}Test Suite 17: GitHub Copilot Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes17 = await loadPlatformCodes(); + const copilotInstaller = platformCodes17.platforms['github-copilot']?.installer; + + assert(copilotInstaller?.target_dir === '.github/skills', 'GitHub Copilot target_dir uses native skills path'); + + assert(copilotInstaller?.skill_format === true, 'GitHub Copilot installer enables native skill output'); + + assert( + Array.isArray(copilotInstaller?.legacy_targets) && copilotInstaller.legacy_targets.includes('.github/agents'), + 'GitHub Copilot installer cleans legacy agents output', + ); + + assert( + Array.isArray(copilotInstaller?.legacy_targets) && copilotInstaller.legacy_targets.includes('.github/prompts'), + 'GitHub Copilot installer cleans legacy prompts output', + ); + + const tempProjectDir17 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-copilot-test-')); + const installedBmadDir17 = await createTestBmadFixture(); + + // Create legacy .github/agents/ and .github/prompts/ files + const legacyAgentsDir17 = path.join(tempProjectDir17, '.github', 'agents'); + const legacyPromptsDir17 = path.join(tempProjectDir17, '.github', 'prompts'); + await fs.ensureDir(legacyAgentsDir17); + await fs.ensureDir(legacyPromptsDir17); + await fs.writeFile(path.join(legacyAgentsDir17, 'bmad-legacy.agent.md'), 'legacy agent\n'); + await fs.writeFile(path.join(legacyPromptsDir17, 'bmad-legacy.prompt.md'), 'legacy prompt\n'); + + // Create legacy copilot-instructions.md with BMAD markers + const copilotInstructionsPath17 = path.join(tempProjectDir17, '.github', 'copilot-instructions.md'); + await fs.writeFile( + copilotInstructionsPath17, + 'User content before\n\nBMAD generated content\n\nUser content after\n', + ); + + const ideManager17 = new IdeManager(); + await ideManager17.ensureInitialized(); + const result17 = await ideManager17.setup('github-copilot', tempProjectDir17, installedBmadDir17, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result17.success === true, 'GitHub Copilot setup succeeds against temp project'); + + const skillFile17 = path.join(tempProjectDir17, '.github', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile17), 'GitHub Copilot install writes SKILL.md directory output'); + + // Verify name frontmatter matches directory name + const skillContent17 = await fs.readFile(skillFile17, 'utf8'); + const nameMatch17 = skillContent17.match(/^name:\s*(.+)$/m); + assert(nameMatch17 && nameMatch17[1].trim() === 'bmad-master', 'GitHub Copilot skill name frontmatter matches directory name exactly'); + + assert(!(await fs.pathExists(legacyAgentsDir17)), 'GitHub Copilot setup removes legacy agents dir'); + + assert(!(await fs.pathExists(legacyPromptsDir17)), 'GitHub Copilot setup removes legacy prompts dir'); + + // Verify copilot-instructions.md BMAD markers were stripped but user content preserved + const cleanedInstructions17 = await fs.readFile(copilotInstructionsPath17, 'utf8'); + assert( + !cleanedInstructions17.includes('BMAD:START') && !cleanedInstructions17.includes('BMAD generated content'), + 'GitHub Copilot setup strips BMAD markers from copilot-instructions.md', + ); + assert( + cleanedInstructions17.includes('User content before') && cleanedInstructions17.includes('User content after'), + 'GitHub Copilot setup preserves user content in copilot-instructions.md', + ); + + await fs.remove(tempProjectDir17); + await fs.remove(installedBmadDir17); + } catch (error) { + assert(false, 'GitHub Copilot native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Test 18: Cline Native Skills Install + // ============================================================ + console.log(`${colors.yellow}Test Suite 18: Cline Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes18 = await loadPlatformCodes(); + const clineInstaller = platformCodes18.platforms.cline?.installer; + + assert(clineInstaller?.target_dir === '.cline/skills', 'Cline target_dir uses native skills path'); + + assert(clineInstaller?.skill_format === true, 'Cline installer enables native skill output'); + + assert( + Array.isArray(clineInstaller?.legacy_targets) && clineInstaller.legacy_targets.includes('.clinerules/workflows'), + 'Cline installer cleans legacy workflow output', + ); + + const tempProjectDir18 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-cline-test-')); + const installedBmadDir18 = await createTestBmadFixture(); + const legacyDir18 = path.join(tempProjectDir18, '.clinerules', 'workflows', 'bmad-legacy-dir'); + await fs.ensureDir(legacyDir18); + await fs.writeFile(path.join(tempProjectDir18, '.clinerules', 'workflows', 'bmad-legacy.md'), 'legacy\n'); + await fs.writeFile(path.join(legacyDir18, 'SKILL.md'), 'legacy\n'); + + const ideManager18 = new IdeManager(); + await ideManager18.ensureInitialized(); + const result18 = await ideManager18.setup('cline', tempProjectDir18, installedBmadDir18, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result18.success === true, 'Cline setup succeeds against temp project'); + + const skillFile18 = path.join(tempProjectDir18, '.cline', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile18), 'Cline install writes SKILL.md directory output'); + + // Verify name frontmatter matches directory name + const skillContent18 = await fs.readFile(skillFile18, 'utf8'); + const nameMatch18 = skillContent18.match(/^name:\s*(.+)$/m); + assert(nameMatch18 && nameMatch18[1].trim() === 'bmad-master', 'Cline skill name frontmatter matches directory name exactly'); + + assert(!(await fs.pathExists(path.join(tempProjectDir18, '.clinerules', 'workflows'))), 'Cline setup removes legacy workflows dir'); + + // Reinstall/upgrade: run setup again over existing skills output + const result18b = await ideManager18.setup('cline', tempProjectDir18, installedBmadDir18, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result18b.success === true, 'Cline reinstall/upgrade succeeds over existing skills'); + assert(await fs.pathExists(skillFile18), 'Cline reinstall preserves SKILL.md output'); + + await fs.remove(tempProjectDir18); + await fs.remove(installedBmadDir18); + } catch (error) { + assert(false, 'Cline native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Test 19: CodeBuddy Native Skills Install + // ============================================================ + console.log(`${colors.yellow}Test Suite 19: CodeBuddy Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes19 = await loadPlatformCodes(); + const codebuddyInstaller = platformCodes19.platforms.codebuddy?.installer; + + assert(codebuddyInstaller?.target_dir === '.codebuddy/skills', 'CodeBuddy target_dir uses native skills path'); + + assert(codebuddyInstaller?.skill_format === true, 'CodeBuddy installer enables native skill output'); + + assert( + Array.isArray(codebuddyInstaller?.legacy_targets) && codebuddyInstaller.legacy_targets.includes('.codebuddy/commands'), + 'CodeBuddy installer cleans legacy command output', + ); + + const tempProjectDir19 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-codebuddy-test-')); + const installedBmadDir19 = await createTestBmadFixture(); + const legacyDir19 = path.join(tempProjectDir19, '.codebuddy', 'commands', 'bmad-legacy-dir'); + await fs.ensureDir(legacyDir19); + await fs.writeFile(path.join(tempProjectDir19, '.codebuddy', 'commands', 'bmad-legacy.md'), 'legacy\n'); + await fs.writeFile(path.join(legacyDir19, 'SKILL.md'), 'legacy\n'); + + const ideManager19 = new IdeManager(); + await ideManager19.ensureInitialized(); + const result19 = await ideManager19.setup('codebuddy', tempProjectDir19, installedBmadDir19, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result19.success === true, 'CodeBuddy setup succeeds against temp project'); + + const skillFile19 = path.join(tempProjectDir19, '.codebuddy', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile19), 'CodeBuddy install writes SKILL.md directory output'); + + const skillContent19 = await fs.readFile(skillFile19, 'utf8'); + const nameMatch19 = skillContent19.match(/^name:\s*(.+)$/m); + assert(nameMatch19 && nameMatch19[1].trim() === 'bmad-master', 'CodeBuddy skill name frontmatter matches directory name exactly'); + + assert(!(await fs.pathExists(path.join(tempProjectDir19, '.codebuddy', 'commands'))), 'CodeBuddy setup removes legacy commands dir'); + + const result19b = await ideManager19.setup('codebuddy', tempProjectDir19, installedBmadDir19, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result19b.success === true, 'CodeBuddy reinstall/upgrade succeeds over existing skills'); + assert(await fs.pathExists(skillFile19), 'CodeBuddy reinstall preserves SKILL.md output'); + + await fs.remove(tempProjectDir19); + await fs.remove(installedBmadDir19); + } catch (error) { + assert(false, 'CodeBuddy native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Test 20: Crush Native Skills Install + // ============================================================ + console.log(`${colors.yellow}Test Suite 20: Crush Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes20 = await loadPlatformCodes(); + const crushInstaller = platformCodes20.platforms.crush?.installer; + + assert(crushInstaller?.target_dir === '.crush/skills', 'Crush target_dir uses native skills path'); + + assert(crushInstaller?.skill_format === true, 'Crush installer enables native skill output'); + + assert( + Array.isArray(crushInstaller?.legacy_targets) && crushInstaller.legacy_targets.includes('.crush/commands'), + 'Crush installer cleans legacy command output', + ); + + const tempProjectDir20 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-crush-test-')); + const installedBmadDir20 = await createTestBmadFixture(); + const legacyDir20 = path.join(tempProjectDir20, '.crush', 'commands', 'bmad-legacy-dir'); + await fs.ensureDir(legacyDir20); + await fs.writeFile(path.join(tempProjectDir20, '.crush', 'commands', 'bmad-legacy.md'), 'legacy\n'); + await fs.writeFile(path.join(legacyDir20, 'SKILL.md'), 'legacy\n'); + + const ideManager20 = new IdeManager(); + await ideManager20.ensureInitialized(); + const result20 = await ideManager20.setup('crush', tempProjectDir20, installedBmadDir20, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result20.success === true, 'Crush setup succeeds against temp project'); + + const skillFile20 = path.join(tempProjectDir20, '.crush', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile20), 'Crush install writes SKILL.md directory output'); + + const skillContent20 = await fs.readFile(skillFile20, 'utf8'); + const nameMatch20 = skillContent20.match(/^name:\s*(.+)$/m); + assert(nameMatch20 && nameMatch20[1].trim() === 'bmad-master', 'Crush skill name frontmatter matches directory name exactly'); + + assert(!(await fs.pathExists(path.join(tempProjectDir20, '.crush', 'commands'))), 'Crush setup removes legacy commands dir'); + + const result20b = await ideManager20.setup('crush', tempProjectDir20, installedBmadDir20, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result20b.success === true, 'Crush reinstall/upgrade succeeds over existing skills'); + assert(await fs.pathExists(skillFile20), 'Crush reinstall preserves SKILL.md output'); + + await fs.remove(tempProjectDir20); + await fs.remove(installedBmadDir20); + } catch (error) { + assert(false, 'Crush native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Test 21: Trae Native Skills Install + // ============================================================ + console.log(`${colors.yellow}Test Suite 21: Trae Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes21 = await loadPlatformCodes(); + const traeInstaller = platformCodes21.platforms.trae?.installer; + + assert(traeInstaller?.target_dir === '.trae/skills', 'Trae target_dir uses native skills path'); + + assert(traeInstaller?.skill_format === true, 'Trae installer enables native skill output'); + + assert( + Array.isArray(traeInstaller?.legacy_targets) && traeInstaller.legacy_targets.includes('.trae/rules'), + 'Trae installer cleans legacy rules output', + ); + + const tempProjectDir21 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-trae-test-')); + const installedBmadDir21 = await createTestBmadFixture(); + const legacyDir21 = path.join(tempProjectDir21, '.trae', 'rules'); + await fs.ensureDir(legacyDir21); + await fs.writeFile(path.join(legacyDir21, 'bmad-legacy.md'), 'legacy\n'); + + const ideManager21 = new IdeManager(); + await ideManager21.ensureInitialized(); + const result21 = await ideManager21.setup('trae', tempProjectDir21, installedBmadDir21, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result21.success === true, 'Trae setup succeeds against temp project'); + + const skillFile21 = path.join(tempProjectDir21, '.trae', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile21), 'Trae install writes SKILL.md directory output'); + + const skillContent21 = await fs.readFile(skillFile21, 'utf8'); + const nameMatch21 = skillContent21.match(/^name:\s*(.+)$/m); + assert(nameMatch21 && nameMatch21[1].trim() === 'bmad-master', 'Trae skill name frontmatter matches directory name exactly'); + + assert(!(await fs.pathExists(path.join(tempProjectDir21, '.trae', 'rules'))), 'Trae setup removes legacy rules dir'); + + const result21b = await ideManager21.setup('trae', tempProjectDir21, installedBmadDir21, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result21b.success === true, 'Trae reinstall/upgrade succeeds over existing skills'); + assert(await fs.pathExists(skillFile21), 'Trae reinstall preserves SKILL.md output'); + + await fs.remove(tempProjectDir21); + await fs.remove(installedBmadDir21); + } catch (error) { + assert(false, 'Trae native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Suite 22: KiloCoder Suspended + // ============================================================ + console.log(`${colors.yellow}Test Suite 22: KiloCoder Suspended${colors.reset}\n`); + + try { + clearCache(); + const platformCodes22 = await loadPlatformCodes(); + const kiloConfig22 = platformCodes22.platforms.kilo; + + assert(typeof kiloConfig22?.suspended === 'string', 'KiloCoder has a suspended message in platform config'); + + assert(kiloConfig22?.installer?.target_dir === '.kilocode/skills', 'KiloCoder retains target_dir config for future use'); + + const ideManager22 = new IdeManager(); + await ideManager22.ensureInitialized(); + + // Should not appear in available IDEs + const availableIdes22 = ideManager22.getAvailableIdes(); + assert(!availableIdes22.some((ide) => ide.value === 'kilo'), 'KiloCoder is hidden from IDE selection'); + + // Setup should be blocked but legacy files should be cleaned up + const tempProjectDir22 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-kilo-test-')); + const installedBmadDir22 = await createTestBmadFixture(); + + // Pre-populate legacy Kilo artifacts that should be cleaned up + const legacyDir22 = path.join(tempProjectDir22, '.kilocode', 'workflows'); + await fs.ensureDir(legacyDir22); + await fs.writeFile(path.join(legacyDir22, 'bmad-legacy.md'), 'legacy\n'); + + const result22 = await ideManager22.setup('kilo', tempProjectDir22, installedBmadDir22, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result22.success === false, 'KiloCoder setup is blocked when suspended'); + assert(result22.error === 'suspended', 'KiloCoder setup returns suspended error'); + + // Should not write new skill files + assert( + !(await fs.pathExists(path.join(tempProjectDir22, '.kilocode', 'skills'))), + 'KiloCoder does not create skills directory when suspended', + ); + + // Legacy files should be cleaned up + assert( + !(await fs.pathExists(path.join(tempProjectDir22, '.kilocode', 'workflows'))), + 'KiloCoder legacy workflows are cleaned up even when suspended', + ); + + await fs.remove(tempProjectDir22); + await fs.remove(installedBmadDir22); + } catch (error) { + assert(false, 'KiloCoder suspended test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Suite 23: Gemini CLI Native Skills + // ============================================================ + console.log(`${colors.yellow}Test Suite 23: Gemini CLI Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes23 = await loadPlatformCodes(); + const geminiInstaller = platformCodes23.platforms.gemini?.installer; + + assert(geminiInstaller?.target_dir === '.gemini/skills', 'Gemini target_dir uses native skills path'); + + assert(geminiInstaller?.skill_format === true, 'Gemini installer enables native skill output'); + + assert( + Array.isArray(geminiInstaller?.legacy_targets) && geminiInstaller.legacy_targets.includes('.gemini/commands'), + 'Gemini installer cleans legacy commands output', + ); + + const tempProjectDir23 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-gemini-test-')); + const installedBmadDir23 = await createTestBmadFixture(); + const legacyDir23 = path.join(tempProjectDir23, '.gemini', 'commands'); + await fs.ensureDir(legacyDir23); + await fs.writeFile(path.join(legacyDir23, 'bmad-legacy.toml'), 'legacy\n'); + + const ideManager23 = new IdeManager(); + await ideManager23.ensureInitialized(); + const result23 = await ideManager23.setup('gemini', tempProjectDir23, installedBmadDir23, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result23.success === true, 'Gemini setup succeeds against temp project'); + + const skillFile23 = path.join(tempProjectDir23, '.gemini', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile23), 'Gemini install writes SKILL.md directory output'); + + const skillContent23 = await fs.readFile(skillFile23, 'utf8'); + const nameMatch23 = skillContent23.match(/^name:\s*(.+)$/m); + assert(nameMatch23 && nameMatch23[1].trim() === 'bmad-master', 'Gemini skill name frontmatter matches directory name exactly'); + + assert(!(await fs.pathExists(path.join(tempProjectDir23, '.gemini', 'commands'))), 'Gemini setup removes legacy commands dir'); + + const result23b = await ideManager23.setup('gemini', tempProjectDir23, installedBmadDir23, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result23b.success === true, 'Gemini reinstall/upgrade succeeds over existing skills'); + assert(await fs.pathExists(skillFile23), 'Gemini reinstall preserves SKILL.md output'); + + await fs.remove(tempProjectDir23); + await fs.remove(installedBmadDir23); + } catch (error) { + assert(false, 'Gemini native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Suite 24: iFlow Native Skills + // ============================================================ + console.log(`${colors.yellow}Test Suite 24: iFlow Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes24 = await loadPlatformCodes(); + const iflowInstaller = platformCodes24.platforms.iflow?.installer; + + assert(iflowInstaller?.target_dir === '.iflow/skills', 'iFlow target_dir uses native skills path'); + assert(iflowInstaller?.skill_format === true, 'iFlow installer enables native skill output'); + assert( + Array.isArray(iflowInstaller?.legacy_targets) && iflowInstaller.legacy_targets.includes('.iflow/commands'), + 'iFlow installer cleans legacy commands output', + ); + + const tempProjectDir24 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-iflow-test-')); + const installedBmadDir24 = await createTestBmadFixture(); + const legacyDir24 = path.join(tempProjectDir24, '.iflow', 'commands'); + await fs.ensureDir(legacyDir24); + await fs.writeFile(path.join(legacyDir24, 'bmad-legacy.md'), 'legacy\n'); + + const ideManager24 = new IdeManager(); + await ideManager24.ensureInitialized(); + const result24 = await ideManager24.setup('iflow', tempProjectDir24, installedBmadDir24, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result24.success === true, 'iFlow setup succeeds against temp project'); + + const skillFile24 = path.join(tempProjectDir24, '.iflow', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile24), 'iFlow install writes SKILL.md directory output'); + + // Verify name frontmatter matches directory name + const skillContent24 = await fs.readFile(skillFile24, 'utf8'); + const nameMatch24 = skillContent24.match(/^name:\s*(.+)$/m); + assert(nameMatch24 && nameMatch24[1].trim() === 'bmad-master', 'iFlow skill name frontmatter matches directory name exactly'); + + assert(!(await fs.pathExists(path.join(tempProjectDir24, '.iflow', 'commands'))), 'iFlow setup removes legacy commands dir'); + + await fs.remove(tempProjectDir24); + await fs.remove(installedBmadDir24); + } catch (error) { + assert(false, 'iFlow native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Suite 25: QwenCoder Native Skills + // ============================================================ + console.log(`${colors.yellow}Test Suite 25: QwenCoder Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes25 = await loadPlatformCodes(); + const qwenInstaller = platformCodes25.platforms.qwen?.installer; + + assert(qwenInstaller?.target_dir === '.qwen/skills', 'QwenCoder target_dir uses native skills path'); + assert(qwenInstaller?.skill_format === true, 'QwenCoder installer enables native skill output'); + assert( + Array.isArray(qwenInstaller?.legacy_targets) && qwenInstaller.legacy_targets.includes('.qwen/commands'), + 'QwenCoder installer cleans legacy commands output', + ); + + const tempProjectDir25 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-qwen-test-')); + const installedBmadDir25 = await createTestBmadFixture(); + const legacyDir25 = path.join(tempProjectDir25, '.qwen', 'commands'); + await fs.ensureDir(legacyDir25); + await fs.writeFile(path.join(legacyDir25, 'bmad-legacy.md'), 'legacy\n'); + + const ideManager25 = new IdeManager(); + await ideManager25.ensureInitialized(); + const result25 = await ideManager25.setup('qwen', tempProjectDir25, installedBmadDir25, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result25.success === true, 'QwenCoder setup succeeds against temp project'); + + const skillFile25 = path.join(tempProjectDir25, '.qwen', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile25), 'QwenCoder install writes SKILL.md directory output'); + + // Verify name frontmatter matches directory name + const skillContent25 = await fs.readFile(skillFile25, 'utf8'); + const nameMatch25 = skillContent25.match(/^name:\s*(.+)$/m); + assert(nameMatch25 && nameMatch25[1].trim() === 'bmad-master', 'QwenCoder skill name frontmatter matches directory name exactly'); + + assert(!(await fs.pathExists(path.join(tempProjectDir25, '.qwen', 'commands'))), 'QwenCoder setup removes legacy commands dir'); + + await fs.remove(tempProjectDir25); + await fs.remove(installedBmadDir25); + } catch (error) { + assert(false, 'QwenCoder native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Suite 26: Rovo Dev Native Skills + // ============================================================ + console.log(`${colors.yellow}Test Suite 26: Rovo Dev Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes26 = await loadPlatformCodes(); + const rovoInstaller = platformCodes26.platforms['rovo-dev']?.installer; + + assert(rovoInstaller?.target_dir === '.rovodev/skills', 'Rovo Dev target_dir uses native skills path'); + assert(rovoInstaller?.skill_format === true, 'Rovo Dev installer enables native skill output'); + assert( + Array.isArray(rovoInstaller?.legacy_targets) && rovoInstaller.legacy_targets.includes('.rovodev/workflows'), + 'Rovo Dev installer cleans legacy workflows output', + ); + + const tempProjectDir26 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-rovodev-test-')); + const installedBmadDir26 = await createTestBmadFixture(); + const legacyDir26 = path.join(tempProjectDir26, '.rovodev', 'workflows'); + await fs.ensureDir(legacyDir26); + await fs.writeFile(path.join(legacyDir26, 'bmad-legacy.md'), 'legacy\n'); + + // Create a prompts.yml with BMAD entries and a user entry + const yaml26 = require('yaml'); + const promptsPath26 = path.join(tempProjectDir26, '.rovodev', 'prompts.yml'); + const promptsContent26 = yaml26.stringify({ + prompts: [ + { name: 'bmad-bmm-create-prd', description: 'BMAD workflow', content_file: 'workflows/bmad-bmm-create-prd.md' }, + { name: 'my-custom-prompt', description: 'User prompt', content_file: 'custom.md' }, + ], + }); + await fs.writeFile(promptsPath26, promptsContent26); + + const ideManager26 = new IdeManager(); + await ideManager26.ensureInitialized(); + const result26 = await ideManager26.setup('rovo-dev', tempProjectDir26, installedBmadDir26, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result26.success === true, 'Rovo Dev setup succeeds against temp project'); + + const skillFile26 = path.join(tempProjectDir26, '.rovodev', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile26), 'Rovo Dev install writes SKILL.md directory output'); + + // Verify name frontmatter matches directory name + const skillContent26 = await fs.readFile(skillFile26, 'utf8'); + const nameMatch26 = skillContent26.match(/^name:\s*(.+)$/m); + assert(nameMatch26 && nameMatch26[1].trim() === 'bmad-master', 'Rovo Dev skill name frontmatter matches directory name exactly'); + + assert(!(await fs.pathExists(path.join(tempProjectDir26, '.rovodev', 'workflows'))), 'Rovo Dev setup removes legacy workflows dir'); + + // Verify prompts.yml cleanup: BMAD entries removed, user entry preserved + const cleanedPrompts26 = yaml26.parse(await fs.readFile(promptsPath26, 'utf8')); + assert( + Array.isArray(cleanedPrompts26.prompts) && cleanedPrompts26.prompts.length === 1, + 'Rovo Dev cleanup removes BMAD entries from prompts.yml', + ); + assert(cleanedPrompts26.prompts[0].name === 'my-custom-prompt', 'Rovo Dev cleanup preserves non-BMAD entries in prompts.yml'); + + await fs.remove(tempProjectDir26); + await fs.remove(installedBmadDir26); + } catch (error) { + assert(false, 'Rovo Dev native skills migration test succeeds', error.message); + } + + console.log(''); + + // ============================================================ + // Suite 27: Cleanup preserves bmad-os-* skills + // ============================================================ + console.log(`${colors.yellow}Test Suite 27: Cleanup preserves bmad-os-* skills${colors.reset}\n`); + + try { + const tempProjectDir27 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-os-preserve-test-')); + const installedBmadDir27 = await createTestBmadFixture(); + + // Pre-populate .claude/skills with bmad-os-* skills (version-controlled repo skills) + const osSkillDir27 = path.join(tempProjectDir27, '.claude', 'skills', 'bmad-os-review-pr'); + await fs.ensureDir(osSkillDir27); + await fs.writeFile( + path.join(osSkillDir27, 'SKILL.md'), + '---\nname: bmad-os-review-pr\ndescription: Review PRs\n---\nOS skill content\n', + ); + + const osSkillDir27b = path.join(tempProjectDir27, '.claude', 'skills', 'bmad-os-release-module'); + await fs.ensureDir(osSkillDir27b); + await fs.writeFile( + path.join(osSkillDir27b, 'SKILL.md'), + '---\nname: bmad-os-release-module\ndescription: Release module\n---\nOS skill content\n', + ); + + // Also add a regular bmad skill that SHOULD be cleaned up + const regularSkillDir27 = path.join(tempProjectDir27, '.claude', 'skills', 'bmad-architect'); + await fs.ensureDir(regularSkillDir27); + await fs.writeFile( + path.join(regularSkillDir27, 'SKILL.md'), + '---\nname: bmad-architect\ndescription: Architect\n---\nOld skill content\n', + ); + + // Run Claude Code setup (which triggers cleanup then install) + const ideManager27 = new IdeManager(); + await ideManager27.ensureInitialized(); + const result27 = await ideManager27.setup('claude-code', tempProjectDir27, installedBmadDir27, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result27.success === true, 'Claude Code setup succeeds with bmad-os-* skills present'); + + // bmad-os-* skills must survive + assert(await fs.pathExists(osSkillDir27), 'Cleanup preserves bmad-os-review-pr skill'); + assert(await fs.pathExists(osSkillDir27b), 'Cleanup preserves bmad-os-release-module skill'); + + // bmad-os skill content must be untouched + const osContent27 = await fs.readFile(path.join(osSkillDir27, 'SKILL.md'), 'utf8'); + assert(osContent27.includes('OS skill content'), 'bmad-os-review-pr skill content is unchanged'); + + // Regular bmad skill should have been replaced by fresh install + const newSkillFile27 = path.join(tempProjectDir27, '.claude', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(newSkillFile27), 'Fresh bmad skills are installed alongside preserved bmad-os-* skills'); + + // Stale non-bmad-os skill must have been removed by cleanup + assert(!(await fs.pathExists(regularSkillDir27)), 'Cleanup removes stale non-bmad-os skills'); + + await fs.remove(tempProjectDir27); + await fs.remove(installedBmadDir27); + } catch (error) { + assert(false, 'bmad-os-* skill preservation test succeeds', error.message); + } + + console.log(''); + // ============================================================ // Summary // ============================================================ diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index fe8b88d7c..1d9868b60 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -713,10 +713,30 @@ class Installer { } // Merge tool selection into config (for both quick update and regular flow) - config.ides = toolSelection.ides; + // Normalize IDE keys to lowercase so they match handler map keys consistently + config.ides = (toolSelection.ides || []).map((ide) => ide.toLowerCase()); config.skipIde = toolSelection.skipIde; const ideConfigurations = toolSelection.configurations; + // Early check: fail fast if ALL selected IDEs are suspended + if (config.ides && config.ides.length > 0) { + await this.ideManager.ensureInitialized(); + const suspendedIdes = config.ides.filter((ide) => { + const handler = this.ideManager.handlers.get(ide); + return handler?.platformConfig?.suspended; + }); + + if (suspendedIdes.length > 0 && suspendedIdes.length === config.ides.length) { + for (const ide of suspendedIdes) { + const handler = this.ideManager.handlers.get(ide); + await prompts.log.error(`${handler.displayName || ide}: ${handler.platformConfig.suspended}`); + } + throw new Error( + `All selected tool(s) are suspended: ${suspendedIdes.join(', ')}. Installation aborted to prevent upgrading _bmad/ without a working IDE configuration.`, + ); + } + } + // Detect IDEs that were previously installed but are NOT in the new selection (to be removed) if (config._isUpdate && config._existingInstall) { const previouslyInstalledIdes = new Set(config._existingInstall.ides || []); @@ -1335,6 +1355,19 @@ class Installer { } catch { // Ensure the original error is never swallowed by a logging failure } + + // Clean up any temp backup directories that were created before the failure + try { + if (config._tempBackupDir && (await fs.pathExists(config._tempBackupDir))) { + await fs.remove(config._tempBackupDir); + } + if (config._tempModifiedBackupDir && (await fs.pathExists(config._tempModifiedBackupDir))) { + await fs.remove(config._tempModifiedBackupDir); + } + } catch { + // Best-effort cleanup — don't mask the original error + } + throw error; } } diff --git a/tools/cli/installers/lib/ide/_config-driven.js b/tools/cli/installers/lib/ide/_config-driven.js index d23d8d6d0..0a311a68d 100644 --- a/tools/cli/installers/lib/ide/_config-driven.js +++ b/tools/cli/installers/lib/ide/_config-driven.js @@ -655,6 +655,21 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}} } } + // Strip BMAD markers from copilot-instructions.md if present + if (this.name === 'github-copilot') { + await this.cleanupCopilotInstructions(projectDir, options); + } + + // Strip BMAD modes from .kilocodemodes if present + if (this.name === 'kilo') { + await this.cleanupKiloModes(projectDir, options); + } + + // Strip BMAD entries from .rovodev/prompts.yml if present + if (this.name === 'rovo-dev') { + await this.cleanupRovoDevPrompts(projectDir, options); + } + // Clean all target directories if (this.installerConfig?.targets) { const parentDirs = new Set(); @@ -741,7 +756,7 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}} if (!entry || typeof entry !== 'string') { continue; } - if (entry.startsWith('bmad')) { + if (entry.startsWith('bmad') && !entry.startsWith('bmad-os-')) { const entryPath = path.join(targetPath, entry); try { await fs.remove(entryPath); @@ -768,6 +783,121 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}} } } } + /** + * Strip BMAD-owned content from .github/copilot-instructions.md. + * The old custom installer injected content between and markers. + * Deletes the file if nothing remains. Restores .bak backup if one exists. + */ + async cleanupCopilotInstructions(projectDir, options = {}) { + const filePath = path.join(projectDir, '.github', 'copilot-instructions.md'); + + if (!(await fs.pathExists(filePath))) return; + + try { + const content = await fs.readFile(filePath, 'utf8'); + const startIdx = content.indexOf(''); + const endIdx = content.indexOf(''); + + if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) return; + + const cleaned = content.slice(0, startIdx) + content.slice(endIdx + ''.length); + + if (cleaned.trim().length === 0) { + await fs.remove(filePath); + const backupPath = `${filePath}.bak`; + if (await fs.pathExists(backupPath)) { + await fs.rename(backupPath, filePath); + if (!options.silent) await prompts.log.message(' Restored copilot-instructions.md from backup'); + } + } else { + await fs.writeFile(filePath, cleaned, 'utf8'); + const backupPath = `${filePath}.bak`; + if (await fs.pathExists(backupPath)) await fs.remove(backupPath); + } + + if (!options.silent) await prompts.log.message(' Cleaned BMAD markers from copilot-instructions.md'); + } catch { + if (!options.silent) await prompts.log.warn(' Warning: Could not clean BMAD markers from copilot-instructions.md'); + } + } + + /** + * Strip BMAD-owned modes from .kilocodemodes. + * The old custom kilo.js installer added modes with slug starting with 'bmad-'. + * Parses YAML, filters out BMAD modes, rewrites. Leaves file as-is on parse failure. + */ + async cleanupKiloModes(projectDir, options = {}) { + const kiloModesPath = path.join(projectDir, '.kilocodemodes'); + + if (!(await fs.pathExists(kiloModesPath))) return; + + const content = await fs.readFile(kiloModesPath, 'utf8'); + + let config; + try { + config = yaml.parse(content) || {}; + } catch { + if (!options.silent) await prompts.log.warn(' Warning: Could not parse .kilocodemodes for cleanup'); + return; + } + + if (!Array.isArray(config.customModes)) return; + + const originalCount = config.customModes.length; + config.customModes = config.customModes.filter((mode) => mode && (!mode.slug || !mode.slug.startsWith('bmad-'))); + const removedCount = originalCount - config.customModes.length; + + if (removedCount > 0) { + try { + await fs.writeFile(kiloModesPath, yaml.stringify(config, { lineWidth: 0 })); + if (!options.silent) await prompts.log.message(` Removed ${removedCount} BMAD modes from .kilocodemodes`); + } catch { + if (!options.silent) await prompts.log.warn(' Warning: Could not write .kilocodemodes during cleanup'); + } + } + } + + /** + * Strip BMAD-owned entries from .rovodev/prompts.yml. + * The old custom rovodev.js installer registered workflows in prompts.yml. + * Parses YAML, filters out entries with name starting with 'bmad-', rewrites. + * Removes the file if no entries remain. + */ + async cleanupRovoDevPrompts(projectDir, options = {}) { + const promptsPath = path.join(projectDir, '.rovodev', 'prompts.yml'); + + if (!(await fs.pathExists(promptsPath))) return; + + const content = await fs.readFile(promptsPath, 'utf8'); + + let config; + try { + config = yaml.parse(content) || {}; + } catch { + if (!options.silent) await prompts.log.warn(' Warning: Could not parse prompts.yml for cleanup'); + return; + } + + if (!Array.isArray(config.prompts)) return; + + const originalCount = config.prompts.length; + config.prompts = config.prompts.filter((entry) => entry && (!entry.name || !entry.name.startsWith('bmad-'))); + const removedCount = originalCount - config.prompts.length; + + if (removedCount > 0) { + try { + if (config.prompts.length === 0) { + await fs.remove(promptsPath); + } else { + await fs.writeFile(promptsPath, yaml.stringify(config, { lineWidth: 0 })); + } + if (!options.silent) await prompts.log.message(` Removed ${removedCount} BMAD entries from prompts.yml`); + } catch { + if (!options.silent) await prompts.log.warn(' Warning: Could not write prompts.yml during cleanup'); + } + } + } + /** * Check ancestor directories for existing BMAD files in the same target_dir. * IDEs like Claude Code inherit commands from parent directories, so an existing @@ -788,7 +918,9 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}} try { if (await fs.pathExists(candidatePath)) { const entries = await fs.readdir(candidatePath); - const hasBmad = entries.some((e) => typeof e === 'string' && e.toLowerCase().startsWith('bmad')); + const hasBmad = entries.some( + (e) => typeof e === 'string' && e.toLowerCase().startsWith('bmad') && !e.toLowerCase().startsWith('bmad-os-'), + ); if (hasBmad) { return candidatePath; } diff --git a/tools/cli/installers/lib/ide/github-copilot.js b/tools/cli/installers/lib/ide/github-copilot.js deleted file mode 100644 index 059127f81..000000000 --- a/tools/cli/installers/lib/ide/github-copilot.js +++ /dev/null @@ -1,699 +0,0 @@ -const path = require('node:path'); -const { BaseIdeSetup } = require('./_base-ide'); -const prompts = require('../../../lib/prompts'); -const { AgentCommandGenerator } = require('./shared/agent-command-generator'); -const { BMAD_FOLDER_NAME, toDashPath } = require('./shared/path-utils'); -const fs = require('fs-extra'); -const csv = require('csv-parse/sync'); -const yaml = require('yaml'); - -/** - * GitHub Copilot setup handler - * Creates agents in .github/agents/, prompts in .github/prompts/, - * copilot-instructions.md, and configures VS Code settings - */ -class GitHubCopilotSetup extends BaseIdeSetup { - constructor() { - super('github-copilot', 'GitHub Copilot', false); - // Don't set configDir to '.github' — nearly every GitHub repo has that directory, - // which would cause the base detect() to false-positive. Use detectionPaths instead. - this.configDir = null; - this.githubDir = '.github'; - this.agentsDir = 'agents'; - this.promptsDir = 'prompts'; - this.detectionPaths = ['.github/copilot-instructions.md', '.github/agents']; - } - - /** - * Setup GitHub Copilot configuration - * @param {string} projectDir - Project directory - * @param {string} bmadDir - BMAD installation directory - * @param {Object} options - Setup options - */ - async setup(projectDir, bmadDir, options = {}) { - if (!options.silent) await prompts.log.info(`Setting up ${this.name}...`); - - // Create .github/agents and .github/prompts directories - const githubDir = path.join(projectDir, this.githubDir); - const agentsDir = path.join(githubDir, this.agentsDir); - const promptsDir = path.join(githubDir, this.promptsDir); - await this.ensureDir(agentsDir); - await this.ensureDir(promptsDir); - - // Preserve any customised tool permissions from existing files before cleanup - this.existingToolPermissions = await this.collectExistingToolPermissions(projectDir); - - // Clean up any existing BMAD files before reinstalling - await this.cleanup(projectDir); - - // Load agent manifest for enriched descriptions - const agentManifest = await this.loadAgentManifest(bmadDir); - - // Generate agent launchers - const agentGen = new AgentCommandGenerator(this.bmadFolderName); - const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []); - - // Create agent .agent.md files - let agentCount = 0; - for (const artifact of agentArtifacts) { - const agentMeta = agentManifest.get(artifact.name); - - // Compute fileName first so we can look up any existing tool permissions - const dashName = toDashPath(artifact.relativePath); - const fileName = dashName.replace(/\.md$/, '.agent.md'); - const toolsStr = this.getToolsForFile(fileName); - const agentContent = this.createAgentContent(artifact, agentMeta, toolsStr); - const targetPath = path.join(agentsDir, fileName); - await this.writeFile(targetPath, agentContent); - agentCount++; - } - - // Generate prompt files from bmad-help.csv - const promptCount = await this.generatePromptFiles(projectDir, bmadDir, agentArtifacts, agentManifest); - - // Generate copilot-instructions.md - await this.generateCopilotInstructions(projectDir, bmadDir, agentManifest, options); - - if (!options.silent) await prompts.log.success(`${this.name} configured: ${agentCount} agents, ${promptCount} prompts → .github/`); - - return { - success: true, - results: { - agents: agentCount, - workflows: promptCount, - tasks: 0, - tools: 0, - }, - }; - } - - /** - * Load agent manifest CSV into a Map keyed by agent name - * @param {string} bmadDir - BMAD installation directory - * @returns {Map} Agent metadata keyed by name - */ - async loadAgentManifest(bmadDir) { - const manifestPath = path.join(bmadDir, '_config', 'agent-manifest.csv'); - const agents = new Map(); - - if (!(await fs.pathExists(manifestPath))) { - return agents; - } - - try { - const csvContent = await fs.readFile(manifestPath, 'utf8'); - const records = csv.parse(csvContent, { - columns: true, - skip_empty_lines: true, - }); - - for (const record of records) { - agents.set(record.name, record); - } - } catch { - // Gracefully degrade if manifest is unreadable/malformed - } - - return agents; - } - - /** - * Load bmad-help.csv to drive prompt generation - * @param {string} bmadDir - BMAD installation directory - * @returns {Array|null} Parsed CSV rows - */ - async loadBmadHelp(bmadDir) { - const helpPath = path.join(bmadDir, '_config', 'bmad-help.csv'); - - if (!(await fs.pathExists(helpPath))) { - return null; - } - - try { - const csvContent = await fs.readFile(helpPath, 'utf8'); - return csv.parse(csvContent, { - columns: true, - skip_empty_lines: true, - }); - } catch { - // Gracefully degrade if help CSV is unreadable/malformed - return null; - } - } - - /** - * Create agent .agent.md content with enriched description - * @param {Object} artifact - Agent artifact from AgentCommandGenerator - * @param {Object|undefined} manifestEntry - Agent manifest entry with metadata - * @returns {string} Agent file content - */ - createAgentContent(artifact, manifestEntry, toolsStr) { - // Build enriched description from manifest metadata - let description; - if (manifestEntry) { - const persona = manifestEntry.displayName || artifact.name; - const title = manifestEntry.title || this.formatTitle(artifact.name); - const capabilities = manifestEntry.capabilities || 'agent capabilities'; - description = `${persona} — ${title}: ${capabilities}`; - } else { - description = `Activates the ${this.formatTitle(artifact.name)} agent persona.`; - } - - // Build the agent file path for the activation block - const agentPath = artifact.agentPath || artifact.relativePath; - const agentFilePath = `{project-root}/${this.bmadFolderName}/${agentPath}`; - - return `--- -description: '${description.replaceAll("'", "''")}' -tools: ${toolsStr} ---- - -You must fully embody this agent's persona and follow all activation instructions exactly as specified. - - -1. LOAD the FULL agent file from ${agentFilePath} -2. READ its entire contents - this contains the complete agent persona, menu, and instructions -3. FOLLOW every step in the section precisely -4. DISPLAY the welcome/greeting as instructed -5. PRESENT the numbered menu -6. WAIT for user input before proceeding - -`; - } - - /** - * Generate .prompt.md files for workflows, tasks, tech-writer commands, and agent activators - * @param {string} projectDir - Project directory - * @param {string} bmadDir - BMAD installation directory - * @param {Array} agentArtifacts - Agent artifacts for activator generation - * @param {Map} agentManifest - Agent manifest data - * @returns {number} Count of prompts generated - */ - async generatePromptFiles(projectDir, bmadDir, agentArtifacts, agentManifest) { - const promptsDir = path.join(projectDir, this.githubDir, this.promptsDir); - let promptCount = 0; - - // Load bmad-help.csv to drive workflow/task prompt generation - const helpEntries = await this.loadBmadHelp(bmadDir); - - if (helpEntries) { - for (const entry of helpEntries) { - const command = entry.command; - if (!command) continue; // Skip entries without a command (tech-writer commands have no command column) - - const workflowFile = entry['workflow-file']; - if (!workflowFile) continue; // Skip entries with no workflow file path - const promptFileName = `${command}.prompt.md`; - const toolsStr = this.getToolsForFile(promptFileName); - const promptContent = this.createWorkflowPromptContent(entry, workflowFile, toolsStr); - const promptPath = path.join(promptsDir, promptFileName); - await this.writeFile(promptPath, promptContent); - promptCount++; - } - - // Generate tech-writer command prompts (entries with no command column) - for (const entry of helpEntries) { - if (entry.command) continue; // Already handled above - const techWriterPrompt = this.createTechWriterPromptContent(entry); - if (techWriterPrompt) { - const promptFileName = `${techWriterPrompt.fileName}.prompt.md`; - const promptPath = path.join(promptsDir, promptFileName); - await this.writeFile(promptPath, techWriterPrompt.content); - promptCount++; - } - } - } - - // Generate agent activator prompts (Pattern D) - for (const artifact of agentArtifacts) { - const agentMeta = agentManifest.get(artifact.name); - const fileName = `bmad-${artifact.name}.prompt.md`; - const toolsStr = this.getToolsForFile(fileName); - const promptContent = this.createAgentActivatorPromptContent(artifact, agentMeta, toolsStr); - const promptPath = path.join(promptsDir, fileName); - await this.writeFile(promptPath, promptContent); - promptCount++; - } - - return promptCount; - } - - /** - * Create prompt content for a workflow/task entry from bmad-help.csv - * Determines the pattern (A, B, or A for .xml tasks) based on file extension - * @param {Object} entry - bmad-help.csv row - * @param {string} workflowFile - Workflow file path - * @returns {string} Prompt file content - */ - createWorkflowPromptContent(entry, workflowFile, toolsStr) { - const description = this.escapeYamlSingleQuote(this.createPromptDescription(entry.name)); - // bmm/config.yaml is safe to hardcode here: these prompts are only generated when - // bmad-help.csv exists (bmm module data), so bmm is guaranteed to be installed. - const configLine = `1. Load {project-root}/${this.bmadFolderName}/bmm/config.yaml and store ALL fields as session variables`; - - let body; - if (workflowFile.endsWith('.yaml')) { - // Pattern B: YAML-based workflows — use workflow engine - 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`; - } else if (workflowFile.endsWith('.xml')) { - // Pattern A variant: XML tasks — load and execute directly - body = `${configLine} -2. Load and execute the task at {project-root}/${workflowFile}`; - } else { - // Pattern A: MD workflows — load and follow directly - body = `${configLine} -2. Load and follow the workflow at {project-root}/${workflowFile}`; - } - - return `--- -description: '${description}' -agent: 'agent' -tools: ${toolsStr} ---- - -${body} -`; - } - - /** - * Create a short 2-5 word description for a prompt from the entry name - * @param {string} name - Entry name from bmad-help.csv - * @returns {string} Short description - */ - createPromptDescription(name) { - const descriptionMap = { - 'Brainstorm Project': 'Brainstorm ideas', - 'Market Research': 'Market research', - 'Domain Research': 'Domain research', - 'Technical Research': 'Technical research', - 'Create Brief': 'Create product brief', - 'Create PRD': 'Create PRD', - 'Validate PRD': 'Validate PRD', - 'Edit PRD': 'Edit PRD', - 'Create UX': 'Create UX design', - 'Create Architecture': 'Create architecture', - 'Create Epics and Stories': 'Create epics and stories', - 'Check Implementation Readiness': 'Check implementation readiness', - 'Sprint Planning': 'Sprint planning', - 'Sprint Status': 'Sprint status', - 'Create Story': 'Create story', - 'Validate Story': 'Validate story', - 'Dev Story': 'Dev story', - 'QA Automation Test': 'QA automation', - 'Code Review': 'Code review', - Retrospective: 'Retrospective', - 'Document Project': 'Document project', - 'Generate Project Context': 'Generate project context', - 'Quick Spec': 'Quick spec', - 'Quick Dev': 'Quick dev', - 'Correct Course': 'Correct course', - Brainstorming: 'Brainstorm ideas', - 'Party Mode': 'Party mode', - 'bmad-help': 'BMAD help', - 'Index Docs': 'Index documents', - 'Shard Document': 'Shard document', - 'Editorial Review - Prose': 'Editorial review prose', - 'Editorial Review - Structure': 'Editorial review structure', - 'Adversarial Review (General)': 'Adversarial review', - }; - - return descriptionMap[name] || name; - } - - /** - * Create prompt content for tech-writer agent-only commands (Pattern C) - * @param {Object} entry - bmad-help.csv row - * @returns {Object|null} { fileName, content } or null if not a tech-writer command - */ - createTechWriterPromptContent(entry) { - if (entry['agent-name'] !== 'tech-writer') return null; - - const techWriterCommands = { - 'Write Document': { code: 'WD', file: 'bmad-bmm-write-document', description: 'Write document' }, - 'Update Standards': { code: 'US', file: 'bmad-bmm-update-standards', description: 'Update standards' }, - 'Mermaid Generate': { code: 'MG', file: 'bmad-bmm-mermaid-generate', description: 'Mermaid generate' }, - 'Validate Document': { code: 'VD', file: 'bmad-bmm-validate-document', description: 'Validate document' }, - 'Explain Concept': { code: 'EC', file: 'bmad-bmm-explain-concept', description: 'Explain concept' }, - }; - - const cmd = techWriterCommands[entry.name]; - if (!cmd) return null; - - const safeDescription = this.escapeYamlSingleQuote(cmd.description); - const toolsStr = this.getToolsForFile(`${cmd.file}.prompt.md`); - - const content = `--- -description: '${safeDescription}' -agent: 'agent' -tools: ${toolsStr} ---- - -1. Load {project-root}/${this.bmadFolderName}/bmm/config.yaml and store ALL fields as session variables -2. Load the full agent file from {project-root}/${this.bmadFolderName}/bmm/agents/tech-writer/tech-writer.md and activate the Paige (Technical Writer) persona -3. Execute the ${entry.name} menu command (${cmd.code}) -`; - - return { fileName: cmd.file, content }; - } - - /** - * Create agent activator prompt content (Pattern D) - * @param {Object} artifact - Agent artifact - * @param {Object|undefined} manifestEntry - Agent manifest entry - * @returns {string} Prompt file content - */ - createAgentActivatorPromptContent(artifact, manifestEntry, toolsStr) { - let description; - if (manifestEntry) { - description = manifestEntry.title || this.formatTitle(artifact.name); - } else { - description = this.formatTitle(artifact.name); - } - - const safeDescription = this.escapeYamlSingleQuote(description); - const agentPath = artifact.agentPath || artifact.relativePath; - const agentFilePath = `{project-root}/${this.bmadFolderName}/${agentPath}`; - - // bmm/config.yaml is safe to hardcode: agent activators are only generated from - // bmm agent artifacts, so bmm is guaranteed to be installed. - return `--- -description: '${safeDescription}' -agent: 'agent' -tools: ${toolsStr} ---- - -1. Load {project-root}/${this.bmadFolderName}/bmm/config.yaml and store ALL fields as session variables -2. Load the full agent file from ${agentFilePath} -3. Follow ALL activation instructions in the agent file -4. Display the welcome/greeting as instructed -5. Present the numbered menu -6. Wait for user input before proceeding -`; - } - - /** - * Generate copilot-instructions.md from module config - * @param {string} projectDir - Project directory - * @param {string} bmadDir - BMAD installation directory - * @param {Map} agentManifest - Agent manifest data - */ - async generateCopilotInstructions(projectDir, bmadDir, agentManifest, options = {}) { - const configVars = await this.loadModuleConfig(bmadDir); - - // Build the agents table from the manifest - let agentsTable = '| Agent | Persona | Title | Capabilities |\n|---|---|---|---|\n'; - const agentOrder = [ - 'bmad-master', - 'analyst', - 'architect', - 'dev', - 'pm', - 'qa', - 'quick-flow-solo-dev', - 'sm', - 'tech-writer', - 'ux-designer', - ]; - - for (const agentName of agentOrder) { - const meta = agentManifest.get(agentName); - if (meta) { - const capabilities = meta.capabilities || 'agent capabilities'; - const cleanTitle = (meta.title || '').replaceAll('""', '"'); - agentsTable += `| ${agentName} | ${meta.displayName} | ${cleanTitle} | ${capabilities} |\n`; - } - } - - const bmad = this.bmadFolderName; - const bmadSection = `# BMAD Method — Project Instructions - -## Project Configuration - -- **Project**: ${configVars.project_name || '{{project_name}}'} -- **User**: ${configVars.user_name || '{{user_name}}'} -- **Communication Language**: ${configVars.communication_language || '{{communication_language}}'} -- **Document Output Language**: ${configVars.document_output_language || '{{document_output_language}}'} -- **User Skill Level**: ${configVars.user_skill_level || '{{user_skill_level}}'} -- **Output Folder**: ${configVars.output_folder || '{{output_folder}}'} -- **Planning Artifacts**: ${configVars.planning_artifacts || '{{planning_artifacts}}'} -- **Implementation Artifacts**: ${configVars.implementation_artifacts || '{{implementation_artifacts}}'} -- **Project Knowledge**: ${configVars.project_knowledge || '{{project_knowledge}}'} - -## BMAD Runtime Structure - -- **Agent definitions**: \`${bmad}/bmm/agents/\` (BMM module) and \`${bmad}/core/agents/\` (core) -- **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) -- **Module configuration**: \`${bmad}/bmm/config.yaml\` -- **Core configuration**: \`${bmad}/core/config.yaml\` -- **Agent manifest**: \`${bmad}/_config/agent-manifest.csv\` -- **Workflow manifest**: \`${bmad}/_config/workflow-manifest.csv\` -- **Help manifest**: \`${bmad}/_config/bmad-help.csv\` -- **Agent memory**: \`${bmad}/_memory/\` - -## Key Conventions - -- 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 -- 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 - -## Available Agents - -${agentsTable} -## Slash Commands - -Type \`/bmad-\` in Copilot Chat to see all available BMAD workflows and agent activators. Agents are also available in the agents dropdown.`; - - const instructionsPath = path.join(projectDir, this.githubDir, 'copilot-instructions.md'); - const markerStart = ''; - const markerEnd = ''; - const markedContent = `${markerStart}\n${bmadSection}\n${markerEnd}`; - - if (await fs.pathExists(instructionsPath)) { - const existing = await fs.readFile(instructionsPath, 'utf8'); - const startIdx = existing.indexOf(markerStart); - const endIdx = existing.indexOf(markerEnd); - - if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) { - // Replace only the BMAD section between markers - const before = existing.slice(0, startIdx); - const after = existing.slice(endIdx + markerEnd.length); - const merged = `${before}${markedContent}${after}`; - await this.writeFile(instructionsPath, merged); - } else { - // Existing file without markers — back it up before overwriting - const backupPath = `${instructionsPath}.bak`; - await fs.copy(instructionsPath, backupPath); - if (!options.silent) await prompts.log.warn(` Backed up copilot-instructions.md → .bak`); - await this.writeFile(instructionsPath, `${markedContent}\n`); - } - } else { - // No existing file — create fresh with markers - await this.writeFile(instructionsPath, `${markedContent}\n`); - } - } - - /** - * Load module config.yaml for template variables - * @param {string} bmadDir - BMAD installation directory - * @returns {Object} Config variables - */ - async loadModuleConfig(bmadDir) { - const bmmConfigPath = path.join(bmadDir, 'bmm', 'config.yaml'); - const coreConfigPath = path.join(bmadDir, 'core', 'config.yaml'); - - for (const configPath of [bmmConfigPath, coreConfigPath]) { - if (await fs.pathExists(configPath)) { - try { - const content = await fs.readFile(configPath, 'utf8'); - return yaml.parse(content) || {}; - } catch { - // Fall through to next config - } - } - } - - return {}; - } - - /** - * Escape a string for use inside YAML single-quoted values. - * In YAML, the only escape inside single quotes is '' for a literal '. - * @param {string} value - Raw string - * @returns {string} Escaped string safe for YAML single-quoted context - */ - escapeYamlSingleQuote(value) { - return (value || '').replaceAll("'", "''"); - } - - /** - * Scan existing agent and prompt files for customised tool permissions before cleanup. - * Returns a Map so permissions can be preserved across reinstalls. - * @param {string} projectDir - Project directory - * @returns {Map} Existing tool permissions keyed by filename - */ - async collectExistingToolPermissions(projectDir) { - const permissions = new Map(); - const dirs = [ - [path.join(projectDir, this.githubDir, this.agentsDir), /^bmad.*\.agent\.md$/], - [path.join(projectDir, this.githubDir, this.promptsDir), /^bmad-.*\.prompt\.md$/], - ]; - - for (const [dir, pattern] of dirs) { - if (!(await fs.pathExists(dir))) continue; - const files = await fs.readdir(dir); - - for (const file of files) { - if (!pattern.test(file)) continue; - - try { - const content = await fs.readFile(path.join(dir, file), 'utf8'); - const fmMatch = content.match(/^---\n([\s\S]*?)\n---/); - if (!fmMatch) continue; - - const frontmatter = yaml.parse(fmMatch[1]); - if (frontmatter && Array.isArray(frontmatter.tools)) { - permissions.set(file, frontmatter.tools); - } - } catch { - // Skip unreadable files - } - } - } - - return permissions; - } - - /** - * Get the tools array string for a file, preserving any existing customisation. - * Falls back to the default tools if no prior customisation exists. - * @param {string} fileName - Target filename (e.g. 'bmad-agent-bmm-pm.agent.md') - * @returns {string} YAML inline array string - */ - getToolsForFile(fileName) { - const defaultTools = ['read', 'edit', 'search', 'execute']; - const tools = (this.existingToolPermissions && this.existingToolPermissions.get(fileName)) || defaultTools; - return '[' + tools.map((t) => `'${t}'`).join(', ') + ']'; - } - - /** - * Format name as title - */ - formatTitle(name) { - return name - .split('-') - .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) - .join(' '); - } - - /** - * Cleanup GitHub Copilot configuration - surgically remove only BMAD files - */ - async cleanup(projectDir, options = {}) { - // Clean up agents directory - const agentsDir = path.join(projectDir, this.githubDir, this.agentsDir); - if (await fs.pathExists(agentsDir)) { - const files = await fs.readdir(agentsDir); - let removed = 0; - - for (const file of files) { - if (file.startsWith('bmad') && (file.endsWith('.agent.md') || file.endsWith('.md'))) { - await fs.remove(path.join(agentsDir, file)); - removed++; - } - } - - if (removed > 0 && !options.silent) { - await prompts.log.message(` Cleaned up ${removed} existing BMAD agents`); - } - } - - // Clean up prompts directory - const promptsDir = path.join(projectDir, this.githubDir, this.promptsDir); - if (await fs.pathExists(promptsDir)) { - const files = await fs.readdir(promptsDir); - let removed = 0; - - for (const file of files) { - if (file.startsWith('bmad-') && file.endsWith('.prompt.md')) { - await fs.remove(path.join(promptsDir, file)); - removed++; - } - } - - if (removed > 0 && !options.silent) { - await prompts.log.message(` Cleaned up ${removed} existing BMAD prompts`); - } - } - - // During uninstall, also strip BMAD markers from copilot-instructions.md. - // During reinstall (default), this is skipped because generateCopilotInstructions() - // handles marker-based replacement in a single read-modify-write pass, - // which correctly preserves user content outside the markers. - if (options.isUninstall) { - await this.cleanupCopilotInstructions(projectDir, options); - } - } - - /** - * Strip BMAD marker section from copilot-instructions.md - * If file becomes empty after stripping, delete it. - * If a .bak backup exists and the main file was deleted, restore the backup. - * @param {string} projectDir - Project directory - * @param {Object} [options] - Options (e.g. { silent: true }) - */ - async cleanupCopilotInstructions(projectDir, options = {}) { - const instructionsPath = path.join(projectDir, this.githubDir, 'copilot-instructions.md'); - const backupPath = `${instructionsPath}.bak`; - - if (!(await fs.pathExists(instructionsPath))) { - return; - } - - const content = await fs.readFile(instructionsPath, 'utf8'); - const markerStart = ''; - const markerEnd = ''; - const startIdx = content.indexOf(markerStart); - const endIdx = content.indexOf(markerEnd); - - if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) { - return; // No valid markers found - } - - // Strip the marker section (including markers) - const before = content.slice(0, startIdx); - const after = content.slice(endIdx + markerEnd.length); - const cleaned = before + after; - - if (cleaned.trim().length === 0) { - // File is empty after stripping — delete it - await fs.remove(instructionsPath); - - // If backup exists, restore it - if (await fs.pathExists(backupPath)) { - await fs.rename(backupPath, instructionsPath); - if (!options.silent) { - await prompts.log.message(' Restored copilot-instructions.md from backup'); - } - } - } else { - // Write cleaned content back (preserve original whitespace) - await fs.writeFile(instructionsPath, cleaned, 'utf8'); - - // If backup exists, it's stale now — remove it - if (await fs.pathExists(backupPath)) { - await fs.remove(backupPath); - } - } - } -} - -module.exports = { GitHubCopilotSetup }; diff --git a/tools/cli/installers/lib/ide/kilo.js b/tools/cli/installers/lib/ide/kilo.js deleted file mode 100644 index 2e5734391..000000000 --- a/tools/cli/installers/lib/ide/kilo.js +++ /dev/null @@ -1,269 +0,0 @@ -const path = require('node:path'); -const { BaseIdeSetup } = require('./_base-ide'); -const yaml = require('yaml'); -const prompts = require('../../../lib/prompts'); -const { AgentCommandGenerator } = require('./shared/agent-command-generator'); -const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator'); -const { TaskToolCommandGenerator } = require('./shared/task-tool-command-generator'); - -/** - * KiloCode IDE setup handler - * Creates custom modes in .kilocodemodes file (similar to Roo) - */ -class KiloSetup extends BaseIdeSetup { - constructor() { - super('kilo', 'Kilo Code'); - this.configFile = '.kilocodemodes'; - } - - /** - * Setup KiloCode IDE configuration - * @param {string} projectDir - Project directory - * @param {string} bmadDir - BMAD installation directory - * @param {Object} options - Setup options - */ - async setup(projectDir, bmadDir, options = {}) { - if (!options.silent) await prompts.log.info(`Setting up ${this.name}...`); - - // Clean up any old BMAD installation first - await this.cleanup(projectDir, options); - - // Load existing config (may contain non-BMAD modes and other settings) - const kiloModesPath = path.join(projectDir, this.configFile); - let config = {}; - - if (await this.pathExists(kiloModesPath)) { - const existingContent = await this.readFile(kiloModesPath); - try { - config = yaml.parse(existingContent) || {}; - } catch { - // If parsing fails, start fresh but warn user - await prompts.log.warn('Warning: Could not parse existing .kilocodemodes, starting fresh'); - config = {}; - } - } - - // Ensure customModes array exists - if (!Array.isArray(config.customModes)) { - config.customModes = []; - } - - // Generate agent launchers - const agentGen = new AgentCommandGenerator(this.bmadFolderName); - const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []); - - // Create mode objects and add to config - let addedCount = 0; - - for (const artifact of agentArtifacts) { - const modeObject = await this.createModeObject(artifact, projectDir); - config.customModes.push(modeObject); - addedCount++; - } - - // Write .kilocodemodes file with proper YAML structure - const finalContent = yaml.stringify(config, { lineWidth: 0 }); - await this.writeFile(kiloModesPath, finalContent); - - // Generate workflow commands - const workflowGenerator = new WorkflowCommandGenerator(this.bmadFolderName); - const { artifacts: workflowArtifacts } = await workflowGenerator.collectWorkflowArtifacts(bmadDir); - - // Write to .kilocode/workflows/ directory - const workflowsDir = path.join(projectDir, '.kilocode', 'workflows'); - await this.ensureDir(workflowsDir); - - // Clear old BMAD workflows before writing new ones - await this.clearBmadWorkflows(workflowsDir); - - // Write workflow files - const workflowCount = await workflowGenerator.writeDashArtifacts(workflowsDir, workflowArtifacts); - - // Generate task and tool commands - const taskToolGen = new TaskToolCommandGenerator(this.bmadFolderName); - const { artifacts: taskToolArtifacts, counts: taskToolCounts } = await taskToolGen.collectTaskToolArtifacts(bmadDir); - - // Write task/tool files to workflows directory (same location as workflows) - await taskToolGen.writeDashArtifacts(workflowsDir, taskToolArtifacts); - const taskCount = taskToolCounts.tasks || 0; - const toolCount = taskToolCounts.tools || 0; - - if (!options.silent) { - await prompts.log.success( - `${this.name} configured: ${addedCount} modes, ${workflowCount} workflows, ${taskCount} tasks, ${toolCount} tools → ${this.configFile}`, - ); - } - - return { - success: true, - modes: addedCount, - workflows: workflowCount, - tasks: taskCount, - tools: toolCount, - }; - } - - /** - * Create a mode object for an agent - * @param {Object} artifact - Agent artifact - * @param {string} projectDir - Project directory - * @returns {Object} Mode object for YAML serialization - */ - async createModeObject(artifact, projectDir) { - // Extract metadata from launcher content - const titleMatch = artifact.content.match(/title="([^"]+)"/); - const title = titleMatch ? titleMatch[1] : this.formatTitle(artifact.name); - - const iconMatch = artifact.content.match(/icon="([^"]+)"/); - const icon = iconMatch ? iconMatch[1] : '🤖'; - - const whenToUseMatch = artifact.content.match(/whenToUse="([^"]+)"/); - const whenToUse = whenToUseMatch ? whenToUseMatch[1] : `Use for ${title} tasks`; - - // Get the activation header from central template (trim to avoid YAML formatting issues) - const activationHeader = (await this.getAgentCommandHeader()).trim(); - - const roleDefinitionMatch = artifact.content.match(/roleDefinition="([^"]+)"/); - const roleDefinition = roleDefinitionMatch - ? roleDefinitionMatch[1] - : `You are a ${title} specializing in ${title.toLowerCase()} tasks.`; - - // Get relative path - const relativePath = path.relative(projectDir, artifact.sourcePath).replaceAll('\\', '/'); - - // Build mode object (KiloCode uses same schema as Roo) - return { - slug: `bmad-${artifact.module}-${artifact.name}`, - name: `${icon} ${title}`, - roleDefinition: roleDefinition, - whenToUse: whenToUse, - customInstructions: `${activationHeader} Read the full YAML from ${relativePath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`, - groups: ['read', 'edit', 'browser', 'command', 'mcp'], - }; - } - - /** - * Format name as title - */ - formatTitle(name) { - return name - .split('-') - .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) - .join(' '); - } - - /** - * Clear old BMAD workflow files from workflows directory - * @param {string} workflowsDir - Workflows directory path - */ - async clearBmadWorkflows(workflowsDir) { - const fs = require('fs-extra'); - if (!(await fs.pathExists(workflowsDir))) return; - - const entries = await fs.readdir(workflowsDir); - for (const entry of entries) { - if (entry.startsWith('bmad-') && entry.endsWith('.md')) { - await fs.remove(path.join(workflowsDir, entry)); - } - } - } - - /** - * Cleanup KiloCode configuration - */ - async cleanup(projectDir, options = {}) { - const fs = require('fs-extra'); - const kiloModesPath = path.join(projectDir, this.configFile); - - if (await fs.pathExists(kiloModesPath)) { - const content = await fs.readFile(kiloModesPath, 'utf8'); - - try { - const config = yaml.parse(content) || {}; - - if (Array.isArray(config.customModes)) { - const originalCount = config.customModes.length; - // Remove BMAD modes only (keep non-BMAD modes) - config.customModes = config.customModes.filter((mode) => !mode.slug || !mode.slug.startsWith('bmad-')); - const removedCount = originalCount - config.customModes.length; - - if (removedCount > 0) { - await fs.writeFile(kiloModesPath, yaml.stringify(config, { lineWidth: 0 })); - if (!options.silent) await prompts.log.message(`Removed ${removedCount} BMAD modes from .kilocodemodes`); - } - } - } catch { - // If parsing fails, leave file as-is - if (!options.silent) await prompts.log.warn('Warning: Could not parse .kilocodemodes for cleanup'); - } - } - - // Clean up workflow files - const workflowsDir = path.join(projectDir, '.kilocode', 'workflows'); - await this.clearBmadWorkflows(workflowsDir); - } - - /** - * Install a custom agent launcher for Kilo - * @param {string} projectDir - Project directory - * @param {string} agentName - Agent name (e.g., "fred-commit-poet") - * @param {string} agentPath - Path to compiled agent (relative to project root) - * @param {Object} metadata - Agent metadata - * @returns {Object} Installation result - */ - async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) { - const kilocodemodesPath = path.join(projectDir, this.configFile); - let config = {}; - - // Read existing .kilocodemodes file - if (await this.pathExists(kilocodemodesPath)) { - const existingContent = await this.readFile(kilocodemodesPath); - try { - config = yaml.parse(existingContent) || {}; - } catch { - config = {}; - } - } - - // Ensure customModes array exists - if (!Array.isArray(config.customModes)) { - config.customModes = []; - } - - // Create custom agent mode object - const slug = `bmad-custom-${agentName.toLowerCase()}`; - - // Check if mode already exists - if (config.customModes.some((mode) => mode.slug === slug)) { - return { - ide: 'kilo', - path: this.configFile, - command: agentName, - type: 'custom-agent-launcher', - alreadyExists: true, - }; - } - - // Add custom mode object - config.customModes.push({ - slug: slug, - name: `BMAD Custom: ${agentName}`, - description: `Custom BMAD agent: ${agentName}\n\n**⚠️ IMPORTANT**: Run @${agentPath} first to load the complete agent!\n\nThis is a launcher for the custom BMAD agent "${agentName}". The agent will follow the persona and instructions from the main agent file.\n`, - prompt: `@${agentPath}\n`, - always: false, - permissions: 'all', - }); - - // Write .kilocodemodes file with proper YAML structure - await this.writeFile(kilocodemodesPath, yaml.stringify(config, { lineWidth: 0 })); - - return { - ide: 'kilo', - path: this.configFile, - command: slug, - type: 'custom-agent-launcher', - }; - } -} - -module.exports = { KiloSetup }; diff --git a/tools/cli/installers/lib/ide/manager.js b/tools/cli/installers/lib/ide/manager.js index 654574a25..2381bddfa 100644 --- a/tools/cli/installers/lib/ide/manager.js +++ b/tools/cli/installers/lib/ide/manager.js @@ -1,5 +1,3 @@ -const fs = require('fs-extra'); -const path = require('node:path'); const { BMAD_FOLDER_NAME } = require('./shared/path-utils'); const prompts = require('../../../lib/prompts'); @@ -8,8 +6,7 @@ const prompts = require('../../../lib/prompts'); * Dynamically discovers and loads IDE handlers * * Loading strategy: - * 1. Custom installer files (github-copilot.js, kilo.js, rovodev.js) - for platforms with unique installation logic - * 2. Config-driven handlers (from platform-codes.yaml) - for standard IDE installation patterns + * All platforms are config-driven from platform-codes.yaml. */ class IdeManager { constructor() { @@ -43,50 +40,12 @@ class IdeManager { } /** - * Dynamically load all IDE handlers - * 1. Load custom installer files first (github-copilot.js, kilo.js, rovodev.js) - * 2. Load config-driven handlers from platform-codes.yaml + * Dynamically load all IDE handlers from platform-codes.yaml */ async loadHandlers() { - // Load custom installer files - await this.loadCustomInstallerFiles(); - - // Load config-driven handlers from platform-codes.yaml await this.loadConfigDrivenHandlers(); } - /** - * Load custom installer files (unique installation logic) - * These files have special installation patterns that don't fit the config-driven model - * Note: codex was migrated to config-driven (platform-codes.yaml) and no longer needs a custom installer - */ - async loadCustomInstallerFiles() { - const ideDir = __dirname; - const customFiles = ['github-copilot.js', 'kilo.js', 'rovodev.js']; - - for (const file of customFiles) { - const filePath = path.join(ideDir, file); - if (!fs.existsSync(filePath)) continue; - - try { - const HandlerModule = require(filePath); - const HandlerClass = HandlerModule.default || Object.values(HandlerModule)[0]; - - if (HandlerClass) { - const instance = new HandlerClass(); - if (instance.name && typeof instance.name === 'string') { - if (typeof instance.setBmadFolderName === 'function') { - instance.setBmadFolderName(this.bmadFolderName); - } - this.handlers.set(instance.name, instance); - } - } - } catch (error) { - await prompts.log.warn(`Warning: Could not load ${file}: ${error.message}`); - } - } - } - /** * Load config-driven handlers from platform-codes.yaml * This creates ConfigDrivenIdeSetup instances for platforms with installer config @@ -98,9 +57,6 @@ class IdeManager { const { ConfigDrivenIdeSetup } = require('./_config-driven'); for (const [platformCode, platformInfo] of Object.entries(platformConfig.platforms)) { - // Skip if already loaded by custom installer - if (this.handlers.has(platformCode)) continue; - // Skip if no installer config (platform may not need installation) if (!platformInfo.installer) continue; @@ -128,6 +84,11 @@ class IdeManager { continue; } + // Skip suspended platforms (e.g., IDE doesn't support skills yet) + if (handler.platformConfig?.suspended) { + continue; + } + ides.push({ value: key, name: name, @@ -177,6 +138,22 @@ class IdeManager { return { success: false, ide: ideName, error: 'unsupported IDE' }; } + // Block suspended platforms — clean up legacy files but don't install + if (handler.platformConfig?.suspended) { + if (!options.silent) { + await prompts.log.warn(`${handler.displayName || ideName}: ${handler.platformConfig.suspended}`); + } + // Still clean up legacy artifacts so old broken configs don't linger + if (typeof handler.cleanup === 'function') { + try { + await handler.cleanup(projectDir, { silent: true }); + } catch { + // Best-effort cleanup — don't let stale files block the suspended result + } + } + return { success: false, ide: ideName, error: 'suspended' }; + } + try { const handlerResult = await handler.setup(projectDir, bmadDir, options); // Build detail string from handler-returned data @@ -190,14 +167,6 @@ class IdeManager { if (r.tasks > 0) parts.push(`${r.tasks} tasks`); if (r.tools > 0) parts.push(`${r.tools} tools`); detail = parts.join(', '); - } else if (handlerResult && handlerResult.modes !== undefined) { - // Kilo handler returns { success, modes, workflows, tasks, tools } - const parts = []; - if (handlerResult.modes > 0) parts.push(`${handlerResult.modes} modes`); - if (handlerResult.workflows > 0) parts.push(`${handlerResult.workflows} workflows`); - if (handlerResult.tasks > 0) parts.push(`${handlerResult.tasks} tasks`); - if (handlerResult.tools > 0) parts.push(`${handlerResult.tools} tools`); - detail = parts.join(', '); } // Propagate handler's success status (default true for backward compat) const success = handlerResult?.success !== false; diff --git a/tools/cli/installers/lib/ide/platform-codes.yaml b/tools/cli/installers/lib/ide/platform-codes.yaml index 99269552f..82d45f562 100644 --- a/tools/cli/installers/lib/ide/platform-codes.yaml +++ b/tools/cli/installers/lib/ide/platform-codes.yaml @@ -57,8 +57,11 @@ platforms: category: ide description: "AI coding assistant" installer: - target_dir: .clinerules/workflows - template_type: windsurf + legacy_targets: + - .clinerules/workflows + target_dir: .cline/skills + template_type: default + skill_format: true codex: name: "Codex" @@ -81,8 +84,11 @@ platforms: category: ide description: "Tencent Cloud Code Assistant - AI-powered coding companion" installer: - target_dir: .codebuddy/commands + legacy_targets: + - .codebuddy/commands + target_dir: .codebuddy/skills template_type: default + skill_format: true crush: name: "Crush" @@ -90,8 +96,11 @@ platforms: category: ide description: "AI development assistant" installer: - target_dir: .crush/commands + legacy_targets: + - .crush/commands + target_dir: .crush/skills template_type: default + skill_format: true cursor: name: "Cursor" @@ -111,15 +120,24 @@ platforms: category: cli description: "Google's CLI for Gemini" installer: - target_dir: .gemini/commands - template_type: gemini + legacy_targets: + - .gemini/commands + target_dir: .gemini/skills + template_type: default + skill_format: true github-copilot: name: "GitHub Copilot" preferred: false category: ide description: "GitHub's AI pair programmer" - # No installer config - uses custom github-copilot.js + installer: + legacy_targets: + - .github/agents + - .github/prompts + target_dir: .github/skills + template_type: default + skill_format: true iflow: name: "iFlow" @@ -127,15 +145,24 @@ platforms: category: ide description: "AI workflow automation" installer: - target_dir: .iflow/commands + legacy_targets: + - .iflow/commands + target_dir: .iflow/skills template_type: default + skill_format: true kilo: name: "KiloCoder" preferred: false category: ide description: "AI coding platform" - # No installer config - uses custom kilo.js (creates .kilocodemodes file) + suspended: "Kilo Code does not yet support the Agent Skills standard. Support is paused until they implement it. See https://github.com/kilocode/kilo-code/issues for updates." + installer: + legacy_targets: + - .kilocode/workflows + target_dir: .kilocode/skills + template_type: default + skill_format: true kiro: name: "Kiro" @@ -171,24 +198,35 @@ platforms: category: ide description: "Qwen AI coding assistant" installer: - target_dir: .qwen/commands + legacy_targets: + - .qwen/commands + target_dir: .qwen/skills template_type: default + skill_format: true roo: - name: "Roo Cline" + name: "Roo Code" preferred: false category: ide description: "Enhanced Cline fork" installer: - target_dir: .roo/commands + legacy_targets: + - .roo/commands + target_dir: .roo/skills template_type: default + skill_format: true rovo-dev: name: "Rovo Dev" preferred: false category: ide description: "Atlassian's Rovo development environment" - # No installer config - uses custom rovodev.js (generates prompts.yml manifest) + installer: + legacy_targets: + - .rovodev/workflows + target_dir: .rovodev/skills + template_type: default + skill_format: true trae: name: "Trae" @@ -196,8 +234,11 @@ platforms: category: ide description: "AI coding tool" installer: - target_dir: .trae/rules - template_type: trae + legacy_targets: + - .trae/rules + target_dir: .trae/skills + template_type: default + skill_format: true windsurf: name: "Windsurf" diff --git a/tools/cli/installers/lib/ide/rovodev.js b/tools/cli/installers/lib/ide/rovodev.js deleted file mode 100644 index da3c4809d..000000000 --- a/tools/cli/installers/lib/ide/rovodev.js +++ /dev/null @@ -1,257 +0,0 @@ -const path = require('node:path'); -const fs = require('fs-extra'); -const yaml = require('yaml'); -const { BaseIdeSetup } = require('./_base-ide'); -const prompts = require('../../../lib/prompts'); -const { AgentCommandGenerator } = require('./shared/agent-command-generator'); -const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator'); -const { TaskToolCommandGenerator } = require('./shared/task-tool-command-generator'); -const { toDashPath } = require('./shared/path-utils'); - -/** - * Rovo Dev IDE setup handler - * - * Custom installer that writes .md workflow files to .rovodev/workflows/ - * and generates .rovodev/prompts.yml to register them with Rovo Dev's /prompts feature. - * - * prompts.yml format (per Rovo Dev docs): - * prompts: - * - name: bmad-bmm-create-prd - * description: "PRD workflow..." - * content_file: workflows/bmad-bmm-create-prd.md - */ -class RovoDevSetup extends BaseIdeSetup { - constructor() { - super('rovo-dev', 'Rovo Dev', false); - this.rovoDir = '.rovodev'; - this.workflowsDir = 'workflows'; - this.promptsFile = 'prompts.yml'; - } - - /** - * Setup Rovo Dev configuration - * @param {string} projectDir - Project directory - * @param {string} bmadDir - BMAD installation directory - * @param {Object} options - Setup options - * @returns {Promise} Setup result with { success, results: { agents, workflows, tasks, tools } } - */ - async setup(projectDir, bmadDir, options = {}) { - if (!options.silent) await prompts.log.info(`Setting up ${this.name}...`); - - // Clean up any old BMAD installation first - await this.cleanup(projectDir, options); - - const workflowsPath = path.join(projectDir, this.rovoDir, this.workflowsDir); - await this.ensureDir(workflowsPath); - - const selectedModules = options.selectedModules || []; - const writtenFiles = []; - - // Generate and write agent launchers - const agentGen = new AgentCommandGenerator(this.bmadFolderName); - const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, selectedModules); - const agentCount = await agentGen.writeDashArtifacts(workflowsPath, agentArtifacts); - this._collectPromptEntries(writtenFiles, agentArtifacts, ['agent-launcher'], 'agent'); - - // Generate and write workflow commands - const workflowGen = new WorkflowCommandGenerator(this.bmadFolderName); - const { artifacts: workflowArtifacts } = await workflowGen.collectWorkflowArtifacts(bmadDir); - const workflowCount = await workflowGen.writeDashArtifacts(workflowsPath, workflowArtifacts); - this._collectPromptEntries(writtenFiles, workflowArtifacts, ['workflow-command'], 'workflow'); - - // Generate and write task/tool commands - const taskToolGen = new TaskToolCommandGenerator(this.bmadFolderName); - const { artifacts: taskToolArtifacts, counts: taskToolCounts } = await taskToolGen.collectTaskToolArtifacts(bmadDir); - await taskToolGen.writeDashArtifacts(workflowsPath, taskToolArtifacts); - const taskCount = taskToolCounts.tasks || 0; - const toolCount = taskToolCounts.tools || 0; - this._collectPromptEntries(writtenFiles, taskToolArtifacts, ['task', 'tool']); - - // Generate prompts.yml manifest (only if we have entries to write) - if (writtenFiles.length > 0) { - await this.generatePromptsYml(projectDir, writtenFiles); - } - - if (!options.silent) { - await prompts.log.success( - `${this.name} configured: ${agentCount} agents, ${workflowCount} workflows, ${taskCount} tasks, ${toolCount} tools`, - ); - } - - return { - success: true, - results: { - agents: agentCount, - workflows: workflowCount, - tasks: taskCount, - tools: toolCount, - }, - }; - } - - /** - * Collect prompt entries from artifacts into writtenFiles array - * @param {Array} writtenFiles - Target array to push entries into - * @param {Array} artifacts - Artifacts from a generator's collect method - * @param {string[]} acceptedTypes - Artifact types to include (e.g., ['agent-launcher']) - * @param {string} [fallbackSuffix] - Suffix for fallback description; defaults to artifact.type - */ - _collectPromptEntries(writtenFiles, artifacts, acceptedTypes, fallbackSuffix) { - for (const artifact of artifacts) { - if (!acceptedTypes.includes(artifact.type)) continue; - const flatName = toDashPath(artifact.relativePath); - writtenFiles.push({ - name: path.basename(flatName, '.md'), - description: artifact.description || `${artifact.name} ${fallbackSuffix || artifact.type}`, - contentFile: `${this.workflowsDir}/${flatName}`, - }); - } - } - - /** - * Generate .rovodev/prompts.yml manifest - * Merges with existing user entries -- strips entries with names starting 'bmad-', - * appends new BMAD entries, and writes back. - * - * @param {string} projectDir - Project directory - * @param {Array} writtenFiles - Array of { name, description, contentFile } - */ - async generatePromptsYml(projectDir, writtenFiles) { - const promptsPath = path.join(projectDir, this.rovoDir, this.promptsFile); - let existingPrompts = []; - - // Read existing prompts.yml and preserve non-BMAD entries - if (await this.pathExists(promptsPath)) { - try { - const content = await this.readFile(promptsPath); - const parsed = yaml.parse(content); - if (parsed && Array.isArray(parsed.prompts)) { - // Keep only non-BMAD entries (entries whose name does NOT start with bmad-) - existingPrompts = parsed.prompts.filter((entry) => !entry.name || !entry.name.startsWith('bmad-')); - } - } catch { - // If parsing fails, start fresh but preserve file safety - existingPrompts = []; - } - } - - // Build new BMAD entries (prefix description with name so /prompts list is scannable) - const bmadEntries = writtenFiles.map((file) => ({ - name: file.name, - description: `${file.name} - ${file.description}`, - content_file: file.contentFile, - })); - - // Merge: user entries first, then BMAD entries - const allPrompts = [...existingPrompts, ...bmadEntries]; - - const config = { prompts: allPrompts }; - const yamlContent = yaml.stringify(config, { lineWidth: 0 }); - await this.writeFile(promptsPath, yamlContent); - } - - /** - * Cleanup Rovo Dev configuration - * Removes bmad-* files from .rovodev/workflows/ and strips BMAD entries from prompts.yml - * @param {string} projectDir - Project directory - * @param {Object} options - Cleanup options - */ - async cleanup(projectDir, options = {}) { - const workflowsPath = path.join(projectDir, this.rovoDir, this.workflowsDir); - - // Remove all bmad-* entries from workflows dir (aligned with detect() predicate) - if (await this.pathExists(workflowsPath)) { - const entries = await fs.readdir(workflowsPath); - for (const entry of entries) { - if (entry.startsWith('bmad-')) { - await fs.remove(path.join(workflowsPath, entry)); - } - } - } - - // Clean BMAD entries from prompts.yml (preserve user entries) - const promptsPath = path.join(projectDir, this.rovoDir, this.promptsFile); - if (await this.pathExists(promptsPath)) { - try { - const content = await this.readFile(promptsPath); - const parsed = yaml.parse(content) || {}; - - if (Array.isArray(parsed.prompts)) { - const originalCount = parsed.prompts.length; - parsed.prompts = parsed.prompts.filter((entry) => !entry.name || !entry.name.startsWith('bmad-')); - const removedCount = originalCount - parsed.prompts.length; - - if (removedCount > 0) { - if (parsed.prompts.length === 0) { - // If no entries remain, remove the file entirely - await fs.remove(promptsPath); - } else { - await this.writeFile(promptsPath, yaml.stringify(parsed, { lineWidth: 0 })); - } - if (!options.silent) { - await prompts.log.message(`Removed ${removedCount} BMAD entries from ${this.promptsFile}`); - } - } - } - } catch { - // If parsing fails, leave file as-is - if (!options.silent) { - await prompts.log.warn(`Warning: Could not parse ${this.promptsFile} for cleanup`); - } - } - } - - // Remove empty .rovodev directories - if (await this.pathExists(workflowsPath)) { - const remaining = await fs.readdir(workflowsPath); - if (remaining.length === 0) { - await fs.remove(workflowsPath); - } - } - - const rovoDirPath = path.join(projectDir, this.rovoDir); - if (await this.pathExists(rovoDirPath)) { - const remaining = await fs.readdir(rovoDirPath); - if (remaining.length === 0) { - await fs.remove(rovoDirPath); - } - } - } - - /** - * Detect whether Rovo Dev configuration exists in the project - * Checks for .rovodev/ dir with bmad files or bmad entries in prompts.yml - * @param {string} projectDir - Project directory - * @returns {boolean} - */ - async detect(projectDir) { - const workflowsPath = path.join(projectDir, this.rovoDir, this.workflowsDir); - - // Check for bmad files in workflows dir - if (await fs.pathExists(workflowsPath)) { - const entries = await fs.readdir(workflowsPath); - if (entries.some((entry) => entry.startsWith('bmad-'))) { - return true; - } - } - - // Check for bmad entries in prompts.yml - const promptsPath = path.join(projectDir, this.rovoDir, this.promptsFile); - if (await fs.pathExists(promptsPath)) { - try { - const content = await fs.readFile(promptsPath, 'utf8'); - const parsed = yaml.parse(content); - if (parsed && Array.isArray(parsed.prompts)) { - return parsed.prompts.some((entry) => entry.name && entry.name.startsWith('bmad-')); - } - } catch { - // If parsing fails, check raw content - return false; - } - } - - return false; - } -} - -module.exports = { RovoDevSetup }; diff --git a/tools/docs/native-skills-migration-checklist.md b/tools/docs/native-skills-migration-checklist.md index ba8f412ed..2f0f31344 100644 --- a/tools/docs/native-skills-migration-checklist.md +++ b/tools/docs/native-skills-migration-checklist.md @@ -15,25 +15,27 @@ This checklist now includes those completed platforms plus the remaining full-su Support assumption: full Agent Skills support. BMAD has already migrated from `.claude/commands` to `.claude/skills`. -- [ ] Confirm current implementation still matches Claude Code skills expectations -- [ ] Confirm legacy cleanup for `.claude/commands` -- [ ] Test fresh install -- [ ] Test reinstall/upgrade from legacy command output -- [ ] Confirm ancestor conflict protection -- [ ] Implement/extend automated tests as needed -- [ ] Commit any follow-up fixes if required +**Install:** `npm install -g @anthropic-ai/claude-code` or `brew install claude-code` + +- [x] Confirm current implementation still matches Claude Code skills expectations +- [x] Confirm legacy cleanup for `.claude/commands` +- [x] Test fresh install +- [x] Test reinstall/upgrade from legacy command output +- [x] Confirm ancestor conflict protection because Claude Code inherits skills from parent directories and `ancestor_conflict_check: true` is set in platform-codes.yaml +- [x] Implement/extend automated tests as needed ## Codex CLI Support assumption: full Agent Skills support. BMAD has already migrated from `.codex/prompts` to `.agents/skills`. -- [ ] Confirm current implementation still matches Codex CLI skills expectations -- [ ] Confirm legacy cleanup for project and global `.codex/prompts` -- [ ] Test fresh install -- [ ] Test reinstall/upgrade from legacy prompt output +**Install:** `npm install -g @openai/codex` + +- [x] Confirm current implementation still matches Codex CLI skills expectations +- [x] Confirm legacy cleanup for project and global `.codex/prompts` +- [x] Test fresh install +- [x] Test reinstall/upgrade from legacy prompt output - [x] Confirm ancestor conflict protection because Codex inherits parent-directory `.agents/skills` -- [ ] Implement/extend automated tests as needed -- [ ] Commit any follow-up fixes if required +- [x] Implement/extend automated tests as needed ## Cursor @@ -45,7 +47,7 @@ Support assumption: full Agent Skills support. BMAD currently installs legacy co - [x] Test fresh install - [x] Test reinstall/upgrade from legacy command output - [x] Confirm no ancestor conflict protection is needed because a child workspace surfaced child `.cursor/skills` entries but not a parent-only skill during manual verification -- [ ] Implement/extend automated tests +- [x] Implement/extend automated tests - [x] Commit ## Windsurf @@ -59,20 +61,21 @@ Support assumption: full Agent Skills support. Windsurf docs confirm workspace s - [x] Test reinstall/upgrade from legacy workflow output - [x] Confirm no ancestor conflict protection is needed because manual Windsurf verification showed child-local `@` skills loaded while a parent-only skill was not inherited - [x] Implement/extend automated tests -- [x] Commit ## Cline -Support assumption: full Agent Skills support. BMAD currently installs workflow files to `.clinerules/workflows`; target should move to the platform's native skills directory. +Support assumption: full Agent Skills support. Cline docs confirm workspace skills at `.cline/skills//SKILL.md` and global skills at `~/.cline/skills/`. BMAD has now migrated from `.clinerules/workflows` to `.cline/skills`. -- [ ] Confirm current Cline skills path and whether `.cline/skills` is the correct BMAD target -- [ ] Implement installer migration to native skills output -- [ ] Add legacy cleanup for `.clinerules/workflows` -- [ ] Test fresh install -- [ ] Test reinstall/upgrade from legacy workflow output -- [ ] Confirm ancestor conflict protection where applicable -- [ ] Implement/extend automated tests -- [ ] Commit +**Install:** VS Code extension `saoudrizwan.claude-dev` — search "Cline" in Extensions or `code --install-extension saoudrizwan.claude-dev` + +- [x] Confirm current Cline skills path is `.cline/skills/{skill-name}/SKILL.md` with YAML frontmatter (name + description) +- [x] Implement installer migration to native skills output +- [x] Add legacy cleanup for `.clinerules/workflows` +- [x] Test fresh install — 43 skills installed to `.cline/skills/` +- [x] Test reinstall/upgrade from legacy workflow output +- [x] Confirm no ancestor conflict protection is needed because Cline only scans workspace-local `.cline/skills/` and global `~/.cline/skills/`, with no ancestor directory inheritance +- [x] Implement/extend automated tests — 9 assertions in test suite 18 +- [x] Commit ## Google Antigravity @@ -85,7 +88,6 @@ Support assumption: full Agent Skills support. Antigravity docs confirm workspac - [x] Test reinstall/upgrade from legacy workflow output - [x] Confirm no ancestor conflict protection is needed because manual Antigravity verification in `/tmp/antigravity-ancestor-repro/parent/child` showed only the child-local `child-only` skill, with no inherited parent `.agent/skills` entry - [x] Implement/extend automated tests -- [x] Commit ## Auggie @@ -98,33 +100,38 @@ Support assumption: full Agent Skills support. BMAD currently installs commands - [x] Test reinstall/upgrade from legacy command output - [x] Confirm no ancestor conflict protection is needed because local `auggie --workspace-root` repro showed child-local `.augment/skills` loading `child-only` but not parent `parent-only` - [x] Implement/extend automated tests -- [ ] Commit +- [x] Commit ## CodeBuddy -Support assumption: full Agent Skills support. BMAD currently installs commands to `.codebuddy/commands`; target should move to `.codebuddy/skills`. +Support assumption: full Agent Skills support. CodeBuddy docs confirm workspace skills at `.codebuddy/skills//SKILL.md` and global skills at `~/.codebuddy/commands/`. BMAD has now migrated from `.codebuddy/commands` to `.codebuddy/skills`. -- [ ] Confirm CodeBuddy native skills path and any naming/frontmatter requirements -- [ ] Implement installer migration to native skills output -- [ ] Add legacy cleanup for `.codebuddy/commands` -- [ ] Test fresh install -- [ ] Test reinstall/upgrade from legacy command output -- [ ] Confirm ancestor conflict protection where applicable -- [ ] Implement/extend automated tests -- [ ] Commit +**Install:** Download [Tencent CodeBuddy IDE](https://codebuddyide.net/) or install as VS Code extension `CodebuddyAI.codebuddy-ai` + +- [x] Confirm CodeBuddy native skills path is `.codebuddy/skills/{skill-name}/SKILL.md` with YAML frontmatter (name + description) — per docs, not IDE-verified +- [x] Implement installer migration to native skills output +- [x] Add legacy cleanup for `.codebuddy/commands` +- [x] Test fresh install — 43 skills installed to `.codebuddy/skills/` (installer output only) +- [x] Test reinstall/upgrade from legacy command output +- [ ] **NEEDS MANUAL IDE VERIFICATION** — requires Tencent Cloud account; confirm skills appear in UI and test ancestor inheritance +- [x] Implement/extend automated tests — 9 assertions in test suite 19 +- [x] Commit ## Crush -Support assumption: full Agent Skills support. BMAD currently installs commands to `.crush/commands`; target should move to the platform's native skills location. +Support assumption: full Agent Skills support. Crush scans project-local `.crush/skills/` exclusively ([GitHub issue #2072](https://github.com/charmbracelet/crush/issues/2072) confirms this and requests adding `~/.agents/skills/`). BMAD has now migrated from `.crush/commands` to `.crush/skills`. -- [ ] Confirm Crush project-local versus global skills path and BMAD's preferred install target -- [ ] Implement installer migration to native skills output -- [ ] Add legacy cleanup for `.crush/commands` -- [ ] Test fresh install -- [ ] Test reinstall/upgrade from legacy command output -- [ ] Confirm ancestor conflict protection where applicable -- [ ] Implement/extend automated tests -- [ ] Commit +**Install:** `brew install charmbracelet/tap/crush` (macOS/Linux) or `winget install charmbracelet.crush` (Windows) + +- [x] Confirm Crush project-local skills path is `.crush/skills/{skill-name}/SKILL.md` — per GitHub issue #2072 confirming `.crush/skills/` is the only scan path +- [x] Implement installer migration to native skills output +- [x] Add legacy cleanup for `.crush/commands` +- [x] Test fresh install — 43 skills installed to `.crush/skills/` +- [x] Test reinstall/upgrade from legacy command output +- [x] Confirm no ancestor conflict protection is needed because Crush only scans project-local `.crush/skills/`, no ancestor inheritance +- [x] Manual CLI verification — `crush run` lists all 10 skills and successfully triggers bmad-help +- [x] Implement/extend automated tests — 9 assertions in test suite 20 +- [x] Commit ## Kiro @@ -137,7 +144,6 @@ Support assumption: full Agent Skills support. Kiro docs confirm project skills - [x] Test reinstall/upgrade from legacy steering output - [x] Confirm no ancestor conflict protection is needed because manual Kiro verification showed Slash-visible skills from the current workspace only, with no ancestor `.kiro/skills` inheritance - [x] Implement/extend automated tests -- [x] Commit ## OpenCode @@ -150,66 +156,126 @@ Support assumption: full Agent Skills support. BMAD currently splits output betw - [x] Test reinstall/upgrade from split legacy output - [x] Confirm ancestor conflict protection is required because local `opencode run` repros loaded both child-local `child-only` and ancestor `parent-only`, matching the docs that project-local skill discovery walks upward to the git worktree - [x] Implement/extend automated tests -- [ ] Commit +- [x] Commit ## Roo Code Support assumption: full Agent Skills support. BMAD currently installs commands to `.roo/commands`; target should move to `.roo/skills` or the correct mode-aware skill directories. -- [ ] Confirm Roo native skills path and whether BMAD should use generic or mode-specific skill directories -- [ ] Implement installer migration to native skills output -- [ ] Add legacy cleanup for `.roo/commands` -- [ ] Test fresh install -- [ ] Test reinstall/upgrade from legacy command output -- [ ] Confirm ancestor conflict protection where applicable -- [ ] Implement/extend automated tests -- [ ] Commit +**Install:** VS Code extension `RooVeterinaryInc.roo-cline` — search "Roo Code" in Extensions or `code --install-extension RooVeterinaryInc.roo-cline` + +- [x] Confirm Roo native skills path is `.roo/skills/{skill-name}/SKILL.md` with `name` frontmatter matching directory exactly (lowercase, alphanumeric + hyphens only) +- [x] Implement installer migration to native skills output +- [x] Add legacy cleanup for `.roo/commands` +- [x] Test fresh install — 43 skills installed, verified in Roo Code v3.51 +- [x] Test reinstall/upgrade from legacy command output +- [x] Confirm no ancestor conflict protection is needed because manual Roo Code v3.51 verification showed child-local `child-only` skill loaded while parent-only skill was not inherited +- [x] Implement/extend automated tests — 7 assertions in test suite 13 +- [x] Commit ## Trae -Support assumption: full Agent Skills support. BMAD currently installs rule files to `.trae/rules`; target should move to the platform's native skills directory. +Support assumption: full Agent Skills support. [Trae docs](https://docs.trae.ai/ide/skills) confirm workspace skills at `.trae/skills//SKILL.md`. BMAD has now migrated from `.trae/rules` to `.trae/skills`. -- [ ] Confirm Trae native skills path and whether the current `.trae/rules` path is still required for compatibility -- [ ] Implement installer migration to native skills output -- [ ] Add legacy cleanup for `.trae/rules` -- [ ] Test fresh install -- [ ] Test reinstall/upgrade from legacy rules output -- [ ] Confirm ancestor conflict protection where applicable -- [ ] Implement/extend automated tests -- [ ] Commit +**Install:** Download [standalone IDE](https://www.trae.ai/download) (macOS/Windows/Linux) or `winget install -e --id ByteDance.Trae` + +- [x] Confirm Trae native skills path is `.trae/skills/{skill-name}/SKILL.md` — per official docs +- [x] Implement installer migration to native skills output +- [x] Add legacy cleanup for `.trae/rules` +- [x] Test fresh install — 43 skills installed to `.trae/skills/` +- [x] Test reinstall/upgrade from legacy rules output +- [x] Confirm no ancestor conflict protection is needed — Trae docs describe project-local `.trae/skills/` only +- [ ] **NEEDS MANUAL IDE VERIFICATION** — download Trae IDE and confirm skills appear in UI +- [x] Implement/extend automated tests — 9 assertions in test suite 21 +- [x] Commit ## GitHub Copilot Support assumption: full Agent Skills support. BMAD currently uses a custom installer that generates `.github/agents`, `.github/prompts`, and `.github/copilot-instructions.md`; target should move to `.github/skills`. -- [ ] Confirm GitHub Copilot native skills path and whether `.github/agents` remains necessary as a compatibility layer -- [ ] Design the migration away from the custom prompt/agent installer model -- [ ] Implement native skills output, ideally with shared config-driven code where practical -- [ ] Add legacy cleanup for `.github/agents`, `.github/prompts`, and any BMAD-owned Copilot instruction file behavior that should be retired -- [ ] Test fresh install -- [ ] Test reinstall/upgrade from legacy custom installer output -- [ ] Confirm ancestor conflict protection where applicable -- [ ] Implement/extend automated tests +**Install:** VS Code extension `GitHub.copilot` — search "GitHub Copilot" in Extensions or `code --install-extension GitHub.copilot` + +- [x] Confirm GitHub Copilot native skills path is `.github/skills/{skill-name}/SKILL.md` — also reads `.claude/skills/` automatically +- [x] Design the migration away from the custom prompt/agent installer model — replaced 699-line custom installer with config-driven `skill_format: true` +- [x] Implement native skills output, ideally with shared config-driven code where practical +- [x] Add legacy cleanup for `.github/agents`, `.github/prompts`, and BMAD markers in `copilot-instructions.md` +- [x] Test fresh install — 43 skills installed to `.github/skills/` +- [x] Test reinstall/upgrade from legacy custom installer output — legacy dirs removed, BMAD markers stripped, user content preserved +- [x] Confirm no ancestor conflict protection is needed because manual Copilot verification showed child-local `child-only` skill loaded while parent-only skill was not inherited +- [x] Implement/extend automated tests — 11 assertions in test suite 17 including marker cleanup +- [x] Commit + +## KiloCoder — SUSPENDED + +**Status: Kilo Code does not support the Agent Skills standard.** The original migration assumed skills support because Kilo forked from Roo Code, but manual IDE verification confirmed Kilo has not merged that feature. BMAD support is paused until Kilo implements skills. + +**Install:** VS Code extension `kilocode.kilo-code` — search "Kilo Code" in Extensions or `code --install-extension kilocode.kilo-code` + +- [x] ~~Confirm KiloCoder native skills path~~ — **FALSE**: assumed from Roo Code fork, not verified. Manual testing showed no skills support in the IDE +- [x] Config and installer code retained in platform-codes.yaml with `suspended` flag — hidden from IDE picker, setup blocked with explanation +- [x] Installer fails early (before writing `_bmad/`) if Kilo is the only selected IDE, protecting existing installations +- [x] Legacy cleanup still runs for `.kilocode/workflows` and `.kilocodemodes` when users switch to a different IDE +- [x] Automated tests — 7 assertions in suite 22 (suspended config, hidden from picker, setup blocked, no files written, legacy cleanup) + +## Gemini CLI + +Support assumption: full Agent Skills support. Gemini CLI docs confirm workspace skills at `.gemini/skills/` and user skills at `~/.gemini/skills/`. Also discovers `.agents/skills/` as an alias. BMAD previously installed TOML files to `.gemini/commands`. + +**Install:** `npm install -g @google/gemini-cli` or see [geminicli.com](https://geminicli.com) + +- [x] Confirm Gemini CLI native skills path is `.gemini/skills/{skill-name}/SKILL.md` (per [geminicli.com/docs/cli/skills](https://geminicli.com/docs/cli/skills/)) +- [x] Implement native skills output — target_dir `.gemini/skills`, skill_format true, template_type default (replaces TOML templates) +- [x] Add legacy cleanup for `.gemini/commands` (via `legacy_targets`) +- [x] Test fresh install — skills written to `.gemini/skills/bmad-master/SKILL.md` with correct frontmatter +- [x] Test reinstall/upgrade from legacy TOML command output — legacy dir removed, skills installed +- [x] Confirm no ancestor conflict protection is needed — Gemini CLI uses workspace > user > extension precedence, no ancestor directory inheritance +- [x] Implement/extend automated tests — 9 assertions in test suite 23 (config, fresh install, legacy cleanup, reinstall) +- [x] Manual CLI verification — `gemini` lists all 10 skills and successfully triggers bmad-help - [ ] Commit -## KiloCoder +## iFlow -Support assumption: full Agent Skills support. BMAD currently uses a custom installer that writes `.kilocodemodes` and `.kilocode/workflows`; target should move to native skills output. +Support assumption: full Agent Skills support. iFlow docs confirm workspace skills at `.iflow/skills/` and global skills at `~/.iflow/skills/`. BMAD previously installed flat files to `.iflow/commands`. -- [ ] Confirm KiloCoder native skills path and whether `.kilocodemodes` should be removed entirely or retained temporarily for compatibility -- [ ] Design the migration away from modes plus workflow markdown -- [ ] Implement native skills output -- [ ] Add legacy cleanup for `.kilocode/workflows` and BMAD-owned entries in `.kilocodemodes` -- [ ] Test fresh install -- [ ] Test reinstall/upgrade from legacy custom installer output -- [ ] Confirm ancestor conflict protection where applicable -- [ ] Implement/extend automated tests +- [x] Confirm iFlow native skills path is `.iflow/skills/{skill-name}/SKILL.md` +- [x] Implement native skills output — target_dir `.iflow/skills`, skill_format true, template_type default +- [x] Add legacy cleanup for `.iflow/commands` (via `legacy_targets`) +- [x] Test fresh install — skills written to `.iflow/skills/bmad-master/SKILL.md` +- [x] Test legacy cleanup — legacy commands dir removed +- [x] Implement/extend automated tests — 6 assertions in test suite 24 +- [ ] **NEEDS MANUAL IDE VERIFICATION** — install iFlow and confirm skills appear in UI and can be triggered +- [ ] Commit + +## QwenCoder + +Support assumption: full Agent Skills support. Qwen Code supports workspace skills at `.qwen/skills/` and global skills at `~/.qwen/skills/`. BMAD previously installed flat files to `.qwen/commands`. + +- [x] Confirm QwenCoder native skills path is `.qwen/skills/{skill-name}/SKILL.md` +- [x] Implement native skills output — target_dir `.qwen/skills`, skill_format true, template_type default +- [x] Add legacy cleanup for `.qwen/commands` (via `legacy_targets`) +- [x] Test fresh install — skills written to `.qwen/skills/bmad-master/SKILL.md` +- [x] Test legacy cleanup — legacy commands dir removed +- [x] Implement/extend automated tests — 6 assertions in test suite 25 +- [ ] **NEEDS MANUAL IDE VERIFICATION** — install QwenCoder and confirm skills appear in UI and can be triggered +- [ ] Commit + +## Rovo Dev + +Support assumption: full Agent Skills support. Rovo Dev now supports workspace skills at `.rovodev/skills/` and user skills at `~/.rovodev/skills/`. BMAD previously used a custom 257-line installer that wrote `.rovodev/workflows/` and `prompts.yml`. + +- [x] Confirm Rovo Dev native skills path is `.rovodev/skills/{skill-name}/SKILL.md` (per Atlassian blog) +- [x] Replace 257-line custom `rovodev.js` with config-driven entry in `platform-codes.yaml` +- [x] Add legacy cleanup for `.rovodev/workflows` (via `legacy_targets`) and BMAD entries in `prompts.yml` (via `cleanupRovoDevPrompts()` in `_config-driven.js`) +- [x] Test fresh install — skills written to `.rovodev/skills/bmad-master/SKILL.md` +- [x] Test legacy cleanup — legacy workflows dir removed, `prompts.yml` BMAD entries stripped while preserving user entries +- [x] Implement/extend automated tests — 8 assertions in test suite 26 +- [ ] **NEEDS MANUAL IDE VERIFICATION** — install Rovo Dev and confirm skills appear in UI and can be triggered - [ ] Commit ## Summary Gates -- [ ] All full-support BMAD platforms install `SKILL.md` directory-based output -- [ ] No full-support platform still emits BMAD command/workflow/rule files as its primary install format -- [ ] Legacy cleanup paths are defined for every migrated platform -- [ ] Automated coverage exists for config-driven and custom-installer migrations +- [x] All full-support BMAD platforms install `SKILL.md` directory-based output +- [x] No full-support platform still emits BMAD command/workflow/rule files as its primary install format +- [x] Legacy cleanup paths are defined for every migrated platform +- [x] Automated coverage exists for config-driven and custom-installer migrations - [ ] Installer docs and migration notes updated after code changes land diff --git a/tools/platform-codes.yaml b/tools/platform-codes.yaml index 97846a9bd..7458143e7 100644 --- a/tools/platform-codes.yaml +++ b/tools/platform-codes.yaml @@ -50,7 +50,7 @@ platforms: description: "AI development tool" roo: - name: "Roo Cline" + name: "Roo Code" preferred: false category: ide description: "Enhanced Cline fork"