diff --git a/.claude/skills/changelog-social/SKILL.md b/.claude/skills/bmad-os-changelog-social/SKILL.md similarity index 100% rename from .claude/skills/changelog-social/SKILL.md rename to .claude/skills/bmad-os-changelog-social/SKILL.md diff --git a/.claude/skills/changelog-social/examples/discord-example.md b/.claude/skills/bmad-os-changelog-social/examples/discord-example.md similarity index 100% rename from .claude/skills/changelog-social/examples/discord-example.md rename to .claude/skills/bmad-os-changelog-social/examples/discord-example.md diff --git a/.claude/skills/changelog-social/examples/linkedin-example.md b/.claude/skills/bmad-os-changelog-social/examples/linkedin-example.md similarity index 100% rename from .claude/skills/changelog-social/examples/linkedin-example.md rename to .claude/skills/bmad-os-changelog-social/examples/linkedin-example.md diff --git a/.claude/skills/changelog-social/examples/twitter-example.md b/.claude/skills/bmad-os-changelog-social/examples/twitter-example.md similarity index 100% rename from .claude/skills/changelog-social/examples/twitter-example.md rename to .claude/skills/bmad-os-changelog-social/examples/twitter-example.md diff --git a/.claude/skills/bmad-os-diataxis-style-fix/SKILL.md b/.claude/skills/bmad-os-diataxis-style-fix/SKILL.md new file mode 100644 index 000000000..a874dc8ce --- /dev/null +++ b/.claude/skills/bmad-os-diataxis-style-fix/SKILL.md @@ -0,0 +1,7 @@ +--- +name: bmad-os-diataxis-style-fix +description: Fixes documentation to comply with Diataxis framework and BMad Method style guide rules +disable-model-invocation: true +--- + +Read `prompts/instructions.md` and execute. diff --git a/.claude/skills/bmad-os-diataxis-style-fix/prompts/instructions.md b/.claude/skills/bmad-os-diataxis-style-fix/prompts/instructions.md new file mode 100644 index 000000000..827e39115 --- /dev/null +++ b/.claude/skills/bmad-os-diataxis-style-fix/prompts/instructions.md @@ -0,0 +1,229 @@ +# Diataxis Style Fixer + +Automatically fixes documentation to comply with the Diataxis framework and BMad Method style guide. + +## CRITICAL RULES + +- **NEVER commit or push changes** — let the user review first +- **NEVER make destructive edits** — preserve all content, only fix formatting +- **Use Edit tool** — make targeted fixes, not full file rewrites +- **Show summary** — after fixing, list all changes made + +## Input + +Documentation file path or directory to fix. Defaults to `docs/` if not specified. + +## Step 1: Understand Diataxis Framework + +**Diataxis** is a documentation framework that categorizes content into four types based on two axes: + +| | **Learning** (oriented toward future) | **Doing** (oriented toward present) | +| -------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | +| **Practical** | **Tutorials** — lessons that guide learners through achieving a specific goal | **How-to guides** — step-by-step instructions for solving a specific problem | +| **Conceptual** | **Explanation** — content that clarifies and describes underlying concepts | **Reference** — technical descriptions, organized for lookup | + +**Key principles:** +- Each document type serves a distinct user need +- Don't mix types — a tutorial shouldn't explain concepts deeply +- Focus on the user's goal, not exhaustive coverage +- Structure follows purpose (tutorials are linear, reference is scannable) + +## Step 2: Read the Style Guide + +Read the project's style guide at `docs/_STYLE_GUIDE.md` to understand all project-specific conventions. + +## Step 3: Detect Document Type + +Based on file location, determine the document type: + +| Location | Diataxis Type | +| -------------------- | -------------------- | +| `/docs/tutorials/` | Tutorial | +| `/docs/how-to/` | How-to guide | +| `/docs/explanation/` | Explanation | +| `/docs/reference/` | Reference | +| `/docs/glossary/` | Reference (glossary) | + +## Step 4: Find and Fix Issues + +For each markdown file, scan for issues and fix them: + +### Universal Fixes (All Doc Types) + +**Horizontal Rules (`---`)** +- Remove any `---` outside of YAML frontmatter +- Replace with `##` section headers or admonitions as appropriate + +**`####` Headers** +- Replace with bold text: `#### Header` → `**Header**` +- Or convert to admonition if it's a warning/notice + +**"Related" or "Next:" Sections** +- Remove entire section including links +- The sidebar handles navigation + +**Deeply Nested Lists** +- Break into sections with `##` headers +- Flatten to max 3 levels + +**Code Blocks for Dialogue/Examples** +- Convert to admonitions: + ``` + :::note[Example] + [content] + ::: + ``` + +**Bold Paragraph Callouts** +- Convert to admonitions with appropriate type + +**Too Many Admonitions** +- Limit to 1-2 per section (tutorials allow 3-4 per major section) +- Consolidate related admonitions +- Remove less critical ones if over limit + +**Table Cells / List Items > 2 Sentences** +- Break into multiple rows/cells +- Or shorten to 1-2 sentences + +**Header Budget Exceeded** +- Merge related sections +- Convert some `##` to `###` subsections +- Goal: 8-12 `##` per doc; 2-3 `###` per section + +### Type-Specific Fixes + +**Tutorials** (`/docs/tutorials/`) +- Ensure hook describes outcome in 1-2 sentences +- Add "What You'll Learn" bullet section if missing +- Add `:::note[Prerequisites]` if missing +- Add `:::tip[Quick Path]` TL;DR at top if missing +- Use tables for phases, commands, agents +- Add "What You've Accomplished" section if missing +- Add Quick Reference table if missing +- Add Common Questions section if missing +- Add Getting Help section if missing +- Add `:::tip[Key Takeaways]` at end if missing + +**How-To** (`/docs/how-to/`) +- Ensure hook starts with "Use the `X` workflow to..." +- Add "When to Use This" with 3-5 bullets if missing +- Add `:::note[Prerequisites]` if missing +- Ensure steps are numbered `###` with action verbs +- Add "What You Get" describing outputs if missing + +**Explanation** (`/docs/explanation/`) +- Ensure hook states what document explains +- Organize content into scannable `##` sections +- Add comparison tables for 3+ options +- Link to how-to guides for procedural questions +- Limit to 2-3 admonitions per document + +**Reference** (`/docs/reference/`) +- Ensure hook states what document references +- Ensure structure matches reference type +- Use consistent item structure throughout +- Use tables for structured/comparative data +- Link to explanation docs for conceptual depth +- Limit to 1-2 admonitions per document + +**Glossary** (`/docs/glossary/` or glossary files) +- Ensure categories as `##` headers +- Ensure terms in tables (not individual headers) +- Definitions 1-2 sentences max +- Bold term names in cells + +## Step 5: Apply Fixes + +For each file with issues: +1. Read the file +2. Use Edit tool for each fix +3. Track what was changed + +## Step 6: Summary + +After processing all files, output a summary: + +```markdown +# Style Fixes Applied + +**Files processed:** N +**Files modified:** N + +## Changes Made + +### `path/to/file.md` +- Removed horizontal rule at line 45 +- Converted `####` headers to bold text +- Added `:::tip[Quick Path]` admonition +- Consolidated 3 admonitions into 2 + +### `path/to/other.md` +- Removed "Related:" section +- Fixed table cell length (broke into 2 rows) + +## Review Required + +Please review the changes. When satisfied, commit and push as needed. +``` + +## Common Patterns + +**Converting `####` to bold:** +```markdown +#### Important Note +Some text here. +``` +→ +```markdown +**Important Note** + +Some text here. +``` + +**Removing horizontal rule:** +```markdown +Some content above. + +--- + +Some content below. +``` +→ +```markdown +Some content above. + +## [Descriptive Section Header] + +Some content below. +``` + +**Converting code block to admonition:** +```markdown +``` +User: What should I do? + +Agent: Run the workflow. +``` +``` +→ +```markdown +:::note[Example] + +**User:** What should I do? + +**Agent:** Run the workflow. + +::: +``` + +**Converting bold paragraph to admonition:** +```markdown +**IMPORTANT:** This is critical that you read this before proceeding. +``` +→ +```markdown +:::caution[Important] +This is critical that you read this before proceeding. +::: +``` diff --git a/.claude/skills/draft-changelog/SKILL.md b/.claude/skills/bmad-os-draft-changelog/SKILL.md similarity index 100% rename from .claude/skills/draft-changelog/SKILL.md rename to .claude/skills/bmad-os-draft-changelog/SKILL.md diff --git a/.claude/skills/draft-changelog/prompts/instructions.md b/.claude/skills/bmad-os-draft-changelog/prompts/instructions.md similarity index 100% rename from .claude/skills/draft-changelog/prompts/instructions.md rename to .claude/skills/bmad-os-draft-changelog/prompts/instructions.md diff --git a/.claude/skills/gh-triage/README.md b/.claude/skills/bmad-os-gh-triage/README.md similarity index 100% rename from .claude/skills/gh-triage/README.md rename to .claude/skills/bmad-os-gh-triage/README.md diff --git a/.claude/skills/gh-triage/SKILL.md b/.claude/skills/bmad-os-gh-triage/SKILL.md similarity index 100% rename from .claude/skills/gh-triage/SKILL.md rename to .claude/skills/bmad-os-gh-triage/SKILL.md diff --git a/.claude/skills/gh-triage/prompts/agent-prompt.md b/.claude/skills/bmad-os-gh-triage/prompts/agent-prompt.md similarity index 100% rename from .claude/skills/gh-triage/prompts/agent-prompt.md rename to .claude/skills/bmad-os-gh-triage/prompts/agent-prompt.md diff --git a/.claude/skills/gh-triage/prompts/instructions.md b/.claude/skills/bmad-os-gh-triage/prompts/instructions.md similarity index 100% rename from .claude/skills/gh-triage/prompts/instructions.md rename to .claude/skills/bmad-os-gh-triage/prompts/instructions.md diff --git a/.claude/skills/release-module/README.md b/.claude/skills/bmad-os-release-module/README.md similarity index 100% rename from .claude/skills/release-module/README.md rename to .claude/skills/bmad-os-release-module/README.md diff --git a/.claude/skills/release-module/SKILL.md b/.claude/skills/bmad-os-release-module/SKILL.md similarity index 100% rename from .claude/skills/release-module/SKILL.md rename to .claude/skills/bmad-os-release-module/SKILL.md diff --git a/.claude/skills/release-module/prompts/instructions.md b/.claude/skills/bmad-os-release-module/prompts/instructions.md similarity index 100% rename from .claude/skills/release-module/prompts/instructions.md rename to .claude/skills/bmad-os-release-module/prompts/instructions.md diff --git a/.gitignore b/.gitignore index fef6d4946..03c4cb860 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ cursor CLAUDE.local.md .serena/ .claude/settings.local.json +.junie/ z*/ diff --git a/.prettierignore b/.prettierignore index 8cbb07f7f..013380044 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,3 +7,6 @@ CODE_OF_CONDUCT.md # BMAD runtime folders (user-specific, not in repo) _bmad/ _bmad*/ + +# IDE integration folders (user-specific, not in repo) +.junie/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 0574f9363..aa9d101d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,40 @@ # Changelog +## [6.0.0] + +V6 Stable Release! The End of Beta! + +### 🎁 Features + +* Add PRD workflow steps 2b (vision/differentiators) and 2c (executive summary) for more complete product requirements documentation +* Add new `bmad uninstall` command with interactive and non-interactive modes for selective component removal +* Add dedicated GitHub Copilot installer that generates enriched `.agent.md`, `.prompt.md` files and project configuration +* Add TEA browser automation prerequisite prompts to guide Playwright CLI/MCP setup after configuration + +### 🐛 Bug Fixes + +* Fix version comparison to use semantic versioning, preventing incorrect downgrade recommendations to older beta versions +* Fix `--custom-content` flag to properly populate sources and selected files in module config +* Fix module configuration UX messaging to show accurate completion status and improve feedback timing +* Fix changelog URL in installer start message for proper GitHub resolution +* Remove incorrect `mode: primary` from OpenCode agent template and restore `name` field across all templates +* Auto-discover PRD files in validate-prd workflow to reduce manual path input +* Fix installer non-interactive mode hanging and improve IDE configuration handling during updates +* Fix workflow-level config.yaml copying for custom content modules + +### ♻️ Refactoring + +* Remove alias variables from Phase 4 workflows, use canonical `{implementation_artifacts}` and `{planning_artifacts}` +* Add missing `project_context` references to workflows for consistency + +### 📚 Documentation + +* Add post-install notes documentation for modules +* Improve project-context documentation and fix folder structure +* Add BMad Builder link to index for extenders + +--- + ## [6.0.0-Beta.8] **Release: February 8, 2026** diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 06ab6d174..d9c12655f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,7 +73,7 @@ After searching, use the [feature request template](https://github.com/bmad-code ### Target Branch -Submit PRs to the `main` branch. +Submit PRs to the `main` branch. We use [trunk-based development](https://trunkbaseddevelopment.com/branch-for-release/): `main` is the trunk where all work lands, and stable release branches receive only cherry-picked fixes. ### PR Size diff --git a/README.md b/README.md index e36d6e36a..950811e85 100644 --- a/README.md +++ b/README.md @@ -5,20 +5,22 @@ [![Node.js Version](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen)](https://nodejs.org) [![Discord](https://img.shields.io/badge/Discord-Join%20Community-7289da?logo=discord&logoColor=white)](https://discord.gg/gk8jAdXWmj) -**Breakthrough Method of Agile AI Driven Development** — An AI-driven agile development framework with 21 specialized agents, 50+ guided workflows, and scale-adaptive intelligence that adjusts from bug fixes to enterprise systems. +**Breakthrough Method of Agile AI Driven Development** — An AI-driven agile development module for the BMad Method Module Ecosystem, the best and most comprehensive Agile AI Driven Development framework that has true scale-adaptive intelligence that adjusts from bug fixes to enterprise systems. -**100% free and open source.** No paywalls. No gated content. No gated Discord. We believe in empowering everyone, not just those who can pay. +**100% free and open source.** No paywalls. No gated content. No gated Discord. We believe in empowering everyone, not just those who can pay for a gated community or courses. -## Why BMad? +## Why the BMad Method? -Traditional AI tools do the thinking for you, producing average results. BMad agents and facilitated workflow act as expert collaborators who guide you through a structured process to bring out your best thinking in partnership with the AI. +Traditional AI tools do the thinking for you, producing average results. BMad agents and facilitated workflows act as expert collaborators who guide you through a structured process to bring out your best thinking in partnership with the AI. -- **AI Intelligent Help**: Brand new for beta - AI assisted help will guide you from the beginning to the end - just ask for `/bmad-help` after you have installed BMad to your project -- **Scale-Domain-Adaptive**: Automatically adjusts planning depth and needs based on project complexity, domain and type - a SaaS Mobile Dating App has different planning needs from a diagnostic medical system, BMad adapts and helps you along the way -- **Structured Workflows**: Grounded in agile best practices across analysis, planning, architecture, and implementation -- **Specialized Agents**: 12+ domain experts (PM, Architect, Developer, UX, Scrum Master, and more) -- **Party Mode**: Bring multiple agent personas into one session to plan, troubleshoot, or discuss your project collaboratively, multiple perspectives with maximum fun -- **Complete Lifecycle**: From brainstorming to deployment, BMad is there with you every step of the way +- **AI Intelligent Help** — Ask `/bmad-help` anytime for guidance on what's next +- **Scale-Domain-Adaptive** — Automatically adjusts planning depth based on project complexity +- **Structured Workflows** — Grounded in agile best practices across analysis, planning, architecture, and implementation +- **Specialized Agents** — 12+ domain experts (PM, Architect, Developer, UX, Scrum Master, and more) +- **Party Mode** — Bring multiple agent personas into one session to collaborate and discuss +- **Complete Lifecycle** — From brainstorming to deployment + +[Learn more at **docs.bmad-method.org**](http://docs.bmad-method.org) ## Quick Start @@ -28,103 +30,41 @@ Traditional AI tools do the thinking for you, producing average results. BMad ag npx bmad-method install ``` -Follow the installer prompts, then open your AI IDE (Claude Code, Cursor, Windsurf, etc.) in the project folder. +> If you are getting a stale beta version, use: `npx bmad-method@6.0.1 install` -**Non-Interactive Installation**: For CI/CD pipelines or automated deployments, use command-line flags: +Follow the installer prompts, then open your AI IDE (Claude Code, Cursor, etc.) in your project folder. + +**Non-Interactive Installation** (for CI/CD): ```bash npx bmad-method install --directory /path/to/project --modules bmm --tools claude-code --yes ``` -See [Non-Interactive Installation Guide](http://docs.bmad-method.org/how-to/non-interactive-installation/) for all available options. +[See all installation options](http://docs.bmad-method.org/how-to/non-interactive-installation/) -> **Not sure what to do?** Run `/bmad-help` — it tells you exactly what's next and what's optional. You can also ask it questions like: - - - `/bmad-help How should I build a web app for my TShirt Business that can scale to millions?` - - `/bmad-help I just finished the architecture, I am not sure what to do next` - -And the amazing thing is BMad Help evolves depending on what modules you install also! - - `/bmad-help Im interested in really exploring creative ways to demo BMad at work, what do you recommend to help plan a great slide deck and compelling narrative?`, and if you have the Creative Intelligence Suite installed, it will offer you different or complimentary advice than if you just have BMad Method Module installed! - -The workflows below show the fastest path to working code. You can also load agents directly for a more structured process, extensive planning, or to learn about agile development practices — the agents guide you with menus, explanations, and elicitation at each step. - -### Simple Path (Quick Flow) - -Bug fixes, small features, clear scope — 3 commands - 1 Optional Agent: - -1. `/quick-spec` — analyzes your codebase and produces a tech-spec with stories -2. `/dev-story` — implements each story -3. `/code-review` — validates quality - -### Full Planning Path (BMad Method) - -Products, platforms, complex features — structured planning then build: - -1. `/product-brief` — define problem, users, and MVP scope -2. `/create-prd` — full requirements with personas, metrics, and risks -3. `/create-architecture` — technical decisions and system design -4. `/create-epics-and-stories` — break work into prioritized stories -5. `/sprint-planning` — initialize sprint tracking -6. **Repeat per story:** `/create-story` → `/dev-story` → `/code-review` - -Every step tells you what's next. Optional phases (brainstorming, research, UX design) are available when you need them — ask `/bmad-help` anytime. For a detailed walkthrough, see the [Getting Started Tutorial](http://docs.bmad-method.org/tutorials/getting-started/). +> **Not sure what to do?** Run `/bmad-help` — it tells you exactly what's next and what's optional. You can also ask questions like `/bmad-help I just finished the architecture, what do I do next?` ## Modules -BMad Method extends with official modules for specialized domains. Modules are available during installation and can be added to your project at any time. After the V6 beta period these will also be available as Plugins and Granular Skills. +BMad Method extends with official modules for specialized domains. Available during installation or anytime after. -| Module | GitHub | NPM | Purpose | -| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | -| **BMad Method (BMM)** | [bmad-code-org/BMAD-METHOD](https://github.com/bmad-code-org/BMAD-METHOD) | [bmad-method](https://www.npmjs.com/package/bmad-method) | Core framework with 34+ workflows across 4 development phases | -| **BMad Builder (BMB)** | [bmad-code-org/bmad-builder](https://github.com/bmad-code-org/bmad-builder) | [bmad-builder](https://www.npmjs.com/package/bmad-builder) | Create custom BMad agents, workflows, and domain-specific modules | -| **Test Architect (TEA)** 🆕 | [bmad-code-org/tea](https://github.com/bmad-code-org/bmad-method-test-architecture-enterprise) | [tea](https://www.npmjs.com/package/bmad-method-test-architecture-enterprise) | Risk-based test strategy, automation, and release gates (8 workflows) | -| **Game Dev Studio (BMGD)** | [bmad-code-org/bmad-module-game-dev-studio](https://github.com/bmad-code-org/bmad-module-game-dev-studio) | [bmad-game-dev-studio](https://www.npmjs.com/package/bmad-game-dev-studio) | Game development workflows for Unity, Unreal, and Godot | -| **Creative Intelligence Suite (CIS)** | [bmad-code-org/bmad-module-creative-intelligence-suite](https://github.com/bmad-code-org/bmad-module-creative-intelligence-suite) | [bmad-creative-intelligence-suite](https://www.npmjs.com/package/bmad-creative-intelligence-suite) | Innovation, brainstorming, design thinking, and problem-solving | - -* More modules are coming in the next 2 weeks from BMad Official, and a community marketplace for the installer also will be coming with the final V6 release! - -## Testing Agents - -BMad provides two testing options to fit your needs: - -### Quinn (QA) - Built-in - -**Quick test automation for rapid coverage** - -- ✅ **Always available** in BMM module (no separate install) -- ✅ **Simple**: One workflow (`QA` - Automate) -- ✅ **Beginner-friendly**: Standard test framework patterns -- ✅ **Fast**: Generate tests and ship - -**Use Quinn for:** Small projects, quick coverage, standard patterns - -### Test Architect (TEA) - Optional Module - -**Enterprise-grade test strategy and quality engineering** - -- 🆕 **Standalone module** (install separately) -- 🏗️ **Comprehensive**: 8 workflows covering full test lifecycle -- 🎯 **Advanced**: Risk-based planning, quality gates, NFR assessment -- 📚 **Knowledge-driven**: 34 testing patterns and best practices -- 📖 [Test Architect Documentation](https://bmad-code-org.github.io/bmad-method-test-architecture-enterprise/) - -**Use TEA for:** Enterprise projects, test strategy, compliance, release gates - ---- +| Module | Purpose | +| ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | +| **[BMad Method (BMM)](https://github.com/bmad-code-org/BMAD-METHOD)** | Core framework with 34+ workflows | +| **[BMad Builder (BMB)](https://github.com/bmad-code-org/bmad-builder)** | Create custom BMad agents and workflows | +| **[Test Architect (TEA)](https://github.com/bmad-code-org/tea)** | Risk-based test strategy and automation | +| **[Game Dev Studio (BMGD)](https://github.com/bmad-code-org/bmad-module-game-dev-studio)** | Game development workflows (Unity, Unreal, Godot) | +| **[Creative Intelligence Suite (CIS)](https://github.com/bmad-code-org/bmad-module-creative-intelligence-suite)** | Innovation, brainstorming, design thinking | ## Documentation -**[BMad Documentation](http://docs.bmad-method.org)** — Tutorials, how-to guides, concepts, and reference -**[Test Architect Documentation](https://bmad-code-org.github.io/bmad-method-test-architecture-enterprise/)** — TEA standalone module documentation +[BMad Method Docs Site](http://docs.bmad-method.org) — Tutorials, guides, concepts, and reference +**Quick links:** - [Getting Started Tutorial](http://docs.bmad-method.org/tutorials/getting-started/) - [Upgrading from Previous Versions](http://docs.bmad-method.org/how-to/upgrade-to-v6/) -- [Test Architect Migration Guide](https://bmad-code-org.github.io/bmad-method-test-architecture-enterprise/migration/) — Upgrading from BMM-embedded TEA +- [Test Architect Documentation](https://bmad-code-org.github.io/bmad-method-test-architecture-enterprise/) -### For v4 Users - -- **[v4 Documentation](https://github.com/bmad-code-org/BMAD-METHOD/tree/V4/docs)** -- If you need to install V4, you can do this with `npx bmad-method@4.44.3 install` - similar for any past version. ## Community diff --git a/docs/_STYLE_GUIDE.md b/docs/_STYLE_GUIDE.md index 801314cd0..c6e9eff58 100644 --- a/docs/_STYLE_GUIDE.md +++ b/docs/_STYLE_GUIDE.md @@ -75,10 +75,12 @@ Show in "What You've Accomplished" sections: ````md ``` your-project/ -├── _bmad/ # BMad configuration +├── _bmad/ # BMad configuration ├── _bmad-output/ -│ ├── PRD.md # Your requirements document -│ └── bmm-workflow-status.yaml # Progress tracking +│ ├── planning-artifacts/ +│ │ └── PRD.md # Your requirements document +│ ├── implementation-artifacts/ +│ └── project-context.md # Implementation rules (optional) └── ... ``` ```` @@ -142,12 +144,12 @@ your-project/ ### Types -| Type | Example | -| ----------------- | ---------------------------- | -| **Index/Landing** | `core-concepts/index.md` | -| **Concept** | `what-are-agents.md` | -| **Feature** | `quick-flow.md` | -| **Philosophy** | `why-solutioning-matters.md` | +| Type | Example | +| ----------------- | ----------------------------- | +| **Index/Landing** | `core-concepts/index.md` | +| **Concept** | `what-are-agents.md` | +| **Feature** | `quick-flow.md` | +| **Philosophy** | `why-solutioning-matters.md` | | **FAQ** | `established-projects-faq.md` | ### General Template diff --git a/docs/explanation/project-context.md b/docs/explanation/project-context.md new file mode 100644 index 000000000..6522b92a5 --- /dev/null +++ b/docs/explanation/project-context.md @@ -0,0 +1,157 @@ +--- +title: "Project Context" +description: How project-context.md guides AI agents with your project's rules and preferences +sidebar: + order: 7 +--- + +The `project-context.md` file is your project's implementation guide for AI agents. Similar to a "constitution" in other development systems, it captures the rules, patterns, and preferences that ensure consistent code generation across all workflows. + +## What It Does + +AI agents make implementation decisions constantly — which patterns to follow, how to structure code, what conventions to use. Without clear guidance, they may: +- Follow generic best practices that don't match your codebase +- Make inconsistent decisions across different stories +- Miss project-specific requirements or constraints + +The `project-context.md` file solves this by documenting what agents need to know in a concise, LLM-optimized format. + +## How It Works + +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 + +## When to Create It + +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 | + +:::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. +::: + +## What Goes In It + +The file has two main sections: + +### Technology Stack & Versions + +Documents the frameworks, languages, and tools your project uses with specific versions: + +```markdown +## Technology Stack & Versions + +- Node.js 20.x, TypeScript 5.3, React 18.2 +- State: Zustand (not Redux) +- Testing: Vitest, Playwright, MSW +- Styling: Tailwind CSS with custom design tokens +``` + +### Critical Implementation Rules + +Documents patterns and conventions that agents might otherwise miss: + +```markdown +## Critical Implementation Rules + +**TypeScript Configuration:** +- Strict mode enabled — no `any` types without explicit approval +- Use `interface` for public APIs, `type` for unions/intersections + +**Code Organization:** +- Components in `/src/components/` with co-located `.test.tsx` +- Utilities in `/src/lib/` for reusable pure functions +- API calls use the `apiClient` singleton — never fetch directly + +**Testing Patterns:** +- Unit tests focus on business logic, not implementation details +- Integration tests use MSW to mock API responses +- E2E tests cover critical user journeys only + +**Framework-Specific:** +- All async operations use the `handleError` wrapper for consistent error handling +- Feature flags accessed via `featureFlag()` from `@/lib/flags` +- New routes follow the file-based routing pattern in `/src/app/` +``` + +Focus on what's **unobvious** — things agents might not infer from reading code snippets. Don't document standard practices that apply universally. + +## Creating the File + +You have three options: + +### Manual Creation + +Create the file at `_bmad-output/project-context.md` and add your rules: + +```bash +# In your project root +mkdir -p _bmad-output +touch _bmad-output/project-context.md +``` + +Edit it with your technology stack and implementation rules. The architect and implementation workflows will automatically find and load it. + +### Generate After Architecture + +Run the `generate-project-context` workflow after completing your architecture: + +```bash +/bmad-bmm-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: + +```bash +/bmad-bmm-generate-project-context +``` + +The workflow analyzes your codebase to identify conventions, then generates a context file you can review and refine. + +## Why It Matters + +Without `project-context.md`, agents make assumptions that may not match your project: + +| Without Context | With Context | +|----------------|--------------| +| Uses generic patterns | Follows your established conventions | +| Inconsistent style across stories | Consistent implementation | +| May miss project-specific constraints | Respects all technical requirements | +| Each agent decides independently | All agents align with same rules | + +This is especially important for: +- **Quick Flow** — skips PRD and architecture, so context file fills the gap +- **Team projects** — ensures all agents follow the same standards +- **Existing projects** — prevents breaking established patterns + +## Editing and Updating + +The `project-context.md` file is a living document. Update it when: + +- Architecture decisions change +- New conventions are established +- 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. + +:::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/how-to/customize-bmad.md b/docs/how-to/customize-bmad.md index 9ebb7884f..d478c349b 100644 --- a/docs/how-to/customize-bmad.md +++ b/docs/how-to/customize-bmad.md @@ -41,14 +41,14 @@ _bmad/_config/agents/ Open the `.customize.yaml` file for the agent you want to modify. Every section is optional -- customize only what you need. -| Section | Behavior | Purpose | -| ------------------- | ------------ | ---------------------------------------------- | -| `agent.metadata` | Replaces | Override the agent's display name | -| `persona` | Replaces | Set role, identity, style, and principles | -| `memories` | Appends | Add persistent context the agent always recalls | -| `menu` | Appends | Add custom menu items for workflows or prompts | -| `critical_actions` | Appends | Define startup instructions for the agent | -| `prompts` | Appends | Create reusable prompts for menu actions | +| Section | Behavior | Purpose | +| ------------------ | -------- | ----------------------------------------------- | +| `agent.metadata` | Replaces | Override the agent's display name | +| `persona` | Replaces | Set role, identity, style, and principles | +| `memories` | Appends | Add persistent context the agent always recalls | +| `menu` | Appends | Add custom menu items for workflows or prompts | +| `critical_actions` | Appends | Define startup instructions for the agent | +| `prompts` | Appends | Create reusable prompts for menu actions | Sections marked **Replaces** overwrite the agent's defaults entirely. Sections marked **Appends** add to the existing configuration. @@ -96,7 +96,7 @@ Add custom entries to the agent's display menu. Each item needs a `trigger`, a t ```yaml menu: - trigger: my-workflow - workflow: '{project-root}/my-custom/workflows/my-workflow.yaml' + workflow: 'my-custom/workflows/my-workflow.yaml' description: My custom workflow - trigger: deploy action: '#deploy-prompt' @@ -136,11 +136,11 @@ npx bmad-method install The installer detects the existing installation and offers these options: -| Option | What It Does | -| --------------------- | ------------------------------------------------------------------- | -| **Quick Update** | Updates all modules to the latest version and recompiles all agents | -| **Recompile Agents** | Applies customizations only, without updating module files | -| **Modify BMad Installation** | Full installation flow for adding or removing modules | +| Option | What It Does | +| ---------------------------- | ------------------------------------------------------------------- | +| **Quick Update** | Updates all modules to the latest version and recompiles all agents | +| **Recompile Agents** | Applies customizations only, without updating module files | +| **Modify BMad Installation** | Full installation flow for adding or removing modules | For customization-only changes, **Recompile Agents** is the fastest option. diff --git a/docs/how-to/established-projects.md b/docs/how-to/established-projects.md index 5f1066a51..cc36e0f90 100644 --- a/docs/how-to/established-projects.md +++ b/docs/how-to/established-projects.md @@ -5,14 +5,14 @@ sidebar: order: 6 --- -Use BMad Method effectively when working on existing projects and legacy codebases, sometimes also referred to as brownfield projects. +Use BMad Method effectively when working on existing projects and legacy codebases. This guide covers the essential workflow for onboarding to existing projects with BMad Method. :::note[Prerequisites] - BMad Method installed (`npx bmad-method install`) - An existing codebase you want to work on -- Access to an AI-powered IDE (Claude Code, Cursor, or Windsurf) +- Access to an AI-powered IDE (Claude Code or Cursor) ::: ## Step 1: Clean Up Completed Planning Artifacts @@ -23,7 +23,30 @@ If you have completed all PRD epics and stories through the BMad process, clean - `_bmad-output/planning-artifacts/` - `_bmad-output/implementation-artifacts/` -## Step 2: Maintain Quality Project Documentation +## Step 2: Create Project Context + +:::tip[Recommended for Existing Projects] +Generate `project-context.md` to capture your existing codebase patterns and conventions. This ensures AI agents follow your established practices when implementing changes. +::: + +Run the generate project context workflow: + +```bash +/bmad-bmm-generate-project-context +``` + +This scans your codebase to identify: +- Technology stack and versions +- Code organization patterns +- Naming conventions +- Testing approaches +- Framework-specific patterns + +You can review and refine the generated file, or create it manually at `_bmad-output/project-context.md` if you prefer. + +[Learn more about project context](../explanation/project-context.md) + +## Step 3: Maintain Quality Project Documentation Your `docs/` folder should contain succinct, well-organized documentation that accurately represents your project: @@ -36,9 +59,21 @@ For complex projects, consider using the `document-project` workflow. It offers ## Step 3: Get Help -Get help to know what to do next based on your unique needs +### BMad-Help: Your Starting Point -Run `bmad-help` to get guidance when you are not sure what to do next. +**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 also **automatically runs at the end of every workflow**, providing clear guidance on exactly what to do next. ### Choosing Your Approach diff --git a/docs/how-to/get-answers-about-bmad.md b/docs/how-to/get-answers-about-bmad.md index 7e1c57ca1..edefdeacb 100644 --- a/docs/how-to/get-answers-about-bmad.md +++ b/docs/how-to/get-answers-about-bmad.md @@ -5,17 +5,48 @@ sidebar: order: 4 --- -If you have successfully installed BMad and the BMad Method (+ other modules as needed) - the first step in getting answers is `/bmad-help`. This will answer upwards of 80% of all questions and is available to you in the IDE as you are working. +## Start Here: BMad-Help -## When to Use This +**The fastest way to get answers about BMad is `/bmad-help`.** This intelligent guide will answer upwards of 80% of all questions and is available to you directly in your IDE as you work. -- You have a question about how BMad works or what to do next with BMad -- You want to understand a specific agent or workflow -- You need quick answers without waiting for Discord +BMad-Help is more than a lookup tool — it: +- **Inspects your project** to see what's already been completed +- **Understands natural language** — ask questions in plain English +- **Varies based on your installed modules** — shows relevant options +- **Auto-runs after workflows** — tells you exactly what to do next +- **Recommends the first required task** — no guessing where to start -:::note[Prerequisites] -An AI tool (Claude Code, Cursor, ChatGPT, Claude.ai, etc.) and either BMad installed in your project or access to the GitHub repo. -::: +### How to Use BMad-Help + +Run it with just the slash command: + +``` +/bmad-help +``` + +Or combine it with a natural language query: + +``` +/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 Show me what's been done so far +``` + +BMad-Help responds with: +- What's recommended for your situation +- What the first required task is +- What the rest of the process looks like + +--- + +## When to Use This Guide + +Use this section when: +- You want to understand BMad's architecture or internals +- You need answers outside of what BMad-Help provides +- You're researching BMad before installing +- You want to explore the source code directly ## Steps diff --git a/docs/how-to/install-bmad.md b/docs/how-to/install-bmad.md index 20a20bab3..177c2c884 100644 --- a/docs/how-to/install-bmad.md +++ b/docs/how-to/install-bmad.md @@ -18,7 +18,7 @@ If you want to use a non interactive installer and provide all install options o :::note[Prerequisites] - **Node.js** 20+ (required for the installer) - **Git** (recommended) -- **AI tool** (Claude Code, Cursor, Windsurf, or similar) +- **AI tool** (Claude Code, Cursor, or similar) ::: ## Steps @@ -49,8 +49,6 @@ Pick which AI tools you use: - Claude Code - Cursor -- Windsurf -- Kiro - 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. @@ -79,7 +77,18 @@ your-project/ ## Verify Installation -Run the `help` workflow (`/bmad-help` on most platforms) 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 +- Show what's available based on your installed modules +- Recommend your first step + +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? +``` ## Troubleshooting diff --git a/docs/how-to/non-interactive-installation.md b/docs/how-to/non-interactive-installation.md index e9122ecdb..fa7a1e7b1 100644 --- a/docs/how-to/non-interactive-installation.md +++ b/docs/how-to/non-interactive-installation.md @@ -59,7 +59,7 @@ Check the [BMad registry](https://github.com/bmad-code-org) for available extern Available tool IDs for the `--tools` flag: -**Preferred:** `claude-code`, `cursor`, `windsurf` +**Preferred:** `claude-code`, `cursor` Run `npx bmad-method install` interactively once to see the full current list of supported tools, or check the [platform codes configuration](https://github.com/bmad-code-org/BMAD-METHOD/blob/main/tools/cli/installers/lib/ide/platform-codes.yaml). diff --git a/docs/how-to/project-context.md b/docs/how-to/project-context.md new file mode 100644 index 000000000..105906098 --- /dev/null +++ b/docs/how-to/project-context.md @@ -0,0 +1,136 @@ +--- +title: "Manage Project Context" +description: Create and maintain project-context.md to guide AI agents +sidebar: + order: 7 +--- + +Use the `project-context.md` file to ensure AI agents follow your project's technical preferences and implementation rules throughout all workflows. + +:::note[Prerequisites] +- BMad Method installed +- Understanding of your project's technology stack and conventions +::: + +## When to Use This + +- You have strong technical preferences before starting architecture +- You've completed architecture and want to capture decisions for implementation +- You're working on an existing codebase with established patterns +- You notice agents making inconsistent decisions across stories + +## Step 1: Choose Your Approach + +**Manual creation** — Best when you know exactly what rules you want to document + +**Generate after architecture** — Best for capturing decisions made during solutioning + +**Generate for existing projects** — Best for discovering patterns in existing codebases + +## Step 2: Create the File + +### Option A: Manual Creation + +Create the file at `_bmad-output/project-context.md`: + +```bash +mkdir -p _bmad-output +touch _bmad-output/project-context.md +``` + +Add your technology stack and implementation rules: + +```markdown +--- +project_name: 'MyProject' +user_name: 'YourName' +date: '2026-02-15' +sections_completed: ['technology_stack', 'critical_rules'] +--- + +# Project Context for AI Agents + +## Technology Stack & Versions + +- Node.js 20.x, TypeScript 5.3, React 18.2 +- State: Zustand +- Testing: Vitest, Playwright +- Styling: Tailwind CSS + +## Critical Implementation Rules + +**TypeScript:** +- Strict mode enabled, no `any` types +- Use `interface` for public APIs, `type` for unions + +**Code Organization:** +- Components in `/src/components/` with co-located tests +- API calls use `apiClient` singleton — never fetch directly + +**Testing:** +- Unit tests focus on business logic +- Integration tests use MSW for API mocking +``` + +### Option B: Generate After Architecture + +Run the workflow in a fresh chat: + +```bash +/bmad-bmm-generate-project-context +``` + +The workflow scans your architecture document and project files to generate a context file capturing the decisions made. + +### Option C: Generate for Existing Projects + +For existing projects, run: + +```bash +/bmad-bmm-generate-project-context +``` + +The workflow analyzes your codebase to identify conventions, then generates a context file you can review and refine. + +## Step 3: Verify Content + +Review the generated file and ensure it captures: + +- Correct technology versions +- Your actual conventions (not generic best practices) +- Rules that prevent common mistakes +- Framework-specific patterns + +Edit manually to add anything missing or remove inaccuracies. + +## What You Get + +A `project-context.md` file that: + +- Ensures all agents follow the same conventions +- Prevents inconsistent decisions across stories +- Captures architecture decisions for implementation +- Serves as a reference for your project's patterns and rules + +## Tips + +:::tip[Focus on the Unobvious] +Document patterns agents might miss such as "Use JSDoc style comments on every public class, function and variable", not universal practices like "use meaningful variable names" which LLMs know at this point. +::: + +:::tip[Keep It Lean] +This file is loaded by every implementation workflow. Long files waste context. Do not include content that only applies to narrow scope or specific stories or features. +::: + +:::tip[Update as Needed] +Edit manually when patterns change, or re-generate after significant architecture changes. +::: + +:::tip[Works for All Project Types] +Just as useful for Quick Flow as for full BMad Method projects. +::: + +## Next Steps + +- [**Project Context Explanation**](../explanation/project-context.md) — Learn more about how it works +- [**Workflow Map**](../reference/workflow-map.md) — See which workflows load project context diff --git a/docs/how-to/quick-fixes.md b/docs/how-to/quick-fixes.md index 4bb870908..76ee5ebe0 100644 --- a/docs/how-to/quick-fixes.md +++ b/docs/how-to/quick-fixes.md @@ -16,7 +16,7 @@ Use the **DEV agent** directly for bug fixes, refactorings, or small targeted ch :::note[Prerequisites] - BMad Method installed (`npx bmad-method install`) -- An AI-powered IDE (Claude Code, Cursor, Windsurf, or similar) +- An AI-powered IDE (Claude Code, Cursor, or similar) ::: ## Choose Your Approach diff --git a/docs/how-to/shard-large-documents.md b/docs/how-to/shard-large-documents.md index e58e37946..b10c64fb8 100644 --- a/docs/how-to/shard-large-documents.md +++ b/docs/how-to/shard-large-documents.md @@ -23,11 +23,11 @@ Document sharding splits large markdown files into smaller, organized files base ```text Before Sharding: -docs/ +_bmad-output/planning-artifacts/ └── PRD.md (large 50k token file) After Sharding: -docs/ +_bmad-output/planning-artifacts/ └── prd/ ├── index.md # Table of contents with descriptions ├── overview.md # Section 1 diff --git a/docs/index.md b/docs/index.md index ddcb421e8..2d3de20cd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,7 +3,7 @@ title: Welcome to the BMad Method description: AI-driven development framework with specialized agents, guided workflows, and intelligent planning --- -The BMad Method (**B**reakthrough **M**ethod of **A**gile AI **D**riven Development) is an AI-driven development framework that helps you build software through the whole process from ideation and planning all the way through agentic implementation. It provides specialized AI agents, guided workflows, and intelligent planning that adapts to your project's complexity, whether you're fixing a bug or building an enterprise platform. +The BMad Method (**B**reakthrough **M**ethod of **A**gile AI **D**riven Development) is an AI-driven development framework module within the BMad Method Ecosystem that helps you build software through the whole process from ideation and planning all the way through agentic implementation. It provides specialized AI agents, guided workflows, and intelligent planning that adapts to your project's complexity, whether you're fixing a bug or building an enterprise platform. If you're comfortable working with AI coding assistants like Claude, Cursor, or GitHub Copilot, you're ready to get started. @@ -12,7 +12,11 @@ If you're comfortable working with AI coding assistants like Claude, Cursor, or The fastest way to understand BMad is to try it. - **[Get Started with BMad](./tutorials/getting-started.md)** — Install and understand how BMad works -- **[Workflow Map](./reference/workflow-map.md)** — Visual overview of BMM phases, workflows, and context management. +- **[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. +::: ## How to Use These Docs @@ -25,15 +29,17 @@ These docs are organized into four sections based on what you're trying to do: | **Explanation** | Understanding-oriented. Deep dives into concepts and architecture. Read when you want to know *why*. | | **Reference** | Information-oriented. Technical specifications for agents, workflows, and configuration. | +## Extend and Customize + +Want to expand BMad with your own agents, workflows, or modules? The **[BMad Builder](https://bmad-builder-docs.bmad-method.org/)** provides the framework and tools for creating custom extensions, whether you're adding new capabilities to BMad or building entirely new modules from scratch. + ## What You'll Need BMad works with any AI coding assistant that supports custom system prompts or project context. Popular options include: - **[Claude Code](https://code.claude.com)** — Anthropic's CLI tool (recommended) - **[Cursor](https://cursor.sh)** — AI-first code editor -- **[Windsurf](https://codeium.com/windsurf)** — Codeium's AI IDE -- **[Kiro](https://kiro.dev)** — Amazon's AI-powered IDE -- **[Roo Code](https://roocode.com)** — VS Code extension +- **[Codex CLI](https://github.com/openai/codex)** — OpenAI's terminal coding agent You should be comfortable with basic software development concepts like version control, project structure, and agile workflows. No prior experience with BMad-style agent systems is required—that's what these docs are for. diff --git a/docs/reference/commands.md b/docs/reference/commands.md index 1ecca7516..af4f1f496 100644 --- a/docs/reference/commands.md +++ b/docs/reference/commands.md @@ -103,9 +103,29 @@ See [Workflow Map](./workflow-map.md) for the complete workflow reference organi 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: + +- **Inspects your project** to see what's already been done +- **Understands natural language queries** — ask questions in plain English +- **Varies by installed modules** — shows options based on what you have +- **Auto-invokes after workflows** — every workflow ends with clear next steps +- **Recommends the first required task** — no guessing where to start + +**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 +``` + +#### Other Tasks and Tools + | Example command | Purpose | | --- | --- | -| `/bmad-help` | Context-aware guidance and next-step recommendations | | `/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 | diff --git a/docs/reference/workflow-map.md b/docs/reference/workflow-map.md index fc38b69ee..05885a5e1 100644 --- a/docs/reference/workflow-map.md +++ b/docs/reference/workflow-map.md @@ -23,68 +23,67 @@ Final important note: Every workflow below can be run directly with your tool of Explore the problem space and validate ideas before committing to planning. -| Workflow | Purpose | Produces | -| ---------------------- | -------------------------------------------------------------------------- | ------------------------- | -| `brainstorming` | Brainstorm Project Ideas with guided facilitation of a brainstorming coach | `brainstorming-report.md` | -| `research` | Validate market, technical, or domain assumptions | Research findings | -| `create-product-brief` | Capture strategic vision | `product-brief.md` | +| 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` | ## Phase 2: Planning Define what to build and for whom. -| Workflow | Purpose | Produces | -| ------------------ | ---------------------------------------- | ------------ | -| `create-prd` | Define requirements (FRs/NFRs) | `PRD.md` | -| `create-ux-design` | Design user experience (when UX matters) | `ux-spec.md` | +| 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` | ## Phase 3: Solutioning Decide how to build it and break work into stories. -| Workflow | Purpose | Produces | -| -------------------------------- | ------------------------------------------ | --------------------------- | -| `create-architecture` | Make technical decisions explicit | `architecture.md` with ADRs | -| `create-epics-and-stories` | Break requirements into implementable work | Epic files with stories | -| `check-implementation-readiness` | Gate check before implementation | PASS/CONCERNS/FAIL decision | +| 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 | ## Phase 4: Implementation -Build it, one story at a time. +Build it, one story at a time. Coming soon, full phase 4 automation! -| Workflow | Purpose | Produces | -| ----------------- | -------------------------------------- | ----------------------------- | -| `sprint-planning` | Initialize tracking (once per project) | `sprint-status.yaml` | -| `create-story` | Prepare next story for implementation | `story-[slug].md` | -| `dev-story` | Implement the story | Working code + tests | -| `automate` (QA) | Generate tests for existing features | Test suite | -| `code-review` | Validate implementation quality | Approved or changes requested | -| `correct-course` | Handle significant mid-sprint changes | Updated plan or re-routing | -| `retrospective` | Review after epic completion | Lessons learned | - -**Quinn (QA Agent):** Built-in QA agent for test automation. Trigger with `QA` or `bmad-bmm-qa-automate`. Generates standard API and E2E tests using your project's test framework. Beginner-friendly, no configuration needed. For advanced test strategy, install [Test Architect (TEA)](https://bmad-code-org.github.io/bmad-method-test-architecture-enterprise/) module. +| 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 | ## Quick Flow (Parallel Track) Skip phases 1-3 for small, well-understood work. -| Workflow | Purpose | Produces | -| ------------ | ------------------------------------------ | --------------------------------------------- | -| `quick-spec` | Define an ad-hoc change | `tech-spec.md` (story file for small changes) | -| `quick-dev` | Implement from spec or direct instructions | Working code + tests | +| 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 | ## Context Management Each document becomes context for the next phase. The PRD tells the architect what constraints matter. The architecture tells the dev agent which patterns to follow. Story files give focused, complete context for implementation. Without this structure, agents make inconsistent decisions. -For established projects, `document-project` creates or updates `project-context.md` - what exists in the codebase and the rules all implementation workflows must observe. Run it just before Phase 4, and again when something significant changes - structure, architecture, or those rules. You can also edit `project-context.md` by hand. +### Project Context -All implementation workflows load `project-context.md` if it exists. Additional context per workflow: +:::tip[Recommended] +Create `project-context.md` to ensure AI agents follow your project's rules and preferences. This file works like a constitution for your project — it guides implementation decisions across all workflows. This optional file can be generated at the end of Architecture Creation, or in an existing project it can be generated also to capture whats important to keep aligned with current conventions. +::: -| Workflow | Also Loads | -| -------------- | ---------------------------- | -| `create-story` | epics, PRD, architecture, UX | -| `dev-story` | story file | -| `code-review` | architecture, story file | -| `quick-spec` | planning docs (if exist) | -| `quick-dev` | tech-spec | +**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 + +[**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 f8dbdad2f..b7aa02dfd 100644 --- a/docs/tutorials/getting-started.md +++ b/docs/tutorials/getting-started.md @@ -8,6 +8,7 @@ Build software faster using AI-powered workflows with specialized agents that gu ## What You'll Learn - Install and initialize BMad Method for a new project +- Use **BMad-Help** — your intelligent guide that knows what to do next - Choose the right planning track for your project size - Progress through phases from requirements to working code - Use agents and workflows effectively @@ -15,15 +16,50 @@ Build software faster using AI-powered workflows with specialized agents that gu :::note[Prerequisites] - **Node.js 20+** — Required for the installer - **Git** — Recommended for version control -- **AI-powered IDE** — Claude Code, Cursor, Windsurf, or similar +- **AI-powered IDE** — Claude Code, Cursor, or similar - **A project idea** — Even a simple one works for learning ::: -:::tip[Quick Path] +:::tip[The Easiest Path] **Install** → `npx bmad-method install` -**Plan** → PM creates PRD, Architect creates architecture -**Build** → SM manages sprints, DEV implements stories -**Fresh chats** for each workflow to avoid context issues. +**Ask** → `/bmad-help what should I do first?` +**Build** → Let BMad-Help guide you workflow by workflow +::: + +## Meet BMad-Help: Your Intelligent Guide + +**BMad-Help is the fastest way to get started with BMad.** You don't need to memorize workflows or phases — just ask, and BMad-Help will: + +- **Inspect your project** to see what's already been done +- **Show your options** based on which modules you have installed +- **Recommend what's next** — including the first required task +- **Answer questions** like "I have a SaaS idea, where do I start?" + +### How to Use BMad-Help + +Run it in your AI IDE with just the slash command: + +``` +/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 will respond with: +- What's recommended for your situation +- What the first required task is +- What the rest of the process looks like + +### It Powers Workflows Too + +BMad-Help doesn't just answer questions — **it automatically runs at the end of every workflow** to tell you exactly what to do next. No guessing, no searching docs — just clear guidance on the next required workflow. + +:::tip[Start Here] +After installing BMad, run `/bmad-help` immediately. It will detect what modules you have installed and guide you to the right starting point for your project. ::: ## Understanding BMad @@ -65,7 +101,15 @@ The installer creates two folders: - `_bmad/` — agents, workflows, tasks, and configuration - `_bmad-output/` — empty for now, but this is where your artifacts will be saved -Open your AI IDE in the project folder. Run the `help` workflow (`/bmad-help`) to see what to do next — it detects what you've completed and recommends the next step. +:::tip[Your Next Step] +Open your AI IDE in the project folder and run: + +``` +/bmad-help +``` + +BMad-Help will detect what you've completed and recommend exactly what to do next. You can also ask it questions like "What are my options?" or "I have a SaaS idea, where should I start?" +::: :::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). @@ -79,6 +123,12 @@ Always start a fresh chat for each workflow. This prevents context limitations f 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). +::: + ### Phase 1: Analysis (Optional) All workflows in this phase are optional: @@ -155,22 +205,26 @@ Your project now has: ```text your-project/ -├── _bmad/ # BMad configuration +├── _bmad/ # BMad configuration ├── _bmad-output/ -│ ├── PRD.md # Your requirements document -│ ├── architecture.md # Technical decisions -│ ├── epics/ # Epic and story files -│ └── sprint-status.yaml # Sprint tracking +│ ├── planning-artifacts/ +│ │ ├── PRD.md # Your requirements document +│ │ ├── architecture.md # Technical decisions +│ │ └── epics/ # Epic and story files +│ ├── implementation-artifacts/ +│ │ └── sprint-status.yaml # Sprint tracking +│ └── project-context.md # Implementation rules (optional) └── ... ``` ## Quick Reference -| Workflow | Command | Agent | Purpose | -| -------------------------------- | ------------------------------------------ | --------- | ------------------------------------ | -| `help` | `/bmad-help` | Any | Get guidance on what to do next | -| `prd` | `/bmad-bmm-create-prd` | PM | Create Product Requirements Document | -| `create-architecture` | `/bmad-bmm-create-architecture` | Architect | Create architecture document | +| 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 | @@ -194,16 +248,26 @@ Not strictly. Once you learn the flow, you can run workflows directly using the ## Getting Help +:::tip[First Stop: BMad-Help] +**Run `/bmad-help` anytime** — it's the fastest way to get unstuck. Ask it anything: +- "What should I do after installing?" +- "I'm stuck on workflow X" +- "What are my options for Y?" +- "Show me what's been done so far" + +BMad-Help inspects your project, detects what you've completed, and tells you exactly what to do next. +::: + - **During workflows** — Agents guide you with questions and explanations - **Community** — [Discord](https://discord.gg/gk8jAdXWmj) (#bmad-method-help, #report-bugs-and-issues) -- **Stuck?** — Run `help` (`/bmad-help`) to see what to do next ## Key Takeaways :::tip[Remember These] +- **Start with `/bmad-help`** — Your intelligent guide that knows your project and options - **Always use fresh chats** — Start a new chat for each workflow - **Track matters** — Quick Flow uses quick-spec; Method/Enterprise need PRD and architecture -- **Use `help` (`/bmad-help`) when stuck** — It detects your progress and suggests next steps +- **BMad-Help runs automatically** — Every workflow ends with guidance on what's next ::: -Ready to start? Install BMad and let the agents guide you through your first project. +Ready to start? Install BMad, run `/bmad-help`, and let your intelligent guide lead the way. diff --git a/package-lock.json b/package-lock.json index da039ecc6..5f538a62f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bmad-method", - "version": "6.0.0-Beta.8", + "version": "6.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "bmad-method", - "version": "6.0.0-Beta.8", + "version": "6.0.1", "license": "MIT", "dependencies": { "@clack/core": "^1.0.0", diff --git a/package.json b/package.json index 9cd7e90ad..3881e2733 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "bmad-method", - "version": "6.0.0-Beta.8", + "version": "6.0.1", "description": "Breakthrough Method of Agile AI-driven Development", "keywords": [ "agile", @@ -25,6 +25,7 @@ }, "scripts": { "bmad:install": "node tools/cli/bmad-cli.js install", + "bmad:uninstall": "node tools/cli/bmad-cli.js uninstall", "docs:build": "node tools/build-docs.mjs", "docs:dev": "astro dev --root website", "docs:fix-links": "node tools/fix-doc-links.js", @@ -44,7 +45,7 @@ "test:install": "node test/test-installation-components.js", "test:refs": "node test/test-file-refs-csv.js", "test:schemas": "node test/test-agent-schema.js", - "validate:refs": "node tools/validate-file-refs.js", + "validate:refs": "node tools/validate-file-refs.js --strict", "validate:schemas": "node tools/validate-agent-schema.js" }, "lint-staged": { diff --git a/src/bmm/agents/analyst.agent.yaml b/src/bmm/agents/analyst.agent.yaml index c340f69c1..28120d098 100644 --- a/src/bmm/agents/analyst.agent.yaml +++ b/src/bmm/agents/analyst.agent.yaml @@ -5,6 +5,7 @@ agent: title: Business Analyst icon: 📊 module: bmm + capabilities: "market research, competitive analysis, requirements elicitation, domain expertise" hasSidecar: false persona: diff --git a/src/bmm/agents/architect.agent.yaml b/src/bmm/agents/architect.agent.yaml index 5ebfd90fb..d9fc48b9b 100644 --- a/src/bmm/agents/architect.agent.yaml +++ b/src/bmm/agents/architect.agent.yaml @@ -7,6 +7,7 @@ agent: title: Architect icon: 🏗️ module: bmm + capabilities: "distributed systems, cloud infrastructure, API design, scalable patterns" hasSidecar: false persona: diff --git a/src/bmm/agents/dev.agent.yaml b/src/bmm/agents/dev.agent.yaml index d88166eda..c707124d0 100644 --- a/src/bmm/agents/dev.agent.yaml +++ b/src/bmm/agents/dev.agent.yaml @@ -7,6 +7,7 @@ agent: title: Developer Agent icon: 💻 module: bmm + capabilities: "story execution, test-driven development, code implementation" hasSidecar: false persona: diff --git a/src/bmm/agents/pm.agent.yaml b/src/bmm/agents/pm.agent.yaml index 9ce0bf32f..30377a682 100644 --- a/src/bmm/agents/pm.agent.yaml +++ b/src/bmm/agents/pm.agent.yaml @@ -5,6 +5,7 @@ agent: title: Product Manager icon: 📋 module: bmm + capabilities: "PRD creation, requirements discovery, stakeholder alignment, user interviews" hasSidecar: false persona: diff --git a/src/bmm/agents/qa.agent.yaml b/src/bmm/agents/qa.agent.yaml index 07ca4022f..9265f5a7b 100644 --- a/src/bmm/agents/qa.agent.yaml +++ b/src/bmm/agents/qa.agent.yaml @@ -5,6 +5,7 @@ agent: title: QA Engineer icon: 🧪 module: bmm + capabilities: "test automation, API testing, E2E testing, coverage analysis" hasSidecar: false persona: diff --git a/src/bmm/agents/quick-flow-solo-dev.agent.yaml b/src/bmm/agents/quick-flow-solo-dev.agent.yaml index 6d207a399..fff3052d4 100644 --- a/src/bmm/agents/quick-flow-solo-dev.agent.yaml +++ b/src/bmm/agents/quick-flow-solo-dev.agent.yaml @@ -7,6 +7,7 @@ agent: title: Quick Flow Solo Dev icon: 🚀 module: bmm + capabilities: "rapid spec creation, lean implementation, minimum ceremony" hasSidecar: false persona: diff --git a/src/bmm/agents/sm.agent.yaml b/src/bmm/agents/sm.agent.yaml index 9e51f4259..d79f644e5 100644 --- a/src/bmm/agents/sm.agent.yaml +++ b/src/bmm/agents/sm.agent.yaml @@ -7,6 +7,7 @@ agent: title: Scrum Master icon: 🏃 module: bmm + capabilities: "sprint planning, story preparation, agile ceremonies, backlog management" hasSidecar: false persona: diff --git a/src/bmm/agents/tech-writer/tech-writer.agent.yaml b/src/bmm/agents/tech-writer/tech-writer.agent.yaml index a742a6c9f..555bd7981 100644 --- a/src/bmm/agents/tech-writer/tech-writer.agent.yaml +++ b/src/bmm/agents/tech-writer/tech-writer.agent.yaml @@ -7,6 +7,7 @@ agent: title: Technical Writer icon: 📚 module: bmm + capabilities: "documentation, Mermaid diagrams, standards compliance, concept explanation" hasSidecar: true persona: @@ -15,7 +16,7 @@ agent: communication_style: "Patient educator who explains like teaching a friend. Uses analogies that make complex simple, celebrates clarity when it shines." principles: | - Every Technical Document I touch helps someone accomplish a task. Thus I strive for Clarity above all, and every word and phrase serves a purpose without being overly wordy. - - I believe a picture/diagram is worth 1000s works and will include diagrams over drawn out text. + - I believe a picture/diagram is worth 1000s of words and will include diagrams over drawn out text. - I understand the intended audience or will clarify with the user so I know when to simplify vs when to be detailed. - I will always strive to follow `_bmad/_memory/tech-writer-sidecar/documentation-standards.md` best practices. diff --git a/src/bmm/agents/ux-designer.agent.yaml b/src/bmm/agents/ux-designer.agent.yaml index 639a8263f..301a07fc6 100644 --- a/src/bmm/agents/ux-designer.agent.yaml +++ b/src/bmm/agents/ux-designer.agent.yaml @@ -7,6 +7,7 @@ agent: title: UX Designer icon: 🎨 module: bmm + capabilities: "user research, interaction design, UI patterns, experience strategy" hasSidecar: false persona: @@ -23,4 +24,4 @@ agent: menu: - trigger: CU or fuzzy match on ux-design exec: "{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md" - description: "[CU] Create UX: Guidance through realizing the plan for your UX to inform architecture and implementation. PRovides more details that what was discovered in the PRD" + description: "[CU] Create UX: Guidance through realizing the plan for your UX to inform architecture and implementation. Provides more details than what was discovered in the PRD" diff --git a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01-init.md b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01-init.md index 496180933..0046af0cc 100644 --- a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01-init.md +++ b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01-init.md @@ -3,7 +3,7 @@ name: 'step-01-init' description: 'Initialize the product brief workflow by detecting continuation state and setting up the document' # File References -nextStepFile: './step-02-vision.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md' outputFile: '{planning_artifacts}/product-brief-{{project_name}}-{{date}}.md' # Template References @@ -73,7 +73,7 @@ If the document exists and has frontmatter with `stepsCompleted`: **Continuation Protocol:** -- **STOP immediately** and load `./step-01b-continue.md` +- **STOP immediately** and load `{project-root}/_bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md` - Do not proceed with any initialization tasks - Let step-01b handle all continuation logic - This is an auto-proceed situation - no user choice needed diff --git a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md index 99b2495fe..bedcfc913 100644 --- a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md +++ b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md @@ -95,9 +95,9 @@ Does this look right, or do you want to make any adjustments before we proceed?" **Next Step Logic:** Based on `lastStep` value, determine which step to load next: -- If `lastStep = 1` → Load `./step-02-vision.md` -- If `lastStep = 2` → Load `./step-03-users.md` -- If `lastStep = 3` → Load `./step-04-metrics.md` +- If `lastStep = 1` → Load `{project-root}/_bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md` +- If `lastStep = 2` → Load `{project-root}/_bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md` +- If `lastStep = 3` → Load `{project-root}/_bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md` - Continue this pattern for all steps - If `lastStep = 6` → Workflow already complete diff --git a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md index f00e18faa..fbbdffd01 100644 --- a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +++ b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md @@ -3,7 +3,7 @@ name: 'step-02-vision' description: 'Discover and define the core product vision, problem statement, and unique value proposition' # File References -nextStepFile: './step-03-users.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md' outputFile: '{planning_artifacts}/product-brief-{{project_name}}-{{date}}.md' # Task References diff --git a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md index cba266411..eb8fd1168 100644 --- a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +++ b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md @@ -3,7 +3,7 @@ name: 'step-03-users' description: 'Define target users with rich personas and map their key interactions with the product' # File References -nextStepFile: './step-04-metrics.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md' outputFile: '{planning_artifacts}/product-brief-{{project_name}}-{{date}}.md' # Task References diff --git a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md index e6b297c3d..04c67edc4 100644 --- a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +++ b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md @@ -3,7 +3,7 @@ name: 'step-04-metrics' description: 'Define comprehensive success metrics that include user success, business objectives, and key performance indicators' # File References -nextStepFile: './step-05-scope.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md' outputFile: '{planning_artifacts}/product-brief-{{project_name}}-{{date}}.md' # Task References diff --git a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md index 0914b835d..04339f41f 100644 --- a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +++ b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md @@ -3,7 +3,7 @@ name: 'step-05-scope' description: 'Define MVP scope with clear boundaries and outline future vision while managing scope creep' # File References -nextStepFile: './step-06-complete.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md' outputFile: '{planning_artifacts}/product-brief-{{project_name}}-{{date}}.md' # Task References diff --git a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md index 010cafe8e..82573286f 100644 --- a/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +++ b/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md @@ -128,7 +128,7 @@ Recap that the brief captures everything needed to guide subsequent product deve ### 5. Suggest next steps -Product Brief complete. Read fully and follow: `_bmad/core/tasks/help.md` with argument `Validate PRD`. +Product Brief complete. Read fully and follow: `{project-root}/_bmad/core/tasks/help.md` with argument `Validate PRD`. --- diff --git a/src/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md b/src/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md index 27d056b1d..50093186e 100644 --- a/src/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md +++ b/src/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md @@ -78,7 +78,7 @@ For **{{research_topic}}**, I will research: - Document scope confirmation in research file - Update frontmatter: `stepsCompleted: [1]` -- Load: `./step-02-domain-analysis.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md` ## APPEND TO DOCUMENT: @@ -132,6 +132,6 @@ When user selects 'C', append scope confirmation: ## NEXT STEP: -After user selects 'C', load `./step-02-domain-analysis.md` to begin industry analysis. +After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md` to begin industry analysis. Remember: This is SCOPE CONFIRMATION ONLY - no actual domain research yet, just confirming the research approach and scope! diff --git a/src/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md b/src/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md index bb4cbb63f..ed5c78f5e 100644 --- a/src/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md +++ b/src/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md @@ -171,7 +171,7 @@ _Source: [URL]_ - **CONTENT ALREADY WRITTEN TO DOCUMENT** - Update frontmatter: `stepsCompleted: [1, 2]` -- Load: `./step-03-competitive-landscape.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md` ## APPEND TO DOCUMENT: @@ -224,6 +224,6 @@ Content is already written to document when generated in step 4. No additional a ## NEXT STEP: -After user selects 'C', load `./step-03-competitive-landscape.md` to analyze competitive landscape, key players, and ecosystem analysis for {{research_topic}}. +After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md` to analyze competitive landscape, key players, and ecosystem analysis for {{research_topic}}. Remember: Always write research content to document immediately and search the web to verify facts! diff --git a/src/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md b/src/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md index 0dc2de6ea..6970ad87b 100644 --- a/src/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md +++ b/src/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md @@ -180,7 +180,7 @@ _Source: [URL]_ - **CONTENT ALREADY WRITTEN TO DOCUMENT** - Update frontmatter: `stepsCompleted: [1, 2, 3]` -- Load: `./step-04-regulatory-focus.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md` ## APPEND TO DOCUMENT: @@ -233,6 +233,6 @@ Content is already written to document when generated in step 4. No additional a ## NEXT STEP: -After user selects 'C', load `./step-04-regulatory-focus.md` to analyze regulatory requirements, compliance frameworks, and legal considerations for {{research_topic}}. +After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md` to analyze regulatory requirements, compliance frameworks, and legal considerations for {{research_topic}}. Remember: Always write research content to document immediately and search the web to verify facts! diff --git a/src/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md b/src/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md index e98010c7f..3fd24b00b 100644 --- a/src/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md +++ b/src/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md @@ -155,7 +155,7 @@ Show the generated regulatory analysis and present continue option: - **CONTENT ALREADY WRITTEN TO DOCUMENT** - Update frontmatter: `stepsCompleted: [1, 2, 3, 4]` -- Load: `./step-05-technical-trends.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md` ## APPEND TO DOCUMENT: @@ -201,6 +201,6 @@ Content is already written to document when generated in step 5. No additional a ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-05-technical-trends.md` to analyze technical trends and innovations in the domain. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md` to analyze technical trends and innovations in the domain. Remember: Search the web to verify regulatory facts and provide practical implementation considerations! diff --git a/src/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md b/src/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md index 55e834cd1..caf69e142 100644 --- a/src/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md +++ b/src/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md @@ -174,7 +174,7 @@ Show the generated technical analysis and present complete option: - **CONTENT ALREADY WRITTEN TO DOCUMENT** - Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5]` -- Load: `./step-06-research-synthesis.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md` ## APPEND TO DOCUMENT: diff --git a/src/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md b/src/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md index 1c7db8c05..9e2261fb7 100644 --- a/src/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md +++ b/src/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md @@ -373,6 +373,7 @@ _This comprehensive research document serves as an authoritative reference on {{ #### If 'C' (Complete Research): +- **Replace** the template placeholder `[Research overview and methodology will be appended here]` in the `## Research Overview` section near the top of the document with a concise 2-3 paragraph overview summarizing the research scope, key findings, and a pointer to the full executive summary in the Research Synthesis section - Append the complete document to the research file - Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5]` - Complete the domain research workflow @@ -380,7 +381,7 @@ _This comprehensive research document serves as an authoritative reference on {{ ## APPEND TO DOCUMENT: -When user selects 'C', append the complete comprehensive research document using the full structure above. +When user selects 'C', append the complete comprehensive research document using the full structure above. Also replace the `[Research overview and methodology will be appended here]` placeholder in the Research Overview section at the top of the document. ## SUCCESS METRICS: diff --git a/src/bmm/workflows/1-analysis/research/market-steps/step-01-init.md b/src/bmm/workflows/1-analysis/research/market-steps/step-01-init.md index 5ab859398..ba7563b71 100644 --- a/src/bmm/workflows/1-analysis/research/market-steps/step-01-init.md +++ b/src/bmm/workflows/1-analysis/research/market-steps/step-01-init.md @@ -138,7 +138,7 @@ Show initial scope document and present continue option: - Update frontmatter: `stepsCompleted: [1]` - Add confirmation note to document: "Scope confirmed by user on {{date}}" -- Load: `./step-02-customer-behavior.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md` #### If 'Modify': @@ -177,6 +177,6 @@ This step ensures: ## NEXT STEP: -After user confirmation and scope finalization, load `./step-02-customer-insights.md` to begin detailed market research with customer insights analysis. +After user confirmation and scope finalization, load `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md` to begin detailed market research with customer insights analysis. Remember: Init steps confirm understanding and scope, not generate research content! diff --git a/src/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md b/src/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md index f707a0a3e..e5315e34e 100644 --- a/src/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md +++ b/src/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md @@ -179,7 +179,7 @@ _Source: [URL]_ - **CONTENT ALREADY WRITTEN TO DOCUMENT** - Update frontmatter: `stepsCompleted: [1, 2]` -- Load: `./step-03-customer-pain-points.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md` ## APPEND TO DOCUMENT: @@ -232,6 +232,6 @@ Content is already written to document when generated in step 4. No additional a ## NEXT STEP: -After user selects 'C', load `./step-03-customer-pain-points.md` to analyze customer pain points, challenges, and unmet needs for {{research_topic}}. +After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md` to analyze customer pain points, challenges, and unmet needs for {{research_topic}}. Remember: Always write research content to document immediately and emphasize current customer data with rigorous source verification! diff --git a/src/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md b/src/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md index f4d2ae6d8..d740ae5e4 100644 --- a/src/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md +++ b/src/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md @@ -190,7 +190,7 @@ _Source: [URL]_ - **CONTENT ALREADY WRITTEN TO DOCUMENT** - Update frontmatter: `stepsCompleted: [1, 2, 3]` -- Load: `./step-04-customer-decisions.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md` ## APPEND TO DOCUMENT: @@ -244,6 +244,6 @@ Content is already written to document when generated in step 4. No additional a ## NEXT STEP: -After user selects 'C', load `./step-04-customer-decisions.md` to analyze customer decision processes, journey mapping, and decision factors for {{research_topic}}. +After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md` to analyze customer decision processes, journey mapping, and decision factors for {{research_topic}}. Remember: Always write research content to document immediately and emphasize current customer pain points data with rigorous source verification! diff --git a/src/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md b/src/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md index 21544335b..0f94f535b 100644 --- a/src/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md +++ b/src/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md @@ -200,7 +200,7 @@ _Source: [URL]_ - **CONTENT ALREADY WRITTEN TO DOCUMENT** - Update frontmatter: `stepsCompleted: [1, 2, 3, 4]` -- Load: `./step-05-competitive-analysis.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md` ## APPEND TO DOCUMENT: @@ -254,6 +254,6 @@ Content is already written to document when generated in step 4. No additional a ## NEXT STEP: -After user selects 'C', load `./step-05-competitive-analysis.md` to analyze competitive landscape, market positioning, and competitive strategies for {{research_topic}}. +After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md` to analyze competitive landscape, market positioning, and competitive strategies for {{research_topic}}. Remember: Always write research content to document immediately and emphasize current customer decision data with rigorous source verification! diff --git a/src/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md b/src/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md index 42d7d7d9d..0073b554e 100644 --- a/src/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md +++ b/src/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md @@ -389,13 +389,14 @@ _This comprehensive market research document serves as an authoritative market r #### If 'C' (Complete Research): +- **Replace** the template placeholder `[Research overview and methodology will be appended here]` in the `## Research Overview` section near the top of the document with a concise 2-3 paragraph overview summarizing the research scope, key findings, and a pointer to the full executive summary in the Research Synthesis section - Append the final content to the research document - Update frontmatter: `stepsCompleted: [1, 2, 3, 4]` - Complete the market research workflow ## APPEND TO DOCUMENT: -When user selects 'C', append the content directly to the research document using the structure from step 4. +When user selects 'C', append the content directly to the research document using the structure from step 4. Also replace the `[Research overview and methodology will be appended here]` placeholder in the Research Overview section at the top of the document. ## SUCCESS METRICS: diff --git a/src/bmm/workflows/1-analysis/research/technical-steps/step-01-init.md b/src/bmm/workflows/1-analysis/research/technical-steps/step-01-init.md index b286822dc..1b0980b3f 100644 --- a/src/bmm/workflows/1-analysis/research/technical-steps/step-01-init.md +++ b/src/bmm/workflows/1-analysis/research/technical-steps/step-01-init.md @@ -78,7 +78,7 @@ For **{{research_topic}}**, I will research: - Document scope confirmation in research file - Update frontmatter: `stepsCompleted: [1]` -- Load: `./step-02-technical-overview.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md` ## APPEND TO DOCUMENT: @@ -132,6 +132,6 @@ When user selects 'C', append scope confirmation: ## NEXT STEP: -After user selects 'C', load `./step-02-technical-overview.md` to begin technology stack analysis. +After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md` to begin technology stack analysis. Remember: This is SCOPE CONFIRMATION ONLY - no actual technical research yet, just confirming the research approach and scope! diff --git a/src/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md b/src/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md index 78151eb0d..406a273ca 100644 --- a/src/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md +++ b/src/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md @@ -180,7 +180,7 @@ _Source: [URL]_ - **CONTENT ALREADY WRITTEN TO DOCUMENT** - Update frontmatter: `stepsCompleted: [1, 2]` -- Load: `./step-03-integration-patterns.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md` ## APPEND TO DOCUMENT: @@ -234,6 +234,6 @@ Content is already written to document when generated in step 4. No additional a ## NEXT STEP: -After user selects 'C', load `./step-03-integration-patterns.md` to analyze APIs, communication protocols, and system interoperability for {{research_topic}}. +After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md` to analyze APIs, communication protocols, and system interoperability for {{research_topic}}. Remember: Always write research content to document immediately and emphasize current technology data with rigorous source verification! diff --git a/src/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md b/src/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md index 68e2b70f9..4d4f6243d 100644 --- a/src/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md +++ b/src/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md @@ -189,7 +189,7 @@ _Source: [URL]_ - **CONTENT ALREADY WRITTEN TO DOCUMENT** - Update frontmatter: `stepsCompleted: [1, 2, 3]` -- Load: `./step-04-architectural-patterns.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md` ## APPEND TO DOCUMENT: @@ -243,6 +243,6 @@ Content is already written to document when generated in step 4. No additional a ## NEXT STEP: -After user selects 'C', load `./step-04-architectural-patterns.md` to analyze architectural patterns, design decisions, and system structures for {{research_topic}}. +After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md` to analyze architectural patterns, design decisions, and system structures for {{research_topic}}. Remember: Always write research content to document immediately and emphasize current integration data with rigorous source verification! diff --git a/src/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md b/src/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md index 3d0e66ab3..abb01037a 100644 --- a/src/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md +++ b/src/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md @@ -156,7 +156,7 @@ Show the generated architectural patterns and present continue option: - Append the final content to the research document - Update frontmatter: `stepsCompleted: [1, 2, 3, 4]` -- Load: `./step-05-implementation-research.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md` ## APPEND TO DOCUMENT: @@ -197,6 +197,6 @@ When user selects 'C', append the content directly to the research document usin ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-05-implementation-research.md` to focus on implementation approaches and technology adoption. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md` to focus on implementation approaches and technology adoption. Remember: Always emphasize current architectural data and rigorous source verification! diff --git a/src/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md b/src/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md index 994537356..9e5be7bbb 100644 --- a/src/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md +++ b/src/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md @@ -179,7 +179,7 @@ Show the generated implementation research and present continue option: - Append the final content to the research document - Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5]` -- Load: `./step-06-research-synthesis.md` +- Load: `{project-root}/_bmad/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md` ## APPEND TO DOCUMENT: @@ -230,4 +230,4 @@ When 'C' is selected: ## NEXT STEP: -After user selects 'C', load `./step-06-research-synthesis.md` to produce the comprehensive technical research document with narrative introduction, detailed TOC, and executive summary. +After user selects 'C', load `{project-root}/_bmad/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md` to produce the comprehensive technical research document with narrative introduction, detailed TOC, and executive summary. diff --git a/src/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md b/src/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md index 27331f667..96852cb1b 100644 --- a/src/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md +++ b/src/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md @@ -416,6 +416,7 @@ _This comprehensive technical research document serves as an authoritative techn #### If 'C' (Complete Research): +- **Replace** the template placeholder `[Research overview and methodology will be appended here]` in the `## Research Overview` section near the top of the document with a concise 2-3 paragraph overview summarizing the research scope, key findings, and a pointer to the full executive summary in the Research Synthesis section - Append the complete technical document to the research file - Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5, 6]` - Complete the technical research workflow @@ -423,7 +424,7 @@ _This comprehensive technical research document serves as an authoritative techn ## APPEND TO DOCUMENT: -When user selects 'C', append the complete comprehensive technical research document using the full structure above. +When user selects 'C', append the complete comprehensive technical research document using the full structure above. Also replace the `[Research overview and methodology will be appended here]` placeholder in the Research Overview section at the top of the document. ## SUCCESS METRICS: diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-01b-continue.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-01b-continue.md index 4f9198af6..2ad958b69 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-01b-continue.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-01b-continue.md @@ -79,9 +79,8 @@ Review the frontmatter to understand: **Example:** - If `stepsCompleted = ["step-01-init.md", "step-02-discovery.md", "step-03-success.md"]` - Last element is `"step-03-success.md"` -- Load `step-03-success.md`, read its frontmatter -- Find `nextStepFile: './step-04-journeys.md'` -- Next step to load is `./step-04-journeys.md` +- Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md`, read its frontmatter +- Read fully and follow: `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md` ### 4. Handle Workflow Completion diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md index 4829a4d36..7d337b47d 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md @@ -3,7 +3,7 @@ name: 'step-02-discovery' description: 'Discover project type, domain, and context through collaborative dialogue' # File References -nextStepFile: './step-03-success.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md' outputFile: '{planning_artifacts}/prd.md' # Data Files diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md new file mode 100644 index 000000000..9b7b2a975 --- /dev/null +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md @@ -0,0 +1,154 @@ +--- +name: 'step-02b-vision' +description: 'Discover the product vision and differentiator through collaborative dialogue' + +# File References +nextStepFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md' +outputFile: '{planning_artifacts}/prd.md' + +# Task References +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' +--- + +# Step 2b: Product Vision Discovery + +**Progress: Step 2b of 13** - Next: Executive Summary + +## STEP GOAL: + +Discover what makes this product special and understand the product vision through collaborative conversation. No content generation — facilitation only. + +## MANDATORY EXECUTION RULES (READ FIRST): + +### Universal Rules: + +- 🛑 NEVER generate content without user input +- 📖 CRITICAL: Read the complete step file before taking any action +- 🔄 CRITICAL: When loading next step with 'C', ensure the entire file is read +- ✅ ALWAYS treat this as collaborative discovery between PM peers +- 📋 YOU ARE A FACILITATOR, not a content generator +- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}` + +### Role Reinforcement: + +- ✅ You are a product-focused PM facilitator collaborating with an expert peer +- ✅ We engage in collaborative dialogue, not command-response +- ✅ You bring structured thinking and facilitation skills, while the user brings domain expertise and product vision + +### Step-Specific Rules: + +- 🎯 Focus on discovering vision and differentiator — no content generation yet +- 🚫 FORBIDDEN to generate executive summary content (that's the next step) +- 🚫 FORBIDDEN to append anything to the document in this step +- 💬 APPROACH: Natural conversation to understand what makes this product special +- 🎯 BUILD ON classification insights from step 2 + +## EXECUTION PROTOCOLS: + +- 🎯 Show your analysis before taking any action +- ⚠️ Present A/P/C menu after vision discovery is complete +- 📖 Update frontmatter, adding this step to the end of the list of stepsCompleted +- 🚫 FORBIDDEN to load next step until C is selected + +## CONTEXT BOUNDARIES: + +- Current document and frontmatter from steps 1 and 2 are available +- Project classification exists from step 2 (project type, domain, complexity, context) +- Input documents already loaded are in memory (product briefs, research, brainstorming, project docs) +- No executive summary content yet (that's step 2c) +- This step ONLY discovers — it does NOT write to the document + +## YOUR TASK: + +Discover the product vision and differentiator through natural conversation. Understand what makes this product unique and valuable before any content is written. + +## VISION DISCOVERY SEQUENCE: + +### 1. Acknowledge Classification Context + +Reference the classification from step 2 and use it to frame the vision conversation: + +"We've established this is a {{projectType}} in the {{domain}} domain with {{complexityLevel}} complexity. Now let's explore what makes this product special." + +### 2. Explore What Makes It Special + +Guide the conversation to uncover the product's unique value: + +- **User delight:** "What would make users say 'this is exactly what I needed'?" +- **Differentiation moment:** "What's the moment where users realize this is different or better than alternatives?" +- **Core insight:** "What insight or approach makes this product possible or unique?" +- **Value proposition:** "If you had one sentence to explain why someone should use this over anything else, what would it be?" + +### 3. Understand the Vision + +Dig deeper into the product vision: + +- **Problem framing:** "What's the real problem you're solving — not the surface symptom, but the deeper need?" +- **Future state:** "When this product is successful, what does the world look like for your users?" +- **Why now:** "Why is this the right time to build this?" + +### 4. Validate Understanding + +Reflect back what you've heard and confirm: + +"Here's what I'm hearing about your vision and differentiator: + +**Vision:** {{summarized_vision}} +**What Makes It Special:** {{summarized_differentiator}} +**Core Insight:** {{summarized_insight}} + +Does this capture it? Anything I'm missing?" + +Let the user confirm or refine your understanding. + +### N. Present MENU OPTIONS + +Present your understanding of the product vision for review, then display menu: + +"Based on our conversation, I have a clear picture of your product vision and what makes it special. I'll use these insights to draft the Executive Summary in the next step. + +**What would you like to do?**" + +Display: "**Select:** [A] Advanced Elicitation [P] Party Mode [C] Continue to Executive Summary (Step 2c of 13)" + +#### Menu Handling Logic: +- IF A: Read fully and follow: {advancedElicitationTask} with the current vision insights, process the enhanced insights that come back, ask user if they accept the improvements, if yes update understanding then redisplay menu, if no keep original understanding then redisplay menu +- IF P: Read fully and follow: {partyModeWorkflow} with the current vision insights, process the collaborative insights, ask user if they accept the changes, if yes update understanding then redisplay menu, if no keep original understanding then redisplay menu +- IF C: Update {outputFile} frontmatter by adding this step name to the end of stepsCompleted array, then read fully and follow: {nextStepFile} +- IF Any other: help user respond, then redisplay menu + +#### EXECUTION RULES: +- ALWAYS halt and wait for user input after presenting menu +- ONLY proceed to next step when user selects 'C' +- After other menu items execution, return to this menu + +## CRITICAL STEP COMPLETION NOTE + +ONLY WHEN [C continue option] is selected and [stepsCompleted updated], will you then read fully and follow: `{nextStepFile}` to generate the Executive Summary. + +--- + +## 🚨 SYSTEM SUCCESS/FAILURE METRICS + +### ✅ SUCCESS: + +- Classification context from step 2 acknowledged and built upon +- Natural conversation to understand product vision and differentiator +- User's existing documents (briefs, research, brainstorming) leveraged for vision insights +- Vision and differentiator validated with user before proceeding +- Clear understanding established that will inform Executive Summary generation +- Frontmatter updated with stepsCompleted when C selected + +### ❌ SYSTEM FAILURE: + +- Generating executive summary or any document content (that's step 2c!) +- Appending anything to the PRD document +- Not building on classification from step 2 +- Being prescriptive instead of having natural conversation +- Proceeding without user selecting 'C' + +❌ **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions +❌ **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file + +**Master Rule:** This step is vision discovery only. No content generation, no document writing. Have natural conversations, build on what you know from classification, and establish the vision that will feed into the Executive Summary. diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md new file mode 100644 index 000000000..3f024decd --- /dev/null +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md @@ -0,0 +1,170 @@ +--- +name: 'step-02c-executive-summary' +description: 'Generate and append the Executive Summary section to the PRD document' + +# File References +nextStepFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md' +outputFile: '{planning_artifacts}/prd.md' + +# Task References +advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' +partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md' +--- + +# Step 2c: Executive Summary Generation + +**Progress: Step 2c of 13** - Next: Success Criteria + +## STEP GOAL: + +Generate the Executive Summary content using insights from classification (step 2) and vision discovery (step 2b), then append it to the PRD document. + +## MANDATORY EXECUTION RULES (READ FIRST): + +### Universal Rules: + +- 🛑 NEVER generate content without user input +- 📖 CRITICAL: Read the complete step file before taking any action +- 🔄 CRITICAL: When loading next step with 'C', ensure the entire file is read +- ✅ ALWAYS treat this as collaborative discovery between PM peers +- 📋 YOU ARE A FACILITATOR, not a content generator +- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}` + +### Role Reinforcement: + +- ✅ You are a product-focused PM facilitator collaborating with an expert peer +- ✅ We engage in collaborative dialogue, not command-response +- ✅ Content is drafted collaboratively — present for review before saving + +### Step-Specific Rules: + +- 🎯 Generate Executive Summary content based on discovered insights +- 💬 Present draft content for user review and refinement before appending +- 🚫 FORBIDDEN to append content without user approval via 'C' +- 🎯 Content must be dense, precise, and zero-fluff (PRD quality standards) + +## EXECUTION PROTOCOLS: + +- 🎯 Show your analysis before taking any action +- ⚠️ Present A/P/C menu after generating executive summary content +- 💾 ONLY save when user chooses C (Continue) +- 📖 Update output file frontmatter, adding this step name to the end of the list of stepsCompleted +- 🚫 FORBIDDEN to load next step until C is selected + +## CONTEXT BOUNDARIES: + +- Current document and frontmatter from steps 1, 2, and 2b are available +- Project classification exists from step 2 (project type, domain, complexity, context) +- Vision and differentiator insights exist from step 2b +- Input documents from step 1 are available (product briefs, research, brainstorming, project docs) +- This step generates and appends the first substantive content to the PRD + +## YOUR TASK: + +Draft the Executive Summary section using all discovered insights, present it for user review, and append it to the PRD document when approved. + +## EXECUTIVE SUMMARY GENERATION SEQUENCE: + +### 1. Synthesize Available Context + +Review all available context before drafting: +- Classification from step 2: project type, domain, complexity, project context +- Vision and differentiator from step 2b: what makes this special, core insight +- Input documents: product briefs, research, brainstorming, project docs + +### 2. Draft Executive Summary Content + +Generate the Executive Summary section using the content structure below. Apply PRD quality standards: +- High information density — every sentence carries weight +- Zero fluff — no filler phrases or vague language +- Precise and actionable — clear, specific statements +- Dual-audience optimized — readable by humans, consumable by LLMs + +### 3. Present Draft for Review + +Present the drafted content to the user for review: + +"Here's the Executive Summary I've drafted based on our discovery work. Please review and let me know if you'd like any changes:" + +Show the full drafted content using the structure from the Content Structure section below. + +Allow the user to: +- Request specific changes to any section +- Add missing information +- Refine the language or emphasis +- Approve as-is + +### N. Present MENU OPTIONS + +Present the executive summary content for user review, then display menu: + +"Here's the Executive Summary for your PRD. Review the content above and let me know what you'd like to do." + +Display: "**Select:** [A] Advanced Elicitation [P] Party Mode [C] Continue to Success Criteria (Step 3 of 13)" + +#### Menu Handling Logic: +- IF A: Read fully and follow: {advancedElicitationTask} with the current executive summary content, process the enhanced content that comes back, ask user if they accept the improvements, if yes update content then redisplay menu, if no keep original content then redisplay menu +- IF P: Read fully and follow: {partyModeWorkflow} with the current executive summary content, process the collaborative improvements, ask user if they accept the changes, if yes update content then redisplay menu, if no keep original content then redisplay menu +- IF C: Append the final content to {outputFile}, update frontmatter by adding this step name to the end of the stepsCompleted array, then read fully and follow: {nextStepFile} +- IF Any other: help user respond, then redisplay menu + +#### EXECUTION RULES: +- ALWAYS halt and wait for user input after presenting menu +- ONLY proceed to next step when user selects 'C' +- After other menu items execution, return to this menu + +## APPEND TO DOCUMENT: + +When user selects 'C', append the following content structure directly to the document: + +```markdown +## Executive Summary + +{vision_alignment_content} + +### What Makes This Special + +{product_differentiator_content} + +## Project Classification + +{project_classification_content} +``` + +Where: +- `{vision_alignment_content}` — Product vision, target users, and the problem being solved. Dense, precise summary drawn from step 2b vision discovery. +- `{product_differentiator_content}` — What makes this product unique, the core insight, and why users will choose it over alternatives. Drawn from step 2b differentiator discovery. +- `{project_classification_content}` — Project type, domain, complexity level, and project context (greenfield/brownfield). Drawn from step 2 classification. + +## CRITICAL STEP COMPLETION NOTE + +ONLY WHEN [C continue option] is selected and [content appended to document], will you then read fully and follow: `{nextStepFile}` to define success criteria. + +--- + +## 🚨 SYSTEM SUCCESS/FAILURE METRICS + +### ✅ SUCCESS: + +- Executive Summary drafted using insights from steps 2 and 2b +- Content meets PRD quality standards (dense, precise, zero-fluff) +- Draft presented to user for review before saving +- User given opportunity to refine content +- Content properly appended to document when C selected +- A/P/C menu presented and handled correctly +- Frontmatter updated with stepsCompleted when C selected + +### ❌ SYSTEM FAILURE: + +- Generating content without incorporating discovered vision and classification +- Appending content without user selecting 'C' +- Producing vague, fluffy, or low-density content +- Not presenting draft for user review +- Not presenting A/P/C menu after content generation +- Skipping directly to next step without appending content + +❌ **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions +❌ **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file +❌ **CRITICAL**: Making decisions without complete understanding of step requirements and protocols + +**Master Rule:** Generate high-quality Executive Summary content from discovered insights. Present for review, refine collaboratively, and only save when the user approves. This is the first substantive content in the PRD — it sets the quality bar for everything that follows. diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md index 9a3c5e341..79722289a 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md @@ -3,7 +3,7 @@ name: 'step-03-success' description: 'Define comprehensive success criteria covering user, business, and technical success' # File References -nextStepFile: './step-04-journeys.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md' outputFile: '{planning_artifacts}/prd.md' # Task References @@ -221,6 +221,6 @@ If working in regulated domains (healthcare, fintech, govtech): ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-04-journeys.md` to map user journeys. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md` to map user journeys. Remember: Do NOT proceed to step-04 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md index 314dab564..fc919ff07 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md @@ -3,7 +3,7 @@ name: 'step-04-journeys' description: 'Map ALL user types that interact with the system with narrative story-based journeys' # File References -nextStepFile: './step-05-domain.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md' outputFile: '{planning_artifacts}/prd.md' # Task References @@ -208,6 +208,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-05-domain.md`. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md`. Remember: Do NOT proceed to step-05 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md index 9539527dc..bb95ea16f 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md @@ -3,9 +3,9 @@ name: 'step-05-domain' description: 'Explore domain-specific requirements for complex domains (optional step)' # File References -nextStepFile: './step-06-innovation.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md' outputFile: '{planning_artifacts}/prd.md' -domainComplexityCSV: '../data/domain-complexity.csv' +domainComplexityCSV: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/domain-complexity.csv' # Task References advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md index 440ccf2d2..708eac7b1 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md @@ -3,11 +3,11 @@ name: 'step-06-innovation' description: 'Detect and explore innovative aspects of the product (optional step)' # File References -nextStepFile: './step-07-project-type.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md' outputFile: '{planning_artifacts}/prd.md' # Data Files -projectTypesCSV: '../data/project-types.csv' +projectTypesCSV: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/project-types.csv' # Task References advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md index c078d6db1..63c9070b6 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md @@ -3,7 +3,7 @@ name: 'step-07-project-type' description: 'Conduct project-type specific discovery using CSV-driven guidance' # File References -nextStepFile: './step-08-scoping.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md' outputFile: '{planning_artifacts}/prd.md' # Data Files diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md index da9230adc..e9df0caba 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md @@ -3,7 +3,7 @@ name: 'step-08-scoping' description: 'Define MVP boundaries and prioritize features across development phases' # File References -nextStepFile: './step-09-functional.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md' outputFile: '{planning_artifacts}/prd.md' # Task References diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md index d689ebf37..a39150c0c 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md @@ -3,7 +3,7 @@ name: 'step-09-functional' description: 'Synthesize all discovery into comprehensive functional requirements' # File References -nextStepFile: './step-10-nonfunctional.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md' outputFile: '{planning_artifacts}/prd.md' # Task References diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md index 40919635d..d42323046 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md @@ -3,7 +3,7 @@ name: 'step-10-nonfunctional' description: 'Define quality attributes that matter for this specific product' # File References -nextStepFile: './step-11-polish.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md' outputFile: '{planning_artifacts}/prd.md' # Task References diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md index 70bf198c3..257afbc27 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md @@ -3,9 +3,9 @@ name: 'step-11-polish' description: 'Optimize and polish the complete PRD document for flow, coherence, and readability' # File References -nextStepFile: './step-12-complete.md' +nextStepFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md' outputFile: '{planning_artifacts}/prd.md' -purposeFile: '../data/prd-purpose.md' +purposeFile: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md' # Task References advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml' @@ -212,6 +212,6 @@ When user selects 'C', replace the entire document content with the polished ver ## NEXT STEP: -After user selects 'C' and polished document is saved, load `./step-12-complete.md` to complete the workflow. +After user selects 'C' and polished document is saved, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md` to complete the workflow. Remember: Do NOT proceed to step-12 until user explicitly selects 'C' from the A/P/C menu and polished document is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md index 598d2c2ec..266bf06e4 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md @@ -87,7 +87,7 @@ Offer validation workflows to ensure PRD is ready for implementation: ### 4. Suggest Next Workflows -PRD complete. Read fully and follow: `_bmad/core/tasks/help.md` with argument `Create PRD`. +PRD complete. Read fully and follow: `{project-root}/_bmad/core/tasks/help.md` with argument `Create PRD`. ### 5. Final Completion Confirmation diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md index b79e12fe0..6c591c2dd 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md @@ -70,14 +70,22 @@ This file contains the BMAD PRD philosophy, standards, and validation criteria t **If PRD path provided as invocation parameter:** - Use provided path -**If no PRD path provided:** -"**PRD Validation Workflow** +**If no PRD path provided, auto-discover:** +- Search `{planning_artifacts}` for files matching `*prd*.md` +- Also check for sharded PRDs: `{planning_artifacts}/*prd*/*.md` -Which PRD would you like to validate? +**If exactly ONE PRD found:** +- Use it automatically +- Inform user: "Found PRD: {discovered_path} — using it for validation." -Please provide the path to the PRD file you want to validate." +**If MULTIPLE PRDs found:** +- List all discovered PRDs with numbered options +- "I found multiple PRDs. Which one would you like to validate?" +- Wait for user selection -**Wait for user to provide PRD path.** +**If NO PRDs found:** +- "I couldn't find any PRD files in {planning_artifacts}. Please provide the path to the PRD file you want to validate." +- Wait for user to provide PRD path. ### 3. Validate PRD Exists and Load diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md b/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md index 15e69301a..24e0c7de7 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md @@ -197,7 +197,7 @@ Display: - **IF X (Exit):** - Display: "**Validation Report Saved:** {validationReportPath}" - Display: "**Summary:** {overall status} - {recommendation}" - - PRD Validation complete. Read fully and follow: `_bmad/core/tasks/help.md` with argument `Validate PRD`. + - PRD Validation complete. Read fully and follow: `{project-root}/_bmad/core/tasks/help.md` with argument `Validate PRD`. - **IF Any other:** Help user, then redisplay menu diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md b/src/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md index 67a1aafc8..e21745139 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md @@ -60,6 +60,4 @@ Load and read full config from {main_config} and resolve: "**Validate Mode: Validating an existing PRD against BMAD standards.**" -Prompt for PRD path: "Which PRD would you like to validate? Please provide the path to the PRD.md file." - Then read fully and follow: `{validateWorkflow}` (steps-v/step-v-01-discovery.md) diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01-init.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01-init.md index 62969bafd..02b69c2d0 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01-init.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01-init.md @@ -44,7 +44,7 @@ First, check if the output document already exists: If the document exists and has frontmatter with `stepsCompleted`: -- **STOP here** and load `./step-01b-continue.md` immediately +- **STOP here** and load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md` immediately - Do not proceed with any initialization tasks - Let step-01b handle the continuation logic @@ -110,7 +110,7 @@ Do you have any other documents you'd like me to include, or shall we continue t ## NEXT STEP: -After user selects [C] to continue, ensure the file `{planning_artifacts}/ux-design-specification.md` has been created and saved, and then load `./step-02-discovery.md` to begin the UX discovery phase. +After user selects [C] to continue, ensure the file `{planning_artifacts}/ux-design-specification.md` has been created and saved, and then load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md` to begin the UX discovery phase. Remember: Do NOT proceed to step-02 until output file has been updated and user explicitly selects [C] to continue! diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md index 3d0f647e2..92fded6c3 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md @@ -72,9 +72,9 @@ Does this look right, or do you want to make any adjustments before we proceed?" Based on `lastStep` value, determine which step to load next: -- If `lastStep = 1` → Load `./step-02-discovery.md` -- If `lastStep = 2` → Load `./step-03-core-experience.md` -- If `lastStep = 3` → Load `./step-04-emotional-response.md` +- If `lastStep = 1` → Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md` +- If `lastStep = 2` → Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md` +- If `lastStep = 3` → Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md` - Continue this pattern for all steps - If `lastStep` indicates final step → Workflow already complete diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md index 7ab275a88..41821e326 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md @@ -155,11 +155,11 @@ Show the generated project understanding content and present choices: - Append the final content to `{planning_artifacts}/ux-design-specification.md` - Update frontmatter: `stepsCompleted: [1, 2]` -- Load `./step-03-core-experience.md` +- Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md` ## APPEND TO DOCUMENT: -When user selects 'C', append the content directly to the document. Only after the content is saved to document, read fully and follow: `./step-03-core-experience.md`. +When user selects 'C', append the content directly to the document. Only after the content is saved to document, read fully and follow: `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md`. ## SUCCESS METRICS: diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md index c64c84230..9dc98e70f 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md @@ -179,7 +179,7 @@ Show the generated core experience content and present choices: - Append the final content to `{planning_artifacts}/ux-design-specification.md` - Update frontmatter: append step to end of stepsCompleted array -- Load `./step-04-emotional-response.md` +- Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md` ## APPEND TO DOCUMENT: @@ -211,6 +211,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-04-emotional-response.md` to define desired emotional responses. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md` to define desired emotional responses. Remember: Do NOT proceed to step-04 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md index 247a61e21..f25bf0528 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md @@ -182,7 +182,7 @@ Show the generated emotional response content and present choices: - Append the final content to `{planning_artifacts}/ux-design-specification.md` - Update frontmatter: append step to end of stepsCompleted array -- Load `./step-05-inspiration.md` +- Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md` ## APPEND TO DOCUMENT: @@ -214,6 +214,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-05-inspiration.md` to analyze UX patterns from inspiring products. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md` to analyze UX patterns from inspiring products. Remember: Do NOT proceed to step-05 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md index 87fe56031..890048b74 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md @@ -197,7 +197,7 @@ Show the generated inspiration analysis content and present choices: - Append the final content to `{planning_artifacts}/ux-design-specification.md` - Update frontmatter: append step to end of stepsCompleted array -- Read fully and follow: `./step-06-design-system.md` +- Read fully and follow: `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md` ## APPEND TO DOCUMENT: @@ -229,6 +229,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-06-design-system.md` to choose the appropriate design system approach. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md` to choose the appropriate design system approach. Remember: Do NOT proceed to step-06 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md index 70d566ada..26caf73db 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md @@ -215,7 +215,7 @@ Show the generated design system content and present choices: - Append the final content to `{planning_artifacts}/ux-design-specification.md` - Update frontmatter: append step to end of stepsCompleted array -- Load `./step-07-defining-experience.md` +- Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md` ## APPEND TO DOCUMENT: @@ -247,6 +247,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-07-defining-experience.md` to define the core user interaction. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md` to define the core user interaction. Remember: Do NOT proceed to step-07 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md index 7e904b948..8cd5ff3b8 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md @@ -217,7 +217,7 @@ Show the generated defining experience content and present choices: - Append the final content to `{planning_artifacts}/ux-design-specification.md` - Update frontmatter: append step to end of stepsCompleted array -- Load `./step-08-visual-foundation.md` +- Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md` ## APPEND TO DOCUMENT: @@ -249,6 +249,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-08-visual-foundation.md` to establish visual design foundation. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md` to establish visual design foundation. Remember: Do NOT proceed to step-08 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md index bd764a60e..430aab043 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md @@ -187,7 +187,7 @@ Show the generated visual foundation content and present choices: - Append the final content to `{planning_artifacts}/ux-design-specification.md` - Update frontmatter: append step to end of stepsCompleted array -- Load `./step-09-design-directions.md` +- Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md` ## APPEND TO DOCUMENT: @@ -219,6 +219,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-09-design-directions.md` to generate design direction mockups. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md` to generate design direction mockups. Remember: Do NOT proceed to step-09 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md index a50ed503e..09864e0b4 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md @@ -187,7 +187,7 @@ Show the generated design direction content and present choices: - Append the final content to `{planning_artifacts}/ux-design-specification.md` - Update frontmatter: append step to end of stepsCompleted array -- Load `./step-10-user-journeys.md` +- Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md` ## APPEND TO DOCUMENT: @@ -219,6 +219,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-10-user-journeys.md` to design user journey flows. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md` to design user journey flows. Remember: Do NOT proceed to step-10 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md index 985577f00..9f05201fe 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md @@ -205,7 +205,7 @@ Show the generated user journey content and present choices: - Append the final content to `{planning_artifacts}/ux-design-specification.md` - Update frontmatter: append step to end of stepsCompleted array -- Load `./step-11-component-strategy.md` +- Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md` ## APPEND TO DOCUMENT: @@ -236,6 +236,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-11-component-strategy.md` to define component library strategy. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md` to define component library strategy. Remember: Do NOT proceed to step-11 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md index deef19b73..95f2f294a 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md @@ -211,7 +211,7 @@ Show the generated component strategy content and present choices: - Append the final content to `{planning_artifacts}/ux-design-specification.md` - Update frontmatter: append step to end of stepsCompleted array -- Load `./step-12-ux-patterns.md` +- Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md` ## APPEND TO DOCUMENT: @@ -243,6 +243,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-12-ux-patterns.md` to define UX consistency patterns. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md` to define UX consistency patterns. Remember: Do NOT proceed to step-12 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md index 4708b52aa..08f272a62 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md @@ -200,7 +200,7 @@ Show the generated UX patterns content and present choices: - Append the final content to `{planning_artifacts}/ux-design-specification.md` - Update frontmatter: append step to end of stepsCompleted array -- Load `./step-13-responsive-accessibility.md` +- Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md` ## APPEND TO DOCUMENT: @@ -232,6 +232,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-13-responsive-accessibility.md` to define responsive design and accessibility strategy. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md` to define responsive design and accessibility strategy. Remember: Do NOT proceed to step-13 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md index 80b81d4c8..d13ffa5c4 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md @@ -227,7 +227,7 @@ Show the generated responsive and accessibility content and present choices: - Append the final content to `{planning_artifacts}/ux-design-specification.md` - Update frontmatter: append step to end of stepsCompleted array -- Load `./step-14-complete.md` +- Load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md` ## APPEND TO DOCUMENT: @@ -259,6 +259,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-14-complete.md` to finalize the UX design workflow. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md` to finalize the UX design workflow. Remember: Do NOT proceed to step-14 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md index db25fb9b7..ff2268248 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md @@ -82,7 +82,7 @@ Update the main workflow status file: ### 3. Suggest Next Steps -UX Design complete. Read fully and follow: `_bmad/core/tasks/help.md` with argument `Create UX`. +UX Design complete. Read fully and follow: `{project-root}/_bmad/core/tasks/help.md` with argument `Create UX`. ### 5. Final Completion Confirmation diff --git a/src/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md b/src/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md index 4af87c39a..baa0fe488 100644 --- a/src/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md +++ b/src/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md @@ -39,4 +39,4 @@ Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: ## EXECUTION - ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}` -- Read fully and follow: `steps/step-01-init.md` to begin the UX design workflow. +- Read fully and follow: `{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01-init.md` to begin the UX design workflow. diff --git a/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md b/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md index d0e15bc02..199b48a21 100644 --- a/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +++ b/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md @@ -109,7 +109,7 @@ The assessment found [number] issues requiring attention. Review the detailed re The implementation readiness workflow is now complete. The report contains all findings and recommendations for the user to consider. -Implementation Readiness complete. Read fully and follow: `_bmad/core/tasks/help.md` with argument `implementation readiness`. +Implementation Readiness complete. Read fully and follow: `{project-root}/_bmad/core/tasks/help.md` with argument `implementation readiness`. --- diff --git a/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md b/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md index 49d2afab9..0c20e032a 100644 --- a/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md +++ b/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md @@ -51,4 +51,4 @@ Load and read full config from {project-root}/_bmad/bmm/config.yaml and resolve: ### 2. First Step EXECUTION -Read fully and follow: `./step-01-document-discovery.md` to begin the workflow. +Read fully and follow: `./steps/step-01-document-discovery.md` to begin the workflow. diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01-init.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01-init.md index 93a83c706..6d70d1492 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01-init.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01-init.md @@ -44,7 +44,7 @@ First, check if the output document already exists: If the document exists and has frontmatter with `stepsCompleted`: -- **STOP here** and load `./step-01b-continue.md` immediately +- **STOP here** and load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-01b-continue.md` immediately - Do not proceed with any initialization tasks - Let step-01b handle the continuation logic @@ -148,6 +148,6 @@ Ready to begin architectural decision making. Do you have any other documents yo ## NEXT STEP: -After user selects [C] to continue, only after ensuring all the template output has been created, then load `./step-02-context.md` to analyze the project context and begin architectural decision making. +After user selects [C] to continue, only after ensuring all the template output has been created, then load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-02-context.md` to analyze the project context and begin architectural decision making. Remember: Do NOT proceed to step-02 until user explicitly selects [C] from the menu and setup is confirmed! diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md index 6e800e7f0..0d2f6ee9a 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md @@ -85,7 +85,7 @@ Show the user their current progress: - Identify the next step based on `stepsCompleted` - Load the appropriate step file to continue -- Example: If `stepsCompleted: [1, 2, 3]`, load `step-04-decisions.md` +- Example: If `stepsCompleted: [1, 2, 3]`, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-04-decisions.md` #### If 'C' (Continue to next logical step): @@ -103,7 +103,7 @@ Show the user their current progress: #### If 'X' (Start over): - Confirm: "This will delete all existing architectural decisions. Are you sure? (y/n)" -- If confirmed: Delete existing document and return to step-01-init.md +- If confirmed: Delete existing document and read fully and follow: `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-01-init.md` - If not confirmed: Return to continuation menu ### 4. Navigate to Selected Step @@ -161,4 +161,13 @@ After user makes choice: After user selects their continuation option, load the appropriate step file based on their choice. The step file will handle the detailed work from that point forward. +Valid step files to load: +- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-02-context.md` +- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-03-starter.md` +- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-04-decisions.md` +- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-05-patterns.md` +- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-06-structure.md` +- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-07-validation.md` +- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-08-complete.md` + Remember: The goal is smooth, transparent resumption that respects the work already done while giving the user control over how to proceed. diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md index 1e9c6b9a3..41e512c7e 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md @@ -188,7 +188,7 @@ Show the generated content and present choices: - Append the final content to `{planning_artifacts}/architecture.md` - Update frontmatter: `stepsCompleted: [1, 2]` -- Load `./step-03-starter.md` +- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-03-starter.md` ## APPEND TO DOCUMENT: @@ -219,6 +219,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-03-starter.md` to evaluate starter template options. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-03-starter.md` to evaluate starter template options. Remember: Do NOT proceed to step-03 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md index bccea19df..59b3a0b06 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md @@ -232,7 +232,6 @@ Prepare the content to append to the document: ```bash {{full_starter_command_with_options}} ``` -```` **Architectural Decisions Provided by Starter:** @@ -256,7 +255,7 @@ Prepare the content to append to the document: **Note:** Project initialization using this command should be the first implementation story. -``` +```` ### 9. Present Content and Menu @@ -295,7 +294,7 @@ Show the generated content and present choices: - Append the final content to `{planning_artifacts}/architecture.md` - Update frontmatter: `stepsCompleted: [1, 2, 3]` -- Load `./step-04-decisions.md` +- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-04-decisions.md` ## APPEND TO DOCUMENT: @@ -325,7 +324,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-04-decisions.md` to begin making specific architectural decisions. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-04-decisions.md` to begin making specific architectural decisions. Remember: Do NOT proceed to step-04 until user explicitly selects 'C' from the A/P/C menu and content is saved! -``` diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md index c9f5cdedd..1077e1da1 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md @@ -282,7 +282,7 @@ Show the generated decisions content and present choices: - Append the final content to `{planning_artifacts}/architecture.md` - Update frontmatter: `stepsCompleted: [1, 2, 3, 4]` -- Load `./step-05-patterns.md` +- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-05-patterns.md` ## APPEND TO DOCUMENT: @@ -313,6 +313,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-05-patterns.md` to define implementation patterns that ensure consistency across AI agents. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-05-patterns.md` to define implementation patterns that ensure consistency across AI agents. Remember: Do NOT proceed to step-05 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md index cbfd99d1d..f14024217 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md @@ -323,7 +323,7 @@ Show the generated patterns content and present choices: - Append the final content to `{planning_artifacts}/architecture.md` - Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5]` -- Load `./step-06-structure.md` +- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-06-structure.md` ## APPEND TO DOCUMENT: @@ -354,6 +354,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-06-structure.md` to define the complete project structure. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-06-structure.md` to define the complete project structure. Remember: Do NOT proceed to step-06 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md index 3df89e6ce..c06072b4c 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md @@ -343,7 +343,7 @@ Show the generated project structure content and present choices: - Append the final content to `{planning_artifacts}/architecture.md` - Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5, 6]` -- Load `./step-07-validation.md` +- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-07-validation.md` ## APPEND TO DOCUMENT: @@ -374,6 +374,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-07-validation.md` to validate architectural coherence and completeness. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-07-validation.md` to validate architectural coherence and completeness. Remember: Do NOT proceed to step-07 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md index b2dc2c462..7a787b6a8 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md @@ -323,7 +323,7 @@ Show the validation results and present choices: - Append the final content to `{planning_artifacts}/architecture.md` - Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5, 6, 7]` -- Load `./step-08-complete.md` +- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-08-complete.md` ## APPEND TO DOCUMENT: @@ -354,6 +354,6 @@ When user selects 'C', append the content directly to the document using the str ## NEXT STEP: -After user selects 'C' and content is saved to document, load `./step-08-complete.md` to complete the workflow and provide implementation guidance. +After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-08-complete.md` to complete the workflow and provide implementation guidance. Remember: Do NOT proceed to step-08 until user explicitly selects 'C' from the A/P/C menu and content is saved! diff --git a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md index 2f949bf7e..791c17778 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md @@ -41,7 +41,7 @@ completedAt: '{{current_date}}' ### 3. Next Steps Guidance -Architecture complete. Read fully and follow: `_bmad/core/tasks/help.md` with argument `Create Architecture`. +Architecture complete. Read fully and follow: `{project-root}/_bmad/core/tasks/help.md` with argument `Create Architecture`. Upon Completion of task output: offer to answer any questions about the Architecture Document. diff --git a/src/bmm/workflows/3-solutioning/create-architecture/workflow.md b/src/bmm/workflows/3-solutioning/create-architecture/workflow.md index b75b4a46c..545011e10 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/workflow.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/workflow.md @@ -36,7 +36,7 @@ Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: ### Paths -- `installed_path` = `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture` +- `installed_path` = `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture` - `template_path` = `{installed_path}/architecture-decision-template.md` - `data_files_path` = `{installed_path}/data/` @@ -44,6 +44,6 @@ Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: ## EXECUTION -Read fully and follow: `steps/step-01-init.md` to begin the workflow. +Read fully and follow: `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-01-init.md` to begin the workflow. **Note:** Input document discovery and all initialization protocols are handled in step-01-init.md. diff --git a/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md b/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md index 05e8d5d4e..dc504182d 100644 --- a/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +++ b/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md @@ -144,6 +144,6 @@ If all validations pass: When C is selected, the workflow is complete and the epics.md is ready for development. -Epics and Stories complete. Read fully and follow: `_bmad/core/tasks/help.md` with argument `Create Epics and Stories`. +Epics and Stories complete. Read fully and follow: `{project-root}/_bmad/core/tasks/help.md` with argument `Create Epics and Stories`. Upon Completion of task output: offer to answer any questions about the Epics and Stories. diff --git a/src/bmm/workflows/4-implementation/code-review/workflow.yaml b/src/bmm/workflows/4-implementation/code-review/workflow.yaml index 5b5f6b2fc..c6edf8464 100644 --- a/src/bmm/workflows/4-implementation/code-review/workflow.yaml +++ b/src/bmm/workflows/4-implementation/code-review/workflow.yaml @@ -12,7 +12,6 @@ document_output_language: "{config_source}:document_output_language" date: system-generated planning_artifacts: "{config_source}:planning_artifacts" implementation_artifacts: "{config_source}:implementation_artifacts" -output_folder: "{implementation_artifacts}" sprint_status: "{implementation_artifacts}/sprint-status.yaml" # Workflow components @@ -21,10 +20,7 @@ instructions: "{installed_path}/instructions.xml" validation: "{installed_path}/checklist.md" template: false -variables: - # Project context - project_context: "**/project-context.md" - story_dir: "{implementation_artifacts}" +project_context: "**/project-context.md" # Smart input file references - handles both whole docs and sharded docs # Priority: Whole document first, then sharded version diff --git a/src/bmm/workflows/4-implementation/correct-course/instructions.md b/src/bmm/workflows/4-implementation/correct-course/instructions.md index 430239a68..bbe2c21e0 100644 --- a/src/bmm/workflows/4-implementation/correct-course/instructions.md +++ b/src/bmm/workflows/4-implementation/correct-course/instructions.md @@ -10,6 +10,7 @@ + Load {project_context} for coding standards and project-wide patterns (if exists) Confirm change trigger and gather user description of the issue Ask: "What specific issue or change has been identified that requires navigation?" Verify access to required project documents: diff --git a/src/bmm/workflows/4-implementation/correct-course/workflow.yaml b/src/bmm/workflows/4-implementation/correct-course/workflow.yaml index 318b5a7dc..6eb4b7f03 100644 --- a/src/bmm/workflows/4-implementation/correct-course/workflow.yaml +++ b/src/bmm/workflows/4-implementation/correct-course/workflow.yaml @@ -12,8 +12,7 @@ date: system-generated implementation_artifacts: "{config_source}:implementation_artifacts" planning_artifacts: "{config_source}:planning_artifacts" project_knowledge: "{config_source}:project_knowledge" -output_folder: "{implementation_artifacts}" -sprint_status: "{implementation_artifacts}/sprint-status.yaml" +project_context: "**/project-context.md" # Smart input file references - handles both whole docs and sharded docs # Priority: Whole document first, then sharded version @@ -51,6 +50,5 @@ input_file_patterns: installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/correct-course" template: false instructions: "{installed_path}/instructions.md" -validation: "{installed_path}/checklist.md" checklist: "{installed_path}/checklist.md" default_output_file: "{planning_artifacts}/sprint-change-proposal-{date}.md" diff --git a/src/bmm/workflows/4-implementation/create-story/checklist.md b/src/bmm/workflows/4-implementation/create-story/checklist.md index 55e6c397e..d9ed06375 100644 --- a/src/bmm/workflows/4-implementation/create-story/checklist.md +++ b/src/bmm/workflows/4-implementation/create-story/checklist.md @@ -33,7 +33,7 @@ This is a COMPETITION to create the **ULTIMATE story context** that makes LLM de ### **When Running from Create-Story Workflow:** -- The `{project-root}/_bmad/core/tasks/validate-workflow.xml` framework will automatically: +- The `{project-root}/_bmad/core/tasks/workflow.xml` framework will automatically: - Load this checklist file - Load the newly created story file (`{story_file_path}`) - Load workflow variables from `{installed_path}/workflow.yaml` @@ -49,7 +49,7 @@ This is a COMPETITION to create the **ULTIMATE story context** that makes LLM de ### **Required Inputs:** - **Story file**: The story file to review and improve -- **Workflow variables**: From workflow.yaml (story_dir, output_folder, epics_file, etc.) +- **Workflow variables**: From workflow.yaml (implementation_artifacts, epics_file, etc.) - **Source documents**: Epics, architecture, etc. (discovered or provided) - **Validation framework**: `validate-workflow.xml` (handles checklist execution) @@ -63,9 +63,9 @@ You will systematically re-do the entire story creation process, but with a crit 1. **Load the workflow configuration**: `{installed_path}/workflow.yaml` for variable inclusion 2. **Load the story file**: `{story_file_path}` (provided by user or discovered) -3. **Load validation framework**: `{project-root}/_bmad/core/tasks/validate-workflow.xml` +3. **Load validation framework**: `{project-root}/_bmad/core/tasks/workflow.xml` 4. **Extract metadata**: epic_num, story_num, story_key, story_title from story file -5. **Resolve all workflow variables**: story_dir, output_folder, epics_file, architecture_file, etc. +5. **Resolve all workflow variables**: implementation_artifacts, epics_file, architecture_file, etc. 6. **Understand current status**: What story implementation guidance is currently provided? **Note:** If running in fresh context, user should provide the story file path being reviewed. If running from create-story workflow, the validation framework will automatically discover the checklist and story file. diff --git a/src/bmm/workflows/4-implementation/create-story/instructions.xml b/src/bmm/workflows/4-implementation/create-story/instructions.xml index 81eb82269..f9433371f 100644 --- a/src/bmm/workflows/4-implementation/create-story/instructions.xml +++ b/src/bmm/workflows/4-implementation/create-story/instructions.xml @@ -192,7 +192,8 @@ (As a, I want, so that) - Detailed acceptance criteria (already BDD formatted) - Technical requirements specific to this story - Business context and value - Success criteria - Load previous story file: {{story_dir}}/{{epic_num}}-{{previous_story_num}}-*.md **PREVIOUS STORY INTELLIGENCE:** - + Find {{previous_story_num}}: scan {implementation_artifacts} for the story file in epic {{epic_num}} with the highest story number less than {{story_num}} + Load previous story file: {implementation_artifacts}/{{epic_num}}-{{previous_story_num}}-*.md **PREVIOUS STORY INTELLIGENCE:** - Dev notes and learnings from previous story - Review feedback and corrections needed - Files that were created/modified and their patterns - Testing approaches that worked/didn't work - Problems encountered and solutions found - Code patterns established Extract all learnings that could impact current story implementation diff --git a/src/bmm/workflows/4-implementation/create-story/workflow.yaml b/src/bmm/workflows/4-implementation/create-story/workflow.yaml index 1f3ac9784..991f78c2e 100644 --- a/src/bmm/workflows/4-implementation/create-story/workflow.yaml +++ b/src/bmm/workflows/4-implementation/create-story/workflow.yaml @@ -6,11 +6,11 @@ author: "BMad" config_source: "{project-root}/_bmad/bmm/config.yaml" user_name: "{config_source}:user_name" communication_language: "{config_source}:communication_language" +document_output_language: "{config_source}:document_output_language" +user_skill_level: "{config_source}:user_skill_level" date: system-generated planning_artifacts: "{config_source}:planning_artifacts" implementation_artifacts: "{config_source}:implementation_artifacts" -output_folder: "{implementation_artifacts}" -story_dir: "{implementation_artifacts}" # Workflow components installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/create-story" @@ -19,18 +19,14 @@ instructions: "{installed_path}/instructions.xml" validation: "{installed_path}/checklist.md" # Variables and inputs -variables: - sprint_status: "{implementation_artifacts}/sprint-status.yaml" # Primary source for story tracking - epics_file: "{planning_artifacts}/epics.md" # Enhanced epics+stories with BDD and source hints - prd_file: "{planning_artifacts}/prd.md" # Fallback for requirements (if not in epics file) - architecture_file: "{planning_artifacts}/architecture.md" # Fallback for constraints (if not in epics file) - ux_file: "{planning_artifacts}/*ux*.md" # Fallback for UX requirements (if not in epics file) - story_title: "" # Will be elicited if not derivable - -# Project context +sprint_status: "{implementation_artifacts}/sprint-status.yaml" # Primary source for story tracking +epics_file: "{planning_artifacts}/epics.md" # Enhanced epics+stories with BDD and source hints +prd_file: "{planning_artifacts}/prd.md" # Fallback for requirements (if not in epics file) +architecture_file: "{planning_artifacts}/architecture.md" # Fallback for constraints (if not in epics file) +ux_file: "{planning_artifacts}/*ux*.md" # Fallback for UX requirements (if not in epics file) +story_title: "" # Will be elicited if not derivable project_context: "**/project-context.md" - -default_output_file: "{story_dir}/{{story_key}}.md" +default_output_file: "{implementation_artifacts}/{{story_key}}.md" # Smart input file references - Simplified for enhanced approach # The epics+stories file should contain everything needed with source hints diff --git a/src/bmm/workflows/4-implementation/dev-story/instructions.xml b/src/bmm/workflows/4-implementation/dev-story/instructions.xml index 6150944f1..3c4989f39 100644 --- a/src/bmm/workflows/4-implementation/dev-story/instructions.xml +++ b/src/bmm/workflows/4-implementation/dev-story/instructions.xml @@ -78,7 +78,7 @@ - Search {story_dir} for stories directly + Search {implementation_artifacts} for stories directly Find stories with "ready-for-dev" status in files Look for story files matching pattern: *-*-*.md Read each candidate story file to check Status section @@ -114,7 +114,7 @@ Store the found story_key (e.g., "1-2-user-authentication") for later status updates - Find matching story file in {story_dir} using story_key pattern: {{story_key}}.md + Find matching story file in {implementation_artifacts} using story_key pattern: {{story_key}}.md Read COMPLETE story file from discovered path diff --git a/src/bmm/workflows/4-implementation/dev-story/workflow.yaml b/src/bmm/workflows/4-implementation/dev-story/workflow.yaml index daf152b71..c8a85a079 100644 --- a/src/bmm/workflows/4-implementation/dev-story/workflow.yaml +++ b/src/bmm/workflows/4-implementation/dev-story/workflow.yaml @@ -4,12 +4,10 @@ author: "BMad" # Critical variables from config config_source: "{project-root}/_bmad/bmm/config.yaml" -output_folder: "{config_source}:output_folder" 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" -story_dir: "{config_source}:implementation_artifacts" date: system-generated # Workflow components diff --git a/src/bmm/workflows/4-implementation/retrospective/instructions.md b/src/bmm/workflows/4-implementation/retrospective/instructions.md index 017503129..018ef6ee3 100644 --- a/src/bmm/workflows/4-implementation/retrospective/instructions.md +++ b/src/bmm/workflows/4-implementation/retrospective/instructions.md @@ -31,6 +31,7 @@ PARTY MODE PROTOCOL: +Load {project_context} for project-wide patterns and conventions (if exists) Explain to {user_name} the epic discovery process using natural dialogue @@ -80,7 +81,7 @@ Bob (Scrum Master): "I'm having trouble detecting the completed epic from {sprin PRIORITY 3: Fallback to stories folder -Scan {story_directory} for highest numbered story files +Scan {implementation_artifacts} for highest numbered story files Extract epic numbers from story filenames (pattern: epic-X-Y-story-name.md) Set {{detected_epic}} = highest epic number found @@ -170,7 +171,7 @@ Bob (Scrum Master): "Before we start the team discussion, let me review all the Charlie (Senior Dev): "Good idea - those dev notes always have gold in them." -For each story in epic {{epic_number}}, read the complete story file from {story_directory}/{{epic_number}}-{{story_num}}-\*.md +For each story in epic {{epic_number}}, read the complete story file from {implementation_artifacts}/{{epic_number}}-{{story_num}}-*.md Extract and analyze from each story: @@ -261,14 +262,14 @@ Bob (Scrum Master): "We'll get to all of it. But first, let me load the previous Calculate previous epic number: {{prev_epic_num}} = {{epic_number}} - 1 - Search for previous retrospective using pattern: {retrospectives_folder}/epic-{{prev_epic_num}}-retro-*.md + Search for previous retrospectives using pattern: {implementation_artifacts}/epic-{{prev_epic_num}}-retro-*.md - + -Bob (Scrum Master): "I found our retrospective from Epic {{prev_epic_num}}. Let me see what we committed to back then..." +Bob (Scrum Master): "I found our retrospectives from Epic {{prev_epic_num}}. Let me see what we committed to back then..." - Read the complete previous retrospective file + Read the previous retrospectives Extract key elements: - **Action items committed**: What did the team agree to improve? @@ -365,7 +366,7 @@ Alice (Product Owner): "Good thinking - helps us connect what we learned to what Attempt to load next epic using selective loading strategy: **Try sharded first (more specific):** -Check if file exists: {planning_artifacts}/epic\*/epic-{{next_epic_num}}.md +Check if file exists: {planning_artifacts}/epic*/epic-{{next_epic_num}}.md Load {planning_artifacts}/*epic*/epic-{{next_epic_num}}.md @@ -374,7 +375,7 @@ Alice (Product Owner): "Good thinking - helps us connect what we learned to what **Fallback to whole document:** -Check if file exists: {planning_artifacts}/epic\*.md +Check if file exists: {planning_artifacts}/epic*.md Load entire epics document @@ -1302,7 +1303,7 @@ Bob (Scrum Master): "See you all when prep work is done. Meeting adjourned!" -Ensure retrospectives folder exists: {retrospectives_folder} +Ensure retrospectives folder exists: {implementation_artifacts} Create folder if it doesn't exist Generate comprehensive retrospective summary document including: @@ -1322,11 +1323,11 @@ Bob (Scrum Master): "See you all when prep work is done. Meeting adjourned!" - Commitments and next steps Format retrospective document as readable markdown with clear sections -Set filename: {retrospectives_folder}/epic-{{epic_number}}-retro-{date}.md +Set filename: {implementation_artifacts}/epic-{{epic_number}}-retro-{date}.md Save retrospective document -✅ Retrospective document saved: {retrospectives_folder}/epic-{{epic_number}}-retro-{date}.md +✅ Retrospective document saved: {implementation_artifacts}/epic-{{epic_number}}-retro-{date}.md Update {sprint_status_file} to mark retrospective as completed @@ -1365,7 +1366,7 @@ Retrospective document was saved successfully, but {sprint_status_file} may need - Epic {{epic_number}}: {{epic_title}} reviewed - Retrospective Status: completed -- Retrospective saved: {retrospectives_folder}/epic-{{epic_number}}-retro-{date}.md +- Retrospective saved: {implementation_artifacts}/epic-{{epic_number}}-retro-{date}.md **Commitments Made:** @@ -1375,7 +1376,7 @@ Retrospective document was saved successfully, but {sprint_status_file} may need **Next Steps:** -1. **Review retrospective summary**: {retrospectives_folder}/epic-{{epic_number}}-retro-{date}.md +1. **Review retrospective summary**: {implementation_artifacts}/epic-{{epic_number}}-retro-{date}.md 2. **Execute preparation sprint** (Est: {{prep_days}} days) - Complete {{critical_count}} critical path items diff --git a/src/bmm/workflows/4-implementation/retrospective/workflow.yaml b/src/bmm/workflows/4-implementation/retrospective/workflow.yaml index b92ecaf1b..773c7f2d6 100644 --- a/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +++ b/src/bmm/workflows/4-implementation/retrospective/workflow.yaml @@ -4,7 +4,6 @@ description: "Run after epic completion to review overall success, extract lesso author: "BMad" config_source: "{project-root}/_bmad/bmm/config.yaml" -output_folder: "{config_source}:implementation_artifacts}" user_name: "{config_source}:user_name" communication_language: "{config_source}:communication_language" user_skill_level: "{config_source}:user_skill_level" @@ -12,6 +11,7 @@ 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 @@ -51,5 +51,3 @@ input_file_patterns: # Required files sprint_status_file: "{implementation_artifacts}/sprint-status.yaml" -story_directory: "{implementation_artifacts}" -retrospectives_folder: "{implementation_artifacts}" diff --git a/src/bmm/workflows/4-implementation/sprint-planning/instructions.md b/src/bmm/workflows/4-implementation/sprint-planning/instructions.md index c4f4bd420..316d2fec3 100644 --- a/src/bmm/workflows/4-implementation/sprint-planning/instructions.md +++ b/src/bmm/workflows/4-implementation/sprint-planning/instructions.md @@ -23,6 +23,7 @@ +Load {project_context} for project-wide patterns and conventions (if exists) Communicate in {communication_language} with {user_name} Look for all files matching `{epics_pattern}` in {epics_location} Could be a single `epics.md` file or multiple `epic-1.md`, `epic-2.md` files diff --git a/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml b/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml index 7b157633c..6c5d22d64 100644 --- a/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +++ b/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml @@ -9,7 +9,6 @@ communication_language: "{config_source}:communication_language" date: system-generated implementation_artifacts: "{config_source}:implementation_artifacts" planning_artifacts: "{config_source}:planning_artifacts" -output_folder: "{implementation_artifacts}" # Workflow components installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/sprint-planning" @@ -18,24 +17,21 @@ template: "{installed_path}/sprint-status-template.yaml" validation: "{installed_path}/checklist.md" # Variables and inputs -variables: - # Project context - project_context: "**/project-context.md" - # Project identification - project_name: "{config_source}:project_name" +project_context: "**/project-context.md" +project_name: "{config_source}:project_name" - # Tracking system configuration - tracking_system: "file-system" # Options: file-system, Future will support other options from config of mcp such as jira, linear, trello - project_key: "NOKEY" # Placeholder for tracker integrations; file-system uses a no-op key - story_location: "{config_source}:implementation_artifacts" # Relative path for file-system, Future will support URL for Jira/Linear/Trello - story_location_absolute: "{config_source}:implementation_artifacts" # Absolute path for file operations +# Tracking system configuration +tracking_system: "file-system" # Options: file-system, Future will support other options from config of mcp such as jira, linear, trello +project_key: "NOKEY" # Placeholder for tracker integrations; file-system uses a no-op key +story_location: "{implementation_artifacts}" # Relative path for file-system, Future will support URL for Jira/Linear/Trello +story_location_absolute: "{implementation_artifacts}" # Absolute path for file operations - # Source files (file-system only) - epics_location: "{planning_artifacts}" # Directory containing epic*.md files - epics_pattern: "epic*.md" # Pattern to find epic files +# Source files (file-system only) +epics_location: "{planning_artifacts}" # Directory containing epic*.md files +epics_pattern: "epic*.md" # Pattern to find epic files - # Output configuration - status_file: "{implementation_artifacts}/sprint-status.yaml" +# Output configuration +status_file: "{implementation_artifacts}/sprint-status.yaml" # Smart input file references - handles both whole docs and sharded docs # Priority: Whole document first, then sharded version @@ -43,8 +39,8 @@ variables: input_file_patterns: epics: description: "All epics with user stories" - whole: "{output_folder}/*epic*.md" - sharded: "{output_folder}/*epic*/*.md" + whole: "{planning_artifacts}/*epic*.md" + sharded: "{planning_artifacts}/*epic*/*.md" load_strategy: "FULL_LOAD" # Output configuration diff --git a/src/bmm/workflows/4-implementation/sprint-status/instructions.md b/src/bmm/workflows/4-implementation/sprint-status/instructions.md index c058644a4..4182e1f25 100644 --- a/src/bmm/workflows/4-implementation/sprint-status/instructions.md +++ b/src/bmm/workflows/4-implementation/sprint-status/instructions.md @@ -24,6 +24,7 @@ + Load {project_context} for project-wide patterns and conventions (if exists) Try {sprint_status_file} ❌ sprint-status.yaml not found. diff --git a/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml b/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml index 8946f0291..f27d57024 100644 --- a/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml +++ b/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml @@ -5,22 +5,17 @@ author: "BMad" # Critical variables from config config_source: "{project-root}/_bmad/bmm/config.yaml" -output_folder: "{config_source}:output_folder" user_name: "{config_source}:user_name" communication_language: "{config_source}:communication_language" document_output_language: "{config_source}:document_output_language" -date: system-generated implementation_artifacts: "{config_source}:implementation_artifacts" -planning_artifacts: "{config_source}:planning_artifacts" # Workflow components installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/sprint-status" instructions: "{installed_path}/instructions.md" # Inputs -variables: - sprint_status_file: "{implementation_artifacts}/sprint-status.yaml" - tracking_system: "file-system" +sprint_status_file: "{implementation_artifacts}/sprint-status.yaml" # Smart input file references input_file_patterns: diff --git a/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md b/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md index eb3458891..2391f9722 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md @@ -50,7 +50,7 @@ Analyze the user's input to determine mode: - Load the spec, extract tasks/context/AC - Set `{execution_mode}` = "tech-spec" - Set `{tech_spec_path}` = provided path -- **NEXT:** Read fully and follow: `step-03-execute.md` +- **NEXT:** Read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md` **Mode B: Direct Instructions** @@ -91,7 +91,7 @@ Display: "**Select:** [P] Plan first (tech-spec) [E] Execute directly" #### Menu Handling Logic: - IF P: Direct user to `{quick_spec_workflow}`. **EXIT Quick Dev.** -- IF E: Ask for any additional guidance, then **NEXT:** Read fully and follow: `step-02-context-gathering.md` +- IF E: Ask for any additional guidance, then **NEXT:** Read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md` #### EXECUTION RULES: @@ -114,7 +114,7 @@ Display: - IF P: Direct to `{quick_spec_workflow}`. **EXIT Quick Dev.** - IF W: Direct user to run the PRD workflow instead. **EXIT Quick Dev.** -- IF E: Ask for guidance, then **NEXT:** Read fully and follow: `step-02-context-gathering.md` +- IF E: Ask for guidance, then **NEXT:** Read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md` #### EXECUTION RULES: @@ -137,7 +137,7 @@ Display: - IF P: Direct to `{quick_spec_workflow}`. **EXIT Quick Dev.** - IF W: Direct user to run the PRD workflow instead. **EXIT Quick Dev.** -- IF E: Ask for guidance, then **NEXT:** Read fully and follow: `step-02-context-gathering.md` +- IF E: Ask for guidance, then **NEXT:** Read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md` #### EXECUTION RULES: @@ -150,8 +150,8 @@ Display: **CRITICAL:** When this step completes, explicitly state which step to load: -- Mode A (tech-spec): "**NEXT:** read fully and follow: `step-03-execute.md`" -- Mode B (direct, [E] selected): "**NEXT:** Read fully and follow: `step-02-context-gathering.md`" +- Mode A (tech-spec): "**NEXT:** read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md`" +- Mode B (direct, [E] selected): "**NEXT:** Read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md`" - Escalation ([P] or [W]): "**EXITING Quick Dev.** Follow the directed workflow." --- diff --git a/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md b/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md index d3461bb16..da178a088 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md @@ -97,7 +97,7 @@ Ready to execute? (y/n/adjust) **CRITICAL:** When user confirms ready, explicitly state: -- **y:** "**NEXT:** Read fully and follow: `step-03-execute.md`" +- **y:** "**NEXT:** Read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md`" - **n/adjust:** Continue gathering context, then re-present plan --- diff --git a/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md b/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md index baeab834b..81be97fba 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md @@ -89,7 +89,7 @@ For each task: ## NEXT STEP -When ALL tasks are complete (or halted on blocker), read fully and follow: `step-04-self-check.md`. +When ALL tasks are complete (or halted on blocker), read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md`. --- diff --git a/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md b/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md index 0c6a822c3..f12b2a3fd 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md @@ -89,7 +89,7 @@ Proceeding to adversarial code review... ## NEXT STEP -Proceed immediately to `step-05-adversarial-review.md`. +Proceed immediately to `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md`. --- diff --git a/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md b/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md index 41c8f4741..8bbd6761e 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md @@ -83,7 +83,7 @@ If TodoWrite or similar tool is available, turn each finding into a TODO, includ ## NEXT STEP -With findings in hand, read fully and follow: `step-06-resolve-findings.md` for user to choose resolution approach. +With findings in hand, read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-06-resolve-findings.md` for user to choose resolution approach. --- diff --git a/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md b/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md index 3fbeb13b1..009ead510 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md @@ -28,7 +28,7 @@ This uses **step-file architecture** for focused execution: Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: - `user_name`, `communication_language`, `user_skill_level` -- `output_folder`, `planning_artifacts`, `implementation_artifacts` +- `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}` @@ -47,4 +47,4 @@ Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: ## EXECUTION -Read fully and follow: `steps/step-01-mode-detection.md` to begin the workflow. +Read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md` to begin the workflow. diff --git a/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-01-understand.md b/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-01-understand.md index d338f24b7..fecac560a 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-01-understand.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-01-understand.md @@ -2,8 +2,6 @@ name: 'step-01-understand' description: 'Analyze the requirement delta between current state and what user wants to build' -nextStepFile: './step-02-investigate.md' -skipToStepFile: './step-03-generate.md' templateFile: '../tech-spec-template.md' wipFile: '{implementation_artifacts}/tech-spec-wip.md' --- @@ -56,9 +54,9 @@ a) **Menu Handling:** - **[Y] Continue existing:** - Jump directly to the appropriate step based on `stepsCompleted`: - - `[1]` → Load `{nextStepFile}` (Step 2) - - `[1, 2]` → Load `{skipToStepFile}` (Step 3) - - `[1, 2, 3]` → Load `./step-04-review.md` (Step 4) + - `[1]` → Read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md` (Step 2) + - `[1, 2]` → Read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md` (Step 3) + - `[1, 2, 3]` → Read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md` (Step 4) - **[N] Archive and start fresh:** - Rename `{wipFile}` to `{implementation_artifacts}/tech-spec-{slug}-archived-{date}.md` @@ -76,7 +74,7 @@ a) **Before asking detailed questions, do a rapid scan to understand the landsca b) **Check for existing context docs:** -- Check `{output_folder}` and `{planning_artifacts}`for planning documents (PRD, architecture, epics, research) +- Check `{implementation_artifacts}` and `{planning_artifacts}`for planning documents (PRD, architecture, epics, research) - Check for `**/project-context.md` - if it exists, skim for patterns and conventions - Check for any existing stories or specs related to user's request @@ -169,7 +167,7 @@ b) **HALT and wait for user selection.** - IF A: Read fully and follow: `{advanced_elicitation}` with current tech-spec content, process enhanced insights, ask user "Accept improvements? (y/n)", if yes update WIP file then redisplay menu, if no keep original then redisplay menu - IF P: Read fully and follow: `{party_mode_exec}` with current tech-spec content, process collaborative insights, ask user "Accept changes? (y/n)", if yes update WIP file then redisplay menu, if no keep original then redisplay menu -- IF C: Verify `{wipFile}` has `stepsCompleted: [1]`, then read fully and follow: `{nextStepFile}` +- IF C: Verify `{wipFile}` has `stepsCompleted: [1]`, then read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md` - IF Any other comments or queries: respond helpfully then redisplay menu #### EXECUTION RULES: diff --git a/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md b/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md index 533c0d55b..5e749a3ff 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md @@ -2,7 +2,6 @@ name: 'step-02-investigate' description: 'Map technical constraints and anchor points within the codebase' -nextStepFile: './step-03-generate.md' wipFile: '{implementation_artifacts}/tech-spec-wip.md' --- @@ -122,7 +121,7 @@ Display: "**Select:** [A] Advanced Elicitation [P] Party Mode [C] Continue to Ge - IF A: Read fully and follow: `{advanced_elicitation}` with current tech-spec content, process enhanced insights, ask user "Accept improvements? (y/n)", if yes update WIP file then redisplay menu, if no keep original then redisplay menu - IF P: Read fully and follow: `{party_mode_exec}` with current tech-spec content, process collaborative insights, ask user "Accept changes? (y/n)", if yes update WIP file then redisplay menu, if no keep original then redisplay menu -- IF C: Verify frontmatter updated with `stepsCompleted: [1, 2]`, then read fully and follow: `{nextStepFile}` +- IF C: Verify frontmatter updated with `stepsCompleted: [1, 2]`, then read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md` - IF Any other comments or queries: respond helpfully then redisplay menu #### EXECUTION RULES: diff --git a/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md b/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md index 1a163ccb0..2a8ee18e1 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md @@ -2,7 +2,6 @@ name: 'step-03-generate' description: 'Build the implementation plan based on the technical mapping of constraints' -nextStepFile: './step-04-review.md' wipFile: '{implementation_artifacts}/tech-spec-wip.md' --- @@ -113,7 +112,7 @@ stepsCompleted: [1, 2, 3] --- ``` -c) **Read fully and follow: `{nextStepFile}` (Step 4)** +c) **Read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md` (Step 4)** ## REQUIRED OUTPUTS: diff --git a/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md b/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md index 7c41b948d..7175b2aa9 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md @@ -68,11 +68,12 @@ This uses **step-file architecture** for disciplined execution: Load and read full config from `{main_config}` and resolve: -- `project_name`, `output_folder`, `planning_artifacts`, `implementation_artifacts`, `user_name` +- `project_name`, `planning_artifacts`, `implementation_artifacts`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` - `date` as system-generated current datetime +- `project_context` = `**/project-context.md` (load if exists) - ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}` ### 2. First Step Execution -Read fully and follow: `steps/step-01-understand.md` to begin the workflow. +Read fully and follow: `{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-01-understand.md` to begin the workflow. diff --git a/src/bmm/workflows/document-project/instructions.md b/src/bmm/workflows/document-project/instructions.md index 2f567fa38..0354be610 100644 --- a/src/bmm/workflows/document-project/instructions.md +++ b/src/bmm/workflows/document-project/instructions.md @@ -8,56 +8,8 @@ This router determines workflow mode and delegates to specialized sub-workflows - - - - mode: data - data_request: project_config - - - - {{suggestion}} - Note: Documentation workflow can run standalone. Continuing without progress tracking. - Set standalone_mode = true - Set status_file_found = false - - - - Store {{status_file_path}} for later updates - Set status_file_found = true - - - - Note: This is a greenfield project. Documentation workflow is typically for brownfield projects. - Continue anyway to document planning artifacts? (y/n) - - Exit workflow - - - - - - mode: validate - calling_workflow: document-project - - - - {{warning}} - Note: This may be auto-invoked by prd for brownfield documentation. - Continue with documentation? (y/n) - - {{suggestion}} - Exit workflow - - - - - - - -SMART LOADING STRATEGY: Check state file FIRST before loading any CSV files - -Check for existing state file at: {output_folder}/project-scan-report.json + +Check for existing state file at: {project_knowledge}/project-scan-report.json Read state file and extract: timestamps, mode, scan_level, current_step, completed_steps, project_classification @@ -66,21 +18,21 @@ I found an in-progress workflow state from {{last_updated}}. -**Current Progress:** + **Current Progress:** -- Mode: {{mode}} -- Scan Level: {{scan_level}} -- Completed Steps: {{completed_steps_count}}/{{total_steps}} -- Last Step: {{current_step}} -- Project Type(s): {{cached_project_types}} + - Mode: {{mode}} + - Scan Level: {{scan_level}} + - Completed Steps: {{completed_steps_count}}/{{total_steps}} + - Last Step: {{current_step}} + - Project Type(s): {{cached_project_types}} -Would you like to: + Would you like to: -1. **Resume from where we left off** - Continue from step {{current_step}} -2. **Start fresh** - Archive old state and begin new scan -3. **Cancel** - Exit without changes + 1. **Resume from where we left off** - Continue from step {{current_step}} + 2. **Start fresh** - Archive old state and begin new scan + 3. **Cancel** - Exit without changes -Your choice [1/2/3]: + Your choice [1/2/3]: @@ -107,8 +59,8 @@ Your choice [1/2/3]: - Create archive directory: {output_folder}/.archive/ - Move old state file to: {output_folder}/.archive/project-scan-report-{{timestamp}}.json + Create archive directory: {project_knowledge}/.archive/ + Move old state file to: {project_knowledge}/.archive/project-scan-report-{{timestamp}}.json Set resume_mode = false Continue to Step 0.5 @@ -120,7 +72,7 @@ Your choice [1/2/3]: Display: "Found old state file (>24 hours). Starting fresh scan." - Archive old state file to: {output_folder}/.archive/project-scan-report-{{timestamp}}.json + Archive old state file to: {project_knowledge}/.archive/project-scan-report-{{timestamp}}.json Set resume_mode = false Continue to Step 0.5 @@ -128,7 +80,7 @@ Your choice [1/2/3]: -Check if {output_folder}/index.md exists +Check if {project_knowledge}/index.md exists Read existing index.md to extract metadata (date, project structure, parts count) @@ -175,47 +127,4 @@ Your choice [1/2/3]: - - - - - mode: update - action: complete_workflow - workflow_name: document-project - - - - Status updated! - - - -**✅ Document Project Workflow Complete, {user_name}!** - -**Documentation Generated:** - -- Mode: {{workflow_mode}} -- Scan Level: {{scan_level}} -- Output: {output_folder}/index.md and related files - -{{#if status_file_found}} -**Status Updated:** - -- Progress tracking updated - -**Next Steps:** - -- **Next required:** {{next_workflow}} ({{next_agent}} agent) - -Check status anytime with: `workflow-status` -{{else}} -**Next Steps:** -Since no workflow is in progress: - -- Refer to the BMM workflow guide if unsure what to do next -- Or run `workflow-init` to create a workflow path and get guided next steps - {{/if}} - - - - diff --git a/src/bmm/workflows/document-project/templates/project-scan-report-schema.json b/src/bmm/workflows/document-project/templates/project-scan-report-schema.json index 8133e15fd..69e059833 100644 --- a/src/bmm/workflows/document-project/templates/project-scan-report-schema.json +++ b/src/bmm/workflows/document-project/templates/project-scan-report-schema.json @@ -45,9 +45,9 @@ "type": "string", "description": "Absolute path to project root directory" }, - "output_folder": { + "project_knowledge": { "type": "string", - "description": "Absolute path to output folder" + "description": "Absolute path to project knowledge folder" }, "completed_steps": { "type": "array", diff --git a/src/bmm/workflows/document-project/workflow.yaml b/src/bmm/workflows/document-project/workflow.yaml index 4667d7c0b..be9600c24 100644 --- a/src/bmm/workflows/document-project/workflow.yaml +++ b/src/bmm/workflows/document-project/workflow.yaml @@ -6,7 +6,7 @@ author: "BMad" # Critical variables config_source: "{project-root}/_bmad/bmm/config.yaml" -output_folder: "{config_source}:project_knowledge" +project_knowledge: "{config_source}:project_knowledge" user_name: "{config_source}:user_name" communication_language: "{config_source}:communication_language" document_output_language: "{config_source}:document_output_language" diff --git a/src/bmm/workflows/document-project/workflows/deep-dive-instructions.md b/src/bmm/workflows/document-project/workflows/deep-dive-instructions.md index c88dfb08b..637621c4c 100644 --- a/src/bmm/workflows/document-project/workflows/deep-dive-instructions.md +++ b/src/bmm/workflows/document-project/workflows/deep-dive-instructions.md @@ -194,7 +194,7 @@ This will read EVERY file in this area. Proceed? [y/n] Load complete deep-dive template from: {installed_path}/templates/deep-dive-template.md Fill template with all collected data from steps 13b-13d -Write filled template to: {output_folder}/deep-dive-{{sanitized_target_name}}.md +Write filled template to: {project_knowledge}/deep-dive-{{sanitized_target_name}}.md Validate deep-dive document completeness deep_dive_documentation @@ -241,7 +241,7 @@ Detailed exhaustive analysis of specific areas: ## Deep-Dive Documentation Complete! ✓ -**Generated:** {output_folder}/deep-dive-{{target_name}}.md +**Generated:** {project_knowledge}/deep-dive-{{target_name}}.md **Files Analyzed:** {{file_count}} **Lines of Code Scanned:** {{total_loc}} **Time Taken:** ~{{duration}} @@ -255,7 +255,7 @@ Detailed exhaustive analysis of specific areas: - Related code and reuse opportunities - Implementation guidance -**Index Updated:** {output_folder}/index.md now includes link to this deep-dive +**Index Updated:** {project_knowledge}/index.md now includes link to this deep-dive ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ @@ -278,7 +278,7 @@ Your choice [1/2]: All deep-dive documentation complete! -**Master Index:** {output_folder}/index.md +**Master Index:** {project_knowledge}/index.md **Deep-Dives Generated:** {{deep_dive_count}} These comprehensive docs are now ready for: diff --git a/src/bmm/workflows/document-project/workflows/deep-dive.yaml b/src/bmm/workflows/document-project/workflows/deep-dive.yaml index a333cc4bf..c7b85c031 100644 --- a/src/bmm/workflows/document-project/workflows/deep-dive.yaml +++ b/src/bmm/workflows/document-project/workflows/deep-dive.yaml @@ -8,7 +8,7 @@ parent_workflow: "{project-root}/_bmad/bmm/workflows/document-project/workflow.y # Critical variables inherited from parent config_source: "{project-root}/_bmad/bmb/config.yaml" -output_folder: "{config_source}:output_folder" +project_knowledge: "{config_source}:project_knowledge" user_name: "{config_source}:user_name" date: system-generated diff --git a/src/bmm/workflows/document-project/workflows/full-scan-instructions.md b/src/bmm/workflows/document-project/workflows/full-scan-instructions.md index 1340f75ec..8a3621d21 100644 --- a/src/bmm/workflows/document-project/workflows/full-scan-instructions.md +++ b/src/bmm/workflows/document-project/workflows/full-scan-instructions.md @@ -43,7 +43,7 @@ This workflow uses a single comprehensive CSV file to intelligently document you -Check if {output_folder}/index.md exists +Check if {project_knowledge}/index.md exists Read existing index.md to extract metadata (date, project structure, parts count) @@ -127,7 +127,7 @@ Your choice [1/2/3] (default: 1): Display: "Using Exhaustive Scan (reading all source files)" -Initialize state file: {output_folder}/project-scan-report.json +Initialize state file: {project_knowledge}/project-scan-report.json Every time you touch the state file, record: step id, human-readable summary (what you actually did), precise timestamp, and any outputs written. Vague phrases are unacceptable. Write initial state: { @@ -136,7 +136,7 @@ Your choice [1/2/3] (default: 1): "mode": "{{workflow_mode}}", "scan_level": "{{scan_level}}", "project_root": "{{project_root_path}}", -"output_folder": "{{output_folder}}", +"project_knowledge": "{{project_knowledge}}", "completed_steps": [], "current_step": "step_1", "findings": {}, @@ -325,7 +325,7 @@ findings.batches_completed: [ Build API contracts catalog -IMMEDIATELY write to: {output_folder}/api-contracts-{part_id}.md +IMMEDIATELY write to: {project_knowledge}/api-contracts-{part_id}.md Validate document has all required sections Update state file with output generated PURGE detailed API data, keep only: "{{api_count}} endpoints documented" @@ -346,7 +346,7 @@ findings.batches_completed: [ Build database schema documentation -IMMEDIATELY write to: {output_folder}/data-models-{part_id}.md +IMMEDIATELY write to: {project_knowledge}/data-models-{part_id}.md Validate document completeness Update state file with output generated PURGE detailed schema data, keep only: "{{table_count}} tables documented" @@ -805,7 +805,7 @@ When a document SHOULD be generated but wasn't (due to quick scan, missing data, Show summary of all generated files: -Generated in {{output_folder}}/: +Generated in {{project_knowledge}}/: {{file_list_with_sizes}} @@ -823,7 +823,7 @@ Generated in {{output_folder}}/: 3. Extract document metadata from each match for user selection -Read {output_folder}/index.md +Read {project_knowledge}/index.md Scan for incomplete documentation markers: Step 1: Search for exact pattern "_(To be generated)_" (case-sensitive) @@ -1065,9 +1065,9 @@ Enter number(s) separated by commas (e.g., "1,3,5"), or type 'all': ## Project Documentation Complete! ✓ -**Location:** {{output_folder}}/ +**Location:** {{project_knowledge}}/ -**Master Index:** {{output_folder}}/index.md +**Master Index:** {{project_knowledge}}/index.md 👆 This is your primary entry point for AI-assisted development **Generated Documentation:** @@ -1076,9 +1076,9 @@ Enter number(s) separated by commas (e.g., "1,3,5"), or type 'all': **Next Steps:** 1. Review the index.md to familiarize yourself with the documentation structure -2. When creating a brownfield PRD, point the PRD workflow to: {{output_folder}}/index.md -3. For UI-only features: Reference {{output_folder}}/architecture-{{ui_part_id}}.md -4. For API-only features: Reference {{output_folder}}/architecture-{{api_part_id}}.md +2. When creating a brownfield PRD, point the PRD workflow to: {{project_knowledge}}/index.md +3. For UI-only features: Reference {{project_knowledge}}/architecture-{{ui_part_id}}.md +4. For API-only features: Reference {{project_knowledge}}/architecture-{{api_part_id}}.md 5. For full-stack features: Reference both part architectures + integration-architecture.md **Verification Recap:** @@ -1101,6 +1101,6 @@ When ready to plan new features, run the PRD workflow and provide this index as - Write final state file -Display: "State file saved: {{output_folder}}/project-scan-report.json" +Display: "State file saved: {{project_knowledge}}/project-scan-report.json" diff --git a/src/bmm/workflows/document-project/workflows/full-scan.yaml b/src/bmm/workflows/document-project/workflows/full-scan.yaml index f62aba9b2..272baedda 100644 --- a/src/bmm/workflows/document-project/workflows/full-scan.yaml +++ b/src/bmm/workflows/document-project/workflows/full-scan.yaml @@ -8,7 +8,7 @@ parent_workflow: "{project-root}/_bmad/bmm/workflows/document-project/workflow.y # Critical variables inherited from parent config_source: "{project-root}/_bmad/bmb/config.yaml" -output_folder: "{config_source}:output_folder" +project_knowledge: "{config_source}:project_knowledge" user_name: "{config_source}:user_name" date: system-generated diff --git a/src/bmm/workflows/generate-project-context/steps/step-01-discover.md b/src/bmm/workflows/generate-project-context/steps/step-01-discover.md index fa36993d3..16f95e15c 100644 --- a/src/bmm/workflows/generate-project-context/steps/step-01-discover.md +++ b/src/bmm/workflows/generate-project-context/steps/step-01-discover.md @@ -179,6 +179,6 @@ Ready to create/update your project context. This will help AI agents implement ## NEXT STEP: -After user selects [C] to continue, load `./step-02-generate.md` to collaboratively generate the specific project context rules. +After user selects [C] to continue, load `{project-root}/_bmad/bmm/workflows/generate-project-context/steps/step-02-generate.md` to collaboratively generate the specific project context rules. Remember: Do NOT proceed to step-02 until user explicitly selects [C] from the menu and discovery is confirmed and the initial file has been written as directed in this discovery step! diff --git a/src/bmm/workflows/generate-project-context/steps/step-02-generate.md b/src/bmm/workflows/generate-project-context/steps/step-02-generate.md index c2b428c57..dcb2f0097 100644 --- a/src/bmm/workflows/generate-project-context/steps/step-02-generate.md +++ b/src/bmm/workflows/generate-project-context/steps/step-02-generate.md @@ -313,6 +313,6 @@ When user selects 'C' for a category, append the content directly to `{output_fo ## NEXT STEP: -After completing all rule categories and user selects 'C' for the final category, load `./step-03-complete.md` to finalize the project context file. +After completing all rule categories and user selects 'C' for the final category, load `{project-root}/_bmad/bmm/workflows/generate-project-context/steps/step-03-complete.md` to finalize the project context file. Remember: Do NOT proceed to step-03 until all categories are complete and user explicitly selects 'C' for each! diff --git a/src/bmm/workflows/generate-project-context/workflow.md b/src/bmm/workflows/generate-project-context/workflow.md index 3f626d65f..e19902270 100644 --- a/src/bmm/workflows/generate-project-context/workflow.md +++ b/src/bmm/workflows/generate-project-context/workflow.md @@ -44,6 +44,6 @@ Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: ## EXECUTION -Load and execute `steps/step-01-discover.md` to begin the workflow. +Load and execute `{project-root}/_bmad/bmm/workflows/generate-project-context/steps/step-01-discover.md` to begin the workflow. **Note:** Input document discovery and initialization protocols are handled in step-01-discover.md. diff --git a/src/bmm/workflows/qa/automate/workflow.yaml b/src/bmm/workflows/qa/automate/workflow.yaml index 847365d7b..f1119e980 100644 --- a/src/bmm/workflows/qa/automate/workflow.yaml +++ b/src/bmm/workflows/qa/automate/workflow.yaml @@ -5,7 +5,6 @@ author: "BMad" # Critical variables from config config_source: "{project-root}/_bmad/bmm/config.yaml" -output_folder: "{config_source}:output_folder" implementation_artifacts: "{config_source}:implementation_artifacts" user_name: "{config_source}:user_name" communication_language: "{config_source}:communication_language" @@ -19,10 +18,8 @@ validation: "{installed_path}/checklist.md" template: false # Variables and inputs -variables: - # Directory paths - test_dir: "{project-root}/tests" # Root test directory - source_dir: "{project-root}" # Source code directory +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" diff --git a/src/core/agents/bmad-master.agent.yaml b/src/core/agents/bmad-master.agent.yaml index 66e9d37fc..1304c1cc9 100644 --- a/src/core/agents/bmad-master.agent.yaml +++ b/src/core/agents/bmad-master.agent.yaml @@ -7,6 +7,7 @@ agent: name: "BMad Master" title: "BMad Master Executor, Knowledge Custodian, and Workflow Orchestrator" icon: "🧙" + capabilities: "runtime resource management, workflow orchestration, task execution, knowledge custodian" hasSidecar: false persona: @@ -14,7 +15,7 @@ agent: identity: "Master-level expert in the BMAD Core Platform and all loaded modules with comprehensive knowledge of all resources, tasks, and workflows. Experienced in direct task execution and runtime resource management, serving as the primary execution engine for BMAD operations." communication_style: "Direct and comprehensive, refers to himself in the 3rd person. Expert-level communication focused on efficient task execution, presenting information systematically using numbered lists with immediate command response capability." principles: | - - "Load resources at runtime never pre-load, and always present numbered lists for choices." + - Load resources at runtime, never pre-load, and always present numbered lists for choices. critical_actions: - "Always greet the user and let them know they can use `/bmad-help` at any time to get advice on what to do next, and they can combine that with what they need help with `/bmad-help where should I start with an idea I have that does XYZ`" diff --git a/src/core/tasks/help.md b/src/core/tasks/help.md index c3c3fab11..f07cbc062 100644 --- a/src/core/tasks/help.md +++ b/src/core/tasks/help.md @@ -9,6 +9,7 @@ description: Get unstuck by showing what workflow steps come next or answering q - **Empty `phase` = anytime** — Universal tools work regardless of workflow state - **Numbered phases indicate sequence** — Phases like `1-discover` → `2-define` → `3-build` → `4-ship` flow in order (naming varies by module) +- **Phase with no Required Steps** - If an entire phase has no required, true items, the entire phase is optional. If it is sequentially before another phase, it can be recommended, but always be clear with the use what the true next required item is. - **Stay in module** — Guide through the active module's workflow based on phase+sequence ordering - **Descriptions contain routing** — Read for alternate paths (e.g., "back to previous if fixes needed") - **`required=true` blocks progress** — Required workflows must complete before proceeding to later phases @@ -54,7 +55,7 @@ Determine what was just completed: 1. **Load catalog** — Load `{project-root}/_bmad/_config/bmad-help.csv` -2. **Resolve output locations and config** — Scan each folder under `_bmad/` (except `_config`) for `config.yaml`. For each workflow row, resolve its `output-location` variables against that module's config so artifact paths can be searched. Also extract `communication_language` and `project_knowledge` from each scanned module's config. +2. **Resolve output locations and config** — Scan each folder under `{project-root}/_bmad/` (except `_config`) for `config.yaml`. For each workflow row, resolve its `output-location` variables against that module's config so artifact paths can be searched. Also extract `communication_language` and `project_knowledge` from each scanned module's config. 3. **Ground in project knowledge** — If `project_knowledge` resolves to an existing path, read available documentation files (architecture docs, project overview, tech stack references) for grounding context. Use discovered project facts when composing any project-specific output. Never fabricate project-specific details — if documentation is unavailable, state so. diff --git a/tools/cli/README.md b/tools/cli/README.md index 6d698580f..9e943d689 100644 --- a/tools/cli/README.md +++ b/tools/cli/README.md @@ -5,3 +5,56 @@ For external official modules to be discoverable during install, ensure an entry for the external repo is added to external-official-modules.yaml. For community modules - this will be handled in a different way. This file is only for registration of modules under the bmad-code-org. + +## Post-Install Notes + +Modules can display setup guidance to users after configuration is collected during `npx bmad-method install`. Notes are defined in the module's own `module.yaml` — no changes to the installer are needed. + +### Simple Format + +Always displayed after the module is configured: + +```yaml +post-install-notes: | + Thank you for choosing the XYZ Cool Module + For Support about this Module call 555-1212 +``` + +### Conditional Format + +Display different messages based on a config question's answer: + +```yaml +post-install-notes: + config_key_name: + value1: | + Instructions for value1... + value2: | + Instructions for value2... +``` + +Values without an entry (e.g., `none`) display nothing. Multiple config keys can each have their own conditional notes. + +### Example: TEA Module + +The TEA module uses the conditional format keyed on `tea_browser_automation`: + +```yaml +post-install-notes: + tea_browser_automation: + cli: | + Playwright CLI Setup: + npm install -g @playwright/cli@latest + playwright-cli install --skills + mcp: | + Playwright MCP Setup (two servers): + 1. playwright — npx @playwright/mcp@latest + 2. playwright-test — npx playwright run-test-mcp-server + auto: | + Playwright CLI Setup: + ... + Playwright MCP Setup (two servers): + ... +``` + +When a user selects `auto`, they see both CLI and MCP instructions. When they select `none`, nothing is shown. diff --git a/tools/cli/bmad-cli.js b/tools/cli/bmad-cli.js index bcd599293..31db41fbf 100755 --- a/tools/cli/bmad-cli.js +++ b/tools/cli/bmad-cli.js @@ -2,6 +2,7 @@ const { program } = require('commander'); const path = require('node:path'); const fs = require('node:fs'); const { execSync } = require('node:child_process'); +const semver = require('semver'); const prompts = require('./lib/prompts'); // The installer flow uses many sequential @clack/prompts, each adding keypress @@ -34,7 +35,7 @@ async function checkForUpdate() { timeout: 5000, }).trim(); - if (result && result !== packageJson.version) { + if (result && semver.gt(result, packageJson.version)) { const color = await prompts.getColor(); const updateMsg = [ `You are using version ${packageJson.version} but ${result} is available.`, diff --git a/tools/cli/commands/install.js b/tools/cli/commands/install.js index 961a1a9fa..d9d8332be 100644 --- a/tools/cli/commands/install.js +++ b/tools/cli/commands/install.js @@ -39,7 +39,6 @@ module.exports = { if (config.actionType === 'cancel') { await prompts.log.warn('Installation cancelled.'); process.exit(0); - return; } // Handle quick update separately @@ -47,23 +46,14 @@ module.exports = { const result = await installer.quickUpdate(config); await prompts.log.success('Quick update complete!'); await prompts.log.info(`Updated ${result.moduleCount} modules with preserved settings (${result.modules.join(', ')})`); - - // Display version-specific end message - const { MessageLoader } = require('../installers/lib/message-loader'); - const messageLoader = new MessageLoader(); - await messageLoader.displayEndMessage(); - process.exit(0); - return; } // Handle compile agents separately if (config.actionType === 'compile-agents') { const result = await installer.compileAgents(config); - await prompts.log.success('Agent recompilation complete!'); await prompts.log.info(`Recompiled ${result.agentCount} agents with customizations applied`); process.exit(0); - return; } // Regular install/update flow @@ -72,16 +62,10 @@ module.exports = { // Check if installation was cancelled if (result && result.cancelled) { process.exit(0); - return; } // Check if installation succeeded if (result && result.success) { - // Display version-specific end message from install-messages.yaml - const { MessageLoader } = require('../installers/lib/message-loader'); - const messageLoader = new MessageLoader(); - await messageLoader.displayEndMessage(); - process.exit(0); } } catch (error) { diff --git a/tools/cli/commands/uninstall.js b/tools/cli/commands/uninstall.js new file mode 100644 index 000000000..99734791e --- /dev/null +++ b/tools/cli/commands/uninstall.js @@ -0,0 +1,167 @@ +const path = require('node:path'); +const fs = require('fs-extra'); +const prompts = require('../lib/prompts'); +const { Installer } = require('../installers/lib/core/installer'); + +const installer = new Installer(); + +module.exports = { + command: 'uninstall', + description: 'Remove BMAD installation from the current project', + options: [ + ['-y, --yes', 'Remove all BMAD components without prompting (preserves user artifacts)'], + ['--directory ', 'Project directory (default: current directory)'], + ], + action: async (options) => { + try { + let projectDir; + + if (options.directory) { + // Explicit --directory flag takes precedence + projectDir = path.resolve(options.directory); + } else if (options.yes) { + // Non-interactive mode: use current directory + projectDir = process.cwd(); + } else { + // Interactive: ask user which directory to uninstall from + // select() handles cancellation internally (exits process) + const dirChoice = await prompts.select({ + message: 'Where do you want to uninstall BMAD from?', + choices: [ + { value: 'cwd', name: `Current directory (${process.cwd()})` }, + { value: 'other', name: 'Another directory...' }, + ], + }); + + if (dirChoice === 'other') { + // text() handles cancellation internally (exits process) + const customDir = await prompts.text({ + message: 'Enter the project directory path:', + placeholder: process.cwd(), + validate: (value) => { + if (!value || value.trim().length === 0) return 'Directory path is required'; + }, + }); + + projectDir = path.resolve(customDir.trim()); + } else { + projectDir = process.cwd(); + } + } + + if (!(await fs.pathExists(projectDir))) { + await prompts.log.error(`Directory does not exist: ${projectDir}`); + process.exit(1); + } + + const { bmadDir } = await installer.findBmadDir(projectDir); + + if (!(await fs.pathExists(bmadDir))) { + await prompts.log.warn('No BMAD installation found.'); + process.exit(0); + } + + const existingInstall = await installer.getStatus(projectDir); + const version = existingInstall.version || 'unknown'; + const modules = (existingInstall.modules || []).map((m) => m.id || m.name).join(', '); + const ides = (existingInstall.ides || []).join(', '); + + const outputFolder = await installer.getOutputFolder(projectDir); + + await prompts.intro('BMAD Uninstall'); + await prompts.note(`Version: ${version}\nModules: ${modules}\nIDE integrations: ${ides}`, 'Current Installation'); + + let removeModules = true; + let removeIdeConfigs = true; + let removeOutputFolder = false; + + if (!options.yes) { + // multiselect() handles cancellation internally (exits process) + const selected = await prompts.multiselect({ + message: 'Select components to remove:', + options: [ + { + value: 'modules', + label: `BMAD Modules & data (${installer.bmadFolderName}/)`, + hint: 'Core installation, agents, workflows, config', + }, + { value: 'ide', label: 'IDE integrations', hint: ides || 'No IDEs configured' }, + { value: 'output', label: `User artifacts (${outputFolder}/)`, hint: 'WARNING: Contains your work products' }, + ], + initialValues: ['modules', 'ide'], + required: true, + }); + + removeModules = selected.includes('modules'); + removeIdeConfigs = selected.includes('ide'); + removeOutputFolder = selected.includes('output'); + + const red = (s) => `\u001B[31m${s}\u001B[0m`; + await prompts.note( + red('💀 This action is IRREVERSIBLE! Removed files cannot be recovered!') + + '\n' + + red('💀 IDE configurations and modules will need to be reinstalled.') + + '\n' + + red('💀 User artifacts are preserved unless explicitly selected.'), + '!! DESTRUCTIVE ACTION !!', + ); + + const confirmed = await prompts.confirm({ + message: 'Proceed with uninstall?', + default: false, + }); + + if (!confirmed) { + await prompts.outro('Uninstall cancelled.'); + process.exit(0); + } + } + + // Phase 1: IDE integrations + if (removeIdeConfigs) { + const s = await prompts.spinner(); + s.start('Removing IDE integrations...'); + await installer.uninstallIdeConfigs(projectDir, existingInstall, { silent: true }); + s.stop(`Removed IDE integrations (${ides || 'none'})`); + } + + // Phase 2: User artifacts + if (removeOutputFolder) { + const s = await prompts.spinner(); + s.start(`Removing user artifacts (${outputFolder}/)...`); + await installer.uninstallOutputFolder(projectDir, outputFolder); + s.stop('User artifacts removed'); + } + + // Phase 3: BMAD modules & data (last — other phases may need _bmad/) + if (removeModules) { + const s = await prompts.spinner(); + s.start(`Removing BMAD modules & data (${installer.bmadFolderName}/)...`); + await installer.uninstallModules(projectDir); + s.stop('Modules & data removed'); + } + + const summary = []; + if (removeIdeConfigs) summary.push('IDE integrations cleaned'); + if (removeModules) summary.push('Modules & data removed'); + if (removeOutputFolder) summary.push('User artifacts removed'); + if (!removeOutputFolder) summary.push(`User artifacts preserved in ${outputFolder}/`); + + await prompts.note(summary.join('\n'), 'Summary'); + await prompts.outro('To reinstall, run: npx bmad-method install'); + + process.exit(0); + } catch (error) { + try { + const errorMessage = error instanceof Error ? error.message : String(error); + await prompts.log.error(`Uninstall failed: ${errorMessage}`); + if (error instanceof Error && error.stack) { + await prompts.log.message(error.stack); + } + } catch { + console.error(error instanceof Error ? error.message : error); + } + process.exit(1); + } + }, +}; diff --git a/tools/cli/installers/install-messages.yaml b/tools/cli/installers/install-messages.yaml index d9f40b0d7..b14265165 100644 --- a/tools/cli/installers/install-messages.yaml +++ b/tools/cli/installers/install-messages.yaml @@ -6,54 +6,34 @@ startMessage: | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - 🎉 BETA IS HERE! Welcome to BMad Method V6 Beta! + 🎉 V6 IS HERE! Welcome to BMad Method V6 - Official Stable Release! - We've officially graduated from Alpha! This milestone represents: - - 50+ workflows covering the full development lifecycle - - Stability - we will still be adding and evolving and optimizing, - but anticipate no massive breaking changes - - Groundwork in place for customization and community modules - - 📚 New Docs Site: http://docs.bmad-method.org/ - - High quality tutorials, guided walkthrough, and articles coming soon! - - Everything is free. No paywalls. No gated content. - - Knowledge should be shared, not sold. - - 💡 Love BMad? Please star us on GitHub & subscribe on YouTube! - - GitHub: https://github.com/bmad-code-org/BMAD-METHOD/ - - YouTube: https://www.youtube.com/@BMadCode - - Latest updates: https://github.com/bmad-code-org/BMAD-METHOD/CHANGELOG.md - - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -# Display at the END of installation (after all setup completes) -endMessage: | - ════════════════════════════════════════════════════════════════════════════════ - - ✨ BMAD V6 BETA IS INSTALLED! Thank you for being part of this journey! + The BMad Method is now a Platform powered by the BMad Method Core and Module Ecosystem! + - Select and install modules during setup - customize your experience + - New BMad Method for Agile AI-Driven Development (the evolution of V4) + - Exciting new modules available during installation, with community modules coming soon + - Documentation: docs.bmad-method.com 🌟 BMad is 100% free and open source. - - No gated Discord. No paywalls. + - No gated Discord. No paywalls. No gated content. - We believe in empowering everyone, not just those who can pay. - - 🙏 SUPPORT BMAD DEVELOPMENT: - - During the Beta, please give us feedback and raise issues on GitHub! - - Donate: https://buymeacoffee.com/bmad - - Corporate Sponsorship available - DM on Discord + - Knowledge should be shared, not sold. 🎤 SPEAKING & MEDIA: - Available for conferences, podcasts, and media appearances - Topics: AI-Native Transformation, Spec and Context Engineering, BMad Method - For speaking inquiries or interviews, reach out to BMad on Discord! - 📚 RESOURCES: - - Docs: http://docs.bmad-method.org/ (bookmark it!) - - Changelog: https://github.com/bmad-code-org/BMAD-METHOD/CHANGELOG.md - - ⭐⭐⭐ HELP US GROW: + ⭐ HELP US GROW: - Star us on GitHub: https://github.com/bmad-code-org/BMAD-METHOD/ - Subscribe on YouTube: https://www.youtube.com/@BMadCode - - Every star & sub helps us reach more developers! + - Free Community and Support: https://discord.gg/gk8jAdXWmj + - Donate: https://buymeacoffee.com/bmad + - Corporate Sponsorship available - ════════════════════════════════════════════════════════════════════════════════ + Latest updates: https://github.com/bmad-code-org/BMAD-METHOD/blob/main/CHANGELOG.md + + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +# No end message - install summary and next steps are rendered by the installer +endMessage: "" diff --git a/tools/cli/installers/lib/core/config-collector.js b/tools/cli/installers/lib/core/config-collector.js index 1fd410fa3..e8569cd0f 100644 --- a/tools/cli/installers/lib/core/config-collector.js +++ b/tools/cli/installers/lib/core/config-collector.js @@ -10,6 +10,19 @@ class ConfigCollector { this.collectedConfig = {}; this.existingConfig = null; this.currentProjectDir = null; + this._moduleManagerInstance = null; + } + + /** + * Get or create a cached ModuleManager instance (lazy initialization) + * @returns {Object} ModuleManager instance + */ + _getModuleManager() { + if (!this._moduleManagerInstance) { + const { ModuleManager } = require('../modules/manager'); + this._moduleManagerInstance = new ModuleManager(); + } + return this._moduleManagerInstance; } /** @@ -129,6 +142,70 @@ class ConfigCollector { return foundAny; } + /** + * Pre-scan module schemas to gather metadata for the configuration gateway prompt. + * Returns info about which modules have configurable options. + * @param {Array} modules - List of non-core module names + * @returns {Promise} Array of {moduleName, displayName, questionCount, hasFieldsWithoutDefaults} + */ + async scanModuleSchemas(modules) { + const metadataFields = new Set(['code', 'name', 'header', 'subheader', 'default_selected']); + const results = []; + + for (const moduleName of modules) { + // Resolve module.yaml path - custom paths first, then standard location, then ModuleManager search + let moduleConfigPath = null; + const customPath = this.customModulePaths?.get(moduleName); + if (customPath) { + moduleConfigPath = path.join(customPath, 'module.yaml'); + } else { + const standardPath = path.join(getModulePath(moduleName), 'module.yaml'); + if (await fs.pathExists(standardPath)) { + moduleConfigPath = standardPath; + } else { + const moduleSourcePath = await this._getModuleManager().findModuleSource(moduleName, { silent: true }); + if (moduleSourcePath) { + moduleConfigPath = path.join(moduleSourcePath, 'module.yaml'); + } + } + } + + if (!moduleConfigPath || !(await fs.pathExists(moduleConfigPath))) { + continue; + } + + try { + const content = await fs.readFile(moduleConfigPath, 'utf8'); + const moduleConfig = yaml.parse(content); + if (!moduleConfig) continue; + + const displayName = moduleConfig.header || `${moduleName.toUpperCase()} Module`; + const configKeys = Object.keys(moduleConfig).filter((key) => key !== 'prompt'); + const questionKeys = configKeys.filter((key) => { + if (metadataFields.has(key)) return false; + const item = moduleConfig[key]; + return item && typeof item === 'object' && item.prompt; + }); + + const hasFieldsWithoutDefaults = questionKeys.some((key) => { + const item = moduleConfig[key]; + return item.default === undefined || item.default === null || item.default === ''; + }); + + results.push({ + moduleName, + displayName, + questionCount: questionKeys.length, + hasFieldsWithoutDefaults, + }); + } catch (error) { + await prompts.log.warn(`Could not read schema for module "${moduleName}": ${error.message}`); + } + } + + return results; + } + /** * Collect configuration for all modules * @param {Array} modules - List of modules to configure (including 'core') @@ -141,6 +218,7 @@ class ConfigCollector { // Store custom module paths for use in collectModuleConfig this.customModulePaths = options.customModulePaths || new Map(); this.skipPrompts = options.skipPrompts || false; + this.modulesToCustomize = undefined; await this.loadExistingConfig(projectDir); // Check if core was already collected (e.g., in early collection phase) @@ -154,10 +232,102 @@ class ConfigCollector { this.allAnswers = {}; } - for (const moduleName of allModules) { + // Split processing: core first, then gateway, then remaining modules + const coreModules = allModules.filter((m) => m === 'core'); + const nonCoreModules = allModules.filter((m) => m !== 'core'); + + // Collect core config first (always fully prompted) + for (const moduleName of coreModules) { await this.collectModuleConfig(moduleName, projectDir); } + // Show batch configuration gateway for non-core modules + // Scan all non-core module schemas for display names and config metadata + let scannedModules = []; + if (!this.skipPrompts && nonCoreModules.length > 0) { + scannedModules = await this.scanModuleSchemas(nonCoreModules); + const customizableModules = scannedModules.filter((m) => m.questionCount > 0); + + if (customizableModules.length > 0) { + const configMode = await prompts.select({ + message: 'Module configuration', + choices: [ + { name: 'Express Setup', value: 'express', hint: 'accept all defaults (recommended)' }, + { name: 'Customize', value: 'customize', hint: 'choose modules to configure' }, + ], + default: 'express', + }); + + if (configMode === 'customize') { + const choices = customizableModules.map((m) => ({ + name: `${m.displayName} (${m.questionCount} option${m.questionCount === 1 ? '' : 's'})`, + value: m.moduleName, + hint: m.hasFieldsWithoutDefaults ? 'has fields without defaults' : undefined, + checked: m.hasFieldsWithoutDefaults, + })); + const selected = await prompts.multiselect({ + message: 'Select modules to customize:', + choices, + required: false, + }); + this.modulesToCustomize = new Set(selected); + } else { + // Express mode: no modules to customize + this.modulesToCustomize = new Set(); + } + } else { + // All non-core modules have zero config - no gateway needed + this.modulesToCustomize = new Set(); + } + } + + // Collect remaining non-core modules + if (this.modulesToCustomize === undefined) { + // No gateway was shown (skipPrompts, no non-core modules, or direct call) - process all normally + for (const moduleName of nonCoreModules) { + await this.collectModuleConfig(moduleName, projectDir); + } + } else { + // Split into default modules (tasks progress) and customized modules (interactive) + const defaultModules = nonCoreModules.filter((m) => !this.modulesToCustomize.has(m)); + const customizeModules = nonCoreModules.filter((m) => this.modulesToCustomize.has(m)); + + // Run default modules with a single spinner + if (defaultModules.length > 0) { + // Build display name map from all scanned modules for pre-call spinner messages + const displayNameMap = new Map(); + for (const m of scannedModules) { + displayNameMap.set(m.moduleName, m.displayName); + } + + const configSpinner = await prompts.spinner(); + configSpinner.start('Configuring modules...'); + try { + for (const moduleName of defaultModules) { + const displayName = displayNameMap.get(moduleName) || moduleName.toUpperCase(); + configSpinner.message(`Configuring ${displayName}...`); + try { + this._silentConfig = true; + await this.collectModuleConfig(moduleName, projectDir); + } finally { + this._silentConfig = false; + } + } + } finally { + configSpinner.stop(customizeModules.length > 0 ? 'Module defaults applied' : 'Module configuration complete'); + } + } + + // Run customized modules individually (may show interactive prompts) + for (const moduleName of customizeModules) { + await this.collectModuleConfig(moduleName, projectDir); + } + + if (customizeModules.length > 0) { + await prompts.log.step('Module configuration complete'); + } + } + // Add metadata this.collectedConfig._meta = { version: require(path.join(getProjectRoot(), 'package.json')).version, @@ -194,10 +364,7 @@ class ConfigCollector { // If not found in src/modules, we need to find it by searching the project if (!(await fs.pathExists(moduleConfigPath))) { - // Use the module manager to find the module source - const { ModuleManager } = require('../modules/manager'); - const moduleManager = new ModuleManager(); - const moduleSourcePath = await moduleManager.findModuleSource(moduleName); + const moduleSourcePath = await this._getModuleManager().findModuleSource(moduleName, { silent: true }); if (moduleSourcePath) { moduleConfigPath = path.join(moduleSourcePath, 'module.yaml'); @@ -211,9 +378,7 @@ class ConfigCollector { configPath = moduleConfigPath; } else { // Check if this is a custom module with custom.yaml - const { ModuleManager } = require('../modules/manager'); - const moduleManager = new ModuleManager(); - const moduleSourcePath = await moduleManager.findModuleSource(moduleName); + const moduleSourcePath = await this._getModuleManager().findModuleSource(moduleName, { silent: true }); if (moduleSourcePath) { const rootCustomConfigPath = path.join(moduleSourcePath, 'custom.yaml'); @@ -392,6 +557,8 @@ class ConfigCollector { } } + await this.displayModulePostConfigNotes(moduleName, moduleConfig); + return newKeys.length > 0 || newStaticKeys.length > 0; // Return true if we had any new fields (interactive or static) } @@ -507,10 +674,7 @@ class ConfigCollector { // If not found in src/modules or custom paths, search the project if (!(await fs.pathExists(moduleConfigPath))) { - // Use the module manager to find the module source - const { ModuleManager } = require('../modules/manager'); - const moduleManager = new ModuleManager(); - const moduleSourcePath = await moduleManager.findModuleSource(moduleName); + const moduleSourcePath = await this._getModuleManager().findModuleSource(moduleName, { silent: true }); if (moduleSourcePath) { moduleConfigPath = path.join(moduleSourcePath, 'module.yaml'); @@ -579,12 +743,12 @@ class ConfigCollector { } } } else { - await prompts.log.step(moduleDisplayName); - let customize = true; + if (!this._silentConfig) await prompts.log.step(`Configuring ${moduleDisplayName}`); + let useDefaults = true; if (moduleName === 'core') { - // Core module: no confirm prompt, continues directly - } else { - // Non-core modules: show "Accept Defaults?" confirm prompt (clack adds spacing) + useDefaults = false; // Core: always show all questions + } else if (this.modulesToCustomize === undefined) { + // Fallback: original per-module confirm (backward compat for direct calls) const customizeAnswer = await prompts.prompt([ { type: 'confirm', @@ -593,10 +757,13 @@ class ConfigCollector { default: true, }, ]); - customize = customizeAnswer.customize; + useDefaults = customizeAnswer.customize; + } else { + // Batch mode: use defaults unless module was selected for customization + useDefaults = !this.modulesToCustomize.has(moduleName); } - if (customize && moduleName !== 'core') { + if (useDefaults && moduleName !== 'core') { // Accept defaults - only ask questions that have NO default value const questionsWithoutDefaults = questions.filter((q) => q.default === undefined || q.default === null || q.default === ''); @@ -726,16 +893,18 @@ class ConfigCollector { const actualConfigKeys = configKeys.filter((key) => !metadataFields.has(key)); const hasNoConfig = actualConfigKeys.length === 0; - if (hasNoConfig && (moduleConfig.subheader || moduleConfig.header)) { - await prompts.log.step(moduleDisplayName); - if (moduleConfig.subheader) { - await prompts.log.message(` \u2713 ${moduleConfig.subheader}`); + if (!this._silentConfig) { + if (hasNoConfig && (moduleConfig.subheader || moduleConfig.header)) { + await prompts.log.step(moduleDisplayName); + if (moduleConfig.subheader) { + await prompts.log.message(` \u2713 ${moduleConfig.subheader}`); + } else { + await prompts.log.message(` \u2713 No custom configuration required`); + } } else { - await prompts.log.message(` \u2713 No custom configuration required`); + // Module has config but just no questions to ask + await prompts.log.message(` \u2713 ${moduleName.toUpperCase()} module configured`); } - } else { - // Module has config but just no questions to ask - await prompts.log.message(` \u2713 ${moduleName.toUpperCase()} module configured`); } } @@ -763,6 +932,8 @@ class ConfigCollector { } } } + + await this.displayModulePostConfigNotes(moduleName, moduleConfig); } /** @@ -1035,6 +1206,58 @@ class ConfigCollector { return question; } + /** + * Display post-configuration notes for a module + * Shows prerequisite guidance based on collected config values + * Reads notes from the module's `post-install-notes` section in module.yaml + * Supports two formats: + * - Simple string: always displayed + * - Object keyed by config field name, with value-specific messages + * @param {string} moduleName - Module name + * @param {Object} moduleConfig - Parsed module.yaml content + */ + async displayModulePostConfigNotes(moduleName, moduleConfig) { + if (this._silentConfig) return; + if (!moduleConfig || !moduleConfig['post-install-notes']) return; + + const notes = moduleConfig['post-install-notes']; + const color = await prompts.getColor(); + + // Format 1: Simple string - always display + if (typeof notes === 'string') { + await prompts.log.message(''); + for (const line of notes.trim().split('\n')) { + await prompts.log.message(color.dim(line)); + } + return; + } + + // Format 2: Conditional on config values + if (typeof notes === 'object') { + const config = this.collectedConfig[moduleName]; + if (!config) return; + + let hasOutput = false; + for (const [configKey, valueMessages] of Object.entries(notes)) { + const selectedValue = config[configKey]; + if (!selectedValue || !valueMessages[selectedValue]) continue; + + if (hasOutput) await prompts.log.message(''); + hasOutput = true; + + const message = valueMessages[selectedValue]; + for (const line of message.trim().split('\n')) { + const trimmedLine = line.trim(); + if (trimmedLine.endsWith(':') && !trimmedLine.startsWith(' ')) { + await prompts.log.info(color.bold(trimmedLine)); + } else { + await prompts.log.message(color.dim(' ' + trimmedLine)); + } + } + } + } + } + /** * Deep merge two objects * @param {Object} target - Target object diff --git a/tools/cli/installers/lib/core/custom-module-cache.js b/tools/cli/installers/lib/core/custom-module-cache.js index 4486e5fe5..b1cc3d0f7 100644 --- a/tools/cli/installers/lib/core/custom-module-cache.js +++ b/tools/cli/installers/lib/core/custom-module-cache.js @@ -7,6 +7,7 @@ const fs = require('fs-extra'); const path = require('node:path'); const crypto = require('node:crypto'); +const prompts = require('../../../lib/prompts'); class CustomModuleCache { constructor(bmadDir) { @@ -195,7 +196,7 @@ class CustomModuleCache { // Verify cache integrity const currentCacheHash = await this.calculateHash(cacheDir); if (currentCacheHash !== cached.cacheHash) { - console.warn(`Warning: Cache integrity check failed for ${moduleId}`); + await prompts.log.warn(`Cache integrity check failed for ${moduleId}`); } return { diff --git a/tools/cli/installers/lib/core/ide-config-manager.js b/tools/cli/installers/lib/core/ide-config-manager.js index f871e4b5d..c00c00d48 100644 --- a/tools/cli/installers/lib/core/ide-config-manager.js +++ b/tools/cli/installers/lib/core/ide-config-manager.js @@ -1,6 +1,7 @@ const path = require('node:path'); const fs = require('fs-extra'); const yaml = require('yaml'); +const prompts = require('../../../lib/prompts'); /** * Manages IDE configuration persistence @@ -93,7 +94,7 @@ class IdeConfigManager { const config = yaml.parse(content); return config; } catch (error) { - console.warn(`Warning: Failed to load IDE config for ${ideName}:`, error.message); + await prompts.log.warn(`Failed to load IDE config for ${ideName}: ${error.message}`); return null; } } @@ -123,7 +124,7 @@ class IdeConfigManager { } } } catch (error) { - console.warn('Warning: Failed to load IDE configs:', error.message); + await prompts.log.warn(`Failed to load IDE configs: ${error.message}`); } return configs; diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index c25b76748..fe8b88d7c 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -109,9 +109,17 @@ class Installer { * @param {boolean} isFullReinstall - Whether this is a full reinstall * @param {Array} previousIdes - Previously configured IDEs (for reinstalls) * @param {Array} preSelectedIdes - Pre-selected IDEs from early prompt (optional) + * @param {boolean} skipPrompts - Skip prompts and use defaults (for --yes flag) * @returns {Object} Tool/IDE selection and configurations */ - async collectToolConfigurations(projectDir, selectedModules, isFullReinstall = false, previousIdes = [], preSelectedIdes = null) { + async collectToolConfigurations( + projectDir, + selectedModules, + isFullReinstall = false, + previousIdes = [], + preSelectedIdes = null, + skipPrompts = false, + ) { // Use pre-selected IDEs if provided, otherwise prompt let toolConfig; if (preSelectedIdes === null) { @@ -182,6 +190,7 @@ class Installer { selectedModules: selectedModules || [], projectDir, bmadDir, + skipPrompts, }); } else { // Config-driven IDEs don't need configuration - mark as ready @@ -406,6 +415,9 @@ class Installer { let action = null; if (config.actionType === 'update') { action = 'update'; + } else if (config.skipPrompts) { + // Non-interactive mode: default to update + action = 'update'; } else { // Fallback: Ask the user (backwards compatibility for other code paths) await prompts.log.warn('Existing BMAD installation detected'); @@ -431,48 +443,56 @@ class Installer { // If there are modules to remove, ask for confirmation if (modulesToRemove.length > 0) { - const prompts = require('../../../lib/prompts'); - if (spinner.isSpinning) { - spinner.stop('Reviewing module changes'); - } - - await prompts.log.warn('Modules to be removed:'); - for (const moduleId of modulesToRemove) { - const moduleInfo = existingInstall.modules.find((m) => m.id === moduleId); - const displayName = moduleInfo?.name || moduleId; - const modulePath = path.join(bmadDir, moduleId); - await prompts.log.error(` - ${displayName} (${modulePath})`); - } - - const confirmRemoval = await prompts.confirm({ - message: `Remove ${modulesToRemove.length} module(s) from BMAD installation?`, - default: false, - }); - - if (confirmRemoval) { - // Remove module folders - for (const moduleId of modulesToRemove) { - const modulePath = path.join(bmadDir, moduleId); - try { - if (await fs.pathExists(modulePath)) { - await fs.remove(modulePath); - await prompts.log.message(` Removed: ${moduleId}`); - } - } catch (error) { - await prompts.log.warn(` Warning: Failed to remove ${moduleId}: ${error.message}`); - } - } - await prompts.log.success(` Removed ${modulesToRemove.length} module(s)`); - } else { - await prompts.log.message(' Module removal cancelled'); - // Add the modules back to the selection since user cancelled removal + if (config.skipPrompts) { + // Non-interactive mode: preserve modules (matches prompt default: false) for (const moduleId of modulesToRemove) { if (!config.modules) config.modules = []; config.modules.push(moduleId); } - } + spinner.start('Preparing update...'); + } else { + if (spinner.isSpinning) { + spinner.stop('Module changes reviewed'); + } - spinner.start('Preparing update...'); + await prompts.log.warn('Modules to be removed:'); + for (const moduleId of modulesToRemove) { + const moduleInfo = existingInstall.modules.find((m) => m.id === moduleId); + const displayName = moduleInfo?.name || moduleId; + const modulePath = path.join(bmadDir, moduleId); + await prompts.log.error(` - ${displayName} (${modulePath})`); + } + + const confirmRemoval = await prompts.confirm({ + message: `Remove ${modulesToRemove.length} module(s) from BMAD installation?`, + default: false, + }); + + if (confirmRemoval) { + // Remove module folders + for (const moduleId of modulesToRemove) { + const modulePath = path.join(bmadDir, moduleId); + try { + if (await fs.pathExists(modulePath)) { + await fs.remove(modulePath); + await prompts.log.message(` Removed: ${moduleId}`); + } + } catch (error) { + await prompts.log.warn(` Warning: Failed to remove ${moduleId}: ${error.message}`); + } + } + await prompts.log.success(` Removed ${modulesToRemove.length} module(s)`); + } else { + await prompts.log.message(' Module removal cancelled'); + // Add the modules back to the selection since user cancelled removal + for (const moduleId of modulesToRemove) { + if (!config.modules) config.modules = []; + config.modules.push(moduleId); + } + } + + spinner.start('Preparing update...'); + } } // Detect custom and modified files BEFORE updating (compare current files vs files-manifest.csv) @@ -507,28 +527,30 @@ class Installer { const cachedModules = await fs.readdir(cacheDir, { withFileTypes: true }); for (const cachedModule of cachedModules) { - if (cachedModule.isDirectory()) { - const moduleId = cachedModule.name; + const moduleId = cachedModule.name; + const cachedPath = path.join(cacheDir, moduleId); - // Skip if we already have this module from manifest - if (customModulePaths.has(moduleId)) { - continue; - } + // Skip if path doesn't exist (broken symlink, deleted dir) - avoids lstat ENOENT + if (!(await fs.pathExists(cachedPath)) || !cachedModule.isDirectory()) { + continue; + } - // Check if this is an external official module - skip cache for those - const isExternal = await this.moduleManager.isExternalModule(moduleId); - if (isExternal) { - // External modules are handled via cloneExternalModule, not from cache - continue; - } + // Skip if we already have this module from manifest + if (customModulePaths.has(moduleId)) { + continue; + } - const cachedPath = path.join(cacheDir, moduleId); + // Check if this is an external official module - skip cache for those + const isExternal = await this.moduleManager.isExternalModule(moduleId); + if (isExternal) { + // External modules are handled via cloneExternalModule, not from cache + continue; + } - // Check if this is actually a custom module (has module.yaml) - const moduleYamlPath = path.join(cachedPath, 'module.yaml'); - if (await fs.pathExists(moduleYamlPath)) { - customModulePaths.set(moduleId, cachedPath); - } + // Check if this is actually a custom module (has module.yaml) + const moduleYamlPath = path.join(cachedPath, 'module.yaml'); + if (await fs.pathExists(moduleYamlPath)) { + customModulePaths.set(moduleId, cachedPath); } } @@ -589,28 +611,30 @@ class Installer { const cachedModules = await fs.readdir(cacheDir, { withFileTypes: true }); for (const cachedModule of cachedModules) { - if (cachedModule.isDirectory()) { - const moduleId = cachedModule.name; + const moduleId = cachedModule.name; + const cachedPath = path.join(cacheDir, moduleId); - // Skip if we already have this module from manifest - if (customModulePaths.has(moduleId)) { - continue; - } + // Skip if path doesn't exist (broken symlink, deleted dir) - avoids lstat ENOENT + if (!(await fs.pathExists(cachedPath)) || !cachedModule.isDirectory()) { + continue; + } - // Check if this is an external official module - skip cache for those - const isExternal = await this.moduleManager.isExternalModule(moduleId); - if (isExternal) { - // External modules are handled via cloneExternalModule, not from cache - continue; - } + // Skip if we already have this module from manifest + if (customModulePaths.has(moduleId)) { + continue; + } - const cachedPath = path.join(cacheDir, moduleId); + // Check if this is an external official module - skip cache for those + const isExternal = await this.moduleManager.isExternalModule(moduleId); + if (isExternal) { + // External modules are handled via cloneExternalModule, not from cache + continue; + } - // Check if this is actually a custom module (has module.yaml) - const moduleYamlPath = path.join(cachedPath, 'module.yaml'); - if (await fs.pathExists(moduleYamlPath)) { - customModulePaths.set(moduleId, cachedPath); - } + // Check if this is actually a custom module (has module.yaml) + const moduleYamlPath = path.join(cachedPath, 'module.yaml'); + if (await fs.pathExists(moduleYamlPath)) { + customModulePaths.set(moduleId, cachedPath); } } @@ -684,6 +708,7 @@ class Installer { config._isFullReinstall || false, config._previouslyConfiguredIdes || [], preSelectedIdes, + config.skipPrompts || false, ); } @@ -692,14 +717,80 @@ class Installer { config.skipIde = toolSelection.skipIde; const ideConfigurations = toolSelection.configurations; + // 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 || []); + const newlySelectedIdes = new Set(config.ides || []); + + const idesToRemove = [...previouslyInstalledIdes].filter((ide) => !newlySelectedIdes.has(ide)); + + if (idesToRemove.length > 0) { + if (config.skipPrompts) { + // Non-interactive mode: silently preserve existing IDE configs + if (!config.ides) config.ides = []; + const savedIdeConfigs = await this.ideConfigManager.loadAllIdeConfigs(bmadDir); + for (const ide of idesToRemove) { + config.ides.push(ide); + if (savedIdeConfigs[ide] && !ideConfigurations[ide]) { + ideConfigurations[ide] = savedIdeConfigs[ide]; + } + } + } else { + if (spinner.isSpinning) { + spinner.stop('IDE changes reviewed'); + } + + await prompts.log.warn('IDEs to be removed:'); + for (const ide of idesToRemove) { + await prompts.log.error(` - ${ide}`); + } + + const confirmRemoval = await prompts.confirm({ + message: `Remove BMAD configuration for ${idesToRemove.length} IDE(s)?`, + default: false, + }); + + if (confirmRemoval) { + await this.ideManager.ensureInitialized(); + for (const ide of idesToRemove) { + try { + const handler = this.ideManager.handlers.get(ide); + if (handler) { + await handler.cleanup(projectDir); + } + await this.ideConfigManager.deleteIdeConfig(bmadDir, ide); + await prompts.log.message(` Removed: ${ide}`); + } catch (error) { + await prompts.log.warn(` Warning: Failed to remove ${ide}: ${error.message}`); + } + } + await prompts.log.success(` Removed ${idesToRemove.length} IDE(s)`); + } else { + await prompts.log.message(' IDE removal cancelled'); + // Add IDEs back to selection and restore their saved configurations + if (!config.ides) config.ides = []; + const savedIdeConfigs = await this.ideConfigManager.loadAllIdeConfigs(bmadDir); + for (const ide of idesToRemove) { + config.ides.push(ide); + if (savedIdeConfigs[ide] && !ideConfigurations[ide]) { + ideConfigurations[ide] = savedIdeConfigs[ide]; + } + } + } + + spinner.start('Preparing installation...'); + } + } + } + // Results collector for consolidated summary const results = []; const addResult = (step, status, detail = '') => results.push({ step, status, detail }); if (spinner.isSpinning) { - spinner.message('Installing...'); + spinner.message('Preparing installation...'); } else { - spinner.start('Installing...'); + spinner.start('Preparing installation...'); } // Create bmad directory structure @@ -728,20 +819,10 @@ class Installer { const projectRoot = getProjectRoot(); - // Step 1: Install core module first (if requested) - if (config.installCore) { - spinner.message('Installing BMAD core...'); - await this.installCoreWithDependencies(bmadDir, { core: {} }); - addResult('Core', 'ok', 'installed'); - - // Generate core config file - await this.generateModuleConfigs(bmadDir, { core: config.coreConfig || {} }); - } - // Custom content is already handled in UI before module selection - let finalCustomContent = config.customContent; + const finalCustomContent = config.customContent; - // Step 3: Prepare modules list including cached custom modules + // Prepare modules list including cached custom modules let allModules = [...(config.modules || [])]; // During quick update, we might have custom module sources from the manifest @@ -780,8 +861,6 @@ class Installer { allModules = allModules.filter((m) => m !== 'core'); } - const modulesToInstall = allModules; - // For dependency resolution, we only need regular modules (not custom modules) // Custom modules are already installed in _bmad and don't need dependency resolution from source const regularModulesForResolution = allModules.filter((module) => { @@ -796,365 +875,439 @@ class Installer { return !isCustom; }); - // For dependency resolution, we need to pass the project root - // Create a temporary module manager that knows about custom content locations - const tempModuleManager = new ModuleManager({ - bmadDir: bmadDir, // Pass bmadDir so we can check cache + // Stop spinner before tasks() takes over progress display + spinner.stop('Preparation complete'); + + // ───────────────────────────────────────────────────────────────────────── + // FIRST TASKS BLOCK: Core installation through manifests (non-interactive) + // ───────────────────────────────────────────────────────────────────────── + const isQuickUpdate = config._quickUpdate || false; + + // Shared resolution result across task callbacks (closure-scoped, not on `this`) + let taskResolution; + + // Collect directory creation results for output after tasks() completes + const dirResults = { createdDirs: [], movedDirs: [], createdWdsFolders: [] }; + + // Build task list conditionally + const installTasks = []; + + // Core installation task + if (config.installCore) { + installTasks.push({ + title: isQuickUpdate ? 'Updating BMAD core' : 'Installing BMAD core', + task: async (message) => { + await this.installCoreWithDependencies(bmadDir, { core: {} }); + addResult('Core', 'ok', isQuickUpdate ? 'updated' : 'installed'); + await this.generateModuleConfigs(bmadDir, { core: config.coreConfig || {} }); + return isQuickUpdate ? 'Core updated' : 'Core installed'; + }, + }); + } + + // Dependency resolution task + installTasks.push({ + title: 'Resolving dependencies', + task: async (message) => { + // Create a temporary module manager that knows about custom content locations + const tempModuleManager = new ModuleManager({ + bmadDir: bmadDir, + }); + + taskResolution = await this.dependencyResolver.resolve(projectRoot, regularModulesForResolution, { + verbose: config.verbose, + moduleManager: tempModuleManager, + }); + return 'Dependencies resolved'; + }, }); - spinner.message('Resolving dependencies...'); - - const resolution = await this.dependencyResolver.resolve(projectRoot, regularModulesForResolution, { - verbose: config.verbose, - moduleManager: tempModuleManager, - }); - - // Install modules with their dependencies + // Module installation task if (allModules && allModules.length > 0) { - const installedModuleNames = new Set(); + installTasks.push({ + title: isQuickUpdate ? `Updating ${allModules.length} module(s)` : `Installing ${allModules.length} module(s)`, + task: async (message) => { + const resolution = taskResolution; + const installedModuleNames = new Set(); - for (const moduleName of allModules) { - // Skip if already installed - if (installedModuleNames.has(moduleName)) { - continue; - } - installedModuleNames.add(moduleName); + for (const moduleName of allModules) { + if (installedModuleNames.has(moduleName)) continue; + installedModuleNames.add(moduleName); - // Show appropriate message based on whether this is a quick update - const isQuickUpdate = config._quickUpdate || false; - spinner.message(`${isQuickUpdate ? 'Updating' : 'Installing'} module: ${moduleName}...`); + message(`${isQuickUpdate ? 'Updating' : 'Installing'} ${moduleName}...`); - // Check if this is a custom module - let isCustomModule = false; - let customInfo = null; - let useCache = false; + // Check if this is a custom module + let isCustomModule = false; + let customInfo = null; - // First check if we have a cached version - if (finalCustomContent && finalCustomContent.cachedModules) { - const cachedModule = finalCustomContent.cachedModules.find((m) => m.id === moduleName); - if (cachedModule) { - isCustomModule = true; - customInfo = { - id: moduleName, - path: cachedModule.cachePath, - config: {}, - }; - useCache = true; - } - } - - // Then check if we have custom module sources from the manifest (for quick update) - if (!isCustomModule && config._customModuleSources && config._customModuleSources.has(moduleName)) { - customInfo = config._customModuleSources.get(moduleName); - isCustomModule = true; - - // Check if this is a cached module (source path starts with _config) - if ( - customInfo.sourcePath && - (customInfo.sourcePath.startsWith('_config') || customInfo.sourcePath.includes('_config/custom')) - ) { - useCache = true; - // Make sure we have the right path structure - if (!customInfo.path) { - customInfo.path = customInfo.sourcePath; + // First check if we have a cached version + if (finalCustomContent && finalCustomContent.cachedModules) { + const cachedModule = finalCustomContent.cachedModules.find((m) => m.id === moduleName); + if (cachedModule) { + isCustomModule = true; + customInfo = { id: moduleName, path: cachedModule.cachePath, config: {} }; + } } - } - } - // Finally check regular custom content - if (!isCustomModule && finalCustomContent && finalCustomContent.selected && finalCustomContent.selectedFiles) { - const customHandler = new CustomHandler(); - for (const customFile of finalCustomContent.selectedFiles) { - const info = await customHandler.getCustomInfo(customFile, projectDir); - if (info && info.id === moduleName) { + // Then check custom module sources from manifest (for quick update) + if (!isCustomModule && config._customModuleSources && config._customModuleSources.has(moduleName)) { + customInfo = config._customModuleSources.get(moduleName); isCustomModule = true; - customInfo = info; - break; + if (customInfo.sourcePath && !customInfo.path) { + customInfo.path = path.isAbsolute(customInfo.sourcePath) + ? customInfo.sourcePath + : path.join(bmadDir, customInfo.sourcePath); + } + } + + // Finally check regular custom content + if (!isCustomModule && finalCustomContent && finalCustomContent.selected && finalCustomContent.selectedFiles) { + const customHandler = new CustomHandler(); + for (const customFile of finalCustomContent.selectedFiles) { + const info = await customHandler.getCustomInfo(customFile, projectDir); + if (info && info.id === moduleName) { + isCustomModule = true; + customInfo = info; + break; + } + } + } + + if (isCustomModule && customInfo) { + if (!customModulePaths.has(moduleName) && customInfo.path) { + customModulePaths.set(moduleName, customInfo.path); + this.moduleManager.setCustomModulePaths(customModulePaths); + } + + const collectedModuleConfig = moduleConfigs[moduleName] || {}; + await this.moduleManager.install( + moduleName, + bmadDir, + (filePath) => { + this.installedFiles.add(filePath); + }, + { + isCustom: true, + moduleConfig: collectedModuleConfig, + isQuickUpdate: isQuickUpdate, + installer: this, + silent: true, + }, + ); + await this.generateModuleConfigs(bmadDir, { + [moduleName]: { ...config.coreConfig, ...customInfo.config, ...collectedModuleConfig }, + }); + } else { + if (!resolution || !resolution.byModule) { + addResult(`Module: ${moduleName}`, 'warn', 'skipped (no resolution data)'); + continue; + } + if (moduleName === 'core') { + await this.installCoreWithDependencies(bmadDir, resolution.byModule[moduleName]); + } else { + await this.installModuleWithDependencies(moduleName, bmadDir, resolution.byModule[moduleName]); + } + } + + addResult(`Module: ${moduleName}`, 'ok', isQuickUpdate ? 'updated' : 'installed'); + } + + // Install partial modules (only dependencies) + if (!resolution || !resolution.byModule) { + return `${allModules.length} module(s) ${isQuickUpdate ? 'updated' : 'installed'}`; + } + for (const [module, files] of Object.entries(resolution.byModule)) { + if (!allModules.includes(module) && module !== 'core') { + const totalFiles = + files.agents.length + + files.tasks.length + + files.tools.length + + files.templates.length + + files.data.length + + files.other.length; + if (totalFiles > 0) { + message(`Installing ${module} dependencies...`); + await this.installPartialModule(module, bmadDir, files); + } + } + } + + return `${allModules.length} module(s) ${isQuickUpdate ? 'updated' : 'installed'}`; + }, + }); + } + + // Module directory creation task + installTasks.push({ + title: 'Creating module directories', + task: async (message) => { + const resolution = taskResolution; + if (!resolution || !resolution.byModule) { + addResult('Module directories', 'warn', 'no resolution data'); + return 'Module directories skipped (no resolution data)'; + } + const verboseMode = process.env.BMAD_VERBOSE_INSTALL === 'true' || config.verbose; + const moduleLogger = { + log: async (msg) => (verboseMode ? await prompts.log.message(msg) : undefined), + error: async (msg) => await prompts.log.error(msg), + warn: async (msg) => await prompts.log.warn(msg), + }; + + // Core module directories + if (config.installCore || resolution.byModule.core) { + const result = await this.moduleManager.createModuleDirectories('core', bmadDir, { + installedIDEs: config.ides || [], + moduleConfig: moduleConfigs.core || {}, + existingModuleConfig: this.configCollector.existingConfig?.core || {}, + coreConfig: moduleConfigs.core || {}, + logger: moduleLogger, + silent: true, + }); + if (result) { + dirResults.createdDirs.push(...result.createdDirs); + dirResults.movedDirs.push(...(result.movedDirs || [])); + dirResults.createdWdsFolders.push(...result.createdWdsFolders); + } + } + + // User-selected module directories + if (config.modules && config.modules.length > 0) { + for (const moduleName of config.modules) { + message(`Setting up ${moduleName}...`); + const result = await this.moduleManager.createModuleDirectories(moduleName, bmadDir, { + installedIDEs: config.ides || [], + moduleConfig: moduleConfigs[moduleName] || {}, + existingModuleConfig: this.configCollector.existingConfig?.[moduleName] || {}, + coreConfig: moduleConfigs.core || {}, + logger: moduleLogger, + silent: true, + }); + if (result) { + dirResults.createdDirs.push(...result.createdDirs); + dirResults.movedDirs.push(...(result.movedDirs || [])); + dirResults.createdWdsFolders.push(...result.createdWdsFolders); } } } - if (isCustomModule && customInfo) { - // Custom modules are now installed via ModuleManager just like standard modules - // The custom module path should already be in customModulePaths from earlier setup - if (!customModulePaths.has(moduleName) && customInfo.path) { - customModulePaths.set(moduleName, customInfo.path); - this.moduleManager.setCustomModulePaths(customModulePaths); - } - - const collectedModuleConfig = moduleConfigs[moduleName] || {}; - - // Use ModuleManager to install the custom module - await this.moduleManager.install( - moduleName, - bmadDir, - (filePath) => { - this.installedFiles.add(filePath); - }, - { - isCustom: true, - moduleConfig: collectedModuleConfig, - isQuickUpdate: config._quickUpdate || false, - installer: this, - silent: true, - }, - ); - - // Create module config (include collected config from module.yaml prompts) - await this.generateModuleConfigs(bmadDir, { - [moduleName]: { ...config.coreConfig, ...customInfo.config, ...collectedModuleConfig }, - }); - } else { - // Regular module installation - // Special case for core module - if (moduleName === 'core') { - await this.installCoreWithDependencies(bmadDir, resolution.byModule[moduleName]); - } else { - await this.installModuleWithDependencies(moduleName, bmadDir, resolution.byModule[moduleName]); - } - } - - addResult(`Module: ${moduleName}`, 'ok', isQuickUpdate ? 'updated' : 'installed'); - } - - // Install partial modules (only dependencies) - for (const [module, files] of Object.entries(resolution.byModule)) { - if (!allModules.includes(module) && module !== 'core') { - const totalFiles = - files.agents.length + - files.tasks.length + - files.tools.length + - files.templates.length + - files.data.length + - files.other.length; - if (totalFiles > 0) { - spinner.message(`Installing ${module} dependencies...`); - await this.installPartialModule(module, bmadDir, files); - } - } - } - } - - // All content is now installed as modules - no separate custom content handling needed - - // Generate clean config.yaml files for each installed module - spinner.message('Generating module configurations...'); - await this.generateModuleConfigs(bmadDir, moduleConfigs); - addResult('Configurations', 'ok', 'generated'); - - // Create agent configuration files - // Note: Legacy createAgentConfigs removed - using YAML customize system instead - // Customize templates are now created in processAgentFiles when building YAML agents - - // Pre-register manifest files that will be created (except files-manifest.csv to avoid recursion) - const cfgDir = path.join(bmadDir, '_config'); - this.installedFiles.add(path.join(cfgDir, 'manifest.yaml')); - this.installedFiles.add(path.join(cfgDir, 'workflow-manifest.csv')); - this.installedFiles.add(path.join(cfgDir, 'agent-manifest.csv')); - this.installedFiles.add(path.join(cfgDir, 'task-manifest.csv')); - - // Generate CSV manifests for workflows, agents, tasks AND ALL FILES with hashes BEFORE IDE setup - // This must happen BEFORE mergeModuleHelpCatalogs because it depends on agent-manifest.csv - spinner.message('Generating workflow and agent manifests...'); - const manifestGen = new ManifestGenerator(); - - // For quick update, we need ALL installed modules in the manifest - // Not just the ones being updated - const allModulesForManifest = config._quickUpdate - ? config._existingModules || allModules || [] - : config._preserveModules - ? [...allModules, ...config._preserveModules] - : allModules || []; - - // For regular installs (including when called from quick update), use what we have - let modulesForCsvPreserve; - if (config._quickUpdate) { - // Quick update - use existing modules or fall back to modules being updated - modulesForCsvPreserve = config._existingModules || allModules || []; - } else { - // Regular install - use the modules we're installing plus any preserved ones - modulesForCsvPreserve = config._preserveModules ? [...allModules, ...config._preserveModules] : allModules; - } - - const manifestStats = await manifestGen.generateManifests(bmadDir, allModulesForManifest, [...this.installedFiles], { - ides: config.ides || [], - preservedModules: modulesForCsvPreserve, // Scan these from installed bmad/ dir + addResult('Module directories', 'ok'); + return 'Module directories created'; + }, }); - // Custom modules are now included in the main modules list - no separate tracking needed + // Configuration generation task (stored as named reference for deferred execution) + const configTask = { + title: 'Generating configurations', + task: async (message) => { + // Generate clean config.yaml files for each installed module + await this.generateModuleConfigs(bmadDir, moduleConfigs); + addResult('Configurations', 'ok', 'generated'); - addResult( - 'Manifests', - 'ok', - `${manifestStats.workflows} workflows, ${manifestStats.agents} agents, ${manifestStats.tasks} tasks, ${manifestStats.tools} tools`, - ); + // Pre-register manifest files + const cfgDir = path.join(bmadDir, '_config'); + this.installedFiles.add(path.join(cfgDir, 'manifest.yaml')); + this.installedFiles.add(path.join(cfgDir, 'workflow-manifest.csv')); + this.installedFiles.add(path.join(cfgDir, 'agent-manifest.csv')); + this.installedFiles.add(path.join(cfgDir, 'task-manifest.csv')); - // Merge all module-help.csv files into bmad-help.csv - // This must happen AFTER generateManifests because it depends on agent-manifest.csv - spinner.message('Generating workflow help catalog...'); - await this.mergeModuleHelpCatalogs(bmadDir); - addResult('Help catalog', 'ok'); + // Generate CSV manifests for workflows, agents, tasks AND ALL FILES with hashes + // This must happen BEFORE mergeModuleHelpCatalogs because it depends on agent-manifest.csv + message('Generating manifests...'); + const manifestGen = new ManifestGenerator(); - // Configure IDEs and copy documentation + const allModulesForManifest = config._quickUpdate + ? config._existingModules || allModules || [] + : config._preserveModules + ? [...allModules, ...config._preserveModules] + : allModules || []; + + let modulesForCsvPreserve; + if (config._quickUpdate) { + modulesForCsvPreserve = config._existingModules || allModules || []; + } else { + modulesForCsvPreserve = config._preserveModules ? [...allModules, ...config._preserveModules] : allModules; + } + + const manifestStats = await manifestGen.generateManifests(bmadDir, allModulesForManifest, [...this.installedFiles], { + ides: config.ides || [], + preservedModules: modulesForCsvPreserve, + }); + + addResult( + 'Manifests', + 'ok', + `${manifestStats.workflows} workflows, ${manifestStats.agents} agents, ${manifestStats.tasks} tasks, ${manifestStats.tools} tools`, + ); + + // Merge help catalogs + message('Generating help catalog...'); + await this.mergeModuleHelpCatalogs(bmadDir); + addResult('Help catalog', 'ok'); + + return 'Configurations generated'; + }, + }; + installTasks.push(configTask); + + // Run all tasks except config (which runs after directory output) + const mainTasks = installTasks.filter((t) => t !== configTask); + await prompts.tasks(mainTasks); + + // Render directory creation output right after directory task + const color = await prompts.getColor(); + if (dirResults.movedDirs.length > 0) { + const lines = dirResults.movedDirs.map((d) => ` ${d}`).join('\n'); + await prompts.log.message(color.cyan(`Moved directories:\n${lines}`)); + } + if (dirResults.createdDirs.length > 0) { + const lines = dirResults.createdDirs.map((d) => ` ${d}`).join('\n'); + await prompts.log.message(color.yellow(`Created directories:\n${lines}`)); + } + if (dirResults.createdWdsFolders.length > 0) { + const lines = dirResults.createdWdsFolders.map((f) => color.dim(` \u2713 ${f}/`)).join('\n'); + await prompts.log.message(color.cyan(`Created WDS folder structure:\n${lines}`)); + } + + // Now run configuration generation + await prompts.tasks([configTask]); + + // Resolution is now available via closure-scoped taskResolution + const resolution = taskResolution; + + // ───────────────────────────────────────────────────────────────────────── + // IDE SETUP: Keep as spinner since it may prompt for user input + // ───────────────────────────────────────────────────────────────────────── if (!config.skipIde && config.ides && config.ides.length > 0) { - // Ensure IDE manager is initialized (handlers may not be loaded in quick update flow) await this.ideManager.ensureInitialized(); - - // Filter out any undefined/null values from the IDE list const validIdes = config.ides.filter((ide) => ide && typeof ide === 'string'); if (validIdes.length === 0) { addResult('IDE configuration', 'warn', 'no valid IDEs selected'); } else { - // Check if any IDE might need prompting (no pre-collected config) const needsPrompting = validIdes.some((ide) => !ideConfigurations[ide]); - - // Temporarily suppress console output if not verbose - const originalLog = console.log; - if (!config.verbose) { - console.log = () => {}; - } + const ideSpinner = await prompts.spinner(); + ideSpinner.start('Configuring tools...'); try { for (const ide of validIdes) { if (!needsPrompting || ideConfigurations[ide]) { - // All IDEs pre-configured, or this specific IDE has config: keep spinner running - spinner.message(`Configuring ${ide}...`); + ideSpinner.message(`Configuring ${ide}...`); } else { - // This IDE needs prompting: stop spinner to allow user interaction - if (spinner.isSpinning) { - spinner.stop('Ready for IDE configuration'); + if (ideSpinner.isSpinning) { + ideSpinner.stop('Ready for IDE configuration'); } } - // Silent when this IDE has pre-collected config (no prompts for THIS IDE) + // Suppress stray console output for pre-configured IDEs (no user interaction) const ideHasConfig = Boolean(ideConfigurations[ide]); - const setupResult = await this.ideManager.setup(ide, projectDir, bmadDir, { - selectedModules: allModules || [], - preCollectedConfig: ideConfigurations[ide] || null, - verbose: config.verbose, - silent: ideHasConfig, - }); + const originalLog = console.log; + if (!config.verbose && ideHasConfig) { + console.log = () => {}; + } + try { + const setupResult = await this.ideManager.setup(ide, projectDir, bmadDir, { + selectedModules: allModules || [], + preCollectedConfig: ideConfigurations[ide] || null, + verbose: config.verbose, + silent: ideHasConfig, + }); - // Save IDE configuration for future updates - if (ideConfigurations[ide] && !ideConfigurations[ide]._alreadyConfigured) { - await this.ideConfigManager.saveIdeConfig(bmadDir, ide, ideConfigurations[ide]); + if (ideConfigurations[ide] && !ideConfigurations[ide]._alreadyConfigured) { + await this.ideConfigManager.saveIdeConfig(bmadDir, ide, ideConfigurations[ide]); + } + + if (setupResult.success) { + addResult(ide, 'ok', setupResult.detail || ''); + } else { + addResult(ide, 'error', setupResult.error || 'failed'); + } + } finally { + console.log = originalLog; } - // Collect result for summary - if (setupResult.success) { - addResult(ide, 'ok', setupResult.detail || ''); - } else { - addResult(ide, 'error', setupResult.error || 'failed'); - } - - // Restart spinner if we stopped it for prompting - if (needsPrompting && !spinner.isSpinning) { - spinner.start('Configuring IDEs...'); + if (needsPrompting && !ideSpinner.isSpinning) { + ideSpinner.start('Configuring tools...'); } } } finally { - console.log = originalLog; - } - } - } - - // Run module-specific installers after IDE setup - spinner.message('Running module-specific installers...'); - - // Create a conditional logger based on verbose mode - const verboseMode = process.env.BMAD_VERBOSE_INSTALL === 'true' || config.verbose; - const moduleLogger = { - log: (msg) => (verboseMode ? console.log(msg) : {}), // Only log in verbose mode - error: (msg) => console.error(msg), // Always show errors - warn: (msg) => console.warn(msg), // Always show warnings - }; - - // Create directories for core module if core was installed - if (config.installCore || resolution.byModule.core) { - spinner.message('Creating core module directories...'); - - await this.moduleManager.createModuleDirectories('core', bmadDir, { - installedIDEs: config.ides || [], - moduleConfig: moduleConfigs.core || {}, - coreConfig: moduleConfigs.core || {}, - logger: moduleLogger, - silent: true, - }); - } - - // Create directories for user-selected modules - if (config.modules && config.modules.length > 0) { - for (const moduleName of config.modules) { - spinner.message(`Creating ${moduleName} module directories...`); - - // Pass installed IDEs and module config to directory creator - await this.moduleManager.createModuleDirectories(moduleName, bmadDir, { - installedIDEs: config.ides || [], - moduleConfig: moduleConfigs[moduleName] || {}, - coreConfig: moduleConfigs.core || {}, - logger: moduleLogger, - silent: true, - }); - } - } - - addResult('Module installers', 'ok'); - - // Note: Manifest files are already created by ManifestGenerator above - // No need to create legacy manifest.csv anymore - - // If this was an update, restore custom files - let customFiles = []; - let modifiedFiles = []; - if (config._isUpdate) { - if (config._customFiles && config._customFiles.length > 0) { - spinner.message(`Restoring ${config._customFiles.length} custom files...`); - - for (const originalPath of config._customFiles) { - const relativePath = path.relative(bmadDir, originalPath); - const backupPath = path.join(config._tempBackupDir, relativePath); - - if (await fs.pathExists(backupPath)) { - await fs.ensureDir(path.dirname(originalPath)); - await fs.copy(backupPath, originalPath, { overwrite: true }); + if (ideSpinner.isSpinning) { + ideSpinner.stop('Tool configuration complete'); } } - - // Clean up temp backup - if (config._tempBackupDir && (await fs.pathExists(config._tempBackupDir))) { - await fs.remove(config._tempBackupDir); - } - - customFiles = config._customFiles; } + } - if (config._modifiedFiles && config._modifiedFiles.length > 0) { - modifiedFiles = config._modifiedFiles; + // ───────────────────────────────────────────────────────────────────────── + // SECOND TASKS BLOCK: Post-IDE operations (non-interactive) + // ───────────────────────────────────────────────────────────────────────── + const postIdeTasks = []; - // Restore modified files as .bak files - if (config._tempModifiedBackupDir && (await fs.pathExists(config._tempModifiedBackupDir))) { - spinner.message(`Restoring ${modifiedFiles.length} modified files as .bak...`); + // File restoration task (only for updates) + if ( + config._isUpdate && + ((config._customFiles && config._customFiles.length > 0) || (config._modifiedFiles && config._modifiedFiles.length > 0)) + ) { + postIdeTasks.push({ + title: 'Finalizing installation', + task: async (message) => { + let customFiles = []; + let modifiedFiles = []; - for (const modifiedFile of modifiedFiles) { - const relativePath = path.relative(bmadDir, modifiedFile.path); - const tempBackupPath = path.join(config._tempModifiedBackupDir, relativePath); - const bakPath = modifiedFile.path + '.bak'; + if (config._customFiles && config._customFiles.length > 0) { + message(`Restoring ${config._customFiles.length} custom files...`); - if (await fs.pathExists(tempBackupPath)) { - await fs.ensureDir(path.dirname(bakPath)); - await fs.copy(tempBackupPath, bakPath, { overwrite: true }); + for (const originalPath of config._customFiles) { + const relativePath = path.relative(bmadDir, originalPath); + const backupPath = path.join(config._tempBackupDir, relativePath); + + if (await fs.pathExists(backupPath)) { + await fs.ensureDir(path.dirname(originalPath)); + await fs.copy(backupPath, originalPath, { overwrite: true }); + } + } + + if (config._tempBackupDir && (await fs.pathExists(config._tempBackupDir))) { + await fs.remove(config._tempBackupDir); + } + + customFiles = config._customFiles; + } + + if (config._modifiedFiles && config._modifiedFiles.length > 0) { + modifiedFiles = config._modifiedFiles; + + if (config._tempModifiedBackupDir && (await fs.pathExists(config._tempModifiedBackupDir))) { + message(`Restoring ${modifiedFiles.length} modified files as .bak...`); + + for (const modifiedFile of modifiedFiles) { + const relativePath = path.relative(bmadDir, modifiedFile.path); + const tempBackupPath = path.join(config._tempModifiedBackupDir, relativePath); + const bakPath = modifiedFile.path + '.bak'; + + if (await fs.pathExists(tempBackupPath)) { + await fs.ensureDir(path.dirname(bakPath)); + await fs.copy(tempBackupPath, bakPath, { overwrite: true }); + } + } + + await fs.remove(config._tempModifiedBackupDir); } } - // Clean up temp backup - await fs.remove(config._tempModifiedBackupDir); - } - } + // Store for summary access + config._restoredCustomFiles = customFiles; + config._restoredModifiedFiles = modifiedFiles; + + return 'Installation finalized'; + }, + }); } - // Stop the single installation spinner - spinner.stop('Installation complete'); + await prompts.tasks(postIdeTasks); + + // Retrieve restored file info for summary + const customFiles = config._restoredCustomFiles || []; + const modifiedFiles = config._restoredModifiedFiles || []; // Render consolidated summary await this.renderInstallSummary(results, { @@ -1173,7 +1326,15 @@ class Installer { projectDir: projectDir, }; } catch (error) { - spinner.error('Installation failed'); + try { + if (spinner.isSpinning) { + spinner.error('Installation failed'); + } else { + await prompts.log.error('Installation failed'); + } + } catch { + // Ensure the original error is never swallowed by a logging failure + } throw error; } } @@ -1213,6 +1374,17 @@ class Installer { lines.push(` ${color.yellow(`Modified files backed up (.bak): ${context.modifiedFiles.length}`)}`); } + // Next steps + lines.push( + '', + ' Next steps:', + ` Read our new Docs Site: ${color.dim('https://docs.bmad-method.org/')}`, + ` Join our Discord: ${color.dim('https://discord.gg/gk8jAdXWmj')}`, + ` Star us on GitHub: ${color.dim('https://github.com/bmad-code-org/BMAD-METHOD/')}`, + ` Subscribe on YouTube: ${color.dim('https://www.youtube.com/@BMadCode')}`, + ` Run ${color.cyan('/bmad-help')} with your IDE Agent and ask it how to get started`, + ); + await prompts.note(lines.join('\n'), 'BMAD is ready to use!'); } @@ -1297,6 +1469,7 @@ class Installer { projectRoot, 'update', existingInstall.modules.map((m) => m.id), + config.skipPrompts || false, ); spinner.start('Preparing update...'); @@ -1361,20 +1534,157 @@ class Installer { } /** - * Uninstall BMAD + * Uninstall BMAD with selective removal options + * @param {string} directory - Project directory + * @param {Object} options - Uninstall options + * @param {boolean} [options.removeModules=true] - Remove _bmad/ directory + * @param {boolean} [options.removeIdeConfigs=true] - Remove IDE configurations + * @param {boolean} [options.removeOutputFolder=false] - Remove user artifacts output folder + * @returns {Object} Result with success status and removed components */ - async uninstall(directory) { + async uninstall(directory, options = {}) { const projectDir = path.resolve(directory); const { bmadDir } = await this.findBmadDir(projectDir); - if (await fs.pathExists(bmadDir)) { - await fs.remove(bmadDir); + if (!(await fs.pathExists(bmadDir))) { + return { success: false, reason: 'not-installed' }; } - // Clean up IDE configurations - await this.ideManager.cleanup(projectDir); + // 1. DETECT: Read state BEFORE deleting anything + const existingInstall = await this.detector.detect(bmadDir); + const outputFolder = await this._readOutputFolder(bmadDir); - return { success: true }; + const removed = { modules: false, ideConfigs: false, outputFolder: false }; + + // 2. IDE CLEANUP (before _bmad/ deletion so configs are accessible) + if (options.removeIdeConfigs !== false) { + await this.uninstallIdeConfigs(projectDir, existingInstall, { silent: options.silent }); + removed.ideConfigs = true; + } + + // 3. OUTPUT FOLDER (only if explicitly requested) + if (options.removeOutputFolder === true && outputFolder) { + removed.outputFolder = await this.uninstallOutputFolder(projectDir, outputFolder); + } + + // 4. BMAD DIRECTORY (last, after everything that needs it) + if (options.removeModules !== false) { + removed.modules = await this.uninstallModules(projectDir); + } + + return { success: true, removed, version: existingInstall.version }; + } + + /** + * Uninstall IDE configurations only + * @param {string} projectDir - Project directory + * @param {Object} existingInstall - Detection result from detector.detect() + * @param {Object} [options] - Options (e.g. { silent: true }) + * @returns {Promise} Results from IDE cleanup + */ + async uninstallIdeConfigs(projectDir, existingInstall, options = {}) { + await this.ideManager.ensureInitialized(); + const cleanupOptions = { isUninstall: true, silent: options.silent }; + const ideList = existingInstall.ides || []; + if (ideList.length > 0) { + return this.ideManager.cleanupByList(projectDir, ideList, cleanupOptions); + } + return this.ideManager.cleanup(projectDir, cleanupOptions); + } + + /** + * Remove user artifacts output folder + * @param {string} projectDir - Project directory + * @param {string} outputFolder - Output folder name (relative) + * @returns {Promise} Whether the folder was removed + */ + async uninstallOutputFolder(projectDir, outputFolder) { + if (!outputFolder) return false; + const resolvedProject = path.resolve(projectDir); + const outputPath = path.resolve(resolvedProject, outputFolder); + if (!outputPath.startsWith(resolvedProject + path.sep)) { + return false; + } + if (await fs.pathExists(outputPath)) { + await fs.remove(outputPath); + return true; + } + return false; + } + + /** + * Remove the _bmad/ directory + * @param {string} projectDir - Project directory + * @returns {Promise} Whether the directory was removed + */ + async uninstallModules(projectDir) { + const { bmadDir } = await this.findBmadDir(projectDir); + if (await fs.pathExists(bmadDir)) { + await fs.remove(bmadDir); + return true; + } + return false; + } + + /** + * Get the configured output folder name for a project + * Resolves bmadDir internally from projectDir + * @param {string} projectDir - Project directory + * @returns {string} Output folder name (relative, default: '_bmad-output') + */ + async getOutputFolder(projectDir) { + const { bmadDir } = await this.findBmadDir(projectDir); + return this._readOutputFolder(bmadDir); + } + + /** + * Read the output_folder setting from module config files + * Checks bmm/config.yaml first, then other module configs + * @param {string} bmadDir - BMAD installation directory + * @returns {string} Output folder path or default + */ + async _readOutputFolder(bmadDir) { + const yaml = require('yaml'); + + // Check bmm/config.yaml first (most common) + const bmmConfigPath = path.join(bmadDir, 'bmm', 'config.yaml'); + if (await fs.pathExists(bmmConfigPath)) { + try { + const content = await fs.readFile(bmmConfigPath, 'utf8'); + const config = yaml.parse(content); + if (config && config.output_folder) { + // Strip {project-root}/ prefix if present + return config.output_folder.replace(/^\{project-root\}[/\\]/, ''); + } + } catch { + // Fall through to other modules + } + } + + // Scan other module config.yaml files + try { + const entries = await fs.readdir(bmadDir, { withFileTypes: true }); + for (const entry of entries) { + if (!entry.isDirectory() || entry.name === 'bmm' || entry.name.startsWith('_')) continue; + const configPath = path.join(bmadDir, entry.name, 'config.yaml'); + if (await fs.pathExists(configPath)) { + try { + const content = await fs.readFile(configPath, 'utf8'); + const config = yaml.parse(content); + if (config && config.output_folder) { + return config.output_folder.replace(/^\{project-root\}[/\\]/, ''); + } + } catch { + // Continue scanning + } + } + } + } catch { + // Directory scan failed + } + + // Default fallback + return '_bmad-output'; } /** @@ -2069,41 +2379,58 @@ class Installer { const configuredIdes = existingInstall.ides || []; const projectRoot = path.dirname(bmadDir); - // Get custom module sources from cache + // Get custom module sources: first from --custom-content (re-cache from source), then from cache const customModuleSources = new Map(); + if (config.customContent?.sources?.length > 0) { + for (const source of config.customContent.sources) { + if (source.id && source.path && (await fs.pathExists(source.path))) { + customModuleSources.set(source.id, { + id: source.id, + name: source.name || source.id, + sourcePath: source.path, + cached: false, // From CLI, will be re-cached + }); + } + } + } const cacheDir = path.join(bmadDir, '_config', 'custom'); if (await fs.pathExists(cacheDir)) { const cachedModules = await fs.readdir(cacheDir, { withFileTypes: true }); for (const cachedModule of cachedModules) { - if (cachedModule.isDirectory()) { - const moduleId = cachedModule.name; + const moduleId = cachedModule.name; + const cachedPath = path.join(cacheDir, moduleId); - // Skip if we already have this module from manifest - if (customModuleSources.has(moduleId)) { - continue; - } + // Skip if path doesn't exist (broken symlink, deleted dir) - avoids lstat ENOENT + if (!(await fs.pathExists(cachedPath))) { + continue; + } + if (!cachedModule.isDirectory()) { + continue; + } - // Check if this is an external official module - skip cache for those - const isExternal = await this.moduleManager.isExternalModule(moduleId); - if (isExternal) { - // External modules are handled via cloneExternalModule, not from cache - continue; - } + // Skip if we already have this module from manifest + if (customModuleSources.has(moduleId)) { + continue; + } - const cachedPath = path.join(cacheDir, moduleId); + // Check if this is an external official module - skip cache for those + const isExternal = await this.moduleManager.isExternalModule(moduleId); + if (isExternal) { + // External modules are handled via cloneExternalModule, not from cache + continue; + } - // Check if this is actually a custom module (has module.yaml) - const moduleYamlPath = path.join(cachedPath, 'module.yaml'); - if (await fs.pathExists(moduleYamlPath)) { - // For quick update, we always rebuild from cache - customModuleSources.set(moduleId, { - id: moduleId, - name: moduleId, // We'll read the actual name if needed - sourcePath: cachedPath, - cached: true, // Flag to indicate this is from cache - }); - } + // Check if this is actually a custom module (has module.yaml) + const moduleYamlPath = path.join(cachedPath, 'module.yaml'); + if (await fs.pathExists(moduleYamlPath)) { + // For quick update, we always rebuild from cache + customModuleSources.set(moduleId, { + id: moduleId, + name: moduleId, // We'll read the actual name if needed + sourcePath: cachedPath, + cached: true, // Flag to indicate this is from cache + }); } } } @@ -2160,6 +2487,7 @@ class Installer { projectRoot, 'update', installedModules, + config.skipPrompts || false, ); const { validCustomModules, keptModulesWithoutSources } = customModuleResult; @@ -2239,6 +2567,7 @@ class Installer { _savedIdeConfigs: savedIdeConfigs, // Pass saved IDE configs to installer _customModuleSources: customModuleSources, // Pass custom module sources for updates _existingModules: installedModules, // Pass all installed modules for manifest generation + customContent: config.customContent, // Pass through for re-caching from source }; // Call the standard install method @@ -2417,7 +2746,9 @@ class Installer { if (proceed === 'exit') { await prompts.log.info('Please remove the .bmad-method folder and any v4 rules/commands, then run the installer again.'); - process.exit(0); + // Allow event loop to flush pending I/O before exit + setImmediate(() => process.exit(0)); + return; } await prompts.log.warn('Proceeding with installation despite legacy v4 folder'); @@ -2601,9 +2932,10 @@ class Installer { * @param {string} projectRoot - Project root directory * @param {string} operation - Current operation ('update', 'compile', etc.) * @param {Array} installedModules - Array of installed module IDs (will be modified) + * @param {boolean} [skipPrompts=false] - Skip interactive prompts and keep all modules with missing sources * @returns {Object} Object with validCustomModules array and keptModulesWithoutSources array */ - async handleMissingCustomSources(customModuleSources, bmadDir, projectRoot, operation, installedModules) { + async handleMissingCustomSources(customModuleSources, bmadDir, projectRoot, operation, installedModules, skipPrompts = false) { const validCustomModules = []; const keptModulesWithoutSources = []; // Track modules kept without sources const customModulesWithMissingSources = []; @@ -2646,6 +2978,14 @@ class Installer { }; } + // Non-interactive mode: keep all modules with missing sources + if (skipPrompts) { + for (const missing of customModulesWithMissingSources) { + keptModulesWithoutSources.push(missing.id); + } + return { validCustomModules, keptModulesWithoutSources }; + } + await prompts.log.warn(`Found ${customModulesWithMissingSources.length} custom module(s) with missing sources:`); let keptCount = 0; @@ -2710,6 +3050,13 @@ class Installer { }, }); + // Defensive: handleCancel should have exited, but guard against symbol propagation + if (typeof newSourcePath !== 'string') { + keptCount++; + keptModulesWithoutSources.push(missing.id); + continue; + } + // Update the source in manifest const resolvedPath = path.resolve(newSourcePath.trim()); missing.info.sourcePath = resolvedPath; diff --git a/tools/cli/installers/lib/core/manifest-generator.js b/tools/cli/installers/lib/core/manifest-generator.js index caea790eb..bc4694a6d 100644 --- a/tools/cli/installers/lib/core/manifest-generator.js +++ b/tools/cli/installers/lib/core/manifest-generator.js @@ -4,6 +4,7 @@ const yaml = require('yaml'); const crypto = require('node:crypto'); const csv = require('csv-parse/sync'); const { getSourcePath, getModulePath } = require('../../../lib/project-root'); +const prompts = require('../../../lib/prompts'); // Load package.json for version info const packageJson = require('../../../../../package.json'); @@ -241,7 +242,7 @@ class ManifestGenerator { } } } catch (error) { - console.warn(`Warning: Failed to parse workflow at ${fullPath}: ${error.message}`); + await prompts.log.warn(`Failed to parse workflow at ${fullPath}: ${error.message}`); } } } @@ -321,6 +322,7 @@ class ManifestGenerator { const nameMatch = content.match(/name="([^"]+)"/); const titleMatch = content.match(/title="([^"]+)"/); const iconMatch = content.match(/icon="([^"]+)"/); + const capabilitiesMatch = content.match(/capabilities="([^"]+)"/); // Extract persona fields const roleMatch = content.match(/([^<]+)<\/role>/); @@ -342,6 +344,7 @@ class ManifestGenerator { displayName: nameMatch ? nameMatch[1] : agentName, title: titleMatch ? titleMatch[1] : '', icon: iconMatch ? iconMatch[1] : '', + capabilities: capabilitiesMatch ? this.cleanForCSV(capabilitiesMatch[1]) : '', role: roleMatch ? this.cleanForCSV(roleMatch[1]) : '', identity: identityMatch ? this.cleanForCSV(identityMatch[1]) : '', communicationStyle: styleMatch ? this.cleanForCSV(styleMatch[1]) : '', @@ -691,7 +694,7 @@ class ManifestGenerator { return preservedRows; } catch (error) { - console.warn(`Warning: Failed to read existing CSV ${csvPath}:`, error.message); + await prompts.log.warn(`Failed to read existing CSV ${csvPath}: ${error.message}`); return []; } } @@ -784,7 +787,7 @@ class ManifestGenerator { } // Create CSV header with persona fields - let csvContent = 'name,displayName,title,icon,role,identity,communicationStyle,principles,module,path\n'; + let csvContent = 'name,displayName,title,icon,capabilities,role,identity,communicationStyle,principles,module,path\n'; // Combine existing and new agents, preferring new data for duplicates const allAgents = new Map(); @@ -802,6 +805,7 @@ class ManifestGenerator { displayName: agent.displayName, title: agent.title, icon: agent.icon, + capabilities: agent.capabilities, role: agent.role, identity: agent.identity, communicationStyle: agent.communicationStyle, @@ -818,6 +822,7 @@ class ManifestGenerator { escapeCsv(record.displayName), escapeCsv(record.title), escapeCsv(record.icon), + escapeCsv(record.capabilities), escapeCsv(record.role), escapeCsv(record.identity), escapeCsv(record.communicationStyle), @@ -1068,7 +1073,7 @@ class ManifestGenerator { } } } catch (error) { - console.warn(`Warning: Could not scan for installed modules: ${error.message}`); + await prompts.log.warn(`Could not scan for installed modules: ${error.message}`); } return modules; diff --git a/tools/cli/installers/lib/core/manifest.js b/tools/cli/installers/lib/core/manifest.js index 865b75f96..5fa1229e1 100644 --- a/tools/cli/installers/lib/core/manifest.js +++ b/tools/cli/installers/lib/core/manifest.js @@ -2,6 +2,7 @@ const path = require('node:path'); const fs = require('fs-extra'); const crypto = require('node:crypto'); const { getProjectRoot } = require('../../../lib/project-root'); +const prompts = require('../../../lib/prompts'); class Manifest { /** @@ -100,7 +101,7 @@ class Manifest { ides: manifestData.ides || [], }; } catch (error) { - console.error('Failed to read YAML manifest:', error.message); + await prompts.log.error(`Failed to read YAML manifest: ${error.message}`); } } @@ -230,7 +231,7 @@ class Manifest { const content = await fs.readFile(yamlPath, 'utf8'); return yaml.parse(content); } catch (error) { - console.error('Failed to read YAML manifest:', error.message); + await prompts.log.error(`Failed to read YAML manifest: ${error.message}`); } } @@ -472,7 +473,7 @@ class Manifest { } } } catch (error) { - console.warn(`Warning: Could not parse ${filePath}:`, error.message); + await prompts.log.warn(`Could not parse ${filePath}: ${error.message}`); } } // Handle other file types (CSV, JSON, YAML, etc.) @@ -774,7 +775,7 @@ class Manifest { configs[moduleName] = yaml.parse(content); } } catch (error) { - console.warn(`Could not load config for module ${moduleName}:`, error.message); + await prompts.log.warn(`Could not load config for module ${moduleName}: ${error.message}`); } } @@ -876,7 +877,7 @@ class Manifest { const pkg = require(packageJsonPath); version = pkg.version; } catch (error) { - console.warn(`Failed to read package.json for ${moduleName}: ${error.message}`); + await prompts.log.warn(`Failed to read package.json for ${moduleName}: ${error.message}`); } } } @@ -904,7 +905,7 @@ class Manifest { repoUrl: moduleConfig.repoUrl || null, }; } catch (error) { - console.warn(`Failed to read module.yaml for ${moduleName}: ${error.message}`); + await prompts.log.warn(`Failed to read module.yaml for ${moduleName}: ${error.message}`); } } diff --git a/tools/cli/installers/lib/ide/_config-driven.js b/tools/cli/installers/lib/ide/_config-driven.js index 7eb2533ed..9541c75ed 100644 --- a/tools/cli/installers/lib/ide/_config-driven.js +++ b/tools/cli/installers/lib/ide/_config-driven.js @@ -456,8 +456,18 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}} async cleanup(projectDir, options = {}) { // Clean all target directories if (this.installerConfig?.targets) { + const parentDirs = new Set(); for (const target of this.installerConfig.targets) { await this.cleanupTarget(projectDir, target.target_dir, options); + // Track parent directories for empty-dir cleanup + const parentDir = path.dirname(target.target_dir); + if (parentDir && parentDir !== '.') { + parentDirs.add(parentDir); + } + } + // After all targets cleaned, remove empty parent directories (recursive up to projectDir) + for (const parentDir of parentDirs) { + await this.removeEmptyParents(projectDir, parentDir); } } else if (this.installerConfig?.target_dir) { await this.cleanupTarget(projectDir, this.installerConfig.target_dir, options); @@ -509,6 +519,41 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}} if (removedCount > 0 && !options.silent) { await prompts.log.message(` Cleaned ${removedCount} BMAD files from ${targetDir}`); } + + // Remove empty directory after cleanup + if (removedCount > 0) { + try { + const remaining = await fs.readdir(targetPath); + if (remaining.length === 0) { + await fs.remove(targetPath); + } + } catch { + // Directory may already be gone or in use — skip + } + } + } + /** + * Recursively remove empty directories walking up from dir toward projectDir + * Stops at projectDir boundary — never removes projectDir itself + * @param {string} projectDir - Project root (boundary) + * @param {string} relativeDir - Relative directory to start from + */ + async removeEmptyParents(projectDir, relativeDir) { + let current = relativeDir; + let last = null; + while (current && current !== '.' && current !== last) { + last = current; + const fullPath = path.join(projectDir, current); + try { + if (!(await fs.pathExists(fullPath))) break; + const remaining = await fs.readdir(fullPath); + if (remaining.length > 0) break; + await fs.rmdir(fullPath); + } catch { + break; + } + current = path.dirname(current); + } } } diff --git a/tools/cli/installers/lib/ide/codex.js b/tools/cli/installers/lib/ide/codex.js index 8e91e003b..5205386a2 100644 --- a/tools/cli/installers/lib/ide/codex.js +++ b/tools/cli/installers/lib/ide/codex.js @@ -14,7 +14,7 @@ const prompts = require('../../../lib/prompts'); */ class CodexSetup extends BaseIdeSetup { constructor() { - super('codex', 'Codex', true); // preferred IDE + super('codex', 'Codex', false); } /** @@ -23,6 +23,11 @@ class CodexSetup extends BaseIdeSetup { * @returns {Object} Collected configuration */ async collectConfiguration(options = {}) { + // Non-interactive mode: use default (project) - recommended for real work + if (options.skipPrompts) { + return { installLocation: options.codexLocation || 'project' }; + } + let confirmed = false; let installLocation = 'global'; diff --git a/tools/cli/installers/lib/ide/github-copilot.js b/tools/cli/installers/lib/ide/github-copilot.js new file mode 100644 index 000000000..033e8d627 --- /dev/null +++ b/tools/cli/installers/lib/ide/github-copilot.js @@ -0,0 +1,700 @@ +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} +disable-model-invocation: true +--- + +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/manager.js b/tools/cli/installers/lib/ide/manager.js index c68527f6a..9b8df1597 100644 --- a/tools/cli/installers/lib/ide/manager.js +++ b/tools/cli/installers/lib/ide/manager.js @@ -8,7 +8,7 @@ const prompts = require('../../../lib/prompts'); * Dynamically discovers and loads IDE handlers * * Loading strategy: - * 1. Custom installer files (codex.js, kilo.js) - for platforms with unique installation logic + * 1. Custom installer files (codex.js, 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 */ class IdeManager { @@ -44,7 +44,7 @@ class IdeManager { /** * Dynamically load all IDE handlers - * 1. Load custom installer files first (codex.js, kilo.js) + * 1. Load custom installer files first (codex.js, github-copilot.js, kilo.js, rovodev.js) * 2. Load config-driven handlers from platform-codes.yaml */ async loadHandlers() { @@ -61,7 +61,7 @@ class IdeManager { */ async loadCustomInstallerFiles() { const ideDir = __dirname; - const customFiles = ['codex.js', 'kilo.js']; + const customFiles = ['codex.js', 'github-copilot.js', 'kilo.js', 'rovodev.js']; for (const file of customFiles) { const filePath = path.join(ideDir, file); @@ -216,13 +216,14 @@ class IdeManager { /** * Cleanup IDE configurations * @param {string} projectDir - Project directory + * @param {Object} [options] - Cleanup options passed through to handlers */ - async cleanup(projectDir) { + async cleanup(projectDir, options = {}) { const results = []; for (const [name, handler] of this.handlers) { try { - await handler.cleanup(projectDir); + await handler.cleanup(projectDir, options); results.push({ ide: name, success: true }); } catch (error) { results.push({ ide: name, success: false, error: error.message }); @@ -232,6 +233,40 @@ class IdeManager { return results; } + /** + * Cleanup only the IDEs in the provided list + * Falls back to cleanup() (all handlers) if ideList is empty or undefined + * @param {string} projectDir - Project directory + * @param {Array} ideList - List of IDE names to clean up + * @param {Object} [options] - Cleanup options passed through to handlers + * @returns {Array} Results array + */ + async cleanupByList(projectDir, ideList, options = {}) { + if (!ideList || ideList.length === 0) { + return this.cleanup(projectDir, options); + } + + await this.ensureInitialized(); + const results = []; + + // Build lowercase lookup for case-insensitive matching + const lowercaseHandlers = new Map([...this.handlers.entries()].map(([k, v]) => [k.toLowerCase(), v])); + + for (const ideName of ideList) { + const handler = lowercaseHandlers.get(ideName.toLowerCase()); + if (!handler) continue; + + try { + await handler.cleanup(projectDir, options); + results.push({ ide: ideName, success: true }); + } catch (error) { + results.push({ ide: ideName, success: false, error: error.message }); + } + } + + return results; + } + /** * Get list of supported IDEs * @returns {Array} List of supported IDE names diff --git a/tools/cli/installers/lib/ide/platform-codes.yaml b/tools/cli/installers/lib/ide/platform-codes.yaml index 8642a3538..16723f9c5 100644 --- a/tools/cli/installers/lib/ide/platform-codes.yaml +++ b/tools/cli/installers/lib/ide/platform-codes.yaml @@ -98,11 +98,7 @@ platforms: preferred: false category: ide description: "GitHub's AI pair programmer" - installer: - targets: - - target_dir: .github/agents - template_type: copilot_agents - artifact_types: [agents] + # No installer config - uses custom github-copilot.js iflow: name: "iFlow" @@ -166,9 +162,7 @@ platforms: preferred: false category: ide description: "Atlassian's Rovo development environment" - installer: - target_dir: .rovodev/workflows - template_type: rovodev + # No installer config - uses custom rovodev.js (generates prompts.yml manifest) trae: name: "Trae" @@ -181,7 +175,7 @@ platforms: windsurf: name: "Windsurf" - preferred: true + preferred: false category: ide description: "AI-powered IDE with cascade flows" installer: diff --git a/tools/cli/installers/lib/ide/rovodev.js b/tools/cli/installers/lib/ide/rovodev.js new file mode 100644 index 000000000..da3c4809d --- /dev/null +++ b/tools/cli/installers/lib/ide/rovodev.js @@ -0,0 +1,257 @@ +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/cli/installers/lib/ide/templates/combined/opencode-agent.md b/tools/cli/installers/lib/ide/templates/combined/opencode-agent.md index 1102aa8a1..65f0a771d 100644 --- a/tools/cli/installers/lib/ide/templates/combined/opencode-agent.md +++ b/tools/cli/installers/lib/ide/templates/combined/opencode-agent.md @@ -1,5 +1,5 @@ --- -mode: primary +name: '{{name}}' description: '{{description}}' --- diff --git a/tools/cli/installers/lib/ide/templates/combined/opencode-task.md b/tools/cli/installers/lib/ide/templates/combined/opencode-task.md index 155c135c4..98b3a5d77 100644 --- a/tools/cli/installers/lib/ide/templates/combined/opencode-task.md +++ b/tools/cli/installers/lib/ide/templates/combined/opencode-task.md @@ -1,10 +1,12 @@ --- +name: '{{name}}' description: '{{description}}' --- Execute the BMAD '{{name}}' task. TASK INSTRUCTIONS: + 1. LOAD the task file from {project-root}/{{bmadFolderName}}/{{path}} 2. READ its entire contents 3. FOLLOW every instruction precisely as specified diff --git a/tools/cli/installers/lib/ide/templates/combined/opencode-tool.md b/tools/cli/installers/lib/ide/templates/combined/opencode-tool.md index 505445253..1ae9c9ac8 100644 --- a/tools/cli/installers/lib/ide/templates/combined/opencode-tool.md +++ b/tools/cli/installers/lib/ide/templates/combined/opencode-tool.md @@ -1,10 +1,12 @@ --- +name: '{{name}}' description: '{{description}}' --- Execute the BMAD '{{name}}' tool. TOOL INSTRUCTIONS: + 1. LOAD the tool file from {project-root}/{{bmadFolderName}}/{{path}} 2. READ its entire contents 3. FOLLOW every instruction precisely as specified diff --git a/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md b/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md index d1e2b0af2..a6f5cb96f 100644 --- a/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md +++ b/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md @@ -1,4 +1,5 @@ --- +name: '{{name}}' description: '{{description}}' --- @@ -7,6 +8,7 @@ Execute the BMAD '{{name}}' workflow. CRITICAL: You must load and follow the workflow definition exactly. WORKFLOW INSTRUCTIONS: + 1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{path}} 2. READ its entire contents 3. FOLLOW every step precisely as specified diff --git a/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md b/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md index d1e2b0af2..a6f5cb96f 100644 --- a/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md +++ b/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md @@ -1,4 +1,5 @@ --- +name: '{{name}}' description: '{{description}}' --- @@ -7,6 +8,7 @@ Execute the BMAD '{{name}}' workflow. CRITICAL: You must load and follow the workflow definition exactly. WORKFLOW INSTRUCTIONS: + 1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{path}} 2. READ its entire contents 3. FOLLOW every step precisely as specified diff --git a/tools/cli/installers/lib/modules/external-manager.js b/tools/cli/installers/lib/modules/external-manager.js index a68a2ba1e..f1ea2206e 100644 --- a/tools/cli/installers/lib/modules/external-manager.js +++ b/tools/cli/installers/lib/modules/external-manager.js @@ -1,6 +1,7 @@ const fs = require('fs-extra'); const path = require('node:path'); const yaml = require('yaml'); +const prompts = require('../../../lib/prompts'); /** * Manages external official modules defined in external-official-modules.yaml @@ -29,7 +30,7 @@ class ExternalModuleManager { this.cachedModules = config; return config; } catch (error) { - console.warn(`Failed to load external modules config: ${error.message}`); + await prompts.log.warn(`Failed to load external modules config: ${error.message}`); return { modules: {} }; } } diff --git a/tools/cli/installers/lib/modules/manager.js b/tools/cli/installers/lib/modules/manager.js index bc199a53d..f162593b7 100644 --- a/tools/cli/installers/lib/modules/manager.js +++ b/tools/cli/installers/lib/modules/manager.js @@ -452,7 +452,7 @@ class ModuleManager { installSpinner.stop(`Installed dependencies for ${moduleInfo.name}`); } catch (error) { installSpinner.error(`Failed to install dependencies for ${moduleInfo.name}`); - if (!silent) await prompts.log.warn(` Warning: ${error.message}`); + if (!silent) await prompts.log.warn(` ${error.message}`); } } else { // Check if package.json is newer than node_modules @@ -478,7 +478,7 @@ class ModuleManager { installSpinner.stop(`Installed dependencies for ${moduleInfo.name}`); } catch (error) { installSpinner.error(`Failed to install dependencies for ${moduleInfo.name}`); - if (!silent) await prompts.log.warn(` Warning: ${error.message}`); + if (!silent) await prompts.log.warn(` ${error.message}`); } } } @@ -541,7 +541,7 @@ class ModuleManager { const customContent = await fs.readFile(rootCustomConfigPath, 'utf8'); customConfig = yaml.parse(customContent); } catch (error) { - await prompts.log.warn(`Warning: Failed to read custom.yaml for ${moduleName}: ${error.message}`); + await prompts.log.warn(`Failed to read custom.yaml for ${moduleName}: ${error.message}`); } } @@ -549,7 +549,7 @@ class ModuleManager { if (customConfig) { options.moduleConfig = { ...options.moduleConfig, ...customConfig }; if (options.logger) { - options.logger.log(` Merged custom configuration for ${moduleName}`); + await options.logger.log(` Merged custom configuration for ${moduleName}`); } } @@ -734,8 +734,10 @@ class ModuleManager { continue; } - // Skip config.yaml templates - we'll generate clean ones with actual values - if (file === 'config.yaml' || file.endsWith('/config.yaml')) { + // Skip module root config.yaml only - generated by config collector with actual values + // Workflow-level config.yaml (e.g. workflows/orchestrate-story/config.yaml) must be copied + // for custom modules that use workflow-specific configuration + if (file === 'config.yaml') { continue; } @@ -857,7 +859,7 @@ class ModuleManager { await fs.writeFile(targetFile, strippedYaml, 'utf8'); } catch { // If anything fails, just copy the file as-is - await prompts.log.warn(` Warning: Could not process ${path.basename(sourceFile)}, copying as-is`); + await prompts.log.warn(` Could not process ${path.basename(sourceFile)}, copying as-is`); await fs.copy(sourceFile, targetFile, { overwrite: true }); } } @@ -1012,7 +1014,7 @@ class ModuleManager { await prompts.log.message(` Sidecar files processed: ${copiedFiles.length} files`); } } else if (process.env.BMAD_VERBOSE_INSTALL === 'true') { - await prompts.log.warn(` Warning: Agent marked as having sidecar but ${sidecarDirName} directory not found`); + await prompts.log.warn(` Agent marked as having sidecar but ${sidecarDirName} directory not found`); } } @@ -1247,15 +1249,20 @@ class ModuleManager { /** * Create directories declared in module.yaml's `directories` key * This replaces the security-risky module installer pattern with declarative config + * During updates, if a directory path changed, moves the old directory to the new path * @param {string} moduleName - Name of the module * @param {string} bmadDir - Target bmad directory * @param {Object} options - Installation options * @param {Object} options.moduleConfig - Module configuration from config collector + * @param {Object} options.existingModuleConfig - Previous module config (for detecting path changes during updates) * @param {Object} options.coreConfig - Core configuration + * @returns {Promise<{createdDirs: string[], movedDirs: string[], createdWdsFolders: string[]}>} Created directories info */ async createModuleDirectories(moduleName, bmadDir, options = {}) { const moduleConfig = options.moduleConfig || {}; + const existingModuleConfig = options.existingModuleConfig || {}; const projectRoot = path.dirname(bmadDir); + const emptyResult = { createdDirs: [], movedDirs: [], createdWdsFolders: [] }; // Special handling for core module - it's in src/core not src/modules let sourcePath; @@ -1264,14 +1271,14 @@ class ModuleManager { } else { sourcePath = await this.findModuleSource(moduleName, { silent: true }); if (!sourcePath) { - return; // No source found, skip + return emptyResult; // No source found, skip } } // Read module.yaml to find the `directories` key const moduleYamlPath = path.join(sourcePath, 'module.yaml'); if (!(await fs.pathExists(moduleYamlPath))) { - return; // No module.yaml, skip + return emptyResult; // No module.yaml, skip } let moduleYaml; @@ -1279,17 +1286,18 @@ class ModuleManager { const yamlContent = await fs.readFile(moduleYamlPath, 'utf8'); moduleYaml = yaml.parse(yamlContent); } catch { - return; // Invalid YAML, skip + return emptyResult; // Invalid YAML, skip } if (!moduleYaml || !moduleYaml.directories) { - return; // No directories declared, skip + return emptyResult; // No directories declared, skip } - // Get color utility for styled output - const color = await prompts.getColor(); const directories = moduleYaml.directories; const wdsFolders = moduleYaml.wds_folders || []; + const createdDirs = []; + const movedDirs = []; + const createdWdsFolders = []; for (const dirRef of directories) { // Parse variable reference like "{design_artifacts}" @@ -1318,29 +1326,96 @@ class ModuleManager { const normalizedPath = path.normalize(fullPath); const normalizedRoot = path.normalize(projectRoot); if (!normalizedPath.startsWith(normalizedRoot + path.sep) && normalizedPath !== normalizedRoot) { - await prompts.log.warn(color.yellow(`Warning: ${configKey} path escapes project root, skipping: ${dirPath}`)); + const color = await prompts.getColor(); + await prompts.log.warn(color.yellow(`${configKey} path escapes project root, skipping: ${dirPath}`)); continue; } - // Create directory if it doesn't exist - if (!(await fs.pathExists(fullPath))) { - const dirName = configKey.replaceAll('_', ' '); - await prompts.log.message(color.yellow(`Creating ${dirName} directory: ${dirPath}`)); + // Check if directory path changed from previous config (update/modify scenario) + const oldDirValue = existingModuleConfig[configKey]; + let oldFullPath = null; + let oldDirPath = null; + if (oldDirValue && typeof oldDirValue === 'string') { + // F3: Normalize both values before comparing to avoid false negatives + // from trailing slashes, separator differences, or prefix format variations + let normalizedOld = oldDirValue.replace(/^\{project-root\}\/?/, ''); + normalizedOld = path.normalize(normalizedOld.replaceAll('{project-root}', '')); + const normalizedNew = path.normalize(dirPath); + + if (normalizedOld !== normalizedNew) { + oldDirPath = normalizedOld; + oldFullPath = path.join(projectRoot, oldDirPath); + const normalizedOldAbsolute = path.normalize(oldFullPath); + if (!normalizedOldAbsolute.startsWith(normalizedRoot + path.sep) && normalizedOldAbsolute !== normalizedRoot) { + oldFullPath = null; // Old path escapes project root, ignore it + } + + // F13: Prevent parent/child move (e.g. docs/planning → docs/planning/v2) + if (oldFullPath) { + const normalizedNewAbsolute = path.normalize(fullPath); + if ( + normalizedOldAbsolute.startsWith(normalizedNewAbsolute + path.sep) || + normalizedNewAbsolute.startsWith(normalizedOldAbsolute + path.sep) + ) { + const color = await prompts.getColor(); + await prompts.log.warn( + color.yellow( + `${configKey}: cannot move between parent/child paths (${oldDirPath} / ${dirPath}), creating new directory instead`, + ), + ); + oldFullPath = null; + } + } + } + } + + const dirName = configKey.replaceAll('_', ' '); + + if (oldFullPath && (await fs.pathExists(oldFullPath)) && !(await fs.pathExists(fullPath))) { + // Path changed and old dir exists → move old to new location + // F1: Use fs.move() instead of fs.rename() for cross-device/volume support + // F2: Wrap in try/catch — fallback to creating new dir on failure + try { + await fs.ensureDir(path.dirname(fullPath)); + await fs.move(oldFullPath, fullPath); + movedDirs.push(`${dirName}: ${oldDirPath} → ${dirPath}`); + } catch (moveError) { + const color = await prompts.getColor(); + await prompts.log.warn( + color.yellow( + `Failed to move ${oldDirPath} → ${dirPath}: ${moveError.message}\n Creating new directory instead. Please move contents from the old directory manually.`, + ), + ); + await fs.ensureDir(fullPath); + createdDirs.push(`${dirName}: ${dirPath}`); + } + } else if (oldFullPath && (await fs.pathExists(oldFullPath)) && (await fs.pathExists(fullPath))) { + // F5: Both old and new directories exist — warn user about potential orphaned documents + const color = await prompts.getColor(); + await prompts.log.warn( + color.yellow( + `${dirName}: path changed but both directories exist:\n Old: ${oldDirPath}\n New: ${dirPath}\n Old directory may contain orphaned documents — please review and merge manually.`, + ), + ); + } else if (!(await fs.pathExists(fullPath))) { + // New directory doesn't exist yet → create it + createdDirs.push(`${dirName}: ${dirPath}`); await fs.ensureDir(fullPath); } // Create WDS subfolders if this is the design_artifacts directory if (configKey === 'design_artifacts' && wdsFolders.length > 0) { - await prompts.log.message(color.cyan('Creating WDS folder structure...')); for (const subfolder of wdsFolders) { const subPath = path.join(fullPath, subfolder); if (!(await fs.pathExists(subPath))) { await fs.ensureDir(subPath); - await prompts.log.message(color.dim(` ✓ ${subfolder}/`)); + createdWdsFolders.push(subfolder); } } } } + + return { createdDirs, movedDirs, createdWdsFolders }; } /** diff --git a/tools/cli/lib/agent/compiler.js b/tools/cli/lib/agent/compiler.js index a0dc4ae01..f9f71baab 100644 --- a/tools/cli/lib/agent/compiler.js +++ b/tools/cli/lib/agent/compiler.js @@ -279,6 +279,9 @@ async function compileToXml(agentYaml, agentName = '', targetPath = '') { `title="${meta.title || ''}"`, `icon="${meta.icon || '🤖'}"`, ]; + if (meta.capabilities) { + agentAttrs.push(`capabilities="${escapeXml(meta.capabilities)}"`); + } xml += `\n`; diff --git a/tools/cli/lib/ui.js b/tools/cli/lib/ui.js index 622f5a1e6..1338c1f17 100644 --- a/tools/cli/lib/ui.js +++ b/tools/cli/lib/ui.js @@ -189,7 +189,7 @@ class UI { const installedVersion = existingInstall.version || 'unknown'; // Check if version is pre beta - const shouldProceed = await this.showLegacyVersionWarning(installedVersion, currentVersion, path.basename(bmadDir)); + const shouldProceed = await this.showLegacyVersionWarning(installedVersion, currentVersion, path.basename(bmadDir), options); // If user chose to cancel, exit the installer if (!shouldProceed) { @@ -227,6 +227,14 @@ class UI { } actionType = options.action; await prompts.log.info(`Using action from command-line: ${actionType}`); + } else if (options.yes) { + // Default to quick-update if available, otherwise first available choice + if (choices.length === 0) { + throw new Error('No valid actions available for this installation'); + } + const hasQuickUpdate = choices.some((c) => c.value === 'quick-update'); + actionType = hasQuickUpdate ? 'quick-update' : choices[0].value; + await prompts.log.info(`Non-interactive mode (--yes): defaulting to ${actionType}`); } else { actionType = await prompts.select({ message: 'How would you like to proceed?', @@ -237,11 +245,49 @@ class UI { // Handle quick update separately if (actionType === 'quick-update') { - // Quick update doesn't install custom content - just updates existing modules + // Pass --custom-content through so installer can re-cache if cache is missing + let customContentForQuickUpdate = { hasCustomContent: false }; + if (options.customContent) { + const paths = options.customContent + .split(',') + .map((p) => p.trim()) + .filter(Boolean); + if (paths.length > 0) { + const customPaths = []; + const selectedModuleIds = []; + const sources = []; + for (const customPath of paths) { + const expandedPath = this.expandUserPath(customPath); + const validation = this.validateCustomContentPathSync(expandedPath); + if (validation) continue; + let moduleMeta; + try { + const moduleYamlPath = path.join(expandedPath, 'module.yaml'); + moduleMeta = require('yaml').parse(await fs.readFile(moduleYamlPath, 'utf-8')); + } catch { + continue; + } + if (!moduleMeta?.code) continue; + customPaths.push(expandedPath); + selectedModuleIds.push(moduleMeta.code); + sources.push({ path: expandedPath, id: moduleMeta.code, name: moduleMeta.name || moduleMeta.code }); + } + if (customPaths.length > 0) { + customContentForQuickUpdate = { + hasCustomContent: true, + selected: true, + sources, + selectedFiles: customPaths.map((p) => path.join(p, 'module.yaml')), + selectedModuleIds, + }; + } + } + } return { actionType: 'quick-update', directory: confirmedDirectory, - customContent: { hasCustomContent: false }, + customContent: customContentForQuickUpdate, + skipPrompts: options.yes || false, }; } @@ -252,6 +298,7 @@ class UI { actionType: 'compile-agents', directory: confirmedDirectory, customContent: { hasCustomContent: false }, + skipPrompts: options.yes || false, }; } @@ -272,6 +319,11 @@ class UI { .map((m) => m.trim()) .filter(Boolean); await prompts.log.info(`Using modules from command-line: ${selectedModules.join(', ')}`); + } else if (options.yes) { + selectedModules = await this.getDefaultModules(installedModuleIds); + await prompts.log.info( + `Non-interactive mode (--yes): using default modules (installed + defaults): ${selectedModules.join(', ')}`, + ); } else { selectedModules = await this.selectAllModules(installedModuleIds); } @@ -290,6 +342,7 @@ class UI { // Build custom content config similar to promptCustomContentSource const customPaths = []; const selectedModuleIds = []; + const sources = []; for (const customPath of paths) { const expandedPath = this.expandUserPath(customPath); @@ -311,6 +364,11 @@ class UI { continue; } + if (!moduleMeta) { + await prompts.log.warn(`Skipping custom content path: ${customPath} - module.yaml is empty`); + continue; + } + if (!moduleMeta.code) { await prompts.log.warn(`Skipping custom content path: ${customPath} - module.yaml missing 'code' field`); continue; @@ -318,6 +376,11 @@ class UI { customPaths.push(expandedPath); selectedModuleIds.push(moduleMeta.code); + sources.push({ + path: expandedPath, + id: moduleMeta.code, + name: moduleMeta.name || moduleMeta.code, + }); } if (customPaths.length > 0) { @@ -325,11 +388,29 @@ class UI { selectedCustomModules: selectedModuleIds, customContentConfig: { hasCustomContent: true, - paths: customPaths, + selected: true, + sources, + selectedFiles: customPaths.map((p) => path.join(p, 'module.yaml')), selectedModuleIds: selectedModuleIds, }, }; } + } else if (options.yes) { + // Non-interactive mode: preserve existing custom modules (matches default: false) + const cacheDir = path.join(bmadDir, '_config', 'custom'); + if (await fs.pathExists(cacheDir)) { + const entries = await fs.readdir(cacheDir, { withFileTypes: true }); + for (const entry of entries) { + if (entry.isDirectory()) { + customModuleResult.selectedCustomModules.push(entry.name); + } + } + await prompts.log.info( + `Non-interactive mode (--yes): preserving ${customModuleResult.selectedCustomModules.length} existing custom module(s)`, + ); + } else { + await prompts.log.info('Non-interactive mode (--yes): no existing custom modules found'); + } } else { const changeCustomModules = await prompts.confirm({ message: 'Modify custom modules, agents, or workflows?', @@ -378,6 +459,7 @@ class UI { skipIde: toolSelection.skipIde, coreConfig: coreConfig, customContent: customModuleResult.customContentConfig, + skipPrompts: options.yes || false, }; } } @@ -414,6 +496,7 @@ class UI { // Build custom content config similar to promptCustomContentSource const customPaths = []; const selectedModuleIds = []; + const sources = []; for (const customPath of paths) { const expandedPath = this.expandUserPath(customPath); @@ -435,6 +518,11 @@ class UI { continue; } + if (!moduleMeta) { + await prompts.log.warn(`Skipping custom content path: ${customPath} - module.yaml is empty`); + continue; + } + if (!moduleMeta.code) { await prompts.log.warn(`Skipping custom content path: ${customPath} - module.yaml missing 'code' field`); continue; @@ -442,12 +530,19 @@ class UI { customPaths.push(expandedPath); selectedModuleIds.push(moduleMeta.code); + sources.push({ + path: expandedPath, + id: moduleMeta.code, + name: moduleMeta.name || moduleMeta.code, + }); } if (customPaths.length > 0) { customContentConfig = { hasCustomContent: true, - paths: customPaths, + selected: true, + sources, + selectedFiles: customPaths.map((p) => path.join(p, 'module.yaml')), selectedModuleIds: selectedModuleIds, }; } @@ -487,7 +582,7 @@ class UI { /** * Prompt for tool/IDE selection (called after module configuration) * Uses a split prompt approach: - * 1. Recommended tools - standard multiselect for 3 preferred tools + * 1. Recommended tools - standard multiselect for preferred tools * 2. Additional tools - autocompleteMultiselect with search capability * @param {string} projectDir - Project directory to check for existing IDEs * @param {Object} options - Command-line options @@ -529,6 +624,27 @@ class UI { if (configuredIdes.length > 0) { const allTools = [...preferredIdes, ...otherIdes]; + // Non-interactive: handle --tools and --yes flags before interactive prompt + if (options.tools) { + if (options.tools.toLowerCase() === 'none') { + await prompts.log.info('Skipping tool configuration (--tools none)'); + return { ides: [], skipIde: true }; + } + const selectedIdes = options.tools + .split(',') + .map((t) => t.trim()) + .filter(Boolean); + await prompts.log.info(`Using tools from command-line: ${selectedIdes.join(', ')}`); + await this.displaySelectedTools(selectedIdes, preferredIdes, allTools); + return { ides: selectedIdes, skipIde: false }; + } + + if (options.yes) { + await prompts.log.info(`Non-interactive mode (--yes): keeping configured tools: ${configuredIdes.join(', ')}`); + await this.displaySelectedTools(configuredIdes, preferredIdes, allTools); + return { ides: configuredIdes, skipIde: false }; + } + // Sort: configured tools first, then preferred, then others const sortedTools = [ ...allTools.filter((ide) => configuredIdes.includes(ide.value)), @@ -691,18 +807,6 @@ class UI { }); } - /** - * Display installation summary - * @param {Object} result - Installation result - */ - async showInstallSummary(result) { - let summary = `Installed to: ${result.path}`; - if (result.modules && result.modules.length > 0) { - summary += `\nModules: ${result.modules.join(', ')}`; - } - await prompts.note(summary, 'BMAD is ready to use!'); - } - /** * Get confirmed directory from user * @returns {string} Confirmed directory path @@ -1642,7 +1746,7 @@ class UI { * @param {string} bmadFolderName - Name of the BMAD folder * @returns {Promise} True if user wants to proceed, false if they cancel */ - async showLegacyVersionWarning(installedVersion, currentVersion, bmadFolderName) { + async showLegacyVersionWarning(installedVersion, currentVersion, bmadFolderName, options = {}) { if (!this.isLegacyVersion(installedVersion)) { return true; // Not legacy, proceed } @@ -1668,6 +1772,11 @@ class UI { await prompts.log.warn('VERSION WARNING'); await prompts.note(warningContent, 'Version Warning'); + if (options.yes) { + await prompts.log.warn('Non-interactive mode (--yes): auto-proceeding with legacy update'); + return true; + } + const proceed = await prompts.select({ message: 'How would you like to proceed?', choices: [ diff --git a/tools/platform-codes.yaml b/tools/platform-codes.yaml index 50831953c..97846a9bd 100644 --- a/tools/platform-codes.yaml +++ b/tools/platform-codes.yaml @@ -18,12 +18,6 @@ platforms: category: cli description: "Anthropic's official CLI for Claude" - windsurf: - name: "Windsurf" - preferred: true - category: ide - description: "AI-powered IDE with cascade flows" - cursor: name: "Cursor" preferred: true @@ -61,12 +55,6 @@ platforms: category: ide description: "Enhanced Cline fork" - rovo: - name: "Rovo" - preferred: false - category: ide - description: "Atlassian's AI coding assistant" - rovo-dev: name: "Rovo Dev" preferred: false @@ -133,6 +121,12 @@ platforms: category: ide description: "AI coding tool" + windsurf: + name: "Windsurf" + preferred: false + category: ide + description: "AI-powered IDE with cascade flows" + # Platform categories categories: ide: diff --git a/tools/schema/agent.js b/tools/schema/agent.js index b6a36a985..93ced7c6e 100644 --- a/tools/schema/agent.js +++ b/tools/schema/agent.js @@ -228,6 +228,7 @@ function buildMetadataSchema(expectedModule) { title: createNonEmptyString('agent.metadata.title'), icon: createNonEmptyString('agent.metadata.icon'), module: createNonEmptyString('agent.metadata.module').optional(), + capabilities: createNonEmptyString('agent.metadata.capabilities').optional(), hasSidecar: z.boolean(), };