diff --git a/.prettierignore b/.prettierignore index 27d94d3e..43122f9e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,7 +4,6 @@ package-lock.json # Build outputs dist/ -web-bundles/ # Generated files *.log diff --git a/bmad-core/agents/analyst.md b/bmad-core/agents/analyst.md index 53a2df2c..ba78dd96 100644 --- a/bmad-core/agents/analyst.md +++ b/bmad-core/agents/analyst.md @@ -3,6 +3,7 @@ CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode: ```yaml +root: .bmad-core activation-instructions: - Follow all instructions in this file -> this defines you, your persona and more importantly what you can do. STAY IN CHARACTER! - Only read the files/tasks listed here when user selects them for execution to minimize context usage @@ -34,14 +35,14 @@ persona: - Numbered Options Protocol - Always use numbered lists for selections startup: - Greet the user with your name and role, and inform of the *help command. -commands: - - '*help" - Show: numbered list of the following commands to allow selection' - - '*chat-mode" - (Default) Strategic analysis consultation with advanced-elicitation' - - '*create-doc {template}" - Create doc (no template = show available templates)' - - '*brainstorm {topic}" - Facilitate structured brainstorming session' - - '*research {topic}" - Generate deep research prompt for investigation' - - '*elicit" - Run advanced elicitation to clarify requirements' - - '*exit" - Say goodbye as the Business Analyst, and then abandon inhabiting this persona' +commands: # All commands require * prefix when used (e.g., *help) + - help: Show numbered list of the following commands to allow selection + - chat-mode: (Default) Strategic analysis consultation with advanced-elicitation + - create-doc {template}: Create doc (no template = show available templates) + - brainstorm {topic}: Facilitate structured brainstorming session + - research {topic}: Generate deep research prompt for investigation + - elicit: Run advanced elicitation to clarify requirements + - exit: Say goodbye as the Business Analyst, and then abandon inhabiting this persona dependencies: tasks: - brainstorming-techniques diff --git a/bmad-core/agents/architect.md b/bmad-core/agents/architect.md index 0fd22a59..aae8f464 100644 --- a/bmad-core/agents/architect.md +++ b/bmad-core/agents/architect.md @@ -3,6 +3,7 @@ CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode: ```yaml +root: .bmad-core activation-instructions: - Follow all instructions in this file -> this defines you, your persona and more importantly what you can do. STAY IN CHARACTER! - Only read the files/tasks listed here when user selects them for execution to minimize context usage @@ -34,13 +35,13 @@ persona: startup: - Greet the user with your name and role, and inform of the *help command. - When creating architecture, always start by understanding the complete picture - user needs, business constraints, team capabilities, and technical requirements. -commands: - - '*help" - Show: numbered list of the following commands to allow selection' - - '*chat-mode" - (Default) Architect consultation with advanced-elicitation for complex system design' - - '*create-doc {template}" - Create doc (no template = show available templates)' - - '*execute-checklist {checklist}" - Run architectural validation checklist' - - '*research {topic}" - Generate deep research prompt for architectural decisions' - - '*exit" - Say goodbye as the Architect, and then abandon inhabiting this persona' +commands: # All commands require * prefix when used (e.g., *help) + - help: Show numbered list of the following commands to allow selection + - chat-mode: (Default) Architect consultation with advanced-elicitation for complex system design + - create-doc {template}: Create doc (no template = show available templates) + - execute-checklist {checklist}: Run architectural validation checklist + - research {topic}: Generate deep research prompt for architectural decisions + - exit: Say goodbye as the Architect, and then abandon inhabiting this persona dependencies: tasks: - create-doc diff --git a/bmad-core/agents/bmad-master.md b/bmad-core/agents/bmad-master.md index 925788d7..00bd6033 100644 --- a/bmad-core/agents/bmad-master.md +++ b/bmad-core/agents/bmad-master.md @@ -3,6 +3,7 @@ CRITICAL: Read the full YML to understand your operating params, start activation to alter your state of being, follow startup instructions, stay in this being until told to exit this mode: ```yml +root: .bmad-core agent: name: BMad Master id: bmad-master @@ -22,21 +23,21 @@ persona: - Use numbered lists for choices - Process (*) commands immediately startup: - - Announce: I'm BMad Master, your BMAD task executor. I can run any task, template, util, checklist, workflow, or schema. Type *help or tell me what you need. + - Greet the user with your name and role, and inform of the *help command. - CRITICAL: Do NOT scan filesystem or load any resources during startup - CRITICAL: Do NOT run discovery tasks automatically - Wait for user request before any tool use - Match request to resources, offer numbered options if unclear - Load resources only when explicitly requested -commands: - - '*help" - Show commands' - - '*chat" - Advanced elicitation + KB mode' - - '*status" - Current context' - - '*task/template/util/checklist/workflow {name}" - Execute (list if no name)' - - '*list {type}" - List resources by type' - - '*exit" - Exit (confirm)' - - '*yolo" - Skip confirmations' - - '*doc-out" - Output full document' +commands: # All commands require * prefix when used (e.g., *help) + - help: Show commands + - chat: Advanced elicitation + KB mode + - status: Current context + - task {template|util|checklist|workflow}: Execute + - list {task|template|util|checklist|workflow}: List resources by type + - exit: Exit (confirm) + - yolo: Toggle Yolo Mode off on - on will skip doc section confirmations + - doc-out: Output full document fuzzy-matching: - 85% confidence threshold - Show numbered list if unsure @@ -74,7 +75,6 @@ dependencies: - prd-tmpl - project-brief-tmpl - story-tmpl - - web-agent-startup-instructions-template data: - bmad-kb - technical-preferences diff --git a/bmad-core/agents/bmad-orchestrator.md b/bmad-core/agents/bmad-orchestrator.md index a0bcd016..28037fcc 100644 --- a/bmad-core/agents/bmad-orchestrator.md +++ b/bmad-core/agents/bmad-orchestrator.md @@ -3,6 +3,7 @@ CRITICAL: Read the full YML to understand your operating params, start activation to alter your state of being, follow startup instructions, stay in this being until told to exit this mode: ```yaml +root: .bmad-core agent: name: BMad Orchestrator id: bmad-orchestrator diff --git a/bmad-core/agents/dev.md b/bmad-core/agents/dev.md index ac08dc9a..724bd8fc 100644 --- a/bmad-core/agents/dev.md +++ b/bmad-core/agents/dev.md @@ -3,6 +3,7 @@ CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode: ```yml +root: .bmad-core agent: name: James id: dev @@ -19,33 +20,35 @@ persona: core_principles: - CRITICAL: Story-Centric - Story has ALL info. NEVER load PRD/architecture/other docs files unless explicitly directed in dev notes - - CRITICAL: Load Standards - MUST load docs/architecture/coding-standards.md into core memory at startup + - CRITICAL: Config-Based Loading - MUST load .bmad-core/core-config.yml at startup, then load ONLY files listed in devLoadAlwaysFiles. Inform user of missing files but continue - CRITICAL: Dev Record Only - ONLY update Dev Agent Record sections (checkboxes/Debug Log/Completion Notes/Change Log) - Sequential Execution - Complete tasks 1-by-1 in order. Mark [x] before next. No skipping - Test-Driven Quality - Write tests alongside code. Task incomplete without passing tests - Debug Log Discipline - Log temp changes to table. Revert after fix. Keep story lean - Block Only When Critical - HALT for: missing approval/ambiguous reqs/3 failures/missing config - - Code Excellence - Clean, secure, maintainable code per coding-standards.md + - Code Excellence - Clean, secure, maintainable code per loaded standards - Numbered Options - Always use numbered lists when presenting choices startup: - Announce: Greet the user with your name and role, and inform of the *help command. - - CRITICAL: Do NOT load any story files or coding-standards.md during startup + - CRITICAL: Load .bmad-core/core-config.yml and read devLoadAlwaysFiles list + - CRITICAL: Load ONLY files specified in devLoadAlwaysFiles. If any missing, inform user but continue + - CRITICAL: Do NOT load any story files during startup unless user requested you do - CRITICAL: Do NOT scan docs/stories/ directory automatically - CRITICAL: Do NOT begin any tasks automatically - Wait for user to specify story or ask for story selection - - Only load files and begin work when explicitly requested by user + - Only load story files and begin work when explicitly requested by user -commands: - - "*help" - Show commands - - "*chat-mode" - Conversational mode - - "*run-tests" - Execute linting+tests - - "*lint" - Run linting only - - "*dod-check" - Run story-dod-checklist - - "*status" - Show task progress - - "*debug-log" - Show debug entries - - "*complete-story" - Finalize to "Review" - - "*exit" - Leave developer mode +commands: # All commands require * prefix when used (e.g., *help) + - help: Show numbered list of the following commands to allow selection + - chat-mode: Conversational mode for development discussions + - run-tests: Execute linting and tests + - lint: Run linting only + - dod-check: Run story-dod-checklist + - status: Show task progress + - debug-log: Show debug entries + - complete-story: Finalize to "Review" + - exit: Say goodbye as the Developer, and then abandon inhabiting this persona task-execution: flow: "Read task→Implement→Write tests→Pass tests→Update [x]→Next task" diff --git a/bmad-core/agents/pm.md b/bmad-core/agents/pm.md index 648e5ed4..a666f951 100644 --- a/bmad-core/agents/pm.md +++ b/bmad-core/agents/pm.md @@ -3,6 +3,7 @@ CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode: ```yml +root: .bmad-core activation-instructions: - Follow all instructions in this file -> this defines you, your persona and more importantly what you can do. STAY IN CHARACTER! - Only read the files/tasks listed here when user selects them for execution to minimize context usage @@ -31,11 +32,11 @@ persona: - Strategic thinking & outcome-oriented startup: - Greet the user with your name and role, and inform of the *help command. -commands: - - '*help" - Show: numbered list of the following commands to allow selection' - - '*chat-mode" - (Default) Deep conversation with advanced-elicitation' - - '*create-doc {template}" - Create doc (no template = show available templates)' - - '*exit" - Say goodbye as the PM, and then abandon inhabiting this persona' +commands: # All commands require * prefix when used (e.g., *help) + - help: Show numbered list of the following commands to allow selection + - chat-mode: (Default) Deep conversation with advanced-elicitation + - create-doc {template}: Create doc (no template = show available templates) + - exit: Say goodbye as the PM, and then abandon inhabiting this persona dependencies: tasks: - create-doc diff --git a/bmad-core/agents/po.md b/bmad-core/agents/po.md index 91b24eb1..569d2f83 100644 --- a/bmad-core/agents/po.md +++ b/bmad-core/agents/po.md @@ -3,6 +3,7 @@ CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode: ```yml +root: .bmad-core activation-instructions: - Follow all instructions in this file -> this defines you, your persona and more importantly what you can do. STAY IN CHARACTER! - Only read the files/tasks listed here when user selects them for execution to minimize context usage @@ -33,16 +34,16 @@ persona: - Documentation Ecosystem Integrity - Maintain consistency across all documents startup: - Greet the user with your name and role, and inform of the *help command. -commands: - - '*help" - Show: numbered list of the following commands to allow selection' - - '*chat-mode" - (Default) Product Owner consultation with advanced-elicitation' - - '*create-doc {template}" - Create doc (no template = show available templates)' - - '*execute-checklist {checklist}" - Run validation checklist (default->po-master-checklist)' - - '*shard-doc {document}" - Break down document into actionable parts' - - '*correct-course" - Analyze and suggest project course corrections' - - '*create-epic" - Create epic for brownfield projects (task brownfield-create-epic)' - - '*create-story" - Create user story from requirements (task brownfield-create-story)' - - '*exit" - Say Goodbye, You are no longer this Agent' +commands: # All commands require * prefix when used (e.g., *help) + - help: Show numbered list of the following commands to allow selection + - chat-mode: (Default) Product Owner consultation with advanced-elicitation + - create-doc {template}: Create doc (no template = show available templates) + - execute-checklist {checklist}: Run validation checklist (default->po-master-checklist) + - shard-doc {document}: Break down document into actionable parts + - correct-course: Analyze and suggest project course corrections + - create-epic: Create epic for brownfield projects (task brownfield-create-epic) + - create-story: Create user story from requirements (task brownfield-create-story) + - exit: Say goodbye as the Product Owner, and then abandon inhabiting this persona dependencies: tasks: - execute-checklist diff --git a/bmad-core/agents/qa.md b/bmad-core/agents/qa.md index 87faa73c..e7bfcf1a 100644 --- a/bmad-core/agents/qa.md +++ b/bmad-core/agents/qa.md @@ -3,6 +3,7 @@ CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode: ```yaml +root: .bmad-core activation-instructions: - Follow all instructions in this file -> this defines you, your persona and more importantly what you can do. STAY IN CHARACTER! - Only read the files/tasks listed here when user selects them for execution to minimize context usage @@ -33,11 +34,11 @@ persona: - Cross-Browser & Cross-Platform Testing - Ensure comprehensive compatibility startup: - Greet the user with your name and role, and inform of the *help command. -commands: - - '*help" - Show: numbered list of the following commands to allow selection' - - '*chat-mode" - (Default) QA consultation with advanced-elicitation for test strategy' - - '*create-doc {template}" - Create doc (no template = show available templates)' - - '*exit" - Say goodbye as the QA Test Architect, and then abandon inhabiting this persona' +commands: # All commands require * prefix when used (e.g., *help) + - help: Show numbered list of the following commands to allow selection + - chat-mode: (Default) QA consultation with advanced-elicitation for test strategy + - create-doc {template}: Create doc (no template = show available templates) + - exit: Say goodbye as the QA Test Architect, and then abandon inhabiting this persona dependencies: data: - technical-preferences diff --git a/bmad-core/agents/sm.md b/bmad-core/agents/sm.md index 8d76d32b..3d5cb7a1 100644 --- a/bmad-core/agents/sm.md +++ b/bmad-core/agents/sm.md @@ -2,16 +2,10 @@ CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode: -## Task and File Resolution - -`Create Next Story`: `.bmad-core/tasks/create-next-story.md` -`story-tmpl`: `.bmad-core/templates/story-tmpl.md` -`story-draft-checklist`: `.bmad-core/checklists/story-draft-checklist.md` - ```yaml +root: .bmad-core activation-instructions: - Follow all instructions in this file -> this defines you, your persona and more importantly what you can do. STAY IN CHARACTER! - - Only read the files/tasks listed here when user selects them for execution to minimize context usage - The customization field ALWAYS takes precedence over any conflicting instructions - When listing tasks/templates or presenting options during conversations, always show as numbered options list, allowing the user to type a number to select or execute agent: @@ -27,31 +21,25 @@ persona: identity: Story creation expert who prepares detailed, actionable stories for AI developers focus: Creating crystal-clear stories that dumb AI agents can implement without confusion core_principles: - - Task Adherence - Rigorously follow `Create Next Story` procedures - - Checklist-Driven Validation - Apply story-draft-checklist meticulously - - Clarity for Developer Handoff - Stories must be immediately actionable - - Focus on One Story at a Time - Complete one before starting next - - Numbered Options Protocol - Always use numbered lists for selections + - Rigorously follow `create-next-story` procedure to generate the detailed user story + - Will ensure all information comes from the PRD and Architecture to guide the dumb dev agent + - You are NOT allowed to implement stories or modify code EVER! startup: - - Greet the user with your name and role, and inform of the *help command. - - CRITICAL: Do NOT automatically execute `Create Next Story` tasks during startup - - CRITICAL: Do NOT create or modify any files during startup + - Greet the user with your name and role, and inform of the *help command and then HALT to await instruction if not given already. - Offer to help with story preparation but wait for explicit user confirmation - Only execute tasks when user explicitly requests them - - 'CRITICAL RULE: You are ONLY allowed to create/modify story files - NEVER implement! If asked to implement, tell user they MUST switch to Dev Agent' -commands: - - '*help" - Show: numbered list of the following commands to allow selection' - - '*chat-mode" - Conversational mode with advanced-elicitation for advice' - - '*create" - Execute all steps in `Create Next Story`' - - '*pivot" - Run correct-course task (ensure no story already created first)' - - '*checklist {checklist}" - Show numbered list of checklists, execute selection' - - '*doc-shard {PRD|Architecture|Other}" - Execute shard-doc task' - - '*index-docs" - Update documentation index in /docs/index.md' - - '*exit" - Say goodbye as the Scrum Master, and then abandon inhabiting this persona' +commands: # All commands require * prefix when used (e.g., *help) + - help: Show numbered list of the following commands to allow selection + - chat-mode: Conversational mode with advanced-elicitation for advice + - create|draft: Execute create-next-story + - pivot: Execute `correct-course` task + - checklist {checklist}: Show numbered list of checklists, execute selection + - exit: Say goodbye as the Scrum Master, and then abandon inhabiting this persona dependencies: tasks: - create-next-story - execute-checklist + - course-correct templates: - story-tmpl checklists: diff --git a/bmad-core/agents/ux-expert.md b/bmad-core/agents/ux-expert.md index 8064fcee..442c970f 100644 --- a/bmad-core/agents/ux-expert.md +++ b/bmad-core/agents/ux-expert.md @@ -3,6 +3,7 @@ CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode: ```yaml +root: .bmad-core activation-instructions: - Follow all instructions in this file -> this defines you, your persona and more importantly what you can do. STAY IN CHARACTER! - Only read the files/tasks listed here when user selects them for execution to minimize context usage @@ -37,14 +38,14 @@ persona: startup: - Greet the user with your name and role, and inform of the *help command. - Always start by understanding the user's context, goals, and constraints before proposing solutions. -commands: - - '*help" - Show: numbered list of the following commands to allow selection' - - '*chat-mode" - (Default) UX consultation with advanced-elicitation for design decisions' - - '*create-doc {template}" - Create doc (no template = show available templates)' - - '*generate-ui-prompt" - Create AI frontend generation prompt' - - '*research {topic}" - Generate deep research prompt for UX investigation' - - '*execute-checklist {checklist}" - Run design validation checklist' - - '*exit" - Say goodbye as the UX Expert, and then abandon inhabiting this persona' +commands: # All commands require * prefix when used (e.g., *help) + - help: Show numbered list of the following commands to allow selection + - chat-mode: (Default) UX consultation with advanced-elicitation for design decisions + - create-doc {template}: Create doc (no template = show available templates) + - generate-ui-prompt: Create AI frontend generation prompt + - research {topic}: Generate deep research prompt for UX investigation + - execute-checklist {checklist}: Run design validation checklist + - exit: Say goodbye as the UX Expert, and then abandon inhabiting this persona dependencies: tasks: - generate-ai-frontend-prompt diff --git a/bmad-core/core-config.yml b/bmad-core/core-config.yml new file mode 100644 index 00000000..c31b281a --- /dev/null +++ b/bmad-core/core-config.yml @@ -0,0 +1,24 @@ +core-project-information: + dev-story-location: docs/stories # alternate could be .ai/stories if preferred for example + prd: + prd-file: docs/prd.md + prdVersion: v4 + prdSharded: true + prdShardedLocation: docs/prd + epicFilePattern: epic-{n}*.md + architecture: + architecture-file: docs/architecture.md + architectureVersion: v4 + architectureSharded: true + architectureShardedLocation: docs/architecture + # if you have a front-end architecture document, uncomment the following and validate the file path + # front-end-architecture: + # front-end-architecture-file: docs/front-end-architecture.md + # architectureVersion: v4 + # architectureSharded: true + # architectureShardedLocation: docs/architecture + customTechnicalDocuments: null # list other documents only if you want the SM to read them when creating stories + devLoadAlwaysFiles: + - docs/architecture/coding-standards.md + - docs/architecture/tech-stack.md + - docs/architecture/project-structure.md diff --git a/bmad-core/data/bmad-kb.md b/bmad-core/data/bmad-kb.md index cd930e11..bea007de 100644 --- a/bmad-core/data/bmad-kb.md +++ b/bmad-core/data/bmad-kb.md @@ -27,7 +27,7 @@ BMAD-METHOD (Breakthrough Method of Agile AI-driven Development) is a framework #### Option 1: Web UI **Best for**: ChatGPT, Claude, Gemini users who want to start immediately -1. Navigate to `.bmad-core/web-bundles/teams/` +1. Navigate to `dist/teams/` 2. Copy `team-fullstack.txt` content 3. Create new Gemini Gem or CustomGPT 4. Upload file with instructions: "Your critical operating instructions are attached, do not break character as directed" @@ -200,14 +200,16 @@ The BMAD-Method is built around a modular architecture centered on the `bmad-cor ### Dual Environment Architecture #### IDE Environment + - Users interact directly with agent markdown files - Agents can access all dependencies dynamically - Supports real-time file operations and project integration - Optimized for development workflow execution #### Web UI Environment -- Uses pre-built bundles from `bmad-core/web-bundles/` -- Single text files containing all agent dependencies + +- Uses pre-built bundles from `dist/teams` for stand alone 1 upload files for all agents and their assest with an orchestrating agent +- Single text files containing all agent dependencies are in `dist/agents/` - these are unnecessary unless you want to create a web agent that is only a single agent and not a team - Created by the web-builder tool for upload to web interfaces - Provides complete context in one package @@ -220,6 +222,7 @@ BMAD employs a sophisticated template system with three key components: 3. **Advanced Elicitation** (`tasks/advanced-elicitation.md`): Provides interactive refinement through structured brainstorming **Template Features**: + - **Self-contained**: Templates embed both output structure and processing instructions - **Variable Substitution**: `{{placeholders}}` for dynamic content - **AI Processing Directives**: `[[LLM: instructions]]` for AI-only processing diff --git a/bmad-core/tasks/create-next-story.md b/bmad-core/tasks/create-next-story.md index fb00b41e..4fd32043 100644 --- a/bmad-core/tasks/create-next-story.md +++ b/bmad-core/tasks/create-next-story.md @@ -4,45 +4,42 @@ To identify the next logical story based on project progress and epic definitions, and then to prepare a comprehensive, self-contained, and actionable story file using the `Story Template`. This task ensures the story is enriched with all necessary technical context, requirements, and acceptance criteria, making it ready for efficient implementation by a Developer Agent with minimal need for additional research. -## Inputs for this Task - -- Access to the project's documentation repository, specifically: - - `docs/index.md` (hereafter "Index Doc") - - All Epic files - located in one of these locations: - - Primary: `docs/prd/epic-{n}-{description}.md` (e.g., `epic-1-foundation-core-infrastructure.md`) - - Secondary: `docs/epics/epic-{n}-{description}.md` - - User-specified location if not found in above paths - - Existing story files in `docs/stories/` - - Main PRD (hereafter "PRD Doc") - - Main Architecture Document (hereafter "Main Arch Doc") - - Frontend Architecture Document (hereafter "Frontend Arch Doc," if relevant) - - Project Structure Guide (`docs/project-structure.md`) - - Operational Guidelines Document (`docs/operational-guidelines.md`) - - Technology Stack Document (`docs/tech-stack.md`) - - Data Models Document (as referenced in Index Doc) - - API Reference Document (as referenced in Index Doc) - - UI/UX Specifications, Style Guides, Component Guides (if relevant, as referenced in Index Doc) -- The `bmad-core/templates/story-tmpl.md` (hereafter "Story Template") -- The `bmad-core/checklists/story-draft-checklist.md` (hereafter "Story Draft Checklist") -- User confirmation to proceed with story identification and, if needed, to override warnings about incomplete prerequisite stories. - ## Task Execution Instructions +### 0. Load Core Configuration + +[[LLM: CRITICAL - This MUST be your first step]] + +- Load `.bmad-core/core-config.yml` from the project root +- If the file does not exist: + - HALT and inform the user: "core-config.yml not found. This file is required for story creation. You can: + 1. Copy it from GITHUB BMAD-METHOD/bmad-core/core-config.yml and configure it for your project + 2. Run the BMAD installer against your project to upgrade and add the file automatically + Please add and configure core-config.yml before proceeding." +- Extract the following key configurations: + - `dev-story-location`: Where to save story files + - `prd.prdSharded`: Whether PRD is sharded or monolithic + - `prd.prd-file`: Location of monolithic PRD (if not sharded) + - `prd.prdShardedLocation`: Location of sharded epic files + - `prd.epicFilePattern`: Pattern for epic files (e.g., `epic-{n}*.md`) + - `architecture.architectureVersion`: Architecture document version + - `architecture.architectureSharded`: Whether architecture is sharded + - `architecture.architecture-file`: Location of monolithic architecture + - `architecture.architectureShardedLocation`: Location of sharded architecture files + ### 1. Identify Next Story for Preparation #### 1.1 Locate Epic Files -- First, determine where epic files are located: - - Check `docs/prd/` for files matching pattern `epic-{n}-*.md` - - If not found, check `docs/epics/` for files matching pattern `epic-{n}-*.md` - - If still not found, ask user: "Unable to locate epic files. Please specify the path where epic files are stored." -- Note: Epic files follow naming convention `epic-{n}-{description}.md` (e.g., `epic-1-foundation-core-infrastructure.md`) +- Based on `prdSharded` from config: + - **If `prdSharded: true`**: Look for epic files in `prdShardedLocation` using `epicFilePattern` + - **If `prdSharded: false`**: Load the full PRD from `prd-file` and extract epics from section headings (## Epic N or ### Epic N) #### 1.2 Review Existing Stories -- Review `docs/stories/` to find the highest-numbered story file. +- Check `dev-story-location` from config (e.g., `docs/stories/`) for existing story files +- If the directory exists and has at least 1 file, find the highest-numbered story file. - **If a highest story file exists (`{lastEpicNum}.{lastStoryNum}.story.md`):** - - Verify its `Status` is 'Done' (or equivalent). - If not 'Done', present an alert to the user: @@ -60,17 +57,17 @@ To identify the next logical story based on project progress and epic definition ``` - Proceed only if user selects option 3 (Override) or if the last story was 'Done'. - - If proceeding: Look for the Epic File for `{lastEpicNum}` (e.g., `epic-{lastEpicNum}-*.md`) and check for a story numbered `{lastStoryNum + 1}`. If it exists and its prerequisites (per Epic File) are met, this is the next story. - - Else (story not found or prerequisites not met): The next story is the first story in the next Epic File (e.g., look for `epic-{lastEpicNum + 1}-*.md`, then `epic-{lastEpicNum + 2}-*.md`, etc.) whose prerequisites are met. + - If proceeding: Look for the Epic File for `{lastEpicNum}` (e.g., `epic-{lastEpicNum}*.md`) and check for a story numbered `{lastStoryNum + 1}`. If it exists and its prerequisites (per Epic File) are met, this is the next story. + - Else (story not found or prerequisites not met): The next story is the first story in the next Epic File (e.g., look for `epic-{lastEpicNum + 1}*.md`, then `epic-{lastEpicNum + 2}*.md`, etc.) whose prerequisites are met. - **If no story files exist in `docs/stories/`:** - The next story is the first story in the first epic file (look for `epic-1-*.md`, then `epic-2-*.md`, etc.) whose prerequisites are met. - If no suitable story with met prerequisites is found, report to the user that story creation is blocked, specifying what prerequisites are pending. HALT task. - Announce the identified story to the user: "Identified next story for preparation: {epicNum}.{storyNum} - {Story Title}". -### 2. Gather Core Story Requirements (from Epic File) +### 2. Gather Core Story Requirements (from Epic) -- For the identified story, open its parent Epic File (e.g., `epic-{epicNum}-*.md` from the location identified in step 1.1). +- For the identified story, review its parent Epic (e.g., `epic-{epicNum}*.md` from the location identified in step 1.1). - Extract: Exact Title, full Goal/User Story statement, initial list of Requirements, all Acceptance Criteria (ACs), and any predefined high-level Tasks. - Keep a record of this original epic-defined scope for later deviation analysis. @@ -79,7 +76,7 @@ To identify the next logical story based on project progress and epic definition [[LLM: This step is CRITICAL for continuity and learning from implementation experience]] - If this is not the first story (i.e., previous story exists): - - Read the previous story file: `docs/stories/{prevEpicNum}.{prevStoryNum}.story.md` + - Read the previous sequential story from `docs/stories` - Pay special attention to: - Dev Agent Record sections (especially Completion Notes and Debug Log References) - Any deviations from planned implementation @@ -88,18 +85,30 @@ To identify the next logical story based on project progress and epic definition - Any "lessons learned" or notes for future stories - Extract relevant insights that might inform the current story's preparation -### 4. Gather & Synthesize Architecture Context from Sharded Docs +### 4. Gather & Synthesize Architecture Context -[[LLM: CRITICAL - You MUST gather technical details from the sharded architecture documents. NEVER make up technical details not found in these documents.]] +[[LLM: CRITICAL - You MUST gather technical details from the architecture documents. NEVER make up technical details not found in these documents.]] -#### 4.1 Start with Architecture Index +#### 4.1 Determine Architecture Document Strategy -- Read `docs/architecture/index.md` to understand the full scope of available documentation -- Identify which sharded documents are most relevant to the current story +Based on configuration loaded in Step 0: -#### 4.2 Recommended Reading Order Based on Story Type +- **If `architectureVersion: v4` and `architectureSharded: true`**: + - Read `{architectureShardedLocation}/index.md` to understand available documentation + - Follow the structured reading order in section 4.2 below + +- **If `architectureVersion: v4` and `architectureSharded: false`**: + - Load the monolithic architecture from `architecture-file` + - Extract relevant sections based on v4 structure (tech stack, project structure, etc.) + +- **If `architectureVersion` is NOT v4**: + - Inform user: "Architecture document is not v4 format. Will use best judgment to find relevant information." + - If `architectureSharded: true`: Search sharded files by filename relevance + - If `architectureSharded: false`: Search within monolithic `architecture-file` for relevant sections -[[LLM: Read documents in this order, but ALWAYS verify relevance to the specific story. Skip irrelevant sections but NEVER skip documents that contain information needed for the story.]] +#### 4.2 Recommended Reading Order Based on Story Type (v4 Sharded Only) + +[[LLM: Use this structured approach ONLY for v4 sharded architecture. For other versions, use best judgment based on file names and content.]] **For ALL Stories:** @@ -108,9 +117,18 @@ To identify the next logical story based on project progress and epic definition 3. `docs/architecture/coding-standards.md` - Ensure dev follows project conventions 4. `docs/architecture/testing-strategy.md` - Include testing requirements in tasks -**For Backend/API Stories, additionally read:** 5. `docs/architecture/data-models.md` - Data structures and validation rules 6. `docs/architecture/database-schema.md` - Database design and relationships 7. `docs/architecture/backend-architecture.md` - Service patterns and structure 8. `docs/architecture/rest-api-spec.md` - API endpoint specifications 9. `docs/architecture/external-apis.md` - Third-party integrations (if relevant) +**For Backend/API Stories, additionally read:** +5. `docs/architecture/data-models.md` - Data structures and validation rules +6. `docs/architecture/database-schema.md` - Database design and relationships +7. `docs/architecture/backend-architecture.md` - Service patterns and structure +8. `docs/architecture/rest-api-spec.md` - API endpoint specifications +9. `docs/architecture/external-apis.md` - Third-party integrations (if relevant) -**For Frontend/UI Stories, additionally read:** 5. `docs/architecture/frontend-architecture.md` - Component structure and patterns 6. `docs/architecture/components.md` - Specific component designs 7. `docs/architecture/core-workflows.md` - User interaction flows 8. `docs/architecture/data-models.md` - Frontend data handling +**For Frontend/UI Stories, additionally read:** +5. `docs/architecture/frontend-architecture.md` - Component structure and patterns +6. `docs/architecture/components.md` - Specific component designs +7. `docs/architecture/core-workflows.md` - User interaction flows +8. `docs/architecture/data-models.md` - Frontend data handling **For Full-Stack Stories:** @@ -143,7 +161,7 @@ Format references as: `[Source: architecture/{filename}.md#{section}]` ### 6. Populate Story Template with Full Context -- Create a new story file: `docs/stories/{epicNum}.{storyNum}.story.md`. +- Create a new story file: `{dev-story-location}/{epicNum}.{storyNum}.story.md` (using location from config). - Use the Story Template to structure the file. - Fill in: - Story `{EpicNum}.{StoryNum}: {Short Title Copied from Epic File}` @@ -190,7 +208,7 @@ Format references as: `[Source: architecture/{filename}.md#{section}]` - Verify all source references are included for technical details - Ensure tasks align with both epic requirements and architecture constraints - Update status to "Draft" -- Save the story file to `docs/stories/{epicNum}.{storyNum}.story.md` +- Save the story file to `{dev-story-location}/{epicNum}.{storyNum}.story.md` (using location from config) ### 9. Report Completion diff --git a/bmad-core/templates/web-agent-startup-instructions-template.md b/bmad-core/utils/web-agent-startup-instructions.md similarity index 100% rename from bmad-core/templates/web-agent-startup-instructions-template.md rename to bmad-core/utils/web-agent-startup-instructions.md diff --git a/docs/bmad-workflow-guide.md b/docs/bmad-workflow-guide.md index d701032a..388209e6 100644 --- a/docs/bmad-workflow-guide.md +++ b/docs/bmad-workflow-guide.md @@ -37,7 +37,7 @@ Use Google's Gemini for collaborative planning with the full team: 2. **Create a new Gem**: - Give it a title and description (e.g., "BMAD Team Fullstack") 3. **Load team-fullstack**: - - Copy contents of: `.bmad-core/web-bundles/teams/team-fullstack.txt` from your project + - Copy contents of: `dist/teams/team-fullstack.txt` from your project - Paste this content into the Gem setup to configure the team 4. **Collaborate with the team**: - Business Analyst: Requirements gathering diff --git a/docs/claude-code-guide.md b/docs/claude-code-guide.md index 9bec295a..ad28c7b1 100644 --- a/docs/claude-code-guide.md +++ b/docs/claude-code-guide.md @@ -23,7 +23,7 @@ For ideation and planning, use Google's Gemini Custom Gem with the team-fullstac 1. Open [Google gems](https://gemini.google.com/gems/view) 2. Create a new Gem - give it a title and description -3. Copy the contents of `./web-bundles/teams/team-fullstack.txt` +3. Copy the contents of `.//teams/team-fullstack.txt` (location can vary if you chose a non default installation location for the bundles) - or just use the bundle premade from the repo dist folder. 4. Paste this content into Gemini to set up the team ### Gemini Planning Phase diff --git a/docs/core-architecture.md b/docs/core-architecture.md index f3e698ea..be2dbd63 100644 --- a/docs/core-architecture.md +++ b/docs/core-architecture.md @@ -16,7 +16,7 @@ The system facilitates a full development lifecycle: The entire BMAD-Method ecosystem is designed around the `.bmad-core` directory, which acts as the brain of the operation. The `tools` directory provides the means to process and package this brain for different environments. -```mermaid +````mermaid graph TD subgraph BMAD Method Project subgraph Core Framework @@ -35,7 +35,7 @@ graph TD end subgraph Outputs - J[".bmad-core/web-bundles"] + J["dist"] end B -- defines dependencies for --> E @@ -133,17 +133,17 @@ The framework is designed for two primary environments: local IDEs and web-based ### 4.1. Web Builder (`tools/builders/web-builder.js`) -- **Purpose**: This Node.js script is responsible for creating the `.txt` bundles found in `.bmad-core/web-bundles/`. +- **Purpose**: This Node.js script is responsible for creating the `.txt` bundles found in `dist`. - **Process**: 1. **Resolves Dependencies**: For a given agent or team, the script reads its definition file. 2. It recursively finds all dependent resources (tasks, templates, etc.) that the agent/team needs. 3. **Bundles Content**: It reads the content of all these files and concatenates them into a single, large text file, with clear separators indicating the original file path of each section. - 4. **Outputs Bundle**: The final `.txt` file is saved in the `web-bundles` directory, ready to be uploaded to a web UI. + 4. **Outputs Bundle**: The final `.txt` file is saved in the `dist` directory, ready to be uploaded to a web UI. ### 4.2. Environment-Specific Usage - **For IDEs**: Users interact with the agents directly via their markdown files in `.bmad-core/agents/`. The IDE integration (for Cursor, Claude Code, etc.) knows how to call these agents. -- **For Web UIs**: Users upload a pre-built bundle from `.bmad-core/web-bundles/`. This single file provides the AI with the context of the entire team and all their required tools and knowledge. +- **For Web UIs**: Users upload a pre-built bundle from `dist`. This single file provides the AI with the context of the entire team and all their required tools and knowledge. ## 5. BMAD Workflows @@ -168,12 +168,12 @@ graph TD I --> L["📁 Switch to IDE"] L --> M["PO: Shard Documents"] M --> N["Ready for SM/Dev Cycle"] - + style I fill:#34a853,color:#fff style G fill:#f9ab00,color:#fff style L fill:#1a73e8,color:#fff style N fill:#34a853,color:#fff -``` +```` **Key Planning Phases:** diff --git a/docs/cursor-guide.md b/docs/cursor-guide.md index 6ceacb07..505eeb26 100644 --- a/docs/cursor-guide.md +++ b/docs/cursor-guide.md @@ -23,7 +23,7 @@ For ideation and planning, use Google's Gemini Custom Gem with the team-fullstac 1. Open [Google gems](https://gemini.google.com/gems/view) 2. Create a new Gem - give it a title and description -3. Copy the contents of `./web-bundles/teams/team-fullstack.txt` +3. Copy the contents of `.//teams/team-fullstack.txt` (location can vary if you chose a non default installation location for the bundles) - or just use the bundle premade from the repo dist folder. 4. Paste this content into Gemini to set up the team ### Gemini Planning Phase diff --git a/docs/roo-code-guide.md b/docs/roo-code-guide.md index 2f11caed..46712681 100644 --- a/docs/roo-code-guide.md +++ b/docs/roo-code-guide.md @@ -23,7 +23,7 @@ For ideation and planning, use Google's Gemini Custom Gem with the team-fullstac 1. Open [Google gems](https://gemini.google.com/gems/view) 2. Create a new Gem - give it a title and description -3. Copy the contents of `./web-bundles/teams/team-fullstack.txt` +3. Copy the contents of `.//teams/team-fullstack.txt` (location can vary if you chose a non default installation location for the bundles) - or just use the bundle premade from the repo dist folder. 4. Paste this content into Gemini to set up the team ### Gemini Planning Phase diff --git a/docs/user-guide.md b/docs/user-guide.md index 849c07d2..62f00540 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -46,7 +46,7 @@ BMAD-METHOD (Breakthrough Method of Agile AI-Driven Development) is an AI agent Best for: ChatGPT, Claude, Gemini users -1. Navigate to `.bmad-core/web-bundles/teams/` +1. Navigate to `dist/teams/` 2. Copy `team-fullstack.txt` content 3. Create new Gemini Gem or CustomGPT 4. Upload file with instructions: "Your critical operating instructions are attached, do not break character as directed" diff --git a/docs/windsurf-guide.md b/docs/windsurf-guide.md index 2359782a..85b9dde3 100644 --- a/docs/windsurf-guide.md +++ b/docs/windsurf-guide.md @@ -23,7 +23,7 @@ For ideation and planning, use Google's Gemini Custom Gem with the team-fullstac 1. Open [Google gems](https://gemini.google.com/gems/view) 2. Create a new Gem - give it a title and description -3. Copy the contents of `./web-bundles/teams/team-fullstack.txt` +3. Copy the contents of `.//teams/team-fullstack.txt` (location can vary if you chose a non default installation location for the bundles) - or just use the bundle premade from the repo dist folder. 4. Paste this content into Gemini to set up the team ### Gemini Planning Phase diff --git a/expansion-packs/expansion-creator/templates/agent-tmpl.md b/expansion-packs/expansion-creator/templates/agent-tmpl.md index 1cf09ac1..45b02771 100644 --- a/expansion-packs/expansion-creator/templates/agent-tmpl.md +++ b/expansion-packs/expansion-creator/templates/agent-tmpl.md @@ -10,12 +10,13 @@ CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode: -```yml +````yml activation-instructions: - Follow all instructions in this file -> this defines you, your persona and more importantly what you can do. STAY IN CHARACTER! - Only read the files/tasks listed here when user selects them for execution to minimize context usage - The customization field ALWAYS takes precedence over any conflicting instructions - When listing tasks/templates or presenting options during conversations, always show as numbered options list, allowing the user to type a number to select or execute + - Command agent: name: [AGENT_NAME] @@ -36,7 +37,9 @@ persona: # Add more principles as needed startup: - - [STARTUP_INSTRUCTIONS] + - Greet the user with your name and role, and inform of the *help command. + - [STARTUP_INSTRUCTION] + - [STARTUP_INSTRUCTION]... commands: - "*help" - Show: numbered list of the following commands to allow selection @@ -137,4 +140,4 @@ dependencies: - 'materials-guide.md # Construction materials specs' utils: - 'template-format # For template processing' -``` +```` diff --git a/tools/builders/web-builder.js b/tools/builders/web-builder.js index 32cfd81e..6c99e61f 100644 --- a/tools/builders/web-builder.js +++ b/tools/builders/web-builder.js @@ -1,19 +1,22 @@ -const fs = require('node:fs').promises; -const path = require('node:path'); -const DependencyResolver = require('../lib/dependency-resolver'); +const fs = require("node:fs").promises; +const path = require("node:path"); +const DependencyResolver = require("../lib/dependency-resolver"); class WebBuilder { constructor(options = {}) { this.rootDir = options.rootDir || process.cwd(); - this.outputDirs = options.outputDirs || [ - path.join(this.rootDir, 'dist') - ]; + this.outputDirs = options.outputDirs || [path.join(this.rootDir, "dist")]; this.resolver = new DependencyResolver(this.rootDir); - this.templatePath = path.join(this.rootDir, 'bmad-core', 'templates', 'web-agent-startup-instructions-template.md'); + this.templatePath = path.join( + this.rootDir, + "bmad-core", + "utils", + "web-agent-startup-instructions.md" + ); } parseYaml(content) { - const yaml = require('js-yaml'); + const yaml = require("js-yaml"); return yaml.load(content); } @@ -38,10 +41,10 @@ class WebBuilder { // Write to all output directories for (const outputDir of this.outputDirs) { - const outputPath = path.join(outputDir, 'agents'); + const outputPath = path.join(outputDir, "agents"); await fs.mkdir(outputPath, { recursive: true }); const outputFile = path.join(outputPath, `${agentId}.txt`); - await fs.writeFile(outputFile, bundle, 'utf8'); + await fs.writeFile(outputFile, bundle, "utf8"); } } @@ -57,10 +60,10 @@ class WebBuilder { // Write to all output directories for (const outputDir of this.outputDirs) { - const outputPath = path.join(outputDir, 'teams'); + const outputPath = path.join(outputDir, "teams"); await fs.mkdir(outputPath, { recursive: true }); const outputFile = path.join(outputPath, `${teamId}.txt`); - await fs.writeFile(outputFile, bundle, 'utf8'); + await fs.writeFile(outputFile, bundle, "utf8"); } } @@ -69,7 +72,7 @@ class WebBuilder { async buildAgentBundle(agentId) { const dependencies = await this.resolver.resolveAgentDependencies(agentId); - const template = await fs.readFile(this.templatePath, 'utf8'); + const template = await fs.readFile(this.templatePath, "utf8"); const sections = [template]; @@ -81,12 +84,12 @@ class WebBuilder { sections.push(this.formatSection(resource.path, resource.content)); } - return sections.join('\n'); + return sections.join("\n"); } async buildTeamBundle(teamId) { const dependencies = await this.resolver.resolveTeamDependencies(teamId); - const template = await fs.readFile(this.templatePath, 'utf8'); + const template = await fs.readFile(this.templatePath, "utf8"); const sections = [template]; @@ -103,21 +106,21 @@ class WebBuilder { sections.push(this.formatSection(resource.path, resource.content)); } - return sections.join('\n'); + return sections.join("\n"); } formatSection(path, content) { - const separator = '===================='; + const separator = "===================="; return [ `${separator} START: ${path} ${separator}`, content.trim(), `${separator} END: ${path} ${separator}`, - '' - ].join('\n'); + "", + ].join("\n"); } async validate() { - console.log('Validating agent configurations...'); + console.log("Validating agent configurations..."); const agents = await this.resolver.listAgents(); for (const agentId of agents) { try { @@ -129,7 +132,7 @@ class WebBuilder { } } - console.log('\nValidating team configurations...'); + console.log("\nValidating team configurations..."); const teams = await this.resolver.listTeams(); for (const teamId of teams) { try { @@ -154,10 +157,8 @@ class WebBuilder { } async buildExpansionPack(packName, options = {}) { - const packDir = path.join(this.rootDir, 'expansion-packs', packName); - const outputDirs = [ - path.join(this.rootDir, 'dist', 'expansion-packs', packName) - ]; + const packDir = path.join(this.rootDir, "expansion-packs", packName); + const outputDirs = [path.join(this.rootDir, "dist", "expansion-packs", packName)]; // Clean output directories if requested if (options.clean !== false) { @@ -171,27 +172,27 @@ class WebBuilder { } // Build individual agents first - const agentsDir = path.join(packDir, 'agents'); + const agentsDir = path.join(packDir, "agents"); try { const agentFiles = await fs.readdir(agentsDir); - const agentMarkdownFiles = agentFiles.filter(f => f.endsWith('.md')); - + const agentMarkdownFiles = agentFiles.filter((f) => f.endsWith(".md")); + if (agentMarkdownFiles.length > 0) { console.log(` Building individual agents for ${packName}:`); - + for (const agentFile of agentMarkdownFiles) { - const agentName = agentFile.replace('.md', ''); + const agentName = agentFile.replace(".md", ""); console.log(` - ${agentName}`); - + // Build individual agent bundle const bundle = await this.buildExpansionAgentBundle(packName, packDir, agentName); - + // Write to all output directories for (const outputDir of outputDirs) { - const agentsOutputDir = path.join(outputDir, 'agents'); + const agentsOutputDir = path.join(outputDir, "agents"); await fs.mkdir(agentsOutputDir, { recursive: true }); const outputFile = path.join(agentsOutputDir, `${agentName}.txt`); - await fs.writeFile(outputFile, bundle, 'utf8'); + await fs.writeFile(outputFile, bundle, "utf8"); } } } @@ -200,24 +201,24 @@ class WebBuilder { } // Build team bundle - const agentTeamsDir = path.join(packDir, 'agent-teams'); + const agentTeamsDir = path.join(packDir, "agent-teams"); try { const teamFiles = await fs.readdir(agentTeamsDir); - const teamFile = teamFiles.find(f => f.endsWith('.yml')); - + const teamFile = teamFiles.find((f) => f.endsWith(".yml")); + if (teamFile) { console.log(` Building team bundle for ${packName}`); const teamConfigPath = path.join(agentTeamsDir, teamFile); - + // Build expansion pack as a team bundle const bundle = await this.buildExpansionTeamBundle(packName, packDir, teamConfigPath); - + // Write to all output directories for (const outputDir of outputDirs) { - const teamsOutputDir = path.join(outputDir, 'teams'); + const teamsOutputDir = path.join(outputDir, "teams"); await fs.mkdir(teamsOutputDir, { recursive: true }); - const outputFile = path.join(teamsOutputDir, teamFile.replace('.yml', '.txt')); - await fs.writeFile(outputFile, bundle, 'utf8'); + const outputFile = path.join(teamsOutputDir, teamFile.replace(".yml", ".txt")); + await fs.writeFile(outputFile, bundle, "utf8"); console.log(` ✓ Created bundle: ${path.relative(this.rootDir, outputFile)}`); } } else { @@ -229,49 +230,58 @@ class WebBuilder { } async buildExpansionAgentBundle(packName, packDir, agentName) { - const template = await fs.readFile(this.templatePath, 'utf8'); + const template = await fs.readFile(this.templatePath, "utf8"); const sections = [template]; // Add agent configuration - const agentPath = path.join(packDir, 'agents', `${agentName}.md`); - const agentContent = await fs.readFile(agentPath, 'utf8'); + const agentPath = path.join(packDir, "agents", `${agentName}.md`); + const agentContent = await fs.readFile(agentPath, "utf8"); sections.push(this.formatSection(`agents#${agentName}`, agentContent)); // Resolve and add agent dependencies const agentYaml = agentContent.match(/```yaml\n([\s\S]*?)\n```/); if (agentYaml) { try { - const yaml = require('js-yaml'); + const yaml = require("js-yaml"); const agentConfig = yaml.load(agentYaml[1]); - + if (agentConfig.dependencies) { // Add resources, first try expansion pack, then core for (const [resourceType, resources] of Object.entries(agentConfig.dependencies)) { if (Array.isArray(resources)) { for (const resourceName of resources) { let found = false; - const extensions = ['.md', '.yml', '.yaml']; - + const extensions = [".md", ".yml", ".yaml"]; + // Try expansion pack first for (const ext of extensions) { const resourcePath = path.join(packDir, resourceType, `${resourceName}${ext}`); try { - const resourceContent = await fs.readFile(resourcePath, 'utf8'); - sections.push(this.formatSection(`${resourceType}#${resourceName}`, resourceContent)); + const resourceContent = await fs.readFile(resourcePath, "utf8"); + sections.push( + this.formatSection(`${resourceType}#${resourceName}`, resourceContent) + ); found = true; break; } catch (error) { // Not in expansion pack, continue } } - + // If not found in expansion pack, try core if (!found) { for (const ext of extensions) { - const corePath = path.join(this.rootDir, 'bmad-core', resourceType, `${resourceName}${ext}`); + const corePath = path.join( + this.rootDir, + "bmad-core", + resourceType, + `${resourceName}${ext}` + ); try { - const coreContent = await fs.readFile(corePath, 'utf8'); - sections.push(this.formatSection(`${resourceType}#${resourceName}`, coreContent)); + const coreContent = await fs.readFile(corePath, "utf8"); + sections.push( + this.formatSection(`${resourceType}#${resourceName}`, coreContent) + ); found = true; break; } catch (error) { @@ -279,9 +289,11 @@ class WebBuilder { } } } - + if (!found) { - console.warn(` ⚠ Dependency ${resourceType}#${resourceName} not found in expansion pack or core`); + console.warn( + ` ⚠ Dependency ${resourceType}#${resourceName} not found in expansion pack or core` + ); } } } @@ -292,27 +304,27 @@ class WebBuilder { } } - return sections.join('\n'); + return sections.join("\n"); } async buildExpansionTeamBundle(packName, packDir, teamConfigPath) { - const template = await fs.readFile(this.templatePath, 'utf8'); + const template = await fs.readFile(this.templatePath, "utf8"); const sections = [template]; // Add team configuration and parse to get agent list - const teamContent = await fs.readFile(teamConfigPath, 'utf8'); - const teamFileName = path.basename(teamConfigPath, '.yml'); + const teamContent = await fs.readFile(teamConfigPath, "utf8"); + const teamFileName = path.basename(teamConfigPath, ".yml"); const teamConfig = this.parseYaml(teamContent); sections.push(this.formatSection(`agent-teams#${teamFileName}`, teamContent)); // Get list of expansion pack agents const expansionAgents = new Set(); - const agentsDir = path.join(packDir, 'agents'); + const agentsDir = path.join(packDir, "agents"); try { const agentFiles = await fs.readdir(agentsDir); - for (const agentFile of agentFiles.filter(f => f.endsWith('.md'))) { - const agentName = agentFile.replace('.md', ''); + for (const agentFile of agentFiles.filter((f) => f.endsWith(".md"))) { + const agentName = agentFile.replace(".md", ""); expansionAgents.add(agentName); } } catch (error) { @@ -321,13 +333,15 @@ class WebBuilder { // Build a map of all available expansion pack resources for override checking const expansionResources = new Map(); - const resourceDirs = ['templates', 'tasks', 'checklists', 'workflows', 'data']; + const resourceDirs = ["templates", "tasks", "checklists", "workflows", "data"]; for (const resourceDir of resourceDirs) { const resourcePath = path.join(packDir, resourceDir); try { const resourceFiles = await fs.readdir(resourcePath); - for (const resourceFile of resourceFiles.filter(f => f.endsWith('.md') || f.endsWith('.yml'))) { - const fileName = resourceFile.replace(/\.(md|yml)$/, ''); + for (const resourceFile of resourceFiles.filter( + (f) => f.endsWith(".md") || f.endsWith(".yml") + )) { + const fileName = resourceFile.replace(/\.(md|yml)$/, ""); expansionResources.set(`${resourceDir}#${fileName}`, true); } } catch (error) { @@ -337,22 +351,21 @@ class WebBuilder { // Process all agents listed in team configuration const agentsToProcess = teamConfig.agents || []; - + // Ensure bmad-orchestrator is always included for teams - if (!agentsToProcess.includes('bmad-orchestrator')) { + if (!agentsToProcess.includes("bmad-orchestrator")) { console.warn(` ⚠ Team ${teamFileName} missing bmad-orchestrator, adding automatically`); - agentsToProcess.unshift('bmad-orchestrator'); + agentsToProcess.unshift("bmad-orchestrator"); } // Track all dependencies from all agents (deduplicated) const allDependencies = new Map(); for (const agentId of agentsToProcess) { - if (expansionAgents.has(agentId)) { // Use expansion pack version (override) const agentPath = path.join(agentsDir, `${agentId}.md`); - const agentContent = await fs.readFile(agentPath, 'utf8'); + const agentContent = await fs.readFile(agentPath, "utf8"); sections.push(this.formatSection(`agents#${agentId}`, agentContent)); // Parse and collect dependencies from expansion agent @@ -379,8 +392,8 @@ class WebBuilder { } else { // Use core BMAD version try { - const coreAgentPath = path.join(this.rootDir, 'bmad-core', 'agents', `${agentId}.md`); - const coreAgentContent = await fs.readFile(coreAgentPath, 'utf8'); + const coreAgentPath = path.join(this.rootDir, "bmad-core", "agents", `${agentId}.md`); + const coreAgentContent = await fs.readFile(coreAgentPath, "utf8"); sections.push(this.formatSection(`agents#${agentId}`, coreAgentContent)); // Parse and collect dependencies from core agent @@ -389,8 +402,8 @@ class WebBuilder { try { // Clean up the YAML to handle command descriptions after dashes let yamlContent = agentYaml[1]; - yamlContent = yamlContent.replace(/^(\s*-)(\s*"[^"]+")(\s*-\s*.*)$/gm, '$1$2'); - + yamlContent = yamlContent.replace(/^(\s*-)(\s*"[^"]+")(\s*-\s*.*)$/gm, "$1$2"); + const agentConfig = this.parseYaml(yamlContent); if (agentConfig.dependencies) { for (const [resourceType, resources] of Object.entries(agentConfig.dependencies)) { @@ -418,15 +431,15 @@ class WebBuilder { // Always prefer expansion pack versions if they exist for (const [key, dep] of allDependencies) { let found = false; - const extensions = ['.md', '.yml', '.yaml']; - + const extensions = [".md", ".yml", ".yaml"]; + // Always check expansion pack first, even if the dependency came from a core agent if (expansionResources.has(key)) { // We know it exists in expansion pack, find and load it for (const ext of extensions) { const expansionPath = path.join(packDir, dep.type, `${dep.name}${ext}`); try { - const content = await fs.readFile(expansionPath, 'utf8'); + const content = await fs.readFile(expansionPath, "utf8"); sections.push(this.formatSection(key, content)); console.log(` ✓ Using expansion override for ${key}`); found = true; @@ -436,13 +449,13 @@ class WebBuilder { } } } - + // If not found in expansion pack (or doesn't exist there), try core if (!found) { for (const ext of extensions) { - const corePath = path.join(this.rootDir, 'bmad-core', dep.type, `${dep.name}${ext}`); + const corePath = path.join(this.rootDir, "bmad-core", dep.type, `${dep.name}${ext}`); try { - const content = await fs.readFile(corePath, 'utf8'); + const content = await fs.readFile(corePath, "utf8"); sections.push(this.formatSection(key, content)); found = true; break; @@ -451,7 +464,7 @@ class WebBuilder { } } } - + if (!found) { console.warn(` ⚠ Dependency ${key} not found in expansion pack or core`); } @@ -462,11 +475,13 @@ class WebBuilder { const resourcePath = path.join(packDir, resourceDir); try { const resourceFiles = await fs.readdir(resourcePath); - for (const resourceFile of resourceFiles.filter(f => f.endsWith('.md') || f.endsWith('.yml'))) { + for (const resourceFile of resourceFiles.filter( + (f) => f.endsWith(".md") || f.endsWith(".yml") + )) { const filePath = path.join(resourcePath, resourceFile); - const fileContent = await fs.readFile(filePath, 'utf8'); - const fileName = resourceFile.replace(/\.(md|yml)$/, ''); - + const fileContent = await fs.readFile(filePath, "utf8"); + const fileName = resourceFile.replace(/\.(md|yml)$/, ""); + // Only add if not already included as a dependency const resourceKey = `${resourceDir}#${fileName}`; if (!allDependencies.has(resourceKey)) { @@ -478,18 +493,16 @@ class WebBuilder { } } - return sections.join('\n'); + return sections.join("\n"); } async listExpansionPacks() { - const expansionPacksDir = path.join(this.rootDir, 'expansion-packs'); + const expansionPacksDir = path.join(this.rootDir, "expansion-packs"); try { const entries = await fs.readdir(expansionPacksDir, { withFileTypes: true }); - return entries - .filter(entry => entry.isDirectory()) - .map(entry => entry.name); + return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name); } catch (error) { - console.warn('No expansion-packs directory found'); + console.warn("No expansion-packs directory found"); return []; } } @@ -499,4 +512,4 @@ class WebBuilder { } } -module.exports = WebBuilder; \ No newline at end of file +module.exports = WebBuilder; diff --git a/tools/installer/lib/ide-setup.js b/tools/installer/lib/ide-setup.js index c505ef05..6a42a085 100644 --- a/tools/installer/lib/ide-setup.js +++ b/tools/installer/lib/ide-setup.js @@ -39,20 +39,13 @@ class IdeSetup { async setupCursor(installDir, selectedAgent) { const cursorRulesDir = path.join(installDir, ".cursor", "rules"); - const agents = selectedAgent - ? [selectedAgent] - : await this.getAllAgentIds(installDir); + const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir); await fileManager.ensureDirectory(cursorRulesDir); for (const agentId of agents) { // Check if .bmad-core is a subdirectory (full install) or if agents are in root (single agent install) - let agentPath = path.join( - installDir, - ".bmad-core", - "agents", - `${agentId}.md` - ); + let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`); if (!(await fileManager.pathExists(agentPath))) { agentPath = path.join(installDir, "agents", `${agentId}.md`); } @@ -103,20 +96,13 @@ class IdeSetup { async setupClaudeCode(installDir, selectedAgent) { const commandsDir = path.join(installDir, ".claude", "commands"); - const agents = selectedAgent - ? [selectedAgent] - : await this.getAllAgentIds(installDir); + const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir); await fileManager.ensureDirectory(commandsDir); for (const agentId of agents) { // Check if .bmad-core is a subdirectory (full install) or if agents are in root (single agent install) - let agentPath = path.join( - installDir, - ".bmad-core", - "agents", - `${agentId}.md` - ); + let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`); if (!(await fileManager.pathExists(agentPath))) { agentPath = path.join(installDir, "agents", `${agentId}.md`); } @@ -136,29 +122,20 @@ class IdeSetup { } } - console.log( - chalk.green(`\n✓ Created Claude Code commands in ${commandsDir}`) - ); + console.log(chalk.green(`\n✓ Created Claude Code commands in ${commandsDir}`)); return true; } async setupWindsurf(installDir, selectedAgent) { const windsurfRulesDir = path.join(installDir, ".windsurf", "rules"); - const agents = selectedAgent - ? [selectedAgent] - : await this.getAllAgentIds(installDir); + const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir); await fileManager.ensureDirectory(windsurfRulesDir); for (const agentId of agents) { // Check if .bmad-core is a subdirectory (full install) or if agents are in root (single agent install) - let agentPath = path.join( - installDir, - ".bmad-core", - "agents", - `${agentId}.md` - ); + let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`); if (!(await fileManager.pathExists(agentPath))) { agentPath = path.join(installDir, "agents", `${agentId}.md`); } @@ -197,9 +174,7 @@ class IdeSetup { } } - console.log( - chalk.green(`\n✓ Created Windsurf rules in ${windsurfRulesDir}`) - ); + console.log(chalk.green(`\n✓ Created Windsurf rules in ${windsurfRulesDir}`)); return true; } @@ -233,13 +208,7 @@ class IdeSetup { } async setupRoo(installDir, selectedAgent) { - const agents = selectedAgent - ? [selectedAgent] - : await this.getAllAgentIds(installDir); - - // Create .roo directory first - const rooDir = path.join(installDir, ".roo"); - await fileManager.ensureDirectory(rooDir); + const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir); // Check for existing .roomodes file in project root const roomodesPath = path.join(installDir, ".roomodes"); @@ -253,11 +222,7 @@ class IdeSetup { for (const match of modeMatches) { existingModes.push(match[1]); } - console.log( - chalk.yellow( - `Found existing .roomodes file with ${existingModes.length} modes` - ) - ); + console.log(chalk.yellow(`Found existing .roomodes file with ${existingModes.length} modes`)); } // Create new modes content @@ -265,55 +230,48 @@ class IdeSetup { // Define file permissions for each agent type const agentPermissions = { - 'analyst': { - fileRegex: '\\.(md|txt)$', - description: 'Documentation and text files' + analyst: { + fileRegex: "\\.(md|txt)$", + description: "Documentation and text files", }, - 'pm': { - fileRegex: '\\.(md|txt)$', - description: 'Product documentation' + pm: { + fileRegex: "\\.(md|txt)$", + description: "Product documentation", }, - 'architect': { - fileRegex: '\\.(md|txt|yml|yaml|json)$', - description: 'Architecture docs and configs' + architect: { + fileRegex: "\\.(md|txt|yml|yaml|json)$", + description: "Architecture docs and configs", }, - 'dev': null, // Full edit access - 'qa': { - fileRegex: '\\.(test|spec)\\.(js|ts|jsx|tsx)$|\\.md$', - description: 'Test files and documentation' + dev: null, // Full edit access + qa: { + fileRegex: "\\.(test|spec)\\.(js|ts|jsx|tsx)$|\\.md$", + description: "Test files and documentation", }, - 'ux-expert': { - fileRegex: '\\.(md|css|scss|html|jsx|tsx)$', - description: 'Design-related files' + "ux-expert": { + fileRegex: "\\.(md|css|scss|html|jsx|tsx)$", + description: "Design-related files", }, - 'po': { - fileRegex: '\\.(md|txt)$', - description: 'Story and requirement docs' + po: { + fileRegex: "\\.(md|txt)$", + description: "Story and requirement docs", }, - 'sm': { - fileRegex: '\\.(md|txt)$', - description: 'Process and planning docs' + sm: { + fileRegex: "\\.(md|txt)$", + description: "Process and planning docs", }, - 'bmad-orchestrator': null, // Full edit access - 'bmad-master': null // Full edit access + "bmad-orchestrator": null, // Full edit access + "bmad-master": null, // Full edit access }; for (const agentId of agents) { // Skip if already exists if (existingModes.includes(`bmad-${agentId}`)) { - console.log( - chalk.dim(`Skipping ${agentId} - already exists in .roomodes`) - ); + console.log(chalk.dim(`Skipping ${agentId} - already exists in .roomodes`)); continue; } // Read agent file to extract all information - let agentPath = path.join( - installDir, - ".bmad-core", - "agents", - `${agentId}.md` - ); + let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`); if (!(await fileManager.pathExists(agentPath))) { agentPath = path.join(installDir, "agents", `${agentId}.md`); } @@ -334,9 +292,7 @@ class IdeSetup { const title = titleMatch ? titleMatch[1].trim() : this.getAgentTitle(agentId); const icon = iconMatch ? iconMatch[1].trim() : "🤖"; - const whenToUse = whenToUseMatch - ? whenToUseMatch[1].trim() - : `Use for ${title} tasks`; + const whenToUse = whenToUseMatch ? whenToUseMatch[1].trim() : `Use for ${title} tasks`; const roleDefinition = roleDefinitionMatch ? roleDefinitionMatch[1].trim() : `You are a ${title} specializing in ${title.toLowerCase()} tasks and responsibilities.`; @@ -360,9 +316,7 @@ class IdeSetup { newModesContent += ` - edit\n`; } - console.log( - chalk.green(`✓ Added mode: bmad-${agentId} (${icon} ${title})`) - ); + console.log(chalk.green(`✓ Added mode: bmad-${agentId} (${icon} ${title})`)); } } } @@ -381,46 +335,8 @@ class IdeSetup { await fileManager.writeFile(roomodesPath, roomodesContent); console.log(chalk.green("✓ Created .roomodes file in project root")); - // Create README in .roo directory - const rooReadme = `# Roo Code Custom Modes for BMAD-METHOD - -This directory contains custom mode configurations for Roo Code to enable BMAD agent personalities. - -## Setup - -The \`.roomodes\` file defines all BMAD agents as custom modes using the proper \`customModes:\` structure. Modes are automatically available in Roo Code when you open this project. - -## Available Modes - -${agents.map((id) => `- **bmad-${id}** - ${this.getAgentTitle(id)}`).join("\n")} - -## Usage - -In Roo Code: -1. Open the mode selector (usually in the status bar) -2. Select any BMAD agent mode -3. The AI will adopt that agent's personality and expertise - -## File Permissions - -Each agent has specific file access permissions: -- **Analysts, PM, PO, SM**: Limited to documentation files (.md, .txt) -- **Architect**: Architecture docs and configs (.md, .txt, .yml, .yaml, .json) -- **QA**: Test files and documentation -- **UX Expert**: Design-related files (.md, .css, .scss, .html, .jsx, .tsx) -- **Developer, Orchestrator, Master**: Full edit access to all files -`; - - const readmePath = path.join(rooDir, "README.md"); - await fileManager.writeFile(readmePath, rooReadme); - console.log(chalk.green("✓ Created .roo/README.md")); - console.log(chalk.green(`\n✓ Roo Code setup complete!`)); - console.log( - chalk.dim( - "Custom modes will be available when you open this project in Roo Code" - ) - ); + console.log(chalk.dim("Custom modes will be available when you open this project in Roo Code")); return true; }