bmad-method 6.0.0-alpha.9 → 6.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.augment/code_review_guidelines.yaml +271 -0
- package/.claude/skills/bmad-os-audit-file-refs/SKILL.md +6 -0
- package/.claude/skills/bmad-os-audit-file-refs/prompts/instructions.md +59 -0
- package/.claude/skills/bmad-os-changelog-social/SKILL.md +177 -0
- package/.claude/skills/bmad-os-changelog-social/examples/discord-example.md +53 -0
- package/.claude/skills/bmad-os-changelog-social/examples/linkedin-example.md +49 -0
- package/.claude/skills/bmad-os-changelog-social/examples/twitter-example.md +55 -0
- package/.claude/skills/bmad-os-diataxis-style-fix/SKILL.md +6 -0
- package/.claude/skills/bmad-os-diataxis-style-fix/prompts/instructions.md +229 -0
- package/.claude/skills/bmad-os-draft-changelog/SKILL.md +6 -0
- package/.claude/skills/bmad-os-draft-changelog/prompts/instructions.md +82 -0
- package/.claude/skills/bmad-os-gh-triage/SKILL.md +6 -0
- package/.claude/skills/bmad-os-gh-triage/prompts/agent-prompt.md +60 -0
- package/.claude/skills/bmad-os-gh-triage/prompts/instructions.md +74 -0
- package/.claude/skills/bmad-os-release-module/SKILL.md +6 -0
- package/.claude/skills/bmad-os-release-module/prompts/instructions.md +53 -0
- package/.claude/skills/bmad-os-review-pr/SKILL.md +6 -0
- package/.claude/skills/bmad-os-review-pr/prompts/instructions.md +231 -0
- package/.coderabbit.yaml +85 -0
- package/.github/CODE_OF_CONDUCT.md +128 -0
- package/.github/ISSUE_TEMPLATE/bug-report.yaml +124 -0
- package/.github/ISSUE_TEMPLATE/config.yaml +5 -2
- package/.github/ISSUE_TEMPLATE/documentation.yaml +55 -0
- package/.github/ISSUE_TEMPLATE/feature-request.md +22 -0
- package/.github/ISSUE_TEMPLATE/issue.md +32 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +13 -0
- package/.github/scripts/discord-helpers.sh +34 -0
- package/.github/workflows/coderabbit-review.yaml +22 -0
- package/.github/workflows/discord.yaml +82 -8
- package/.github/workflows/docs.yaml +64 -0
- package/.github/workflows/quality.yaml +40 -2
- package/.husky/pre-commit +13 -0
- package/.markdownlint-cli2.yaml +41 -0
- package/.prettierignore +10 -0
- package/.vscode/settings.json +4 -3
- package/CHANGELOG.md +1110 -673
- package/CNAME +1 -0
- package/CONTRIBUTING.md +97 -189
- package/CONTRIBUTORS.md +32 -0
- package/LICENSE +7 -3
- package/README.md +55 -388
- package/SECURITY.md +85 -0
- package/TRADEMARK.md +55 -0
- package/Wordmark.png +0 -0
- package/banner-bmad-method.png +0 -0
- package/docs/404.md +9 -0
- package/docs/_STYLE_GUIDE.md +370 -0
- package/docs/explanation/advanced-elicitation.md +49 -0
- package/docs/explanation/adversarial-review.md +59 -0
- package/docs/explanation/brainstorming.md +33 -0
- package/docs/explanation/established-projects-faq.md +50 -0
- package/docs/explanation/party-mode.md +59 -0
- package/docs/explanation/preventing-agent-conflicts.md +112 -0
- package/docs/explanation/project-context.md +157 -0
- package/docs/explanation/quick-flow.md +73 -0
- package/docs/explanation/why-solutioning-matters.md +77 -0
- package/docs/how-to/customize-bmad.md +172 -0
- package/docs/how-to/established-projects.md +117 -0
- package/docs/how-to/get-answers-about-bmad.md +134 -0
- package/docs/how-to/install-bmad.md +97 -0
- package/docs/how-to/non-interactive-installation.md +171 -0
- package/docs/how-to/project-context.md +136 -0
- package/docs/how-to/quick-fixes.md +123 -0
- package/docs/how-to/shard-large-documents.md +78 -0
- package/docs/how-to/upgrade-to-v6.md +97 -0
- package/docs/index.md +37 -204
- package/docs/reference/agents.md +28 -0
- package/docs/reference/commands.md +151 -0
- package/docs/reference/modules.md +76 -0
- package/docs/reference/testing.md +106 -0
- package/docs/reference/workflow-map.md +89 -0
- package/docs/roadmap.mdx +136 -0
- package/docs/tutorials/getting-started.md +273 -0
- package/eslint.config.mjs +26 -16
- package/package.json +35 -28
- package/src/bmm/agents/analyst.agent.yaml +43 -0
- package/src/bmm/agents/architect.agent.yaml +29 -0
- package/src/bmm/agents/dev.agent.yaml +38 -0
- package/src/bmm/agents/pm.agent.yaml +44 -0
- package/src/bmm/agents/qa.agent.yaml +58 -0
- package/src/bmm/agents/quick-flow-solo-dev.agent.yaml +32 -0
- package/src/bmm/agents/sm.agent.yaml +37 -0
- package/src/bmm/agents/tech-writer/tech-writer-sidecar/documentation-standards.md +224 -0
- package/src/bmm/agents/tech-writer/tech-writer.agent.yaml +46 -0
- package/src/bmm/agents/ux-designer.agent.yaml +27 -0
- package/src/bmm/data/project-context-template.md +26 -0
- package/src/bmm/module-help.csv +31 -0
- package/src/bmm/module.yaml +50 -0
- package/src/bmm/teams/default-party.csv +20 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/product-brief.template.md +10 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01-init.md +177 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md +161 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +199 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +202 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +205 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +219 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +162 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/workflow.md +57 -0
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md +137 -0
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md +229 -0
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md +238 -0
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md +206 -0
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md +234 -0
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md +444 -0
- package/src/bmm/workflows/1-analysis/research/market-steps/step-01-init.md +182 -0
- package/src/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md +237 -0
- package/src/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md +249 -0
- package/src/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md +259 -0
- package/src/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md +177 -0
- package/src/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md +476 -0
- package/src/bmm/workflows/1-analysis/research/research.template.md +29 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-01-init.md +137 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md +239 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md +248 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md +202 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md +233 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md +487 -0
- package/src/bmm/workflows/1-analysis/research/workflow-domain-research.md +54 -0
- package/src/bmm/workflows/1-analysis/research/workflow-market-research.md +54 -0
- package/src/bmm/workflows/1-analysis/research/workflow-technical-research.md +54 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/data/domain-complexity.csv +15 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md +197 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/data/project-types.csv +11 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-01-init.md +191 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-01b-continue.md +152 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +224 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md +154 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md +170 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +226 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +213 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +207 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +226 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +237 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +228 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +231 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +242 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +217 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md +124 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md +247 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01b-legacy-conversion.md +208 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-02-review.md +249 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-03-edit.md +253 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-04-complete.md +168 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +226 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02-format-detection.md +191 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02b-parity-check.md +209 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-03-density-validation.md +174 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-04-brief-coverage-validation.md +214 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-05-measurability-validation.md +228 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-06-traceability-validation.md +217 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-07-implementation-leakage-validation.md +205 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-08-domain-compliance-validation.md +243 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-09-project-type-validation.md +263 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +209 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +264 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-12-completeness-validation.md +242 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +231 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/templates/prd-template.md +10 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md +63 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md +65 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md +63 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01-init.md +135 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md +127 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +190 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +216 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +219 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +234 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +252 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +254 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +224 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +224 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +241 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +248 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +237 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +264 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +171 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/ux-design-template.md +13 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md +42 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-01-document-discovery.md +184 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-02-prd-analysis.md +172 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-03-epic-coverage-validation.md +173 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-04-ux-alignment.md +133 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-05-epic-quality-review.md +245 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +129 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/templates/readiness-report-template.md +4 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md +54 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/architecture-decision-template.md +12 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/data/domain-complexity.csv +13 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/data/project-types.csv +7 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01-init.md +153 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md +173 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +224 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +329 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +318 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +359 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +379 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +359 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +76 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/workflow.md +49 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md +259 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +233 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +272 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +149 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/templates/epics-template.md +57 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md +58 -0
- package/src/bmm/workflows/4-implementation/code-review/checklist.md +23 -0
- package/src/bmm/workflows/4-implementation/code-review/instructions.xml +227 -0
- package/src/bmm/workflows/4-implementation/code-review/workflow.yaml +43 -0
- package/src/bmm/workflows/4-implementation/correct-course/checklist.md +288 -0
- package/src/bmm/workflows/4-implementation/correct-course/instructions.md +207 -0
- package/src/bmm/workflows/4-implementation/correct-course/workflow.yaml +53 -0
- package/src/bmm/workflows/4-implementation/create-story/checklist.md +358 -0
- package/src/bmm/workflows/4-implementation/create-story/instructions.xml +346 -0
- package/src/bmm/workflows/4-implementation/create-story/template.md +49 -0
- package/src/bmm/workflows/4-implementation/create-story/workflow.yaml +52 -0
- package/src/bmm/workflows/4-implementation/dev-story/checklist.md +80 -0
- package/src/bmm/workflows/4-implementation/dev-story/instructions.xml +410 -0
- package/src/bmm/workflows/4-implementation/dev-story/workflow.yaml +20 -0
- package/src/bmm/workflows/4-implementation/retrospective/instructions.md +1444 -0
- package/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +52 -0
- package/src/bmm/workflows/4-implementation/sprint-planning/instructions.md +226 -0
- package/src/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +55 -0
- package/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +47 -0
- package/src/bmm/workflows/4-implementation/sprint-status/instructions.md +230 -0
- package/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml +25 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md +174 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md +118 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md +111 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md +111 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +104 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-06-resolve-findings.md +146 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +50 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-01-understand.md +189 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md +143 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md +126 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +200 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/tech-spec-template.md +74 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +79 -0
- package/src/bmm/workflows/document-project/checklist.md +245 -0
- package/src/bmm/workflows/document-project/instructions.md +130 -0
- package/src/bmm/workflows/document-project/templates/project-scan-report-schema.json +160 -0
- package/src/bmm/workflows/document-project/workflow.yaml +22 -0
- package/src/bmm/workflows/document-project/workflows/deep-dive-instructions.md +298 -0
- package/src/bmm/workflows/document-project/workflows/deep-dive.yaml +31 -0
- package/src/bmm/workflows/document-project/workflows/full-scan-instructions.md +1106 -0
- package/src/bmm/workflows/document-project/workflows/full-scan.yaml +31 -0
- package/src/bmm/workflows/generate-project-context/project-context-template.md +21 -0
- package/src/bmm/workflows/generate-project-context/steps/step-01-discover.md +184 -0
- package/src/bmm/workflows/generate-project-context/steps/step-02-generate.md +318 -0
- package/src/bmm/workflows/generate-project-context/steps/step-03-complete.md +278 -0
- package/src/bmm/workflows/generate-project-context/workflow.md +49 -0
- package/src/bmm/workflows/qa-generate-e2e-tests/checklist.md +33 -0
- package/src/bmm/workflows/qa-generate-e2e-tests/instructions.md +110 -0
- package/src/bmm/workflows/qa-generate-e2e-tests/workflow.yaml +42 -0
- package/src/core/agents/bmad-master.agent.yaml +12 -21
- package/src/core/module-help.csv +9 -0
- package/src/core/module.yaml +25 -0
- package/src/core/tasks/editorial-review-prose.xml +102 -0
- package/src/core/tasks/editorial-review-structure.xml +208 -0
- package/src/core/tasks/help.md +86 -0
- package/src/core/tasks/index-docs.xml +2 -2
- package/src/core/tasks/review-adversarial-general.xml +49 -0
- package/src/core/tasks/shard-doc.xml +108 -0
- package/src/core/tasks/workflow.xml +39 -74
- package/src/core/workflows/advanced-elicitation/methods.csv +51 -0
- package/src/core/workflows/advanced-elicitation/workflow.xml +118 -0
- package/src/core/workflows/brainstorming/brain-methods.csv +62 -36
- package/src/core/workflows/brainstorming/steps/step-01-session-setup.md +197 -0
- package/src/core/workflows/brainstorming/steps/step-01b-continue.md +122 -0
- package/src/core/workflows/brainstorming/steps/step-02a-user-selected.md +225 -0
- package/src/core/workflows/brainstorming/steps/step-02b-ai-recommended.md +237 -0
- package/src/core/workflows/brainstorming/steps/step-02c-random-selection.md +209 -0
- package/src/core/workflows/brainstorming/steps/step-02d-progressive-flow.md +264 -0
- package/src/core/workflows/brainstorming/steps/step-03-technique-execution.md +399 -0
- package/src/core/workflows/brainstorming/steps/step-04-idea-organization.md +303 -0
- package/src/core/workflows/brainstorming/template.md +13 -104
- package/src/core/workflows/brainstorming/workflow.md +58 -0
- package/src/core/workflows/party-mode/steps/step-01-agent-loading.md +138 -0
- package/src/core/workflows/party-mode/steps/step-02-discussion-orchestration.md +187 -0
- package/src/core/workflows/party-mode/steps/step-03-graceful-exit.md +168 -0
- package/src/core/workflows/party-mode/workflow.md +194 -0
- package/src/utility/agent-components/activation-rules.txt +6 -0
- package/src/utility/agent-components/activation-steps.txt +14 -0
- package/src/utility/agent-components/agent-command-header.md +1 -0
- package/src/utility/agent-components/agent.customize.template.yaml +41 -0
- package/src/utility/agent-components/handler-action.txt +4 -0
- package/src/utility/agent-components/handler-exec.txt +6 -0
- package/src/utility/agent-components/handler-multi.txt +14 -0
- package/src/utility/agent-components/handler-tmpl.txt +5 -0
- package/src/utility/agent-components/handler-validate-workflow.txt +7 -0
- package/src/utility/agent-components/handler-workflow.txt +10 -0
- package/src/utility/agent-components/menu-handlers.txt +6 -0
- package/test/README.md +4 -4
- package/test/adversarial-review-tests/README.md +56 -0
- package/test/adversarial-review-tests/sample-content.md +46 -0
- package/test/adversarial-review-tests/test-cases.yaml +103 -0
- package/test/fixtures/agent-schema/invalid/critical-actions/actions-as-string.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/critical-actions/empty-string-in-actions.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/menu/empty-menu.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/menu/missing-menu.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/menu-commands/empty-command-target.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/menu-commands/no-command-target.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/camel-case.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/compound-invalid-format.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/compound-mismatched-kebab.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/duplicate-triggers.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/empty-trigger.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/leading-asterisk.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/snake-case.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/trigger-with-spaces.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/metadata/empty-module-string.agent.yaml +1 -1
- package/test/fixtures/agent-schema/invalid/metadata/extra-metadata-fields.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/persona/empty-principles-array.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/persona/empty-string-in-principles.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/persona/extra-persona-fields.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/persona/missing-role.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/prompts/empty-content.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/prompts/extra-prompt-fields.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/prompts/missing-content.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/prompts/missing-id.agent.yaml +1 -0
- package/test/fixtures/agent-schema/invalid/top-level/extra-top-level-keys.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/critical-actions/empty-critical-actions.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/critical-actions/no-critical-actions.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/critical-actions/valid-critical-actions.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/menu/multiple-menu-items.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/menu/single-menu-item.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/menu-commands/all-command-types.agent.yaml +2 -3
- package/test/fixtures/agent-schema/valid/menu-commands/multiple-commands.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/menu-triggers/compound-triggers.agent.yaml +31 -0
- package/test/fixtures/agent-schema/valid/menu-triggers/kebab-case-triggers.agent.yaml +2 -1
- package/test/fixtures/agent-schema/valid/metadata/core-agent-with-module.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/metadata/empty-module-name-in-path.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/metadata/malformed-path-treated-as-core.agent.yaml +2 -1
- package/test/fixtures/agent-schema/valid/metadata/module-agent-correct.agent.yaml +2 -1
- package/test/fixtures/agent-schema/valid/metadata/module-agent-missing-module.agent.yaml +23 -0
- package/test/fixtures/agent-schema/valid/metadata/wrong-module-value.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/persona/complete-persona.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/prompts/empty-prompts.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/prompts/no-prompts.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/prompts/valid-prompts-minimal.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/prompts/valid-prompts-with-description.agent.yaml +1 -0
- package/test/fixtures/agent-schema/valid/top-level/minimal-core-agent.agent.yaml +1 -0
- package/test/fixtures/file-refs-csv/invalid/all-empty-workflow.csv +3 -0
- package/test/fixtures/file-refs-csv/invalid/empty-data.csv +1 -0
- package/test/fixtures/file-refs-csv/invalid/no-workflow-column.csv +3 -0
- package/test/fixtures/file-refs-csv/invalid/unresolvable-vars.csv +3 -0
- package/test/fixtures/file-refs-csv/valid/bmm-style.csv +3 -0
- package/test/fixtures/file-refs-csv/valid/core-style.csv +3 -0
- package/test/fixtures/file-refs-csv/valid/minimal.csv +2 -0
- package/test/test-agent-schema.js +4 -4
- package/test/test-file-refs-csv.js +133 -0
- package/test/test-installation-components.js +10 -12
- package/test/test-rehype-plugins.mjs +1050 -0
- package/test/unit-test-schema.js +2 -2
- package/tools/build-docs.mjs +463 -0
- package/tools/cli/README.md +41 -589
- package/tools/cli/bmad-cli.js +67 -1
- package/tools/cli/commands/install.js +42 -34
- package/tools/cli/commands/status.js +44 -26
- package/tools/cli/commands/uninstall.js +146 -23
- package/tools/cli/external-official-modules.yaml +53 -0
- package/tools/cli/installers/install-messages.yaml +39 -0
- package/tools/cli/installers/lib/core/config-collector.js +589 -95
- package/tools/cli/installers/lib/core/custom-module-cache.js +260 -0
- package/tools/cli/installers/lib/core/dependency-resolver.js +57 -39
- package/tools/cli/installers/lib/core/detector.js +19 -125
- package/tools/cli/installers/lib/core/ide-config-manager.js +12 -9
- package/tools/cli/installers/lib/core/installer.js +2075 -1161
- package/tools/cli/installers/lib/core/manifest-generator.js +494 -103
- package/tools/cli/installers/lib/core/manifest.js +544 -46
- package/tools/cli/installers/lib/custom/handler.js +358 -0
- package/tools/cli/installers/lib/ide/_base-ide.js +83 -44
- package/tools/cli/installers/lib/ide/_config-driven.js +559 -0
- package/tools/cli/installers/lib/ide/codex.js +301 -64
- package/tools/cli/installers/lib/ide/github-copilot.js +606 -209
- package/tools/cli/installers/lib/ide/kilo.js +169 -75
- package/tools/cli/installers/lib/ide/manager.js +179 -48
- package/tools/cli/installers/lib/ide/platform-codes.js +100 -0
- package/tools/cli/installers/lib/ide/platform-codes.yaml +234 -0
- package/tools/cli/installers/lib/ide/rovodev.js +257 -0
- package/tools/cli/installers/lib/ide/shared/agent-command-generator.js +95 -5
- package/tools/cli/installers/lib/ide/shared/bmad-artifacts.js +51 -20
- package/tools/cli/installers/lib/ide/shared/module-injections.js +6 -3
- package/tools/cli/installers/lib/ide/shared/path-utils.js +299 -0
- package/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +261 -14
- package/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +108 -27
- package/tools/cli/installers/lib/ide/templates/agent-command-template.md +1 -1
- package/tools/cli/installers/lib/ide/templates/combined/antigravity.md +8 -0
- package/tools/cli/installers/lib/ide/templates/combined/default-agent.md +15 -0
- package/tools/cli/installers/lib/ide/templates/combined/default-task.md +10 -0
- package/tools/cli/installers/lib/ide/templates/combined/default-tool.md +10 -0
- package/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md +14 -0
- package/tools/cli/installers/lib/ide/templates/combined/default-workflow.md +6 -0
- package/tools/cli/installers/lib/ide/templates/combined/gemini-agent.toml +14 -0
- package/tools/cli/installers/lib/ide/templates/combined/gemini-task.toml +11 -0
- package/tools/cli/installers/lib/ide/templates/combined/gemini-tool.toml +11 -0
- package/tools/cli/installers/lib/ide/templates/combined/gemini-workflow-yaml.toml +16 -0
- package/tools/cli/installers/lib/ide/templates/combined/gemini-workflow.toml +14 -0
- package/tools/cli/installers/lib/ide/templates/combined/kiro-agent.md +16 -0
- package/tools/cli/installers/lib/ide/templates/combined/kiro-task.md +9 -0
- package/tools/cli/installers/lib/ide/templates/combined/kiro-tool.md +9 -0
- package/tools/cli/installers/lib/ide/templates/combined/kiro-workflow-yaml.md +15 -0
- package/tools/cli/installers/lib/ide/templates/combined/kiro-workflow.md +7 -0
- package/tools/cli/installers/lib/ide/templates/combined/opencode-agent.md +15 -0
- package/tools/cli/installers/lib/ide/templates/combined/opencode-task.md +14 -0
- package/tools/cli/installers/lib/ide/templates/combined/opencode-tool.md +14 -0
- package/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md +17 -0
- package/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md +17 -0
- package/tools/cli/installers/lib/ide/templates/combined/rovodev.md +9 -0
- package/tools/cli/installers/lib/ide/templates/combined/trae.md +9 -0
- package/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md +10 -0
- package/tools/cli/installers/lib/ide/templates/workflow-command-template.md +1 -1
- package/tools/cli/installers/lib/ide/templates/workflow-commander.md +5 -0
- package/tools/cli/installers/lib/message-loader.js +83 -0
- package/tools/cli/installers/lib/modules/external-manager.js +136 -0
- package/tools/cli/installers/lib/modules/manager.js +931 -207
- package/tools/cli/lib/activation-builder.js +13 -16
- package/tools/cli/lib/agent/compiler.js +525 -0
- package/tools/cli/lib/agent/installer.js +680 -0
- package/tools/cli/lib/agent/template-engine.js +152 -0
- package/tools/cli/lib/agent-analyzer.js +48 -20
- package/tools/cli/lib/agent-party-generator.js +5 -17
- package/tools/cli/lib/cli-utils.js +76 -104
- package/tools/cli/lib/config.js +4 -3
- package/tools/cli/lib/platform-codes.js +2 -2
- package/tools/cli/lib/project-root.js +6 -0
- package/tools/cli/lib/prompts.js +809 -0
- package/tools/cli/lib/ui.js +1600 -272
- package/tools/cli/lib/xml-handler.js +4 -55
- package/tools/cli/lib/yaml-format.js +4 -6
- package/tools/cli/lib/yaml-xml-builder.js +183 -61
- package/tools/docs/_prompt-external-modules-page.md +59 -0
- package/tools/docs/fix-refs.md +91 -0
- package/tools/fix-doc-links.js +285 -0
- package/tools/lib/xml-utils.js +13 -0
- package/tools/migrate-custom-module-paths.js +124 -0
- package/tools/platform-codes.yaml +30 -6
- package/tools/schema/agent.js +306 -53
- package/tools/validate-agent-schema.js +3 -3
- package/tools/validate-doc-links.js +407 -0
- package/tools/validate-file-refs.js +554 -0
- package/tools/validate-svg-changes.sh +356 -0
- package/website/README.md +75 -0
- package/website/astro.config.mjs +136 -0
- package/website/public/favicon.ico +0 -0
- package/website/public/img/bmad-dark.png +0 -0
- package/website/public/img/bmad-light.png +0 -0
- package/website/public/workflow-map-diagram.html +361 -0
- package/website/src/components/Banner.astro +62 -0
- package/website/src/components/Header.astro +96 -0
- package/website/src/components/MobileMenuFooter.astro +33 -0
- package/website/src/content/config.ts +6 -0
- package/website/src/lib/site-url.mjs +25 -0
- package/website/src/pages/404.astro +11 -0
- package/website/src/pages/robots.txt.ts +48 -0
- package/website/src/rehype-base-paths.js +112 -0
- package/website/src/rehype-markdown-links.js +119 -0
- package/website/src/styles/custom.css +805 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -32
- package/.github/ISSUE_TEMPLATE/idea_submission.md +0 -109
- package/.github/workflows/bundle-latest.yaml +0 -277
- package/.github/workflows/manual-release.yaml +0 -212
- package/docs/BUNDLE_DISTRIBUTION_SETUP.md +0 -95
- package/docs/agent-customization-guide.md +0 -208
- package/docs/document-sharding-guide.md +0 -447
- package/docs/ide-info/auggie.md +0 -31
- package/docs/ide-info/claude-code.md +0 -25
- package/docs/ide-info/cline.md +0 -31
- package/docs/ide-info/codex.md +0 -21
- package/docs/ide-info/crush.md +0 -30
- package/docs/ide-info/cursor.md +0 -25
- package/docs/ide-info/gemini.md +0 -25
- package/docs/ide-info/github-copilot.md +0 -26
- package/docs/ide-info/iflow.md +0 -33
- package/docs/ide-info/kilo.md +0 -24
- package/docs/ide-info/opencode.md +0 -24
- package/docs/ide-info/qwen.md +0 -25
- package/docs/ide-info/roo.md +0 -27
- package/docs/ide-info/trae.md +0 -25
- package/docs/ide-info/windsurf.md +0 -22
- package/docs/installers-bundlers/ide-injections.md +0 -186
- package/docs/installers-bundlers/installers-modules-platforms-reference.md +0 -388
- package/docs/installers-bundlers/web-bundler-usage.md +0 -54
- package/docs/v4-to-v6-upgrade.md +0 -227
- package/docs/web-bundles-gemini-gpt-guide.md +0 -473
- package/src/core/_module-installer/install-config.yaml +0 -35
- package/src/core/_module-installer/installer.js +0 -60
- package/src/core/agents/bmad-web-orchestrator.agent.xml +0 -113
- package/src/core/tasks/adv-elicit-methods.csv +0 -39
- package/src/core/tasks/advanced-elicitation.xml +0 -106
- package/src/core/tasks/validate-workflow.xml +0 -89
- package/src/core/tools/shard-doc.xml +0 -109
- package/src/core/workflows/brainstorming/README.md +0 -261
- package/src/core/workflows/brainstorming/instructions.md +0 -315
- package/src/core/workflows/brainstorming/workflow.yaml +0 -43
- package/src/core/workflows/party-mode/instructions.md +0 -183
- package/src/core/workflows/party-mode/workflow.yaml +0 -27
- package/src/modules/bmb/README.md +0 -194
- package/src/modules/bmb/_module-installer/install-config.yaml +0 -31
- package/src/modules/bmb/agents/bmad-builder.agent.yaml +0 -59
- package/src/modules/bmb/workflows/audit-workflow/checklist.md +0 -142
- package/src/modules/bmb/workflows/audit-workflow/instructions.md +0 -341
- package/src/modules/bmb/workflows/audit-workflow/template.md +0 -118
- package/src/modules/bmb/workflows/audit-workflow/workflow.yaml +0 -25
- package/src/modules/bmb/workflows/convert-legacy/README.md +0 -262
- package/src/modules/bmb/workflows/convert-legacy/checklist.md +0 -205
- package/src/modules/bmb/workflows/convert-legacy/instructions.md +0 -377
- package/src/modules/bmb/workflows/convert-legacy/workflow.yaml +0 -34
- package/src/modules/bmb/workflows/create-agent/README.md +0 -203
- package/src/modules/bmb/workflows/create-agent/agent-architecture.md +0 -415
- package/src/modules/bmb/workflows/create-agent/agent-command-patterns.md +0 -759
- package/src/modules/bmb/workflows/create-agent/agent-types.md +0 -292
- package/src/modules/bmb/workflows/create-agent/brainstorm-context.md +0 -174
- package/src/modules/bmb/workflows/create-agent/checklist.md +0 -62
- package/src/modules/bmb/workflows/create-agent/communication-styles.md +0 -202
- package/src/modules/bmb/workflows/create-agent/instructions.md +0 -456
- package/src/modules/bmb/workflows/create-agent/workflow.yaml +0 -49
- package/src/modules/bmb/workflows/create-module/README.md +0 -229
- package/src/modules/bmb/workflows/create-module/brainstorm-context.md +0 -137
- package/src/modules/bmb/workflows/create-module/checklist.md +0 -235
- package/src/modules/bmb/workflows/create-module/installer-templates/install-config.yaml +0 -92
- package/src/modules/bmb/workflows/create-module/installer-templates/installer.js +0 -231
- package/src/modules/bmb/workflows/create-module/instructions.md +0 -576
- package/src/modules/bmb/workflows/create-module/module-structure.md +0 -400
- package/src/modules/bmb/workflows/create-module/workflow.yaml +0 -44
- package/src/modules/bmb/workflows/create-workflow/README.md +0 -277
- package/src/modules/bmb/workflows/create-workflow/brainstorm-context.md +0 -197
- package/src/modules/bmb/workflows/create-workflow/checklist.md +0 -94
- package/src/modules/bmb/workflows/create-workflow/instructions.md +0 -724
- package/src/modules/bmb/workflows/create-workflow/workflow-creation-guide.md +0 -1306
- package/src/modules/bmb/workflows/create-workflow/workflow-template/checklist.md +0 -24
- package/src/modules/bmb/workflows/create-workflow/workflow-template/instructions.md +0 -13
- package/src/modules/bmb/workflows/create-workflow/workflow-template/template.md +0 -9
- package/src/modules/bmb/workflows/create-workflow/workflow-template/workflow.yaml +0 -65
- package/src/modules/bmb/workflows/create-workflow/workflow.yaml +0 -42
- package/src/modules/bmb/workflows/edit-agent/README.md +0 -112
- package/src/modules/bmb/workflows/edit-agent/checklist.md +0 -112
- package/src/modules/bmb/workflows/edit-agent/instructions.md +0 -290
- package/src/modules/bmb/workflows/edit-agent/workflow.yaml +0 -35
- package/src/modules/bmb/workflows/edit-module/README.md +0 -187
- package/src/modules/bmb/workflows/edit-module/checklist.md +0 -165
- package/src/modules/bmb/workflows/edit-module/instructions.md +0 -339
- package/src/modules/bmb/workflows/edit-module/workflow.yaml +0 -36
- package/src/modules/bmb/workflows/edit-workflow/README.md +0 -119
- package/src/modules/bmb/workflows/edit-workflow/checklist.md +0 -70
- package/src/modules/bmb/workflows/edit-workflow/instructions.md +0 -342
- package/src/modules/bmb/workflows/edit-workflow/workflow.yaml +0 -29
- package/src/modules/bmb/workflows/module-brief/README.md +0 -264
- package/src/modules/bmb/workflows/module-brief/checklist.md +0 -116
- package/src/modules/bmb/workflows/module-brief/instructions.md +0 -267
- package/src/modules/bmb/workflows/module-brief/template.md +0 -275
- package/src/modules/bmb/workflows/module-brief/workflow.yaml +0 -31
- package/src/modules/bmb/workflows/redoc/README.md +0 -87
- package/src/modules/bmb/workflows/redoc/checklist.md +0 -99
- package/src/modules/bmb/workflows/redoc/instructions.md +0 -265
- package/src/modules/bmb/workflows/redoc/workflow.yaml +0 -34
- package/src/modules/bmgd/README.md +0 -208
- package/src/modules/bmgd/_module-installer/install-config.yaml +0 -54
- package/src/modules/bmgd/agents/game-architect.agent.yaml +0 -33
- package/src/modules/bmgd/agents/game-designer.agent.yaml +0 -40
- package/src/modules/bmgd/agents/game-dev.agent.yaml +0 -40
- package/src/modules/bmgd/agents/game-scrum-master.agent.yaml +0 -75
- package/src/modules/bmgd/teams/default-party.csv +0 -10
- package/src/modules/bmgd/teams/team-gamedev.yaml +0 -18
- package/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/game-brain-methods.csv +0 -26
- package/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/game-context.md +0 -115
- package/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/instructions.md +0 -128
- package/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/workflow.yaml +0 -41
- package/src/modules/bmgd/workflows/1-preproduction/game-brief/checklist.md +0 -128
- package/src/modules/bmgd/workflows/1-preproduction/game-brief/instructions.md +0 -371
- package/src/modules/bmgd/workflows/1-preproduction/game-brief/template.md +0 -205
- package/src/modules/bmgd/workflows/1-preproduction/game-brief/workflow.yaml +0 -44
- package/src/modules/bmgd/workflows/2-design/gdd/checklist.md +0 -148
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/action-platformer.md +0 -45
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/adventure.md +0 -84
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/card-game.md +0 -76
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/fighting.md +0 -89
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/horror.md +0 -86
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/idle-incremental.md +0 -78
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/metroidvania.md +0 -87
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/moba.md +0 -74
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/party-game.md +0 -79
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/puzzle.md +0 -58
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/racing.md +0 -88
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/rhythm.md +0 -79
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/roguelike.md +0 -69
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/rpg.md +0 -70
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/sandbox.md +0 -79
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/shooter.md +0 -62
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/simulation.md +0 -73
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/sports.md +0 -75
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/strategy.md +0 -71
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/survival.md +0 -79
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/text-based.md +0 -91
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/tower-defense.md +0 -79
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/turn-based-tactics.md +0 -88
- package/src/modules/bmgd/workflows/2-design/gdd/game-types/visual-novel.md +0 -89
- package/src/modules/bmgd/workflows/2-design/gdd/game-types.csv +0 -25
- package/src/modules/bmgd/workflows/2-design/gdd/gdd-template.md +0 -153
- package/src/modules/bmgd/workflows/2-design/gdd/instructions-gdd.md +0 -501
- package/src/modules/bmgd/workflows/2-design/gdd/workflow.yaml +0 -81
- package/src/modules/bmgd/workflows/2-design/narrative/checklist.md +0 -139
- package/src/modules/bmgd/workflows/2-design/narrative/instructions-narrative.md +0 -603
- package/src/modules/bmgd/workflows/2-design/narrative/narrative-template.md +0 -195
- package/src/modules/bmgd/workflows/2-design/narrative/workflow.yaml +0 -38
- package/src/modules/bmgd/workflows/3-technical/game-architecture/architecture-patterns.yaml +0 -321
- package/src/modules/bmgd/workflows/3-technical/game-architecture/architecture-template.md +0 -103
- package/src/modules/bmgd/workflows/3-technical/game-architecture/checklist.md +0 -240
- package/src/modules/bmgd/workflows/3-technical/game-architecture/decision-catalog.yaml +0 -222
- package/src/modules/bmgd/workflows/3-technical/game-architecture/instructions.md +0 -699
- package/src/modules/bmgd/workflows/3-technical/game-architecture/pattern-categories.csv +0 -13
- package/src/modules/bmgd/workflows/3-technical/game-architecture/workflow.yaml +0 -67
- package/src/modules/bmgd/workflows/4-production/code-review/backlog_template.md +0 -12
- package/src/modules/bmgd/workflows/4-production/code-review/checklist.md +0 -22
- package/src/modules/bmgd/workflows/4-production/code-review/instructions.md +0 -398
- package/src/modules/bmgd/workflows/4-production/code-review/workflow.yaml +0 -57
- package/src/modules/bmgd/workflows/4-production/correct-course/checklist.md +0 -279
- package/src/modules/bmgd/workflows/4-production/correct-course/instructions.md +0 -206
- package/src/modules/bmgd/workflows/4-production/correct-course/workflow.yaml +0 -52
- package/src/modules/bmgd/workflows/4-production/create-story/checklist.md +0 -240
- package/src/modules/bmgd/workflows/4-production/create-story/instructions.md +0 -256
- package/src/modules/bmgd/workflows/4-production/create-story/template.md +0 -51
- package/src/modules/bmgd/workflows/4-production/create-story/workflow.yaml +0 -68
- package/src/modules/bmgd/workflows/4-production/dev-story/checklist.md +0 -38
- package/src/modules/bmgd/workflows/4-production/dev-story/instructions.md +0 -267
- package/src/modules/bmgd/workflows/4-production/dev-story/workflow.yaml +0 -53
- package/src/modules/bmgd/workflows/4-production/epic-tech-context/checklist.md +0 -17
- package/src/modules/bmgd/workflows/4-production/epic-tech-context/instructions.md +0 -164
- package/src/modules/bmgd/workflows/4-production/epic-tech-context/template.md +0 -76
- package/src/modules/bmgd/workflows/4-production/epic-tech-context/workflow.yaml +0 -52
- package/src/modules/bmgd/workflows/4-production/retrospective/instructions.md +0 -1442
- package/src/modules/bmgd/workflows/4-production/retrospective/workflow.yaml +0 -52
- package/src/modules/bmgd/workflows/4-production/sprint-planning/instructions.md +0 -234
- package/src/modules/bmgd/workflows/4-production/sprint-planning/sprint-status-template.yaml +0 -55
- package/src/modules/bmgd/workflows/4-production/sprint-planning/workflow.yaml +0 -50
- package/src/modules/bmgd/workflows/4-production/story-context/checklist.md +0 -16
- package/src/modules/bmgd/workflows/4-production/story-context/context-template.xml +0 -34
- package/src/modules/bmgd/workflows/4-production/story-context/instructions.md +0 -209
- package/src/modules/bmgd/workflows/4-production/story-context/workflow.yaml +0 -57
- package/src/modules/bmgd/workflows/4-production/story-done/instructions.md +0 -111
- package/src/modules/bmgd/workflows/4-production/story-done/workflow.yaml +0 -28
- package/src/modules/bmgd/workflows/4-production/story-ready/instructions.md +0 -117
- package/src/modules/bmgd/workflows/4-production/story-ready/workflow.yaml +0 -25
- package/src/modules/bmm/README.md +0 -128
- package/src/modules/bmm/_module-installer/assets/bmm-kb.md +0 -1
- package/src/modules/bmm/_module-installer/assets/technical-decisions.md +0 -30
- package/src/modules/bmm/_module-installer/install-config.yaml +0 -60
- package/src/modules/bmm/_module-installer/installer.js +0 -131
- package/src/modules/bmm/_module-installer/platform-specifics/claude-code.js +0 -35
- package/src/modules/bmm/_module-installer/platform-specifics/windsurf.js +0 -32
- package/src/modules/bmm/agents/analyst.agent.yaml +0 -48
- package/src/modules/bmm/agents/architect.agent.yaml +0 -42
- package/src/modules/bmm/agents/dev.agent.yaml +0 -40
- package/src/modules/bmm/agents/pm.agent.yaml +0 -61
- package/src/modules/bmm/agents/sm.agent.yaml +0 -72
- package/src/modules/bmm/agents/tea.agent.yaml +0 -65
- package/src/modules/bmm/agents/tech-writer.agent.yaml +0 -73
- package/src/modules/bmm/agents/ux-designer.agent.yaml +0 -38
- package/src/modules/bmm/docs/README.md +0 -235
- package/src/modules/bmm/docs/agents-guide.md +0 -1056
- package/src/modules/bmm/docs/brownfield-guide.md +0 -754
- package/src/modules/bmm/docs/enterprise-agentic-development.md +0 -680
- package/src/modules/bmm/docs/faq.md +0 -587
- package/src/modules/bmm/docs/glossary.md +0 -320
- package/src/modules/bmm/docs/party-mode.md +0 -224
- package/src/modules/bmm/docs/quick-spec-flow.md +0 -652
- package/src/modules/bmm/docs/quick-start.md +0 -366
- package/src/modules/bmm/docs/scale-adaptive-system.md +0 -599
- package/src/modules/bmm/docs/test-architecture.md +0 -394
- package/src/modules/bmm/docs/workflow-architecture-reference.md +0 -371
- package/src/modules/bmm/docs/workflow-document-project-reference.md +0 -487
- package/src/modules/bmm/docs/workflows-analysis.md +0 -370
- package/src/modules/bmm/docs/workflows-implementation.md +0 -284
- package/src/modules/bmm/docs/workflows-planning.md +0 -601
- package/src/modules/bmm/docs/workflows-solutioning.md +0 -501
- package/src/modules/bmm/teams/default-party.csv +0 -19
- package/src/modules/bmm/testarch/knowledge/ci-burn-in.md +0 -675
- package/src/modules/bmm/testarch/knowledge/component-tdd.md +0 -486
- package/src/modules/bmm/testarch/knowledge/contract-testing.md +0 -957
- package/src/modules/bmm/testarch/knowledge/data-factories.md +0 -500
- package/src/modules/bmm/testarch/knowledge/email-auth.md +0 -721
- package/src/modules/bmm/testarch/knowledge/error-handling.md +0 -725
- package/src/modules/bmm/testarch/knowledge/feature-flags.md +0 -750
- package/src/modules/bmm/testarch/knowledge/fixture-architecture.md +0 -401
- package/src/modules/bmm/testarch/knowledge/network-first.md +0 -486
- package/src/modules/bmm/testarch/knowledge/nfr-criteria.md +0 -670
- package/src/modules/bmm/testarch/knowledge/playwright-config.md +0 -730
- package/src/modules/bmm/testarch/knowledge/probability-impact.md +0 -601
- package/src/modules/bmm/testarch/knowledge/risk-governance.md +0 -615
- package/src/modules/bmm/testarch/knowledge/selective-testing.md +0 -732
- package/src/modules/bmm/testarch/knowledge/selector-resilience.md +0 -527
- package/src/modules/bmm/testarch/knowledge/test-healing-patterns.md +0 -644
- package/src/modules/bmm/testarch/knowledge/test-levels-framework.md +0 -473
- package/src/modules/bmm/testarch/knowledge/test-priorities-matrix.md +0 -373
- package/src/modules/bmm/testarch/knowledge/test-quality.md +0 -664
- package/src/modules/bmm/testarch/knowledge/timing-debugging.md +0 -372
- package/src/modules/bmm/testarch/knowledge/visual-debugging.md +0 -524
- package/src/modules/bmm/testarch/tea-index.csv +0 -22
- package/src/modules/bmm/workflows/1-analysis/brainstorm-project/instructions.md +0 -110
- package/src/modules/bmm/workflows/1-analysis/brainstorm-project/project-context.md +0 -25
- package/src/modules/bmm/workflows/1-analysis/brainstorm-project/workflow.yaml +0 -39
- package/src/modules/bmm/workflows/1-analysis/domain-research/instructions.md +0 -423
- package/src/modules/bmm/workflows/1-analysis/domain-research/template.md +0 -180
- package/src/modules/bmm/workflows/1-analysis/domain-research/workflow.yaml +0 -56
- package/src/modules/bmm/workflows/1-analysis/product-brief/checklist.md +0 -115
- package/src/modules/bmm/workflows/1-analysis/product-brief/instructions.md +0 -522
- package/src/modules/bmm/workflows/1-analysis/product-brief/template.md +0 -181
- package/src/modules/bmm/workflows/1-analysis/product-brief/workflow.yaml +0 -65
- package/src/modules/bmm/workflows/1-analysis/research/checklist-deep-prompt.md +0 -144
- package/src/modules/bmm/workflows/1-analysis/research/checklist-technical.md +0 -249
- package/src/modules/bmm/workflows/1-analysis/research/checklist.md +0 -299
- package/src/modules/bmm/workflows/1-analysis/research/claude-code/injections.yaml +0 -114
- package/src/modules/bmm/workflows/1-analysis/research/instructions-deep-prompt.md +0 -437
- package/src/modules/bmm/workflows/1-analysis/research/instructions-market.md +0 -674
- package/src/modules/bmm/workflows/1-analysis/research/instructions-router.md +0 -133
- package/src/modules/bmm/workflows/1-analysis/research/instructions-technical.md +0 -533
- package/src/modules/bmm/workflows/1-analysis/research/template-deep-prompt.md +0 -94
- package/src/modules/bmm/workflows/1-analysis/research/template-market.md +0 -347
- package/src/modules/bmm/workflows/1-analysis/research/template-technical.md +0 -245
- package/src/modules/bmm/workflows/1-analysis/research/workflow.yaml +0 -62
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/checklist.md +0 -310
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/instructions.md +0 -1306
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/ux-design-template.md +0 -145
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml +0 -99
- package/src/modules/bmm/workflows/2-plan-workflows/prd/checklist.md +0 -346
- package/src/modules/bmm/workflows/2-plan-workflows/prd/create-epics-and-stories/epics-template.md +0 -80
- package/src/modules/bmm/workflows/2-plan-workflows/prd/create-epics-and-stories/instructions.md +0 -292
- package/src/modules/bmm/workflows/2-plan-workflows/prd/create-epics-and-stories/workflow.yaml +0 -53
- package/src/modules/bmm/workflows/2-plan-workflows/prd/domain-complexity.csv +0 -13
- package/src/modules/bmm/workflows/2-plan-workflows/prd/instructions.md +0 -525
- package/src/modules/bmm/workflows/2-plan-workflows/prd/prd-template.md +0 -237
- package/src/modules/bmm/workflows/2-plan-workflows/prd/project-types.csv +0 -11
- package/src/modules/bmm/workflows/2-plan-workflows/prd/workflow.yaml +0 -76
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/checklist.md +0 -217
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/epics-template.md +0 -74
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/instructions-generate-stories.md +0 -434
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/instructions.md +0 -978
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/tech-spec-template.md +0 -181
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/user-story-template.md +0 -90
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/workflow.yaml +0 -57
- package/src/modules/bmm/workflows/3-solutioning/architecture/architecture-patterns.yaml +0 -321
- package/src/modules/bmm/workflows/3-solutioning/architecture/architecture-template.md +0 -103
- package/src/modules/bmm/workflows/3-solutioning/architecture/checklist.md +0 -240
- package/src/modules/bmm/workflows/3-solutioning/architecture/decision-catalog.yaml +0 -222
- package/src/modules/bmm/workflows/3-solutioning/architecture/instructions.md +0 -696
- package/src/modules/bmm/workflows/3-solutioning/architecture/pattern-categories.csv +0 -13
- package/src/modules/bmm/workflows/3-solutioning/architecture/workflow.yaml +0 -96
- package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/checklist.md +0 -169
- package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/instructions.md +0 -302
- package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/template.md +0 -146
- package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/workflow.yaml +0 -66
- package/src/modules/bmm/workflows/4-implementation/code-review/backlog_template.md +0 -12
- package/src/modules/bmm/workflows/4-implementation/code-review/checklist.md +0 -22
- package/src/modules/bmm/workflows/4-implementation/code-review/instructions.md +0 -398
- package/src/modules/bmm/workflows/4-implementation/code-review/workflow.yaml +0 -57
- package/src/modules/bmm/workflows/4-implementation/correct-course/checklist.md +0 -279
- package/src/modules/bmm/workflows/4-implementation/correct-course/instructions.md +0 -206
- package/src/modules/bmm/workflows/4-implementation/correct-course/workflow.yaml +0 -52
- package/src/modules/bmm/workflows/4-implementation/create-story/checklist.md +0 -240
- package/src/modules/bmm/workflows/4-implementation/create-story/instructions.md +0 -256
- package/src/modules/bmm/workflows/4-implementation/create-story/template.md +0 -51
- package/src/modules/bmm/workflows/4-implementation/create-story/workflow.yaml +0 -68
- package/src/modules/bmm/workflows/4-implementation/dev-story/checklist.md +0 -38
- package/src/modules/bmm/workflows/4-implementation/dev-story/instructions.md +0 -267
- package/src/modules/bmm/workflows/4-implementation/dev-story/workflow.yaml +0 -53
- package/src/modules/bmm/workflows/4-implementation/epic-tech-context/checklist.md +0 -17
- package/src/modules/bmm/workflows/4-implementation/epic-tech-context/instructions.md +0 -164
- package/src/modules/bmm/workflows/4-implementation/epic-tech-context/template.md +0 -76
- package/src/modules/bmm/workflows/4-implementation/epic-tech-context/workflow.yaml +0 -52
- package/src/modules/bmm/workflows/4-implementation/retrospective/instructions.md +0 -1442
- package/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml +0 -52
- package/src/modules/bmm/workflows/4-implementation/sprint-planning/checklist.md +0 -33
- package/src/modules/bmm/workflows/4-implementation/sprint-planning/instructions.md +0 -234
- package/src/modules/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +0 -55
- package/src/modules/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +0 -50
- package/src/modules/bmm/workflows/4-implementation/story-context/checklist.md +0 -16
- package/src/modules/bmm/workflows/4-implementation/story-context/context-template.xml +0 -34
- package/src/modules/bmm/workflows/4-implementation/story-context/instructions.md +0 -209
- package/src/modules/bmm/workflows/4-implementation/story-context/workflow.yaml +0 -57
- package/src/modules/bmm/workflows/4-implementation/story-done/instructions.md +0 -111
- package/src/modules/bmm/workflows/4-implementation/story-done/workflow.yaml +0 -28
- package/src/modules/bmm/workflows/4-implementation/story-ready/instructions.md +0 -117
- package/src/modules/bmm/workflows/4-implementation/story-ready/workflow.yaml +0 -25
- package/src/modules/bmm/workflows/document-project/checklist.md +0 -245
- package/src/modules/bmm/workflows/document-project/instructions.md +0 -222
- package/src/modules/bmm/workflows/document-project/templates/project-scan-report-schema.json +0 -160
- package/src/modules/bmm/workflows/document-project/workflow.yaml +0 -36
- package/src/modules/bmm/workflows/document-project/workflows/deep-dive-instructions.md +0 -298
- package/src/modules/bmm/workflows/document-project/workflows/deep-dive.yaml +0 -31
- package/src/modules/bmm/workflows/document-project/workflows/full-scan-instructions.md +0 -1106
- package/src/modules/bmm/workflows/document-project/workflows/full-scan.yaml +0 -31
- package/src/modules/bmm/workflows/techdoc/documentation-standards.md +0 -262
- package/src/modules/bmm/workflows/testarch/atdd/atdd-checklist-template.md +0 -363
- package/src/modules/bmm/workflows/testarch/atdd/checklist.md +0 -373
- package/src/modules/bmm/workflows/testarch/atdd/instructions.md +0 -785
- package/src/modules/bmm/workflows/testarch/atdd/workflow.yaml +0 -54
- package/src/modules/bmm/workflows/testarch/automate/checklist.md +0 -580
- package/src/modules/bmm/workflows/testarch/automate/instructions.md +0 -1303
- package/src/modules/bmm/workflows/testarch/automate/workflow.yaml +0 -63
- package/src/modules/bmm/workflows/testarch/ci/checklist.md +0 -246
- package/src/modules/bmm/workflows/testarch/ci/github-actions-template.yaml +0 -165
- package/src/modules/bmm/workflows/testarch/ci/gitlab-ci-template.yaml +0 -128
- package/src/modules/bmm/workflows/testarch/ci/instructions.md +0 -517
- package/src/modules/bmm/workflows/testarch/ci/workflow.yaml +0 -55
- package/src/modules/bmm/workflows/testarch/framework/checklist.md +0 -321
- package/src/modules/bmm/workflows/testarch/framework/instructions.md +0 -455
- package/src/modules/bmm/workflows/testarch/framework/workflow.yaml +0 -55
- package/src/modules/bmm/workflows/testarch/nfr-assess/checklist.md +0 -405
- package/src/modules/bmm/workflows/testarch/nfr-assess/instructions.md +0 -722
- package/src/modules/bmm/workflows/testarch/nfr-assess/nfr-report-template.md +0 -443
- package/src/modules/bmm/workflows/testarch/nfr-assess/workflow.yaml +0 -58
- package/src/modules/bmm/workflows/testarch/test-design/checklist.md +0 -234
- package/src/modules/bmm/workflows/testarch/test-design/instructions.md +0 -782
- package/src/modules/bmm/workflows/testarch/test-design/test-design-template.md +0 -285
- package/src/modules/bmm/workflows/testarch/test-design/workflow.yaml +0 -58
- package/src/modules/bmm/workflows/testarch/test-review/checklist.md +0 -470
- package/src/modules/bmm/workflows/testarch/test-review/instructions.md +0 -608
- package/src/modules/bmm/workflows/testarch/test-review/test-review-template.md +0 -388
- package/src/modules/bmm/workflows/testarch/test-review/workflow.yaml +0 -55
- package/src/modules/bmm/workflows/testarch/trace/checklist.md +0 -654
- package/src/modules/bmm/workflows/testarch/trace/instructions.md +0 -1045
- package/src/modules/bmm/workflows/testarch/trace/trace-template.md +0 -673
- package/src/modules/bmm/workflows/testarch/trace/workflow.yaml +0 -68
- package/src/modules/bmm/workflows/workflow-status/init/instructions.md +0 -823
- package/src/modules/bmm/workflows/workflow-status/init/workflow.yaml +0 -29
- package/src/modules/bmm/workflows/workflow-status/instructions.md +0 -387
- package/src/modules/bmm/workflows/workflow-status/paths/enterprise-brownfield.yaml +0 -120
- package/src/modules/bmm/workflows/workflow-status/paths/enterprise-greenfield.yaml +0 -108
- package/src/modules/bmm/workflows/workflow-status/paths/game-design.yaml +0 -52
- package/src/modules/bmm/workflows/workflow-status/paths/method-brownfield.yaml +0 -104
- package/src/modules/bmm/workflows/workflow-status/paths/method-greenfield.yaml +0 -95
- package/src/modules/bmm/workflows/workflow-status/paths/quick-flow-brownfield.yaml +0 -58
- package/src/modules/bmm/workflows/workflow-status/paths/quick-flow-greenfield.yaml +0 -47
- package/src/modules/bmm/workflows/workflow-status/project-levels.yaml +0 -59
- package/src/modules/bmm/workflows/workflow-status/workflow-status-template.yaml +0 -24
- package/src/modules/bmm/workflows/workflow-status/workflow.yaml +0 -30
- package/src/modules/cis/README.md +0 -153
- package/src/modules/cis/_module-installer/install-config.yaml +0 -16
- package/src/modules/cis/_module-installer/installer.js +0 -92
- package/src/modules/cis/agents/README.md +0 -104
- package/src/modules/cis/agents/brainstorming-coach.agent.yaml +0 -28
- package/src/modules/cis/agents/creative-problem-solver.agent.yaml +0 -28
- package/src/modules/cis/agents/design-thinking-coach.agent.yaml +0 -28
- package/src/modules/cis/agents/innovation-strategist.agent.yaml +0 -28
- package/src/modules/cis/agents/storyteller.agent.yaml +0 -28
- package/src/modules/cis/teams/creative-squad.yaml +0 -7
- package/src/modules/cis/teams/default-party.csv +0 -11
- package/src/modules/cis/workflows/README.md +0 -139
- package/src/modules/cis/workflows/design-thinking/README.md +0 -56
- package/src/modules/cis/workflows/design-thinking/design-methods.csv +0 -31
- package/src/modules/cis/workflows/design-thinking/instructions.md +0 -200
- package/src/modules/cis/workflows/design-thinking/template.md +0 -111
- package/src/modules/cis/workflows/design-thinking/workflow.yaml +0 -43
- package/src/modules/cis/workflows/innovation-strategy/README.md +0 -56
- package/src/modules/cis/workflows/innovation-strategy/innovation-frameworks.csv +0 -31
- package/src/modules/cis/workflows/innovation-strategy/instructions.md +0 -274
- package/src/modules/cis/workflows/innovation-strategy/template.md +0 -189
- package/src/modules/cis/workflows/innovation-strategy/workflow.yaml +0 -43
- package/src/modules/cis/workflows/problem-solving/README.md +0 -56
- package/src/modules/cis/workflows/problem-solving/instructions.md +0 -250
- package/src/modules/cis/workflows/problem-solving/solving-methods.csv +0 -31
- package/src/modules/cis/workflows/problem-solving/template.md +0 -165
- package/src/modules/cis/workflows/problem-solving/workflow.yaml +0 -43
- package/src/modules/cis/workflows/storytelling/README.md +0 -58
- package/src/modules/cis/workflows/storytelling/instructions.md +0 -291
- package/src/modules/cis/workflows/storytelling/story-types.csv +0 -26
- package/src/modules/cis/workflows/storytelling/template.md +0 -113
- package/src/modules/cis/workflows/storytelling/workflow.yaml +0 -43
- package/src/utility/models/agent-activation-ide.xml +0 -51
- package/src/utility/models/agent-activation-web.xml +0 -60
- package/src/utility/models/agent-command-header.md +0 -1
- package/src/utility/models/agent-config-template.md +0 -23
- package/src/utility/models/agent-in-team-activation.xml +0 -3
- package/src/utility/models/fragments/activation-rules.xml +0 -8
- package/src/utility/models/fragments/activation-steps.xml +0 -16
- package/src/utility/models/fragments/handler-action.xml +0 -4
- package/src/utility/models/fragments/handler-exec.xml +0 -5
- package/src/utility/models/fragments/handler-tmpl.xml +0 -5
- package/src/utility/models/fragments/handler-validate-workflow.xml +0 -7
- package/src/utility/models/fragments/handler-workflow.xml +0 -9
- package/src/utility/models/fragments/menu-handlers.xml +0 -6
- package/src/utility/models/fragments/web-bundle-activation-steps.xml +0 -32
- package/src/utility/templates/agent.customize.template.yaml +0 -42
- package/test/fixtures/agent-schema/invalid/metadata/core-agent-with-module.agent.yaml +0 -26
- package/test/fixtures/agent-schema/invalid/metadata/module-agent-missing-module.agent.yaml +0 -25
- package/test/fixtures/agent-schema/invalid/metadata/wrong-module-value.agent.yaml +0 -26
- package/tools/cli/bundlers/bundle-web.js +0 -179
- package/tools/cli/bundlers/test-analyst.js +0 -28
- package/tools/cli/bundlers/test-bundler.js +0 -118
- package/tools/cli/bundlers/web-bundler.js +0 -1667
- package/tools/cli/commands/build.js +0 -458
- package/tools/cli/commands/list.js +0 -28
- package/tools/cli/commands/update.js +0 -28
- package/tools/cli/installers/lib/ide/auggie.js +0 -179
- package/tools/cli/installers/lib/ide/claude-code.js +0 -471
- package/tools/cli/installers/lib/ide/cline.js +0 -220
- package/tools/cli/installers/lib/ide/crush.js +0 -240
- package/tools/cli/installers/lib/ide/cursor.js +0 -352
- package/tools/cli/installers/lib/ide/gemini.js +0 -206
- package/tools/cli/installers/lib/ide/iflow.js +0 -125
- package/tools/cli/installers/lib/ide/opencode.js +0 -212
- package/tools/cli/installers/lib/ide/qwen.js +0 -318
- package/tools/cli/installers/lib/ide/roo.js +0 -253
- package/tools/cli/installers/lib/ide/templates/gemini-agent-command.toml +0 -14
- package/tools/cli/installers/lib/ide/templates/gemini-task-command.toml +0 -12
- package/tools/cli/installers/lib/ide/trae.js +0 -266
- package/tools/cli/installers/lib/ide/windsurf.js +0 -211
- package/tools/cli/lib/replace-project-root.js +0 -239
- package/tools/cli/regenerate-manifests.js +0 -28
- package/tools/cli/test-yaml-builder.js +0 -43
- package/tools/flattener/aggregate.js +0 -76
- package/tools/flattener/binary.js +0 -80
- package/tools/flattener/discovery.js +0 -71
- package/tools/flattener/files.js +0 -35
- package/tools/flattener/ignoreRules.js +0 -172
- package/tools/flattener/main.js +0 -483
- package/tools/flattener/projectRoot.js +0 -201
- package/tools/flattener/prompts.js +0 -44
- package/tools/flattener/stats.helpers.js +0 -368
- package/tools/flattener/stats.js +0 -75
- package/tools/flattener/test-matrix.js +0 -409
- package/tools/flattener/xml.js +0 -88
- package/tools/validate-bundles.js +0 -87
- package/v6-open-items.md +0 -17
- /package/src/{modules/bmm → bmm}/teams/team-fullstack.yaml +0 -0
- /package/src/{modules/bmgd/workflows/4-production → bmm/workflows/4-implementation}/sprint-planning/checklist.md +0 -0
- /package/src/{modules/bmm → bmm}/workflows/document-project/documentation-requirements.csv +0 -0
- /package/src/{modules/bmm → bmm}/workflows/document-project/templates/deep-dive-template.md +0 -0
- /package/src/{modules/bmm → bmm}/workflows/document-project/templates/index-template.md +0 -0
- /package/src/{modules/bmm → bmm}/workflows/document-project/templates/project-overview-template.md +0 -0
- /package/src/{modules/bmm → bmm}/workflows/document-project/templates/source-tree-template.md +0 -0
- /package/src/utility/{models/fragments/handler-data.xml → agent-components/handler-data.txt} +0 -0
- /package/{src/utility/models/action-command-header.md → tools/cli/installers/lib/ide/templates/split/.gitkeep} +0 -0
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
const path = require('node:path');
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
|
-
const yaml = require('
|
|
4
|
-
const
|
|
3
|
+
const yaml = require('yaml');
|
|
4
|
+
const prompts = require('../../../lib/prompts');
|
|
5
5
|
const { XmlHandler } = require('../../../lib/xml-handler');
|
|
6
6
|
const { getProjectRoot, getSourcePath, getModulePath } = require('../../../lib/project-root');
|
|
7
|
+
const { filterCustomizationData } = require('../../../lib/agent/compiler');
|
|
8
|
+
const { ExternalModuleManager } = require('./external-manager');
|
|
9
|
+
const { BMAD_FOLDER_NAME } = require('../ide/shared/path-utils');
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Manages the installation, updating, and removal of BMAD modules.
|
|
@@ -12,8 +15,8 @@ const { getProjectRoot, getSourcePath, getModulePath } = require('../../../lib/p
|
|
|
12
15
|
*
|
|
13
16
|
* @class ModuleManager
|
|
14
17
|
* @requires fs-extra
|
|
15
|
-
* @requires
|
|
16
|
-
* @requires
|
|
18
|
+
* @requires yaml
|
|
19
|
+
* @requires prompts
|
|
17
20
|
* @requires XmlHandler
|
|
18
21
|
*
|
|
19
22
|
* @example
|
|
@@ -22,11 +25,11 @@ const { getProjectRoot, getSourcePath, getModulePath } = require('../../../lib/p
|
|
|
22
25
|
* await manager.install('core-module', '/path/to/bmad');
|
|
23
26
|
*/
|
|
24
27
|
class ModuleManager {
|
|
25
|
-
constructor() {
|
|
26
|
-
// Path to source modules directory
|
|
27
|
-
this.modulesSourcePath = getSourcePath('modules');
|
|
28
|
+
constructor(options = {}) {
|
|
28
29
|
this.xmlHandler = new XmlHandler();
|
|
29
|
-
this.bmadFolderName =
|
|
30
|
+
this.bmadFolderName = BMAD_FOLDER_NAME; // Default, can be overridden
|
|
31
|
+
this.customModulePaths = new Map(); // Initialize custom module paths
|
|
32
|
+
this.externalModuleManager = new ExternalModuleManager(); // For external official modules
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
/**
|
|
@@ -38,45 +41,38 @@ class ModuleManager {
|
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
/**
|
|
41
|
-
*
|
|
42
|
-
* @param {
|
|
43
|
-
* @param {string} targetPath - Target file path
|
|
44
|
+
* Set the core configuration for access during module installation
|
|
45
|
+
* @param {Object} coreConfig - Core configuration object
|
|
44
46
|
*/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const ext = path.extname(sourcePath).toLowerCase();
|
|
49
|
-
|
|
50
|
-
// Check if this is a text file that might contain placeholders
|
|
51
|
-
if (textExtensions.includes(ext)) {
|
|
52
|
-
try {
|
|
53
|
-
// Read the file content
|
|
54
|
-
let content = await fs.readFile(sourcePath, 'utf8');
|
|
47
|
+
setCoreConfig(coreConfig) {
|
|
48
|
+
this.coreConfig = coreConfig;
|
|
49
|
+
}
|
|
55
50
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Set custom module paths for priority lookup
|
|
53
|
+
* @param {Map<string, string>} customModulePaths - Map of module ID to source path
|
|
54
|
+
*/
|
|
55
|
+
setCustomModulePaths(customModulePaths) {
|
|
56
|
+
this.customModulePaths = customModulePaths;
|
|
57
|
+
}
|
|
60
58
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// Binary file or other file type - just copy directly
|
|
70
|
-
await fs.copy(sourcePath, targetPath, { overwrite: true });
|
|
71
|
-
}
|
|
59
|
+
/**
|
|
60
|
+
* Copy a file to the target location
|
|
61
|
+
* @param {string} sourcePath - Source file path
|
|
62
|
+
* @param {string} targetPath - Target file path
|
|
63
|
+
* @param {boolean} overwrite - Whether to overwrite existing files (default: true)
|
|
64
|
+
*/
|
|
65
|
+
async copyFileWithPlaceholderReplacement(sourcePath, targetPath, overwrite = true) {
|
|
66
|
+
await fs.copy(sourcePath, targetPath, { overwrite });
|
|
72
67
|
}
|
|
73
68
|
|
|
74
69
|
/**
|
|
75
|
-
* Copy a directory recursively
|
|
70
|
+
* Copy a directory recursively
|
|
76
71
|
* @param {string} sourceDir - Source directory path
|
|
77
72
|
* @param {string} targetDir - Target directory path
|
|
73
|
+
* @param {boolean} overwrite - Whether to overwrite existing files (default: true)
|
|
78
74
|
*/
|
|
79
|
-
async copyDirectoryWithPlaceholderReplacement(sourceDir, targetDir) {
|
|
75
|
+
async copyDirectoryWithPlaceholderReplacement(sourceDir, targetDir, overwrite = true) {
|
|
80
76
|
await fs.ensureDir(targetDir);
|
|
81
77
|
const entries = await fs.readdir(sourceDir, { withFileTypes: true });
|
|
82
78
|
|
|
@@ -85,75 +81,438 @@ class ModuleManager {
|
|
|
85
81
|
const targetPath = path.join(targetDir, entry.name);
|
|
86
82
|
|
|
87
83
|
if (entry.isDirectory()) {
|
|
88
|
-
await this.copyDirectoryWithPlaceholderReplacement(sourcePath, targetPath);
|
|
84
|
+
await this.copyDirectoryWithPlaceholderReplacement(sourcePath, targetPath, overwrite);
|
|
85
|
+
} else {
|
|
86
|
+
await this.copyFileWithPlaceholderReplacement(sourcePath, targetPath, overwrite);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Copy sidecar directory to _bmad/_memory location with update-safe handling
|
|
93
|
+
* @param {string} sourceSidecarPath - Source sidecar directory path
|
|
94
|
+
* @param {string} agentName - Name of the agent (for naming)
|
|
95
|
+
* @param {string} bmadMemoryPath - This should ALWAYS be _bmad/_memory
|
|
96
|
+
* @param {boolean} isUpdate - Whether this is an update (default: false)
|
|
97
|
+
* @param {string} bmadDir - BMAD installation directory
|
|
98
|
+
* @param {Object} installer - Installer instance for file tracking
|
|
99
|
+
*/
|
|
100
|
+
async copySidecarToMemory(sourceSidecarPath, agentName, bmadMemoryPath, isUpdate = false, bmadDir = null, installer = null) {
|
|
101
|
+
const crypto = require('node:crypto');
|
|
102
|
+
const sidecarTargetDir = path.join(bmadMemoryPath, `${agentName}-sidecar`);
|
|
103
|
+
|
|
104
|
+
// Ensure target directory exists
|
|
105
|
+
await fs.ensureDir(bmadMemoryPath);
|
|
106
|
+
await fs.ensureDir(sidecarTargetDir);
|
|
107
|
+
|
|
108
|
+
// Get existing files manifest for update checking
|
|
109
|
+
let existingFilesManifest = [];
|
|
110
|
+
if (isUpdate && installer) {
|
|
111
|
+
existingFilesManifest = await installer.readFilesManifest(bmadDir);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Build map of existing sidecar files with their hashes
|
|
115
|
+
const existingSidecarFiles = new Map();
|
|
116
|
+
for (const fileEntry of existingFilesManifest) {
|
|
117
|
+
if (fileEntry.path && fileEntry.path.includes(`${agentName}-sidecar/`)) {
|
|
118
|
+
existingSidecarFiles.set(fileEntry.path, fileEntry.hash);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Get all files in source sidecar
|
|
123
|
+
const sourceFiles = await this.getFileList(sourceSidecarPath);
|
|
124
|
+
|
|
125
|
+
for (const file of sourceFiles) {
|
|
126
|
+
const sourceFilePath = path.join(sourceSidecarPath, file);
|
|
127
|
+
const targetFilePath = path.join(sidecarTargetDir, file);
|
|
128
|
+
|
|
129
|
+
// Calculate current source file hash
|
|
130
|
+
const sourceHash = crypto
|
|
131
|
+
.createHash('sha256')
|
|
132
|
+
.update(await fs.readFile(sourceFilePath))
|
|
133
|
+
.digest('hex');
|
|
134
|
+
|
|
135
|
+
// Path relative to bmad directory
|
|
136
|
+
const relativeToBmad = path.join('_memory', `${agentName}-sidecar`, file);
|
|
137
|
+
|
|
138
|
+
if (isUpdate && (await fs.pathExists(targetFilePath))) {
|
|
139
|
+
// Calculate current target file hash
|
|
140
|
+
const currentTargetHash = crypto
|
|
141
|
+
.createHash('sha256')
|
|
142
|
+
.update(await fs.readFile(targetFilePath))
|
|
143
|
+
.digest('hex');
|
|
144
|
+
|
|
145
|
+
// Get the last known hash from files-manifest
|
|
146
|
+
const lastKnownHash = existingSidecarFiles.get(relativeToBmad);
|
|
147
|
+
|
|
148
|
+
if (lastKnownHash) {
|
|
149
|
+
// We have a record of this file
|
|
150
|
+
if (currentTargetHash === lastKnownHash) {
|
|
151
|
+
// File hasn't been modified by user, safe to update
|
|
152
|
+
await this.copyFileWithPlaceholderReplacement(sourceFilePath, targetFilePath, true);
|
|
153
|
+
if (process.env.BMAD_VERBOSE_INSTALL === 'true') {
|
|
154
|
+
await prompts.log.message(` Updated sidecar file: ${relativeToBmad}`);
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
// User has modified the file, preserve it
|
|
158
|
+
if (process.env.BMAD_VERBOSE_INSTALL === 'true') {
|
|
159
|
+
await prompts.log.message(` Preserving user-modified file: ${relativeToBmad}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
// First time seeing this file in manifest, copy it
|
|
164
|
+
await this.copyFileWithPlaceholderReplacement(sourceFilePath, targetFilePath, true);
|
|
165
|
+
if (process.env.BMAD_VERBOSE_INSTALL === 'true') {
|
|
166
|
+
await prompts.log.message(` Added new sidecar file: ${relativeToBmad}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
89
169
|
} else {
|
|
90
|
-
|
|
170
|
+
// New installation
|
|
171
|
+
await this.copyFileWithPlaceholderReplacement(sourceFilePath, targetFilePath, true);
|
|
172
|
+
if (process.env.BMAD_VERBOSE_INSTALL === 'true') {
|
|
173
|
+
await prompts.log.message(` Copied sidecar file: ${relativeToBmad}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Track the file in the installer's file tracking system
|
|
178
|
+
if (installer && installer.installedFiles) {
|
|
179
|
+
installer.installedFiles.add(targetFilePath);
|
|
91
180
|
}
|
|
92
181
|
}
|
|
182
|
+
|
|
183
|
+
// Return list of files that were processed
|
|
184
|
+
const processedFiles = sourceFiles.map((file) => path.join('_memory', `${agentName}-sidecar`, file));
|
|
185
|
+
return processedFiles;
|
|
93
186
|
}
|
|
94
187
|
|
|
95
188
|
/**
|
|
96
|
-
* List all available modules
|
|
97
|
-
*
|
|
189
|
+
* List all available modules (excluding core which is always installed)
|
|
190
|
+
* bmm is the only built-in module, directly under src/bmm
|
|
191
|
+
* All other modules come from external-official-modules.yaml
|
|
192
|
+
* @returns {Object} Object with modules array and customModules array
|
|
98
193
|
*/
|
|
99
194
|
async listAvailable() {
|
|
100
195
|
const modules = [];
|
|
196
|
+
const customModules = [];
|
|
197
|
+
|
|
198
|
+
// Add built-in bmm module (directly under src/bmm)
|
|
199
|
+
const bmmPath = getSourcePath('bmm');
|
|
200
|
+
if (await fs.pathExists(bmmPath)) {
|
|
201
|
+
const bmmInfo = await this.getModuleInfo(bmmPath, 'bmm', 'src/bmm');
|
|
202
|
+
if (bmmInfo) {
|
|
203
|
+
modules.push(bmmInfo);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
101
206
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
207
|
+
// Check for cached custom modules in _config/custom/
|
|
208
|
+
if (this.bmadDir) {
|
|
209
|
+
const customCacheDir = path.join(this.bmadDir, '_config', 'custom');
|
|
210
|
+
if (await fs.pathExists(customCacheDir)) {
|
|
211
|
+
const cacheEntries = await fs.readdir(customCacheDir, { withFileTypes: true });
|
|
212
|
+
for (const entry of cacheEntries) {
|
|
213
|
+
if (entry.isDirectory()) {
|
|
214
|
+
const cachePath = path.join(customCacheDir, entry.name);
|
|
215
|
+
const moduleInfo = await this.getModuleInfo(cachePath, entry.name, '_config/custom');
|
|
216
|
+
if (moduleInfo && !modules.some((m) => m.id === moduleInfo.id) && !customModules.some((m) => m.id === moduleInfo.id)) {
|
|
217
|
+
moduleInfo.isCustom = true;
|
|
218
|
+
moduleInfo.fromCache = true;
|
|
219
|
+
customModules.push(moduleInfo);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
105
224
|
}
|
|
106
225
|
|
|
107
|
-
|
|
226
|
+
return { modules, customModules };
|
|
227
|
+
}
|
|
108
228
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
229
|
+
/**
|
|
230
|
+
* Get module information from a module path
|
|
231
|
+
* @param {string} modulePath - Path to the module directory
|
|
232
|
+
* @param {string} defaultName - Default name for the module
|
|
233
|
+
* @param {string} sourceDescription - Description of where the module was found
|
|
234
|
+
* @returns {Object|null} Module info or null if not a valid module
|
|
235
|
+
*/
|
|
236
|
+
async getModuleInfo(modulePath, defaultName, sourceDescription) {
|
|
237
|
+
// Check for module structure (module.yaml OR custom.yaml)
|
|
238
|
+
const moduleConfigPath = path.join(modulePath, 'module.yaml');
|
|
239
|
+
const rootCustomConfigPath = path.join(modulePath, 'custom.yaml');
|
|
240
|
+
let configPath = null;
|
|
241
|
+
|
|
242
|
+
if (await fs.pathExists(moduleConfigPath)) {
|
|
243
|
+
configPath = moduleConfigPath;
|
|
244
|
+
} else if (await fs.pathExists(rootCustomConfigPath)) {
|
|
245
|
+
configPath = rootCustomConfigPath;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Skip if this doesn't look like a module
|
|
249
|
+
if (!configPath) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Mark as custom if it's using custom.yaml OR if it's outside src/bmm or src/core
|
|
254
|
+
const isCustomSource = sourceDescription !== 'src/bmm' && sourceDescription !== 'src/core' && sourceDescription !== 'src/modules';
|
|
255
|
+
const moduleInfo = {
|
|
256
|
+
id: defaultName,
|
|
257
|
+
path: modulePath,
|
|
258
|
+
name: defaultName
|
|
259
|
+
.split('-')
|
|
260
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
261
|
+
.join(' '),
|
|
262
|
+
description: 'BMAD Module',
|
|
263
|
+
version: '5.0.0',
|
|
264
|
+
source: sourceDescription,
|
|
265
|
+
isCustom: configPath === rootCustomConfigPath || isCustomSource,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// Read module config for metadata
|
|
269
|
+
try {
|
|
270
|
+
const configContent = await fs.readFile(configPath, 'utf8');
|
|
271
|
+
const config = yaml.parse(configContent);
|
|
272
|
+
|
|
273
|
+
// Use the code property as the id if available
|
|
274
|
+
if (config.code) {
|
|
275
|
+
moduleInfo.id = config.code;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
moduleInfo.name = config.name || moduleInfo.name;
|
|
279
|
+
moduleInfo.description = config.description || moduleInfo.description;
|
|
280
|
+
moduleInfo.version = config.version || moduleInfo.version;
|
|
281
|
+
moduleInfo.dependencies = config.dependencies || [];
|
|
282
|
+
moduleInfo.defaultSelected = config.default_selected === undefined ? false : config.default_selected;
|
|
283
|
+
} catch (error) {
|
|
284
|
+
await prompts.log.warn(`Failed to read config for ${defaultName}: ${error.message}`);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return moduleInfo;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Find the source path for a module by searching all possible locations
|
|
292
|
+
* @param {string} moduleCode - Code of the module to find (from module.yaml)
|
|
293
|
+
* @returns {string|null} Path to the module source or null if not found
|
|
294
|
+
*/
|
|
295
|
+
async findModuleSource(moduleCode, options = {}) {
|
|
296
|
+
const projectRoot = getProjectRoot();
|
|
297
|
+
|
|
298
|
+
// First check custom module paths if they exist
|
|
299
|
+
if (this.customModulePaths && this.customModulePaths.has(moduleCode)) {
|
|
300
|
+
return this.customModulePaths.get(moduleCode);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Check for built-in bmm module (directly under src/bmm)
|
|
304
|
+
if (moduleCode === 'bmm') {
|
|
305
|
+
const bmmPath = getSourcePath('bmm');
|
|
306
|
+
if (await fs.pathExists(bmmPath)) {
|
|
307
|
+
return bmmPath;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Check external official modules
|
|
312
|
+
const externalSource = await this.findExternalModuleSource(moduleCode, options);
|
|
313
|
+
if (externalSource) {
|
|
314
|
+
return externalSource;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Check if a module is an external official module
|
|
322
|
+
* @param {string} moduleCode - Code of the module to check
|
|
323
|
+
* @returns {boolean} True if the module is external
|
|
324
|
+
*/
|
|
325
|
+
async isExternalModule(moduleCode) {
|
|
326
|
+
return await this.externalModuleManager.hasModule(moduleCode);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Get the cache directory for external modules
|
|
331
|
+
* @returns {string} Path to the external modules cache directory
|
|
332
|
+
*/
|
|
333
|
+
getExternalCacheDir() {
|
|
334
|
+
const os = require('node:os');
|
|
335
|
+
const cacheDir = path.join(os.homedir(), '.bmad', 'cache', 'external-modules');
|
|
336
|
+
return cacheDir;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Clone an external module repository to cache
|
|
341
|
+
* @param {string} moduleCode - Code of the external module
|
|
342
|
+
* @returns {string} Path to the cloned repository
|
|
343
|
+
*/
|
|
344
|
+
async cloneExternalModule(moduleCode, options = {}) {
|
|
345
|
+
const { execSync } = require('node:child_process');
|
|
346
|
+
const moduleInfo = await this.externalModuleManager.getModuleByCode(moduleCode);
|
|
347
|
+
|
|
348
|
+
if (!moduleInfo) {
|
|
349
|
+
throw new Error(`External module '${moduleCode}' not found in external-official-modules.yaml`);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const cacheDir = this.getExternalCacheDir();
|
|
353
|
+
const moduleCacheDir = path.join(cacheDir, moduleCode);
|
|
354
|
+
const silent = options.silent || false;
|
|
355
|
+
|
|
356
|
+
// Create cache directory if it doesn't exist
|
|
357
|
+
await fs.ensureDir(cacheDir);
|
|
358
|
+
|
|
359
|
+
// Helper to create a spinner or a no-op when silent
|
|
360
|
+
const createSpinner = async () => {
|
|
361
|
+
if (silent) {
|
|
362
|
+
return {
|
|
363
|
+
start() {},
|
|
364
|
+
stop() {},
|
|
365
|
+
error() {},
|
|
366
|
+
message() {},
|
|
367
|
+
cancel() {},
|
|
368
|
+
clear() {},
|
|
369
|
+
get isSpinning() {
|
|
370
|
+
return false;
|
|
371
|
+
},
|
|
372
|
+
get isCancelled() {
|
|
373
|
+
return false;
|
|
374
|
+
},
|
|
123
375
|
};
|
|
376
|
+
}
|
|
377
|
+
return await prompts.spinner();
|
|
378
|
+
};
|
|
124
379
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
try {
|
|
129
|
-
const configContent = await fs.readFile(configToRead, 'utf8');
|
|
130
|
-
const config = yaml.load(configContent);
|
|
380
|
+
// Track if we need to install dependencies
|
|
381
|
+
let needsDependencyInstall = false;
|
|
382
|
+
let wasNewClone = false;
|
|
131
383
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
384
|
+
// Check if already cloned
|
|
385
|
+
if (await fs.pathExists(moduleCacheDir)) {
|
|
386
|
+
// Try to update if it's a git repo
|
|
387
|
+
const fetchSpinner = await createSpinner();
|
|
388
|
+
fetchSpinner.start(`Fetching ${moduleInfo.name}...`);
|
|
389
|
+
try {
|
|
390
|
+
const currentRef = execSync('git rev-parse HEAD', { cwd: moduleCacheDir, stdio: 'pipe' }).toString().trim();
|
|
391
|
+
// Fetch and reset to remote - works better with shallow clones than pull
|
|
392
|
+
execSync('git fetch origin --depth 1', {
|
|
393
|
+
cwd: moduleCacheDir,
|
|
394
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
395
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
396
|
+
});
|
|
397
|
+
execSync('git reset --hard origin/HEAD', {
|
|
398
|
+
cwd: moduleCacheDir,
|
|
399
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
400
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
401
|
+
});
|
|
402
|
+
const newRef = execSync('git rev-parse HEAD', { cwd: moduleCacheDir, stdio: 'pipe' }).toString().trim();
|
|
136
403
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
404
|
+
fetchSpinner.stop(`Fetched ${moduleInfo.name}`);
|
|
405
|
+
// Force dependency install if we got new code
|
|
406
|
+
if (currentRef !== newRef) {
|
|
407
|
+
needsDependencyInstall = true;
|
|
408
|
+
}
|
|
409
|
+
} catch {
|
|
410
|
+
fetchSpinner.error(`Fetch failed, re-downloading ${moduleInfo.name}`);
|
|
411
|
+
// If update fails, remove and re-clone
|
|
412
|
+
await fs.remove(moduleCacheDir);
|
|
413
|
+
wasNewClone = true;
|
|
414
|
+
}
|
|
415
|
+
} else {
|
|
416
|
+
wasNewClone = true;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Clone if not exists or was removed
|
|
420
|
+
if (wasNewClone) {
|
|
421
|
+
const fetchSpinner = await createSpinner();
|
|
422
|
+
fetchSpinner.start(`Fetching ${moduleInfo.name}...`);
|
|
423
|
+
try {
|
|
424
|
+
execSync(`git clone --depth 1 "${moduleInfo.url}" "${moduleCacheDir}"`, {
|
|
425
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
426
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
427
|
+
});
|
|
428
|
+
fetchSpinner.stop(`Fetched ${moduleInfo.name}`);
|
|
429
|
+
} catch (error) {
|
|
430
|
+
fetchSpinner.error(`Failed to fetch ${moduleInfo.name}`);
|
|
431
|
+
throw new Error(`Failed to clone external module '${moduleCode}': ${error.message}`);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Install dependencies if package.json exists
|
|
436
|
+
const packageJsonPath = path.join(moduleCacheDir, 'package.json');
|
|
437
|
+
const nodeModulesPath = path.join(moduleCacheDir, 'node_modules');
|
|
438
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
439
|
+
// Install if node_modules doesn't exist, or if package.json is newer (dependencies changed)
|
|
440
|
+
const nodeModulesMissing = !(await fs.pathExists(nodeModulesPath));
|
|
441
|
+
|
|
442
|
+
// Force install if we updated or cloned new
|
|
443
|
+
if (needsDependencyInstall || wasNewClone || nodeModulesMissing) {
|
|
444
|
+
const installSpinner = await createSpinner();
|
|
445
|
+
installSpinner.start(`Installing dependencies for ${moduleInfo.name}...`);
|
|
446
|
+
try {
|
|
447
|
+
execSync('npm install --omit=dev --no-audit --no-fund --no-progress --legacy-peer-deps', {
|
|
448
|
+
cwd: moduleCacheDir,
|
|
449
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
450
|
+
timeout: 120_000, // 2 minute timeout
|
|
451
|
+
});
|
|
452
|
+
installSpinner.stop(`Installed dependencies for ${moduleInfo.name}`);
|
|
453
|
+
} catch (error) {
|
|
454
|
+
installSpinner.error(`Failed to install dependencies for ${moduleInfo.name}`);
|
|
455
|
+
if (!silent) await prompts.log.warn(` ${error.message}`);
|
|
456
|
+
}
|
|
457
|
+
} else {
|
|
458
|
+
// Check if package.json is newer than node_modules
|
|
459
|
+
let packageJsonNewer = false;
|
|
460
|
+
try {
|
|
461
|
+
const packageStats = await fs.stat(packageJsonPath);
|
|
462
|
+
const nodeModulesStats = await fs.stat(nodeModulesPath);
|
|
463
|
+
packageJsonNewer = packageStats.mtime > nodeModulesStats.mtime;
|
|
464
|
+
} catch {
|
|
465
|
+
// If stat fails, assume we need to install
|
|
466
|
+
packageJsonNewer = true;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (packageJsonNewer) {
|
|
470
|
+
const installSpinner = await createSpinner();
|
|
471
|
+
installSpinner.start(`Installing dependencies for ${moduleInfo.name}...`);
|
|
472
|
+
try {
|
|
473
|
+
execSync('npm install --omit=dev --no-audit --no-fund --no-progress --legacy-peer-deps', {
|
|
474
|
+
cwd: moduleCacheDir,
|
|
475
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
476
|
+
timeout: 120_000, // 2 minute timeout
|
|
477
|
+
});
|
|
478
|
+
installSpinner.stop(`Installed dependencies for ${moduleInfo.name}`);
|
|
142
479
|
} catch (error) {
|
|
143
|
-
|
|
480
|
+
installSpinner.error(`Failed to install dependencies for ${moduleInfo.name}`);
|
|
481
|
+
if (!silent) await prompts.log.warn(` ${error.message}`);
|
|
144
482
|
}
|
|
145
483
|
}
|
|
146
|
-
|
|
147
|
-
modules.push(moduleInfo);
|
|
148
484
|
}
|
|
149
485
|
}
|
|
150
486
|
|
|
151
|
-
return
|
|
487
|
+
return moduleCacheDir;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Find the source path for an external module
|
|
492
|
+
* @param {string} moduleCode - Code of the external module
|
|
493
|
+
* @returns {string|null} Path to the module source or null if not found
|
|
494
|
+
*/
|
|
495
|
+
async findExternalModuleSource(moduleCode, options = {}) {
|
|
496
|
+
const moduleInfo = await this.externalModuleManager.getModuleByCode(moduleCode);
|
|
497
|
+
|
|
498
|
+
if (!moduleInfo) {
|
|
499
|
+
return null;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Clone the external module repo
|
|
503
|
+
const cloneDir = await this.cloneExternalModule(moduleCode, options);
|
|
504
|
+
|
|
505
|
+
// The module-definition specifies the path to module.yaml relative to repo root
|
|
506
|
+
// We need to return the directory containing module.yaml
|
|
507
|
+
const moduleDefinitionPath = moduleInfo.moduleDefinition; // e.g., 'src/module.yaml'
|
|
508
|
+
const moduleDir = path.dirname(path.join(cloneDir, moduleDefinitionPath));
|
|
509
|
+
|
|
510
|
+
return moduleDir;
|
|
152
511
|
}
|
|
153
512
|
|
|
154
513
|
/**
|
|
155
514
|
* Install a module
|
|
156
|
-
* @param {string} moduleName -
|
|
515
|
+
* @param {string} moduleName - Code of the module to install (from module.yaml)
|
|
157
516
|
* @param {string} bmadDir - Target bmad directory
|
|
158
517
|
* @param {Function} fileTrackingCallback - Optional callback to track installed files
|
|
159
518
|
* @param {Object} options - Additional installation options
|
|
@@ -162,17 +521,40 @@ class ModuleManager {
|
|
|
162
521
|
* @param {Object} options.logger - Logger instance for output
|
|
163
522
|
*/
|
|
164
523
|
async install(moduleName, bmadDir, fileTrackingCallback = null, options = {}) {
|
|
165
|
-
const sourcePath =
|
|
524
|
+
const sourcePath = await this.findModuleSource(moduleName, { silent: options.silent });
|
|
166
525
|
const targetPath = path.join(bmadDir, moduleName);
|
|
167
526
|
|
|
168
527
|
// Check if source module exists
|
|
169
|
-
if (!
|
|
170
|
-
|
|
528
|
+
if (!sourcePath) {
|
|
529
|
+
// Provide a more user-friendly error message
|
|
530
|
+
throw new Error(
|
|
531
|
+
`Source for module '${moduleName}' is not available. It will be retained but cannot be updated without its source files.`,
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Check if this is a custom module and read its custom.yaml values
|
|
536
|
+
let customConfig = null;
|
|
537
|
+
const rootCustomConfigPath = path.join(sourcePath, 'custom.yaml');
|
|
538
|
+
|
|
539
|
+
if (await fs.pathExists(rootCustomConfigPath)) {
|
|
540
|
+
try {
|
|
541
|
+
const customContent = await fs.readFile(rootCustomConfigPath, 'utf8');
|
|
542
|
+
customConfig = yaml.parse(customContent);
|
|
543
|
+
} catch (error) {
|
|
544
|
+
await prompts.log.warn(`Failed to read custom.yaml for ${moduleName}: ${error.message}`);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// If this is a custom module, merge its values into the module config
|
|
549
|
+
if (customConfig) {
|
|
550
|
+
options.moduleConfig = { ...options.moduleConfig, ...customConfig };
|
|
551
|
+
if (options.logger) {
|
|
552
|
+
await options.logger.log(` Merged custom configuration for ${moduleName}`);
|
|
553
|
+
}
|
|
171
554
|
}
|
|
172
555
|
|
|
173
556
|
// Check if already installed
|
|
174
557
|
if (await fs.pathExists(targetPath)) {
|
|
175
|
-
console.log(chalk.yellow(`Module '${moduleName}' already installed, updating...`));
|
|
176
558
|
await fs.remove(targetPath);
|
|
177
559
|
}
|
|
178
560
|
|
|
@@ -183,18 +565,34 @@ class ModuleManager {
|
|
|
183
565
|
// Copy module files with filtering
|
|
184
566
|
await this.copyModuleWithFiltering(sourcePath, targetPath, fileTrackingCallback, options.moduleConfig);
|
|
185
567
|
|
|
568
|
+
// Compile any .agent.yaml files to .md format
|
|
569
|
+
await this.compileModuleAgents(sourcePath, targetPath, moduleName, bmadDir, options.installer);
|
|
570
|
+
|
|
186
571
|
// Process agent files to inject activation block
|
|
187
572
|
await this.processAgentFiles(targetPath, moduleName);
|
|
188
573
|
|
|
189
|
-
//
|
|
574
|
+
// Create directories declared in module.yaml (unless explicitly skipped)
|
|
190
575
|
if (!options.skipModuleInstaller) {
|
|
191
|
-
await this.
|
|
576
|
+
await this.createModuleDirectories(moduleName, bmadDir, options);
|
|
192
577
|
}
|
|
193
578
|
|
|
579
|
+
// Capture version info for manifest
|
|
580
|
+
const { Manifest } = require('../core/manifest');
|
|
581
|
+
const manifestObj = new Manifest();
|
|
582
|
+
const versionInfo = await manifestObj.getModuleVersionInfo(moduleName, bmadDir, sourcePath);
|
|
583
|
+
|
|
584
|
+
await manifestObj.addModule(bmadDir, moduleName, {
|
|
585
|
+
version: versionInfo.version,
|
|
586
|
+
source: versionInfo.source,
|
|
587
|
+
npmPackage: versionInfo.npmPackage,
|
|
588
|
+
repoUrl: versionInfo.repoUrl,
|
|
589
|
+
});
|
|
590
|
+
|
|
194
591
|
return {
|
|
195
592
|
success: true,
|
|
196
593
|
module: moduleName,
|
|
197
594
|
path: targetPath,
|
|
595
|
+
versionInfo,
|
|
198
596
|
};
|
|
199
597
|
}
|
|
200
598
|
|
|
@@ -204,13 +602,13 @@ class ModuleManager {
|
|
|
204
602
|
* @param {string} bmadDir - Target bmad directory
|
|
205
603
|
* @param {boolean} force - Force update (overwrite modifications)
|
|
206
604
|
*/
|
|
207
|
-
async update(moduleName, bmadDir, force = false) {
|
|
208
|
-
const sourcePath =
|
|
605
|
+
async update(moduleName, bmadDir, force = false, options = {}) {
|
|
606
|
+
const sourcePath = await this.findModuleSource(moduleName);
|
|
209
607
|
const targetPath = path.join(bmadDir, moduleName);
|
|
210
608
|
|
|
211
609
|
// Check if source module exists
|
|
212
|
-
if (!
|
|
213
|
-
throw new Error(`Module '${moduleName}' not found in source`);
|
|
610
|
+
if (!sourcePath) {
|
|
611
|
+
throw new Error(`Module '${moduleName}' not found in any source location`);
|
|
214
612
|
}
|
|
215
613
|
|
|
216
614
|
// Check if module is installed
|
|
@@ -221,10 +619,14 @@ class ModuleManager {
|
|
|
221
619
|
if (force) {
|
|
222
620
|
// Force update - remove and reinstall
|
|
223
621
|
await fs.remove(targetPath);
|
|
224
|
-
return await this.install(moduleName, bmadDir);
|
|
622
|
+
return await this.install(moduleName, bmadDir, null, { installer: options.installer });
|
|
225
623
|
} else {
|
|
226
624
|
// Selective update - preserve user modifications
|
|
227
625
|
await this.syncModule(sourcePath, targetPath);
|
|
626
|
+
|
|
627
|
+
// Recompile agents (#1133)
|
|
628
|
+
await this.compileModuleAgents(sourcePath, targetPath, moduleName, bmadDir, options.installer);
|
|
629
|
+
await this.processAgentFiles(targetPath, moduleName);
|
|
228
630
|
}
|
|
229
631
|
|
|
230
632
|
return {
|
|
@@ -288,10 +690,10 @@ class ModuleManager {
|
|
|
288
690
|
if (await fs.pathExists(configPath)) {
|
|
289
691
|
try {
|
|
290
692
|
const configContent = await fs.readFile(configPath, 'utf8');
|
|
291
|
-
const config = yaml.
|
|
693
|
+
const config = yaml.parse(configContent);
|
|
292
694
|
Object.assign(moduleInfo, config);
|
|
293
695
|
} catch (error) {
|
|
294
|
-
|
|
696
|
+
await prompts.log.warn(`Failed to read installed module config: ${error.message}`);
|
|
295
697
|
}
|
|
296
698
|
}
|
|
297
699
|
|
|
@@ -309,49 +711,39 @@ class ModuleManager {
|
|
|
309
711
|
// Get all files in source
|
|
310
712
|
const sourceFiles = await this.getFileList(sourcePath);
|
|
311
713
|
|
|
312
|
-
// Game development files to conditionally exclude
|
|
313
|
-
const gameDevFiles = [
|
|
314
|
-
'agents/game-architect.agent.yaml',
|
|
315
|
-
'agents/game-designer.agent.yaml',
|
|
316
|
-
'agents/game-dev.agent.yaml',
|
|
317
|
-
'workflows/1-analysis/brainstorm-game',
|
|
318
|
-
'workflows/1-analysis/game-brief',
|
|
319
|
-
'workflows/2-plan-workflows/gdd',
|
|
320
|
-
];
|
|
321
|
-
|
|
322
714
|
for (const file of sourceFiles) {
|
|
323
715
|
// Skip sub-modules directory - these are IDE-specific and handled separately
|
|
324
716
|
if (file.startsWith('sub-modules/')) {
|
|
325
717
|
continue;
|
|
326
718
|
}
|
|
327
719
|
|
|
328
|
-
//
|
|
329
|
-
|
|
720
|
+
// Only skip sidecar directories - they are handled separately during agent compilation
|
|
721
|
+
// But still allow other files in agent directories
|
|
722
|
+
const isInAgentDirectory = file.startsWith('agents/');
|
|
723
|
+
const isInSidecarDirectory = path
|
|
724
|
+
.dirname(file)
|
|
725
|
+
.split('/')
|
|
726
|
+
.some((dir) => dir.toLowerCase().endsWith('-sidecar'));
|
|
727
|
+
|
|
728
|
+
if (isInSidecarDirectory) {
|
|
330
729
|
continue;
|
|
331
730
|
}
|
|
332
731
|
|
|
333
|
-
// Skip
|
|
334
|
-
if (file === '
|
|
732
|
+
// Skip module.yaml at root - it's only needed at install time
|
|
733
|
+
if (file === 'module.yaml') {
|
|
335
734
|
continue;
|
|
336
735
|
}
|
|
337
736
|
|
|
338
|
-
// Skip
|
|
339
|
-
|
|
340
|
-
|
|
737
|
+
// Skip module root config.yaml only - generated by config collector with actual values
|
|
738
|
+
// Workflow-level config.yaml (e.g. workflows/orchestrate-story/config.yaml) must be copied
|
|
739
|
+
// for custom modules that use workflow-specific configuration
|
|
740
|
+
if (file === 'config.yaml') {
|
|
341
741
|
continue;
|
|
342
742
|
}
|
|
343
743
|
|
|
344
|
-
// Skip
|
|
345
|
-
if (
|
|
346
|
-
|
|
347
|
-
// Check if file path starts with or is within any game dev directory
|
|
348
|
-
return file === gamePath || file.startsWith(gamePath + '/') || file.startsWith(gamePath + '\\');
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
if (shouldSkipGameDev) {
|
|
352
|
-
console.log(chalk.dim(` Skipping game dev content: ${file}`));
|
|
353
|
-
continue;
|
|
354
|
-
}
|
|
744
|
+
// Skip .agent.yaml files - they will be compiled separately
|
|
745
|
+
if (file.endsWith('.agent.yaml')) {
|
|
746
|
+
continue;
|
|
355
747
|
}
|
|
356
748
|
|
|
357
749
|
const sourceFile = path.join(sourcePath, file);
|
|
@@ -365,7 +757,7 @@ class ModuleManager {
|
|
|
365
757
|
// Check for localskip="true" in the agent tag
|
|
366
758
|
const agentMatch = content.match(/<agent[^>]*\slocalskip="true"[^>]*>/);
|
|
367
759
|
if (agentMatch) {
|
|
368
|
-
|
|
760
|
+
await prompts.log.message(` Skipping web-only agent: ${path.basename(file)}`);
|
|
369
761
|
continue; // Skip this agent
|
|
370
762
|
}
|
|
371
763
|
}
|
|
@@ -396,13 +788,13 @@ class ModuleManager {
|
|
|
396
788
|
// Read the source YAML file
|
|
397
789
|
let yamlContent = await fs.readFile(sourceFile, 'utf8');
|
|
398
790
|
|
|
399
|
-
// IMPORTANT: Replace
|
|
791
|
+
// IMPORTANT: Replace escape sequence and placeholder BEFORE parsing YAML
|
|
400
792
|
// Otherwise parsing will fail on the placeholder
|
|
401
|
-
yamlContent = yamlContent.replaceAll('
|
|
793
|
+
yamlContent = yamlContent.replaceAll('_bmad', this.bmadFolderName);
|
|
402
794
|
|
|
403
795
|
try {
|
|
404
796
|
// First check if web_bundle exists by parsing
|
|
405
|
-
const workflowConfig = yaml.
|
|
797
|
+
const workflowConfig = yaml.parse(yamlContent);
|
|
406
798
|
|
|
407
799
|
if (workflowConfig.web_bundle === undefined) {
|
|
408
800
|
// No web_bundle section, just write (placeholders already replaced above)
|
|
@@ -410,10 +802,6 @@ class ModuleManager {
|
|
|
410
802
|
return;
|
|
411
803
|
}
|
|
412
804
|
|
|
413
|
-
// Remove web_bundle section using regex to preserve formatting
|
|
414
|
-
// Match the web_bundle key and all its content (including nested items)
|
|
415
|
-
// This handles both web_bundle: false and web_bundle: {...}
|
|
416
|
-
|
|
417
805
|
// Find the line that starts web_bundle
|
|
418
806
|
const lines = yamlContent.split('\n');
|
|
419
807
|
let startIdx = -1;
|
|
@@ -471,42 +859,267 @@ class ModuleManager {
|
|
|
471
859
|
await fs.writeFile(targetFile, strippedYaml, 'utf8');
|
|
472
860
|
} catch {
|
|
473
861
|
// If anything fails, just copy the file as-is
|
|
474
|
-
|
|
862
|
+
await prompts.log.warn(` Could not process ${path.basename(sourceFile)}, copying as-is`);
|
|
475
863
|
await fs.copy(sourceFile, targetFile, { overwrite: true });
|
|
476
864
|
}
|
|
477
865
|
}
|
|
478
866
|
|
|
479
867
|
/**
|
|
480
|
-
*
|
|
481
|
-
* @param {string}
|
|
868
|
+
* Compile .agent.yaml files to .md format in modules
|
|
869
|
+
* @param {string} sourcePath - Source module path
|
|
870
|
+
* @param {string} targetPath - Target module path
|
|
482
871
|
* @param {string} moduleName - Module name
|
|
872
|
+
* @param {string} bmadDir - BMAD installation directory
|
|
873
|
+
* @param {Object} installer - Installer instance for file tracking
|
|
483
874
|
*/
|
|
484
|
-
async
|
|
485
|
-
const
|
|
875
|
+
async compileModuleAgents(sourcePath, targetPath, moduleName, bmadDir, installer = null) {
|
|
876
|
+
const sourceAgentsPath = path.join(sourcePath, 'agents');
|
|
877
|
+
const targetAgentsPath = path.join(targetPath, 'agents');
|
|
878
|
+
const cfgAgentsDir = path.join(bmadDir, '_config', 'agents');
|
|
486
879
|
|
|
487
|
-
// Check if agents directory exists
|
|
488
|
-
if (!(await fs.pathExists(
|
|
489
|
-
return; // No agents to
|
|
880
|
+
// Check if agents directory exists in source
|
|
881
|
+
if (!(await fs.pathExists(sourceAgentsPath))) {
|
|
882
|
+
return; // No agents to compile
|
|
490
883
|
}
|
|
491
884
|
|
|
492
|
-
// Get all agent files
|
|
493
|
-
const agentFiles = await
|
|
885
|
+
// Get all agent YAML files recursively
|
|
886
|
+
const agentFiles = await this.findAgentFiles(sourceAgentsPath);
|
|
494
887
|
|
|
495
888
|
for (const agentFile of agentFiles) {
|
|
496
|
-
if (!agentFile.endsWith('.
|
|
889
|
+
if (!agentFile.endsWith('.agent.yaml')) continue;
|
|
890
|
+
|
|
891
|
+
const relativePath = path.relative(sourceAgentsPath, agentFile).split(path.sep).join('/');
|
|
892
|
+
const targetDir = path.join(targetAgentsPath, path.dirname(relativePath));
|
|
893
|
+
|
|
894
|
+
await fs.ensureDir(targetDir);
|
|
895
|
+
|
|
896
|
+
const agentName = path.basename(agentFile, '.agent.yaml');
|
|
897
|
+
const sourceYamlPath = agentFile;
|
|
898
|
+
const targetMdPath = path.join(targetDir, `${agentName}.md`);
|
|
899
|
+
const customizePath = path.join(cfgAgentsDir, `${moduleName}-${agentName}.customize.yaml`);
|
|
900
|
+
|
|
901
|
+
// Read and compile the YAML
|
|
902
|
+
try {
|
|
903
|
+
const yamlContent = await fs.readFile(sourceYamlPath, 'utf8');
|
|
904
|
+
const { compileAgent } = require('../../../lib/agent/compiler');
|
|
905
|
+
|
|
906
|
+
// Create customize template if it doesn't exist
|
|
907
|
+
if (!(await fs.pathExists(customizePath))) {
|
|
908
|
+
const { getSourcePath } = require('../../../lib/project-root');
|
|
909
|
+
const genericTemplatePath = getSourcePath('utility', 'agent-components', 'agent.customize.template.yaml');
|
|
910
|
+
if (await fs.pathExists(genericTemplatePath)) {
|
|
911
|
+
await this.copyFileWithPlaceholderReplacement(genericTemplatePath, customizePath);
|
|
912
|
+
// Only show customize creation in verbose mode
|
|
913
|
+
if (process.env.BMAD_VERBOSE_INSTALL === 'true') {
|
|
914
|
+
await prompts.log.message(` Created customize: ${moduleName}-${agentName}.customize.yaml`);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// Store original hash for modification detection
|
|
918
|
+
const crypto = require('node:crypto');
|
|
919
|
+
const customizeContent = await fs.readFile(customizePath, 'utf8');
|
|
920
|
+
const originalHash = crypto.createHash('sha256').update(customizeContent).digest('hex');
|
|
921
|
+
|
|
922
|
+
// Store in main manifest
|
|
923
|
+
const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml');
|
|
924
|
+
let manifestData = {};
|
|
925
|
+
if (await fs.pathExists(manifestPath)) {
|
|
926
|
+
const manifestContent = await fs.readFile(manifestPath, 'utf8');
|
|
927
|
+
const yaml = require('yaml');
|
|
928
|
+
manifestData = yaml.parse(manifestContent);
|
|
929
|
+
}
|
|
930
|
+
if (!manifestData.agentCustomizations) {
|
|
931
|
+
manifestData.agentCustomizations = {};
|
|
932
|
+
}
|
|
933
|
+
manifestData.agentCustomizations[path.relative(bmadDir, customizePath)] = originalHash;
|
|
934
|
+
|
|
935
|
+
// Write back to manifest
|
|
936
|
+
const yaml = require('yaml');
|
|
937
|
+
// Clean the manifest data to remove any non-serializable values
|
|
938
|
+
const cleanManifestData = structuredClone(manifestData);
|
|
939
|
+
|
|
940
|
+
const updatedContent = yaml.stringify(cleanManifestData, {
|
|
941
|
+
indent: 2,
|
|
942
|
+
lineWidth: 0,
|
|
943
|
+
});
|
|
944
|
+
await fs.writeFile(manifestPath, updatedContent, 'utf8');
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// Check for customizations and build answers object
|
|
949
|
+
let customizedFields = [];
|
|
950
|
+
let answers = {};
|
|
951
|
+
if (await fs.pathExists(customizePath)) {
|
|
952
|
+
const customizeContent = await fs.readFile(customizePath, 'utf8');
|
|
953
|
+
const customizeData = yaml.parse(customizeContent);
|
|
954
|
+
customizedFields = customizeData.customized_fields || [];
|
|
955
|
+
|
|
956
|
+
// Build answers object from customizations
|
|
957
|
+
if (customizeData.persona) {
|
|
958
|
+
answers.persona = customizeData.persona;
|
|
959
|
+
}
|
|
960
|
+
if (customizeData.agent?.metadata) {
|
|
961
|
+
const filteredMetadata = filterCustomizationData(customizeData.agent.metadata);
|
|
962
|
+
if (Object.keys(filteredMetadata).length > 0) {
|
|
963
|
+
Object.assign(answers, { metadata: filteredMetadata });
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
if (customizeData.critical_actions && customizeData.critical_actions.length > 0) {
|
|
967
|
+
answers.critical_actions = customizeData.critical_actions;
|
|
968
|
+
}
|
|
969
|
+
if (customizeData.memories && customizeData.memories.length > 0) {
|
|
970
|
+
answers.memories = customizeData.memories;
|
|
971
|
+
}
|
|
972
|
+
if (customizeData.menu && customizeData.menu.length > 0) {
|
|
973
|
+
answers.menu = customizeData.menu;
|
|
974
|
+
}
|
|
975
|
+
if (customizeData.prompts && customizeData.prompts.length > 0) {
|
|
976
|
+
answers.prompts = customizeData.prompts;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// Check if agent has sidecar
|
|
981
|
+
let hasSidecar = false;
|
|
982
|
+
try {
|
|
983
|
+
const agentYaml = yaml.parse(yamlContent);
|
|
984
|
+
hasSidecar = agentYaml?.agent?.metadata?.hasSidecar === true;
|
|
985
|
+
} catch {
|
|
986
|
+
// Continue without sidecar processing
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
// Compile with customizations if any
|
|
990
|
+
const { xml } = await compileAgent(yamlContent, answers, agentName, relativePath, { config: this.coreConfig || {} });
|
|
991
|
+
|
|
992
|
+
// Write the compiled agent
|
|
993
|
+
await fs.writeFile(targetMdPath, xml, 'utf8');
|
|
497
994
|
|
|
498
|
-
|
|
499
|
-
|
|
995
|
+
// Handle sidecar copying if present
|
|
996
|
+
if (hasSidecar) {
|
|
997
|
+
// Get the agent's directory to look for sidecar
|
|
998
|
+
const agentDir = path.dirname(agentFile);
|
|
999
|
+
const sidecarDirName = `${agentName}-sidecar`;
|
|
1000
|
+
const sourceSidecarPath = path.join(agentDir, sidecarDirName);
|
|
500
1001
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
1002
|
+
// Check if sidecar directory exists
|
|
1003
|
+
if (await fs.pathExists(sourceSidecarPath)) {
|
|
1004
|
+
// Memory is always in _bmad/_memory
|
|
1005
|
+
const bmadMemoryPath = path.join(bmadDir, '_memory');
|
|
1006
|
+
|
|
1007
|
+
// Determine if this is an update (by checking if agent already exists)
|
|
1008
|
+
const isUpdate = await fs.pathExists(targetMdPath);
|
|
1009
|
+
|
|
1010
|
+
// Copy sidecar to memory location with update-safe handling
|
|
1011
|
+
const copiedFiles = await this.copySidecarToMemory(sourceSidecarPath, agentName, bmadMemoryPath, isUpdate, bmadDir, installer);
|
|
1012
|
+
|
|
1013
|
+
if (process.env.BMAD_VERBOSE_INSTALL === 'true' && copiedFiles.length > 0) {
|
|
1014
|
+
await prompts.log.message(` Sidecar files processed: ${copiedFiles.length} files`);
|
|
1015
|
+
}
|
|
1016
|
+
} else if (process.env.BMAD_VERBOSE_INSTALL === 'true') {
|
|
1017
|
+
await prompts.log.warn(` Agent marked as having sidecar but ${sidecarDirName} directory not found`);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// Copy any non-sidecar files from agent directory (e.g., foo.md)
|
|
1022
|
+
const agentDir = path.dirname(agentFile);
|
|
1023
|
+
const agentEntries = await fs.readdir(agentDir, { withFileTypes: true });
|
|
1024
|
+
|
|
1025
|
+
for (const entry of agentEntries) {
|
|
1026
|
+
if (entry.isFile() && !entry.name.endsWith('.agent.yaml') && !entry.name.endsWith('.md')) {
|
|
1027
|
+
// Copy additional files (like foo.md) to the agent target directory
|
|
1028
|
+
const sourceFile = path.join(agentDir, entry.name);
|
|
1029
|
+
const targetFile = path.join(targetDir, entry.name);
|
|
1030
|
+
await this.copyFileWithPlaceholderReplacement(sourceFile, targetFile);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
// Only show compilation details in verbose mode
|
|
1035
|
+
if (process.env.BMAD_VERBOSE_INSTALL === 'true') {
|
|
1036
|
+
await prompts.log.message(
|
|
1037
|
+
` Compiled agent: ${agentName} -> ${path.relative(targetPath, targetMdPath)}${hasSidecar ? ' (with sidecar)' : ''}`,
|
|
1038
|
+
);
|
|
1039
|
+
}
|
|
1040
|
+
} catch (error) {
|
|
1041
|
+
await prompts.log.warn(` Failed to compile agent ${agentName}: ${error.message}`);
|
|
506
1042
|
}
|
|
507
1043
|
}
|
|
508
1044
|
}
|
|
509
1045
|
|
|
1046
|
+
/**
|
|
1047
|
+
* Find all .agent.yaml files recursively in a directory
|
|
1048
|
+
* @param {string} dir - Directory to search
|
|
1049
|
+
* @returns {Array} List of .agent.yaml file paths
|
|
1050
|
+
*/
|
|
1051
|
+
async findAgentFiles(dir) {
|
|
1052
|
+
const agentFiles = [];
|
|
1053
|
+
|
|
1054
|
+
async function searchDirectory(searchDir) {
|
|
1055
|
+
const entries = await fs.readdir(searchDir, { withFileTypes: true });
|
|
1056
|
+
|
|
1057
|
+
for (const entry of entries) {
|
|
1058
|
+
const fullPath = path.join(searchDir, entry.name);
|
|
1059
|
+
|
|
1060
|
+
if (entry.isFile() && entry.name.endsWith('.agent.yaml')) {
|
|
1061
|
+
agentFiles.push(fullPath);
|
|
1062
|
+
} else if (entry.isDirectory()) {
|
|
1063
|
+
await searchDirectory(fullPath);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
await searchDirectory(dir);
|
|
1069
|
+
return agentFiles;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
/**
|
|
1073
|
+
* Process agent files to inject activation block
|
|
1074
|
+
* @param {string} modulePath - Path to installed module
|
|
1075
|
+
* @param {string} moduleName - Module name
|
|
1076
|
+
*/
|
|
1077
|
+
async processAgentFiles(modulePath, moduleName) {
|
|
1078
|
+
// const agentsPath = path.join(modulePath, 'agents');
|
|
1079
|
+
// // Check if agents directory exists
|
|
1080
|
+
// if (!(await fs.pathExists(agentsPath))) {
|
|
1081
|
+
// return; // No agents to process
|
|
1082
|
+
// }
|
|
1083
|
+
// // Get all agent MD files recursively
|
|
1084
|
+
// const agentFiles = await this.findAgentMdFiles(agentsPath);
|
|
1085
|
+
// for (const agentFile of agentFiles) {
|
|
1086
|
+
// if (!agentFile.endsWith('.md')) continue;
|
|
1087
|
+
// let content = await fs.readFile(agentFile, 'utf8');
|
|
1088
|
+
// // Check if content has agent XML and no activation block
|
|
1089
|
+
// if (content.includes('<agent') && !content.includes('<activation')) {
|
|
1090
|
+
// // Inject the activation block using XML handler
|
|
1091
|
+
// content = this.xmlHandler.injectActivationSimple(content);
|
|
1092
|
+
// await fs.writeFile(agentFile, content, 'utf8');
|
|
1093
|
+
// }
|
|
1094
|
+
// }
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
/**
|
|
1098
|
+
* Find all .md agent files recursively in a directory
|
|
1099
|
+
* @param {string} dir - Directory to search
|
|
1100
|
+
* @returns {Array} List of .md agent file paths
|
|
1101
|
+
*/
|
|
1102
|
+
async findAgentMdFiles(dir) {
|
|
1103
|
+
const agentFiles = [];
|
|
1104
|
+
|
|
1105
|
+
async function searchDirectory(searchDir) {
|
|
1106
|
+
const entries = await fs.readdir(searchDir, { withFileTypes: true });
|
|
1107
|
+
|
|
1108
|
+
for (const entry of entries) {
|
|
1109
|
+
const fullPath = path.join(searchDir, entry.name);
|
|
1110
|
+
|
|
1111
|
+
if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
1112
|
+
agentFiles.push(fullPath);
|
|
1113
|
+
} else if (entry.isDirectory()) {
|
|
1114
|
+
await searchDirectory(fullPath);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
await searchDirectory(dir);
|
|
1120
|
+
return agentFiles;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
510
1123
|
/**
|
|
511
1124
|
* Vendor cross-module workflows referenced in agent files
|
|
512
1125
|
* Scans SOURCE agent.yaml files for workflow-install and copies workflows to destination
|
|
@@ -534,7 +1147,7 @@ class ModuleManager {
|
|
|
534
1147
|
|
|
535
1148
|
for (const agentFile of yamlFiles) {
|
|
536
1149
|
const agentPath = path.join(sourceAgentsPath, agentFile);
|
|
537
|
-
const agentYaml = yaml.
|
|
1150
|
+
const agentYaml = yaml.parse(await fs.readFile(agentPath, 'utf8'));
|
|
538
1151
|
|
|
539
1152
|
// Check if agent has menu items with workflow-install
|
|
540
1153
|
const menuItems = agentYaml?.agent?.menu || [];
|
|
@@ -545,56 +1158,53 @@ class ModuleManager {
|
|
|
545
1158
|
}
|
|
546
1159
|
|
|
547
1160
|
if (!workflowsVendored) {
|
|
548
|
-
|
|
1161
|
+
await prompts.log.info(`\n Vendoring cross-module workflows for ${moduleName}...`);
|
|
549
1162
|
workflowsVendored = true;
|
|
550
1163
|
}
|
|
551
1164
|
|
|
552
|
-
|
|
1165
|
+
await prompts.log.message(` Processing: ${agentFile}`);
|
|
553
1166
|
|
|
554
1167
|
for (const item of workflowInstallItems) {
|
|
555
1168
|
const sourceWorkflowPath = item.workflow; // Where to copy FROM
|
|
556
1169
|
const installWorkflowPath = item['workflow-install']; // Where to copy TO
|
|
557
1170
|
|
|
558
1171
|
// Parse SOURCE workflow path
|
|
559
|
-
// Handle both
|
|
560
|
-
// Example: {project-root}/
|
|
1172
|
+
// Handle both _bmad placeholder and hardcoded 'bmad'
|
|
1173
|
+
// Example: {project-root}/_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml
|
|
561
1174
|
// Or: {project-root}/bmad/bmm/workflows/4-implementation/create-story/workflow.yaml
|
|
562
|
-
const sourceMatch = sourceWorkflowPath.match(/\{project-root\}\/(
|
|
1175
|
+
const sourceMatch = sourceWorkflowPath.match(/\{project-root\}\/(?:_bmad)\/([^/]+)\/workflows\/(.+)/);
|
|
563
1176
|
if (!sourceMatch) {
|
|
564
|
-
|
|
1177
|
+
await prompts.log.warn(` Could not parse workflow path: ${sourceWorkflowPath}`);
|
|
565
1178
|
continue;
|
|
566
1179
|
}
|
|
567
1180
|
|
|
568
1181
|
const [, sourceModule, sourceWorkflowSubPath] = sourceMatch;
|
|
569
1182
|
|
|
570
1183
|
// Parse INSTALL workflow path
|
|
571
|
-
//
|
|
572
|
-
// Example: {project-root}/
|
|
573
|
-
const installMatch = installWorkflowPath.match(/\{project-root\}\/(
|
|
1184
|
+
// Handle_bmad
|
|
1185
|
+
// Example: {project-root}/_bmad/bmgd/workflows/4-production/create-story/workflow.yaml
|
|
1186
|
+
const installMatch = installWorkflowPath.match(/\{project-root\}\/(_bmad)\/([^/]+)\/workflows\/(.+)/);
|
|
574
1187
|
if (!installMatch) {
|
|
575
|
-
|
|
1188
|
+
await prompts.log.warn(` Could not parse workflow-install path: ${installWorkflowPath}`);
|
|
576
1189
|
continue;
|
|
577
1190
|
}
|
|
578
1191
|
|
|
579
1192
|
const installWorkflowSubPath = installMatch[2];
|
|
580
1193
|
|
|
581
|
-
|
|
582
|
-
const sourceModulePath = path.join(this.modulesSourcePath, sourceModule);
|
|
1194
|
+
const sourceModulePath = getModulePath(sourceModule);
|
|
583
1195
|
const actualSourceWorkflowPath = path.join(sourceModulePath, 'workflows', sourceWorkflowSubPath.replace(/\/workflow\.yaml$/, ''));
|
|
584
1196
|
|
|
585
1197
|
const actualDestWorkflowPath = path.join(targetPath, 'workflows', installWorkflowSubPath.replace(/\/workflow\.yaml$/, ''));
|
|
586
1198
|
|
|
587
1199
|
// Check if source workflow exists
|
|
588
1200
|
if (!(await fs.pathExists(actualSourceWorkflowPath))) {
|
|
589
|
-
|
|
1201
|
+
await prompts.log.warn(` Source workflow not found: ${actualSourceWorkflowPath}`);
|
|
590
1202
|
continue;
|
|
591
1203
|
}
|
|
592
1204
|
|
|
593
1205
|
// Copy the entire workflow folder
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
` Vendoring: ${sourceModule}/workflows/${sourceWorkflowSubPath.replace(/\/workflow\.yaml$/, '')} → ${moduleName}/workflows/${installWorkflowSubPath.replace(/\/workflow\.yaml$/, '')}`,
|
|
597
|
-
),
|
|
1206
|
+
await prompts.log.message(
|
|
1207
|
+
` Vendoring: ${sourceModule}/workflows/${sourceWorkflowSubPath.replace(/\/workflow\.yaml$/, '')} → ${moduleName}/workflows/${installWorkflowSubPath.replace(/\/workflow\.yaml$/, '')}`,
|
|
598
1208
|
);
|
|
599
1209
|
|
|
600
1210
|
await fs.ensureDir(path.dirname(actualDestWorkflowPath));
|
|
@@ -610,7 +1220,7 @@ class ModuleManager {
|
|
|
610
1220
|
}
|
|
611
1221
|
|
|
612
1222
|
if (workflowsVendored) {
|
|
613
|
-
|
|
1223
|
+
await prompts.log.success(` Workflow vendoring complete\n`);
|
|
614
1224
|
}
|
|
615
1225
|
}
|
|
616
1226
|
|
|
@@ -622,9 +1232,9 @@ class ModuleManager {
|
|
|
622
1232
|
async updateWorkflowConfigSource(workflowYamlPath, newModuleName) {
|
|
623
1233
|
let yamlContent = await fs.readFile(workflowYamlPath, 'utf8');
|
|
624
1234
|
|
|
625
|
-
// Replace config_source: "{project-root}/
|
|
626
|
-
// with config_source: "{project-root}/
|
|
627
|
-
// Note: At this point
|
|
1235
|
+
// Replace config_source: "{project-root}/_bmad/OLD_MODULE/config.yaml"
|
|
1236
|
+
// with config_source: "{project-root}/_bmad/NEW_MODULE/config.yaml"
|
|
1237
|
+
// Note: At this point _bmad has already been replaced with actual folder name
|
|
628
1238
|
const configSourcePattern = /config_source:\s*["']?\{project-root\}\/[^/]+\/[^/]+\/config\.yaml["']?/g;
|
|
629
1239
|
const newConfigSource = `config_source: "{project-root}/${this.bmadFolderName}/${newModuleName}/config.yaml"`;
|
|
630
1240
|
|
|
@@ -632,62 +1242,180 @@ class ModuleManager {
|
|
|
632
1242
|
|
|
633
1243
|
if (updatedYaml !== yamlContent) {
|
|
634
1244
|
await fs.writeFile(workflowYamlPath, updatedYaml, 'utf8');
|
|
635
|
-
|
|
1245
|
+
await prompts.log.message(` Updated config_source to: ${this.bmadFolderName}/${newModuleName}/config.yaml`);
|
|
636
1246
|
}
|
|
637
1247
|
}
|
|
638
1248
|
|
|
639
1249
|
/**
|
|
640
|
-
*
|
|
1250
|
+
* Create directories declared in module.yaml's `directories` key
|
|
1251
|
+
* This replaces the security-risky module installer pattern with declarative config
|
|
1252
|
+
* During updates, if a directory path changed, moves the old directory to the new path
|
|
641
1253
|
* @param {string} moduleName - Name of the module
|
|
642
1254
|
* @param {string} bmadDir - Target bmad directory
|
|
643
1255
|
* @param {Object} options - Installation options
|
|
1256
|
+
* @param {Object} options.moduleConfig - Module configuration from config collector
|
|
1257
|
+
* @param {Object} options.existingModuleConfig - Previous module config (for detecting path changes during updates)
|
|
1258
|
+
* @param {Object} options.coreConfig - Core configuration
|
|
1259
|
+
* @returns {Promise<{createdDirs: string[], movedDirs: string[], createdWdsFolders: string[]}>} Created directories info
|
|
644
1260
|
*/
|
|
645
|
-
async
|
|
1261
|
+
async createModuleDirectories(moduleName, bmadDir, options = {}) {
|
|
1262
|
+
const moduleConfig = options.moduleConfig || {};
|
|
1263
|
+
const existingModuleConfig = options.existingModuleConfig || {};
|
|
1264
|
+
const projectRoot = path.dirname(bmadDir);
|
|
1265
|
+
const emptyResult = { createdDirs: [], movedDirs: [], createdWdsFolders: [] };
|
|
1266
|
+
|
|
646
1267
|
// Special handling for core module - it's in src/core not src/modules
|
|
647
1268
|
let sourcePath;
|
|
648
1269
|
if (moduleName === 'core') {
|
|
649
1270
|
sourcePath = getSourcePath('core');
|
|
650
1271
|
} else {
|
|
651
|
-
sourcePath =
|
|
1272
|
+
sourcePath = await this.findModuleSource(moduleName, { silent: true });
|
|
1273
|
+
if (!sourcePath) {
|
|
1274
|
+
return emptyResult; // No source found, skip
|
|
1275
|
+
}
|
|
652
1276
|
}
|
|
653
1277
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
return; // No custom installer
|
|
1278
|
+
// Read module.yaml to find the `directories` key
|
|
1279
|
+
const moduleYamlPath = path.join(sourcePath, 'module.yaml');
|
|
1280
|
+
if (!(await fs.pathExists(moduleYamlPath))) {
|
|
1281
|
+
return emptyResult; // No module.yaml, skip
|
|
659
1282
|
}
|
|
660
1283
|
|
|
1284
|
+
let moduleYaml;
|
|
661
1285
|
try {
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
const projectRoot = path.dirname(bmadDir);
|
|
668
|
-
|
|
669
|
-
// Prepare logger (use console if not provided)
|
|
670
|
-
const logger = options.logger || {
|
|
671
|
-
log: console.log,
|
|
672
|
-
error: console.error,
|
|
673
|
-
warn: console.warn,
|
|
674
|
-
};
|
|
1286
|
+
const yamlContent = await fs.readFile(moduleYamlPath, 'utf8');
|
|
1287
|
+
moduleYaml = yaml.parse(yamlContent);
|
|
1288
|
+
} catch {
|
|
1289
|
+
return emptyResult; // Invalid YAML, skip
|
|
1290
|
+
}
|
|
675
1291
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
1292
|
+
if (!moduleYaml || !moduleYaml.directories) {
|
|
1293
|
+
return emptyResult; // No directories declared, skip
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
const directories = moduleYaml.directories;
|
|
1297
|
+
const wdsFolders = moduleYaml.wds_folders || [];
|
|
1298
|
+
const createdDirs = [];
|
|
1299
|
+
const movedDirs = [];
|
|
1300
|
+
const createdWdsFolders = [];
|
|
1301
|
+
|
|
1302
|
+
for (const dirRef of directories) {
|
|
1303
|
+
// Parse variable reference like "{design_artifacts}"
|
|
1304
|
+
const varMatch = dirRef.match(/^\{([^}]+)\}$/);
|
|
1305
|
+
if (!varMatch) {
|
|
1306
|
+
// Not a variable reference, skip
|
|
1307
|
+
continue;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
const configKey = varMatch[1];
|
|
1311
|
+
const dirValue = moduleConfig[configKey];
|
|
1312
|
+
if (!dirValue || typeof dirValue !== 'string') {
|
|
1313
|
+
continue; // No value or not a string, skip
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
// Strip {project-root}/ prefix if present
|
|
1317
|
+
let dirPath = dirValue.replace(/^\{project-root\}\/?/, '');
|
|
1318
|
+
|
|
1319
|
+
// Handle remaining {project-root} anywhere in the path
|
|
1320
|
+
dirPath = dirPath.replaceAll('{project-root}', '');
|
|
1321
|
+
|
|
1322
|
+
// Resolve to absolute path
|
|
1323
|
+
const fullPath = path.join(projectRoot, dirPath);
|
|
1324
|
+
|
|
1325
|
+
// Validate path is within project root (prevent directory traversal)
|
|
1326
|
+
const normalizedPath = path.normalize(fullPath);
|
|
1327
|
+
const normalizedRoot = path.normalize(projectRoot);
|
|
1328
|
+
if (!normalizedPath.startsWith(normalizedRoot + path.sep) && normalizedPath !== normalizedRoot) {
|
|
1329
|
+
const color = await prompts.getColor();
|
|
1330
|
+
await prompts.log.warn(color.yellow(`${configKey} path escapes project root, skipping: ${dirPath}`));
|
|
1331
|
+
continue;
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
// Check if directory path changed from previous config (update/modify scenario)
|
|
1335
|
+
const oldDirValue = existingModuleConfig[configKey];
|
|
1336
|
+
let oldFullPath = null;
|
|
1337
|
+
let oldDirPath = null;
|
|
1338
|
+
if (oldDirValue && typeof oldDirValue === 'string') {
|
|
1339
|
+
// F3: Normalize both values before comparing to avoid false negatives
|
|
1340
|
+
// from trailing slashes, separator differences, or prefix format variations
|
|
1341
|
+
let normalizedOld = oldDirValue.replace(/^\{project-root\}\/?/, '');
|
|
1342
|
+
normalizedOld = path.normalize(normalizedOld.replaceAll('{project-root}', ''));
|
|
1343
|
+
const normalizedNew = path.normalize(dirPath);
|
|
1344
|
+
|
|
1345
|
+
if (normalizedOld !== normalizedNew) {
|
|
1346
|
+
oldDirPath = normalizedOld;
|
|
1347
|
+
oldFullPath = path.join(projectRoot, oldDirPath);
|
|
1348
|
+
const normalizedOldAbsolute = path.normalize(oldFullPath);
|
|
1349
|
+
if (!normalizedOldAbsolute.startsWith(normalizedRoot + path.sep) && normalizedOldAbsolute !== normalizedRoot) {
|
|
1350
|
+
oldFullPath = null; // Old path escapes project root, ignore it
|
|
1351
|
+
}
|
|
683
1352
|
|
|
684
|
-
|
|
685
|
-
|
|
1353
|
+
// F13: Prevent parent/child move (e.g. docs/planning → docs/planning/v2)
|
|
1354
|
+
if (oldFullPath) {
|
|
1355
|
+
const normalizedNewAbsolute = path.normalize(fullPath);
|
|
1356
|
+
if (
|
|
1357
|
+
normalizedOldAbsolute.startsWith(normalizedNewAbsolute + path.sep) ||
|
|
1358
|
+
normalizedNewAbsolute.startsWith(normalizedOldAbsolute + path.sep)
|
|
1359
|
+
) {
|
|
1360
|
+
const color = await prompts.getColor();
|
|
1361
|
+
await prompts.log.warn(
|
|
1362
|
+
color.yellow(
|
|
1363
|
+
`${configKey}: cannot move between parent/child paths (${oldDirPath} / ${dirPath}), creating new directory instead`,
|
|
1364
|
+
),
|
|
1365
|
+
);
|
|
1366
|
+
oldFullPath = null;
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
const dirName = configKey.replaceAll('_', ' ');
|
|
1373
|
+
|
|
1374
|
+
if (oldFullPath && (await fs.pathExists(oldFullPath)) && !(await fs.pathExists(fullPath))) {
|
|
1375
|
+
// Path changed and old dir exists → move old to new location
|
|
1376
|
+
// F1: Use fs.move() instead of fs.rename() for cross-device/volume support
|
|
1377
|
+
// F2: Wrap in try/catch — fallback to creating new dir on failure
|
|
1378
|
+
try {
|
|
1379
|
+
await fs.ensureDir(path.dirname(fullPath));
|
|
1380
|
+
await fs.move(oldFullPath, fullPath);
|
|
1381
|
+
movedDirs.push(`${dirName}: ${oldDirPath} → ${dirPath}`);
|
|
1382
|
+
} catch (moveError) {
|
|
1383
|
+
const color = await prompts.getColor();
|
|
1384
|
+
await prompts.log.warn(
|
|
1385
|
+
color.yellow(
|
|
1386
|
+
`Failed to move ${oldDirPath} → ${dirPath}: ${moveError.message}\n Creating new directory instead. Please move contents from the old directory manually.`,
|
|
1387
|
+
),
|
|
1388
|
+
);
|
|
1389
|
+
await fs.ensureDir(fullPath);
|
|
1390
|
+
createdDirs.push(`${dirName}: ${dirPath}`);
|
|
1391
|
+
}
|
|
1392
|
+
} else if (oldFullPath && (await fs.pathExists(oldFullPath)) && (await fs.pathExists(fullPath))) {
|
|
1393
|
+
// F5: Both old and new directories exist — warn user about potential orphaned documents
|
|
1394
|
+
const color = await prompts.getColor();
|
|
1395
|
+
await prompts.log.warn(
|
|
1396
|
+
color.yellow(
|
|
1397
|
+
`${dirName}: path changed but both directories exist:\n Old: ${oldDirPath}\n New: ${dirPath}\n Old directory may contain orphaned documents — please review and merge manually.`,
|
|
1398
|
+
),
|
|
1399
|
+
);
|
|
1400
|
+
} else if (!(await fs.pathExists(fullPath))) {
|
|
1401
|
+
// New directory doesn't exist yet → create it
|
|
1402
|
+
createdDirs.push(`${dirName}: ${dirPath}`);
|
|
1403
|
+
await fs.ensureDir(fullPath);
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
// Create WDS subfolders if this is the design_artifacts directory
|
|
1407
|
+
if (configKey === 'design_artifacts' && wdsFolders.length > 0) {
|
|
1408
|
+
for (const subfolder of wdsFolders) {
|
|
1409
|
+
const subPath = path.join(fullPath, subfolder);
|
|
1410
|
+
if (!(await fs.pathExists(subPath))) {
|
|
1411
|
+
await fs.ensureDir(subPath);
|
|
1412
|
+
createdWdsFolders.push(subfolder);
|
|
1413
|
+
}
|
|
686
1414
|
}
|
|
687
1415
|
}
|
|
688
|
-
} catch (error) {
|
|
689
|
-
console.error(chalk.red(`Error running module installer for ${moduleName}: ${error.message}`));
|
|
690
1416
|
}
|
|
1417
|
+
|
|
1418
|
+
return { createdDirs, movedDirs, createdWdsFolders };
|
|
691
1419
|
}
|
|
692
1420
|
|
|
693
1421
|
/**
|
|
@@ -708,7 +1436,7 @@ class ModuleManager {
|
|
|
708
1436
|
|
|
709
1437
|
await fs.writeFile(configPath, configContent, 'utf8');
|
|
710
1438
|
} catch (error) {
|
|
711
|
-
|
|
1439
|
+
await prompts.log.warn(`Failed to process module config: ${error.message}`);
|
|
712
1440
|
}
|
|
713
1441
|
}
|
|
714
1442
|
}
|
|
@@ -756,10 +1484,6 @@ class ModuleManager {
|
|
|
756
1484
|
const fullPath = path.join(dir, entry.name);
|
|
757
1485
|
|
|
758
1486
|
if (entry.isDirectory()) {
|
|
759
|
-
// Skip _module-installer directories
|
|
760
|
-
if (entry.name === '_module-installer') {
|
|
761
|
-
continue;
|
|
762
|
-
}
|
|
763
1487
|
const subFiles = await this.getFileList(fullPath, baseDir);
|
|
764
1488
|
files.push(...subFiles);
|
|
765
1489
|
} else {
|