diff --git a/docs/how-to/monorepo-setup.md b/docs/how-to/monorepo-setup.md new file mode 100644 index 000000000..4aea2fb48 --- /dev/null +++ b/docs/how-to/monorepo-setup.md @@ -0,0 +1,79 @@ +--- +title: "Set Up Monorepo Support" +description: Manage multiple projects in a single repository with isolated artifacts +sidebar: + order: 8 +--- + +BMad Method supports working in monorepo environments where multiple projects share a single repository. This allows you to centralize methodology files while keeping project artifacts isolated and organized. + +:::note[Prerequisites] +- BMad Method v6.0.1+ +- A repository containing multiple projects +::: + +## Why Use Monorepo Support? + +In a standard setup, BMad expects one project per repository. In a monorepo, you might have `apps/frontend`, `apps/backend`, and `packages/shared`. Without monorepo support, BMad's artifacts (plans, architecture, stories) would be mixed or require installing BMad in every sub-directory. + +Monorepo support allows you to: +- **Centralize Methodology**: Install BMad once at the root based on your team's process. +- **Isolate Artifacts**: Automatically route outputs to project-specific folders (e.g., `_bmad-output/frontend/`). +- **Context Switch Easily**: Switch between projects without reinstalling or reconfiguring. + +## Project Structure + +When monorepo support is active, the structure changes slightly to accommodate multiple projects: + +``` +monorepo-root/ +├── _bmad/ # Methodology (installed core & modules) +│ └── .current_project # Context marker (e.g., "app-alpha") +├── _bmad-output/ # Unified output directory +│ ├── app-alpha/ # Sub-project artifacts +│ │ ├── planning-artifacts/ +│ │ └── implementation-artifacts/ +│ └── app-beta/ # Sub-project artifacts +│ └── planning-artifacts/ +├── apps/ # Actual source code +│ ├── app-alpha/ +│ └── app-beta/ +└── package.json +``` + +## How It Works + +### Context Injection + +Core and BMM workflows automatically check for the existence of `_bmad/.current_project`. +- **If found**: It reads the content (e.g., "app-alpha") and overrides the `output_folder` to `_bmad-output/app-alpha`. +- **If not found**: It behaves like a standard single-project installation, outputting to `_bmad-output` root. + +### The /set-project Command + +You can easily manage the active project context using the `/set-project` workflow. + +**To set a context:** +1. Run `/set-project` in your chat. +2. Select "Set Project Context". +3. Enter the name of your project (e.g., `frontend`, `backend`, `mobile-app`). + +**To clear context (return to single-project mode):** +1. Run `/set-project`. +2. Select "Clear Project Context". + +### Inline Override + +You can temporarily override the project context for a specific command without changing the global `.current_project` state. This is useful for one-off tasks in a different project. + +Use the `#project:` syntax (or `#p:` for short) anywhere in your prompt: + +```bash +# Full syntax +/create-prd #project:myproject_name + +# Short alias +/create-story #p:frontend +``` + +**Note:** The inline override takes precedence over the `.current_project` file. If no project is specified via `#` or `.current_project`, BMad defaults to the root `_bmad-output` folder. diff --git a/docs/index.md b/docs/index.md index 5ae60e922..dba1fccf9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -18,6 +18,12 @@ The fastest way to understand BMad is to try it. Install BMad and run `/bmad-help` — it will guide you through everything based on your project and installed modules. ::: +## Advanced Setup + +- **[Monorepo Support](./how-to/monorepo-setup.md)** — Manage multiple projects in a single repository. +- **[Non-Interactive Installation](./how-to/non-interactive-installation.md)** — Automate BMad installation for CI/CD. + + ## How to Use These Docs These docs are organized into four sections based on what you're trying to do: diff --git a/package.json b/package.json index cd02e3746..8166acb2d 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "test": "npm run test:schemas && npm run test:refs && npm run test:install && npm run validate:schemas && npm run lint && npm run lint:md && npm run format:check", "test:coverage": "c8 --reporter=text --reporter=html npm run test:schemas", "test:install": "node test/test-installation-components.js", + "test:monorepo": "node test/test-monorepo-validation.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", diff --git a/src/bmm/module-help.csv b/src/bmm/module-help.csv index 635bb8a81..a77860a06 100644 --- a/src/bmm/module-help.csv +++ b/src/bmm/module-help.csv @@ -28,4 +28,5 @@ bmm,4-implementation,Create Story,CS,30,_bmad/bmm/workflows/4-implementation/cre bmm,4-implementation,Dev Story,DS,40,_bmad/bmm/workflows/4-implementation/dev-story/workflow.yaml,bmad-bmm-dev-story,true,dev,Create Mode,"Story cycle: Execute story implementation tasks and tests then CR then back to DS if fixes needed",,, bmm,4-implementation,Code Review,CR,50,_bmad/bmm/workflows/4-implementation/code-review/workflow.yaml,bmad-bmm-code-review,false,dev,Create Mode,"Story cycle: If issues back to DS if approved then next CS or ER if epic complete",,, bmm,4-implementation,QA Automation Test,QA,45,_bmad/bmm/workflows/qa/automate/workflow.yaml,bmad-bmm-qa-automate,false,qa,Create Mode,"Generate automated API and E2E tests for implemented code using the project's existing test framework (detects existing well known in use test frameworks). Use after implementation to add test coverage. NOT for code review or story validation - use CR for that.",implementation_artifacts,"test suite", +bmm,anytime,Set Project,SPJ,05,_bmad/bmm/workflows/0-context/set-project/workflow.md,bmad-set-project,false,bmad-master,Anytime,"Set or clear the current project context for monorepo support.",_bmad,.current_project, bmm,4-implementation,Retrospective,ER,60,_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml,bmad-bmm-retrospective,false,sm,Create Mode,"Optional at epic end: Review completed work lessons learned and next epic or if major issues consider CC",implementation_artifacts,retrospective, diff --git a/src/bmm/workflows/0-context/set-project/workflow.md b/src/bmm/workflows/0-context/set-project/workflow.md new file mode 100644 index 000000000..51fa848c2 --- /dev/null +++ b/src/bmm/workflows/0-context/set-project/workflow.md @@ -0,0 +1,49 @@ +--- +name: set-project +description: Set the current project context for monorepo support +main_config: '{project-root}/_bmad/bmm/config.yaml' +--- + +# Set Project Context + +**Goal:** Configure the active project path for BMAD artifacts. + +**Your Role:** Configuration Assistant. + +## WORKFLOW ARCHITECTURE + +This is a single-step workflow that updates a local state file. + +### 1. Configuration Loading + +Load and read full config from {main_config} and resolve basic variables. + +### 2. Context Management + +1. **Ask User:** "Please enter the **project name** or path relative to `_bmad-output/` (e.g. `project-name` or `libs/auth-lib`). Enter `CLEAR` to reset to root." +2. **Wait for Input.** +3. **Process Input:** + - **Case: CLEAR**: + - Delete file: `{project-root}/_bmad/.current_project` + - Output: "✅ Project context cleared. Artifacts will go to root `_bmad-output/`." + - **Case: Path Provided**: + - **Sanitize:** Remove leading `/` or `_bmad-output/` if present in the input. + - Write file: `{project-root}/_bmad/.current_project` with content `` + - Output: "✅ Project context set to: ``. Artifacts will go to `_bmad-output//`." + +### 3. Verification + +- Display the full resolved output path for confirmation. + +## Inline Project Overrides + +You can also temporarily run a command against a different project without changing the global context file. Use the `#project:NAME` or `#p:NAME` syntax in your command invocation. + +**Examples:** +- `/create-prd #project:my-app` +- `/sprint-planning #p:admin-portal` + +**Precedence:** +1. **Inline Override** (`#p:NAME`) +2. **Global Context File** (`_bmad/.current_project`) +3. **Default Config** (if neither is present) diff --git a/src/bmm/workflows/1-analysis/create-product-brief/workflow.md b/src/bmm/workflows/1-analysis/create-product-brief/workflow.md index 9d5e83f19..14a9084a5 100644 --- a/src/bmm/workflows/1-analysis/create-product-brief/workflow.md +++ b/src/bmm/workflows/1-analysis/create-product-brief/workflow.md @@ -1,6 +1,7 @@ --- name: create-product-brief description: Create comprehensive product briefs through collaborative step-by-step discovery as creative Business Analyst working with the user as peers. +main_config: '{project-root}/_bmad/bmm/config.yaml' --- # Product Brief Workflow @@ -48,7 +49,7 @@ This uses **step-file architecture** for disciplined execution: ### 1. Configuration Loading -Load and read full config from {project-root}/_bmad/bmm/config.yaml and resolve: +Load and read full config from {main_config} and resolve basic variables. - `project_name`, `output_folder`, `planning_artifacts`, `user_name`, `communication_language`, `document_output_language`, `user_skill_level` diff --git a/src/bmm/workflows/1-analysis/research/workflow-domain-research.md b/src/bmm/workflows/1-analysis/research/workflow-domain-research.md index 91fcbaa9a..f17a7d907 100644 --- a/src/bmm/workflows/1-analysis/research/workflow-domain-research.md +++ b/src/bmm/workflows/1-analysis/research/workflow-domain-research.md @@ -1,6 +1,7 @@ --- name: domain-research description: Conduct domain research covering industry analysis, regulations, technology trends, and ecosystem dynamics using current web data and verified sources. +main_config: '{project-root}/_bmad/bmm/config.yaml' --- # Domain Research Workflow @@ -15,7 +16,11 @@ description: Conduct domain research covering industry analysis, regulations, te ## CONFIGURATION -Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: +### 1. Configuration Loading + +Load and read full config from {main_config} and resolve basic variables. + + - `project_name`, `output_folder`, `planning_artifacts`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` - `date` as a system-generated value diff --git a/src/bmm/workflows/1-analysis/research/workflow-market-research.md b/src/bmm/workflows/1-analysis/research/workflow-market-research.md index 5669e6f24..06501fdb1 100644 --- a/src/bmm/workflows/1-analysis/research/workflow-market-research.md +++ b/src/bmm/workflows/1-analysis/research/workflow-market-research.md @@ -1,6 +1,7 @@ --- name: market-research description: Conduct market research covering market size, growth, competition, and customer insights using current web data and verified sources. +main_config: '{project-root}/_bmad/bmm/config.yaml' --- # Market Research Workflow @@ -15,7 +16,11 @@ description: Conduct market research covering market size, growth, competition, ## CONFIGURATION -Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: +### 1. Configuration Loading + +Load and read full config from {main_config} and resolve basic variables. + + - `project_name`, `output_folder`, `planning_artifacts`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` - `date` as a system-generated value diff --git a/src/bmm/workflows/1-analysis/research/workflow-technical-research.md b/src/bmm/workflows/1-analysis/research/workflow-technical-research.md index 2ac5420ce..778def8c7 100644 --- a/src/bmm/workflows/1-analysis/research/workflow-technical-research.md +++ b/src/bmm/workflows/1-analysis/research/workflow-technical-research.md @@ -1,6 +1,7 @@ --- name: technical-research description: Conduct technical research covering technology evaluation, architecture decisions, and implementation approaches using current web data and verified sources. +main_config: '{project-root}/_bmad/bmm/config.yaml' --- # Technical Research Workflow @@ -15,7 +16,11 @@ description: Conduct technical research covering technology evaluation, architec ## CONFIGURATION -Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: +### 1. Configuration Loading + +Load and read full config from {main_config} and resolve basic variables. + + - `project_name`, `output_folder`, `planning_artifacts`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` - `date` as a system-generated value diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md b/src/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md index 7d10ec3ed..7007ab8fb 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md @@ -46,10 +46,6 @@ This uses **step-file architecture** for disciplined execution: ## INITIALIZATION SEQUENCE -### 1. Configuration Loading - -Load and read full config from {main_config} and resolve: - - `project_name`, `output_folder`, `planning_artifacts`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` - `date` as system-generated current datetime diff --git a/src/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md b/src/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md index 5cb05af53..37731b4c5 100644 --- a/src/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md +++ b/src/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md @@ -48,7 +48,7 @@ This uses **step-file architecture** for disciplined execution: ### 1. Configuration Loading -Load and read full config from {main_config} and resolve: +Load and read full config from {main_config} and resolve basic variables. - `project_name`, `output_folder`, `planning_artifacts`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` 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 e21745139..7b17c8026 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 @@ -48,7 +48,8 @@ This uses **step-file architecture** for disciplined execution: ### 1. Configuration Loading -Load and read full config from {main_config} and resolve: +Load and read full config from {main_config} and resolve basic variables. + - `project_name`, `output_folder`, `planning_artifacts`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` 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..f00c76256 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 @@ -22,9 +22,10 @@ This uses **micro-file architecture** for disciplined execution: ## INITIALIZATION -### Configuration Loading +### 1. Configuration Loading + +Load and read full config from {main_config} and resolve basic variables. -Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: - `project_name`, `output_folder`, `planning_artifacts`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` 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..58b12630d 100644 --- a/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md +++ b/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md @@ -42,9 +42,9 @@ description: 'Critical validation workflow that assesses PRD, Architecture, and ## INITIALIZATION SEQUENCE -### 1. Module Configuration Loading +### 1. Configuration Loading -Load and read full config from {project-root}/_bmad/bmm/config.yaml and resolve: +Load and read full config from {main_config} and resolve basic variables. - `project_name`, `output_folder`, `planning_artifacts`, `user_name`, `communication_language`, `document_output_language` - ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}` diff --git a/src/bmm/workflows/3-solutioning/create-architecture/workflow.md b/src/bmm/workflows/3-solutioning/create-architecture/workflow.md index b75b4a46c..100432e4e 100644 --- a/src/bmm/workflows/3-solutioning/create-architecture/workflow.md +++ b/src/bmm/workflows/3-solutioning/create-architecture/workflow.md @@ -25,7 +25,9 @@ This uses **micro-file architecture** for disciplined execution: ## INITIALIZATION -### Configuration Loading +### 1. Configuration Loading + +Load and read full config from {main_config} and resolve basic variables. Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: diff --git a/src/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md b/src/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md index a0e232ab8..6d449749e 100644 --- a/src/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md +++ b/src/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md @@ -48,7 +48,8 @@ This uses **step-file architecture** for disciplined execution: ### 1. Configuration Loading -Load and read full config from {project-root}/_bmad/bmm/config.yaml and resolve: +Load and read full config from {main_config} and resolve basic variables. + - `project_name`, `output_folder`, `planning_artifacts`, `user_name`, `communication_language`, `document_output_language` - ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}` diff --git a/src/bmm/workflows/4-implementation/code-review/instructions.xml b/src/bmm/workflows/4-implementation/code-review/instructions.xml index e5649559d..becdbc943 100644 --- a/src/bmm/workflows/4-implementation/code-review/instructions.xml +++ b/src/bmm/workflows/4-implementation/code-review/instructions.xml @@ -16,6 +16,21 @@ + + Read content as project_suffix + + Trim whitespace and newlines from project_suffix + + 🚫 Security Error: Invalid project context path detected. + HALT + + + 🚫 Error: Project context must only contain alphanumeric characters, dots, dashes, or underscores. + HALT + + Override output_folder to {project-root}/_bmad-output/{project_suffix} + + Use provided {{story_path}} or ask user which story file to review Read COMPLETE story file Set {{story_key}} = extracted key from filename (e.g., "1-2-user-authentication.md" → "1-2-user-authentication") or story @@ -41,6 +56,7 @@ Load {project_context} for coding standards (if exists) + diff --git a/src/bmm/workflows/4-implementation/correct-course/instructions.md b/src/bmm/workflows/4-implementation/correct-course/instructions.md index bbe2c21e0..023c8c4fd 100644 --- a/src/bmm/workflows/4-implementation/correct-course/instructions.md +++ b/src/bmm/workflows/4-implementation/correct-course/instructions.md @@ -40,7 +40,7 @@ - [x] Done - Item completed successfully - [N/A] Skip - Item not applicable to this change - [!] Action-needed - Item requires attention or follow-up - Maintain running notes of findings and impacts discovered + Present checklist progress after each major section Identify blocking issues and work with user to resolve before continuing diff --git a/src/bmm/workflows/4-implementation/create-story/instructions.xml b/src/bmm/workflows/4-implementation/create-story/instructions.xml index f9433371f..d7b7158aa 100644 --- a/src/bmm/workflows/4-implementation/create-story/instructions.xml +++ b/src/bmm/workflows/4-implementation/create-story/instructions.xml @@ -18,6 +18,7 @@ 🎯 ZERO USER INTERVENTION: Process should be fully automated except for initial epic/story selection or missing documents + Parse user-provided story path: extract epic_num, story_num, story_title from format like "1-2-user-auth" Set {{epic_num}}, {{story_num}}, {{story_key}} from user input @@ -260,48 +261,52 @@ 📝 CREATE ULTIMATE STORY FILE - The developer's master implementation guide! + + Set {target_story_file} = {output_folder}/{story_key}.md + Output "Generating story file at: {target_story_file}" + Initialize from template.md: - {default_output_file} - story_header + {target_story_file} + story_header story_requirements + file="{target_story_file}">story_requirements - - developer_context_section **DEV AGENT GUARDRAILS:** + + developer_context_section **DEV AGENT GUARDRAILS:** technical_requirements - architecture_compliance + architecture_compliance library_framework_requirements - + file="{target_story_file}">library_framework_requirements + file_structure_requirements - testing_requirements + testing_requirements - previous_story_intelligence + previous_story_intelligence - git_intelligence_summary + git_intelligence_summary - latest_tech_information + latest_tech_information project_context_reference + file="{target_story_file}">project_context_reference - + story_completion_status diff --git a/src/bmm/workflows/4-implementation/dev-story/instructions.xml b/src/bmm/workflows/4-implementation/dev-story/instructions.xml index 3c4989f39..aa8308404 100644 --- a/src/bmm/workflows/4-implementation/dev-story/instructions.xml +++ b/src/bmm/workflows/4-implementation/dev-story/instructions.xml @@ -13,6 +13,7 @@ User skill level ({user_skill_level}) affects conversation style ONLY, not code updates. + Use {{story_path}} directly Read COMPLETE story file @@ -376,8 +377,6 @@ Communicate to {user_name} that story implementation is complete and ready for review Summarize key accomplishments: story ID, story key, title, key changes made, tests added, files modified - Provide the story file path and current status (now "review") - Based on {user_skill_level}, ask if user needs any explanations about: - What was implemented and how it works - Why certain technical decisions were made diff --git a/src/bmm/workflows/4-implementation/retrospective/instructions.md b/src/bmm/workflows/4-implementation/retrospective/instructions.md index 018ef6ee3..762f5a6ef 100644 --- a/src/bmm/workflows/4-implementation/retrospective/instructions.md +++ b/src/bmm/workflows/4-implementation/retrospective/instructions.md @@ -1,7 +1,9 @@ # Retrospective - Epic Completion Review Instructions The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml -You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml +You MUST have already loaded and processed: {installed_path}/workflow.yaml + + Communicate all responses in {communication_language} and language MUST be tailored to {user_skill_level} Generate all documents in {document_output_language} ⚠️ ABSOLUTELY NO TIME ESTIMATES - NEVER mention hours, days, weeks, months, or ANY time-based predictions. AI has fundamentally changed development speed - what once took teams weeks/months can now be done by one person in hours. DO NOT give ANY time estimates whatsoever. diff --git a/src/bmm/workflows/4-implementation/sprint-planning/instructions.md b/src/bmm/workflows/4-implementation/sprint-planning/instructions.md index 316d2fec3..e87110c27 100644 --- a/src/bmm/workflows/4-implementation/sprint-planning/instructions.md +++ b/src/bmm/workflows/4-implementation/sprint-planning/instructions.md @@ -3,7 +3,9 @@ The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/sprint-planning/workflow.yaml -## 📚 Document Discovery - Full Epic Loading +## 📚 Document Discovery + +- Full Epic Loading **Strategy**: Sprint planning needs ALL epics and stories to build complete status tracking. diff --git a/src/bmm/workflows/4-implementation/sprint-status/instructions.md b/src/bmm/workflows/4-implementation/sprint-status/instructions.md index 4182e1f25..43b5e1316 100644 --- a/src/bmm/workflows/4-implementation/sprint-status/instructions.md +++ b/src/bmm/workflows/4-implementation/sprint-status/instructions.md @@ -1,6 +1,7 @@ # Sprint Status - Multi-Mode Service The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml + You MUST have already loaded and processed: {project-root}/_bmad/bmm/workflows/4-implementation/sprint-status/workflow.yaml Modes: interactive (default), validate, data ⚠️ ABSOLUTELY NO TIME ESTIMATES. Do NOT mention hours, days, weeks, or timelines. diff --git a/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md b/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md index 8c6a1902b..56fa658e1 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md @@ -23,7 +23,9 @@ This uses **step-file architecture** for focused execution: ## INITIALIZATION -### Configuration Loading +### 1. Configuration Loading + +Load and read full config from {main_config} and resolve basic variables. Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: diff --git a/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md b/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md index cc4fdf221..ad027deb7 100644 --- a/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +++ b/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md @@ -66,8 +66,9 @@ This uses **step-file architecture** for disciplined execution: ### 1. Configuration Loading -Load and read full config from `{main_config}` and resolve: +Load and read full config from {main_config} and resolve basic variables. +Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: - `project_name`, `planning_artifacts`, `implementation_artifacts`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` - `date` as system-generated current datetime diff --git a/src/bmm/workflows/document-project/instructions.md b/src/bmm/workflows/document-project/instructions.md index 0354be610..d6a685c3d 100644 --- a/src/bmm/workflows/document-project/instructions.md +++ b/src/bmm/workflows/document-project/instructions.md @@ -79,6 +79,11 @@ +## 1. Configuration Loading + +Load and read full config from {main_config} and resolve basic variables. + + Check if {project_knowledge}/index.md exists 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 637621c4c..17b7768d9 100644 --- a/src/bmm/workflows/document-project/workflows/deep-dive-instructions.md +++ b/src/bmm/workflows/document-project/workflows/deep-dive-instructions.md @@ -11,6 +11,23 @@ Load existing project structure from index.md and project-parts.json (if exists) Load source tree analysis to understand available areas + + Read content as project_suffix + + Trim whitespace and newlines from project_suffix + + 🚫 Security Error: Invalid project context path detected. + HALT + + + 🚫 Error: Project context must only contain alphanumeric characters, dots, dashes, or underscores. + HALT + + Override output_folder to {project-root}/_bmad-output/{project_suffix} + Override project_knowledge to {project-root}/_bmad-output/{project_suffix} + Output "Monorepo context detected. Writing deep-dive artifacts to: {project_knowledge}" + + Analyze existing documentation to suggest deep-dive options @@ -250,8 +267,11 @@ Detailed exhaustive analysis of specific areas: - Complete file inventory with all exports - Dependency graph and data flow -- Integration points and API contracts -- Testing analysis and coverage +### 1. Configuration Loading + +Load and read full config from {main_config} and resolve basic variables. + + - Related code and reuse opportunities - Implementation guidance 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 8a3621d21..6e3a3fed3 100644 --- a/src/bmm/workflows/document-project/workflows/full-scan-instructions.md +++ b/src/bmm/workflows/document-project/workflows/full-scan-instructions.md @@ -95,6 +95,8 @@ Your choice [1/2/3]: - Best for: Quick project overview, initial understanding - File reading: Minimal (configs, README, package.json, etc.) + + **2. Deep Scan** (10-30 minutes) - Reads files in critical directories based on project type diff --git a/src/bmm/workflows/generate-project-context/workflow.md b/src/bmm/workflows/generate-project-context/workflow.md index 3f626d65f..749016fec 100644 --- a/src/bmm/workflows/generate-project-context/workflow.md +++ b/src/bmm/workflows/generate-project-context/workflow.md @@ -25,9 +25,10 @@ This uses **micro-file architecture** for disciplined execution: ## INITIALIZATION -### Configuration Loading +### 1. Configuration Loading + +Load and read full config from {main_config} and resolve basic variables. -Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve: - `project_name`, `output_folder`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` diff --git a/src/bmm/workflows/qa/automate/instructions.md b/src/bmm/workflows/qa/automate/instructions.md index 03653337f..561a80581 100644 --- a/src/bmm/workflows/qa/automate/instructions.md +++ b/src/bmm/workflows/qa/automate/instructions.md @@ -18,6 +18,7 @@ Check project for existing test framework: - Search online for current recommended test framework for that stack - Suggest the meta framework and use it (or ask user to confirm) + ### Step 1: Identify Features Ask user what to test: diff --git a/src/core/tasks/workflow.xml b/src/core/tasks/workflow.xml index 536c9d8e7..2b5503135 100644 --- a/src/core/tasks/workflow.xml +++ b/src/core/tasks/workflow.xml @@ -18,7 +18,11 @@ - + + {{monorepo_context_logic}} + + + Read workflow.yaml from provided path Load config_source (REQUIRED for all modules) Load external config from config_source path @@ -27,7 +31,7 @@ Ask user for input of any variables that are still unknown - + Instructions: Read COMPLETE file from path OR embedded list (REQUIRED) If template path → Read COMPLETE template file If validation path → Note path for later loading when needed @@ -35,7 +39,7 @@ Data files (csv, json) → Store paths only, load on-demand when instructions reference them - + Resolve default_output_file path with all variables and {{date}} Create output directory if doesn't exist If template-workflow → Write template to output file with placeholders diff --git a/src/core/workflows/advanced-elicitation/workflow.xml b/src/core/workflows/advanced-elicitation/workflow.xml index ea7395e41..edce339f8 100644 --- a/src/core/workflows/advanced-elicitation/workflow.xml +++ b/src/core/workflows/advanced-elicitation/workflow.xml @@ -20,6 +20,22 @@ + + + Read content as project_suffix + + Trim whitespace and newlines from project_suffix + + 🚫 Security Error: Invalid project context path detected. + HALT + + + 🚫 Error: Project context must only contain alphanumeric characters, dots, dashes, or underscores. + HALT + + Override output_folder to {project-root}/_bmad-output/{project_suffix} + + Load and read {{methods}} and {{agent-party}} diff --git a/src/core/workflows/brainstorming/workflow.md b/src/core/workflows/brainstorming/workflow.md index 3190c983c..fb983a730 100644 --- a/src/core/workflows/brainstorming/workflow.md +++ b/src/core/workflows/brainstorming/workflow.md @@ -32,9 +32,10 @@ This uses **micro-file architecture** for disciplined execution: ## INITIALIZATION -### Configuration Loading +### 1. Configuration Loading + +Load and read full config from {main_config} and resolve basic variables. -Load config from `{project-root}/_bmad/core/config.yaml` and resolve: - `project_name`, `output_folder`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` diff --git a/src/core/workflows/party-mode/workflow.md b/src/core/workflows/party-mode/workflow.md index eaec3c931..183968f7d 100644 --- a/src/core/workflows/party-mode/workflow.md +++ b/src/core/workflows/party-mode/workflow.md @@ -25,9 +25,9 @@ This uses **micro-file architecture** with **sequential conversation orchestrati ## INITIALIZATION -### Configuration Loading +### 1. Configuration Loading -Load config from `{project-root}/_bmad/core/config.yaml` and resolve: +Load and read full config from {main_config} and resolve basic variables. - `project_name`, `output_folder`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` diff --git a/test/test-context-logic-integration.js b/test/test-context-logic-integration.js new file mode 100644 index 000000000..75a40d8d4 --- /dev/null +++ b/test/test-context-logic-integration.js @@ -0,0 +1,206 @@ +/** + * Context Logic Integration Tests + * + * Validates the centralized monorepo context logic deduplication: + * 1. context-logic.js exports a valid XML block + * 2. All workflow templates that need it use the {{monorepo_context_logic}} placeholder + * 3. No stale hardcoded blocks exist in templates + * 4. src/core/tasks/workflow.xml uses the placeholder (not a hardcoded block) + * 5. All JS consumers correctly import context-logic.js + * 6. MONOREPO_CONTEXT_LOGIC string integrity (key fields are present) + */ + +const fs = require('fs-extra'); +const path = require('node:path'); + +// ANSI colors +const c = { + reset: '\u001B[0m', + green: '\u001B[32m', + red: '\u001B[31m', + yellow: '\u001B[33m', + cyan: '\u001B[36m', + dim: '\u001B[2m', +}; + +let passed = 0; +let failed = 0; + +function ok(condition, testName, detail = '') { + if (condition) { + console.log(`${c.green}✓${c.reset} ${testName}`); + passed++; + } else { + console.log(`${c.red}✗${c.reset} ${testName}`); + if (detail) console.log(` ${c.dim}${detail}${c.reset}`); + failed++; + } +} + +async function readFile(p) { + return fs.readFile(p, 'utf8'); +} + +async function exists(p) { + return fs.pathExists(p); +} + +async function runTests() { + console.log(`${c.cyan}============================================================`); + console.log(' Context Logic Integration Tests'); + console.log(`============================================================${c.reset}\n`); + + const root = path.join(__dirname, '..'); + const sharedDir = path.join(root, 'tools/cli/installers/lib/ide/shared'); + const templatesDir = path.join(root, 'tools/cli/installers/lib/ide/templates'); + const combinedDir = path.join(templatesDir, 'combined'); + + // ──────────────────────────────────────────────────────────── + // Suite 1: context-logic.js module integrity + // ──────────────────────────────────────────────────────────── + console.log(`${c.yellow}Suite 1: context-logic.js module integrity${c.reset}\n`); + + const contextLogicPath = path.join(sharedDir, 'context-logic.js'); + ok(await exists(contextLogicPath), 'context-logic.js file exists'); + + let MONOREPO_CONTEXT_LOGIC; + try { + const mod = require(contextLogicPath); + ok(typeof mod.MONOREPO_CONTEXT_LOGIC === 'string', 'exports MONOREPO_CONTEXT_LOGIC as a string'); + ok(mod.MONOREPO_CONTEXT_LOGIC.length > 0, 'MONOREPO_CONTEXT_LOGIC is non-empty'); + MONOREPO_CONTEXT_LOGIC = mod.MONOREPO_CONTEXT_LOGIC; + } catch (error) { + ok(false, 'context-logic.js is require()-able', error.message); + MONOREPO_CONTEXT_LOGIC = ''; + } + + // Key content checks + ok(MONOREPO_CONTEXT_LOGIC.includes(' tag'); + ok(MONOREPO_CONTEXT_LOGIC.includes(''), 'has closing tag'); + ok(MONOREPO_CONTEXT_LOGIC.includes('#project:NAME'), 'documents #project:NAME syntax'); + ok(MONOREPO_CONTEXT_LOGIC.includes('#p:NAME'), 'documents #p:NAME short alias'); + ok(MONOREPO_CONTEXT_LOGIC.includes('.current_project'), 'includes .current_project fallback logic'); + ok(MONOREPO_CONTEXT_LOGIC.includes('path traversal'), 'includes path traversal security check'); + ok(MONOREPO_CONTEXT_LOGIC.includes('output_folder'), 'overrides output_folder path variable'); + ok(MONOREPO_CONTEXT_LOGIC.includes('planning_artifacts'), 'overrides planning_artifacts path variable'); + ok(MONOREPO_CONTEXT_LOGIC.includes('HALT'), 'halts on security violation'); + console.log(''); + + // ──────────────────────────────────────────────────────────── + // Suite 2: JS consumers import context-logic.js correctly + // ──────────────────────────────────────────────────────────── + console.log(`${c.yellow}Suite 2: JS consumers import context-logic.js${c.reset}\n`); + + const consumers = [ + { + file: 'tools/cli/installers/lib/core/installer.js', + expectedImport: "require('../ide/shared/context-logic')", + }, + { + file: 'tools/cli/installers/lib/ide/_config-driven.js', + expectedImport: "require('./shared/context-logic')", + }, + { + file: 'tools/cli/installers/lib/ide/shared/workflow-command-generator.js', + expectedImport: "require('./context-logic')", + }, + ]; + + for (const { file, expectedImport } of consumers) { + const fullPath = path.join(root, file); + const content = await readFile(fullPath); + ok(content.includes(expectedImport), `${path.basename(file)} imports context-logic correctly`); + ok(content.includes("replaceAll('{{monorepo_context_logic}}'"), `${path.basename(file)} uses replaceAll for placeholder`); + } + console.log(''); + + // ──────────────────────────────────────────────────────────── + // Suite 3: Templates use placeholder, not hardcoded blocks + // ──────────────────────────────────────────────────────────── + console.log(`${c.yellow}Suite 3: Templates use {{monorepo_context_logic}} placeholder${c.reset}\n`); + + // These templates MUST have the placeholder (they are rendered directly as IDE workflow commands) + const mustHavePlaceholder = [ + path.join(templatesDir, 'workflow-command-template.md'), + path.join(templatesDir, 'workflow-commander.md'), + path.join(combinedDir, 'antigravity.md'), + path.join(combinedDir, 'claude-workflow.md'), + path.join(combinedDir, 'claude-workflow-yaml.md'), + path.join(combinedDir, 'default-workflow.md'), + path.join(combinedDir, 'default-workflow-yaml.md'), + path.join(combinedDir, 'kiro-workflow.md'), + path.join(combinedDir, 'opencode-workflow.md'), + path.join(combinedDir, 'windsurf-workflow.md'), + ]; + + for (const filePath of mustHavePlaceholder) { + const rel = path.relative(root, filePath); + const content = await readFile(filePath); + ok(content.includes('{{monorepo_context_logic}}'), `${path.basename(filePath)} has {{monorepo_context_logic}} placeholder`); + // Must NOT have raw hardcoded block (only the shared module should have it) + ok(!content.includes(' block`); + } + console.log(''); + + // ──────────────────────────────────────────────────────────── + // Suite 4: No rogue hardcoded blocks anywhere in templates dir + // ──────────────────────────────────────────────────────────── + console.log(`${c.yellow}Suite 4: No hardcoded blocks in templates directory${c.reset}\n`); + + const walkDir = async (dir) => { + const entries = await fs.readdir(dir, { withFileTypes: true }); + const files = []; + for (const e of entries) { + const full = path.join(dir, e.name); + if (e.isDirectory()) files.push(...(await walkDir(full))); + else if (e.isFile()) files.push(full); + } + return files; + }; + + const allTemplateFiles = await walkDir(templatesDir); + const rogueFiles = []; + for (const f of allTemplateFiles) { + const content = await readFile(f); + if (content.includes(' blocks in templates (found ${rogueFiles.length})`, + rogueFiles.length > 0 ? `Rogue files: ${rogueFiles.join(', ')}` : '', + ); + console.log(''); + + // ──────────────────────────────────────────────────────────── + // Suite 5: src/core/tasks/workflow.xml uses placeholder + // ──────────────────────────────────────────────────────────── + console.log(`${c.yellow}Suite 5: src/core/tasks/workflow.xml uses placeholder${c.reset}\n`); + + const srcWorkflowXml = path.join(root, 'src/core/tasks/workflow.xml'); + ok(await exists(srcWorkflowXml), 'src/core/tasks/workflow.xml exists'); + const srcXmlContent = await readFile(srcWorkflowXml); + ok(srcXmlContent.includes('{{monorepo_context_logic}}'), 'workflow.xml (src) uses {{monorepo_context_logic}} placeholder'); + ok(!srcXmlContent.includes(' block'); + + // ──────────────────────────────────────────────────────────── + // Results + // ──────────────────────────────────────────────────────────── + console.log(`\n${c.cyan}============================================================`); + console.log(` Results: ${c.green}${passed} passed${c.reset}${c.cyan}, ${c.red}${failed} failed${c.reset}${c.cyan}`); + console.log(`============================================================${c.reset}\n`); + + if (failed === 0) { + console.log(`${c.green}✨ All context-logic integration tests passed!${c.reset}\n`); + process.exit(0); + } else { + console.log(`${c.red}❌ ${failed} test(s) failed${c.reset}\n`); + process.exit(1); + } +} + +runTests().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/test/test-monorepo-validation.js b/test/test-monorepo-validation.js new file mode 100644 index 000000000..0b696390e --- /dev/null +++ b/test/test-monorepo-validation.js @@ -0,0 +1,133 @@ +/** + * Monorepo Support Validation Tests + * + * Architecture after deduplication: + * - Monorepo context logic lives ONLY in context-logic.js + * - workflow.xml (src) uses {{monorepo_context_logic}} placeholder → injected at install time + * - Individual source workflow files do NOT have inline checks (that's the deduplication!) + * - Only code-review/instructions.xml, dev-story/instructions.xml, create-story/instructions.xml + * and advanced-elicitation/workflow.xml are XML workflows checked; XML workflows that go through + * workflow.xml no longer need inline checks. + * + * Verifies: + * 1. The set-project workflow is correctly registered. + * 2. No source workflow file has a stale inline "Monorepo Context Check" block. + * 3. Only the canonical SINGLE source (context-logic.js) defines the check. + * 4. set-project implementation still manages .current_project. + */ + +const fs = require('fs-extra'); +const path = require('node:path'); +const glob = require('glob'); + +// ANSI colors +const colors = { + reset: '\u001B[0m', + green: '\u001B[32m', + red: '\u001B[31m', + yellow: '\u001B[33m', + cyan: '\u001B[36m', + dim: '\u001B[2m', +}; + +let passed = 0; +let failed = 0; + +function assert(condition, testName, errorMessage = '') { + if (condition) { + console.log(`${colors.green}✓${colors.reset} ${testName}`); + passed++; + } else { + console.log(`${colors.red}✗${colors.reset} ${testName}`); + if (errorMessage) { + console.log(` ${colors.dim}${errorMessage}${colors.reset}`); + } + failed++; + } +} + +async function runTests() { + console.log(`${colors.cyan}========================================`); + console.log('Monorepo Support Validation Tests'); + console.log(`========================================${colors.reset}\n`); + + const projectRoot = path.join(__dirname, '..'); + + // 1. Verify set-project registration + console.log(`${colors.yellow}Test Suite 1: Workflow Registration${colors.reset}\n`); + try { + const csvPath = path.join(projectRoot, 'src/bmm/module-help.csv'); + const content = await fs.readFile(csvPath, 'utf8'); + assert(content.includes('set-project'), 'set-project workflow is registered in module-help.csv'); + } catch (error) { + assert(false, 'Registration check failed', error.message); + } + + console.log(''); + + // 2. Verify NO stale inline "Monorepo Context Check" blocks in source workflow files + // These are redundant since workflow.xml now handles context injection via context-logic.js + console.log(`${colors.yellow}Test Suite 2: No Stale Inline Monorepo Context Checks${colors.reset}\n`); + console.log(` ${colors.dim}(Inline checks were moved to workflow.xml via context-logic.js)${colors.reset}\n`); + + const workflowFiles = glob.sync('src/{core,bmm}/workflows/**/*.{md,xml}', { cwd: projectRoot }); + + for (const file of workflowFiles) { + // skip the context-logic source itself (it's the canonical source) + if (file.includes('context-logic')) continue; + + const content = await fs.readFile(path.join(projectRoot, file), 'utf8'); + + assert(!content.includes('**Monorepo Context Check:**'), `No stale inline check block in: ${file}`); + } + + console.log(''); + + // 3. Verify canonical source is context-logic.js (single source of truth) + console.log(`${colors.yellow}Test Suite 3: Single Source of Truth${colors.reset}\n`); + + const contextLogicPath = path.join(projectRoot, 'tools/cli/installers/lib/ide/shared/context-logic.js'); + assert(await fs.pathExists(contextLogicPath), 'context-logic.js exists as canonical source'); + + const srcWorkflowXml = path.join(projectRoot, 'src/core/tasks/workflow.xml'); + const xmlContent = await fs.readFile(srcWorkflowXml, 'utf8'); + assert(xmlContent.includes('{{monorepo_context_logic}}'), 'workflow.xml uses {{monorepo_context_logic}} placeholder'); + assert(!xmlContent.includes('**Monorepo Context Check:**'), 'workflow.xml has no stale inline check'); + + console.log(''); + + // 4. Verify set-project implementation + console.log(`${colors.yellow}Test Suite 4: set-project Implementation${colors.reset}\n`); + try { + const setProjectPath = path.join(projectRoot, 'src/bmm/workflows/0-context/set-project/workflow.md'); + const exists = await fs.pathExists(setProjectPath); + assert(exists, 'set-project workflow file exists'); + if (exists) { + const content = await fs.readFile(setProjectPath, 'utf8'); + assert(content.includes('_bmad/.current_project'), 'set-project implementation manages .current_project'); + assert(content.includes('my-app'), 'set-project examples use generic public-friendly names'); + } + } catch (error) { + assert(false, 'set-project check failed', error.message); + } + + console.log('\n'); + console.log(`${colors.cyan}========================================`); + console.log('Test Results:'); + console.log(` Passed: ${colors.green}${passed}${colors.reset}`); + console.log(` Failed: ${colors.red}${failed}${colors.reset}`); + console.log(`========================================${colors.reset}\n`); + + if (failed === 0) { + console.log(`${colors.green}✨ All monorepo validation tests passed!${colors.reset}\n`); + process.exit(0); + } else { + console.log(`${colors.red}❌ Some monorepo validation tests failed${colors.reset}\n`); + process.exit(1); + } +} + +runTests().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index fe8b88d7c..e9c9518fe 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -16,6 +16,7 @@ const { IdeConfigManager } = require('./ide-config-manager'); const { CustomHandler } = require('../custom/handler'); const prompts = require('../../../lib/prompts'); const { BMAD_FOLDER_NAME } = require('../ide/shared/path-utils'); +const { MONOREPO_CONTEXT_LOGIC } = require('../ide/shared/context-logic'); class Installer { constructor() { @@ -89,6 +90,10 @@ class Installer { // Read the file content let content = await fs.readFile(sourcePath, 'utf8'); + // Apply replacements + content = content.replaceAll('{{monorepo_context_logic}}', MONOREPO_CONTEXT_LOGIC); + content = content.replaceAll('_bmad', this.bmadFolderName); + // Write to target with replaced content await fs.ensureDir(path.dirname(targetPath)); await fs.writeFile(targetPath, content, 'utf8'); diff --git a/tools/cli/installers/lib/ide/_config-driven.js b/tools/cli/installers/lib/ide/_config-driven.js index 9541c75ed..68c3a18c9 100644 --- a/tools/cli/installers/lib/ide/_config-driven.js +++ b/tools/cli/installers/lib/ide/_config-driven.js @@ -391,12 +391,15 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}} // No default } + const { MONOREPO_CONTEXT_LOGIC } = require('./shared/context-logic'); + let rendered = template .replaceAll('{{name}}', artifact.name || '') .replaceAll('{{module}}', artifact.module || 'core') .replaceAll('{{path}}', pathToUse) .replaceAll('{{description}}', artifact.description || `${artifact.name} ${artifact.type || ''}`) - .replaceAll('{{workflow_path}}', pathToUse); + .replaceAll('{{workflow_path}}', pathToUse) + .replaceAll('{{monorepo_context_logic}}', MONOREPO_CONTEXT_LOGIC); // Replace _bmad placeholder with actual folder name rendered = rendered.replaceAll('_bmad', this.bmadFolderName); diff --git a/tools/cli/installers/lib/ide/github-copilot.js b/tools/cli/installers/lib/ide/github-copilot.js index 033e8d627..082cd1543 100644 --- a/tools/cli/installers/lib/ide/github-copilot.js +++ b/tools/cli/installers/lib/ide/github-copilot.js @@ -437,9 +437,9 @@ tools: ${toolsStr} - **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}}'} +- **Output Folder**: ${configVars.output_folder || '{{output_folder}}'}/{context} (Dynamic) +- **Planning Artifacts**: ${configVars.planning_artifacts || '{{planning_artifacts}}'}/{context} (Dynamic) +- **Implementation Artifacts**: ${configVars.implementation_artifacts || '{{implementation_artifacts}}'}/{context} (Dynamic) - **Project Knowledge**: ${configVars.project_knowledge || '{{project_knowledge}}'} ## BMAD Runtime Structure diff --git a/tools/cli/installers/lib/ide/shared/context-logic.js b/tools/cli/installers/lib/ide/shared/context-logic.js new file mode 100644 index 000000000..f5fb7359e --- /dev/null +++ b/tools/cli/installers/lib/ide/shared/context-logic.js @@ -0,0 +1,48 @@ +/** + * Monorepo Context Logic XML Block + * + * robust, secure, and centralized logic for handling: + * 1. Inline project overrides (#p:NAME) + * 2. .current_project file fallback + * 3. Path variable overrides + */ +const MONOREPO_CONTEXT_LOGIC = ` + + + + Scan user's invocation message for pattern #project:NAME or #p:NAME (case-insensitive) + + Set project_suffix = extracted NAME + 🎯 Inline project override: {project_suffix} + + + + + Read {project-root}/_bmad/.current_project as project_suffix + + + + + Trim whitespace and newlines from project_suffix + + + 🚫 Security Error: Invalid project context — path traversal detected. + HALT + + + 🚫 Error: project_suffix must only contain alphanumeric characters, dots, dashes, or underscores. + HALT + + + + Override output_folder = {project-root}/_bmad-output/{project_suffix} + Override planning_artifacts = {output_folder}/planning-artifacts + Override implementation_artifacts = {output_folder}/implementation-artifacts + Override project_knowledge = {output_folder}/knowledge + Override sprint_status_file = {output_folder}/sprint-status.yaml + 🗂️ Monorepo context: {project_suffix} → outputs to {output_folder} + + +`; + +module.exports = { MONOREPO_CONTEXT_LOGIC }; diff --git a/tools/cli/installers/lib/ide/shared/workflow-command-generator.js b/tools/cli/installers/lib/ide/shared/workflow-command-generator.js index d94e77db1..985e3437b 100644 --- a/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +++ b/tools/cli/installers/lib/ide/shared/workflow-command-generator.js @@ -151,12 +151,15 @@ class WorkflowCommandGenerator { } } + const { MONOREPO_CONTEXT_LOGIC } = require('./context-logic'); + // Replace template variables return template .replaceAll('{{name}}', workflow.name) .replaceAll('{{module}}', workflow.module) .replaceAll('{{description}}', workflow.description) .replaceAll('{{workflow_path}}', workflowPath) + .replaceAll('{{monorepo_context_logic}}', MONOREPO_CONTEXT_LOGIC) .replaceAll('_bmad', this.bmadFolderName); } diff --git a/tools/cli/installers/lib/ide/templates/combined/antigravity.md b/tools/cli/installers/lib/ide/templates/combined/antigravity.md index 88e806e9d..b897563f9 100644 --- a/tools/cli/installers/lib/ide/templates/combined/antigravity.md +++ b/tools/cli/installers/lib/ide/templates/combined/antigravity.md @@ -3,6 +3,8 @@ name: '{{name}}' description: '{{description}}' --- +{{monorepo_context_logic}} + Read the entire workflow file at: {project-root}/_bmad/{{workflow_path}} Follow all instructions in the workflow file exactly as written. diff --git a/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md b/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md index 2a5e49b83..605e6c57b 100644 --- a/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md +++ b/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md @@ -7,6 +7,8 @@ disable-model-invocation: true IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded: +0. {{monorepo_context_logic}} + 1. Always LOAD the FULL @{project-root}/{{bmadFolderName}}/core/tasks/workflow.xml 2. READ its entire contents - this is the CORE OS for EXECUTING the specific workflow-config @{project-root}/{{bmadFolderName}}/{{path}} 3. Pass the yaml path @{project-root}/{{bmadFolderName}}/{{path}} as 'workflow-config' parameter to the workflow.xml instructions diff --git a/tools/cli/installers/lib/ide/templates/combined/default-workflow.md b/tools/cli/installers/lib/ide/templates/combined/default-workflow.md index 8c4fa818f..8b7d9eea6 100644 --- a/tools/cli/installers/lib/ide/templates/combined/default-workflow.md +++ b/tools/cli/installers/lib/ide/templates/combined/default-workflow.md @@ -4,4 +4,6 @@ description: '{{description}}' disable-model-invocation: true --- +{{monorepo_context_logic}} + IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{project-root}/{{bmadFolderName}}/{{path}}, READ its entire contents and follow its directions exactly! diff --git a/tools/cli/installers/lib/ide/templates/combined/kiro-workflow.md b/tools/cli/installers/lib/ide/templates/combined/kiro-workflow.md index e1847f414..2041edfdd 100644 --- a/tools/cli/installers/lib/ide/templates/combined/kiro-workflow.md +++ b/tools/cli/installers/lib/ide/templates/combined/kiro-workflow.md @@ -4,4 +4,6 @@ inclusion: manual # {{name}} -IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL #[[file:{{bmadFolderName}}/{{path}}]], READ its entire contents and follow its directions exactly! +{{monorepo_context_logic}} + +IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{project-root}/{{bmadFolderName}}/{{path}}, READ its entire contents and follow its directions exactly! diff --git a/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md b/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md index a6f5cb96f..e7596ea1d 100644 --- a/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md +++ b/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md @@ -8,6 +8,7 @@ Execute the BMAD '{{name}}' workflow. CRITICAL: You must load and follow the workflow definition exactly. WORKFLOW INSTRUCTIONS: +{{monorepo_context_logic}} 1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{path}} 2. READ its entire contents diff --git a/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md b/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md index 6366425c7..cb2b8bb2d 100644 --- a/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md +++ b/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md @@ -5,6 +5,8 @@ auto_execution_mode: "iterate" # {{name}} +{{monorepo_context_logic}} + Read the entire workflow file at {project-root}/_bmad/{{workflow_path}} Follow all instructions in the workflow file exactly as written. diff --git a/tools/cli/installers/lib/ide/templates/workflow-command-template.md b/tools/cli/installers/lib/ide/templates/workflow-command-template.md index 472c1553a..7a26a6684 100644 --- a/tools/cli/installers/lib/ide/templates/workflow-command-template.md +++ b/tools/cli/installers/lib/ide/templates/workflow-command-template.md @@ -3,6 +3,8 @@ description: '{{description}}' disable-model-invocation: true --- +{{monorepo_context_logic}} + IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded: diff --git a/tools/cli/installers/lib/ide/templates/workflow-commander.md b/tools/cli/installers/lib/ide/templates/workflow-commander.md index d49c8319d..6f9ed8759 100644 --- a/tools/cli/installers/lib/ide/templates/workflow-commander.md +++ b/tools/cli/installers/lib/ide/templates/workflow-commander.md @@ -3,4 +3,6 @@ description: '{{description}}' disable-model-invocation: true --- +{{monorepo_context_logic}} + IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{{workflow_path}}, READ its entire contents and follow its directions exactly!