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,853 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Network-First Patterns Explained"
|
|
3
|
+
description: Understanding how TEA eliminates test flakiness by waiting for actual network responses
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Network-First Patterns Explained
|
|
7
|
+
|
|
8
|
+
Network-first patterns are TEA's solution to test flakiness. Instead of guessing how long to wait with fixed timeouts, wait for the actual network event that causes UI changes.
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
**The Core Principle:**
|
|
13
|
+
UI changes because APIs respond. Wait for the API response, not an arbitrary timeout.
|
|
14
|
+
|
|
15
|
+
**Traditional approach:**
|
|
16
|
+
```typescript
|
|
17
|
+
await page.click('button');
|
|
18
|
+
await page.waitForTimeout(3000); // Hope 3 seconds is enough
|
|
19
|
+
await expect(page.locator('.success')).toBeVisible();
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Network-first approach:**
|
|
23
|
+
```typescript
|
|
24
|
+
const responsePromise = page.waitForResponse(
|
|
25
|
+
resp => resp.url().includes('/api/submit') && resp.ok()
|
|
26
|
+
);
|
|
27
|
+
await page.click('button');
|
|
28
|
+
await responsePromise; // Wait for actual response
|
|
29
|
+
await expect(page.locator('.success')).toBeVisible();
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Result:** Deterministic tests that wait exactly as long as needed.
|
|
33
|
+
|
|
34
|
+
## The Problem
|
|
35
|
+
|
|
36
|
+
### Hard Waits Create Flakiness
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
// ❌ The flaky test pattern
|
|
40
|
+
test('should submit form', async ({ page }) => {
|
|
41
|
+
await page.fill('#name', 'Test User');
|
|
42
|
+
await page.click('button[type="submit"]');
|
|
43
|
+
|
|
44
|
+
await page.waitForTimeout(2000); // Wait 2 seconds
|
|
45
|
+
|
|
46
|
+
await expect(page.locator('.success')).toBeVisible();
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Why this fails:**
|
|
51
|
+
- **Fast network:** Wastes 1.5 seconds waiting
|
|
52
|
+
- **Slow network:** Not enough time, test fails
|
|
53
|
+
- **CI environment:** Slower than local, fails randomly
|
|
54
|
+
- **Under load:** API takes 3 seconds, test fails
|
|
55
|
+
|
|
56
|
+
**Result:** "Works on my machine" syndrome, flaky CI.
|
|
57
|
+
|
|
58
|
+
### The Timeout Escalation Trap
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
// Developer sees flaky test
|
|
62
|
+
await page.waitForTimeout(2000); // Failed in CI
|
|
63
|
+
|
|
64
|
+
// Increases timeout
|
|
65
|
+
await page.waitForTimeout(5000); // Still fails sometimes
|
|
66
|
+
|
|
67
|
+
// Increases again
|
|
68
|
+
await page.waitForTimeout(10000); // Now it passes... slowly
|
|
69
|
+
|
|
70
|
+
// Problem: Now EVERY test waits 10 seconds
|
|
71
|
+
// Suite that took 5 minutes now takes 30 minutes
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Result:** Slow, still-flaky tests.
|
|
75
|
+
|
|
76
|
+
### Race Conditions
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// ❌ Navigate-then-wait race condition
|
|
80
|
+
test('should load dashboard data', async ({ page }) => {
|
|
81
|
+
await page.goto('/dashboard'); // Navigation starts
|
|
82
|
+
|
|
83
|
+
// Race condition! API might not have responded yet
|
|
84
|
+
await expect(page.locator('.data-table')).toBeVisible();
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**What happens:**
|
|
89
|
+
1. `goto()` starts navigation
|
|
90
|
+
2. Page loads HTML
|
|
91
|
+
3. JavaScript requests `/api/dashboard`
|
|
92
|
+
4. Test checks for `.data-table` BEFORE API responds
|
|
93
|
+
5. Test fails intermittently
|
|
94
|
+
|
|
95
|
+
**Result:** "Sometimes it works, sometimes it doesn't."
|
|
96
|
+
|
|
97
|
+
## The Solution: Intercept-Before-Navigate
|
|
98
|
+
|
|
99
|
+
### Wait for Response Before Asserting
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
// ✅ Good: Network-first pattern
|
|
103
|
+
test('should load dashboard data', async ({ page }) => {
|
|
104
|
+
// Set up promise BEFORE navigation
|
|
105
|
+
const dashboardPromise = page.waitForResponse(
|
|
106
|
+
resp => resp.url().includes('/api/dashboard') && resp.ok()
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
// Navigate
|
|
110
|
+
await page.goto('/dashboard');
|
|
111
|
+
|
|
112
|
+
// Wait for API response
|
|
113
|
+
const response = await dashboardPromise;
|
|
114
|
+
const data = await response.json();
|
|
115
|
+
|
|
116
|
+
// Now assert UI
|
|
117
|
+
await expect(page.locator('.data-table')).toBeVisible();
|
|
118
|
+
await expect(page.locator('.data-table tr')).toHaveCount(data.items.length);
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Why this works:**
|
|
123
|
+
- Wait set up BEFORE navigation (no race)
|
|
124
|
+
- Wait for actual API response (deterministic)
|
|
125
|
+
- No fixed timeout (fast when API is fast)
|
|
126
|
+
- Validates API response (catch backend errors)
|
|
127
|
+
|
|
128
|
+
**With Playwright Utils (Even Cleaner):**
|
|
129
|
+
```typescript
|
|
130
|
+
import { test } from '@seontechnologies/playwright-utils/fixtures';
|
|
131
|
+
import { expect } from '@playwright/test';
|
|
132
|
+
|
|
133
|
+
test('should load dashboard data', async ({ page, interceptNetworkCall }) => {
|
|
134
|
+
// Set up interception BEFORE navigation
|
|
135
|
+
const dashboardCall = interceptNetworkCall({
|
|
136
|
+
method: 'GET',
|
|
137
|
+
url: '**/api/dashboard'
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Navigate
|
|
141
|
+
await page.goto('/dashboard');
|
|
142
|
+
|
|
143
|
+
// Wait for API response (automatic JSON parsing)
|
|
144
|
+
const { status, responseJson: data } = await dashboardCall;
|
|
145
|
+
|
|
146
|
+
// Validate API response
|
|
147
|
+
expect(status).toBe(200);
|
|
148
|
+
expect(data.items).toBeDefined();
|
|
149
|
+
|
|
150
|
+
// Assert UI matches API data
|
|
151
|
+
await expect(page.locator('.data-table')).toBeVisible();
|
|
152
|
+
await expect(page.locator('.data-table tr')).toHaveCount(data.items.length);
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Playwright Utils Benefits:**
|
|
157
|
+
- Automatic JSON parsing (no `await response.json()`)
|
|
158
|
+
- Returns `{ status, responseJson, requestJson }` structure
|
|
159
|
+
- Cleaner API (no need to check `resp.ok()`)
|
|
160
|
+
- Same intercept-before-navigate pattern
|
|
161
|
+
|
|
162
|
+
### Intercept-Before-Navigate Pattern
|
|
163
|
+
|
|
164
|
+
**Key insight:** Set up wait BEFORE triggering the action.
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
// ✅ Pattern: Intercept → Action → Await
|
|
168
|
+
|
|
169
|
+
// 1. Intercept (set up wait)
|
|
170
|
+
const promise = page.waitForResponse(matcher);
|
|
171
|
+
|
|
172
|
+
// 2. Action (trigger request)
|
|
173
|
+
await page.click('button');
|
|
174
|
+
|
|
175
|
+
// 3. Await (wait for actual response)
|
|
176
|
+
await promise;
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Why this order:**
|
|
180
|
+
- `waitForResponse()` starts listening immediately
|
|
181
|
+
- Then trigger the action that makes the request
|
|
182
|
+
- Then wait for the promise to resolve
|
|
183
|
+
- No race condition possible
|
|
184
|
+
|
|
185
|
+
#### Intercept-Before-Navigate Flow
|
|
186
|
+
|
|
187
|
+
```mermaid
|
|
188
|
+
%%{init: {'theme':'base', 'themeVariables': { 'fontSize':'14px'}}}%%
|
|
189
|
+
sequenceDiagram
|
|
190
|
+
participant Test
|
|
191
|
+
participant Playwright
|
|
192
|
+
participant Browser
|
|
193
|
+
participant API
|
|
194
|
+
|
|
195
|
+
rect rgb(200, 230, 201)
|
|
196
|
+
Note over Test,Playwright: ✅ CORRECT: Intercept First
|
|
197
|
+
Test->>Playwright: 1. waitForResponse(matcher)
|
|
198
|
+
Note over Playwright: Starts listening for response
|
|
199
|
+
Test->>Browser: 2. click('button')
|
|
200
|
+
Browser->>API: 3. POST /api/submit
|
|
201
|
+
API-->>Browser: 4. 200 OK {success: true}
|
|
202
|
+
Browser-->>Playwright: 5. Response captured
|
|
203
|
+
Test->>Playwright: 6. await promise
|
|
204
|
+
Playwright-->>Test: 7. Returns response
|
|
205
|
+
Note over Test: No race condition!
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
rect rgb(255, 205, 210)
|
|
209
|
+
Note over Test,API: ❌ WRONG: Action First
|
|
210
|
+
Test->>Browser: 1. click('button')
|
|
211
|
+
Browser->>API: 2. POST /api/submit
|
|
212
|
+
API-->>Browser: 3. 200 OK (already happened!)
|
|
213
|
+
Test->>Playwright: 4. waitForResponse(matcher)
|
|
214
|
+
Note over Test,Playwright: Too late - response already occurred
|
|
215
|
+
Note over Test: Race condition! Test hangs or fails
|
|
216
|
+
end
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Correct Order (Green):**
|
|
220
|
+
1. Set up listener (`waitForResponse`)
|
|
221
|
+
2. Trigger action (`click`)
|
|
222
|
+
3. Wait for response (`await promise`)
|
|
223
|
+
|
|
224
|
+
**Wrong Order (Red):**
|
|
225
|
+
1. Trigger action first
|
|
226
|
+
2. Set up listener too late
|
|
227
|
+
3. Response already happened - missed!
|
|
228
|
+
|
|
229
|
+
## How It Works in TEA
|
|
230
|
+
|
|
231
|
+
### TEA Generates Network-First Tests
|
|
232
|
+
|
|
233
|
+
**Vanilla Playwright:**
|
|
234
|
+
```typescript
|
|
235
|
+
// When you run *atdd or *automate, TEA generates:
|
|
236
|
+
|
|
237
|
+
test('should create user', async ({ page }) => {
|
|
238
|
+
// TEA automatically includes network wait
|
|
239
|
+
const createUserPromise = page.waitForResponse(
|
|
240
|
+
resp => resp.url().includes('/api/users') &&
|
|
241
|
+
resp.request().method() === 'POST' &&
|
|
242
|
+
resp.ok()
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
await page.fill('#name', 'Test User');
|
|
246
|
+
await page.click('button[type="submit"]');
|
|
247
|
+
|
|
248
|
+
const response = await createUserPromise;
|
|
249
|
+
const user = await response.json();
|
|
250
|
+
|
|
251
|
+
// Validate both API and UI
|
|
252
|
+
expect(user.id).toBeDefined();
|
|
253
|
+
await expect(page.locator('.success')).toContainText(user.name);
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
**With Playwright Utils (if `tea_use_playwright_utils: true`):**
|
|
258
|
+
```typescript
|
|
259
|
+
import { test } from '@seontechnologies/playwright-utils/fixtures';
|
|
260
|
+
import { expect } from '@playwright/test';
|
|
261
|
+
|
|
262
|
+
test('should create user', async ({ page, interceptNetworkCall }) => {
|
|
263
|
+
// TEA uses interceptNetworkCall for cleaner interception
|
|
264
|
+
const createUserCall = interceptNetworkCall({
|
|
265
|
+
method: 'POST',
|
|
266
|
+
url: '**/api/users'
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
await page.getByLabel('Name').fill('Test User');
|
|
270
|
+
await page.getByRole('button', { name: 'Submit' }).click();
|
|
271
|
+
|
|
272
|
+
// Wait for response (automatic JSON parsing)
|
|
273
|
+
const { status, responseJson: user } = await createUserCall;
|
|
274
|
+
|
|
275
|
+
// Validate both API and UI
|
|
276
|
+
expect(status).toBe(201);
|
|
277
|
+
expect(user.id).toBeDefined();
|
|
278
|
+
await expect(page.locator('.success')).toContainText(user.name);
|
|
279
|
+
});
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Playwright Utils Benefits:**
|
|
283
|
+
- Automatic JSON parsing (`responseJson` ready to use)
|
|
284
|
+
- No manual `await response.json()`
|
|
285
|
+
- Returns `{ status, responseJson }` structure
|
|
286
|
+
- Cleaner, more readable code
|
|
287
|
+
|
|
288
|
+
### TEA Reviews for Hard Waits
|
|
289
|
+
|
|
290
|
+
When you run `*test-review`:
|
|
291
|
+
|
|
292
|
+
```markdown
|
|
293
|
+
## Critical Issue: Hard Wait Detected
|
|
294
|
+
|
|
295
|
+
**File:** tests/e2e/submit.spec.ts:45
|
|
296
|
+
**Issue:** Using `page.waitForTimeout(3000)`
|
|
297
|
+
**Severity:** Critical (causes flakiness)
|
|
298
|
+
|
|
299
|
+
**Current Code:**
|
|
300
|
+
```typescript
|
|
301
|
+
await page.click('button');
|
|
302
|
+
await page.waitForTimeout(3000); // ❌
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Fix:**
|
|
306
|
+
```typescript
|
|
307
|
+
const responsePromise = page.waitForResponse(
|
|
308
|
+
resp => resp.url().includes('/api/submit') && resp.ok()
|
|
309
|
+
);
|
|
310
|
+
await page.click('button');
|
|
311
|
+
await responsePromise; // ✅
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Why:** Hard waits are non-deterministic. Use network-first patterns.
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Pattern Variations
|
|
318
|
+
|
|
319
|
+
### Basic Response Wait
|
|
320
|
+
|
|
321
|
+
**Vanilla Playwright:**
|
|
322
|
+
```typescript
|
|
323
|
+
// Wait for any successful response
|
|
324
|
+
const promise = page.waitForResponse(resp => resp.ok());
|
|
325
|
+
await page.click('button');
|
|
326
|
+
await promise;
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**With Playwright Utils:**
|
|
330
|
+
```typescript
|
|
331
|
+
import { test } from '@seontechnologies/playwright-utils/fixtures';
|
|
332
|
+
|
|
333
|
+
test('basic wait', async ({ page, interceptNetworkCall }) => {
|
|
334
|
+
const responseCall = interceptNetworkCall({ url: '**' }); // Match any
|
|
335
|
+
await page.click('button');
|
|
336
|
+
const { status } = await responseCall;
|
|
337
|
+
expect(status).toBe(200);
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
### Specific URL Match
|
|
344
|
+
|
|
345
|
+
**Vanilla Playwright:**
|
|
346
|
+
```typescript
|
|
347
|
+
// Wait for specific endpoint
|
|
348
|
+
const promise = page.waitForResponse(
|
|
349
|
+
resp => resp.url().includes('/api/users/123')
|
|
350
|
+
);
|
|
351
|
+
await page.goto('/user/123');
|
|
352
|
+
await promise;
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**With Playwright Utils:**
|
|
356
|
+
```typescript
|
|
357
|
+
test('specific URL', async ({ page, interceptNetworkCall }) => {
|
|
358
|
+
const userCall = interceptNetworkCall({ url: '**/api/users/123' });
|
|
359
|
+
await page.goto('/user/123');
|
|
360
|
+
const { status, responseJson } = await userCall;
|
|
361
|
+
expect(status).toBe(200);
|
|
362
|
+
});
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
### Method + Status Match
|
|
368
|
+
|
|
369
|
+
**Vanilla Playwright:**
|
|
370
|
+
```typescript
|
|
371
|
+
// Wait for POST that returns 201
|
|
372
|
+
const promise = page.waitForResponse(
|
|
373
|
+
resp =>
|
|
374
|
+
resp.url().includes('/api/users') &&
|
|
375
|
+
resp.request().method() === 'POST' &&
|
|
376
|
+
resp.status() === 201
|
|
377
|
+
);
|
|
378
|
+
await page.click('button[type="submit"]');
|
|
379
|
+
await promise;
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**With Playwright Utils:**
|
|
383
|
+
```typescript
|
|
384
|
+
test('method and status', async ({ page, interceptNetworkCall }) => {
|
|
385
|
+
const createCall = interceptNetworkCall({
|
|
386
|
+
method: 'POST',
|
|
387
|
+
url: '**/api/users'
|
|
388
|
+
});
|
|
389
|
+
await page.click('button[type="submit"]');
|
|
390
|
+
const { status, responseJson } = await createCall;
|
|
391
|
+
expect(status).toBe(201); // Explicit status check
|
|
392
|
+
});
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
### Multiple Responses
|
|
398
|
+
|
|
399
|
+
**Vanilla Playwright:**
|
|
400
|
+
```typescript
|
|
401
|
+
// Wait for multiple API calls
|
|
402
|
+
const [usersResp, postsResp] = await Promise.all([
|
|
403
|
+
page.waitForResponse(resp => resp.url().includes('/api/users')),
|
|
404
|
+
page.waitForResponse(resp => resp.url().includes('/api/posts')),
|
|
405
|
+
page.goto('/dashboard') // Triggers both requests
|
|
406
|
+
]);
|
|
407
|
+
|
|
408
|
+
const users = await usersResp.json();
|
|
409
|
+
const posts = await postsResp.json();
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**With Playwright Utils:**
|
|
413
|
+
```typescript
|
|
414
|
+
test('multiple responses', async ({ page, interceptNetworkCall }) => {
|
|
415
|
+
const usersCall = interceptNetworkCall({ url: '**/api/users' });
|
|
416
|
+
const postsCall = interceptNetworkCall({ url: '**/api/posts' });
|
|
417
|
+
|
|
418
|
+
await page.goto('/dashboard'); // Triggers both
|
|
419
|
+
|
|
420
|
+
const [{ responseJson: users }, { responseJson: posts }] = await Promise.all([
|
|
421
|
+
usersCall,
|
|
422
|
+
postsCall
|
|
423
|
+
]);
|
|
424
|
+
|
|
425
|
+
expect(users).toBeInstanceOf(Array);
|
|
426
|
+
expect(posts).toBeInstanceOf(Array);
|
|
427
|
+
});
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
### Validate Response Data
|
|
433
|
+
|
|
434
|
+
**Vanilla Playwright:**
|
|
435
|
+
```typescript
|
|
436
|
+
// Verify API response before asserting UI
|
|
437
|
+
const promise = page.waitForResponse(
|
|
438
|
+
resp => resp.url().includes('/api/checkout') && resp.ok()
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
await page.click('button:has-text("Complete Order")');
|
|
442
|
+
|
|
443
|
+
const response = await promise;
|
|
444
|
+
const order = await response.json();
|
|
445
|
+
|
|
446
|
+
// Response validation
|
|
447
|
+
expect(order.status).toBe('confirmed');
|
|
448
|
+
expect(order.total).toBeGreaterThan(0);
|
|
449
|
+
|
|
450
|
+
// UI validation
|
|
451
|
+
await expect(page.locator('.order-confirmation')).toContainText(order.id);
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
**With Playwright Utils:**
|
|
455
|
+
```typescript
|
|
456
|
+
test('validate response data', async ({ page, interceptNetworkCall }) => {
|
|
457
|
+
const checkoutCall = interceptNetworkCall({
|
|
458
|
+
method: 'POST',
|
|
459
|
+
url: '**/api/checkout'
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
await page.click('button:has-text("Complete Order")');
|
|
463
|
+
|
|
464
|
+
const { status, responseJson: order } = await checkoutCall;
|
|
465
|
+
|
|
466
|
+
// Response validation (automatic JSON parsing)
|
|
467
|
+
expect(status).toBe(200);
|
|
468
|
+
expect(order.status).toBe('confirmed');
|
|
469
|
+
expect(order.total).toBeGreaterThan(0);
|
|
470
|
+
|
|
471
|
+
// UI validation
|
|
472
|
+
await expect(page.locator('.order-confirmation')).toContainText(order.id);
|
|
473
|
+
});
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
## Advanced Patterns
|
|
477
|
+
|
|
478
|
+
### HAR Recording for Offline Testing
|
|
479
|
+
|
|
480
|
+
**Vanilla Playwright (Manual HAR Handling):**
|
|
481
|
+
|
|
482
|
+
```typescript
|
|
483
|
+
// First run: Record mode (saves HAR file)
|
|
484
|
+
test('offline testing - RECORD', async ({ page, context }) => {
|
|
485
|
+
// Record mode: Save network traffic to HAR
|
|
486
|
+
await context.routeFromHAR('./hars/dashboard.har', {
|
|
487
|
+
url: '**/api/**',
|
|
488
|
+
update: true // Update HAR file
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
await page.goto('/dashboard');
|
|
492
|
+
// All network traffic saved to dashboard.har
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
// Subsequent runs: Playback mode (uses saved HAR)
|
|
496
|
+
test('offline testing - PLAYBACK', async ({ page, context }) => {
|
|
497
|
+
// Playback mode: Use saved network traffic
|
|
498
|
+
await context.routeFromHAR('./hars/dashboard.har', {
|
|
499
|
+
url: '**/api/**',
|
|
500
|
+
update: false // Use existing HAR, no network calls
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
await page.goto('/dashboard');
|
|
504
|
+
// Uses recorded responses, no backend needed
|
|
505
|
+
});
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
**With Playwright Utils (Automatic HAR Management):**
|
|
509
|
+
```typescript
|
|
510
|
+
import { test } from '@seontechnologies/playwright-utils/network-recorder/fixtures';
|
|
511
|
+
|
|
512
|
+
// Record mode: Set environment variable
|
|
513
|
+
process.env.PW_NET_MODE = 'record';
|
|
514
|
+
|
|
515
|
+
test('should work offline', async ({ page, context, networkRecorder }) => {
|
|
516
|
+
await networkRecorder.setup(context); // Handles HAR automatically
|
|
517
|
+
|
|
518
|
+
await page.goto('/dashboard');
|
|
519
|
+
await page.click('#add-item');
|
|
520
|
+
// All network traffic recorded, CRUD operations detected
|
|
521
|
+
});
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
**Switch to playback:**
|
|
525
|
+
```bash
|
|
526
|
+
# Playback mode (offline)
|
|
527
|
+
PW_NET_MODE=playback npx playwright test
|
|
528
|
+
# Uses HAR file, no backend needed!
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
**Playwright Utils Benefits:**
|
|
532
|
+
- Automatic HAR file management (naming, paths)
|
|
533
|
+
- CRUD operation detection (stateful mocking)
|
|
534
|
+
- Environment variable control (easy switching)
|
|
535
|
+
- Works for complex interactions (create, update, delete)
|
|
536
|
+
- No manual route configuration
|
|
537
|
+
|
|
538
|
+
### Network Request Interception
|
|
539
|
+
|
|
540
|
+
**Vanilla Playwright:**
|
|
541
|
+
```typescript
|
|
542
|
+
test('should handle API error', async ({ page }) => {
|
|
543
|
+
// Manual route setup
|
|
544
|
+
await page.route('**/api/users', (route) => {
|
|
545
|
+
route.fulfill({
|
|
546
|
+
status: 500,
|
|
547
|
+
body: JSON.stringify({ error: 'Internal server error' })
|
|
548
|
+
});
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
await page.goto('/users');
|
|
552
|
+
|
|
553
|
+
const response = await page.waitForResponse('**/api/users');
|
|
554
|
+
const error = await response.json();
|
|
555
|
+
|
|
556
|
+
expect(error.error).toContain('Internal server');
|
|
557
|
+
await expect(page.locator('.error-message')).toContainText('Server error');
|
|
558
|
+
});
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
**With Playwright Utils:**
|
|
562
|
+
```typescript
|
|
563
|
+
import { test } from '@seontechnologies/playwright-utils/fixtures';
|
|
564
|
+
|
|
565
|
+
test('should handle API error', async ({ page, interceptNetworkCall }) => {
|
|
566
|
+
// Stub API to return error (set up BEFORE navigation)
|
|
567
|
+
const usersCall = interceptNetworkCall({
|
|
568
|
+
method: 'GET',
|
|
569
|
+
url: '**/api/users',
|
|
570
|
+
fulfillResponse: {
|
|
571
|
+
status: 500,
|
|
572
|
+
body: { error: 'Internal server error' }
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
await page.goto('/users');
|
|
577
|
+
|
|
578
|
+
// Wait for mocked response and access parsed data
|
|
579
|
+
const { status, responseJson } = await usersCall;
|
|
580
|
+
|
|
581
|
+
expect(status).toBe(500);
|
|
582
|
+
expect(responseJson.error).toContain('Internal server');
|
|
583
|
+
await expect(page.locator('.error-message')).toContainText('Server error');
|
|
584
|
+
});
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
**Playwright Utils Benefits:**
|
|
588
|
+
- Automatic JSON parsing (`responseJson` ready to use)
|
|
589
|
+
- Returns promise with `{ status, responseJson, requestJson }`
|
|
590
|
+
- No need to pass `page` (auto-injected by fixture)
|
|
591
|
+
- Glob pattern matching (simpler than regex)
|
|
592
|
+
- Single declarative call (setup + wait in one)
|
|
593
|
+
|
|
594
|
+
## Comparison: Traditional vs Network-First
|
|
595
|
+
|
|
596
|
+
### Loading Dashboard Data
|
|
597
|
+
|
|
598
|
+
**Traditional (Flaky):**
|
|
599
|
+
```typescript
|
|
600
|
+
test('dashboard loads data', async ({ page }) => {
|
|
601
|
+
await page.goto('/dashboard');
|
|
602
|
+
await page.waitForTimeout(2000); // ❌ Magic number
|
|
603
|
+
await expect(page.locator('table tr')).toHaveCount(5);
|
|
604
|
+
});
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
**Failure modes:**
|
|
608
|
+
- API takes 2.5s → test fails
|
|
609
|
+
- API returns 3 items not 5 → hard to debug (which issue?)
|
|
610
|
+
- CI slower than local → fails in CI only
|
|
611
|
+
|
|
612
|
+
**Network-First (Deterministic):**
|
|
613
|
+
```typescript
|
|
614
|
+
test('dashboard loads data', async ({ page }) => {
|
|
615
|
+
const apiPromise = page.waitForResponse(
|
|
616
|
+
resp => resp.url().includes('/api/dashboard') && resp.ok()
|
|
617
|
+
);
|
|
618
|
+
|
|
619
|
+
await page.goto('/dashboard');
|
|
620
|
+
|
|
621
|
+
const response = await apiPromise;
|
|
622
|
+
const { items } = await response.json();
|
|
623
|
+
|
|
624
|
+
// Validate API response
|
|
625
|
+
expect(items).toHaveLength(5);
|
|
626
|
+
|
|
627
|
+
// Validate UI matches API
|
|
628
|
+
await expect(page.locator('table tr')).toHaveCount(items.length);
|
|
629
|
+
});
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
**Benefits:**
|
|
633
|
+
- Waits exactly as long as needed (100ms or 5s, doesn't matter)
|
|
634
|
+
- Validates API response (catch backend errors)
|
|
635
|
+
- Validates UI matches API (catch frontend bugs)
|
|
636
|
+
- Works in any environment (local, CI, staging)
|
|
637
|
+
|
|
638
|
+
**With Playwright Utils (Even Better):**
|
|
639
|
+
```typescript
|
|
640
|
+
import { test } from '@seontechnologies/playwright-utils/fixtures';
|
|
641
|
+
|
|
642
|
+
test('dashboard loads data', async ({ page, interceptNetworkCall }) => {
|
|
643
|
+
const dashboardCall = interceptNetworkCall({
|
|
644
|
+
method: 'GET',
|
|
645
|
+
url: '**/api/dashboard'
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
await page.goto('/dashboard');
|
|
649
|
+
|
|
650
|
+
const { status, responseJson: { items } } = await dashboardCall;
|
|
651
|
+
|
|
652
|
+
// Validate API response (automatic JSON parsing)
|
|
653
|
+
expect(status).toBe(200);
|
|
654
|
+
expect(items).toHaveLength(5);
|
|
655
|
+
|
|
656
|
+
// Validate UI matches API
|
|
657
|
+
await expect(page.locator('table tr')).toHaveCount(items.length);
|
|
658
|
+
});
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
**Additional Benefits:**
|
|
662
|
+
- No manual `await response.json()` (automatic parsing)
|
|
663
|
+
- Cleaner destructuring of nested data
|
|
664
|
+
- Consistent API across all network calls
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
### Form Submission
|
|
669
|
+
|
|
670
|
+
**Traditional (Flaky):**
|
|
671
|
+
```typescript
|
|
672
|
+
test('form submission', async ({ page }) => {
|
|
673
|
+
await page.fill('#email', 'test@example.com');
|
|
674
|
+
await page.click('button[type="submit"]');
|
|
675
|
+
await page.waitForTimeout(3000); // ❌ Hope it's enough
|
|
676
|
+
await expect(page.locator('.success')).toBeVisible();
|
|
677
|
+
});
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
**Network-First (Deterministic):**
|
|
681
|
+
```typescript
|
|
682
|
+
test('form submission', async ({ page }) => {
|
|
683
|
+
const submitPromise = page.waitForResponse(
|
|
684
|
+
resp => resp.url().includes('/api/submit') &&
|
|
685
|
+
resp.request().method() === 'POST' &&
|
|
686
|
+
resp.ok()
|
|
687
|
+
);
|
|
688
|
+
|
|
689
|
+
await page.fill('#email', 'test@example.com');
|
|
690
|
+
await page.click('button[type="submit"]');
|
|
691
|
+
|
|
692
|
+
const response = await submitPromise;
|
|
693
|
+
const result = await response.json();
|
|
694
|
+
|
|
695
|
+
expect(result.success).toBe(true);
|
|
696
|
+
await expect(page.locator('.success')).toBeVisible();
|
|
697
|
+
});
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
**With Playwright Utils:**
|
|
701
|
+
```typescript
|
|
702
|
+
import { test } from '@seontechnologies/playwright-utils/fixtures';
|
|
703
|
+
|
|
704
|
+
test('form submission', async ({ page, interceptNetworkCall }) => {
|
|
705
|
+
const submitCall = interceptNetworkCall({
|
|
706
|
+
method: 'POST',
|
|
707
|
+
url: '**/api/submit'
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
await page.getByLabel('Email').fill('test@example.com');
|
|
711
|
+
await page.getByRole('button', { name: 'Submit' }).click();
|
|
712
|
+
|
|
713
|
+
const { status, responseJson: result } = await submitCall;
|
|
714
|
+
|
|
715
|
+
// Automatic JSON parsing, no manual await
|
|
716
|
+
expect(status).toBe(200);
|
|
717
|
+
expect(result.success).toBe(true);
|
|
718
|
+
await expect(page.locator('.success')).toBeVisible();
|
|
719
|
+
});
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
**Progression:**
|
|
723
|
+
- Traditional: Hard waits (flaky)
|
|
724
|
+
- Network-First (Vanilla): waitForResponse (deterministic)
|
|
725
|
+
- Network-First (PW-Utils): interceptNetworkCall (deterministic + cleaner API)
|
|
726
|
+
|
|
727
|
+
---
|
|
728
|
+
|
|
729
|
+
## Common Misconceptions
|
|
730
|
+
|
|
731
|
+
### "I Already Use waitForSelector"
|
|
732
|
+
|
|
733
|
+
```typescript
|
|
734
|
+
// This is still a hard wait in disguise
|
|
735
|
+
await page.click('button');
|
|
736
|
+
await page.waitForSelector('.success', { timeout: 5000 });
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
**Problem:** Waiting for DOM, not for the API that caused DOM change.
|
|
740
|
+
|
|
741
|
+
**Better:**
|
|
742
|
+
```typescript
|
|
743
|
+
await page.waitForResponse(matcher); // Wait for root cause
|
|
744
|
+
await page.waitForSelector('.success'); // Then validate UI
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
### "My Tests Are Fast, Why Add Complexity?"
|
|
748
|
+
|
|
749
|
+
**Short-term:** Tests are fast locally
|
|
750
|
+
|
|
751
|
+
**Long-term problems:**
|
|
752
|
+
- Different environments (CI slower)
|
|
753
|
+
- Under load (API slower)
|
|
754
|
+
- Network variability (random)
|
|
755
|
+
- Scaling test suite (100 → 1000 tests)
|
|
756
|
+
|
|
757
|
+
**Network-first prevents these issues before they appear.**
|
|
758
|
+
|
|
759
|
+
### "Too Much Boilerplate"
|
|
760
|
+
|
|
761
|
+
**Problem:** `waitForResponse` is verbose, repeated in every test.
|
|
762
|
+
|
|
763
|
+
**Solution:** Use Playwright Utils `interceptNetworkCall` - built-in fixture that reduces boilerplate.
|
|
764
|
+
|
|
765
|
+
**Vanilla Playwright (Repetitive):**
|
|
766
|
+
```typescript
|
|
767
|
+
test('test 1', async ({ page }) => {
|
|
768
|
+
const promise = page.waitForResponse(
|
|
769
|
+
resp => resp.url().includes('/api/submit') && resp.ok()
|
|
770
|
+
);
|
|
771
|
+
await page.click('button');
|
|
772
|
+
await promise;
|
|
773
|
+
});
|
|
774
|
+
|
|
775
|
+
test('test 2', async ({ page }) => {
|
|
776
|
+
const promise = page.waitForResponse(
|
|
777
|
+
resp => resp.url().includes('/api/load') && resp.ok()
|
|
778
|
+
);
|
|
779
|
+
await page.click('button');
|
|
780
|
+
await promise;
|
|
781
|
+
});
|
|
782
|
+
// Repeated pattern in every test
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
**With Playwright Utils (Cleaner):**
|
|
786
|
+
```typescript
|
|
787
|
+
import { test } from '@seontechnologies/playwright-utils/fixtures';
|
|
788
|
+
|
|
789
|
+
test('test 1', async ({ page, interceptNetworkCall }) => {
|
|
790
|
+
const submitCall = interceptNetworkCall({ url: '**/api/submit' });
|
|
791
|
+
await page.click('button');
|
|
792
|
+
const { status, responseJson } = await submitCall;
|
|
793
|
+
expect(status).toBe(200);
|
|
794
|
+
});
|
|
795
|
+
|
|
796
|
+
test('test 2', async ({ page, interceptNetworkCall }) => {
|
|
797
|
+
const loadCall = interceptNetworkCall({ url: '**/api/load' });
|
|
798
|
+
await page.click('button');
|
|
799
|
+
const { responseJson } = await loadCall;
|
|
800
|
+
// Automatic JSON parsing, cleaner API
|
|
801
|
+
});
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
**Benefits:**
|
|
805
|
+
- Less boilerplate (fixture handles complexity)
|
|
806
|
+
- Automatic JSON parsing
|
|
807
|
+
- Glob pattern matching (`**/api/**`)
|
|
808
|
+
- Consistent API across all tests
|
|
809
|
+
|
|
810
|
+
See [Integrate Playwright Utils](/docs/how-to/customization/integrate-playwright-utils.md#intercept-network-call) for setup.
|
|
811
|
+
|
|
812
|
+
## Technical Implementation
|
|
813
|
+
|
|
814
|
+
For detailed network-first patterns, see the knowledge base:
|
|
815
|
+
- [Knowledge Base Index - Network & Reliability](/docs/reference/tea/knowledge-base.md)
|
|
816
|
+
- [Complete Knowledge Base Index](/docs/reference/tea/knowledge-base.md)
|
|
817
|
+
|
|
818
|
+
## Related Concepts
|
|
819
|
+
|
|
820
|
+
**Core TEA Concepts:**
|
|
821
|
+
- [Test Quality Standards](/docs/explanation/tea/test-quality-standards.md) - Determinism requires network-first
|
|
822
|
+
- [Risk-Based Testing](/docs/explanation/tea/risk-based-testing.md) - High-risk features need reliable tests
|
|
823
|
+
|
|
824
|
+
**Technical Patterns:**
|
|
825
|
+
- [Fixture Architecture](/docs/explanation/tea/fixture-architecture.md) - Network utilities as fixtures
|
|
826
|
+
- [Knowledge Base System](/docs/explanation/tea/knowledge-base-system.md) - Network patterns in knowledge base
|
|
827
|
+
|
|
828
|
+
**Overview:**
|
|
829
|
+
- [TEA Overview](/docs/explanation/features/tea-overview.md) - Network-first in workflows
|
|
830
|
+
- [Testing as Engineering](/docs/explanation/philosophy/testing-as-engineering.md) - Why flakiness matters
|
|
831
|
+
|
|
832
|
+
## Practical Guides
|
|
833
|
+
|
|
834
|
+
**Workflow Guides:**
|
|
835
|
+
- [How to Run Test Review](/docs/how-to/workflows/run-test-review.md) - Review for hard waits
|
|
836
|
+
- [How to Run ATDD](/docs/how-to/workflows/run-atdd.md) - Generate network-first tests
|
|
837
|
+
- [How to Run Automate](/docs/how-to/workflows/run-automate.md) - Expand with network patterns
|
|
838
|
+
|
|
839
|
+
**Use-Case Guides:**
|
|
840
|
+
- [Using TEA with Existing Tests](/docs/how-to/brownfield/use-tea-with-existing-tests.md) - Fix flaky legacy tests
|
|
841
|
+
|
|
842
|
+
**Customization:**
|
|
843
|
+
- [Integrate Playwright Utils](/docs/how-to/customization/integrate-playwright-utils.md) - Network utilities (recorder, interceptor, error monitor)
|
|
844
|
+
|
|
845
|
+
## Reference
|
|
846
|
+
|
|
847
|
+
- [TEA Command Reference](/docs/reference/tea/commands.md) - All workflows use network-first
|
|
848
|
+
- [Knowledge Base Index](/docs/reference/tea/knowledge-base.md) - Network-first fragment
|
|
849
|
+
- [Glossary](/docs/reference/glossary/index.md#test-architect-tea-concepts) - Network-first pattern term
|
|
850
|
+
|
|
851
|
+
---
|
|
852
|
+
|
|
853
|
+
Generated with [BMad Method](https://bmad-method.org) - TEA (Test Architect)
|