bmad-fh 6.0.0-alpha.052779ef
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 +54 -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 +400 -0
- package/src/core/lib/scope/index.js +30 -0
- package/src/core/lib/scope/scope-context.js +301 -0
- package/src/core/lib/scope/scope-initializer.js +456 -0
- package/src/core/lib/scope/scope-manager.js +512 -0
- package/src/core/lib/scope/scope-migrator.js +434 -0
- package/src/core/lib/scope/scope-sync.js +483 -0
- package/src/core/lib/scope/scope-validator.js +294 -0
- package/src/core/lib/scope/state-lock.js +336 -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 +439 -0
- package/test/test-scope-system.js +781 -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 +273 -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,781 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scope System Test Suite
|
|
3
|
+
*
|
|
4
|
+
* Tests for multi-scope parallel artifacts system including:
|
|
5
|
+
* - ScopeValidator: ID validation, schema validation, circular dependency detection
|
|
6
|
+
* - ScopeManager: CRUD operations, path resolution
|
|
7
|
+
* - ArtifactResolver: Read/write access control
|
|
8
|
+
* - StateLock: File locking and optimistic versioning
|
|
9
|
+
*
|
|
10
|
+
* Usage: node test/test-scope-system.js
|
|
11
|
+
* Exit codes: 0 = all tests pass, 1 = test failures
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require('node:fs');
|
|
15
|
+
const path = require('node:path');
|
|
16
|
+
const os = require('node:os');
|
|
17
|
+
|
|
18
|
+
// ANSI color codes
|
|
19
|
+
const colors = {
|
|
20
|
+
reset: '\u001B[0m',
|
|
21
|
+
green: '\u001B[32m',
|
|
22
|
+
red: '\u001B[31m',
|
|
23
|
+
yellow: '\u001B[33m',
|
|
24
|
+
blue: '\u001B[34m',
|
|
25
|
+
cyan: '\u001B[36m',
|
|
26
|
+
dim: '\u001B[2m',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Test utilities
|
|
30
|
+
let testCount = 0;
|
|
31
|
+
let passCount = 0;
|
|
32
|
+
let failCount = 0;
|
|
33
|
+
const failures = [];
|
|
34
|
+
|
|
35
|
+
function test(name, fn) {
|
|
36
|
+
testCount++;
|
|
37
|
+
try {
|
|
38
|
+
fn();
|
|
39
|
+
passCount++;
|
|
40
|
+
console.log(` ${colors.green}✓${colors.reset} ${name}`);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
failCount++;
|
|
43
|
+
console.log(` ${colors.red}✗${colors.reset} ${name}`);
|
|
44
|
+
console.log(` ${colors.red}${error.message}${colors.reset}`);
|
|
45
|
+
failures.push({ name, error: error.message });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function assertEqual(actual, expected, message = '') {
|
|
50
|
+
if (actual !== expected) {
|
|
51
|
+
throw new Error(`${message}\n Expected: ${expected}\n Actual: ${actual}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function assertTrue(value, message = 'Expected true') {
|
|
56
|
+
if (!value) {
|
|
57
|
+
throw new Error(message);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function assertFalse(value, message = 'Expected false') {
|
|
62
|
+
if (value) {
|
|
63
|
+
throw new Error(message);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function assertThrows(fn, expectedMessage = null) {
|
|
68
|
+
let threw = false;
|
|
69
|
+
let actualMessage = null;
|
|
70
|
+
try {
|
|
71
|
+
fn();
|
|
72
|
+
} catch (error) {
|
|
73
|
+
threw = true;
|
|
74
|
+
actualMessage = error.message;
|
|
75
|
+
}
|
|
76
|
+
if (!threw) {
|
|
77
|
+
throw new Error('Expected function to throw');
|
|
78
|
+
}
|
|
79
|
+
if (expectedMessage && !actualMessage.includes(expectedMessage)) {
|
|
80
|
+
throw new Error(`Expected error message to contain "${expectedMessage}", got "${actualMessage}"`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function assertArrayEqual(actual, expected, message = '') {
|
|
85
|
+
if (JSON.stringify(actual) !== JSON.stringify(expected)) {
|
|
86
|
+
throw new Error(`${message}\n Expected: ${JSON.stringify(expected)}\n Actual: ${JSON.stringify(actual)}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Create temporary test directory
|
|
91
|
+
function createTempDir() {
|
|
92
|
+
const tmpDir = path.join(os.tmpdir(), `bmad-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
93
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
94
|
+
return tmpDir;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function cleanupTempDir(tmpDir) {
|
|
98
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ============================================================================
|
|
102
|
+
// ScopeValidator Tests
|
|
103
|
+
// ============================================================================
|
|
104
|
+
|
|
105
|
+
function testScopeValidator() {
|
|
106
|
+
console.log(`\n${colors.blue}ScopeValidator Tests${colors.reset}`);
|
|
107
|
+
|
|
108
|
+
const { ScopeValidator } = require('../src/core/lib/scope/scope-validator');
|
|
109
|
+
const validator = new ScopeValidator();
|
|
110
|
+
|
|
111
|
+
// Valid scope IDs
|
|
112
|
+
test('validates simple scope ID', () => {
|
|
113
|
+
assertTrue(validator.isValidScopeId('auth'), 'auth should be valid');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('validates hyphenated scope ID', () => {
|
|
117
|
+
assertTrue(validator.isValidScopeId('user-service'), 'user-service should be valid');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('validates scope ID with numbers', () => {
|
|
121
|
+
assertTrue(validator.isValidScopeId('api-v2'), 'api-v2 should be valid');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('validates minimum length scope ID', () => {
|
|
125
|
+
assertTrue(validator.isValidScopeId('ab'), 'ab (2 chars) should be valid');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Invalid scope IDs
|
|
129
|
+
test('rejects single character scope ID', () => {
|
|
130
|
+
assertFalse(validator.isValidScopeId('a'), 'single char should be invalid');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test('rejects scope ID starting with number', () => {
|
|
134
|
+
assertFalse(validator.isValidScopeId('1auth'), 'starting with number should be invalid');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test('rejects scope ID with uppercase', () => {
|
|
138
|
+
assertFalse(validator.isValidScopeId('Auth'), 'uppercase should be invalid');
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test('rejects scope ID with underscore', () => {
|
|
142
|
+
assertFalse(validator.isValidScopeId('user_service'), 'underscore should be invalid');
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test('rejects scope ID ending with hyphen', () => {
|
|
146
|
+
assertFalse(validator.isValidScopeId('auth-'), 'ending with hyphen should be invalid');
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test('rejects scope ID starting with hyphen', () => {
|
|
150
|
+
assertFalse(validator.isValidScopeId('-auth'), 'starting with hyphen should be invalid');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test('rejects scope ID with spaces', () => {
|
|
154
|
+
assertFalse(validator.isValidScopeId('auth service'), 'spaces should be invalid');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Reserved IDs
|
|
158
|
+
test('rejects reserved ID _shared', () => {
|
|
159
|
+
assertFalse(validator.isValidScopeId('_shared'), '_shared is reserved');
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test('rejects reserved ID _events', () => {
|
|
163
|
+
assertFalse(validator.isValidScopeId('_events'), '_events is reserved');
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test('rejects reserved ID _config', () => {
|
|
167
|
+
assertFalse(validator.isValidScopeId('_config'), '_config is reserved');
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test('rejects reserved ID global', () => {
|
|
171
|
+
assertFalse(validator.isValidScopeId('global'), 'global is reserved');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// Circular dependency detection
|
|
175
|
+
test('detects direct circular dependency', () => {
|
|
176
|
+
const scopes = {
|
|
177
|
+
auth: { dependencies: ['payments'] },
|
|
178
|
+
payments: { dependencies: ['auth'] },
|
|
179
|
+
};
|
|
180
|
+
const result = validator.detectCircularDependencies(scopes);
|
|
181
|
+
assertTrue(result.hasCircular, 'Should detect circular dependency');
|
|
182
|
+
assertTrue(result.cycles.length > 0, 'Should report cycles');
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test('detects indirect circular dependency', () => {
|
|
186
|
+
const scopes = {
|
|
187
|
+
aa: { dependencies: ['bb'] },
|
|
188
|
+
bb: { dependencies: ['cc'] },
|
|
189
|
+
cc: { dependencies: ['aa'] },
|
|
190
|
+
};
|
|
191
|
+
const result = validator.detectCircularDependencies(scopes);
|
|
192
|
+
assertTrue(result.hasCircular, 'Should detect indirect circular dependency');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test('accepts valid dependency graph', () => {
|
|
196
|
+
const scopes = {
|
|
197
|
+
auth: { dependencies: [] },
|
|
198
|
+
payments: { dependencies: ['auth'] },
|
|
199
|
+
orders: { dependencies: ['auth', 'payments'] },
|
|
200
|
+
};
|
|
201
|
+
const result = validator.detectCircularDependencies(scopes);
|
|
202
|
+
assertFalse(result.hasCircular, 'Should not detect circular dependency');
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ============================================================================
|
|
207
|
+
// ScopeManager Tests
|
|
208
|
+
// ============================================================================
|
|
209
|
+
|
|
210
|
+
function testScopeManager() {
|
|
211
|
+
console.log(`\n${colors.blue}ScopeManager Tests${colors.reset}`);
|
|
212
|
+
|
|
213
|
+
const { ScopeManager } = require('../src/core/lib/scope/scope-manager');
|
|
214
|
+
|
|
215
|
+
let tmpDir;
|
|
216
|
+
|
|
217
|
+
// Setup/teardown for each test
|
|
218
|
+
function setup() {
|
|
219
|
+
tmpDir = createTempDir();
|
|
220
|
+
// Create minimal BMAD structure
|
|
221
|
+
fs.mkdirSync(path.join(tmpDir, '_bmad', '_config'), { recursive: true });
|
|
222
|
+
fs.mkdirSync(path.join(tmpDir, '_bmad-output'), { recursive: true });
|
|
223
|
+
return new ScopeManager({ projectRoot: tmpDir });
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function teardown() {
|
|
227
|
+
if (tmpDir) {
|
|
228
|
+
cleanupTempDir(tmpDir);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Test initialization
|
|
233
|
+
test('initializes scope system', async () => {
|
|
234
|
+
const manager = setup();
|
|
235
|
+
try {
|
|
236
|
+
await manager.initialize();
|
|
237
|
+
const scopesPath = path.join(tmpDir, '_bmad', '_config', 'scopes.yaml');
|
|
238
|
+
assertTrue(fs.existsSync(scopesPath), 'scopes.yaml should be created');
|
|
239
|
+
} finally {
|
|
240
|
+
teardown();
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Test scope creation
|
|
245
|
+
test('creates new scope', async () => {
|
|
246
|
+
const manager = setup();
|
|
247
|
+
try {
|
|
248
|
+
await manager.initialize();
|
|
249
|
+
const scope = await manager.createScope('auth', { name: 'Authentication' });
|
|
250
|
+
assertEqual(scope.id, 'auth', 'Scope ID should match');
|
|
251
|
+
assertEqual(scope.name, 'Authentication', 'Scope name should match');
|
|
252
|
+
assertEqual(scope.status, 'active', 'Scope should be active');
|
|
253
|
+
} finally {
|
|
254
|
+
teardown();
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
test('creates scope directory structure', async () => {
|
|
259
|
+
const manager = setup();
|
|
260
|
+
try {
|
|
261
|
+
await manager.initialize();
|
|
262
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
263
|
+
|
|
264
|
+
const scopePath = path.join(tmpDir, '_bmad-output', 'auth');
|
|
265
|
+
assertTrue(fs.existsSync(scopePath), 'Scope directory should exist');
|
|
266
|
+
assertTrue(fs.existsSync(path.join(scopePath, 'planning-artifacts')), 'planning-artifacts should exist');
|
|
267
|
+
assertTrue(fs.existsSync(path.join(scopePath, 'implementation-artifacts')), 'implementation-artifacts should exist');
|
|
268
|
+
assertTrue(fs.existsSync(path.join(scopePath, 'tests')), 'tests should exist');
|
|
269
|
+
} finally {
|
|
270
|
+
teardown();
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test('rejects invalid scope ID on create', async () => {
|
|
275
|
+
const manager = setup();
|
|
276
|
+
try {
|
|
277
|
+
await manager.initialize();
|
|
278
|
+
let threw = false;
|
|
279
|
+
try {
|
|
280
|
+
await manager.createScope('Invalid-ID', { name: 'Test' });
|
|
281
|
+
} catch {
|
|
282
|
+
threw = true;
|
|
283
|
+
}
|
|
284
|
+
assertTrue(threw, 'Should throw for invalid ID');
|
|
285
|
+
} finally {
|
|
286
|
+
teardown();
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
test('rejects duplicate scope ID', async () => {
|
|
291
|
+
const manager = setup();
|
|
292
|
+
try {
|
|
293
|
+
await manager.initialize();
|
|
294
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
295
|
+
let threw = false;
|
|
296
|
+
try {
|
|
297
|
+
await manager.createScope('auth', { name: 'Auth 2' });
|
|
298
|
+
} catch {
|
|
299
|
+
threw = true;
|
|
300
|
+
}
|
|
301
|
+
assertTrue(threw, 'Should throw for duplicate ID');
|
|
302
|
+
} finally {
|
|
303
|
+
teardown();
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// Test scope retrieval
|
|
308
|
+
test('retrieves scope by ID', async () => {
|
|
309
|
+
const manager = setup();
|
|
310
|
+
try {
|
|
311
|
+
await manager.initialize();
|
|
312
|
+
await manager.createScope('auth', { name: 'Authentication', description: 'Auth service' });
|
|
313
|
+
|
|
314
|
+
const scope = await manager.getScope('auth');
|
|
315
|
+
assertEqual(scope.id, 'auth', 'ID should match');
|
|
316
|
+
assertEqual(scope.name, 'Authentication', 'Name should match');
|
|
317
|
+
assertEqual(scope.description, 'Auth service', 'Description should match');
|
|
318
|
+
} finally {
|
|
319
|
+
teardown();
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
test('returns null for non-existent scope', async () => {
|
|
324
|
+
const manager = setup();
|
|
325
|
+
try {
|
|
326
|
+
await manager.initialize();
|
|
327
|
+
const scope = await manager.getScope('nonexistent');
|
|
328
|
+
assertEqual(scope, null, 'Should return null');
|
|
329
|
+
} finally {
|
|
330
|
+
teardown();
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Test scope listing
|
|
335
|
+
test('lists all scopes', async () => {
|
|
336
|
+
const manager = setup();
|
|
337
|
+
try {
|
|
338
|
+
await manager.initialize();
|
|
339
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
340
|
+
await manager.createScope('payments', { name: 'Payments' });
|
|
341
|
+
|
|
342
|
+
const scopes = await manager.listScopes();
|
|
343
|
+
assertEqual(scopes.length, 2, 'Should have 2 scopes');
|
|
344
|
+
} finally {
|
|
345
|
+
teardown();
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
test('filters scopes by status', async () => {
|
|
350
|
+
const manager = setup();
|
|
351
|
+
try {
|
|
352
|
+
await manager.initialize();
|
|
353
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
354
|
+
await manager.createScope('legacy', { name: 'Legacy' });
|
|
355
|
+
await manager.archiveScope('legacy');
|
|
356
|
+
|
|
357
|
+
const activeScopes = await manager.listScopes({ status: 'active' });
|
|
358
|
+
assertEqual(activeScopes.length, 1, 'Should have 1 active scope');
|
|
359
|
+
assertEqual(activeScopes[0].id, 'auth', 'Active scope should be auth');
|
|
360
|
+
} finally {
|
|
361
|
+
teardown();
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
// Test scope update
|
|
366
|
+
test('updates scope properties', async () => {
|
|
367
|
+
const manager = setup();
|
|
368
|
+
try {
|
|
369
|
+
await manager.initialize();
|
|
370
|
+
await manager.createScope('auth', { name: 'Auth', description: 'Old desc' });
|
|
371
|
+
|
|
372
|
+
await manager.updateScope('auth', { description: 'New description' });
|
|
373
|
+
|
|
374
|
+
const scope = await manager.getScope('auth');
|
|
375
|
+
assertEqual(scope.description, 'New description', 'Description should be updated');
|
|
376
|
+
} finally {
|
|
377
|
+
teardown();
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// Test scope archive/activate
|
|
382
|
+
test('archives scope', async () => {
|
|
383
|
+
const manager = setup();
|
|
384
|
+
try {
|
|
385
|
+
await manager.initialize();
|
|
386
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
387
|
+
|
|
388
|
+
await manager.archiveScope('auth');
|
|
389
|
+
|
|
390
|
+
const scope = await manager.getScope('auth');
|
|
391
|
+
assertEqual(scope.status, 'archived', 'Status should be archived');
|
|
392
|
+
} finally {
|
|
393
|
+
teardown();
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
test('activates archived scope', async () => {
|
|
398
|
+
const manager = setup();
|
|
399
|
+
try {
|
|
400
|
+
await manager.initialize();
|
|
401
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
402
|
+
await manager.archiveScope('auth');
|
|
403
|
+
|
|
404
|
+
await manager.activateScope('auth');
|
|
405
|
+
|
|
406
|
+
const scope = await manager.getScope('auth');
|
|
407
|
+
assertEqual(scope.status, 'active', 'Status should be active');
|
|
408
|
+
} finally {
|
|
409
|
+
teardown();
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
// Test path resolution
|
|
414
|
+
test('resolves scope paths', async () => {
|
|
415
|
+
const manager = setup();
|
|
416
|
+
try {
|
|
417
|
+
await manager.initialize();
|
|
418
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
419
|
+
|
|
420
|
+
const paths = await manager.getScopePaths('auth');
|
|
421
|
+
assertTrue(paths.root.includes('auth'), 'Root path should contain scope ID');
|
|
422
|
+
assertTrue(paths.planning.includes('planning-artifacts'), 'Should have planning path');
|
|
423
|
+
assertTrue(paths.implementation.includes('implementation-artifacts'), 'Should have implementation path');
|
|
424
|
+
assertTrue(paths.tests.includes('tests'), 'Should have tests path');
|
|
425
|
+
} finally {
|
|
426
|
+
teardown();
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// Test dependency management
|
|
431
|
+
test('tracks scope dependencies', async () => {
|
|
432
|
+
const manager = setup();
|
|
433
|
+
try {
|
|
434
|
+
await manager.initialize();
|
|
435
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
436
|
+
await manager.createScope('payments', { name: 'Payments', dependencies: ['auth'] });
|
|
437
|
+
|
|
438
|
+
const scope = await manager.getScope('payments');
|
|
439
|
+
assertArrayEqual(scope.dependencies, ['auth'], 'Dependencies should be set');
|
|
440
|
+
} finally {
|
|
441
|
+
teardown();
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
test('finds dependent scopes', async () => {
|
|
446
|
+
const manager = setup();
|
|
447
|
+
try {
|
|
448
|
+
await manager.initialize();
|
|
449
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
450
|
+
await manager.createScope('payments', { name: 'Payments', dependencies: ['auth'] });
|
|
451
|
+
await manager.createScope('orders', { name: 'Orders', dependencies: ['auth'] });
|
|
452
|
+
|
|
453
|
+
const dependents = await manager.findDependentScopes('auth');
|
|
454
|
+
assertEqual(dependents.length, 2, 'Should have 2 dependents');
|
|
455
|
+
assertTrue(dependents.includes('payments'), 'payments should depend on auth');
|
|
456
|
+
assertTrue(dependents.includes('orders'), 'orders should depend on auth');
|
|
457
|
+
} finally {
|
|
458
|
+
teardown();
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// ============================================================================
|
|
464
|
+
// ArtifactResolver Tests
|
|
465
|
+
// ============================================================================
|
|
466
|
+
|
|
467
|
+
function testArtifactResolver() {
|
|
468
|
+
console.log(`\n${colors.blue}ArtifactResolver Tests${colors.reset}`);
|
|
469
|
+
|
|
470
|
+
const { ArtifactResolver } = require('../src/core/lib/scope/artifact-resolver');
|
|
471
|
+
|
|
472
|
+
test('allows read from any scope', () => {
|
|
473
|
+
const resolver = new ArtifactResolver({
|
|
474
|
+
currentScope: 'auth',
|
|
475
|
+
basePath: '_bmad-output',
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
assertTrue(resolver.canRead('_bmad-output/payments/planning-artifacts/prd.md'), 'Should allow cross-scope read');
|
|
479
|
+
assertTrue(resolver.canRead('_bmad-output/auth/planning-artifacts/prd.md'), 'Should allow own-scope read');
|
|
480
|
+
assertTrue(resolver.canRead('_bmad-output/_shared/project-context.md'), 'Should allow shared read');
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
test('allows write to own scope', () => {
|
|
484
|
+
const resolver = new ArtifactResolver({
|
|
485
|
+
currentScope: 'auth',
|
|
486
|
+
basePath: '_bmad-output',
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
assertTrue(resolver.canWrite('_bmad-output/auth/planning-artifacts/prd.md'), 'Should allow own-scope write');
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
test('blocks write to other scope in strict mode', () => {
|
|
493
|
+
const resolver = new ArtifactResolver({
|
|
494
|
+
currentScope: 'auth',
|
|
495
|
+
basePath: '_bmad-output',
|
|
496
|
+
isolationMode: 'strict',
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
assertFalse(resolver.canWrite('_bmad-output/payments/planning-artifacts/prd.md'), 'Should block cross-scope write');
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
test('blocks direct write to _shared', () => {
|
|
503
|
+
const resolver = new ArtifactResolver({
|
|
504
|
+
currentScope: 'auth',
|
|
505
|
+
basePath: '_bmad-output',
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
assertFalse(resolver.canWrite('_bmad-output/_shared/project-context.md'), 'Should block _shared write');
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
test('extracts scope from path', () => {
|
|
512
|
+
const resolver = new ArtifactResolver({
|
|
513
|
+
currentScope: 'auth',
|
|
514
|
+
basePath: '_bmad-output',
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
assertEqual(resolver.extractScopeFromPath('_bmad-output/payments/planning-artifacts/prd.md'), 'payments');
|
|
518
|
+
assertEqual(resolver.extractScopeFromPath('_bmad-output/auth/tests/unit.js'), 'auth');
|
|
519
|
+
assertEqual(resolver.extractScopeFromPath('_bmad-output/_shared/context.md'), '_shared');
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
test('throws on cross-scope write validation in strict mode', () => {
|
|
523
|
+
const resolver = new ArtifactResolver({
|
|
524
|
+
currentScope: 'auth',
|
|
525
|
+
basePath: '_bmad-output',
|
|
526
|
+
isolationMode: 'strict',
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
assertThrows(() => resolver.validateWrite('_bmad-output/payments/prd.md'), 'Cannot write to scope');
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
test('warns on cross-scope write in warn mode', () => {
|
|
533
|
+
const resolver = new ArtifactResolver({
|
|
534
|
+
currentScope: 'auth',
|
|
535
|
+
basePath: '_bmad-output',
|
|
536
|
+
isolationMode: 'warn',
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
// Should not throw in warn mode
|
|
540
|
+
const result = resolver.canWrite('_bmad-output/payments/prd.md');
|
|
541
|
+
// In warn mode, it may return true but log a warning
|
|
542
|
+
// The exact behavior depends on implementation
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// ============================================================================
|
|
547
|
+
// StateLock Tests
|
|
548
|
+
// ============================================================================
|
|
549
|
+
|
|
550
|
+
function testStateLock() {
|
|
551
|
+
console.log(`\n${colors.blue}StateLock Tests${colors.reset}`);
|
|
552
|
+
|
|
553
|
+
const { StateLock } = require('../src/core/lib/scope/state-lock');
|
|
554
|
+
|
|
555
|
+
let tmpDir;
|
|
556
|
+
|
|
557
|
+
function setup() {
|
|
558
|
+
tmpDir = createTempDir();
|
|
559
|
+
return new StateLock();
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function teardown() {
|
|
563
|
+
if (tmpDir) {
|
|
564
|
+
cleanupTempDir(tmpDir);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
test('acquires and releases lock', async () => {
|
|
569
|
+
const lock = setup();
|
|
570
|
+
try {
|
|
571
|
+
const lockPath = path.join(tmpDir, 'test.lock');
|
|
572
|
+
|
|
573
|
+
const result = await lock.withLock(lockPath, async () => {
|
|
574
|
+
return 'success';
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
assertEqual(result, 'success', 'Should return operation result');
|
|
578
|
+
} finally {
|
|
579
|
+
teardown();
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
test('prevents concurrent access', async () => {
|
|
584
|
+
const lock = setup();
|
|
585
|
+
try {
|
|
586
|
+
const lockPath = path.join(tmpDir, 'test.lock');
|
|
587
|
+
const order = [];
|
|
588
|
+
|
|
589
|
+
// Start first operation (holds lock)
|
|
590
|
+
const op1 = lock.withLock(lockPath, async () => {
|
|
591
|
+
order.push('op1-start');
|
|
592
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
593
|
+
order.push('op1-end');
|
|
594
|
+
return 'op1';
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
// Start second operation immediately (should wait)
|
|
598
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
599
|
+
const op2 = lock.withLock(lockPath, async () => {
|
|
600
|
+
order.push('op2');
|
|
601
|
+
return 'op2';
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
await Promise.all([op1, op2]);
|
|
605
|
+
|
|
606
|
+
// op2 should start after op1 ends
|
|
607
|
+
assertTrue(order.indexOf('op1-end') < order.indexOf('op2'), 'op2 should run after op1 completes');
|
|
608
|
+
} finally {
|
|
609
|
+
teardown();
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
test('detects stale locks', async () => {
|
|
614
|
+
const lock = setup();
|
|
615
|
+
try {
|
|
616
|
+
const lockPath = path.join(tmpDir, 'test.lock');
|
|
617
|
+
|
|
618
|
+
// Create a stale lock file manually
|
|
619
|
+
fs.writeFileSync(
|
|
620
|
+
lockPath,
|
|
621
|
+
JSON.stringify({
|
|
622
|
+
pid: 99_999_999, // Non-existent PID
|
|
623
|
+
timestamp: Date.now() - 60_000, // 60 seconds ago
|
|
624
|
+
}),
|
|
625
|
+
);
|
|
626
|
+
|
|
627
|
+
// Should be able to acquire lock despite stale file
|
|
628
|
+
const result = await lock.withLock(lockPath, async () => 'success');
|
|
629
|
+
assertEqual(result, 'success', 'Should acquire lock after stale detection');
|
|
630
|
+
} finally {
|
|
631
|
+
teardown();
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// ============================================================================
|
|
637
|
+
// ScopeContext Tests
|
|
638
|
+
// ============================================================================
|
|
639
|
+
|
|
640
|
+
function testScopeContext() {
|
|
641
|
+
console.log(`\n${colors.blue}ScopeContext Tests${colors.reset}`);
|
|
642
|
+
|
|
643
|
+
const { ScopeContext } = require('../src/core/lib/scope/scope-context');
|
|
644
|
+
const { ScopeManager } = require('../src/core/lib/scope/scope-manager');
|
|
645
|
+
|
|
646
|
+
let tmpDir;
|
|
647
|
+
|
|
648
|
+
function setup() {
|
|
649
|
+
tmpDir = createTempDir();
|
|
650
|
+
fs.mkdirSync(path.join(tmpDir, '_bmad', '_config'), { recursive: true });
|
|
651
|
+
fs.mkdirSync(path.join(tmpDir, '_bmad-output', '_shared'), { recursive: true });
|
|
652
|
+
return new ScopeContext({ projectRoot: tmpDir });
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
function teardown() {
|
|
656
|
+
if (tmpDir) {
|
|
657
|
+
cleanupTempDir(tmpDir);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
test('sets session scope', async () => {
|
|
662
|
+
const context = setup();
|
|
663
|
+
try {
|
|
664
|
+
// Initialize scope system first
|
|
665
|
+
const manager = new ScopeManager({ projectRoot: tmpDir });
|
|
666
|
+
await manager.initialize();
|
|
667
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
668
|
+
|
|
669
|
+
await context.setScope('auth');
|
|
670
|
+
|
|
671
|
+
const scopeFile = path.join(tmpDir, '.bmad-scope');
|
|
672
|
+
assertTrue(fs.existsSync(scopeFile), '.bmad-scope file should be created');
|
|
673
|
+
} finally {
|
|
674
|
+
teardown();
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
test('gets current scope from session', async () => {
|
|
679
|
+
const context = setup();
|
|
680
|
+
try {
|
|
681
|
+
// Initialize scope system first
|
|
682
|
+
const manager = new ScopeManager({ projectRoot: tmpDir });
|
|
683
|
+
await manager.initialize();
|
|
684
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
685
|
+
|
|
686
|
+
await context.setScope('auth');
|
|
687
|
+
const current = await context.getCurrentScope();
|
|
688
|
+
|
|
689
|
+
assertEqual(current, 'auth', 'Should return session scope');
|
|
690
|
+
} finally {
|
|
691
|
+
teardown();
|
|
692
|
+
}
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
test('clears session scope', async () => {
|
|
696
|
+
const context = setup();
|
|
697
|
+
try {
|
|
698
|
+
const manager = new ScopeManager({ projectRoot: tmpDir });
|
|
699
|
+
await manager.initialize();
|
|
700
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
701
|
+
|
|
702
|
+
await context.setScope('auth');
|
|
703
|
+
await context.clearScope();
|
|
704
|
+
|
|
705
|
+
const current = await context.getCurrentScope();
|
|
706
|
+
assertEqual(current, null, 'Should return null after clearing');
|
|
707
|
+
} finally {
|
|
708
|
+
teardown();
|
|
709
|
+
}
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
test('loads merged project context', async () => {
|
|
713
|
+
const context = setup();
|
|
714
|
+
try {
|
|
715
|
+
const manager = new ScopeManager({ projectRoot: tmpDir });
|
|
716
|
+
await manager.initialize();
|
|
717
|
+
await manager.createScope('auth', { name: 'Auth' });
|
|
718
|
+
|
|
719
|
+
// Create global context
|
|
720
|
+
fs.writeFileSync(path.join(tmpDir, '_bmad-output', '_shared', 'project-context.md'), '# Global Project\n\nGlobal content here.');
|
|
721
|
+
|
|
722
|
+
// Create scope-specific context
|
|
723
|
+
fs.mkdirSync(path.join(tmpDir, '_bmad-output', 'auth'), { recursive: true });
|
|
724
|
+
fs.writeFileSync(path.join(tmpDir, '_bmad-output', 'auth', 'project-context.md'), '# Auth Scope\n\nScope-specific content.');
|
|
725
|
+
|
|
726
|
+
const merged = await context.loadProjectContext('auth');
|
|
727
|
+
|
|
728
|
+
assertTrue(merged.includes('Global content'), 'Should include global content');
|
|
729
|
+
assertTrue(merged.includes('Scope-specific content'), 'Should include scope content');
|
|
730
|
+
} finally {
|
|
731
|
+
teardown();
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
// ============================================================================
|
|
737
|
+
// Main Runner
|
|
738
|
+
// ============================================================================
|
|
739
|
+
|
|
740
|
+
async function main() {
|
|
741
|
+
console.log(`${colors.cyan}╔═══════════════════════════════════════════════════════════╗${colors.reset}`);
|
|
742
|
+
console.log(`${colors.cyan}║ Scope System Test Suite ║${colors.reset}`);
|
|
743
|
+
console.log(`${colors.cyan}╚═══════════════════════════════════════════════════════════╝${colors.reset}`);
|
|
744
|
+
|
|
745
|
+
try {
|
|
746
|
+
testScopeValidator();
|
|
747
|
+
await testScopeManager();
|
|
748
|
+
testArtifactResolver();
|
|
749
|
+
await testStateLock();
|
|
750
|
+
await testScopeContext();
|
|
751
|
+
} catch (error) {
|
|
752
|
+
console.log(`\n${colors.red}Fatal error: ${error.message}${colors.reset}`);
|
|
753
|
+
console.log(error.stack);
|
|
754
|
+
process.exit(1);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// Summary
|
|
758
|
+
console.log(`\n${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}`);
|
|
759
|
+
console.log(`${colors.cyan}Test Results:${colors.reset}`);
|
|
760
|
+
console.log(` Total: ${testCount}`);
|
|
761
|
+
console.log(` Passed: ${colors.green}${passCount}${colors.reset}`);
|
|
762
|
+
console.log(` Failed: ${failCount === 0 ? colors.green : colors.red}${failCount}${colors.reset}`);
|
|
763
|
+
console.log(`${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}\n`);
|
|
764
|
+
|
|
765
|
+
if (failures.length > 0) {
|
|
766
|
+
console.log(`${colors.red}Failed Tests:${colors.reset}\n`);
|
|
767
|
+
for (const failure of failures) {
|
|
768
|
+
console.log(`${colors.red}✗${colors.reset} ${failure.name}`);
|
|
769
|
+
console.log(` ${failure.error}\n`);
|
|
770
|
+
}
|
|
771
|
+
process.exit(1);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
console.log(`${colors.green}All tests passed!${colors.reset}\n`);
|
|
775
|
+
process.exit(0);
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
main().catch((error) => {
|
|
779
|
+
console.error(`${colors.red}Fatal error:${colors.reset}`, error);
|
|
780
|
+
process.exit(1);
|
|
781
|
+
});
|