bmad-fh 6.0.0-alpha.23
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/.coderabbit.yaml +40 -0
- package/.githooks/post-checkout +129 -0
- package/.githooks/pre-commit +63 -0
- package/.githooks/pre-push +135 -0
- package/.github/CODE_OF_CONDUCT.md +128 -0
- package/.github/FUNDING.yaml +15 -0
- package/.github/ISSUE_TEMPLATE/config.yaml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
- package/.github/ISSUE_TEMPLATE/issue.md +32 -0
- package/.github/scripts/discord-helpers.sh +34 -0
- package/.github/workflows/bundle-latest.yaml +330 -0
- package/.github/workflows/discord.yaml +90 -0
- package/.github/workflows/docs.yaml +63 -0
- package/.github/workflows/manual-release.yaml +190 -0
- package/.github/workflows/publish-multi-artifact.yaml +50 -0
- package/.github/workflows/quality.yaml +115 -0
- package/.husky/pre-commit +20 -0
- package/.markdownlint-cli2.yaml +41 -0
- package/.nvmrc +1 -0
- package/.prettierignore +9 -0
- package/.vscode/settings.json +97 -0
- package/CHANGELOG.md +1394 -0
- package/CNAME +1 -0
- package/CONTRIBUTING.md +306 -0
- package/CONTRIBUTORS.md +32 -0
- package/LICENSE +30 -0
- package/README.md +126 -0
- 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/_README_WORKFLOW_DIAGRAMS.md +40 -0
- package/docs/_STYLE_GUIDE.md +367 -0
- package/docs/_archive/customize-workflows.md +30 -0
- package/docs/_archive/getting-started-bmadv4.md +247 -0
- package/docs/_archive/vendor-workflows.md +52 -0
- package/docs/downloads.md +72 -0
- package/docs/explanation/agents/barry-quick-flow.md +328 -0
- package/docs/explanation/agents/index.md +19 -0
- package/docs/explanation/architecture/four-phases.md +107 -0
- package/docs/explanation/architecture/preventing-agent-conflicts.md +111 -0
- package/docs/explanation/architecture/why-solutioning-matters.md +75 -0
- package/docs/explanation/bmm/index.md +131 -0
- package/docs/explanation/core/index.md +18 -0
- package/docs/explanation/core-concepts/agent-roles.md +179 -0
- package/docs/explanation/core-concepts/index.md +35 -0
- package/docs/explanation/core-concepts/what-are-agents.md +97 -0
- package/docs/explanation/core-concepts/what-are-modules.md +85 -0
- package/docs/explanation/core-concepts/what-are-workflows.md +204 -0
- package/docs/explanation/faq/brownfield-faq.md +73 -0
- package/docs/explanation/faq/getting-started-faq.md +67 -0
- package/docs/explanation/faq/implementation-faq.md +52 -0
- package/docs/explanation/faq/index.md +16 -0
- package/docs/explanation/faq/levels-and-tracks-faq.md +52 -0
- package/docs/explanation/faq/planning-faq.md +41 -0
- package/docs/explanation/faq/tools-faq.md +277 -0
- package/docs/explanation/faq/workflows-faq.md +61 -0
- package/docs/explanation/features/advanced-elicitation.md +95 -0
- package/docs/explanation/features/brainstorming-techniques.md +92 -0
- package/docs/explanation/features/party-mode.md +95 -0
- package/docs/explanation/features/quick-flow.md +149 -0
- package/docs/explanation/features/tea-overview.md +410 -0
- package/docs/explanation/features/web-bundles.md +34 -0
- package/docs/explanation/philosophy/facilitation-over-generation.md +333 -0
- package/docs/explanation/philosophy/testing-as-engineering.md +112 -0
- package/docs/explanation/tea/engagement-models.md +710 -0
- package/docs/explanation/tea/fixture-architecture.md +457 -0
- package/docs/explanation/tea/knowledge-base-system.md +554 -0
- package/docs/explanation/tea/network-first-patterns.md +853 -0
- package/docs/explanation/tea/risk-based-testing.md +586 -0
- package/docs/explanation/tea/test-quality-standards.md +907 -0
- package/docs/how-to/brownfield/add-feature-to-existing.md +74 -0
- package/docs/how-to/brownfield/document-existing-project.md +66 -0
- package/docs/how-to/brownfield/index.md +84 -0
- package/docs/how-to/brownfield/quick-fix-in-brownfield.md +77 -0
- package/docs/how-to/brownfield/use-tea-for-enterprise.md +526 -0
- package/docs/how-to/brownfield/use-tea-with-existing-tests.md +577 -0
- package/docs/how-to/customization/customize-agents.md +212 -0
- package/docs/how-to/customization/enable-tea-mcp-enhancements.md +424 -0
- package/docs/how-to/customization/index.md +23 -0
- package/docs/how-to/customization/integrate-playwright-utils.md +813 -0
- package/docs/how-to/customization/shard-large-documents.md +101 -0
- package/docs/how-to/get-answers-about-bmad.md +102 -0
- package/docs/how-to/installation/index.md +12 -0
- package/docs/how-to/installation/install-bmad.md +111 -0
- package/docs/how-to/installation/install-custom-modules.md +118 -0
- package/docs/how-to/installation/upgrade-to-v6.md +131 -0
- package/docs/how-to/workflows/bmgd-quick-flow.md +156 -0
- package/docs/how-to/workflows/conduct-research.md +97 -0
- package/docs/how-to/workflows/create-architecture.md +119 -0
- package/docs/how-to/workflows/create-epics-and-stories.md +109 -0
- package/docs/how-to/workflows/create-prd.md +91 -0
- package/docs/how-to/workflows/create-product-brief.md +94 -0
- package/docs/how-to/workflows/create-story.md +102 -0
- package/docs/how-to/workflows/create-ux-design.md +100 -0
- package/docs/how-to/workflows/implement-story.md +97 -0
- package/docs/how-to/workflows/quick-spec.md +122 -0
- package/docs/how-to/workflows/run-atdd.md +436 -0
- package/docs/how-to/workflows/run-automate.md +653 -0
- package/docs/how-to/workflows/run-brainstorming-session.md +73 -0
- package/docs/how-to/workflows/run-code-review.md +89 -0
- package/docs/how-to/workflows/run-implementation-readiness.md +125 -0
- package/docs/how-to/workflows/run-nfr-assess.md +679 -0
- package/docs/how-to/workflows/run-sprint-planning.md +94 -0
- package/docs/how-to/workflows/run-test-design.md +98 -0
- package/docs/how-to/workflows/run-test-review.md +605 -0
- package/docs/how-to/workflows/run-trace.md +883 -0
- package/docs/how-to/workflows/setup-ci.md +712 -0
- package/docs/how-to/workflows/setup-party-mode.md +89 -0
- package/docs/how-to/workflows/setup-test-framework.md +98 -0
- package/docs/index.md +63 -0
- package/docs/migration-guide.md +365 -0
- package/docs/multi-scope-guide.md +379 -0
- package/docs/plans/multi-scope-parallel-artifacts-plan.md +695 -0
- package/docs/reference/agents/index.md +109 -0
- package/docs/reference/configuration/core-tasks.md +67 -0
- package/docs/reference/configuration/global-config.md +28 -0
- package/docs/reference/glossary/index.md +159 -0
- package/docs/reference/tea/commands.md +254 -0
- package/docs/reference/tea/configuration.md +678 -0
- package/docs/reference/tea/knowledge-base.md +340 -0
- package/docs/reference/workflows/core-workflows.md +32 -0
- package/docs/reference/workflows/document-project.md +73 -0
- package/docs/reference/workflows/index.md +12 -0
- package/docs/tutorials/getting-started/getting-started-bmadv6.md +246 -0
- package/docs/tutorials/getting-started/images/workflow-method-greenfield.excalidraw +5034 -0
- package/docs/tutorials/getting-started/images/workflow-method-greenfield.svg +4 -0
- package/docs/tutorials/getting-started/images/workflow-overview.jpg +0 -0
- package/docs/tutorials/getting-started/tea-lite-quickstart.md +444 -0
- package/docs/tutorials/getting-started/workflow-overview.jpg +0 -0
- package/eslint.config.mjs +152 -0
- package/package.json +117 -0
- package/prettier.config.mjs +32 -0
- package/src/bmm/_module-installer/installer.js +48 -0
- package/src/bmm/_module-installer/platform-specifics/claude-code.js +35 -0
- package/src/bmm/_module-installer/platform-specifics/windsurf.js +32 -0
- package/src/bmm/agents/analyst.agent.yaml +41 -0
- package/src/bmm/agents/architect.agent.yaml +33 -0
- package/src/bmm/agents/dev.agent.yaml +38 -0
- package/src/bmm/agents/pm.agent.yaml +51 -0
- package/src/bmm/agents/quick-flow-solo-dev.agent.yaml +32 -0
- package/src/bmm/agents/sm.agent.yaml +47 -0
- package/src/bmm/agents/tea.agent.yaml +68 -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 +49 -0
- package/src/bmm/agents/ux-designer.agent.yaml +30 -0
- package/src/bmm/data/README.md +29 -0
- package/src/bmm/data/project-context-template.md +40 -0
- package/src/bmm/module.yaml +64 -0
- package/src/bmm/sub-modules/claude-code/config.yaml +4 -0
- package/src/bmm/sub-modules/claude-code/injections.yaml +242 -0
- package/src/bmm/sub-modules/claude-code/readme.md +87 -0
- package/src/bmm/teams/default-party.csv +21 -0
- package/src/bmm/teams/team-fullstack.yaml +12 -0
- package/src/bmm/testarch/knowledge/api-request.md +442 -0
- package/src/bmm/testarch/knowledge/api-testing-patterns.md +843 -0
- package/src/bmm/testarch/knowledge/auth-session.md +552 -0
- package/src/bmm/testarch/knowledge/burn-in.md +273 -0
- package/src/bmm/testarch/knowledge/ci-burn-in.md +675 -0
- package/src/bmm/testarch/knowledge/component-tdd.md +486 -0
- package/src/bmm/testarch/knowledge/contract-testing.md +957 -0
- package/src/bmm/testarch/knowledge/data-factories.md +500 -0
- package/src/bmm/testarch/knowledge/email-auth.md +721 -0
- package/src/bmm/testarch/knowledge/error-handling.md +725 -0
- package/src/bmm/testarch/knowledge/feature-flags.md +750 -0
- package/src/bmm/testarch/knowledge/file-utils.md +463 -0
- package/src/bmm/testarch/knowledge/fixture-architecture.md +401 -0
- package/src/bmm/testarch/knowledge/fixtures-composition.md +382 -0
- package/src/bmm/testarch/knowledge/intercept-network-call.md +430 -0
- package/src/bmm/testarch/knowledge/log.md +429 -0
- package/src/bmm/testarch/knowledge/network-error-monitor.md +405 -0
- package/src/bmm/testarch/knowledge/network-first.md +486 -0
- package/src/bmm/testarch/knowledge/network-recorder.md +527 -0
- package/src/bmm/testarch/knowledge/nfr-criteria.md +670 -0
- package/src/bmm/testarch/knowledge/overview.md +286 -0
- package/src/bmm/testarch/knowledge/playwright-config.md +730 -0
- package/src/bmm/testarch/knowledge/probability-impact.md +601 -0
- package/src/bmm/testarch/knowledge/recurse.md +421 -0
- package/src/bmm/testarch/knowledge/risk-governance.md +615 -0
- package/src/bmm/testarch/knowledge/selective-testing.md +732 -0
- package/src/bmm/testarch/knowledge/selector-resilience.md +527 -0
- package/src/bmm/testarch/knowledge/test-healing-patterns.md +644 -0
- package/src/bmm/testarch/knowledge/test-levels-framework.md +473 -0
- package/src/bmm/testarch/knowledge/test-priorities-matrix.md +373 -0
- package/src/bmm/testarch/knowledge/test-quality.md +664 -0
- package/src/bmm/testarch/knowledge/timing-debugging.md +372 -0
- package/src/bmm/testarch/knowledge/visual-debugging.md +524 -0
- package/src/bmm/testarch/tea-index.csv +34 -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 +194 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/workflow.md +58 -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 +443 -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-02-customer-insights.md +200 -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 +475 -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 +239 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md +486 -0
- package/src/bmm/workflows/1-analysis/research/workflow.md +173 -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 +228 -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 +43 -0
- package/src/bmm/workflows/2-plan-workflows/prd/data/domain-complexity.csv +13 -0
- package/src/bmm/workflows/2-plan-workflows/prd/data/prd-purpose.md +197 -0
- package/src/bmm/workflows/2-plan-workflows/prd/data/project-types.csv +11 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-01-init.md +191 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-01b-continue.md +153 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-02-discovery.md +224 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-03-success.md +226 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-04-journeys.md +213 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-05-domain.md +207 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-06-innovation.md +226 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-07-project-type.md +237 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-08-scoping.md +228 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-09-functional.md +231 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-10-nonfunctional.md +242 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-11-polish.md +217 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-c/step-12-complete.md +180 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-e/step-e-01-discovery.md +247 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-e/step-e-01b-legacy-conversion.md +208 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-e/step-e-02-review.md +249 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-e/step-e-03-edit.md +253 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-e/step-e-04-complete.md +168 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-01-discovery.md +218 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-02-format-detection.md +191 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-02b-parity-check.md +209 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-03-density-validation.md +174 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-04-brief-coverage-validation.md +214 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-05-measurability-validation.md +228 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-06-traceability-validation.md +217 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-07-implementation-leakage-validation.md +205 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-08-domain-compliance-validation.md +243 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-09-project-type-validation.md +263 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-10-smart-validation.md +209 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-11-holistic-quality-validation.md +264 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-12-completeness-validation.md +242 -0
- package/src/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-13-report-complete.md +232 -0
- package/src/bmm/workflows/2-plan-workflows/prd/templates/prd-template.md +10 -0
- package/src/bmm/workflows/2-plan-workflows/prd/validation-report-prd-workflow.md +433 -0
- package/src/bmm/workflows/2-plan-workflows/prd/workflow.md +150 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-01-document-discovery.md +190 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-02-prd-analysis.md +178 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-03-epic-coverage-validation.md +179 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-04-ux-alignment.md +139 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-05-epic-quality-review.md +252 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +133 -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 +55 -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 +11 -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 +164 -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 +331 -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 +352 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/workflow.md +50 -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 +145 -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 +59 -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 +51 -0
- package/src/bmm/workflows/4-implementation/correct-course/checklist.md +288 -0
- package/src/bmm/workflows/4-implementation/correct-course/instructions.md +206 -0
- package/src/bmm/workflows/4-implementation/correct-course/workflow.yaml +60 -0
- package/src/bmm/workflows/4-implementation/create-story/checklist.md +358 -0
- package/src/bmm/workflows/4-implementation/create-story/instructions.xml +345 -0
- package/src/bmm/workflows/4-implementation/create-story/template.md +49 -0
- package/src/bmm/workflows/4-implementation/create-story/workflow.yaml +61 -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 +27 -0
- package/src/bmm/workflows/4-implementation/retrospective/instructions.md +1443 -0
- package/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +58 -0
- package/src/bmm/workflows/4-implementation/sprint-planning/checklist.md +33 -0
- package/src/bmm/workflows/4-implementation/sprint-planning/instructions.md +225 -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 +54 -0
- package/src/bmm/workflows/4-implementation/sprint-status/instructions.md +229 -0
- package/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml +36 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md +156 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md +120 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md +113 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md +113 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +106 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-06-resolve-findings.md +140 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +52 -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 +144 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md +128 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +191 -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/documentation-requirements.csv +12 -0
- package/src/bmm/workflows/document-project/instructions.md +221 -0
- package/src/bmm/workflows/document-project/templates/deep-dive-template.md +345 -0
- package/src/bmm/workflows/document-project/templates/index-template.md +169 -0
- package/src/bmm/workflows/document-project/templates/project-overview-template.md +103 -0
- package/src/bmm/workflows/document-project/templates/project-scan-report-schema.json +160 -0
- package/src/bmm/workflows/document-project/templates/source-tree-template.md +135 -0
- package/src/bmm/workflows/document-project/workflow.yaml +30 -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/excalidraw-diagrams/_shared/excalidraw-library.json +90 -0
- package/src/bmm/workflows/excalidraw-diagrams/_shared/excalidraw-templates.yaml +127 -0
- package/src/bmm/workflows/excalidraw-diagrams/create-dataflow/checklist.md +39 -0
- package/src/bmm/workflows/excalidraw-diagrams/create-dataflow/instructions.md +130 -0
- package/src/bmm/workflows/excalidraw-diagrams/create-dataflow/workflow.yaml +27 -0
- package/src/bmm/workflows/excalidraw-diagrams/create-diagram/checklist.md +43 -0
- package/src/bmm/workflows/excalidraw-diagrams/create-diagram/instructions.md +141 -0
- package/src/bmm/workflows/excalidraw-diagrams/create-diagram/workflow.yaml +27 -0
- package/src/bmm/workflows/excalidraw-diagrams/create-flowchart/checklist.md +49 -0
- package/src/bmm/workflows/excalidraw-diagrams/create-flowchart/instructions.md +241 -0
- package/src/bmm/workflows/excalidraw-diagrams/create-flowchart/workflow.yaml +27 -0
- package/src/bmm/workflows/excalidraw-diagrams/create-wireframe/checklist.md +38 -0
- package/src/bmm/workflows/excalidraw-diagrams/create-wireframe/instructions.md +133 -0
- package/src/bmm/workflows/excalidraw-diagrams/create-wireframe/workflow.yaml +27 -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/testarch/atdd/atdd-checklist-template.md +364 -0
- package/src/bmm/workflows/testarch/atdd/checklist.md +374 -0
- package/src/bmm/workflows/testarch/atdd/instructions.md +806 -0
- package/src/bmm/workflows/testarch/atdd/workflow.yaml +47 -0
- package/src/bmm/workflows/testarch/automate/checklist.md +582 -0
- package/src/bmm/workflows/testarch/automate/instructions.md +1324 -0
- package/src/bmm/workflows/testarch/automate/workflow.yaml +54 -0
- package/src/bmm/workflows/testarch/ci/checklist.md +248 -0
- package/src/bmm/workflows/testarch/ci/github-actions-template.yaml +198 -0
- package/src/bmm/workflows/testarch/ci/gitlab-ci-template.yaml +149 -0
- package/src/bmm/workflows/testarch/ci/instructions.md +536 -0
- package/src/bmm/workflows/testarch/ci/workflow.yaml +47 -0
- package/src/bmm/workflows/testarch/framework/checklist.md +321 -0
- package/src/bmm/workflows/testarch/framework/instructions.md +481 -0
- package/src/bmm/workflows/testarch/framework/workflow.yaml +49 -0
- package/src/bmm/workflows/testarch/nfr-assess/checklist.md +407 -0
- package/src/bmm/workflows/testarch/nfr-assess/instructions.md +722 -0
- package/src/bmm/workflows/testarch/nfr-assess/nfr-report-template.md +445 -0
- package/src/bmm/workflows/testarch/nfr-assess/workflow.yaml +49 -0
- package/src/bmm/workflows/testarch/test-design/checklist.md +235 -0
- package/src/bmm/workflows/testarch/test-design/instructions.md +788 -0
- package/src/bmm/workflows/testarch/test-design/test-design-template.md +294 -0
- package/src/bmm/workflows/testarch/test-design/workflow.yaml +56 -0
- package/src/bmm/workflows/testarch/test-review/checklist.md +472 -0
- package/src/bmm/workflows/testarch/test-review/instructions.md +628 -0
- package/src/bmm/workflows/testarch/test-review/test-review-template.md +390 -0
- package/src/bmm/workflows/testarch/test-review/workflow.yaml +48 -0
- package/src/bmm/workflows/testarch/trace/checklist.md +655 -0
- package/src/bmm/workflows/testarch/trace/instructions.md +1047 -0
- package/src/bmm/workflows/testarch/trace/trace-template.md +675 -0
- package/src/bmm/workflows/testarch/trace/workflow.yaml +57 -0
- package/src/bmm/workflows/workflow-status/init/instructions.md +346 -0
- package/src/bmm/workflows/workflow-status/init/workflow.yaml +30 -0
- package/src/bmm/workflows/workflow-status/instructions.md +397 -0
- package/src/bmm/workflows/workflow-status/paths/enterprise-brownfield.yaml +103 -0
- package/src/bmm/workflows/workflow-status/paths/enterprise-greenfield.yaml +100 -0
- package/src/bmm/workflows/workflow-status/paths/method-brownfield.yaml +103 -0
- package/src/bmm/workflows/workflow-status/paths/method-greenfield.yaml +100 -0
- package/src/bmm/workflows/workflow-status/project-levels.yaml +59 -0
- package/src/bmm/workflows/workflow-status/workflow-status-template.yaml +24 -0
- package/src/bmm/workflows/workflow-status/workflow.yaml +32 -0
- package/src/core/_module-installer/installer.js +60 -0
- package/src/core/agents/bmad-master.agent.yaml +30 -0
- package/src/core/lib/scope/artifact-resolver.js +298 -0
- package/src/core/lib/scope/event-logger.js +411 -0
- package/src/core/lib/scope/index.js +30 -0
- package/src/core/lib/scope/scope-context.js +307 -0
- package/src/core/lib/scope/scope-initializer.js +458 -0
- package/src/core/lib/scope/scope-manager.js +512 -0
- package/src/core/lib/scope/scope-migrator.js +442 -0
- package/src/core/lib/scope/scope-sync.js +489 -0
- package/src/core/lib/scope/scope-validator.js +299 -0
- package/src/core/lib/scope/state-lock.js +342 -0
- package/src/core/module.yaml +53 -0
- package/src/core/resources/excalidraw/README.md +160 -0
- package/src/core/resources/excalidraw/excalidraw-helpers.md +127 -0
- package/src/core/resources/excalidraw/library-loader.md +50 -0
- package/src/core/resources/excalidraw/validate-json-instructions.md +79 -0
- package/src/core/tasks/editorial-review-prose.xml +91 -0
- package/src/core/tasks/editorial-review-structure.xml +198 -0
- package/src/core/tasks/index-docs.xml +65 -0
- package/src/core/tasks/review-adversarial-general.xml +46 -0
- package/src/core/tasks/shard-doc.xml +109 -0
- package/src/core/tasks/workflow.xml +277 -0
- package/src/core/workflows/advanced-elicitation/methods.csv +51 -0
- package/src/core/workflows/advanced-elicitation/workflow.xml +117 -0
- package/src/core/workflows/brainstorming/brain-methods.csv +62 -0
- 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 +15 -0
- 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 +157 -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 +28 -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-data.txt +5 -0
- package/src/utility/agent-components/handler-exec.txt +19 -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 +295 -0
- package/test/fixtures/agent-schema/invalid/critical-actions/actions-as-string.agent.yaml +27 -0
- package/test/fixtures/agent-schema/invalid/critical-actions/empty-string-in-actions.agent.yaml +30 -0
- package/test/fixtures/agent-schema/invalid/menu/empty-menu.agent.yaml +22 -0
- package/test/fixtures/agent-schema/invalid/menu/missing-menu.agent.yaml +20 -0
- package/test/fixtures/agent-schema/invalid/menu-commands/empty-command-target.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-commands/no-command-target.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/camel-case.agent.yaml +25 -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 +31 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/empty-trigger.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/leading-asterisk.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/snake-case.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/trigger-with-spaces.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/metadata/empty-module-string.agent.yaml +26 -0
- package/test/fixtures/agent-schema/invalid/metadata/empty-name.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/metadata/extra-metadata-fields.agent.yaml +27 -0
- package/test/fixtures/agent-schema/invalid/metadata/missing-id.agent.yaml +23 -0
- package/test/fixtures/agent-schema/invalid/persona/empty-principles-array.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/persona/empty-string-in-principles.agent.yaml +27 -0
- package/test/fixtures/agent-schema/invalid/persona/extra-persona-fields.agent.yaml +27 -0
- package/test/fixtures/agent-schema/invalid/persona/missing-role.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/prompts/empty-content.agent.yaml +29 -0
- package/test/fixtures/agent-schema/invalid/prompts/extra-prompt-fields.agent.yaml +31 -0
- package/test/fixtures/agent-schema/invalid/prompts/missing-content.agent.yaml +28 -0
- package/test/fixtures/agent-schema/invalid/prompts/missing-id.agent.yaml +28 -0
- package/test/fixtures/agent-schema/invalid/top-level/empty-file.agent.yaml +5 -0
- package/test/fixtures/agent-schema/invalid/top-level/extra-top-level-keys.agent.yaml +28 -0
- package/test/fixtures/agent-schema/invalid/top-level/missing-agent-key.agent.yaml +11 -0
- package/test/fixtures/agent-schema/invalid/yaml-errors/invalid-indentation.agent.yaml +19 -0
- package/test/fixtures/agent-schema/invalid/yaml-errors/malformed-yaml.agent.yaml +18 -0
- package/test/fixtures/agent-schema/valid/critical-actions/empty-critical-actions.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/critical-actions/no-critical-actions.agent.yaml +22 -0
- package/test/fixtures/agent-schema/valid/critical-actions/valid-critical-actions.agent.yaml +27 -0
- package/test/fixtures/agent-schema/valid/menu/multiple-menu-items.agent.yaml +31 -0
- package/test/fixtures/agent-schema/valid/menu/single-menu-item.agent.yaml +22 -0
- package/test/fixtures/agent-schema/valid/menu-commands/all-command-types.agent.yaml +38 -0
- package/test/fixtures/agent-schema/valid/menu-commands/multiple-commands.agent.yaml +24 -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 +34 -0
- 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 +24 -0
- package/test/fixtures/agent-schema/valid/metadata/malformed-path-treated-as-core.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/metadata/module-agent-correct.agent.yaml +24 -0
- 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 +24 -0
- package/test/fixtures/agent-schema/valid/prompts/empty-prompts.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/prompts/no-prompts.agent.yaml +22 -0
- package/test/fixtures/agent-schema/valid/prompts/valid-prompts-minimal.agent.yaml +28 -0
- package/test/fixtures/agent-schema/valid/prompts/valid-prompts-with-description.agent.yaml +30 -0
- package/test/fixtures/agent-schema/valid/top-level/minimal-core-agent.agent.yaml +24 -0
- package/test/test-agent-schema.js +387 -0
- package/test/test-cli-integration.sh +159 -0
- package/test/test-installation-components.js +214 -0
- package/test/test-scope-e2e.js +450 -0
- package/test/test-scope-system.js +787 -0
- package/test/unit-test-schema.js +133 -0
- package/tools/bmad-npx-wrapper.js +38 -0
- package/tools/build-docs.js +577 -0
- package/tools/cli/README.md +7 -0
- package/tools/cli/bmad-cli.js +58 -0
- package/tools/cli/commands/install.js +87 -0
- package/tools/cli/commands/scope.js +474 -0
- package/tools/cli/external-official-modules.yaml +41 -0
- package/tools/cli/installers/install-messages.yaml +58 -0
- package/tools/cli/installers/lib/core/config-collector.js +1079 -0
- package/tools/cli/installers/lib/core/custom-module-cache.js +259 -0
- package/tools/cli/installers/lib/core/dependency-resolver.js +739 -0
- package/tools/cli/installers/lib/core/detector.js +223 -0
- package/tools/cli/installers/lib/core/ide-config-manager.js +156 -0
- package/tools/cli/installers/lib/core/installer.js +2585 -0
- package/tools/cli/installers/lib/core/manifest-generator.js +963 -0
- package/tools/cli/installers/lib/core/manifest.js +590 -0
- package/tools/cli/installers/lib/custom/handler.js +363 -0
- package/tools/cli/installers/lib/ide/_base-ide.js +654 -0
- package/tools/cli/installers/lib/ide/antigravity.js +486 -0
- package/tools/cli/installers/lib/ide/auggie.js +244 -0
- package/tools/cli/installers/lib/ide/claude-code.js +487 -0
- package/tools/cli/installers/lib/ide/cline.js +269 -0
- package/tools/cli/installers/lib/ide/codex.js +375 -0
- package/tools/cli/installers/lib/ide/crush.js +300 -0
- package/tools/cli/installers/lib/ide/cursor.js +169 -0
- package/tools/cli/installers/lib/ide/gemini.js +301 -0
- package/tools/cli/installers/lib/ide/github-copilot.js +383 -0
- package/tools/cli/installers/lib/ide/iflow.js +191 -0
- package/tools/cli/installers/lib/ide/kilo.js +250 -0
- package/tools/cli/installers/lib/ide/kiro-cli.js +326 -0
- package/tools/cli/installers/lib/ide/manager.js +244 -0
- package/tools/cli/installers/lib/ide/opencode.js +257 -0
- package/tools/cli/installers/lib/ide/qwen.js +372 -0
- package/tools/cli/installers/lib/ide/roo.js +270 -0
- package/tools/cli/installers/lib/ide/rovo-dev.js +290 -0
- package/tools/cli/installers/lib/ide/shared/agent-command-generator.js +96 -0
- package/tools/cli/installers/lib/ide/shared/bmad-artifacts.js +158 -0
- package/tools/cli/installers/lib/ide/shared/module-injections.js +136 -0
- package/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +119 -0
- package/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +242 -0
- package/tools/cli/installers/lib/ide/templates/agent-command-template.md +29 -0
- package/tools/cli/installers/lib/ide/templates/gemini-agent-command.toml +14 -0
- package/tools/cli/installers/lib/ide/templates/gemini-task-command.toml +12 -0
- package/tools/cli/installers/lib/ide/templates/workflow-command-template.md +30 -0
- package/tools/cli/installers/lib/ide/templates/workflow-commander.md +45 -0
- package/tools/cli/installers/lib/ide/trae.js +313 -0
- package/tools/cli/installers/lib/ide/windsurf.js +258 -0
- package/tools/cli/installers/lib/message-loader.js +85 -0
- package/tools/cli/installers/lib/modules/external-manager.js +133 -0
- package/tools/cli/installers/lib/modules/manager.js +1362 -0
- package/tools/cli/lib/activation-builder.js +163 -0
- package/tools/cli/lib/agent/compiler.js +522 -0
- package/tools/cli/lib/agent/installer.js +716 -0
- package/tools/cli/lib/agent/template-engine.js +152 -0
- package/tools/cli/lib/agent-analyzer.js +109 -0
- package/tools/cli/lib/agent-party-generator.js +194 -0
- package/tools/cli/lib/cli-utils.js +227 -0
- package/tools/cli/lib/config.js +213 -0
- package/tools/cli/lib/file-ops.js +204 -0
- package/tools/cli/lib/platform-codes.js +116 -0
- package/tools/cli/lib/project-root.js +77 -0
- package/tools/cli/lib/prompts.js +433 -0
- package/tools/cli/lib/ui.js +1591 -0
- package/tools/cli/lib/xml-handler.js +177 -0
- package/tools/cli/lib/xml-to-markdown.js +82 -0
- package/tools/cli/lib/yaml-format.js +245 -0
- package/tools/cli/lib/yaml-xml-builder.js +587 -0
- package/tools/cli/scripts/migrate-workflows.js +281 -0
- package/tools/docs/BUNDLE_DISTRIBUTION_SETUP.md +95 -0
- package/tools/docs/index.md +2 -0
- package/tools/fix-doc-links.js +288 -0
- package/tools/flattener/aggregate.js +76 -0
- package/tools/flattener/binary.js +80 -0
- package/tools/flattener/discovery.js +71 -0
- package/tools/flattener/files.js +35 -0
- package/tools/flattener/ignoreRules.js +172 -0
- package/tools/flattener/main.js +483 -0
- package/tools/flattener/projectRoot.js +201 -0
- package/tools/flattener/prompts.js +44 -0
- package/tools/flattener/stats.helpers.js +368 -0
- package/tools/flattener/stats.js +75 -0
- package/tools/flattener/test-matrix.js +409 -0
- package/tools/flattener/xml.js +82 -0
- package/tools/format-workflow-md.js +263 -0
- package/tools/lib/xml-utils.js +13 -0
- package/tools/maintainer/review-pr-README.md +55 -0
- package/tools/maintainer/review-pr.md +242 -0
- package/tools/migrate-custom-module-paths.js +124 -0
- package/tools/platform-codes.yaml +157 -0
- package/tools/schema/agent.js +493 -0
- package/tools/validate-agent-schema.js +110 -0
- package/tools/validate-doc-links.js +363 -0
- package/tools/validate-svg-changes.sh +356 -0
- package/website/README.md +76 -0
- package/website/astro.config.mjs +228 -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/img/logo.svg +4 -0
- package/website/public/robots.txt +37 -0
- package/website/src/components/Banner.astro +59 -0
- package/website/src/components/Header.astro +121 -0
- package/website/src/components/MobileMenuFooter.astro +53 -0
- package/website/src/content/config.ts +6 -0
- package/website/src/lib/site-url.js +25 -0
- package/website/src/rehype-markdown-links.js +102 -0
- package/website/src/styles/custom.css +485 -0
|
@@ -0,0 +1,716 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BMAD Agent Installer
|
|
3
|
+
* Discovers, prompts, compiles, and installs agents
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('node:fs');
|
|
7
|
+
const path = require('node:path');
|
|
8
|
+
const yaml = require('yaml');
|
|
9
|
+
const readline = require('node:readline');
|
|
10
|
+
const { compileAgent, compileAgentFile } = require('./compiler');
|
|
11
|
+
const { extractInstallConfig, getDefaultValues } = require('./template-engine');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Find BMAD config file in project
|
|
15
|
+
* @param {string} startPath - Starting directory to search from
|
|
16
|
+
* @returns {Object|null} Config data or null
|
|
17
|
+
*/
|
|
18
|
+
function findBmadConfig(startPath = process.cwd()) {
|
|
19
|
+
// Look for common BMAD folder names
|
|
20
|
+
const possibleNames = ['_bmad'];
|
|
21
|
+
|
|
22
|
+
for (const name of possibleNames) {
|
|
23
|
+
const configPath = path.join(startPath, name, 'bmb', 'config.yaml');
|
|
24
|
+
if (fs.existsSync(configPath)) {
|
|
25
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
26
|
+
const config = yaml.parse(content);
|
|
27
|
+
return {
|
|
28
|
+
...config,
|
|
29
|
+
bmadFolder: path.join(startPath, name),
|
|
30
|
+
projectRoot: startPath,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Resolve path variables like {project-root} and {bmad-folder}
|
|
40
|
+
* @param {string} pathStr - Path with variables
|
|
41
|
+
* @param {Object} context - Contains projectRoot, bmadFolder
|
|
42
|
+
* @returns {string} Resolved path
|
|
43
|
+
*/
|
|
44
|
+
function resolvePath(pathStr, context) {
|
|
45
|
+
return pathStr.replaceAll('{project-root}', context.projectRoot).replaceAll('{bmad-folder}', context_bmadFolder);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Discover available agents in the custom agent location recursively
|
|
50
|
+
* @param {string} searchPath - Path to search for agents
|
|
51
|
+
* @returns {Array} List of agent info objects
|
|
52
|
+
*/
|
|
53
|
+
function discoverAgents(searchPath) {
|
|
54
|
+
if (!fs.existsSync(searchPath)) {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const agents = [];
|
|
59
|
+
|
|
60
|
+
// Helper function to recursively search
|
|
61
|
+
function searchDirectory(dir, relativePath = '') {
|
|
62
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
63
|
+
|
|
64
|
+
for (const entry of entries) {
|
|
65
|
+
const fullPath = path.join(dir, entry.name);
|
|
66
|
+
const agentRelativePath = relativePath ? path.join(relativePath, entry.name) : entry.name;
|
|
67
|
+
|
|
68
|
+
if (entry.isFile() && entry.name.endsWith('.agent.yaml')) {
|
|
69
|
+
// Simple agent (single file)
|
|
70
|
+
// The agent name is based on the filename
|
|
71
|
+
const agentName = entry.name.replace('.agent.yaml', '');
|
|
72
|
+
agents.push({
|
|
73
|
+
type: 'simple',
|
|
74
|
+
name: agentName,
|
|
75
|
+
path: fullPath,
|
|
76
|
+
yamlFile: fullPath,
|
|
77
|
+
relativePath: agentRelativePath.replace('.agent.yaml', ''),
|
|
78
|
+
});
|
|
79
|
+
} else if (entry.isDirectory()) {
|
|
80
|
+
// Check if this directory contains an .agent.yaml file
|
|
81
|
+
try {
|
|
82
|
+
const dirContents = fs.readdirSync(fullPath);
|
|
83
|
+
const yamlFiles = dirContents.filter((f) => f.endsWith('.agent.yaml'));
|
|
84
|
+
|
|
85
|
+
if (yamlFiles.length > 0) {
|
|
86
|
+
// Found .agent.yaml files in this directory
|
|
87
|
+
for (const yamlFile of yamlFiles) {
|
|
88
|
+
const agentYamlPath = path.join(fullPath, yamlFile);
|
|
89
|
+
const agentName = path.basename(yamlFile, '.agent.yaml');
|
|
90
|
+
|
|
91
|
+
agents.push({
|
|
92
|
+
type: 'expert',
|
|
93
|
+
name: agentName,
|
|
94
|
+
path: fullPath,
|
|
95
|
+
yamlFile: agentYamlPath,
|
|
96
|
+
relativePath: agentRelativePath,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
// No .agent.yaml in this directory, recurse deeper
|
|
101
|
+
searchDirectory(fullPath, agentRelativePath);
|
|
102
|
+
}
|
|
103
|
+
} catch {
|
|
104
|
+
// Skip directories we can't read
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
searchDirectory(searchPath);
|
|
111
|
+
return agents;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Load agent YAML and extract install_config
|
|
116
|
+
* @param {string} yamlPath - Path to agent YAML file
|
|
117
|
+
* @returns {Object} Agent YAML and install config
|
|
118
|
+
*/
|
|
119
|
+
function loadAgentConfig(yamlPath) {
|
|
120
|
+
const content = fs.readFileSync(yamlPath, 'utf8');
|
|
121
|
+
const agentYaml = yaml.parse(content);
|
|
122
|
+
const installConfig = extractInstallConfig(agentYaml);
|
|
123
|
+
const defaults = installConfig ? getDefaultValues(installConfig) : {};
|
|
124
|
+
|
|
125
|
+
// Check for saved_answers (from previously installed custom agents)
|
|
126
|
+
// These take precedence over defaults
|
|
127
|
+
const savedAnswers = agentYaml?.saved_answers || {};
|
|
128
|
+
|
|
129
|
+
const metadata = agentYaml?.agent?.metadata || {};
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
yamlContent: content,
|
|
133
|
+
agentYaml,
|
|
134
|
+
installConfig,
|
|
135
|
+
defaults: { ...defaults, ...savedAnswers }, // saved_answers override defaults
|
|
136
|
+
metadata,
|
|
137
|
+
hasSidecar: metadata.hasSidecar === true,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Interactive prompt for install_config questions
|
|
143
|
+
* @param {Object} installConfig - Install configuration with questions
|
|
144
|
+
* @param {Object} defaults - Default values
|
|
145
|
+
* @returns {Promise<Object>} User answers
|
|
146
|
+
*/
|
|
147
|
+
async function promptInstallQuestions(installConfig, defaults, presetAnswers = {}) {
|
|
148
|
+
if (!installConfig || !installConfig.questions || installConfig.questions.length === 0) {
|
|
149
|
+
return { ...defaults, ...presetAnswers };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const rl = readline.createInterface({
|
|
153
|
+
input: process.stdin,
|
|
154
|
+
output: process.stdout,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const question = (prompt) =>
|
|
158
|
+
new Promise((resolve) => {
|
|
159
|
+
rl.question(prompt, resolve);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const answers = { ...defaults, ...presetAnswers };
|
|
163
|
+
|
|
164
|
+
console.log('\n📝 Agent Configuration\n');
|
|
165
|
+
if (installConfig.description) {
|
|
166
|
+
console.log(` ${installConfig.description}\n`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
for (const q of installConfig.questions) {
|
|
170
|
+
// Skip questions for variables that are already set (e.g., custom_name set upfront)
|
|
171
|
+
if (answers[q.var] !== undefined && answers[q.var] !== defaults[q.var]) {
|
|
172
|
+
console.log(chalk.dim(` ${q.var}: ${answers[q.var]} (already set)`));
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let response;
|
|
177
|
+
|
|
178
|
+
switch (q.type) {
|
|
179
|
+
case 'text': {
|
|
180
|
+
const defaultHint = q.default ? ` (default: ${q.default})` : '';
|
|
181
|
+
response = await question(` ${q.prompt}${defaultHint}: `);
|
|
182
|
+
answers[q.var] = response || q.default || '';
|
|
183
|
+
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case 'boolean': {
|
|
187
|
+
const defaultHint = q.default ? ' [Y/n]' : ' [y/N]';
|
|
188
|
+
response = await question(` ${q.prompt}${defaultHint}: `);
|
|
189
|
+
if (response === '') {
|
|
190
|
+
answers[q.var] = q.default;
|
|
191
|
+
} else {
|
|
192
|
+
answers[q.var] = response.toLowerCase().startsWith('y');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
case 'choice': {
|
|
198
|
+
console.log(` ${q.prompt}`);
|
|
199
|
+
for (const [idx, opt] of q.options.entries()) {
|
|
200
|
+
const marker = opt.value === q.default ? '* ' : ' ';
|
|
201
|
+
console.log(` ${marker}${idx + 1}. ${opt.label}`);
|
|
202
|
+
}
|
|
203
|
+
const defaultIdx = q.options.findIndex((o) => o.value === q.default) + 1;
|
|
204
|
+
let validChoice = false;
|
|
205
|
+
let choiceIdx;
|
|
206
|
+
while (!validChoice) {
|
|
207
|
+
response = await question(` Choice (default: ${defaultIdx}): `);
|
|
208
|
+
if (response) {
|
|
209
|
+
choiceIdx = parseInt(response, 10) - 1;
|
|
210
|
+
if (isNaN(choiceIdx) || choiceIdx < 0 || choiceIdx >= q.options.length) {
|
|
211
|
+
console.log(` Invalid choice. Please enter 1-${q.options.length}`);
|
|
212
|
+
} else {
|
|
213
|
+
validChoice = true;
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
choiceIdx = defaultIdx - 1;
|
|
217
|
+
validChoice = true;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
answers[q.var] = q.options[choiceIdx].value;
|
|
221
|
+
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
// No default
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
rl.close();
|
|
229
|
+
return answers;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Install a compiled agent to target location
|
|
234
|
+
* @param {Object} agentInfo - Agent discovery info
|
|
235
|
+
* @param {Object} answers - User answers for install_config
|
|
236
|
+
* @param {string} targetPath - Target installation directory
|
|
237
|
+
* @param {Object} options - Additional options including config
|
|
238
|
+
* @returns {Object} Installation result
|
|
239
|
+
*/
|
|
240
|
+
function installAgent(agentInfo, answers, targetPath, options = {}) {
|
|
241
|
+
// Compile the agent
|
|
242
|
+
const { xml, metadata, processedYaml } = compileAgent(fs.readFileSync(agentInfo.yamlFile, 'utf8'), answers);
|
|
243
|
+
|
|
244
|
+
// Determine target agent folder name
|
|
245
|
+
// Use the folder name from agentInfo, NOT the persona name from metadata
|
|
246
|
+
const agentFolderName = agentInfo.name;
|
|
247
|
+
|
|
248
|
+
const agentTargetDir = path.join(targetPath, agentFolderName);
|
|
249
|
+
|
|
250
|
+
// Create target directory
|
|
251
|
+
if (!fs.existsSync(agentTargetDir)) {
|
|
252
|
+
fs.mkdirSync(agentTargetDir, { recursive: true });
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Write compiled XML (.md)
|
|
256
|
+
const compiledFileName = `${agentFolderName}.md`;
|
|
257
|
+
const compiledPath = path.join(agentTargetDir, compiledFileName);
|
|
258
|
+
fs.writeFileSync(compiledPath, xml, 'utf8');
|
|
259
|
+
|
|
260
|
+
const result = {
|
|
261
|
+
success: true,
|
|
262
|
+
agentName: metadata.name || agentInfo.name,
|
|
263
|
+
targetDir: agentTargetDir,
|
|
264
|
+
compiledFile: compiledPath,
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
return result;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Update agent metadata ID to reflect installed location
|
|
272
|
+
* @param {string} compiledContent - Compiled XML content
|
|
273
|
+
* @param {string} targetPath - Target installation path relative to project
|
|
274
|
+
* @returns {string} Updated content
|
|
275
|
+
*/
|
|
276
|
+
function updateAgentId(compiledContent, targetPath) {
|
|
277
|
+
// Update the id attribute in the opening agent tag
|
|
278
|
+
return compiledContent.replace(/(<agent\s+id=")[^"]*(")/, `$1${targetPath}$2`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Detect if a path is within a BMAD project
|
|
283
|
+
* @param {string} targetPath - Path to check
|
|
284
|
+
* @returns {Object|null} Project info with bmadFolder and cfgFolder
|
|
285
|
+
*/
|
|
286
|
+
function detectBmadProject(targetPath) {
|
|
287
|
+
let checkPath = path.resolve(targetPath);
|
|
288
|
+
const root = path.parse(checkPath).root;
|
|
289
|
+
|
|
290
|
+
// Walk up directory tree looking for BMAD installation
|
|
291
|
+
while (checkPath !== root) {
|
|
292
|
+
const possibleNames = ['_bmad'];
|
|
293
|
+
for (const name of possibleNames) {
|
|
294
|
+
const bmadFolder = path.join(checkPath, name);
|
|
295
|
+
const cfgFolder = path.join(bmadFolder, '_config');
|
|
296
|
+
const manifestFile = path.join(cfgFolder, 'agent-manifest.csv');
|
|
297
|
+
|
|
298
|
+
if (fs.existsSync(manifestFile)) {
|
|
299
|
+
return {
|
|
300
|
+
projectRoot: checkPath,
|
|
301
|
+
bmadFolder,
|
|
302
|
+
cfgFolder,
|
|
303
|
+
manifestFile,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
checkPath = path.dirname(checkPath);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Escape CSV field value
|
|
315
|
+
* @param {string} value - Value to escape
|
|
316
|
+
* @returns {string} Escaped value
|
|
317
|
+
*/
|
|
318
|
+
function escapeCsvField(value) {
|
|
319
|
+
if (typeof value !== 'string') value = String(value);
|
|
320
|
+
// If contains comma, quote, or newline, wrap in quotes and escape internal quotes
|
|
321
|
+
if (value.includes(',') || value.includes('"') || value.includes('\n')) {
|
|
322
|
+
return '"' + value.replaceAll('"', '""') + '"';
|
|
323
|
+
}
|
|
324
|
+
return value;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Parse CSV line respecting quoted fields
|
|
329
|
+
* @param {string} line - CSV line
|
|
330
|
+
* @returns {Array} Parsed fields
|
|
331
|
+
*/
|
|
332
|
+
function parseCsvLine(line) {
|
|
333
|
+
const fields = [];
|
|
334
|
+
let current = '';
|
|
335
|
+
let inQuotes = false;
|
|
336
|
+
|
|
337
|
+
for (let i = 0; i < line.length; i++) {
|
|
338
|
+
const char = line[i];
|
|
339
|
+
const nextChar = line[i + 1];
|
|
340
|
+
|
|
341
|
+
if (char === '"' && !inQuotes) {
|
|
342
|
+
inQuotes = true;
|
|
343
|
+
} else if (char === '"' && inQuotes) {
|
|
344
|
+
if (nextChar === '"') {
|
|
345
|
+
current += '"';
|
|
346
|
+
i++; // Skip escaped quote
|
|
347
|
+
} else {
|
|
348
|
+
inQuotes = false;
|
|
349
|
+
}
|
|
350
|
+
} else if (char === ',' && !inQuotes) {
|
|
351
|
+
fields.push(current);
|
|
352
|
+
current = '';
|
|
353
|
+
} else {
|
|
354
|
+
current += char;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
fields.push(current);
|
|
358
|
+
return fields;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Check if agent name exists in manifest
|
|
363
|
+
* @param {string} manifestFile - Path to agent-manifest.csv
|
|
364
|
+
* @param {string} agentName - Agent name to check
|
|
365
|
+
* @returns {Object|null} Existing entry or null
|
|
366
|
+
*/
|
|
367
|
+
function checkManifestForAgent(manifestFile, agentName) {
|
|
368
|
+
const content = fs.readFileSync(manifestFile, 'utf8');
|
|
369
|
+
const lines = content.trim().split('\n');
|
|
370
|
+
|
|
371
|
+
if (lines.length < 2) return null;
|
|
372
|
+
|
|
373
|
+
const header = parseCsvLine(lines[0]);
|
|
374
|
+
const nameIndex = header.indexOf('name');
|
|
375
|
+
|
|
376
|
+
if (nameIndex === -1) return null;
|
|
377
|
+
|
|
378
|
+
for (let i = 1; i < lines.length; i++) {
|
|
379
|
+
const fields = parseCsvLine(lines[i]);
|
|
380
|
+
if (fields[nameIndex] === agentName) {
|
|
381
|
+
const entry = {};
|
|
382
|
+
for (const [idx, col] of header.entries()) {
|
|
383
|
+
entry[col] = fields[idx] || '';
|
|
384
|
+
}
|
|
385
|
+
entry._lineNumber = i;
|
|
386
|
+
return entry;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Check if agent path exists in manifest
|
|
395
|
+
* @param {string} manifestFile - Path to agent-manifest.csv
|
|
396
|
+
* @param {string} agentPath - Agent path to check
|
|
397
|
+
* @returns {Object|null} Existing entry or null
|
|
398
|
+
*/
|
|
399
|
+
function checkManifestForPath(manifestFile, agentPath) {
|
|
400
|
+
const content = fs.readFileSync(manifestFile, 'utf8');
|
|
401
|
+
const lines = content.trim().split('\n');
|
|
402
|
+
|
|
403
|
+
if (lines.length < 2) return null;
|
|
404
|
+
|
|
405
|
+
const header = parseCsvLine(lines[0]);
|
|
406
|
+
const pathIndex = header.indexOf('path');
|
|
407
|
+
|
|
408
|
+
if (pathIndex === -1) return null;
|
|
409
|
+
|
|
410
|
+
for (let i = 1; i < lines.length; i++) {
|
|
411
|
+
const fields = parseCsvLine(lines[i]);
|
|
412
|
+
if (fields[pathIndex] === agentPath) {
|
|
413
|
+
const entry = {};
|
|
414
|
+
for (const [idx, col] of header.entries()) {
|
|
415
|
+
entry[col] = fields[idx] || '';
|
|
416
|
+
}
|
|
417
|
+
entry._lineNumber = i;
|
|
418
|
+
return entry;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Update existing entry in manifest
|
|
427
|
+
* @param {string} manifestFile - Path to agent-manifest.csv
|
|
428
|
+
* @param {Object} agentData - New agent data
|
|
429
|
+
* @param {number} lineNumber - Line number to replace (1-indexed, excluding header)
|
|
430
|
+
* @returns {boolean} Success
|
|
431
|
+
*/
|
|
432
|
+
function updateManifestEntry(manifestFile, agentData, lineNumber) {
|
|
433
|
+
const content = fs.readFileSync(manifestFile, 'utf8');
|
|
434
|
+
const lines = content.trim().split('\n');
|
|
435
|
+
|
|
436
|
+
const header = lines[0];
|
|
437
|
+
const columns = header.split(',');
|
|
438
|
+
|
|
439
|
+
// Build the new row
|
|
440
|
+
const row = columns.map((col) => {
|
|
441
|
+
const value = agentData[col] || '';
|
|
442
|
+
return escapeCsvField(value);
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
// Replace the line
|
|
446
|
+
lines[lineNumber] = row.join(',');
|
|
447
|
+
|
|
448
|
+
fs.writeFileSync(manifestFile, lines.join('\n') + '\n', 'utf8');
|
|
449
|
+
return true;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Add agent to manifest CSV
|
|
454
|
+
* @param {string} manifestFile - Path to agent-manifest.csv
|
|
455
|
+
* @param {Object} agentData - Agent metadata and path info
|
|
456
|
+
* @returns {boolean} Success
|
|
457
|
+
*/
|
|
458
|
+
function addToManifest(manifestFile, agentData) {
|
|
459
|
+
const content = fs.readFileSync(manifestFile, 'utf8');
|
|
460
|
+
const lines = content.trim().split('\n');
|
|
461
|
+
|
|
462
|
+
// Parse header to understand column order
|
|
463
|
+
const header = lines[0];
|
|
464
|
+
const columns = header.split(',');
|
|
465
|
+
|
|
466
|
+
// Build the new row based on header columns
|
|
467
|
+
const row = columns.map((col) => {
|
|
468
|
+
const value = agentData[col] || '';
|
|
469
|
+
return escapeCsvField(value);
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// Append new row
|
|
473
|
+
const newLine = row.join(',');
|
|
474
|
+
const updatedContent = content.trim() + '\n' + newLine + '\n';
|
|
475
|
+
|
|
476
|
+
fs.writeFileSync(manifestFile, updatedContent, 'utf8');
|
|
477
|
+
return true;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Save agent source YAML to _config/custom/agents/ for reinstallation
|
|
482
|
+
* Stores user answers in a top-level saved_answers section (cleaner than overwriting defaults)
|
|
483
|
+
* @param {Object} agentInfo - Agent info (path, type, etc.)
|
|
484
|
+
* @param {string} cfgFolder - Path to _config folder
|
|
485
|
+
* @param {string} agentName - Final agent name (e.g., "fred-commit-poet")
|
|
486
|
+
* @param {Object} answers - User answers to save for reinstallation
|
|
487
|
+
* @returns {Object} Info about saved source
|
|
488
|
+
*/
|
|
489
|
+
function saveAgentSource(agentInfo, cfgFolder, agentName, answers = {}) {
|
|
490
|
+
// Save to _config/custom/agents/ instead of _config/agents/
|
|
491
|
+
const customAgentsCfgDir = path.join(cfgFolder, 'custom', 'agents');
|
|
492
|
+
|
|
493
|
+
if (!fs.existsSync(customAgentsCfgDir)) {
|
|
494
|
+
fs.mkdirSync(customAgentsCfgDir, { recursive: true });
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const yamlLib = require('yaml');
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Add saved_answers section to store user's actual answers
|
|
501
|
+
*/
|
|
502
|
+
function addSavedAnswers(agentYaml, answers) {
|
|
503
|
+
// Store answers in a clear, separate section
|
|
504
|
+
agentYaml.saved_answers = answers;
|
|
505
|
+
return agentYaml;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (agentInfo.type === 'simple') {
|
|
509
|
+
// Simple agent: copy YAML with saved_answers section
|
|
510
|
+
const targetYaml = path.join(customAgentsCfgDir, `${agentName}.agent.yaml`);
|
|
511
|
+
const originalContent = fs.readFileSync(agentInfo.yamlFile, 'utf8');
|
|
512
|
+
const agentYaml = yamlLib.parse(originalContent);
|
|
513
|
+
|
|
514
|
+
// Add saved_answers section with user's choices
|
|
515
|
+
addSavedAnswers(agentYaml, answers);
|
|
516
|
+
|
|
517
|
+
fs.writeFileSync(targetYaml, yamlLib.stringify(agentYaml), 'utf8');
|
|
518
|
+
return { type: 'simple', path: targetYaml };
|
|
519
|
+
} else {
|
|
520
|
+
// Expert agent with sidecar: copy entire folder with saved_answers
|
|
521
|
+
const targetFolder = path.join(customAgentsCfgDir, agentName);
|
|
522
|
+
if (!fs.existsSync(targetFolder)) {
|
|
523
|
+
fs.mkdirSync(targetFolder, { recursive: true });
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Copy YAML and entire sidecar structure
|
|
527
|
+
const sourceDir = agentInfo.path;
|
|
528
|
+
const copied = [];
|
|
529
|
+
|
|
530
|
+
function copyDir(src, dest) {
|
|
531
|
+
if (!fs.existsSync(dest)) {
|
|
532
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
536
|
+
for (const entry of entries) {
|
|
537
|
+
const srcPath = path.join(src, entry.name);
|
|
538
|
+
const destPath = path.join(dest, entry.name);
|
|
539
|
+
|
|
540
|
+
if (entry.isDirectory()) {
|
|
541
|
+
copyDir(srcPath, destPath);
|
|
542
|
+
} else if (entry.name.endsWith('.agent.yaml')) {
|
|
543
|
+
// For the agent YAML, add saved_answers section
|
|
544
|
+
const originalContent = fs.readFileSync(srcPath, 'utf8');
|
|
545
|
+
const agentYaml = yamlLib.parse(originalContent);
|
|
546
|
+
addSavedAnswers(agentYaml, answers);
|
|
547
|
+
// Rename YAML to match final agent name
|
|
548
|
+
const newYamlPath = path.join(dest, `${agentName}.agent.yaml`);
|
|
549
|
+
fs.writeFileSync(newYamlPath, yamlLib.stringify(agentYaml), 'utf8');
|
|
550
|
+
copied.push(newYamlPath);
|
|
551
|
+
} else {
|
|
552
|
+
fs.copyFileSync(srcPath, destPath);
|
|
553
|
+
copied.push(destPath);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
copyDir(sourceDir, targetFolder);
|
|
559
|
+
return { type: 'expert', path: targetFolder, files: copied };
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Create IDE slash command wrapper for agent
|
|
565
|
+
* Leverages IdeManager to dispatch to IDE-specific handlers
|
|
566
|
+
* @param {string} projectRoot - Project root path
|
|
567
|
+
* @param {string} agentName - Agent name (e.g., "commit-poet")
|
|
568
|
+
* @param {string} agentPath - Path to compiled agent (relative to project root)
|
|
569
|
+
* @param {Object} metadata - Agent metadata
|
|
570
|
+
* @returns {Promise<Object>} Info about created slash commands
|
|
571
|
+
*/
|
|
572
|
+
async function createIdeSlashCommands(projectRoot, agentName, agentPath, metadata) {
|
|
573
|
+
// Read manifest.yaml to get installed IDEs
|
|
574
|
+
const manifestPath = path.join(projectRoot, '_bmad', '_config', 'manifest.yaml');
|
|
575
|
+
let installedIdes = ['claude-code']; // Default to Claude Code if no manifest
|
|
576
|
+
|
|
577
|
+
if (fs.existsSync(manifestPath)) {
|
|
578
|
+
const yamlLib = require('yaml');
|
|
579
|
+
const manifestContent = fs.readFileSync(manifestPath, 'utf8');
|
|
580
|
+
const manifest = yamlLib.parse(manifestContent);
|
|
581
|
+
if (manifest.ides && Array.isArray(manifest.ides)) {
|
|
582
|
+
installedIdes = manifest.ides;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// Use IdeManager to install custom agent launchers for all configured IDEs
|
|
587
|
+
const { IdeManager } = require('../../installers/lib/ide/manager');
|
|
588
|
+
const ideManager = new IdeManager();
|
|
589
|
+
|
|
590
|
+
const results = await ideManager.installCustomAgentLaunchers(installedIdes, projectRoot, agentName, agentPath, metadata);
|
|
591
|
+
|
|
592
|
+
return results;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* Update manifest.yaml to track custom agent
|
|
597
|
+
* @param {string} manifestPath - Path to manifest.yaml
|
|
598
|
+
* @param {string} agentName - Agent name
|
|
599
|
+
* @param {string} agentType - Agent type (source name)
|
|
600
|
+
* @returns {boolean} Success
|
|
601
|
+
*/
|
|
602
|
+
function updateManifestYaml(manifestPath, agentName, agentType) {
|
|
603
|
+
if (!fs.existsSync(manifestPath)) {
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const yamlLib = require('yaml');
|
|
608
|
+
const content = fs.readFileSync(manifestPath, 'utf8');
|
|
609
|
+
const manifest = yamlLib.parse(content);
|
|
610
|
+
|
|
611
|
+
// Initialize custom_agents array if not exists
|
|
612
|
+
if (!manifest.custom_agents) {
|
|
613
|
+
manifest.custom_agents = [];
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Check if this agent is already registered
|
|
617
|
+
const existingIndex = manifest.custom_agents.findIndex((a) => a.name === agentName || (typeof a === 'string' && a === agentName));
|
|
618
|
+
|
|
619
|
+
const agentEntry = {
|
|
620
|
+
name: agentName,
|
|
621
|
+
type: agentType,
|
|
622
|
+
installed: new Date().toISOString(),
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
if (existingIndex === -1) {
|
|
626
|
+
// Add new entry
|
|
627
|
+
manifest.custom_agents.push(agentEntry);
|
|
628
|
+
} else {
|
|
629
|
+
// Update existing entry
|
|
630
|
+
manifest.custom_agents[existingIndex] = agentEntry;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// Update lastUpdated timestamp
|
|
634
|
+
if (manifest.installation) {
|
|
635
|
+
manifest.installation.lastUpdated = new Date().toISOString();
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// Write back
|
|
639
|
+
const newContent = yamlLib.stringify(manifest);
|
|
640
|
+
fs.writeFileSync(manifestPath, newContent, 'utf8');
|
|
641
|
+
|
|
642
|
+
return true;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Extract manifest data from compiled agent XML
|
|
647
|
+
* @param {string} xmlContent - Compiled agent XML
|
|
648
|
+
* @param {Object} metadata - Agent metadata from YAML
|
|
649
|
+
* @param {string} agentPath - Relative path to agent file
|
|
650
|
+
* @param {string} moduleName - Module name (default: 'custom')
|
|
651
|
+
* @returns {Object} Manifest row data
|
|
652
|
+
*/
|
|
653
|
+
function extractManifestData(xmlContent, metadata, agentPath, moduleName = 'custom') {
|
|
654
|
+
// Extract data from XML using regex (simple parsing)
|
|
655
|
+
const extractTag = (tag) => {
|
|
656
|
+
const match = xmlContent.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
|
|
657
|
+
if (!match) return '';
|
|
658
|
+
// Collapse multiple lines into single line, normalize whitespace
|
|
659
|
+
return match[1].trim().replaceAll(/\n+/g, ' ').replaceAll(/\s+/g, ' ').trim();
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
// Extract attributes from agent tag
|
|
663
|
+
const extractAgentAttribute = (attr) => {
|
|
664
|
+
const match = xmlContent.match(new RegExp(`<agent[^>]*\\s${attr}=["']([^"']+)["']`));
|
|
665
|
+
return match ? match[1] : '';
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
const extractPrinciples = () => {
|
|
669
|
+
const match = xmlContent.match(/<principles>([\s\S]*?)<\/principles>/);
|
|
670
|
+
if (!match) return '';
|
|
671
|
+
// Extract individual principle lines
|
|
672
|
+
const principles = match[1]
|
|
673
|
+
.split('\n')
|
|
674
|
+
.map((l) => l.trim())
|
|
675
|
+
.filter((l) => l.length > 0)
|
|
676
|
+
.join(' ');
|
|
677
|
+
return principles;
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
// Prioritize XML extraction over metadata for agent persona info
|
|
681
|
+
const xmlTitle = extractAgentAttribute('title') || extractTag('name');
|
|
682
|
+
const xmlIcon = extractAgentAttribute('icon');
|
|
683
|
+
|
|
684
|
+
return {
|
|
685
|
+
name: metadata.id ? path.basename(metadata.id, '.md') : metadata.name.toLowerCase().replaceAll(/\s+/g, '-'),
|
|
686
|
+
displayName: xmlTitle || metadata.name || '',
|
|
687
|
+
title: xmlTitle || metadata.title || '',
|
|
688
|
+
icon: xmlIcon || metadata.icon || '',
|
|
689
|
+
role: extractTag('role'),
|
|
690
|
+
identity: extractTag('identity'),
|
|
691
|
+
communicationStyle: extractTag('communication_style'),
|
|
692
|
+
principles: extractPrinciples(),
|
|
693
|
+
module: moduleName,
|
|
694
|
+
path: agentPath,
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
module.exports = {
|
|
699
|
+
findBmadConfig,
|
|
700
|
+
resolvePath,
|
|
701
|
+
discoverAgents,
|
|
702
|
+
loadAgentConfig,
|
|
703
|
+
promptInstallQuestions,
|
|
704
|
+
installAgent,
|
|
705
|
+
updateAgentId,
|
|
706
|
+
detectBmadProject,
|
|
707
|
+
addToManifest,
|
|
708
|
+
extractManifestData,
|
|
709
|
+
escapeCsvField,
|
|
710
|
+
checkManifestForAgent,
|
|
711
|
+
checkManifestForPath,
|
|
712
|
+
updateManifestEntry,
|
|
713
|
+
saveAgentSource,
|
|
714
|
+
createIdeSlashCommands,
|
|
715
|
+
updateManifestYaml,
|
|
716
|
+
};
|