ma-agents 3.6.2 → 3.8.0
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/CONTRIBUTING.md +139 -0
- package/README.md +27 -11
- package/bin/cli.js +34 -10
- package/docs/deployment/vllm-nemotron.md +4 -2
- package/lib/.bmad-extension-plugin.build-1264-1777348888201/.claude-plugin/marketplace.json +109 -0
- package/lib/{bmad-extension → .bmad-extension-plugin.build-1264-1777348888201/skills}/module-help.csv +5 -5
- package/lib/.bmad-extension-plugin.build-1264-1777348888201/skills/module.yaml +20 -0
- package/lib/.bmad-extension-plugin.build-24696-1777348768444/.claude-plugin/marketplace.json +109 -0
- package/lib/.bmad-extension-plugin.build-24696-1777348768444/skills/module-help.csv +62 -0
- package/lib/.bmad-extension-plugin.build-24696-1777348768444/skills/module.yaml +20 -0
- package/lib/.bmad-extension-plugin.build-25428-1777348694953/.claude-plugin/marketplace.json +109 -0
- package/lib/.bmad-extension-plugin.build-25428-1777348694953/skills/module-help.csv +62 -0
- package/lib/.bmad-extension-plugin.build-25428-1777348694953/skills/module.yaml +20 -0
- package/lib/agents.js +36 -6
- package/lib/bmad-cache/bmb/.claude-plugin/marketplace.json +4 -11
- package/lib/bmad-cache/bmb/README.md +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/index +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-6ecd9fc6445b1281449c5ec49a6c5794708e662e.idx +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/{pack-554778ad4e7254827618ebd2497c3f4bce9054a4.pack → pack-6ecd9fc6445b1281449c5ec49a6c5794708e662e.pack} +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-6ecd9fc6445b1281449c5ec49a6c5794708e662e.rev +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/refs/tags/v1.7.0 +1 -0
- package/lib/bmad-cache/bmb/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/bmb/package-lock.json +2 -2
- package/lib/bmad-cache/bmb/package.json +2 -7
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/customize-template.toml +62 -0
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/sample-customize-analyst.toml +87 -0
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/assets/customize-template.toml +56 -0
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/assets/sample-customize-product-brief.toml +51 -0
- package/lib/bmad-cache/bmb/tools/validate-doc-links.cjs +6 -1
- package/lib/bmad-cache/bmb/website/astro.config.mjs +5 -1
- package/lib/bmad-cache/cache-manifest.json +13 -11
- package/lib/bmad-cache/cis/.claude-plugin/marketplace.json +1 -1
- package/lib/bmad-cache/cis/README.md +1 -1
- package/lib/bmad-cache/cis/_git_preserved/index +0 -0
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-cad8ff313ea5db860ddcc7780f03917dcba1da8d.idx +0 -0
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/{pack-39c4fd66f4e0eb3f4d93665318df04cd356b0297.pack → pack-cad8ff313ea5db860ddcc7780f03917dcba1da8d.pack} +0 -0
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-cad8ff313ea5db860ddcc7780f03917dcba1da8d.rev +0 -0
- package/lib/bmad-cache/cis/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/cis/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/cis/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/cis/package.json +1 -1
- package/lib/bmad-cache/cis/src/module.yaml +49 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-brainstorming-coach/customize.toml +38 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-creative-problem-solver/customize.toml +38 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-design-thinking-coach/customize.toml +39 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-innovation-strategist/customize.toml +38 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-presentation-master/customize.toml +73 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-storyteller/customize.toml +60 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-design-thinking/customize.toml +41 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-innovation-strategy/customize.toml +41 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-problem-solving/customize.toml +42 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-storytelling/customize.toml +41 -0
- package/lib/bmad-cache/cis/tools/build-docs.mjs +8 -0
- package/lib/bmad-cache/cis/website/astro.config.mjs +34 -4
- package/lib/bmad-cache/cis/website/src/content/config.ts +2 -1
- package/lib/bmad-cache/cis/website/src/content/i18n/zh-CN.json +28 -0
- package/lib/bmad-cache/cis/website/src/lib/locales.mjs +27 -0
- package/lib/bmad-cache/gds/.claude-plugin/marketplace.json +7 -6
- package/lib/bmad-cache/gds/README.md +5 -3
- package/lib/bmad-cache/gds/_git_preserved/index +0 -0
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-c1322f7c8531a89dc4f3f34c4955d194f286c1e6.idx +0 -0
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/{pack-ac967149d58fba215d07238ad8881bdbdad5c9c3.pack → pack-c1322f7c8531a89dc4f3f34c4955d194f286c1e6.pack} +0 -0
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-c1322f7c8531a89dc4f3f34c4955d194f286c1e6.rev +0 -0
- package/lib/bmad-cache/gds/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/gds/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/gds/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/gds/package.json +1 -1
- package/lib/bmad-cache/gds/src/agents/gds-agent-game-architect/customize.toml +57 -0
- package/lib/bmad-cache/gds/src/agents/gds-agent-game-designer/customize.toml +59 -0
- package/lib/bmad-cache/gds/src/agents/gds-agent-game-dev/customize.toml +129 -0
- package/lib/bmad-cache/gds/src/agents/gds-agent-game-solo-dev/customize.toml +60 -0
- package/lib/bmad-cache/gds/src/agents/gds-agent-tech-writer/customize.toml +65 -0
- package/lib/bmad-cache/gds/src/module-help.csv +4 -4
- package/lib/bmad-cache/gds/src/module.yaml +43 -1
- package/lib/bmad-cache/gds/src/workflows/1-preproduction/gds-brainstorm-game/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/1-preproduction/gds-create-game-brief/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/1-preproduction/research/gds-domain-research/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-gdd/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-narrative/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-prd/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-ux-design/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-edit-gdd/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-edit-prd/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-gdd/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-gdd/data/genre-complexity.csv +26 -0
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-prd/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-prd/data/domain-complexity.csv +15 -0
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-prd/data/project-types.csv +11 -0
- package/lib/bmad-cache/gds/src/workflows/3-technical/gds-check-implementation-readiness/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/3-technical/gds-create-epics-and-stories/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/3-technical/gds-game-architecture/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/3-technical/gds-generate-project-context/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-code-review/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-correct-course/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-create-story/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-dev-story/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-retrospective/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-sprint-planning/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-sprint-status/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-e2e-scaffold/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-performance-test/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-playtest-plan/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-test-automate/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-test-design/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-test-framework/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-test-review/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/gds-document-project/customize.toml +41 -0
- package/lib/bmad-cache/gds/src/workflows/gds-quick-flow/gds-quick-dev/customize.toml +41 -0
- package/lib/bmad-cache/tea/.claude-plugin/marketplace.json +1 -1
- package/lib/bmad-cache/tea/.github/CODE_OF_CONDUCT.md +128 -0
- package/lib/bmad-cache/tea/.github/FUNDING.yaml +15 -0
- package/lib/bmad-cache/tea/.github/ISSUE_TEMPLATE/config.yaml +11 -0
- package/lib/bmad-cache/tea/.github/ISSUE_TEMPLATE/feature_request.md +70 -0
- package/lib/bmad-cache/tea/.github/ISSUE_TEMPLATE/issue.md +61 -0
- package/lib/bmad-cache/tea/.github/workflows/docs.yaml +66 -0
- package/lib/bmad-cache/tea/.github/workflows/manual-release.yaml +216 -0
- package/lib/bmad-cache/tea/.github/workflows/quality.yaml +117 -0
- package/lib/bmad-cache/tea/.vscode/settings.json +47 -0
- package/lib/bmad-cache/tea/README.md +63 -55
- package/lib/bmad-cache/tea/_git_preserved/index +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-9b16db8eb5022c18cef1f0a27d63b6e0f4bc2b2a.idx +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/{pack-e75385cd52b693dbb8a3b2afb50058952543b3a2.pack → pack-9b16db8eb5022c18cef1f0a27d63b6e0f4bc2b2a.pack} +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-9b16db8eb5022c18cef1f0a27d63b6e0f4bc2b2a.rev +0 -0
- package/lib/bmad-cache/tea/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/tea/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/tea/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/tea/docs/explanation/engagement-models.md +1 -1
- package/lib/bmad-cache/tea/docs/explanation/tea-overview.md +1 -1
- package/lib/bmad-cache/tea/docs/glossary/index.md +1 -1
- package/lib/bmad-cache/tea/docs/how-to/customization/extend-tea-with-custom-workflows.md +29 -0
- package/lib/bmad-cache/tea/docs/how-to/workflows/run-trace.md +27 -20
- package/lib/bmad-cache/tea/docs/how-to/workflows/teach-me-testing.md +2 -2
- package/lib/bmad-cache/tea/docs/reference/commands.md +3 -3
- package/lib/bmad-cache/tea/docs/reference/troubleshooting.md +36 -0
- package/lib/bmad-cache/tea/docs/tutorials/learn-testing-tea-academy.md +1 -1
- package/lib/bmad-cache/tea/package-lock.json +2 -2
- package/lib/bmad-cache/tea/package.json +3 -3
- package/lib/bmad-cache/tea/src/agents/bmad-tea/SKILL.md +54 -44
- package/lib/bmad-cache/tea/src/agents/bmad-tea/customize.toml +104 -0
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/contract-testing.md +32 -15
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pact-broker-webhooks.md +237 -0
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pact-consumer-framework-setup.md +134 -12
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pact-mcp.md +1 -0
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-consumer-helpers.md +111 -1
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-overview.md +15 -12
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-provider-verifier.md +83 -1
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-zod-to-pact.md +262 -0
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-module-setup.md +122 -0
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-providers.md +155 -0
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-risk-guidance.md +114 -0
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-template-matchers.md +160 -0
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-testing-fundamentals.md +42 -0
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-timeout-error.md +130 -0
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-waiting-querying.md +167 -0
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/tea-index.csv +13 -4
- package/lib/bmad-cache/tea/src/module.yaml +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/README.md +5 -3
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/SKILL.md +124 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/checklist.md +3 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/customize.toml +40 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/instructions.md +7 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-01-init.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-01b-continue.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-02-assess.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-01.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-02.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-03.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-04.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-05.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-06.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-07.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-05-completion.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-e/step-e-01-assess-workflow.md +2 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-e/step-e-02-apply-edits.md +9 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-v/step-v-01-validate.md +12 -3
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/SKILL.md +80 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/customize.toml +40 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/instructions.md +2 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/contract-testing.md +32 -15
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pact-broker-webhooks.md +237 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pact-consumer-framework-setup.md +134 -12
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pact-mcp.md +1 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pactjs-utils-consumer-helpers.md +111 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pactjs-utils-overview.md +15 -12
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pactjs-utils-provider-verifier.md +83 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pactjs-utils-zod-to-pact.md +262 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-module-setup.md +122 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-providers.md +155 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-risk-guidance.md +114 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-template-matchers.md +160 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-testing-fundamentals.md +42 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-timeout-error.md +130 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-waiting-querying.md +167 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/tea-index.csv +13 -4
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-01-preflight-and-context.md +3 -3
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-02-generation-mode.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-03-test-strategy.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04-generate-tests.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04a-subagent-api-failing.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04c-aggregate.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-05-validate-and-complete.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-e/step-01-assess.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-e/step-02-apply-edit.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-v/step-01-validate.md +9 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/SKILL.md +80 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/customize.toml +40 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/instructions.md +2 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/contract-testing.md +18 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pact-broker-webhooks.md +237 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pact-consumer-framework-setup.md +134 -12
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pact-mcp.md +1 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pactjs-utils-consumer-helpers.md +111 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pactjs-utils-provider-verifier.md +83 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-module-setup.md +122 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-providers.md +155 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-risk-guidance.md +114 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-template-matchers.md +160 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-testing-fundamentals.md +42 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-timeout-error.md +130 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-waiting-querying.md +167 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/tea-index.csv +12 -4
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-01-preflight-and-context.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-02-identify-targets.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-03-generate-tests.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-03a-subagent-api.md +9 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-03c-aggregate.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-04-validate-and-summarize.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-e/step-01-assess.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-e/step-02-apply-edit.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-v/step-01-validate.md +9 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/SKILL.md +80 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/customize.toml +40 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/instructions.md +2 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/contract-testing.md +18 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pact-broker-webhooks.md +237 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pact-consumer-framework-setup.md +134 -12
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pact-mcp.md +1 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pactjs-utils-consumer-helpers.md +111 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pactjs-utils-provider-verifier.md +83 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-module-setup.md +122 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-providers.md +155 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-risk-guidance.md +114 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-template-matchers.md +160 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-testing-fundamentals.md +42 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-timeout-error.md +130 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-waiting-querying.md +167 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/tea-index.csv +12 -4
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-c/step-01-preflight.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-c/step-02-generate-pipeline.md +15 -7
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-c/step-03-configure-quality-gates.md +7 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-c/step-04-validate-and-summary.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-e/step-01-assess.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-e/step-02-apply-edit.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-v/step-01-validate.md +9 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/SKILL.md +80 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/customize.toml +40 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/instructions.md +2 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/contract-testing.md +18 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pact-broker-webhooks.md +237 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pact-consumer-framework-setup.md +134 -12
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pact-mcp.md +1 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pactjs-utils-consumer-helpers.md +111 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pactjs-utils-provider-verifier.md +83 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-module-setup.md +122 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-providers.md +155 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-risk-guidance.md +114 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-template-matchers.md +160 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-testing-fundamentals.md +42 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-timeout-error.md +130 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-waiting-querying.md +167 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/tea-index.csv +12 -4
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-c/step-01-preflight.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-c/step-02-select-framework.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-c/step-03-scaffold-framework.md +11 -7
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-c/step-04-docs-and-scripts.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-c/step-05-validate-and-summary.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-e/step-01-assess.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-e/step-02-apply-edit.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-v/step-01-validate.md +9 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/SKILL.md +80 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/customize.toml +40 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/instructions.md +2 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/contract-testing.md +18 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pact-broker-webhooks.md +237 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pact-consumer-framework-setup.md +134 -12
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pact-mcp.md +1 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pactjs-utils-consumer-helpers.md +111 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pactjs-utils-provider-verifier.md +83 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-module-setup.md +122 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-providers.md +155 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-risk-guidance.md +114 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-template-matchers.md +160 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-testing-fundamentals.md +42 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-timeout-error.md +130 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-waiting-querying.md +167 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/tea-index.csv +12 -4
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-01-load-context.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-02-define-thresholds.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-03-gather-evidence.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04-evaluate-and-score.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04e-aggregate-nfr.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-05-generate-report.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-e/step-01-assess.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-e/step-02-apply-edit.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-v/step-01-validate.md +9 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/SKILL.md +82 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/customize.toml +40 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/instructions.md +2 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/contract-testing.md +18 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pact-broker-webhooks.md +237 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pact-consumer-framework-setup.md +134 -12
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pact-mcp.md +1 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pactjs-utils-consumer-helpers.md +111 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pactjs-utils-provider-verifier.md +83 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-module-setup.md +122 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-providers.md +155 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-risk-guidance.md +114 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-template-matchers.md +160 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-testing-fundamentals.md +42 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-timeout-error.md +130 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-waiting-querying.md +167 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/tea-index.csv +12 -4
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-01-detect-mode.md +7 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-01b-resume.md +29 -15
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-02-load-context.md +7 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-03-risk-and-testability.md +7 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-04-coverage-plan.md +7 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-05-generate-output.md +14 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-e/step-01-assess.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-e/step-02-apply-edit.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-v/step-01-validate.md +9 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/test-design-architecture-template.md +3 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/test-design-qa-template.md +3 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/test-design-template.md +3 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/SKILL.md +80 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/customize.toml +40 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/instructions.md +2 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/contract-testing.md +18 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pact-broker-webhooks.md +237 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pact-consumer-framework-setup.md +134 -12
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pact-mcp.md +1 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pactjs-utils-consumer-helpers.md +111 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pactjs-utils-provider-verifier.md +83 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-module-setup.md +122 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-providers.md +155 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-risk-guidance.md +114 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-template-matchers.md +160 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-testing-fundamentals.md +42 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-timeout-error.md +130 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-waiting-querying.md +167 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/tea-index.csv +12 -4
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-01-load-context.md +3 -3
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-02-discover-tests.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-03-quality-evaluation.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-03a-subagent-determinism.md +43 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-03f-aggregate-scores.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-04-generate-report.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-e/step-01-assess.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-e/step-02-apply-edit.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-v/step-01-validate.md +9 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/SKILL.md +82 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/checklist.md +42 -18
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/customize.toml +40 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/instructions.md +6 -4
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/contract-testing.md +18 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pact-broker-webhooks.md +237 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pact-consumer-framework-setup.md +134 -12
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pact-mcp.md +1 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pactjs-utils-consumer-helpers.md +111 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pactjs-utils-provider-verifier.md +83 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-module-setup.md +122 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-providers.md +155 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-risk-guidance.md +114 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-template-matchers.md +160 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-testing-fundamentals.md +42 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-timeout-error.md +130 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-waiting-querying.md +167 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/tea-index.csv +12 -4
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-01-load-context.md +74 -13
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-01b-resume.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-02-discover-tests.md +24 -4
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-03-map-criteria.md +15 -11
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-04-analyze-gaps.md +210 -3
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-05-gate-decision.md +477 -62
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-e/step-01-assess.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-e/step-02-apply-edit.md +8 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-v/step-01-validate.md +9 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/trace-template.md +10 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/workflow-plan.md +14 -11
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/workflow.yaml +24 -0
- package/lib/bmad-cache/tea/test/test-installation-components.js +210 -66
- package/lib/bmad-cache/tea/test/test-knowledge-base.js +6 -1
- package/lib/bmad-cache/tea/test/test-release-metadata.js +71 -0
- package/lib/bmad-cache/tea/tools/validate-agent-schema.js +73 -0
- package/lib/bmad-customize/bmm-qa.customize.yaml +1 -1
- package/lib/bmad-extension/.claude-plugin/marketplace.json.template +117 -0
- package/lib/bmad-extension/skills/ma-agent-cyber/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ma-agent-cyber/SKILL.md +49 -0
- package/lib/bmad-extension/skills/ma-agent-cyber/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-extension/skills/ma-agent-devops/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ma-agent-devops/SKILL.md +49 -0
- package/lib/bmad-extension/skills/ma-agent-devops/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-extension/skills/ma-agent-ml/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ma-agent-ml/SKILL.md +59 -0
- package/lib/bmad-extension/skills/ma-agent-ml/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-extension/skills/ma-agent-sqa/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ma-agent-sqa/SKILL.md +59 -0
- package/lib/bmad-extension/skills/ma-agent-sqa/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-extension/skills/ma-agent-sre/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ma-agent-sre/SKILL.md +49 -0
- package/lib/bmad-extension/skills/ma-agent-sre/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-extension/skills/module-help.csv +62 -0
- package/lib/bmad-extension/skills/module.yaml +20 -0
- package/lib/bmad-extension-plugin/.claude-plugin/marketplace.json +109 -0
- package/lib/bmad-extension-plugin/skills/add-sprint/SKILL.md +175 -0
- package/lib/bmad-extension-plugin/skills/add-sprint/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/add-to-sprint/SKILL.md +243 -0
- package/lib/bmad-extension-plugin/skills/add-to-sprint/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/bmad-dev-story/SKILL.md +6 -0
- package/lib/bmad-extension-plugin/skills/bmad-dev-story/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/bmad-dev-story/checklist.md +80 -0
- package/lib/bmad-extension-plugin/skills/bmad-dev-story/workflow.md +509 -0
- package/lib/bmad-extension-plugin/skills/bmad-sprint-planning/SKILL.md +6 -0
- package/lib/bmad-extension-plugin/skills/bmad-sprint-planning/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/bmad-sprint-planning/checklist.md +74 -0
- package/lib/bmad-extension-plugin/skills/bmad-sprint-planning/sprint-status-template.yaml +89 -0
- package/lib/bmad-extension-plugin/skills/bmad-sprint-planning/workflow.md +372 -0
- package/lib/bmad-extension-plugin/skills/bmad-sprint-status/SKILL.md +6 -0
- package/lib/bmad-extension-plugin/skills/bmad-sprint-status/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/bmad-sprint-status/workflow.md +434 -0
- package/lib/bmad-extension-plugin/skills/cleanup-done/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/cleanup-done/SKILL.md +215 -0
- package/lib/bmad-extension-plugin/skills/cleanup-done/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/close-sprint/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/close-sprint/SKILL.md +379 -0
- package/lib/bmad-extension-plugin/skills/close-sprint/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/create-bug-story/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/create-bug-story/SKILL.md +195 -0
- package/lib/bmad-extension-plugin/skills/create-bug-story/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/cyber-generate-certs/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/cyber-generate-certs/SKILL.md +27 -0
- package/lib/bmad-extension-plugin/skills/cyber-generate-certs/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/cyber-immunity-estimation/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/cyber-immunity-estimation/SKILL.md +29 -0
- package/lib/bmad-extension-plugin/skills/cyber-immunity-estimation/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/cyber-security-audit/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/cyber-security-audit/SKILL.md +27 -0
- package/lib/bmad-extension-plugin/skills/cyber-security-audit/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/cyber-vault-secrets/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/cyber-vault-secrets/SKILL.md +28 -0
- package/lib/bmad-extension-plugin/skills/cyber-vault-secrets/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/cyber-verify-docker-users/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/cyber-verify-docker-users/SKILL.md +23 -0
- package/lib/bmad-extension-plugin/skills/cyber-verify-docker-users/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/cyber-verify-image-signature/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/cyber-verify-image-signature/SKILL.md +22 -0
- package/lib/bmad-extension-plugin/skills/cyber-verify-image-signature/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/cyber-vulnerability-scan/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/cyber-vulnerability-scan/SKILL.md +28 -0
- package/lib/bmad-extension-plugin/skills/cyber-vulnerability-scan/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/devops-configure-infrastructure/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/devops-configure-infrastructure/SKILL.md +27 -0
- package/lib/bmad-extension-plugin/skills/devops-configure-infrastructure/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/devops-disconnected-deployment/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/devops-disconnected-deployment/SKILL.md +27 -0
- package/lib/bmad-extension-plugin/skills/devops-disconnected-deployment/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/devops-docker-compose-setup/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/devops-docker-compose-setup/SKILL.md +26 -0
- package/lib/bmad-extension-plugin/skills/devops-docker-compose-setup/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/devops-manage-helm/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/devops-manage-helm/SKILL.md +28 -0
- package/lib/bmad-extension-plugin/skills/devops-manage-helm/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/devops-sign-docker-image/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/devops-sign-docker-image/SKILL.md +24 -0
- package/lib/bmad-extension-plugin/skills/devops-sign-docker-image/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/generate-backlog/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/generate-backlog/SKILL.md +195 -0
- package/lib/bmad-extension-plugin/skills/generate-backlog/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ma-agent-cyber/.gitkeep +0 -0
- package/lib/{bmad-extension/skills/bmad-ma-agent-cyber → bmad-extension-plugin/skills/ma-agent-cyber}/SKILL.md +1 -1
- package/lib/{bmad-extension/skills/bmad-ma-agent-cyber → bmad-extension-plugin/skills/ma-agent-cyber}/bmad-skill-manifest.yaml +1 -1
- package/lib/bmad-extension-plugin/skills/ma-agent-devops/.gitkeep +0 -0
- package/lib/{bmad-extension/skills/bmad-ma-agent-devops → bmad-extension-plugin/skills/ma-agent-devops}/SKILL.md +1 -1
- package/lib/{bmad-extension/skills/bmad-ma-agent-devops → bmad-extension-plugin/skills/ma-agent-devops}/bmad-skill-manifest.yaml +1 -1
- package/lib/bmad-extension-plugin/skills/ma-agent-ml/.gitkeep +0 -0
- package/lib/{bmad-extension/skills/bmad-ma-agent-ml → bmad-extension-plugin/skills/ma-agent-ml}/SKILL.md +1 -1
- package/lib/{bmad-extension/skills/bmad-ma-agent-ml → bmad-extension-plugin/skills/ma-agent-ml}/bmad-skill-manifest.yaml +1 -1
- package/lib/bmad-extension-plugin/skills/ma-agent-sqa/.gitkeep +0 -0
- package/lib/{bmad-extension/skills/bmad-ma-agent-sqa → bmad-extension-plugin/skills/ma-agent-sqa}/SKILL.md +1 -1
- package/lib/{bmad-extension/skills/bmad-ma-agent-sqa → bmad-extension-plugin/skills/ma-agent-sqa}/bmad-skill-manifest.yaml +1 -1
- package/lib/bmad-extension-plugin/skills/ma-agent-sre/.gitkeep +0 -0
- package/lib/{bmad-extension/skills/bmad-ma-agent-sre → bmad-extension-plugin/skills/ma-agent-sre}/SKILL.md +1 -1
- package/lib/{bmad-extension/skills/bmad-ma-agent-sre → bmad-extension-plugin/skills/ma-agent-sre}/bmad-skill-manifest.yaml +1 -1
- package/lib/bmad-extension-plugin/skills/mil498-ocd/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/mil498-ocd/SKILL.md +30 -0
- package/lib/bmad-extension-plugin/skills/mil498-ocd/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension-plugin/skills/mil498-ocd/prompts/01-discover-project-artifacts.md +26 -0
- package/lib/bmad-extension-plugin/skills/mil498-ocd/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension-plugin/skills/mil498-ocd/prompts/03-generate-document.md +90 -0
- package/lib/bmad-extension-plugin/skills/mil498-ocd/prompts/04-validate.md +14 -0
- package/lib/bmad-extension-plugin/skills/mil498-ocd/prompts/05-review.md +15 -0
- package/lib/bmad-extension-plugin/skills/mil498-ocd/prompts/06-save.md +15 -0
- package/lib/bmad-extension-plugin/skills/mil498-ocd/template.md +169 -0
- package/lib/bmad-extension-plugin/skills/mil498-requirement-quality/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/mil498-requirement-quality/SKILL.md +105 -0
- package/lib/bmad-extension-plugin/skills/mil498-requirement-quality/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdd/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdd/SKILL.md +30 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdd/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdd/prompts/01-discover-project-artifacts.md +50 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdd/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdd/prompts/03-generate-document.md +98 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdd/prompts/04-validate.md +16 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdd/prompts/05-review.md +15 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdd/prompts/06-save.md +19 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdd/template.md +163 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdp/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdp/SKILL.md +30 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdp/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdp/prompts/01-discover-project-artifacts.md +32 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdp/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdp/prompts/03-generate-document.md +187 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdp/prompts/04-validate.md +13 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdp/prompts/05-review.md +15 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdp/prompts/06-save.md +14 -0
- package/lib/bmad-extension-plugin/skills/mil498-sdp/template.md +307 -0
- package/lib/bmad-extension-plugin/skills/mil498-srs/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/mil498-srs/SKILL.md +30 -0
- package/lib/bmad-extension-plugin/skills/mil498-srs/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension-plugin/skills/mil498-srs/prompts/01-discover-project-artifacts.md +42 -0
- package/lib/bmad-extension-plugin/skills/mil498-srs/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension-plugin/skills/mil498-srs/prompts/03-generate-document.md +100 -0
- package/lib/bmad-extension-plugin/skills/mil498-srs/prompts/04-validate.md +16 -0
- package/lib/bmad-extension-plugin/skills/mil498-srs/prompts/05-review.md +15 -0
- package/lib/bmad-extension-plugin/skills/mil498-srs/prompts/06-save.md +18 -0
- package/lib/bmad-extension-plugin/skills/mil498-srs/template.md +219 -0
- package/lib/bmad-extension-plugin/skills/mil498-ssdd/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/mil498-ssdd/SKILL.md +32 -0
- package/lib/bmad-extension-plugin/skills/mil498-ssdd/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension-plugin/skills/mil498-ssdd/prompts/01-discover-project-artifacts.md +32 -0
- package/lib/bmad-extension-plugin/skills/mil498-ssdd/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension-plugin/skills/mil498-ssdd/prompts/03-csci-discovery-interview.md +43 -0
- package/lib/bmad-extension-plugin/skills/mil498-ssdd/prompts/04-generate-document.md +96 -0
- package/lib/bmad-extension-plugin/skills/mil498-ssdd/prompts/05-validate.md +18 -0
- package/lib/bmad-extension-plugin/skills/mil498-ssdd/prompts/06-review.md +16 -0
- package/lib/bmad-extension-plugin/skills/mil498-ssdd/prompts/07-save.md +16 -0
- package/lib/bmad-extension-plugin/skills/mil498-ssdd/template.md +154 -0
- package/lib/bmad-extension-plugin/skills/mil498-sss/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/mil498-sss/SKILL.md +31 -0
- package/lib/bmad-extension-plugin/skills/mil498-sss/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension-plugin/skills/mil498-sss/prompts/01-discover-project-artifacts.md +31 -0
- package/lib/bmad-extension-plugin/skills/mil498-sss/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension-plugin/skills/mil498-sss/prompts/03-generate-document.md +108 -0
- package/lib/bmad-extension-plugin/skills/mil498-sss/prompts/04-validate.md +16 -0
- package/lib/bmad-extension-plugin/skills/mil498-sss/prompts/05-review.md +15 -0
- package/lib/bmad-extension-plugin/skills/mil498-sss/prompts/06-save.md +15 -0
- package/lib/bmad-extension-plugin/skills/mil498-sss/template.md +225 -0
- package/lib/bmad-extension-plugin/skills/mil498-std/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/mil498-std/SKILL.md +30 -0
- package/lib/bmad-extension-plugin/skills/mil498-std/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension-plugin/skills/mil498-std/prompts/01-discover-project-artifacts.md +42 -0
- package/lib/bmad-extension-plugin/skills/mil498-std/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension-plugin/skills/mil498-std/prompts/03-generate-document.md +117 -0
- package/lib/bmad-extension-plugin/skills/mil498-std/prompts/04-validate.md +15 -0
- package/lib/bmad-extension-plugin/skills/mil498-std/prompts/05-review.md +15 -0
- package/lib/bmad-extension-plugin/skills/mil498-std/prompts/06-save.md +15 -0
- package/lib/bmad-extension-plugin/skills/mil498-std/template.md +188 -0
- package/lib/bmad-extension-plugin/skills/ml-advise/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/ml-advise/SKILL.md +76 -0
- package/lib/bmad-extension-plugin/skills/ml-advise/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ml-advise/skill.json +7 -0
- package/lib/bmad-extension-plugin/skills/ml-analysis/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/ml-analysis/SKILL.md +60 -0
- package/lib/bmad-extension-plugin/skills/ml-analysis/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ml-analysis/skill.json +7 -0
- package/lib/bmad-extension-plugin/skills/ml-architecture/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/ml-architecture/SKILL.md +55 -0
- package/lib/bmad-extension-plugin/skills/ml-architecture/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ml-architecture/skill.json +7 -0
- package/lib/bmad-extension-plugin/skills/ml-detailed-design/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/ml-detailed-design/SKILL.md +67 -0
- package/lib/bmad-extension-plugin/skills/ml-detailed-design/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ml-detailed-design/skill.json +7 -0
- package/lib/bmad-extension-plugin/skills/ml-eda/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/ml-eda/SKILL.md +56 -0
- package/lib/bmad-extension-plugin/skills/ml-eda/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ml-eda/scripts/baseline_classifier.py +522 -0
- package/lib/bmad-extension-plugin/skills/ml-eda/scripts/class_weights_calculator.py +295 -0
- package/lib/bmad-extension-plugin/skills/ml-eda/scripts/clustering_explorer.py +383 -0
- package/lib/bmad-extension-plugin/skills/ml-eda/scripts/eda_analyzer.py +654 -0
- package/lib/bmad-extension-plugin/skills/ml-eda/skill.json +7 -0
- package/lib/bmad-extension-plugin/skills/ml-experiment/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/ml-experiment/SKILL.md +74 -0
- package/lib/bmad-extension-plugin/skills/ml-experiment/assets/advanced_trainer_configs.py +430 -0
- package/lib/bmad-extension-plugin/skills/ml-experiment/assets/quick_trainer_setup.py +233 -0
- package/lib/bmad-extension-plugin/skills/ml-experiment/assets/template_datamodule.py +219 -0
- package/lib/bmad-extension-plugin/skills/ml-experiment/assets/template_gnn_module.py +341 -0
- package/lib/bmad-extension-plugin/skills/ml-experiment/assets/template_lightning_module.py +158 -0
- package/lib/bmad-extension-plugin/skills/ml-experiment/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ml-experiment/skill.json +7 -0
- package/lib/bmad-extension-plugin/skills/ml-hparam/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/ml-hparam/SKILL.md +81 -0
- package/lib/bmad-extension-plugin/skills/ml-hparam/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ml-hparam/skill.json +7 -0
- package/lib/bmad-extension-plugin/skills/ml-ideation/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/ml-ideation/SKILL.md +50 -0
- package/lib/bmad-extension-plugin/skills/ml-ideation/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ml-ideation/scripts/validate_ml_prd.py +287 -0
- package/lib/bmad-extension-plugin/skills/ml-ideation/skill.json +7 -0
- package/lib/bmad-extension-plugin/skills/ml-infra/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/ml-infra/SKILL.md +58 -0
- package/lib/bmad-extension-plugin/skills/ml-infra/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ml-infra/skill.json +7 -0
- package/lib/bmad-extension-plugin/skills/ml-retrospective/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/ml-retrospective/SKILL.md +63 -0
- package/lib/bmad-extension-plugin/skills/ml-retrospective/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ml-retrospective/skill.json +7 -0
- package/lib/bmad-extension-plugin/skills/ml-revision/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/ml-revision/SKILL.md +82 -0
- package/lib/bmad-extension-plugin/skills/ml-revision/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ml-revision/skill.json +7 -0
- package/lib/bmad-extension-plugin/skills/ml-techspec/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/ml-techspec/SKILL.md +80 -0
- package/lib/bmad-extension-plugin/skills/ml-techspec/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/ml-techspec/skill.json +7 -0
- package/lib/bmad-extension-plugin/skills/modify-sprint/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/modify-sprint/SKILL.md +311 -0
- package/lib/bmad-extension-plugin/skills/modify-sprint/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/module-help.csv +62 -0
- package/lib/bmad-extension-plugin/skills/module.yaml +20 -0
- package/lib/bmad-extension-plugin/skills/prioritize-backlog/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/prioritize-backlog/SKILL.md +217 -0
- package/lib/bmad-extension-plugin/skills/prioritize-backlog/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/project-context-expansion/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/project-context-expansion/SKILL.md +238 -0
- package/lib/bmad-extension-plugin/skills/project-context-expansion/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/remove-from-sprint/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/remove-from-sprint/SKILL.md +184 -0
- package/lib/bmad-extension-plugin/skills/remove-from-sprint/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/sprint-status-view/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/sprint-status-view/SKILL.md +177 -0
- package/lib/bmad-extension-plugin/skills/sprint-status-view/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/sqa-audit/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/sqa-audit/SKILL.md +279 -0
- package/lib/bmad-extension-plugin/skills/sqa-audit/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/sqa-ieee12207/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/sqa-ieee12207/SKILL.md +374 -0
- package/lib/bmad-extension-plugin/skills/sqa-ieee12207/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/sqa-requirements-quality/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/sqa-requirements-quality/SKILL.md +244 -0
- package/lib/bmad-extension-plugin/skills/sqa-requirements-quality/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/sre-check-deployment-status/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/sre-check-deployment-status/SKILL.md +32 -0
- package/lib/bmad-extension-plugin/skills/sre-check-deployment-status/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/sre-check-secrets/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/sre-check-secrets/SKILL.md +23 -0
- package/lib/bmad-extension-plugin/skills/sre-check-secrets/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/sre-check-system-status/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/sre-check-system-status/SKILL.md +27 -0
- package/lib/bmad-extension-plugin/skills/sre-check-system-status/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/sre-day-2-ops/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/sre-day-2-ops/SKILL.md +26 -0
- package/lib/bmad-extension-plugin/skills/sre-day-2-ops/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/sre-deployment-strategies/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/sre-deployment-strategies/SKILL.md +28 -0
- package/lib/bmad-extension-plugin/skills/sre-deployment-strategies/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/sre-fix-deployments/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/sre-fix-deployments/SKILL.md +25 -0
- package/lib/bmad-extension-plugin/skills/sre-fix-deployments/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension-plugin/skills/sre-gitops-status/.gitkeep +0 -0
- package/lib/bmad-extension-plugin/skills/sre-gitops-status/SKILL.md +25 -0
- package/lib/bmad-extension-plugin/skills/sre-gitops-status/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad.js +1379 -372
- package/lib/installer.js +362 -2
- package/package.json +23 -5
- package/scripts/build-bmad-cache.js +250 -47
- package/scripts/build-plugin.js +574 -0
- package/.ma-agents.json +0 -10
- package/AGENTS.md +0 -97
- package/AiAudit.md +0 -12
- package/DEVELOPMENT.md +0 -173
- package/MANIFEST.yaml +0 -3
- package/_bmad-output/implementation-artifacts/16-4-validation-report.md +0 -79
- package/_bmad-output/implementation-artifacts/17-10-rework-generate-backlog.md +0 -237
- package/_bmad-output/implementation-artifacts/17-11-rework-add-to-sprint.md +0 -339
- package/_bmad-output/implementation-artifacts/17-12-rework-remove-from-sprint.md +0 -348
- package/_bmad-output/implementation-artifacts/17-13-rework-sprint-status-view.md +0 -383
- package/_bmad-output/implementation-artifacts/17-14-rework-cleanup-done.md +0 -348
- package/_bmad-output/implementation-artifacts/17-15-rework-bmad-sprint-planning.md +0 -385
- package/_bmad-output/implementation-artifacts/17-16-rework-add-sprint.md +0 -362
- package/_bmad-output/implementation-artifacts/17-17-rework-modify-sprint.md +0 -477
- package/_bmad-output/implementation-artifacts/17-18-rework-bmad-dev-story.md +0 -377
- package/_bmad-output/implementation-artifacts/17-19-rework-story-status-lookup.md +0 -301
- package/_bmad-output/implementation-artifacts/17-20-rework-bmad-sprint-status.md +0 -508
- package/_bmad-output/implementation-artifacts/17-21-new-close-sprint.md +0 -455
- package/_bmad-output/implementation-artifacts/17-22-jira-adapter-pattern.md +0 -325
- package/_bmad-output/implementation-artifacts/17-23-migration-deprecation-old-files.md +0 -403
- package/_bmad-output/implementation-artifacts/17-24-rework-prioritize-backlog.md +0 -344
- package/_bmad-output/implementation-artifacts/17-9-unified-sprint-status-schema.md +0 -279
- package/_bmad-output/implementation-artifacts/19-1-knowledge-graph-core-library.md +0 -239
- package/_bmad-output/implementation-artifacts/19-2-graph-emission-create-prd.md +0 -171
- package/_bmad-output/implementation-artifacts/19-3-graph-emission-create-architecture-epics.md +0 -179
- package/_bmad-output/implementation-artifacts/19-4-graph-emission-create-story-remaining.md +0 -190
- package/_bmad-output/implementation-artifacts/19-5-open-graph-skill.md +0 -213
- package/_bmad-output/implementation-artifacts/19-6-interactive-visualization-renderer.md +0 -259
- package/_bmad-output/implementation-artifacts/19-7-llm-writability-validation-tests.md +0 -280
- package/_bmad-output/implementation-artifacts/21-1-install-time-profile-prompt.md +0 -181
- package/_bmad-output/implementation-artifacts/21-10-profile-reconfigure.md +0 -161
- package/_bmad-output/implementation-artifacts/21-11-profile-uninstall.md +0 -150
- package/_bmad-output/implementation-artifacts/21-2-universal-instruction-block-expansion.md +0 -253
- package/_bmad-output/implementation-artifacts/21-3-roomodes-template-bmad-modes.md +0 -229
- package/_bmad-output/implementation-artifacts/21-4-agents-md-template-opencode.md +0 -275
- package/_bmad-output/implementation-artifacts/21-5-clinerules-template-extension.md +0 -221
- package/_bmad-output/implementation-artifacts/21-6-onprem-layered-guardrails.md +0 -287
- package/_bmad-output/implementation-artifacts/21-7-bmad-persona-phase-prefix.md +0 -258
- package/_bmad-output/implementation-artifacts/21-8-vllm-reference-doc-readme.md +0 -158
- package/_bmad-output/implementation-artifacts/21-9-tests-validation.md +0 -368
- package/_bmad-output/implementation-artifacts/4-1-vs-agent-registry-entry.md +0 -173
- package/_bmad-output/implementation-artifacts/4-2-vs-skill-template-format.md +0 -129
- package/_bmad-output/implementation-artifacts/5-5-explicit-parameter-passing.md +0 -274
- package/_bmad-output/implementation-artifacts/5-6-fix-space-in-path-bug.md +0 -186
- package/_bmad-output/implementation-artifacts/7-1-test-infrastructure-setup.md +0 -144
- package/_bmad-output/implementation-artifacts/7-2-installer-pipeline-tests.md +0 -132
- package/_bmad-output/implementation-artifacts/7-3-bmad-pipeline-tests.md +0 -119
- package/_bmad-output/implementation-artifacts/7-4-cli-command-routing-tests.md +0 -162
- package/_bmad-output/implementation-artifacts/bug-bmad-recompile-fails-on-airgapped-network.md +0 -112
- package/_bmad-output/implementation-artifacts/bug-experimentalwarning-about-commonjs-loading-es-module-during-install.md +0 -57
- package/_bmad-output/implementation-artifacts/deferred-work.md +0 -9
- package/_bmad-output/implementation-artifacts/done/1-1-ci-cd-yes-flag.md +0 -200
- package/_bmad-output/implementation-artifacts/done/10-1-ensure-bmad-output-not-gitignored.md +0 -172
- package/_bmad-output/implementation-artifacts/done/10-2-document-bmad-output-policy.md +0 -102
- package/_bmad-output/implementation-artifacts/done/11-1-auto-bug-detection-skill.md +0 -119
- package/_bmad-output/implementation-artifacts/done/11-2-bug-story-extension-workflow.md +0 -132
- package/_bmad-output/implementation-artifacts/done/11-3-integrate-bug-detection-code-review.md +0 -111
- package/_bmad-output/implementation-artifacts/done/12-1-add-sprint-workflow.md +0 -126
- package/_bmad-output/implementation-artifacts/done/12-2-add-to-sprint-workflow.md +0 -137
- package/_bmad-output/implementation-artifacts/done/12-3-modify-sprint-workflow.md +0 -127
- package/_bmad-output/implementation-artifacts/done/12-4-sprint-status-assigned-items.md +0 -129
- package/_bmad-output/implementation-artifacts/done/13-1-project-context-template-and-generator.md +0 -179
- package/_bmad-output/implementation-artifacts/done/13-2-install-pipeline-integration.md +0 -138
- package/_bmad-output/implementation-artifacts/done/13-3-bmad-critical-actions-update.md +0 -150
- package/_bmad-output/implementation-artifacts/done/13-4-retrospective-expansion-trigger.md +0 -128
- package/_bmad-output/implementation-artifacts/done/13-5-document-project-context-generation.md +0 -118
- package/_bmad-output/implementation-artifacts/done/15-1-bump-bmad-method-to-6-2-1.md +0 -132
- package/_bmad-output/implementation-artifacts/done/15-2-restructure-extension-module.md +0 -174
- package/_bmad-output/implementation-artifacts/done/15-3-convert-custom-agents-to-skill-folders.md +0 -183
- package/_bmad-output/implementation-artifacts/done/15-4-convert-mil498-workflows-to-skill-md.md +0 -252
- package/_bmad-output/implementation-artifacts/done/15-5-convert-sre-devops-cyber-workflows.md +0 -232
- package/_bmad-output/implementation-artifacts/done/15-6-separate-built-in-agent-customizations.md +0 -163
- package/_bmad-output/implementation-artifacts/done/15-7-migration-detection-and-upgrade-path.md +0 -133
- package/_bmad-output/implementation-artifacts/done/15-8-validate-migrated-agents-and-workflows.md +0 -172
- package/_bmad-output/implementation-artifacts/done/15-8-validation-report.md +0 -342
- package/_bmad-output/implementation-artifacts/done/16-1-repository-layout-wizard.md +0 -223
- package/_bmad-output/implementation-artifacts/done/16-2-config-storage-and-cross-reference.md +0 -180
- package/_bmad-output/implementation-artifacts/done/16-3-project-context-multi-repo-section.md +0 -136
- package/_bmad-output/implementation-artifacts/done/16-4-validate-cross-repo-path-resolution.md +0 -137
- package/_bmad-output/implementation-artifacts/done/16-4-validation-report.md +0 -79
- package/_bmad-output/implementation-artifacts/done/16-5-fix-config-lost-on-update.md +0 -110
- package/_bmad-output/implementation-artifacts/done/16-6-repo-sync-check-skill.md +0 -116
- package/_bmad-output/implementation-artifacts/done/16-7-portable-path-storage.md +0 -109
- package/_bmad-output/implementation-artifacts/done/16-8-cicd-remote-mode.md +0 -97
- package/_bmad-output/implementation-artifacts/done/16-9-reconfigure-layout-workflow.md +0 -125
- package/_bmad-output/implementation-artifacts/done/17-1-sprint-entity-model.md +0 -322
- package/_bmad-output/implementation-artifacts/done/17-2-flat-backlog-model.md +0 -264
- package/_bmad-output/implementation-artifacts/done/17-3-bug-as-story-type.md +0 -208
- package/_bmad-output/implementation-artifacts/done/17-4-backlog-to-sprint-workflow.md +0 -209
- package/_bmad-output/implementation-artifacts/done/17-5-sprint-to-backlog-workflow.md +0 -221
- package/_bmad-output/implementation-artifacts/done/17-6-done-item-cleanup.md +0 -273
- package/_bmad-output/implementation-artifacts/done/17-7-multi-criteria-prioritization.md +0 -235
- package/_bmad-output/implementation-artifacts/done/17-8-rework-sprint-status-display.md +0 -285
- package/_bmad-output/implementation-artifacts/done/2-1-cpp-coding-standards-skill.md +0 -188
- package/_bmad-output/implementation-artifacts/done/2-2-csharp-coding-standards-skill.md +0 -211
- package/_bmad-output/implementation-artifacts/done/2-3-python-coding-standards-skill.md +0 -189
- package/_bmad-output/implementation-artifacts/done/3-1-skill-scaffolding-tool.md +0 -184
- package/_bmad-output/implementation-artifacts/done/3-2-skill-validation-tool.md +0 -178
- package/_bmad-output/implementation-artifacts/done/3-3-mandatory-skill-designation.md +0 -136
- package/_bmad-output/implementation-artifacts/done/3-4-bmad-persona-customization-tooling.md +0 -141
- package/_bmad-output/implementation-artifacts/done/3-5-specialized-agent-development-tooling.md +0 -145
- package/_bmad-output/implementation-artifacts/done/5-1-bmad-method-direct-dependency.md +0 -188
- package/_bmad-output/implementation-artifacts/done/5-2-bmad-cache-build-script.md +0 -219
- package/_bmad-output/implementation-artifacts/done/5-3-pre-populate-bmad-cache.md +0 -234
- package/_bmad-output/implementation-artifacts/done/5-4-validate-bundled-installation.md +0 -274
- package/_bmad-output/implementation-artifacts/done/6-1-methodology-presentation-bundle.md +0 -173
- package/_bmad-output/implementation-artifacts/done/8-1-move-instruction-injection-to-top.md +0 -131
- package/_bmad-output/implementation-artifacts/done/8-2-agent-aware-injection-strategy.md +0 -124
- package/_bmad-output/implementation-artifacts/done/8-3-create-bmad-extension-module.md +0 -187
- package/_bmad-output/implementation-artifacts/done/8-4-integration-verification.md +0 -102
- package/_bmad-output/implementation-artifacts/done/8-5-per-agent-enforcement-hooks-research.md +0 -126
- package/_bmad-output/implementation-artifacts/done/8-6-context-persistence-research.md +0 -101
- package/_bmad-output/implementation-artifacts/done/9-1-register-opencode-agent.md +0 -73
- package/_bmad-output/implementation-artifacts/done/9-2-json-merge-injection.md +0 -91
- package/_bmad-output/implementation-artifacts/done/9-3-json-merge-existing.md +0 -113
- package/_bmad-output/implementation-artifacts/done/9-4-json-error-handling.md +0 -90
- package/_bmad-output/implementation-artifacts/epic-11-12-shared-guardrails.md +0 -53
- package/_bmad-output/implementation-artifacts/epic-15-adversarial-fixes.md +0 -287
- package/_bmad-output/implementation-artifacts/epic-16-adversarial-review.md +0 -49
- package/_bmad-output/implementation-artifacts/epic-16-edge-case-review.md +0 -230
- package/_bmad-output/implementation-artifacts/epic-17-adversarial-review.md +0 -37
- package/_bmad-output/implementation-artifacts/epic-17-edge-case-review.md +0 -140
- package/_bmad-output/implementation-artifacts/sprint-status.yaml +0 -139
- package/_bmad-output/planning-artifacts/adapter-pattern-spec.md +0 -508
- package/_bmad-output/planning-artifacts/architecture.md +0 -2023
- package/_bmad-output/planning-artifacts/domain-research-roocode-2026-03-31.md +0 -295
- package/_bmad-output/planning-artifacts/epics.md +0 -4232
- package/_bmad-output/planning-artifacts/mil498-workflow-audit.md +0 -290
- package/_bmad-output/planning-artifacts/prd.md +0 -811
- package/_bmad-output/planning-artifacts/product-brief-agents-2026-03-08.md +0 -214
- package/_bmad-output/planning-artifacts/sprint-status-schema.md +0 -506
- package/_bmad-output/planning-artifacts/validation-report-prd-2026-04-07.md +0 -330
- package/_bmad-output/project-context.md +0 -47
- package/agents.code-workspace +0 -11
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-554778ad4e7254827618ebd2497c3f4bce9054a4.idx +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-554778ad4e7254827618ebd2497c3f4bce9054a4.rev +0 -0
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-39c4fd66f4e0eb3f4d93665318df04cd356b0297.idx +0 -0
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-39c4fd66f4e0eb3f4d93665318df04cd356b0297.rev +0 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-brainstorming-coach/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-creative-problem-solver/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-design-thinking-coach/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-innovation-strategist/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-presentation-master/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-storyteller/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/cis/src/skills/bmad-cis-design-thinking/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/cis/src/skills/bmad-cis-innovation-strategy/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/cis/src/skills/bmad-cis-problem-solving/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/cis/src/skills/bmad-cis-storytelling/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-ac967149d58fba215d07238ad8881bdbdad5c9c3.idx +0 -0
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-ac967149d58fba215d07238ad8881bdbdad5c9c3.rev +0 -0
- package/lib/bmad-cache/gds/src/agents/gds-agent-game-architect/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/gds/src/agents/gds-agent-game-designer/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/gds/src/agents/gds-agent-game-dev/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/gds/src/agents/gds-agent-game-qa/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/gds/src/agents/gds-agent-game-scrum-master/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/gds/src/agents/gds-agent-game-solo-dev/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/gds/src/agents/gds-agent-tech-writer/bmad-skill-manifest.yaml +0 -11
- package/lib/bmad-cache/gds/src/workflows/1-preproduction/gds-brainstorm-game/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/1-preproduction/gds-create-game-brief/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/1-preproduction/research/bmad-skill-manifest.yaml +0 -9
- package/lib/bmad-cache/gds/src/workflows/1-preproduction/research/gds-domain-research/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/2-design/create-prd/bmad-skill-manifest.yaml +0 -14
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-gdd/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-narrative/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-ux-design/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/3-technical/gds-check-implementation-readiness/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/3-technical/gds-create-epics-and-stories/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/3-technical/gds-game-architecture/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/3-technical/gds-generate-project-context/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-code-review/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-correct-course/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-create-story/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-dev-story/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-retrospective/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-sprint-planning/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/4-production/gds-sprint-status/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-e2e-scaffold/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-performance-test/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-playtest-plan/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-test-automate/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-test-design/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-test-framework/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/gametest/gds-test-review/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/gds-document-project/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/gds-quick-flow/gds-quick-dev/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/gds-quick-flow/gds-quick-dev-new-preview/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/gds/src/workflows/gds-quick-flow/gds-quick-spec/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-e75385cd52b693dbb8a3b2afb50058952543b3a2.idx +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-e75385cd52b693dbb8a3b2afb50058952543b3a2.rev +0 -0
- package/lib/bmad-cache/tea/_git_preserved/refs/tags/v1.10.0 +0 -1
- package/lib/bmad-cache/tea/src/agents/bmad-tea/bmad-skill-manifest.yaml +0 -14
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/workflow.md +0 -90
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/workflow.md +0 -41
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/workflow.md +0 -41
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/workflow.md +0 -41
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/workflow.md +0 -41
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/workflow.md +0 -41
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/workflow.md +0 -41
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/workflow.md +0 -41
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/bmad-skill-manifest.yaml +0 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/workflow.md +0 -41
- package/lib/bmad-customizations/bmm-demerzel.customize.yaml +0 -36
- package/lib/bmad-customizations/demerzel.md +0 -32
- package/lib/bmad-customize/bmm-quick-flow-solo-dev.customize.yaml +0 -8
- package/lib/bmad-extension/module.yaml +0 -5
- package/out.txt +0 -0
- package/test/agent-injection-strategy.test.js +0 -129
- package/test/agents-md.test.js +0 -398
- package/test/bmad-extension.test.js +0 -283
- package/test/bmad-output-policy.test.js +0 -119
- package/test/bmad-persona-phase-prefix.test.js +0 -271
- package/test/bmad-version-bump.test.js +0 -313
- package/test/build-bmad-args.test.js +0 -368
- package/test/cicd-remote-mode.test.js +0 -224
- package/test/clinerules.test.js +0 -339
- package/test/config-layout.test.js +0 -230
- package/test/config-lost-on-update.test.js +0 -363
- package/test/config-storage.test.js +0 -275
- package/test/convert-agents-to-skills.test.js +0 -255
- package/test/create-agent.test.js +0 -232
- package/test/cross-repo-validation.test.js +0 -201
- package/test/enforcement-hooks.test.js +0 -324
- package/test/experimental-warning.test.js +0 -314
- package/test/extension-module-restructure.test.js +0 -407
- package/test/fixtures/README.md +0 -74
- package/test/fixtures/empty-project/README.md +0 -5
- package/test/fixtures/empty-project/package.json +0 -5
- package/test/fixtures/onprem-profile-baseline/.gitkeep +0 -2
- package/test/fixtures/standard-profile-baseline/.gitkeep +0 -2
- package/test/generate-project-context.test.js +0 -483
- package/test/instruction-block.test.js +0 -388
- package/test/instruction-injection.test.js +0 -336
- package/test/integration-verification.test.js +0 -433
- package/test/migration-validation.test.js +0 -506
- package/test/migration.test.js +0 -832
- package/test/offline-recompile.test.js +0 -267
- package/test/onprem-injection.test.js +0 -441
- package/test/onprem-layer.test.js +0 -419
- package/test/opencode-agent.test.js +0 -150
- package/test/opencode-json-error.test.js +0 -260
- package/test/opencode-json-injection.test.js +0 -264
- package/test/opencode-json-merge.test.js +0 -318
- package/test/portable-paths.test.js +0 -268
- package/test/profile.test.js +0 -301
- package/test/reconfigure.test.js +0 -436
- package/test/repo-layout.test.js +0 -246
- package/test/roo-code-agent.test.js +0 -166
- package/test/roo-code-injection.test.js +0 -172
- package/test/roomodes.test.js +0 -343
- package/test/skill-authoring.test.js +0 -272
- package/test/skill-customize-agent.test.js +0 -253
- package/test/skill-mandatory.test.js +0 -235
- package/test/skill-validation.test.js +0 -378
- package/test/story-15-5-workflow-skills.test.js +0 -311
- package/test/uninstall.test.js +0 -402
- package/test/yes-flag.test.js +0 -200
- /package/lib/bmad-cache/gds/src/{gametest → agents/gds-agent-game-dev/gametest}/qa-index.csv +0 -0
- /package/lib/bmad-cache/gds/src/workflows/2-design/{create-prd → gds-create-prd}/data/domain-complexity.csv +0 -0
- /package/lib/bmad-cache/gds/src/workflows/2-design/{create-prd → gds-create-prd}/data/project-types.csv +0 -0
- /package/lib/{bmad-extension/skills/bmad-ma-agent-cyber → bmad-extension-plugin/skills/add-sprint}/.gitkeep +0 -0
- /package/lib/{bmad-extension/skills/bmad-ma-agent-devops → bmad-extension-plugin/skills/add-to-sprint}/.gitkeep +0 -0
- /package/lib/{bmad-extension/skills/bmad-ma-agent-ml → bmad-extension-plugin/skills/bmad-dev-story}/.gitkeep +0 -0
- /package/lib/{bmad-extension/skills/bmad-ma-agent-sqa → bmad-extension-plugin/skills/bmad-sprint-planning}/.gitkeep +0 -0
- /package/lib/{bmad-extension/skills/bmad-ma-agent-sre → bmad-extension-plugin/skills/bmad-sprint-status}/.gitkeep +0 -0
package/lib/bmad.js
CHANGED
|
@@ -30,6 +30,267 @@ function buildChildSpawnEnv(parentEnv = process.env) {
|
|
|
30
30
|
const BMAD_DIR = '_bmad';
|
|
31
31
|
const CONFIG_DIR = path.join(BMAD_DIR, '_config', 'agents');
|
|
32
32
|
|
|
33
|
+
// ── Canonical config paths (Story 22.7) ─────────────────────────────────────
|
|
34
|
+
//
|
|
35
|
+
// BMAD v6.3.0 (PR #2159) removed the `bmad-init` skill and moved the canonical
|
|
36
|
+
// project config from `_bmad/_config/manifest.yaml` to `_bmad/bmm/config.yaml`.
|
|
37
|
+
// All ma-agents code paths and skills MUST read from CANONICAL_CONFIG_REL.
|
|
38
|
+
//
|
|
39
|
+
// LEGACY_MANIFEST_REL is kept ONLY as a detection marker for the migration
|
|
40
|
+
// shim in ensureCanonicalConfigLocation() below — it is NEVER read silently
|
|
41
|
+
// as a value source. The stale-module surgery in runUpdateStep() still
|
|
42
|
+
// references it because that code cleans up pre-6.3 install artifacts before
|
|
43
|
+
// handing control to bmad-method; the cleanup is a write-path, not a
|
|
44
|
+
// canonical-config read.
|
|
45
|
+
const CANONICAL_CONFIG_REL = path.join(BMAD_DIR, 'bmm', 'config.yaml');
|
|
46
|
+
const LEGACY_MANIFEST_REL = path.join(BMAD_DIR, '_config', 'manifest.yaml');
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Project-relative directory name used to stage the bundled plugin
|
|
50
|
+
* (`lib/bmad-extension-plugin/`) before invoking `bmad-method install
|
|
51
|
+
* --custom-source <stage-path>`.
|
|
52
|
+
*
|
|
53
|
+
* Kept as a module-level constant (not an env-var) so the path is stable
|
|
54
|
+
* across runs and easy for operators to inspect after a failed install.
|
|
55
|
+
* See Story 22.8 (adds this path to the ma-agents-managed .gitignore).
|
|
56
|
+
*/
|
|
57
|
+
const PLUGIN_STAGE_DIR_NAME = '.ma-agents-plugin-stage';
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Copy the bundled plugin (`lib/bmad-extension-plugin/`) into the target
|
|
61
|
+
* project at `<projectRoot>/.ma-agents-plugin-stage/` so that bmad-method
|
|
62
|
+
* 6.3.0's PluginResolver (local-file strategy) can install it via
|
|
63
|
+
* `--custom-source <stage-path>`.
|
|
64
|
+
*
|
|
65
|
+
* Contract (Story 22.6 AC 2, AC 3):
|
|
66
|
+
* - Produces a fresh byte-identical copy of the source tree (not a symlink,
|
|
67
|
+
* not a hardlink). fs-extra's `copySync` performs a recursive file copy;
|
|
68
|
+
* combined with the pre-copy wipe below it guarantees the stage is a
|
|
69
|
+
* clean snapshot of the build output.
|
|
70
|
+
* - Any pre-existing stage directory (left over from a prior failed install)
|
|
71
|
+
* is removed first so content never merges across runs. This mirrors
|
|
72
|
+
* `scripts/build-plugin.js`'s own wipe-and-recreate pattern and defends
|
|
73
|
+
* against cross-version skill bleed (the skill catalog renamed in 22.2).
|
|
74
|
+
* - On platforms where the source contains symlinks, they are dereferenced
|
|
75
|
+
* by `fs-extra.copySync` (`dereference: true`) — the stage is a flat copy
|
|
76
|
+
* so a BMAD installer that writes into the stage never touches repo source.
|
|
77
|
+
*
|
|
78
|
+
* Return shape:
|
|
79
|
+
* `{ stagePath, customSourceArg }` — where `stagePath` is the absolute path
|
|
80
|
+
* used for filesystem work (remove on cleanup, surface on failure) and
|
|
81
|
+
* `customSourceArg` is what to pass to bmad-method's `--custom-source`.
|
|
82
|
+
* Why split them: bmad-method 6.3.0's `parseSource()` only treats strings
|
|
83
|
+
* starting with `/`, `./`, `../`, or `~` as local paths; a Windows
|
|
84
|
+
* absolute like `D:\path\...` falls through to "Not a valid Git URL or
|
|
85
|
+
* local path" and the plugin silently fails to resolve. We pass the
|
|
86
|
+
* relative form `./<dir>` (the installer runs with cwd = projectRoot, so
|
|
87
|
+
* it resolves to the same absolute path) to stay cross-platform safe.
|
|
88
|
+
*
|
|
89
|
+
* @param {string} projectRoot - Absolute path to the target project
|
|
90
|
+
* @returns {{ stagePath: string, customSourceArg: string }}
|
|
91
|
+
* @throws {Error} If the source plugin bundle is missing (build was skipped)
|
|
92
|
+
*/
|
|
93
|
+
function stagePlugin(projectRoot) {
|
|
94
|
+
// Edge-case #2 — normalize to absolute FIRST. Callers may pass a relative
|
|
95
|
+
// `./some-project` path; downstream `fs.statSync` / `path.join` then
|
|
96
|
+
// resolve against the current cwd, which differs between the ma-agents
|
|
97
|
+
// CLI process and the bmad-method child (runCommand sets cwd = projectRoot).
|
|
98
|
+
// Resolving here once keeps every subsequent path op unambiguous.
|
|
99
|
+
// path.resolve does NOT require the path to exist, so it's safe to run
|
|
100
|
+
// before the existence check below.
|
|
101
|
+
projectRoot = path.resolve(projectRoot);
|
|
102
|
+
// Import inside the function so unit-tests can exercise the helper without
|
|
103
|
+
// the build-plugin.js require-chain loading the full pipeline.
|
|
104
|
+
const { OUT_DIR: pluginBundlePath } = require('../scripts/build-plugin');
|
|
105
|
+
if (!fs.existsSync(pluginBundlePath)) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
`Bundled plugin not found at ${pluginBundlePath} — run \`npm run build:plugin\` before installing.`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
// Edge-case #1 — the bundle directory may exist but be empty (half-built
|
|
111
|
+
// or a partially wiped prior `scripts/build-plugin.js` run). Verify the
|
|
112
|
+
// two load-bearing manifests are present before we copy anything; without
|
|
113
|
+
// these, bmad-method's PluginResolver would either silently install a
|
|
114
|
+
// no-op or throw deep in its pipeline with a less diagnosable message.
|
|
115
|
+
const requiredBundleEntries = [
|
|
116
|
+
path.join('.claude-plugin', 'marketplace.json'),
|
|
117
|
+
path.join('skills', 'module.yaml'),
|
|
118
|
+
];
|
|
119
|
+
for (const rel of requiredBundleEntries) {
|
|
120
|
+
const abs = path.join(pluginBundlePath, rel);
|
|
121
|
+
if (!fs.existsSync(abs)) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`Bundled plugin at ${pluginBundlePath} is missing required file ` +
|
|
124
|
+
`"${rel}" — run \`npm run build:plugin\` to regenerate a complete bundle.`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (!fs.existsSync(projectRoot)) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Cannot stage plugin — projectRoot does not exist: ${projectRoot}`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
// Edge-case #3 — projectRoot must be a directory. A caller passing a file
|
|
134
|
+
// path would otherwise surface as a confusing EEXIST/ENOTDIR deep inside
|
|
135
|
+
// the fs.copySync call. Fail fast with a clear message.
|
|
136
|
+
if (!fs.statSync(projectRoot).isDirectory()) {
|
|
137
|
+
throw new Error(
|
|
138
|
+
`Cannot stage plugin — projectRoot is not a directory: ${projectRoot}`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
const stagePath = path.join(projectRoot, PLUGIN_STAGE_DIR_NAME);
|
|
142
|
+
// Remove any stale stage left behind by a previous failed install.
|
|
143
|
+
// Merging old and new content would risk shipping retired skill IDs
|
|
144
|
+
// (Story 22.2) and break the byte-identical guarantee in AC 3.
|
|
145
|
+
//
|
|
146
|
+
// Security: reject a stage path that IS a symlink before removing it.
|
|
147
|
+
// Without this check, fs.removeSync follows the link and could delete
|
|
148
|
+
// content outside the project (e.g., if an attacker or a careless user
|
|
149
|
+
// pre-created `.ma-agents-plugin-stage` as a symlink to a home dir).
|
|
150
|
+
if (fs.existsSync(stagePath)) {
|
|
151
|
+
const stageLstat = fs.lstatSync(stagePath);
|
|
152
|
+
if (stageLstat.isSymbolicLink()) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
`Refusing to stage plugin — ${stagePath} is a symbolic link. ` +
|
|
155
|
+
`Remove it manually and re-run; ma-agents will not follow symlinks ` +
|
|
156
|
+
`inside the project root for safety.`
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
// Edge-case #5 — on Windows, a prior install may still hold file
|
|
160
|
+
// handles (EBUSY/EPERM). Re-throw with context so the operator knows
|
|
161
|
+
// which path failed and can close the offending process.
|
|
162
|
+
try {
|
|
163
|
+
fs.removeSync(stagePath);
|
|
164
|
+
} catch (err) {
|
|
165
|
+
throw new Error(
|
|
166
|
+
`Cannot wipe stale stage ${stagePath}: ${err.message}`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// `dereference: true` copies symlink targets as regular files — we never
|
|
171
|
+
// want a symlink inside the stage pointing back into repo source, because
|
|
172
|
+
// bmad-method may write into the staged plugin during install.
|
|
173
|
+
//
|
|
174
|
+
// Edge-case #6 — if the copy aborts mid-tree (disk full, permission flip,
|
|
175
|
+
// user Ctrl+C at the OS layer), the partial stage would be merged on next
|
|
176
|
+
// run and break AC 3's byte-identical guarantee. Best-effort remove the
|
|
177
|
+
// half-populated stage, then rethrow with a contextual message.
|
|
178
|
+
try {
|
|
179
|
+
fs.copySync(pluginBundlePath, stagePath, { overwrite: true, dereference: true });
|
|
180
|
+
} catch (err) {
|
|
181
|
+
try { fs.removeSync(stagePath); } catch { /* swallow — primary error wins */ }
|
|
182
|
+
throw new Error(`Stage copy failed: ${err.message}`);
|
|
183
|
+
}
|
|
184
|
+
// POSIX-style `./<dir>` satisfies BMAD's parseSource() local-path detector
|
|
185
|
+
// on both Linux/macOS and Windows. The installer's cwd is always
|
|
186
|
+
// projectRoot (see runCommand calls below), so this resolves identically
|
|
187
|
+
// to `stagePath`.
|
|
188
|
+
const customSourceArg = `./${PLUGIN_STAGE_DIR_NAME}`;
|
|
189
|
+
console.log(chalk.gray(` Staged plugin: ${stagePath}`));
|
|
190
|
+
return { stagePath, customSourceArg };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Remove the plugin stage directory produced by {@link stagePlugin}.
|
|
195
|
+
*
|
|
196
|
+
* Call this only after the bmad-method install succeeds. On failure we
|
|
197
|
+
* deliberately leave the stage in place (Story 22.6 AC 6) so operators can
|
|
198
|
+
* inspect exactly what was about to be installed and re-run BMAD directly
|
|
199
|
+
* with `--custom-source <stage>` as a bypass.
|
|
200
|
+
*
|
|
201
|
+
* @param {string} stagePath - Absolute path returned by stagePlugin()
|
|
202
|
+
* @returns {void}
|
|
203
|
+
*/
|
|
204
|
+
function cleanupStage(stagePath) {
|
|
205
|
+
if (!stagePath) return;
|
|
206
|
+
try {
|
|
207
|
+
// Edge-case #4 — if the path is (now) a symlink, unlink ONLY the link.
|
|
208
|
+
// `fs.removeSync` on a symlink-to-directory would recurse into the
|
|
209
|
+
// target and could delete files outside the project root (e.g., if a
|
|
210
|
+
// concurrent process replaced the stage with a symlink between
|
|
211
|
+
// stagePlugin() and cleanupStage()). `lstatSync` does not follow the
|
|
212
|
+
// link; `unlinkSync` removes the link entry without touching the
|
|
213
|
+
// target.
|
|
214
|
+
if (fs.existsSync(stagePath)) {
|
|
215
|
+
const lst = fs.lstatSync(stagePath);
|
|
216
|
+
if (lst.isSymbolicLink()) {
|
|
217
|
+
fs.unlinkSync(stagePath);
|
|
218
|
+
console.log(chalk.gray(` Removed plugin stage symlink: ${stagePath}`));
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
fs.removeSync(stagePath);
|
|
223
|
+
console.log(chalk.gray(` Removed plugin stage directory: ${stagePath}`));
|
|
224
|
+
} catch (err) {
|
|
225
|
+
// Non-fatal — surface a warning so the operator can clean up manually.
|
|
226
|
+
// We do not rethrow because the install itself succeeded; leaving the
|
|
227
|
+
// stage on disk is a cosmetic issue compared to breaking an otherwise
|
|
228
|
+
// green install.
|
|
229
|
+
console.warn(
|
|
230
|
+
chalk.yellow(
|
|
231
|
+
` Warning: failed to remove plugin stage directory at ${stagePath}: ${err.message}`
|
|
232
|
+
)
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* F2a — Ensure the **project-root** `.gitignore` lists the plugin-stage
|
|
239
|
+
* directory exactly once. The single canonical write site for the Story 22.8
|
|
240
|
+
* policy: every BMAD orchestrator that calls `stagePlugin(projectRoot)` must
|
|
241
|
+
* call this immediately afterwards (or beforehand) with the same `projectRoot`.
|
|
242
|
+
*
|
|
243
|
+
* Why this lives here, not in the installer:
|
|
244
|
+
* - The reason the entry exists is `stagePlugin()` writing
|
|
245
|
+
* `<projectRoot>/.ma-agents-plugin-stage/`. The two operations belong
|
|
246
|
+
* together so a future maintainer sees them as one unit.
|
|
247
|
+
* - The pre-F2a placement (inside `installSkill()` per-agent loop) wrote
|
|
248
|
+
* per-skill-dir `.gitignore` files because `installPath` is the agent's
|
|
249
|
+
* skills directory, not the project root. Moving the call here makes
|
|
250
|
+
* the project-root contract self-evident.
|
|
251
|
+
*
|
|
252
|
+
* Lazy-require — `lib/installer.js` requires `./bmad` for `PLUGIN_STAGE_DIR_NAME`
|
|
253
|
+
* at module top, so a top-level require of installer here would create a
|
|
254
|
+
* load-order circular dependency. The runtime `require('./installer')` below
|
|
255
|
+
* is safe because installer's exports object is fully populated by the time
|
|
256
|
+
* this function is invoked (after CLI startup).
|
|
257
|
+
*
|
|
258
|
+
* Failure policy — gitignore management is cosmetic relative to the install.
|
|
259
|
+
* If writing the file fails (permission denied, read-only fs, ENOSPC), we
|
|
260
|
+
* surface a warning and continue rather than aborting an otherwise-green
|
|
261
|
+
* install. The install will have produced no observable side effect under
|
|
262
|
+
* the project's `.gitignore` policy in that case, which is the same outcome
|
|
263
|
+
* as a project that already lists the entry.
|
|
264
|
+
*
|
|
265
|
+
* @param {string} projectRoot - Absolute path to the target project root
|
|
266
|
+
* (the directory containing the project's top-level `.gitignore`).
|
|
267
|
+
* @returns {void}
|
|
268
|
+
*/
|
|
269
|
+
function ensurePluginStageGitignoredForProject(projectRoot) {
|
|
270
|
+
if (typeof projectRoot !== 'string' || projectRoot.length === 0) return;
|
|
271
|
+
let installer;
|
|
272
|
+
try {
|
|
273
|
+
installer = require('./installer');
|
|
274
|
+
} catch (err) {
|
|
275
|
+
// Installer module failed to load — should never happen in a valid
|
|
276
|
+
// install, but if it does we cannot do anything useful here.
|
|
277
|
+
console.warn(chalk.yellow(` Warning: could not load installer for gitignore policy: ${err.message}`));
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (typeof installer.ensurePluginStageIgnored !== 'function') return;
|
|
281
|
+
try {
|
|
282
|
+
installer.ensurePluginStageIgnored(projectRoot);
|
|
283
|
+
} catch (err) {
|
|
284
|
+
// EACCES on read-only `.gitignore`, EROFS on read-only filesystem, etc.
|
|
285
|
+
// Logged so the operator can fix it manually; never fatal to the install.
|
|
286
|
+
console.warn(
|
|
287
|
+
chalk.yellow(
|
|
288
|
+
` Warning: could not update ${path.join(projectRoot, '.gitignore')} with plugin-stage entry: ${err.message}`
|
|
289
|
+
)
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
33
294
|
/**
|
|
34
295
|
* Run a shell command, relaying output to stdout/stderr.
|
|
35
296
|
* Always uses pipe mode so that on failure, error.stdout and error.stderr
|
|
@@ -52,14 +313,33 @@ function runCommand(command, options = {}) {
|
|
|
52
313
|
}
|
|
53
314
|
|
|
54
315
|
function getBmadCommand(args) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
316
|
+
// bmad-method 6.3.0 replaced the `tools/bmad-npx-wrapper.js` entry point
|
|
317
|
+
// with `tools/installer/bmad-cli.js` (see `bin.bmad-method` in the
|
|
318
|
+
// upstream package.json). Prefer the new entry; fall back to the legacy
|
|
319
|
+
// wrapper path only to keep older local checkouts working during a
|
|
320
|
+
// partial upgrade (defensive — the test suite pins the installed version).
|
|
321
|
+
const candidates = [
|
|
322
|
+
'bmad-method/tools/installer/bmad-cli.js',
|
|
323
|
+
'bmad-method/tools/bmad-npx-wrapper.js',
|
|
324
|
+
];
|
|
325
|
+
let lastError = null;
|
|
326
|
+
for (const candidate of candidates) {
|
|
327
|
+
try {
|
|
328
|
+
const resolved = require.resolve(candidate);
|
|
329
|
+
return `node "${resolved}" ${args}`;
|
|
330
|
+
} catch (err) {
|
|
331
|
+
// Remember the last failure so diagnostics can chain back to the
|
|
332
|
+
// actual MODULE_NOT_FOUND / ENOENT from require.resolve.
|
|
333
|
+
lastError = err;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const wrapped = new Error(
|
|
337
|
+
'bmad-method CLI entry point not found in node_modules — run "npm install" first'
|
|
338
|
+
);
|
|
339
|
+
if (lastError) {
|
|
340
|
+
wrapped.cause = lastError;
|
|
62
341
|
}
|
|
342
|
+
throw wrapped;
|
|
63
343
|
}
|
|
64
344
|
|
|
65
345
|
function isBmadInstalled(projectRoot = process.cwd()) {
|
|
@@ -258,6 +538,45 @@ function classifyRecompileFailure(error, opts = {}) {
|
|
|
258
538
|
};
|
|
259
539
|
}
|
|
260
540
|
|
|
541
|
+
/**
|
|
542
|
+
* Resolve the correct CLI flag for passing extension/custom-module sources.
|
|
543
|
+
*
|
|
544
|
+
* bmad-method 6.3.0 renamed `--custom-content` to `--custom-source`. To keep
|
|
545
|
+
* the builder working across both versions (and to survive local downgrades),
|
|
546
|
+
* grep the installed install command for the newer flag first and fall back
|
|
547
|
+
* to the legacy name. We read once and cache the result because buildBmadArgs
|
|
548
|
+
* can be called repeatedly during a single install flow.
|
|
549
|
+
*
|
|
550
|
+
* @returns {'--custom-source' | '--custom-content'}
|
|
551
|
+
*/
|
|
552
|
+
let _cachedCustomContentFlag = null;
|
|
553
|
+
function resolveCustomContentFlag() {
|
|
554
|
+
if (_cachedCustomContentFlag) return _cachedCustomContentFlag;
|
|
555
|
+
const candidates = [
|
|
556
|
+
{ path: 'bmad-method/tools/installer/commands/install.js', flags: ['--custom-source', '--custom-content'] },
|
|
557
|
+
{ path: 'bmad-method/tools/cli/commands/install.js', flags: ['--custom-source', '--custom-content'] },
|
|
558
|
+
];
|
|
559
|
+
for (const { path: relPath, flags } of candidates) {
|
|
560
|
+
try {
|
|
561
|
+
const resolved = require.resolve(relPath);
|
|
562
|
+
const content = fs.readFileSync(resolved, 'utf8');
|
|
563
|
+
for (const flag of flags) {
|
|
564
|
+
if (content.includes(flag)) {
|
|
565
|
+
_cachedCustomContentFlag = flag;
|
|
566
|
+
return flag;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
} catch {
|
|
570
|
+
// try next
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
// Defensive default — keep older behavior if we cannot inspect the installed
|
|
574
|
+
// package. The installer will fail loudly with an unknown-flag error, which
|
|
575
|
+
// is a safer failure mode than silently dropping the extension.
|
|
576
|
+
_cachedCustomContentFlag = '--custom-content';
|
|
577
|
+
return _cachedCustomContentFlag;
|
|
578
|
+
}
|
|
579
|
+
|
|
261
580
|
/**
|
|
262
581
|
* Build a complete bmad-method CLI command from an install context object.
|
|
263
582
|
* Replaces ad-hoc string concatenation with a single authoritative builder.
|
|
@@ -272,6 +591,11 @@ function classifyRecompileFailure(error, opts = {}) {
|
|
|
272
591
|
* @param {string} [ctx.commLang] - Communication language
|
|
273
592
|
* @param {string} [ctx.docLang] - Document output language
|
|
274
593
|
* @param {string} [ctx.outputFolder] - Output folder relative to project root
|
|
594
|
+
* @param {string} [ctx.customSource] - Absolute path to a staged plugin
|
|
595
|
+
* directory (Story 22.6). When provided, this is appended as
|
|
596
|
+
* `--custom-source <path>`; when omitted no extension flag is added.
|
|
597
|
+
* The legacy fallback to `lib/bmad-extension/` was removed when the
|
|
598
|
+
* stage-and-invoke flow replaced applyCustomizations().
|
|
275
599
|
* @returns {string} Complete command string ready for execSync
|
|
276
600
|
*/
|
|
277
601
|
function buildBmadArgs(ctx) {
|
|
@@ -299,13 +623,15 @@ function buildBmadArgs(ctx) {
|
|
|
299
623
|
parts.push('--output-folder', `"${ctx.outputFolder}"`);
|
|
300
624
|
}
|
|
301
625
|
|
|
302
|
-
//
|
|
303
|
-
//
|
|
304
|
-
//
|
|
305
|
-
//
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
626
|
+
// Story 22.6 — stage-and-invoke. When callers pass an explicit customSource
|
|
627
|
+
// (the project-local `.ma-agents-plugin-stage/` directory produced by
|
|
628
|
+
// stagePlugin()), we append it via the 6.3.0 `--custom-source` flag (with a
|
|
629
|
+
// downgrade path to the legacy `--custom-content` name for local checkouts
|
|
630
|
+
// that still run bmad-method 6.2.x). The hand-parsed `lib/bmad-extension/`
|
|
631
|
+
// fallback that lived here was removed alongside applyCustomizations().
|
|
632
|
+
if (ctx.customSource) {
|
|
633
|
+
const flag = resolveCustomContentFlag();
|
|
634
|
+
parts.push(flag, `"${ctx.customSource}"`);
|
|
309
635
|
}
|
|
310
636
|
|
|
311
637
|
if (ctx.action === 'update') {
|
|
@@ -315,7 +641,52 @@ function buildBmadArgs(ctx) {
|
|
|
315
641
|
return getBmadCommand(parts.join(' '));
|
|
316
642
|
}
|
|
317
643
|
|
|
644
|
+
/**
|
|
645
|
+
* Common pre-install hook invoked at the top of every BMAD entry point
|
|
646
|
+
* (installBmad, updateBmad, runMigration). Centralizing this makes it
|
|
647
|
+
* obvious which actions every entry point shares, and lets us add new
|
|
648
|
+
* shared pre-checks in one place rather than tracking N call sites.
|
|
649
|
+
*
|
|
650
|
+
* F3 Section 6 — added so updateBmad() and runMigration() also get the
|
|
651
|
+
* canonical-config-location drift signal that installBmad() already has.
|
|
652
|
+
*
|
|
653
|
+
* Idempotency: ensureCanonicalConfigLocation is read-mostly (only writes
|
|
654
|
+
* is a notice log when both legacy and canonical config exist, and only
|
|
655
|
+
* sets the migration-needed flag in its return value when the legacy
|
|
656
|
+
* file is the only one present). Calling it twice in a single entry-
|
|
657
|
+
* point invocation (e.g. installBmad → runMigration) re-emits the same
|
|
658
|
+
* notice, but:
|
|
659
|
+
* - The notice is informational, not destructive.
|
|
660
|
+
* - Operators upgrading from pre-6.3 see at most two identical lines,
|
|
661
|
+
* which is acceptable for a one-shot migration path.
|
|
662
|
+
* - Steady-state installs (canonical-only or fresh) emit zero notices.
|
|
663
|
+
*
|
|
664
|
+
* @param {string} projectRoot - Absolute path to the project root.
|
|
665
|
+
* @returns {ReturnType<typeof ensureCanonicalConfigLocation>} The drift
|
|
666
|
+
* detection result so callers that need the `needsRegeneration` flag
|
|
667
|
+
* (e.g. installBmad's migration check) can use it without a second call.
|
|
668
|
+
*/
|
|
669
|
+
function preInstallHooks(projectRoot) {
|
|
670
|
+
// Edge-case-hunter E6: guard against undefined / empty projectRoot
|
|
671
|
+
// because path.join('', anything) silently resolves to a relative path
|
|
672
|
+
// against the caller's cwd, which would surface the drift signal for
|
|
673
|
+
// the WRONG project. Caller error must surface loud, not silently.
|
|
674
|
+
if (!projectRoot || typeof projectRoot !== 'string') {
|
|
675
|
+
throw new Error(
|
|
676
|
+
`preInstallHooks: projectRoot must be a non-empty string (got ${JSON.stringify(projectRoot)})`
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
// Story 22.7 AC #6 — normalize the config location BEFORE any read that
|
|
680
|
+
// assumes the canonical v6.3.0 path. This runs ahead of
|
|
681
|
+
// detectMigrationNeed() so operators upgrading from a pre-6.3 install get
|
|
682
|
+
// a clear message that legacy config is NOT used as a fallback; the
|
|
683
|
+
// downstream bmad-method install will regenerate the new layout.
|
|
684
|
+
return ensureCanonicalConfigLocation(projectRoot);
|
|
685
|
+
}
|
|
686
|
+
|
|
318
687
|
async function installBmad(modules = ['bmm', 'bmb'], tools = [], projectRoot = process.cwd(), force = false, { userName = '', commLang = '', docLang = '', outputFolder = '' } = {}) {
|
|
688
|
+
preInstallHooks(projectRoot);
|
|
689
|
+
|
|
319
690
|
// Detect migration need
|
|
320
691
|
const detection = detectMigrationNeed(projectRoot);
|
|
321
692
|
|
|
@@ -325,6 +696,29 @@ async function installBmad(modules = ['bmm', 'bmb'], tools = [], projectRoot = p
|
|
|
325
696
|
return await runMigration(modules, tools, projectRoot, force, { userName, commLang, docLang, outputFolder });
|
|
326
697
|
}
|
|
327
698
|
|
|
699
|
+
// Story 22.6 — stage-and-invoke. Copy the bundled plugin into the project
|
|
700
|
+
// and hand its path to bmad-method via --custom-source so BMAD's own
|
|
701
|
+
// PluginResolver places the skills (no more post-install manifest surgery).
|
|
702
|
+
//
|
|
703
|
+
// Edge-case #7 — stagePlugin() can throw (missing bundle, invalid
|
|
704
|
+
// projectRoot, stale-stage wipe EBUSY, half-populated copy). The CLI
|
|
705
|
+
// caller (bin/cli.js) treats this function's return value as a
|
|
706
|
+
// success/failure boolean and does not try/catch around it, so an
|
|
707
|
+
// uncaught throw here would bubble out as a crash. Catch staging errors
|
|
708
|
+
// explicitly, log them, and propagate as `return false` like the other
|
|
709
|
+
// failure branches.
|
|
710
|
+
let stagePath;
|
|
711
|
+
let customSourceArg;
|
|
712
|
+
try {
|
|
713
|
+
({ stagePath, customSourceArg } = stagePlugin(projectRoot));
|
|
714
|
+
} catch (error) {
|
|
715
|
+
console.error(chalk.red(` Plugin staging failed: ${error.message}`));
|
|
716
|
+
return false;
|
|
717
|
+
}
|
|
718
|
+
// F2a — Story 22.8 gitignore policy. Apply at the project root next to
|
|
719
|
+
// stagePlugin() so the two operations are co-located. Idempotent and
|
|
720
|
+
// non-fatal (see ensurePluginStageGitignoredForProject() for details).
|
|
721
|
+
ensurePluginStageGitignoredForProject(projectRoot);
|
|
328
722
|
const command = buildBmadArgs({
|
|
329
723
|
projectRoot,
|
|
330
724
|
modules,
|
|
@@ -334,18 +728,51 @@ async function installBmad(modules = ['bmm', 'bmb'], tools = [], projectRoot = p
|
|
|
334
728
|
commLang,
|
|
335
729
|
docLang,
|
|
336
730
|
outputFolder,
|
|
731
|
+
customSource: customSourceArg,
|
|
337
732
|
});
|
|
338
733
|
|
|
339
734
|
await prePopulateBmadCache(force);
|
|
340
735
|
|
|
736
|
+
console.log(chalk.cyan(` Invoking bmad-method with --tools ${(tools && tools.length > 0) ? tools.join(',') : 'none'}`));
|
|
341
737
|
console.log(chalk.gray(` Running: ${command}`));
|
|
738
|
+
// Edge-case #8 — track bmad-method success and post-step (deployMethodology)
|
|
739
|
+
// success SEPARATELY. The stage must only be cleaned up when BOTH succeed;
|
|
740
|
+
// otherwise the operator loses the exact bundle that was handed to
|
|
741
|
+
// bmad-method when a post-install step fails, making diagnosis harder.
|
|
742
|
+
let bmadInvokeSucceeded = false;
|
|
743
|
+
let postStepsSucceeded = false;
|
|
342
744
|
try {
|
|
343
745
|
runCommand(command, { cwd: projectRoot, env: buildChildSpawnEnv() });
|
|
746
|
+
bmadInvokeSucceeded = true;
|
|
747
|
+
// F1a — on-prem persona phase-prefix pass. Runs BEFORE
|
|
748
|
+
// deployMethodology so a methodology-deploy failure doesn't prevent
|
|
749
|
+
// the prefix from being applied (they are independent concerns).
|
|
750
|
+
// No-op for standard profile; reads profile from `.ma-agents.json`
|
|
751
|
+
// if present (the same signal setProfile() / Story 21.10 writes).
|
|
752
|
+
const profile = require('./profile').getProfile(projectRoot);
|
|
753
|
+
await applyOnPremPhasePrefixToDeployedSkills(projectRoot, profile);
|
|
344
754
|
await deployMethodology(projectRoot, force);
|
|
755
|
+
postStepsSucceeded = true;
|
|
345
756
|
return true;
|
|
346
757
|
} catch (error) {
|
|
758
|
+
// Edge-case #7 — surface stagePlugin errors (or any downstream error)
|
|
759
|
+
// as a clean non-zero outcome rather than an uncaught exception. The
|
|
760
|
+
// existing try/catch already satisfies this; the explicit
|
|
761
|
+
// `bmadInvokeSucceeded` check below distinguishes pre-invoke failures
|
|
762
|
+
// (stage never created / already left in place by stagePlugin's own
|
|
763
|
+
// error paths) from runtime bmad/deploy failures.
|
|
347
764
|
console.error(chalk.red(` BMAD installation failed: ${error.message}`));
|
|
348
765
|
return false;
|
|
766
|
+
} finally {
|
|
767
|
+
if (bmadInvokeSucceeded && postStepsSucceeded) {
|
|
768
|
+
cleanupStage(stagePath);
|
|
769
|
+
} else {
|
|
770
|
+
// AC 6 — leave the stage for diagnostics so the operator can
|
|
771
|
+
// re-run bmad-method manually against the same bundle. This fires
|
|
772
|
+
// for BOTH bmad-method failure and post-step failure (e.g.,
|
|
773
|
+
// deployMethodology throwing after a green bmad install).
|
|
774
|
+
console.error(chalk.yellow(` Install failed — plugin stage left in place for inspection: ${stagePath}`));
|
|
775
|
+
}
|
|
349
776
|
}
|
|
350
777
|
}
|
|
351
778
|
|
|
@@ -354,12 +781,41 @@ async function installBmad(modules = ['bmm', 'bmb'], tools = [], projectRoot = p
|
|
|
354
781
|
* Rolls back on failure (NFR29).
|
|
355
782
|
*/
|
|
356
783
|
async function runMigration(modules, tools, projectRoot, force, { userName, commLang, docLang, outputFolder }) {
|
|
784
|
+
// F3 Section 6 — invoke shared pre-install hooks. When runMigration is
|
|
785
|
+
// called from installBmad() this is a re-call (installBmad already ran
|
|
786
|
+
// the hook); the duplicate is intentional so runMigration is correct
|
|
787
|
+
// when invoked from any future entry point. ensureCanonicalConfigLocation
|
|
788
|
+
// is idempotent — see preInstallHooks() docstring.
|
|
789
|
+
preInstallHooks(projectRoot);
|
|
790
|
+
|
|
357
791
|
// Step 1: Backup existing customizations
|
|
358
792
|
console.log(chalk.cyan(' Step 1/4: Backing up existing customizations...'));
|
|
359
793
|
const backedUpFiles = await backupCustomizations(projectRoot);
|
|
360
794
|
|
|
361
795
|
// Step 2: Run bmad-method with --action update
|
|
362
796
|
console.log(chalk.cyan(' Step 2/4: Updating BMAD-METHOD...'));
|
|
797
|
+
// Story 22.6 — migration path also uses stage-and-invoke so the plugin
|
|
798
|
+
// rides in on --custom-source instead of the retired manifest-surgery path.
|
|
799
|
+
//
|
|
800
|
+
// Edge-case #7 — catch stagePlugin() errors so the migration surfaces as
|
|
801
|
+
// a clean `return false` rather than an uncaught exception bubbling out
|
|
802
|
+
// of installBmad() into the CLI.
|
|
803
|
+
let stagePath;
|
|
804
|
+
let customSourceArg;
|
|
805
|
+
try {
|
|
806
|
+
({ stagePath, customSourceArg } = stagePlugin(projectRoot));
|
|
807
|
+
} catch (error) {
|
|
808
|
+
console.error(chalk.red(` Plugin staging failed: ${error.message}`));
|
|
809
|
+
if (backedUpFiles.length > 0) {
|
|
810
|
+
console.log(chalk.yellow(' Rolling back — restoring backed-up customizations...'));
|
|
811
|
+
await restoreCustomizations(projectRoot);
|
|
812
|
+
}
|
|
813
|
+
return false;
|
|
814
|
+
}
|
|
815
|
+
// F2a — Story 22.8 gitignore policy on the migration path. Same rationale
|
|
816
|
+
// as installBmad(): co-locate with stagePlugin() so the project-root write
|
|
817
|
+
// happens once per pipeline pass.
|
|
818
|
+
ensurePluginStageGitignoredForProject(projectRoot);
|
|
363
819
|
const command = buildBmadArgs({
|
|
364
820
|
projectRoot,
|
|
365
821
|
modules,
|
|
@@ -369,15 +825,19 @@ async function runMigration(modules, tools, projectRoot, force, { userName, comm
|
|
|
369
825
|
commLang,
|
|
370
826
|
docLang,
|
|
371
827
|
outputFolder,
|
|
828
|
+
customSource: customSourceArg,
|
|
372
829
|
});
|
|
373
830
|
|
|
374
831
|
await prePopulateBmadCache(force);
|
|
375
832
|
|
|
833
|
+
console.log(chalk.cyan(` Invoking bmad-method with --tools ${(tools && tools.length > 0) ? tools.join(',') : 'none'}`));
|
|
376
834
|
console.log(chalk.gray(` Running: ${command}`));
|
|
377
835
|
try {
|
|
378
836
|
runCommand(command, { cwd: projectRoot, env: buildChildSpawnEnv() });
|
|
379
837
|
} catch (error) {
|
|
380
|
-
// Rollback on failure
|
|
838
|
+
// Rollback on failure — leave the stage in place (AC 6) so the
|
|
839
|
+
// operator can re-run BMAD manually with `--custom-source <stage>`
|
|
840
|
+
// as a bypass, and inspect what was about to be installed.
|
|
381
841
|
console.error(chalk.red(` BMAD update failed: ${error.message}`));
|
|
382
842
|
if (backedUpFiles.length > 0) {
|
|
383
843
|
console.log(chalk.yellow(' Rolling back — restoring backed-up customizations...'));
|
|
@@ -385,6 +845,7 @@ async function runMigration(modules, tools, projectRoot, force, { userName, comm
|
|
|
385
845
|
}
|
|
386
846
|
console.error(chalk.red(' Migration aborted. Your project remains on the previous version.'));
|
|
387
847
|
console.error(chalk.yellow(' Suggestion: Run "npm update bmad-method" manually, then retry installation.'));
|
|
848
|
+
console.error(chalk.yellow(` Plugin stage left in place for inspection: ${stagePath}`));
|
|
388
849
|
return false;
|
|
389
850
|
}
|
|
390
851
|
|
|
@@ -400,13 +861,55 @@ async function runMigration(modules, tools, projectRoot, force, { userName, comm
|
|
|
400
861
|
console.log(chalk.cyan(' Step 4/4: Cleaning up legacy artifacts...'));
|
|
401
862
|
await cleanupLegacyArtifacts(projectRoot);
|
|
402
863
|
|
|
864
|
+
// F1a — on-prem persona phase-prefix pass. Migrations can flip profile
|
|
865
|
+
// or re-stage skills, so the pass runs here too. Identical no-op
|
|
866
|
+
// semantics for standard profile.
|
|
867
|
+
const profile = require('./profile').getProfile(projectRoot);
|
|
868
|
+
await applyOnPremPhasePrefixToDeployedSkills(projectRoot, profile);
|
|
869
|
+
|
|
403
870
|
await deployMethodology(projectRoot, force);
|
|
404
871
|
|
|
872
|
+
// All migration steps succeeded — safe to clean up the stage now.
|
|
873
|
+
// Cleaning up earlier would remove diagnostics if any of steps 3-4 or
|
|
874
|
+
// deployMethodology failed after a successful bmad-method invocation.
|
|
875
|
+
cleanupStage(stagePath);
|
|
876
|
+
|
|
405
877
|
console.log(chalk.green(` Migration to BMAD ${BMAD_TARGET_VERSION} complete!`));
|
|
406
878
|
return true;
|
|
407
879
|
}
|
|
408
880
|
|
|
409
881
|
async function updateBmad(modules = ['bmm', 'bmb'], tools = [], projectRoot = process.cwd(), force = false, { userName = '', commLang = '', docLang = '', outputFolder = '' } = {}) {
|
|
882
|
+
// F3 Section 6 — invoke shared pre-install hooks so operators using the
|
|
883
|
+
// update entry point also receive the canonical-config-location drift
|
|
884
|
+
// signal. Previously only installBmad() ran this check, meaning a
|
|
885
|
+
// pre-6.3 → 6.3+ upgrade triggered via `--action update` (skipping the
|
|
886
|
+
// install path) would silently miss the drift notice.
|
|
887
|
+
preInstallHooks(projectRoot);
|
|
888
|
+
|
|
889
|
+
// Story 22.6 — stage-and-invoke replaces the legacy manifest-surgery block
|
|
890
|
+
// that used to live here (hand-parsing of BMAD-internal registry files,
|
|
891
|
+
// hardcoded stale-module whitelist, CSV column indexing, and physical
|
|
892
|
+
// directory removal). bmad-method 6.3.0's PluginResolver handles update
|
|
893
|
+
// semantics natively via --custom-source, so we only need to stage the
|
|
894
|
+
// bundled plugin and invoke the installer.
|
|
895
|
+
//
|
|
896
|
+
// Edge-case #7 — catch stagePlugin() errors so the CLI caller receives a
|
|
897
|
+
// false return rather than an uncaught exception (same rationale as
|
|
898
|
+
// installBmad). Without this, a broken bundle or stale stage with held
|
|
899
|
+
// file handles would crash the CLI instead of logging a diagnosable
|
|
900
|
+
// message.
|
|
901
|
+
let stagePath;
|
|
902
|
+
let customSourceArg;
|
|
903
|
+
try {
|
|
904
|
+
({ stagePath, customSourceArg } = stagePlugin(projectRoot));
|
|
905
|
+
} catch (error) {
|
|
906
|
+
console.error(chalk.red(` Plugin staging failed: ${error.message}`));
|
|
907
|
+
return false;
|
|
908
|
+
}
|
|
909
|
+
// F2a — Story 22.8 gitignore policy on the update path. Idempotent re-runs
|
|
910
|
+
// are the explicit AC #4 contract; calling here on every update keeps the
|
|
911
|
+
// entry present even if the project's `.gitignore` was reset between runs.
|
|
912
|
+
ensurePluginStageGitignoredForProject(projectRoot);
|
|
410
913
|
const command = buildBmadArgs({
|
|
411
914
|
projectRoot,
|
|
412
915
|
modules,
|
|
@@ -416,98 +919,46 @@ async function updateBmad(modules = ['bmm', 'bmb'], tools = [], projectRoot = pr
|
|
|
416
919
|
commLang,
|
|
417
920
|
docLang,
|
|
418
921
|
outputFolder,
|
|
922
|
+
customSource: customSourceArg,
|
|
419
923
|
});
|
|
420
924
|
|
|
421
925
|
await prePopulateBmadCache(force);
|
|
422
926
|
|
|
423
|
-
//
|
|
424
|
-
//
|
|
425
|
-
//
|
|
426
|
-
//
|
|
427
|
-
//
|
|
428
|
-
//
|
|
429
|
-
//
|
|
430
|
-
//
|
|
431
|
-
|
|
432
|
-
// and "bmb" fails due to a broken directory structure in 6.2.2.
|
|
433
|
-
//
|
|
434
|
-
// Fix: before running bmad-method, clean all three persistence layers:
|
|
435
|
-
// 1. manifest.yaml — remove stale module entries
|
|
436
|
-
// 2. files-manifest.csv — remove stale file tracking entries
|
|
437
|
-
// 3. physical directories — remove _bmad/bmb/ and _bmad/_config/custom/
|
|
438
|
-
|
|
439
|
-
const staleModules = ['custom', 'bmb'];
|
|
440
|
-
|
|
441
|
-
// 1. Clean manifest.yaml (the primary trigger for the re-install loop)
|
|
442
|
-
const yamlManifestPath = path.join(projectRoot, BMAD_DIR, '_config', 'manifest.yaml');
|
|
443
|
-
if (fs.existsSync(yamlManifestPath)) {
|
|
444
|
-
try {
|
|
445
|
-
const yamlContent = await fs.readFile(yamlManifestPath, 'utf-8');
|
|
446
|
-
const manifest = yaml.parse(yamlContent);
|
|
447
|
-
if (manifest?.modules && Array.isArray(manifest.modules)) {
|
|
448
|
-
const before = manifest.modules.length;
|
|
449
|
-
manifest.modules = manifest.modules.filter(
|
|
450
|
-
m => !staleModules.includes(typeof m === 'string' ? m : m.name)
|
|
451
|
-
);
|
|
452
|
-
const removed = before - manifest.modules.length;
|
|
453
|
-
if (removed > 0) {
|
|
454
|
-
await fs.writeFile(yamlManifestPath, yaml.stringify(manifest), 'utf-8');
|
|
455
|
-
console.log(chalk.gray(` Cleaned ${removed} stale module(s) from manifest.yaml`));
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
} catch (err) {
|
|
459
|
-
// Non-fatal
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
// 2. Clean files-manifest.csv (prevents stale file-tracking references)
|
|
464
|
-
const filesManifestPath = path.join(projectRoot, BMAD_DIR, '_config', 'files-manifest.csv');
|
|
465
|
-
if (fs.existsSync(filesManifestPath)) {
|
|
466
|
-
try {
|
|
467
|
-
let csv = await fs.readFile(filesManifestPath, 'utf-8');
|
|
468
|
-
const before = csv.split('\n').length;
|
|
469
|
-
csv = csv.split('\n').filter(line => {
|
|
470
|
-
const fields = line.split(',');
|
|
471
|
-
const mod = fields[2] && fields[2].replace(/"/g, '');
|
|
472
|
-
return !staleModules.includes(mod);
|
|
473
|
-
}).join('\n');
|
|
474
|
-
const after = csv.split('\n').length;
|
|
475
|
-
if (after < before) {
|
|
476
|
-
await fs.writeFile(filesManifestPath, csv, 'utf-8');
|
|
477
|
-
console.log(chalk.gray(` Cleaned ${before - after} stale entries from files-manifest.csv`));
|
|
478
|
-
}
|
|
479
|
-
} catch (err) {
|
|
480
|
-
// Non-fatal
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// 3. Remove physical directories so bmad-method's manifest-generator
|
|
485
|
-
// doesn't re-discover them via scanInstalledModules().
|
|
486
|
-
// _bmad/custom/ is safe to remove — applyCustomizations() recreates it after.
|
|
487
|
-
const staleDirs = [
|
|
488
|
-
path.join(projectRoot, BMAD_DIR, 'bmb'),
|
|
489
|
-
path.join(projectRoot, BMAD_DIR, 'custom'),
|
|
490
|
-
path.join(projectRoot, BMAD_DIR, '_config', 'custom'),
|
|
491
|
-
];
|
|
492
|
-
for (const dir of staleDirs) {
|
|
493
|
-
if (fs.existsSync(dir)) {
|
|
494
|
-
try {
|
|
495
|
-
await fs.remove(dir);
|
|
496
|
-
console.log(chalk.gray(` Removed stale directory: ${path.relative(projectRoot, dir)}`));
|
|
497
|
-
} catch (err) {
|
|
498
|
-
// Non-fatal
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
|
|
927
|
+
// Story 22.6 — the legacy manifest-surgery block that used to live here
|
|
928
|
+
// (hand-parsing of BMAD-internal registry files, hardcoded stale-module
|
|
929
|
+
// whitelist, physical directory removal) has been removed. bmad-method
|
|
930
|
+
// 6.3.0's PluginResolver handles update semantics natively via
|
|
931
|
+
// --custom-source against the staged plugin bundle. Story 22.7's
|
|
932
|
+
// "legacy-WRITE" annotation was retired along with the block it
|
|
933
|
+
// annotated — canonical config reads still go through
|
|
934
|
+
// readCanonicalBmadConfig() (see exports below).
|
|
935
|
+
console.log(chalk.cyan(` Invoking bmad-method with --tools ${(tools && tools.length > 0) ? tools.join(',') : 'none'}`));
|
|
503
936
|
console.log(chalk.gray(` Running: ${command}`));
|
|
937
|
+
// Edge-case #8 — same split-tracking as installBmad(): the stage must
|
|
938
|
+
// survive a deployMethodology failure so the operator can inspect what
|
|
939
|
+
// was handed to bmad-method.
|
|
940
|
+
let bmadInvokeSucceeded = false;
|
|
941
|
+
let postStepsSucceeded = false;
|
|
504
942
|
try {
|
|
505
943
|
runCommand(command, { cwd: projectRoot, env: buildChildSpawnEnv() });
|
|
944
|
+
bmadInvokeSucceeded = true;
|
|
945
|
+
// F1a — on-prem persona phase-prefix pass; identical call to
|
|
946
|
+
// installBmad(). Runs on every update so a profile flipped since
|
|
947
|
+
// the last install gets re-stamped (Story 21.10 reconfigure).
|
|
948
|
+
const profile = require('./profile').getProfile(projectRoot);
|
|
949
|
+
await applyOnPremPhasePrefixToDeployedSkills(projectRoot, profile);
|
|
506
950
|
await deployMethodology(projectRoot, force);
|
|
951
|
+
postStepsSucceeded = true;
|
|
507
952
|
return true;
|
|
508
953
|
} catch (error) {
|
|
509
954
|
console.error(chalk.red(` BMAD update failed: ${error.message}`));
|
|
510
955
|
return false;
|
|
956
|
+
} finally {
|
|
957
|
+
if (bmadInvokeSucceeded && postStepsSucceeded) {
|
|
958
|
+
cleanupStage(stagePath);
|
|
959
|
+
} else {
|
|
960
|
+
console.error(chalk.yellow(` Update failed — plugin stage left in place for inspection: ${stagePath}`));
|
|
961
|
+
}
|
|
511
962
|
}
|
|
512
963
|
}
|
|
513
964
|
|
|
@@ -617,297 +1068,252 @@ async function applyPersonaPhasePrefix(customizeSourceDir, configTargetDir, prof
|
|
|
617
1068
|
}
|
|
618
1069
|
}
|
|
619
1070
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
modules,
|
|
677
|
-
tools,
|
|
678
|
-
action: 'install',
|
|
679
|
-
userName,
|
|
680
|
-
commLang,
|
|
681
|
-
docLang,
|
|
682
|
-
outputFolder,
|
|
683
|
-
});
|
|
684
|
-
await prePopulateBmadCache(force);
|
|
1071
|
+
// ─── F1a — on-prem persona phase-prefix restoration ──────────────────────────
|
|
1072
|
+
//
|
|
1073
|
+
// Pre-22.6, the phase-prefix pass ran against `.customize.yaml` files in
|
|
1074
|
+
// `_bmad/_config/agents/` via the now-retired `applyCustomizations()` flow.
|
|
1075
|
+
// Under the stage-and-invoke architecture those YAML files are no longer
|
|
1076
|
+
// deployed — bmad-method 6.3.0's PluginResolver emits per-tool persona SKILL.md
|
|
1077
|
+
// files under each tool's skills directory (e.g. `.claude/skills/bmad-agent-pm/
|
|
1078
|
+
// SKILL.md`). The persona content that used to live in YAML `critical_actions`
|
|
1079
|
+
// now lives inline in markdown.
|
|
1080
|
+
//
|
|
1081
|
+
// This helper walks the deployed tool trees after the install succeeds and
|
|
1082
|
+
// injects the `on_prem_phase_prefix` text (read from the canonical
|
|
1083
|
+
// `lib/bmad-customize/bmm-<persona>.customize.yaml` source) into each persona
|
|
1084
|
+
// SKILL.md using a marker-delimited block for idempotency. Only runs when
|
|
1085
|
+
// profile === 'on-prem'; no-op in every other case.
|
|
1086
|
+
//
|
|
1087
|
+
// Marker convention: `<!-- BEGIN:ma-on-prem-phase-prefix -->` …
|
|
1088
|
+
// `<!-- END:ma-on-prem-phase-prefix -->`. A second run replaces the existing
|
|
1089
|
+
// block byte-for-byte; removing/reverting is a manifest-uninstall concern
|
|
1090
|
+
// (Story 21.11) owned elsewhere.
|
|
1091
|
+
|
|
1092
|
+
const ON_PREM_PREFIX_MARKER_BEGIN = '<!-- BEGIN:ma-on-prem-phase-prefix -->';
|
|
1093
|
+
const ON_PREM_PREFIX_MARKER_END = '<!-- END:ma-on-prem-phase-prefix -->';
|
|
1094
|
+
|
|
1095
|
+
// ma-agents persona-id → deployed SKILL directory name. The deployed name
|
|
1096
|
+
// mirrors the BMAD plugin's skill manifest (Story 22.2 renamed these from
|
|
1097
|
+
// `bmad-ma-agent-*` to `bmad-agent-*`; keep the mapping explicit so future
|
|
1098
|
+
// upstream renames surface here as a contained change rather than a silent
|
|
1099
|
+
// no-op across every tool tree).
|
|
1100
|
+
const PERSONA_SKILL_MAP = Object.freeze({
|
|
1101
|
+
'bmm-pm': 'bmad-agent-pm',
|
|
1102
|
+
'bmm-architect': 'bmad-agent-architect',
|
|
1103
|
+
'bmm-dev': 'bmad-agent-dev',
|
|
1104
|
+
'bmm-analyst': 'bmad-agent-analyst',
|
|
1105
|
+
'bmm-tech-writer': 'bmad-agent-tech-writer',
|
|
1106
|
+
'bmm-ux-designer': 'bmad-agent-ux-designer',
|
|
1107
|
+
'bmm-sm': 'bmad-agent-sm',
|
|
1108
|
+
'bmm-qa': 'bmad-agent-qa',
|
|
1109
|
+
});
|
|
1110
|
+
|
|
1111
|
+
// Tool skill-dir roots. Kept in sync with `lib/agents.js` canonical
|
|
1112
|
+
// `skillsDir` values — duplicated here (not imported) to avoid pulling the
|
|
1113
|
+
// agents module into install-time code paths that don't need it. The five
|
|
1114
|
+
// IDE tools listed are the only targets that receive `bmad-agent-*` persona
|
|
1115
|
+
// skills post-22.6 (verified 2026-04-23 via scratch install).
|
|
1116
|
+
// F2b — copilot's skills directory was realigned from `.github/copilot/skills`
|
|
1117
|
+
// to `.github/skills` so it matches bmad-method 6.3.0's `github-copilot`
|
|
1118
|
+
// platform target_dir. Without this update F1a's prefix pass would walk a
|
|
1119
|
+
// directory that no longer receives the persona SKILL.md files.
|
|
1120
|
+
const TOOL_SKILL_DIRS = Object.freeze([
|
|
1121
|
+
path.join('.claude', 'skills'),
|
|
1122
|
+
path.join('.github', 'skills'),
|
|
1123
|
+
path.join('.cline', 'skills'),
|
|
1124
|
+
path.join('.roo', 'skills'),
|
|
1125
|
+
path.join('.kilocode', 'skills'),
|
|
1126
|
+
]);
|
|
685
1127
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
// STAGE:EXTENSION — Deploy BMAD extension module (AFTER recompile — extensions/ survives recompile)
|
|
707
|
-
// NOTE: Stage 1 deploys persona/menu customize.yaml to _bmad/_config/agents/ (consumed
|
|
708
|
-
// by BMAD's agent compilation). This stage deploys the extension module to
|
|
709
|
-
// _bmad/extensions/ma-agents-skills/ which adds critical_actions for skill loading.
|
|
710
|
-
// These are complementary paths: _config/agents/ drives agent recompilation (persona/menu),
|
|
711
|
-
// while extensions/ adds runtime behavior (critical_actions). BMAD does NOT merge them —
|
|
712
|
-
// they are consumed by different mechanisms. The 4 custom agents have persona/menu in both
|
|
713
|
-
// locations; this is intentional for backward compatibility during transition (Story 8.3).
|
|
714
|
-
const extensionSource = path.join(__dirname, 'bmad-extension');
|
|
715
|
-
const extensionTarget = path.join(projectRoot, BMAD_DIR, 'extensions', 'ma-agents-skills');
|
|
716
|
-
if (fs.existsSync(extensionSource)) {
|
|
717
|
-
await fs.ensureDir(extensionTarget);
|
|
718
|
-
await fs.copy(extensionSource, extensionTarget);
|
|
719
|
-
console.log(chalk.cyan(' + Deployed BMAD extension module: ma-agents-skills'));
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
// STAGE:CUSTOMIZE — Deploy built-in agent customizations from lib/bmad-customize/
|
|
723
|
-
// These add critical_actions to the 8 built-in BMM agents (pm, architect, dev, qa,
|
|
724
|
-
// sm, tech-writer, ux-designer, bmad-master) so they load project skills at startup.
|
|
725
|
-
// Runs AFTER --custom-content (extension module) and BEFORE quick-update.
|
|
726
|
-
// Post-deploy: phase:/on_prem_phase_prefix: keys are stripped for standard profile;
|
|
727
|
-
// for on-prem profile the prefix is injected as critical_actions[0] instead.
|
|
728
|
-
const customizeSource = path.join(__dirname, 'bmad-customize');
|
|
729
|
-
if (fs.existsSync(customizeSource)) {
|
|
730
|
-
await fs.ensureDir(configTargetDir);
|
|
731
|
-
const customizeFiles = (await fs.readdir(customizeSource)).filter(f => f.endsWith('.customize.yaml'));
|
|
732
|
-
for (const file of customizeFiles) {
|
|
733
|
-
await fs.copy(path.join(customizeSource, file), path.join(configTargetDir, file));
|
|
734
|
-
console.log(chalk.cyan(` + Applied built-in customization: ${file}`));
|
|
735
|
-
}
|
|
736
|
-
const profile = require('./profile').getProfile(projectRoot) ?? 'standard';
|
|
737
|
-
await applyPersonaPhasePrefix(customizeSource, configTargetDir, profile);
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
// STAGE:WORKFLOWS — Apply workflows (AFTER recompile so they persist)
|
|
741
|
-
if (fs.existsSync(workflowSourceDir)) {
|
|
742
|
-
await fs.ensureDir(workflowTargetDir);
|
|
743
|
-
await fs.copy(workflowSourceDir, workflowTargetDir);
|
|
744
|
-
console.log(chalk.cyan(` + Applied BMAD workflows`));
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
// 5. Apply MIL-STD-498 templates (AFTER recompile so they persist)
|
|
748
|
-
if (fs.existsSync(templateSourceDir)) {
|
|
749
|
-
await fs.ensureDir(templateTargetDir);
|
|
750
|
-
await fs.copy(templateSourceDir, templateTargetDir);
|
|
751
|
-
console.log(chalk.cyan(` + Applied MIL-STD-498 templates`));
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
// 6. Copy agent templates to compiled location (AFTER recompile)
|
|
755
|
-
// BMAD recompile doesn't generate custom agents (mil498, cyber) in _bmad/bmm/agents/.
|
|
756
|
-
// Without this, updateAgentInstructions() creates the file with only the MA-AGENTS block.
|
|
757
|
-
if (fs.existsSync(sourceDir)) {
|
|
758
|
-
const compiledAgentDir = path.join(projectRoot, BMAD_DIR, 'bmm', 'agents');
|
|
759
|
-
await fs.ensureDir(compiledAgentDir);
|
|
760
|
-
const files = await fs.readdir(sourceDir);
|
|
761
|
-
for (const file of files) {
|
|
762
|
-
if (file.endsWith('.md')) {
|
|
763
|
-
const matchingAgentId = Object.entries(agentMdMap).find(([, mdFile]) => mdFile === file)?.[0];
|
|
764
|
-
if (!matchingAgentId || selectedAgentIds.length === 0 || selectedAgentIds.includes(matchingAgentId)) {
|
|
765
|
-
await fs.copy(path.join(sourceDir, file), path.join(compiledAgentDir, file));
|
|
766
|
-
console.log(chalk.cyan(` + Applied compiled agent: ${file}`));
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
// 7. Register custom workflows in BMAD CSV registries (after recompile)
|
|
773
|
-
if (selectedAgentIds.length === 0 || selectedAgentIds.includes('bmm-mil498')) {
|
|
774
|
-
await registerMilWorkflows(projectRoot);
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
// 8. Register ML workflows
|
|
778
|
-
if (selectedAgentIds.length === 0 || selectedAgentIds.includes('bmm-demerzel')) {
|
|
779
|
-
await registerMlWorkflows(projectRoot);
|
|
780
|
-
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Build the marker-wrapped block that is injected into a persona SKILL.md.
|
|
1130
|
+
* Kept as a single-source helper so the test assertions and the production
|
|
1131
|
+
* code match byte-for-byte.
|
|
1132
|
+
*
|
|
1133
|
+
* @param {string} prefixText The `on_prem_phase_prefix` from the customize YAML
|
|
1134
|
+
* @returns {string} Multi-line block with markers and trailing newline
|
|
1135
|
+
*/
|
|
1136
|
+
function buildOnPremPrefixBlock(prefixText) {
|
|
1137
|
+
return [
|
|
1138
|
+
ON_PREM_PREFIX_MARKER_BEGIN,
|
|
1139
|
+
'## On-Prem Phase Prefix',
|
|
1140
|
+
'',
|
|
1141
|
+
prefixText,
|
|
1142
|
+
ON_PREM_PREFIX_MARKER_END,
|
|
1143
|
+
'',
|
|
1144
|
+
].join('\n');
|
|
781
1145
|
}
|
|
782
1146
|
|
|
783
1147
|
/**
|
|
784
|
-
*
|
|
785
|
-
*
|
|
1148
|
+
* Inject-or-replace the on-prem prefix block inside `skillContent`. Idempotent:
|
|
1149
|
+
* a second call with the same prefix returns identical content.
|
|
1150
|
+
*
|
|
1151
|
+
* Placement rule:
|
|
1152
|
+
* - If an existing marker block is present, replace it in place (byte-stable).
|
|
1153
|
+
* - Otherwise, insert the new block immediately AFTER the YAML frontmatter
|
|
1154
|
+
* (the second `---` line) and BEFORE the rest of the markdown body.
|
|
1155
|
+
* - If no frontmatter exists, prepend the block.
|
|
1156
|
+
*
|
|
1157
|
+
* @param {string} skillContent Current SKILL.md contents
|
|
1158
|
+
* @param {string} prefixText Prefix text to inject
|
|
1159
|
+
* @returns {string} Updated content
|
|
786
1160
|
*/
|
|
787
|
-
|
|
788
|
-
const
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
},
|
|
801
|
-
{
|
|
802
|
-
name: 'Generate SDP', code: 'GP',
|
|
803
|
-
file: '_bmad/bmm/workflows/mil498/sdp/workflow.yaml',
|
|
804
|
-
command: 'bmad-mil-generate-sdp',
|
|
805
|
-
description: 'Generate a MIL-STD-498 Software Development Plan from project planning artifacts'
|
|
806
|
-
},
|
|
807
|
-
{
|
|
808
|
-
name: 'Generate OCD', code: 'GO',
|
|
809
|
-
file: '_bmad/bmm/workflows/mil498/ocd/workflow.yaml',
|
|
810
|
-
command: 'bmad-mil-generate-ocd',
|
|
811
|
-
description: 'Generate a MIL-STD-498 Operational Concept Description from PRD and architecture'
|
|
812
|
-
},
|
|
813
|
-
{
|
|
814
|
-
name: 'Generate SSS', code: 'SS',
|
|
815
|
-
file: '_bmad/bmm/workflows/mil498/sss/workflow.yaml',
|
|
816
|
-
command: 'bmad-mil-generate-sss',
|
|
817
|
-
description: 'Generate a MIL-STD-498 System/Subsystem Specification from project requirements'
|
|
818
|
-
},
|
|
819
|
-
{
|
|
820
|
-
name: 'Generate STD', code: 'GT',
|
|
821
|
-
file: '_bmad/bmm/workflows/mil498/std/workflow.yaml',
|
|
822
|
-
command: 'bmad-mil-generate-std',
|
|
823
|
-
description: 'Generate a MIL-STD-498 Software Test Description from epics stories and architecture'
|
|
824
|
-
},
|
|
825
|
-
{
|
|
826
|
-
name: 'Generate SSDD', code: 'SD',
|
|
827
|
-
file: '_bmad/bmm/workflows/mil498/ssdd/workflow.yaml',
|
|
828
|
-
command: 'bmad-mil-generate-ssdd',
|
|
829
|
-
description: 'Generate a MIL-STD-498 System/Subsystem Design Description from architecture and PRD'
|
|
830
|
-
}
|
|
831
|
-
];
|
|
832
|
-
|
|
833
|
-
// Append or update entries in module-help.csv
|
|
834
|
-
const moduleHelpPath = path.join(projectRoot, BMAD_DIR, 'bmm', 'module-help.csv');
|
|
835
|
-
if (fs.existsSync(moduleHelpPath)) {
|
|
836
|
-
let content = await fs.readFile(moduleHelpPath, 'utf-8');
|
|
837
|
-
for (const entry of milEntries) {
|
|
838
|
-
const row = `bmm,anytime,${entry.name},${entry.code},,${entry.file},${entry.command},false,mil498,Create Mode,${entry.description},planning_artifacts,document,`;
|
|
839
|
-
// Remove any existing line for this command, then append the current one
|
|
840
|
-
const lines = content.split('\n').filter(line => !line.includes(entry.command));
|
|
841
|
-
content = lines.join('\n').trimEnd() + '\n' + row + '\n';
|
|
1161
|
+
function injectOnPremPrefixBlock(skillContent, prefixText) {
|
|
1162
|
+
const block = buildOnPremPrefixBlock(prefixText);
|
|
1163
|
+
const beginIdx = skillContent.indexOf(ON_PREM_PREFIX_MARKER_BEGIN);
|
|
1164
|
+
if (beginIdx !== -1) {
|
|
1165
|
+
const endIdx = skillContent.indexOf(ON_PREM_PREFIX_MARKER_END, beginIdx);
|
|
1166
|
+
if (endIdx !== -1) {
|
|
1167
|
+
const afterEnd = endIdx + ON_PREM_PREFIX_MARKER_END.length;
|
|
1168
|
+
// Swallow the single trailing newline that belongs to the existing
|
|
1169
|
+
// block so we don't accumulate blank lines on repeated runs.
|
|
1170
|
+
const tail = skillContent[afterEnd] === '\n'
|
|
1171
|
+
? skillContent.slice(afterEnd + 1)
|
|
1172
|
+
: skillContent.slice(afterEnd);
|
|
1173
|
+
return skillContent.slice(0, beginIdx) + block + tail;
|
|
842
1174
|
}
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
//
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
1175
|
+
// Malformed half-block (begin without end). Treat as fresh-insert below
|
|
1176
|
+
// rather than silently corrupting the file further.
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
// Fresh insert. Place after frontmatter when present. Accept both LF
|
|
1180
|
+
// and CRLF line endings — BMAD-deployed SKILL.md files are LF today
|
|
1181
|
+
// (verified 2026-04-23), but operators on Windows may hand-edit with
|
|
1182
|
+
// editors that rewrite to CRLF; we shouldn't corrupt their file.
|
|
1183
|
+
const fmMatch = skillContent.match(/^---\r?\n/);
|
|
1184
|
+
if (fmMatch) {
|
|
1185
|
+
const searchFrom = fmMatch[0].length;
|
|
1186
|
+
// Close delimiter may be `\n---\n` or `\r\n---\r\n`; match either.
|
|
1187
|
+
const closeMatch = skillContent.slice(searchFrom).match(/\r?\n---\r?\n/);
|
|
1188
|
+
if (closeMatch) {
|
|
1189
|
+
const insertAt = searchFrom + closeMatch.index + closeMatch[0].length;
|
|
1190
|
+
return skillContent.slice(0, insertAt) + '\n' + block + skillContent.slice(insertAt);
|
|
856
1191
|
}
|
|
857
|
-
await fs.writeFile(bmadHelpPath, content, 'utf-8');
|
|
858
|
-
console.log(chalk.cyan(` + Registered MIL-STD-498 workflows in bmad-help.csv`));
|
|
859
1192
|
}
|
|
1193
|
+
return block + skillContent;
|
|
860
1194
|
}
|
|
861
1195
|
|
|
862
1196
|
/**
|
|
863
|
-
*
|
|
864
|
-
*
|
|
1197
|
+
* F1a — post-install on-prem phase-prefix pass.
|
|
1198
|
+
*
|
|
1199
|
+
* For each persona with an `on_prem_phase_prefix` in the canonical customize
|
|
1200
|
+
* source, locate the deployed `SKILL.md` in every tool skill-dir that exists
|
|
1201
|
+
* under `projectRoot`, and inject the prefix block. No-op when `profile` is
|
|
1202
|
+
* not `'on-prem'` so standard-profile installs never see on-prem content
|
|
1203
|
+
* (NFR44 — bug spec edge-case 1).
|
|
1204
|
+
*
|
|
1205
|
+
* Invariants:
|
|
1206
|
+
* - Never creates a tool directory that the install didn't create first
|
|
1207
|
+
* (bug spec edge-case 2): missing dirs are skipped.
|
|
1208
|
+
* - Malformed YAML in the source is logged and that persona is skipped
|
|
1209
|
+
* (bug spec edge-case 3) — other personas still get their prefix.
|
|
1210
|
+
* - A persona skill that hasn't been deployed (e.g. copilot's per-bug-A
|
|
1211
|
+
* routing gap, or personas consolidated upstream) is a silent skip —
|
|
1212
|
+
* we don't invent files the deployer didn't emit (bug spec edge-case 4).
|
|
1213
|
+
* - Re-running against an already-prefixed file replaces the existing
|
|
1214
|
+
* marker block rather than stacking a second one (bug spec edge-case 5).
|
|
1215
|
+
*
|
|
1216
|
+
* @param {string} projectRoot Absolute path to the install target
|
|
1217
|
+
* @param {string} [profile] Resolved profile value; only 'on-prem' acts
|
|
1218
|
+
* @param {string} [customizeSourceDir] Override for tests. Defaults to
|
|
1219
|
+
* `lib/bmad-customize/`.
|
|
1220
|
+
* @returns {Promise<{ tool: string, persona: string, injected: boolean }[]>}
|
|
1221
|
+
* Per-file outcome list — useful for test assertions and operator logs
|
|
865
1222
|
*/
|
|
866
|
-
async function
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
];
|
|
1223
|
+
async function applyOnPremPhasePrefixToDeployedSkills(
|
|
1224
|
+
projectRoot,
|
|
1225
|
+
profile,
|
|
1226
|
+
customizeSourceDir = path.join(__dirname, 'bmad-customize'),
|
|
1227
|
+
) {
|
|
1228
|
+
if (profile !== 'on-prem') {
|
|
1229
|
+
return [];
|
|
1230
|
+
}
|
|
1231
|
+
if (!projectRoot || typeof projectRoot !== 'string') {
|
|
1232
|
+
return [];
|
|
1233
|
+
}
|
|
1234
|
+
if (!fs.existsSync(customizeSourceDir)) {
|
|
1235
|
+
return [];
|
|
1236
|
+
}
|
|
881
1237
|
|
|
882
|
-
//
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1238
|
+
// Build the persona → prefix map once. Malformed sources are logged and
|
|
1239
|
+
// skipped (bug spec edge-case 3).
|
|
1240
|
+
const personaPrefix = new Map();
|
|
1241
|
+
for (const [personaId, skillDirName] of Object.entries(PERSONA_SKILL_MAP)) {
|
|
1242
|
+
const sourceFile = path.join(customizeSourceDir, `${personaId}.customize.yaml`);
|
|
1243
|
+
if (!fs.existsSync(sourceFile)) continue;
|
|
1244
|
+
let doc;
|
|
1245
|
+
try {
|
|
1246
|
+
doc = jsYaml.load(await fs.readFile(sourceFile, 'utf8'));
|
|
1247
|
+
} catch (err) {
|
|
1248
|
+
console.warn(chalk.yellow(
|
|
1249
|
+
` on-prem prefix: skipping ${personaId} — malformed source YAML: ${err.message}`
|
|
1250
|
+
));
|
|
1251
|
+
continue;
|
|
891
1252
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1253
|
+
if (!doc || typeof doc !== 'object') continue;
|
|
1254
|
+
const prefix = doc.on_prem_phase_prefix;
|
|
1255
|
+
if (typeof prefix !== 'string' || !prefix.trim()) continue;
|
|
1256
|
+
personaPrefix.set(skillDirName, prefix);
|
|
1257
|
+
}
|
|
1258
|
+
if (personaPrefix.size === 0) return [];
|
|
1259
|
+
|
|
1260
|
+
const results = [];
|
|
1261
|
+
for (const toolRel of TOOL_SKILL_DIRS) {
|
|
1262
|
+
const toolSkillsDir = path.join(projectRoot, toolRel);
|
|
1263
|
+
if (!fs.existsSync(toolSkillsDir)) continue; // tool not installed
|
|
1264
|
+
|
|
1265
|
+
for (const [skillDirName, prefix] of personaPrefix) {
|
|
1266
|
+
const skillDir = path.join(toolSkillsDir, skillDirName);
|
|
1267
|
+
const skillFile = path.join(skillDir, 'SKILL.md');
|
|
1268
|
+
if (!fs.existsSync(skillFile)) {
|
|
1269
|
+
// Persona not deployed for this tool — e.g. copilot routing gap
|
|
1270
|
+
// (tracked separately). Do not invent files.
|
|
1271
|
+
continue;
|
|
1272
|
+
}
|
|
1273
|
+
let content;
|
|
1274
|
+
try {
|
|
1275
|
+
content = await fs.readFile(skillFile, 'utf8');
|
|
1276
|
+
} catch (err) {
|
|
1277
|
+
console.warn(chalk.yellow(
|
|
1278
|
+
` on-prem prefix: could not read ${skillFile}: ${err.message}`
|
|
1279
|
+
));
|
|
1280
|
+
continue;
|
|
1281
|
+
}
|
|
1282
|
+
const updated = injectOnPremPrefixBlock(content, prefix);
|
|
1283
|
+
if (updated === content) {
|
|
1284
|
+
results.push({ tool: toolRel, persona: skillDirName, injected: false });
|
|
1285
|
+
continue;
|
|
1286
|
+
}
|
|
1287
|
+
try {
|
|
1288
|
+
await fs.writeFile(skillFile, updated, 'utf8');
|
|
1289
|
+
results.push({ tool: toolRel, persona: skillDirName, injected: true });
|
|
1290
|
+
} catch (err) {
|
|
1291
|
+
console.warn(chalk.yellow(
|
|
1292
|
+
` on-prem prefix: could not write ${skillFile}: ${err.message}`
|
|
1293
|
+
));
|
|
1294
|
+
}
|
|
905
1295
|
}
|
|
906
|
-
await fs.writeFile(bmadHelpPath, content, 'utf-8');
|
|
907
|
-
console.log(chalk.cyan(` + Registered ML workflows in bmad-help.csv`));
|
|
908
1296
|
}
|
|
1297
|
+
|
|
1298
|
+
if (results.some(r => r.injected)) {
|
|
1299
|
+
const count = results.filter(r => r.injected).length;
|
|
1300
|
+
console.log(chalk.cyan(` + Injected on-prem phase prefix into ${count} persona SKILL.md file(s)`));
|
|
1301
|
+
}
|
|
1302
|
+
return results;
|
|
909
1303
|
}
|
|
910
1304
|
|
|
1305
|
+
// Story 22.6 — `applyCustomizations()` removed. Its responsibilities are now
|
|
1306
|
+
// handled by bmad-method 6.3.0's PluginResolver, invoked via --custom-source
|
|
1307
|
+
// against the staged plugin bundle (see stagePlugin() above). The supporting
|
|
1308
|
+
// `registerMilWorkflows()` and `registerMlWorkflows()` helpers were removed
|
|
1309
|
+
// alongside it — their CSV registrations now ship in the plugin's own
|
|
1310
|
+
// `module-help.csv` and are merged by BMAD's installer.
|
|
1311
|
+
//
|
|
1312
|
+
// The ~290 lines of manifest-surgery, custom-agent-YAML staging, and CSV
|
|
1313
|
+
// rewriting that used to live here are gone — BMAD owns placement now.
|
|
1314
|
+
// Remaining helpers below (deployMethodology, prePopulateBmadCache, etc.) are
|
|
1315
|
+
// independent concerns invoked from installBmad()/updateBmad() directly.
|
|
1316
|
+
|
|
911
1317
|
/**
|
|
912
1318
|
* Deploy the methodology presentation to the target project's _bmad-output/methodology/ directory.
|
|
913
1319
|
* Version-aware: skips if target is same or newer; overwrites only with --force.
|
|
@@ -1023,9 +1429,109 @@ async function prePopulateBmadCache(force = false) {
|
|
|
1023
1429
|
}
|
|
1024
1430
|
}
|
|
1025
1431
|
|
|
1432
|
+
// ── Canonical config helpers (Story 22.7) ───────────────────────────────────
|
|
1433
|
+
|
|
1434
|
+
/**
|
|
1435
|
+
* Read and parse the canonical v6.3.0 project config at `_bmad/bmm/config.yaml`.
|
|
1436
|
+
*
|
|
1437
|
+
* This is the ONLY sanctioned read path for BMAD-canonical values in ma-agents
|
|
1438
|
+
* code. If the file is absent, this returns `null` — callers MUST NOT fall
|
|
1439
|
+
* back silently to the legacy `_bmad/_config/manifest.yaml`. Callers that need
|
|
1440
|
+
* to handle a legacy install should invoke `ensureCanonicalConfigLocation()`
|
|
1441
|
+
* BEFORE reading so that the layout is normalized first.
|
|
1442
|
+
*
|
|
1443
|
+
* Malformed YAML logs a warning and returns `null` rather than throwing — the
|
|
1444
|
+
* caller decides whether to error out or fall back to defaults.
|
|
1445
|
+
*
|
|
1446
|
+
* @param {string} projectRoot - Absolute path to the project root
|
|
1447
|
+
* @returns {object|null} Parsed config object, or `null` when the file is
|
|
1448
|
+
* missing or unreadable.
|
|
1449
|
+
*/
|
|
1450
|
+
function readCanonicalBmadConfig(projectRoot) {
|
|
1451
|
+
const configPath = path.join(projectRoot, CANONICAL_CONFIG_REL);
|
|
1452
|
+
if (!fs.existsSync(configPath)) {
|
|
1453
|
+
return null;
|
|
1454
|
+
}
|
|
1455
|
+
try {
|
|
1456
|
+
const raw = fs.readFileSync(configPath, 'utf-8');
|
|
1457
|
+
if (!raw.trim()) {
|
|
1458
|
+
// Empty file — treat as "present but has no values".
|
|
1459
|
+
return {};
|
|
1460
|
+
}
|
|
1461
|
+
const parsed = yaml.parse(raw);
|
|
1462
|
+
// yaml.parse returns null for `{}` / empty-like content; normalize.
|
|
1463
|
+
return parsed === null || parsed === undefined ? {} : parsed;
|
|
1464
|
+
} catch (err) {
|
|
1465
|
+
console.log(chalk.yellow(
|
|
1466
|
+
` Warning: failed to parse ${CANONICAL_CONFIG_REL}: ${err.message}`
|
|
1467
|
+
));
|
|
1468
|
+
return null;
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
/**
|
|
1473
|
+
* Migration shim: normalize the project layout so that canonical config lives
|
|
1474
|
+
* at `_bmad/bmm/config.yaml` (v6.3.0) instead of `_bmad/_config/manifest.yaml`
|
|
1475
|
+
* (legacy pre-6.3 location).
|
|
1476
|
+
*
|
|
1477
|
+
* Behavior (idempotent):
|
|
1478
|
+
* - Both files present: PREFER_NEW — log that legacy exists, do nothing.
|
|
1479
|
+
* The new path already wins; operators can delete the legacy file at
|
|
1480
|
+
* their discretion. We never read it silently.
|
|
1481
|
+
* - Only new path present: no-op (normal 6.3+ install).
|
|
1482
|
+
* - Only legacy path present: flag for migration — return the signal so the
|
|
1483
|
+
* caller can invoke bmad-method's installer to regenerate the new
|
|
1484
|
+
* layout. We deliberately DO NOT translate-in-place: the legacy manifest
|
|
1485
|
+
* schema differs from the new config schema (module list vs. shared
|
|
1486
|
+
* core+module sections), and a faithful translation requires upstream
|
|
1487
|
+
* knowledge we don't own.
|
|
1488
|
+
* - Neither present: no-op (fresh install — bmad-method will create
|
|
1489
|
+
* the new layout).
|
|
1490
|
+
*
|
|
1491
|
+
* This function NEVER writes to the new path from legacy content and NEVER
|
|
1492
|
+
* reads legacy content as a value source. Its sole job is to surface the
|
|
1493
|
+
* drift signal so the caller can trigger regeneration via the normal install
|
|
1494
|
+
* flow, which writes `_bmad/bmm/config.yaml` directly.
|
|
1495
|
+
*
|
|
1496
|
+
* @param {string} projectRoot - Absolute path to the project root
|
|
1497
|
+
* @returns {{
|
|
1498
|
+
* newExists: boolean,
|
|
1499
|
+
* legacyExists: boolean,
|
|
1500
|
+
* needsRegeneration: boolean,
|
|
1501
|
+
* }}
|
|
1502
|
+
*/
|
|
1503
|
+
function ensureCanonicalConfigLocation(projectRoot) {
|
|
1504
|
+
const newPath = path.join(projectRoot, CANONICAL_CONFIG_REL);
|
|
1505
|
+
const legacyPath = path.join(projectRoot, LEGACY_MANIFEST_REL);
|
|
1506
|
+
const newExists = fs.existsSync(newPath);
|
|
1507
|
+
const legacyExists = fs.existsSync(legacyPath);
|
|
1508
|
+
|
|
1509
|
+
if (newExists && legacyExists) {
|
|
1510
|
+
// Drift state. New wins; warn once so operators notice the legacy
|
|
1511
|
+
// file still lingering in `_bmad/_config/`. Story 22.6 removes the
|
|
1512
|
+
// manifest-surgery code that was writing there, so this file becomes
|
|
1513
|
+
// a non-participant after upgrade.
|
|
1514
|
+
console.log(chalk.yellow(
|
|
1515
|
+
` Notice: legacy ${LEGACY_MANIFEST_REL} still present alongside ${CANONICAL_CONFIG_REL}. ` +
|
|
1516
|
+
`The canonical v6.3.0 path is used; the legacy file is ignored and may be removed.`
|
|
1517
|
+
));
|
|
1518
|
+
return { newExists: true, legacyExists: true, needsRegeneration: false };
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
if (!newExists && legacyExists) {
|
|
1522
|
+
console.log(chalk.yellow(
|
|
1523
|
+
` Detected legacy BMAD config at ${LEGACY_MANIFEST_REL} with no ${CANONICAL_CONFIG_REL}. ` +
|
|
1524
|
+
`bmad-method will regenerate the canonical v6.3.0 layout during install — legacy file is NOT read as a fallback.`
|
|
1525
|
+
));
|
|
1526
|
+
return { newExists: false, legacyExists: true, needsRegeneration: true };
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
return { newExists, legacyExists: false, needsRegeneration: false };
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1026
1532
|
// ── Migration constants ─────────────────────────────────────────────────────
|
|
1027
1533
|
|
|
1028
|
-
const BMAD_TARGET_VERSION = '6.
|
|
1534
|
+
const BMAD_TARGET_VERSION = '6.5.0';
|
|
1029
1535
|
const BMAD_MIGRATION_THRESHOLD = '6.2.0'; // versions below this need migration
|
|
1030
1536
|
const BACKUP_DIR_NAME = '.backup-pre-migration';
|
|
1031
1537
|
|
|
@@ -1255,12 +1761,440 @@ function parseCustomizeYaml(content) {
|
|
|
1255
1761
|
return result;
|
|
1256
1762
|
}
|
|
1257
1763
|
|
|
1764
|
+
// ─── F1b: Legacy→plugin-bundle translation for upgrade migration ────────────
|
|
1765
|
+
//
|
|
1766
|
+
// Pre-6.3.0 ma-agents deployed `*.customize.yaml` files to `_bmad/_config/agents/`
|
|
1767
|
+
// where BMAD's agent-compilation read persona/memories/critical_actions and
|
|
1768
|
+
// injected them into the compiled agent prompts. Story 22.6 removed that
|
|
1769
|
+
// compilation step and now delegates placement to bmad-method 6.3.0's
|
|
1770
|
+
// PluginResolver via `--custom-source`. Result: `_bmad/_config/agents/` is no
|
|
1771
|
+
// longer a deployment target — the deployed LLM-readable skills live at
|
|
1772
|
+
// `<tool-skillsDir>/bmad-agent-<name>/SKILL.md` (for bmm-* personas BMAD
|
|
1773
|
+
// itself deploys) and `<tool-skillsDir>/ma-agent-<name>/SKILL.md` (for the
|
|
1774
|
+
// ma-agents-owned custom agents bundled in our plugin).
|
|
1775
|
+
//
|
|
1776
|
+
// Consequence: on upgrade from pre-6.3, simply merging user edits back into
|
|
1777
|
+
// `_bmad/_config/agents/` silently strands them. This translator bridges the
|
|
1778
|
+
// gap by parsing legacy `.customize.yaml` backups and appending user-edited
|
|
1779
|
+
// content to the deployed `SKILL.md` files with idempotency markers so
|
|
1780
|
+
// repeated runs do not duplicate content.
|
|
1781
|
+
|
|
1782
|
+
/**
|
|
1783
|
+
* Block marker used to delimit translated user customizations inside a
|
|
1784
|
+
* deployed SKILL.md file. Stable across runs so the translator can detect
|
|
1785
|
+
* a prior apply and replace the block rather than appending a second copy.
|
|
1786
|
+
* Public so tests can locate the block deterministically.
|
|
1787
|
+
*/
|
|
1788
|
+
const MA_CUSTOMIZATIONS_MARKER_START = '<!-- ma-agents:user-customizations:start -->';
|
|
1789
|
+
const MA_CUSTOMIZATIONS_MARKER_END = '<!-- ma-agents:user-customizations:end -->';
|
|
1790
|
+
|
|
1791
|
+
/**
|
|
1792
|
+
* Diagnostic directory where legacy `.customize.yaml` files are preserved when
|
|
1793
|
+
* they contain fields that cannot be translated to the plugin-bundle format.
|
|
1794
|
+
* Kept under `_bmad/` so it survives across installs and is discoverable by
|
|
1795
|
+
* users looking for their pre-upgrade customizations.
|
|
1796
|
+
*
|
|
1797
|
+
* Stored as a forward-slash string (not `path.join`) so it is stable across
|
|
1798
|
+
* Windows and POSIX in user-facing log output; callers that need a
|
|
1799
|
+
* filesystem path should still pass it through `path.join`/`path.resolve`
|
|
1800
|
+
* which normalize mixed separators on Windows.
|
|
1801
|
+
*/
|
|
1802
|
+
const LEGACY_CUSTOMIZATIONS_DIR = '_bmad/.ma-agents-customizations-legacy';
|
|
1803
|
+
|
|
1804
|
+
/**
|
|
1805
|
+
* Map a legacy `.customize.yaml` filename (e.g. `bmm-pm.customize.yaml`) to the
|
|
1806
|
+
* set of candidate deployed skill directory names. Legacy files targeted the
|
|
1807
|
+
* pre-6.3 BMAD persona IDs (`bmm-<name>`); v6.3.0 deploys those personas as
|
|
1808
|
+
* plugin skills named `bmad-agent-<name>` and ma-agents-owned personas as
|
|
1809
|
+
* `ma-agent-<name>`. Both candidates are returned so the translator can
|
|
1810
|
+
* overlay whichever the upstream installer actually produced.
|
|
1811
|
+
*
|
|
1812
|
+
* @param {string} customizeFilename - e.g. `bmm-pm.customize.yaml`
|
|
1813
|
+
* @returns {string[]} Candidate skill directory names ordered by preference
|
|
1814
|
+
*/
|
|
1815
|
+
function getCandidateSkillDirNames(customizeFilename) {
|
|
1816
|
+
const base = customizeFilename.replace(/\.customize\.yaml$/, '');
|
|
1817
|
+
// `generic.customize.yaml` targeted a non-persona umbrella file that
|
|
1818
|
+
// BMAD 6.3.0 does not deploy — no skill candidate.
|
|
1819
|
+
if (base === 'generic') return [];
|
|
1820
|
+
// `bmm-<name>` legacy → `bmad-agent-<name>` (BMAD core) or `ma-agent-<name>`
|
|
1821
|
+
// (ma-agents plugin, for cyber/devops/sqa/sre/ml which used bmm-<name>
|
|
1822
|
+
// legacy filenames but are now owned by our plugin).
|
|
1823
|
+
if (base.startsWith('bmm-')) {
|
|
1824
|
+
const suffix = base.slice('bmm-'.length);
|
|
1825
|
+
return [`bmad-agent-${suffix}`, `ma-agent-${suffix}`];
|
|
1826
|
+
}
|
|
1827
|
+
// Already in `ma-agent-*` form → pass through.
|
|
1828
|
+
if (base.startsWith('ma-agent-')) return [base];
|
|
1829
|
+
// Unknown prefix — try as-is and as a `ma-agent-<id>` variant.
|
|
1830
|
+
return [base, `ma-agent-${base}`];
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
/**
|
|
1834
|
+
* Enumerate the IDE/BMAD tool skill directories that may contain deployed
|
|
1835
|
+
* persona skills. Reads from `lib/agents.js` so the list stays in lockstep
|
|
1836
|
+
* with the installer's own fan-out (Story 22.10). Returns absolute paths to
|
|
1837
|
+
* directories that actually exist on disk; non-existent tool dirs are
|
|
1838
|
+
* silently skipped (the tool was not selected for install).
|
|
1839
|
+
*
|
|
1840
|
+
* @param {string} projectRoot - Absolute path to the project root
|
|
1841
|
+
* @returns {string[]} Absolute skills-dir paths that exist
|
|
1842
|
+
*/
|
|
1843
|
+
function getDeployedSkillsRoots(projectRoot) {
|
|
1844
|
+
const agentsModule = require('./agents');
|
|
1845
|
+
const roots = new Set();
|
|
1846
|
+
for (const agent of agentsModule.getAllAgents()) {
|
|
1847
|
+
if (!agent || !agent.skillsDir) continue;
|
|
1848
|
+
const abs = path.resolve(projectRoot, agent.skillsDir);
|
|
1849
|
+
if (fs.existsSync(abs) && fs.statSync(abs).isDirectory()) {
|
|
1850
|
+
roots.add(abs);
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
return [...roots];
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
/**
|
|
1857
|
+
* Build the translated markdown block to append to a deployed SKILL.md.
|
|
1858
|
+
* Encodes legacy user edits as a clearly-labelled section between the
|
|
1859
|
+
* ma-customizations markers. Pure string building — no filesystem access.
|
|
1860
|
+
*
|
|
1861
|
+
* Translation policy:
|
|
1862
|
+
* - `memories[]` → bullet list under "### User Memories"
|
|
1863
|
+
* - `critical_actions[]` (non-standard only) → numbered list under
|
|
1864
|
+
* "### Additional Critical Actions (from pre-6.3 customization)"
|
|
1865
|
+
* - `persona.*` lines (raw YAML child lines) → fenced YAML block under
|
|
1866
|
+
* "### User Persona Overrides" so users can re-apply manually; we do
|
|
1867
|
+
* NOT rewrite the deployed persona narrative (bmad-method v6.3.0 owns
|
|
1868
|
+
* that content in SKILL.md's Identity/Communication Style sections).
|
|
1869
|
+
*
|
|
1870
|
+
* @param {object} parsed - Output of parseCustomizeYaml()
|
|
1871
|
+
* @param {string} sourceFilename - Original `.customize.yaml` name, for trace
|
|
1872
|
+
* @returns {{ block: string, droppedFields: string[] }}
|
|
1873
|
+
*/
|
|
1874
|
+
function buildCustomizationsMarkdownBlock(parsed, sourceFilename) {
|
|
1875
|
+
// Defang our own marker literals inside user-originated text BEFORE
|
|
1876
|
+
// interpolating it into the block template. A user memory/critical-
|
|
1877
|
+
// action/persona line that contains the literal marker would otherwise
|
|
1878
|
+
// let an attacker (or accidental copy-paste) break out of the block
|
|
1879
|
+
// and either swallow content during idempotent replace or inject
|
|
1880
|
+
// instructions outside the "this is user-migrated content" region.
|
|
1881
|
+
// A zero-width space inside the `ma-agents:` prefix is invisible to the
|
|
1882
|
+
// LLM's reader but disambiguates the string from our real markers.
|
|
1883
|
+
const defang = (s) => {
|
|
1884
|
+
if (typeof s !== 'string') return s;
|
|
1885
|
+
return s.replace(
|
|
1886
|
+
/<!--\s*ma-agents:user-customizations:(start|end)\s*-->/g,
|
|
1887
|
+
'<!-- ma-agents\u200B:user-customizations:$1 -->'
|
|
1888
|
+
);
|
|
1889
|
+
};
|
|
1890
|
+
|
|
1891
|
+
const lines = [];
|
|
1892
|
+
lines.push(MA_CUSTOMIZATIONS_MARKER_START);
|
|
1893
|
+
lines.push('');
|
|
1894
|
+
lines.push(`## User Customizations (migrated from ${defang(sourceFilename)})`);
|
|
1895
|
+
lines.push('');
|
|
1896
|
+
lines.push('> Auto-migrated by ma-agents on upgrade to plugin-bundle format.');
|
|
1897
|
+
lines.push('> Edit this block directly or re-run `ma-agents install` after');
|
|
1898
|
+
lines.push(`> updating \`${defang(sourceFilename)}\` in \`${LEGACY_CUSTOMIZATIONS_DIR}/\`.`);
|
|
1899
|
+
lines.push('');
|
|
1900
|
+
|
|
1901
|
+
// User-added memories (always user content).
|
|
1902
|
+
if (parsed.memories && parsed.memories.length > 0) {
|
|
1903
|
+
lines.push('### User Memories');
|
|
1904
|
+
lines.push('');
|
|
1905
|
+
for (const memory of parsed.memories) {
|
|
1906
|
+
lines.push(`- ${defang(memory)}`);
|
|
1907
|
+
}
|
|
1908
|
+
lines.push('');
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
// Non-standard critical_actions — filter out the standard ma-agents set
|
|
1912
|
+
// so upgrade does not duplicate what bmad-method already ships.
|
|
1913
|
+
const userCriticalActions = (parsed.criticalActions || []).filter(
|
|
1914
|
+
ca => !isStandardCriticalAction(ca)
|
|
1915
|
+
);
|
|
1916
|
+
if (userCriticalActions.length > 0) {
|
|
1917
|
+
lines.push('### Additional Critical Actions');
|
|
1918
|
+
lines.push('');
|
|
1919
|
+
userCriticalActions.forEach((ca, idx) => {
|
|
1920
|
+
lines.push(`${idx + 1}. ${defang(ca)}`);
|
|
1921
|
+
});
|
|
1922
|
+
lines.push('');
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
// Persona overrides — preserve as raw YAML because we cannot safely
|
|
1926
|
+
// rewrite the persona narrative without breaking the bmad-method-owned
|
|
1927
|
+
// SKILL.md structure. Users can read and re-apply as needed.
|
|
1928
|
+
const droppedFields = [];
|
|
1929
|
+
if (parsed.personaLines && parsed.personaLines.length > 0) {
|
|
1930
|
+
lines.push('### User Persona Overrides');
|
|
1931
|
+
lines.push('');
|
|
1932
|
+
lines.push('> NOTE: v6.3.0 deploys persona text directly in SKILL.md above.');
|
|
1933
|
+
lines.push('> These legacy overrides are preserved verbatim — review and');
|
|
1934
|
+
lines.push('> edit the persona sections above if you want them active.');
|
|
1935
|
+
lines.push('');
|
|
1936
|
+
lines.push('```yaml');
|
|
1937
|
+
lines.push('persona:');
|
|
1938
|
+
for (const ln of parsed.personaLines) {
|
|
1939
|
+
lines.push(defang(ln));
|
|
1940
|
+
}
|
|
1941
|
+
lines.push('```');
|
|
1942
|
+
lines.push('');
|
|
1943
|
+
droppedFields.push('persona (preserved as read-only YAML; v6.3.0 persona schema differs)');
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
lines.push(MA_CUSTOMIZATIONS_MARKER_END);
|
|
1947
|
+
return { block: lines.join('\n'), droppedFields };
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
/**
|
|
1951
|
+
* Apply the translated block to a single SKILL.md file. Idempotent: if the
|
|
1952
|
+
* file already contains a marker block, it is replaced in place; otherwise
|
|
1953
|
+
* the block is appended with a single blank line of separation. Writes are
|
|
1954
|
+
* skipped when the existing block byte-matches the incoming block (repeated
|
|
1955
|
+
* runs do not bump mtime).
|
|
1956
|
+
*
|
|
1957
|
+
* @param {string} skillFile - Absolute path to the SKILL.md
|
|
1958
|
+
* @param {string} block - Translated markdown block (with markers)
|
|
1959
|
+
* @returns {Promise<boolean>} true if the file was written, false if no-op
|
|
1960
|
+
*/
|
|
1961
|
+
async function applyCustomizationsBlockToSkill(skillFile, block) {
|
|
1962
|
+
const existing = await fs.readFile(skillFile, 'utf-8');
|
|
1963
|
+
const startIdx = existing.indexOf(MA_CUSTOMIZATIONS_MARKER_START);
|
|
1964
|
+
const endIdx = existing.indexOf(MA_CUSTOMIZATIONS_MARKER_END);
|
|
1965
|
+
let next;
|
|
1966
|
+
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
1967
|
+
// Replace existing block (idempotent on second run).
|
|
1968
|
+
const before = existing.slice(0, startIdx);
|
|
1969
|
+
const after = existing.slice(endIdx + MA_CUSTOMIZATIONS_MARKER_END.length);
|
|
1970
|
+
next = `${before.trimEnd()}\n\n${block}\n${after.trimStart() ? '\n' + after.trimStart() : ''}`;
|
|
1971
|
+
} else {
|
|
1972
|
+
// Append with separation.
|
|
1973
|
+
next = `${existing.trimEnd()}\n\n${block}\n`;
|
|
1974
|
+
}
|
|
1975
|
+
if (next === existing) return false;
|
|
1976
|
+
await fs.writeFile(skillFile, next, 'utf-8');
|
|
1977
|
+
return true;
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
/**
|
|
1981
|
+
* Translate user-edited legacy `.customize.yaml` files into appended blocks
|
|
1982
|
+
* on the deployed SKILL.md files across every tool skills-dir. Non-destructive
|
|
1983
|
+
* (wraps edits in marker block), idempotent (re-runs replace the block), and
|
|
1984
|
+
* preserves the original legacy file alongside so users can diff/inspect.
|
|
1985
|
+
*
|
|
1986
|
+
* @param {string} projectRoot - Absolute path to the project root
|
|
1987
|
+
* @returns {Promise<{
|
|
1988
|
+
* translated: Array<{ file: string, skillFiles: string[] }>,
|
|
1989
|
+
* preserved: string[],
|
|
1990
|
+
* warnings: string[],
|
|
1991
|
+
* noTargetFound: string[],
|
|
1992
|
+
* }>}
|
|
1993
|
+
*/
|
|
1994
|
+
async function translateUserCustomizations(projectRoot) {
|
|
1995
|
+
const backupDir = path.join(projectRoot, CONFIG_DIR, BACKUP_DIR_NAME);
|
|
1996
|
+
const legacyPreserveDir = path.join(projectRoot, LEGACY_CUSTOMIZATIONS_DIR);
|
|
1997
|
+
const result = {
|
|
1998
|
+
translated: [],
|
|
1999
|
+
preserved: [],
|
|
2000
|
+
warnings: [],
|
|
2001
|
+
noTargetFound: [],
|
|
2002
|
+
};
|
|
2003
|
+
|
|
2004
|
+
if (!fs.existsSync(backupDir)) {
|
|
2005
|
+
return result;
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
// Enumerate `.customize.yaml` entries but verify each is a regular file.
|
|
2009
|
+
// A directory or symlink-to-directory named with the suffix would otherwise
|
|
2010
|
+
// trigger a spurious "malformed" warning and pointless preservation on
|
|
2011
|
+
// every run — skip silently at the source.
|
|
2012
|
+
const backupEntries = await fs.readdir(backupDir, { withFileTypes: true });
|
|
2013
|
+
const backupFiles = backupEntries
|
|
2014
|
+
.filter(d => d.isFile() && d.name.endsWith('.customize.yaml'))
|
|
2015
|
+
.map(d => d.name);
|
|
2016
|
+
if (backupFiles.length === 0) {
|
|
2017
|
+
return result;
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
/**
|
|
2021
|
+
* Recognized top-level keys in a legacy `.customize.yaml`. Anything else
|
|
2022
|
+
* the user added (e.g. `extra_config`) cannot be translated without a
|
|
2023
|
+
* field-level mapping and is surfaced as a drop warning.
|
|
2024
|
+
*/
|
|
2025
|
+
const KNOWN_TOP_LEVEL_KEYS = new Set([
|
|
2026
|
+
'memories', 'critical_actions', 'persona',
|
|
2027
|
+
// Epic 21 / Story 21.7 keys (handled by F1a, safe to ignore here):
|
|
2028
|
+
'phase', 'on_prem_phase_prefix',
|
|
2029
|
+
]);
|
|
2030
|
+
|
|
2031
|
+
const deployedSkillsRoots = getDeployedSkillsRoots(projectRoot);
|
|
2032
|
+
if (deployedSkillsRoots.length === 0) {
|
|
2033
|
+
result.warnings.push(
|
|
2034
|
+
'No deployed tool skills directories found under projectRoot — ' +
|
|
2035
|
+
'customizations preserved for manual reapplication.'
|
|
2036
|
+
);
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
// Resolve shipped customize defaults so we can tell which legacy files
|
|
2040
|
+
// represent actual user edits vs. verbatim-shipped defaults that the
|
|
2041
|
+
// user never touched. If the user never edited the file, we skip
|
|
2042
|
+
// translation entirely (no noise on the deployed SKILL.md).
|
|
2043
|
+
const shippedDir = path.join(__dirname, 'bmad-customize');
|
|
2044
|
+
|
|
2045
|
+
for (const file of backupFiles) {
|
|
2046
|
+
const backupPath = path.join(backupDir, file);
|
|
2047
|
+
let parsed;
|
|
2048
|
+
try {
|
|
2049
|
+
const backupContent = await fs.readFile(backupPath, 'utf-8');
|
|
2050
|
+
parsed = parseCustomizeYaml(backupContent);
|
|
2051
|
+
} catch (err) {
|
|
2052
|
+
// Edge-case: legacy file malformed — log and continue so other
|
|
2053
|
+
// files still migrate. Preserves user data by copying the raw
|
|
2054
|
+
// file to the diagnostic directory.
|
|
2055
|
+
result.warnings.push(
|
|
2056
|
+
`Skipped malformed legacy file ${file}: ${err.message}`
|
|
2057
|
+
);
|
|
2058
|
+
try {
|
|
2059
|
+
await fs.ensureDir(legacyPreserveDir);
|
|
2060
|
+
await fs.copy(backupPath, path.join(legacyPreserveDir, file), { overwrite: true });
|
|
2061
|
+
result.preserved.push(file);
|
|
2062
|
+
} catch { /* best-effort preservation */ }
|
|
2063
|
+
continue;
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2066
|
+
// Scan the raw YAML for unknown top-level keys (user added a custom
|
|
2067
|
+
// field that cannot be translated). Surface as a non-blocking warning
|
|
2068
|
+
// so the user knows to re-apply manually from the preserved file.
|
|
2069
|
+
const unknownKeys = [];
|
|
2070
|
+
for (const line of (parsed.raw || '').split('\n')) {
|
|
2071
|
+
const m = line.match(/^([a-z_][a-z0-9_]*)\s*:/);
|
|
2072
|
+
if (m && !KNOWN_TOP_LEVEL_KEYS.has(m[1])) {
|
|
2073
|
+
if (!unknownKeys.includes(m[1])) unknownKeys.push(m[1]);
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
// Detect user content vs. shipped defaults.
|
|
2078
|
+
const userMemories = parsed.memories || [];
|
|
2079
|
+
const userCriticalActions = (parsed.criticalActions || []).filter(
|
|
2080
|
+
ca => !isStandardCriticalAction(ca)
|
|
2081
|
+
);
|
|
2082
|
+
let hasPersonaOverride = false;
|
|
2083
|
+
const shippedPath = path.join(shippedDir, file);
|
|
2084
|
+
if (fs.existsSync(shippedPath)) {
|
|
2085
|
+
try {
|
|
2086
|
+
const shippedContent = await fs.readFile(shippedPath, 'utf-8');
|
|
2087
|
+
const shippedParsed = parseCustomizeYaml(shippedContent);
|
|
2088
|
+
if (
|
|
2089
|
+
parsed.personaLines.join('\n').trim() !==
|
|
2090
|
+
shippedParsed.personaLines.join('\n').trim() &&
|
|
2091
|
+
parsed.personaLines.length > 0
|
|
2092
|
+
) {
|
|
2093
|
+
hasPersonaOverride = true;
|
|
2094
|
+
}
|
|
2095
|
+
} catch {
|
|
2096
|
+
// If shipped default unreadable, treat any persona content as user edit.
|
|
2097
|
+
if (parsed.personaLines.length > 0) hasPersonaOverride = true;
|
|
2098
|
+
}
|
|
2099
|
+
} else if (parsed.personaLines.length > 0) {
|
|
2100
|
+
hasPersonaOverride = true;
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
const hasUserContent =
|
|
2104
|
+
userMemories.length > 0 ||
|
|
2105
|
+
userCriticalActions.length > 0 ||
|
|
2106
|
+
hasPersonaOverride ||
|
|
2107
|
+
unknownKeys.length > 0;
|
|
2108
|
+
if (!hasUserContent) continue;
|
|
2109
|
+
|
|
2110
|
+
// Build the translated block using only user-originated content.
|
|
2111
|
+
const userParsed = {
|
|
2112
|
+
memories: userMemories,
|
|
2113
|
+
criticalActions: userCriticalActions,
|
|
2114
|
+
// Only attach personaLines if the user actually overrode them,
|
|
2115
|
+
// so unchanged shipped persona defaults don't leak into the block.
|
|
2116
|
+
personaLines: hasPersonaOverride ? parsed.personaLines : [],
|
|
2117
|
+
};
|
|
2118
|
+
const { block, droppedFields } = buildCustomizationsMarkdownBlock(userParsed, file);
|
|
2119
|
+
|
|
2120
|
+
// Fan out to every candidate skill dir across every installed tool.
|
|
2121
|
+
const candidates = getCandidateSkillDirNames(file);
|
|
2122
|
+
const skillFilesTouched = [];
|
|
2123
|
+
for (const root of deployedSkillsRoots) {
|
|
2124
|
+
for (const skillDirName of candidates) {
|
|
2125
|
+
const skillFile = path.join(root, skillDirName, 'SKILL.md');
|
|
2126
|
+
if (!fs.existsSync(skillFile)) continue;
|
|
2127
|
+
try {
|
|
2128
|
+
// Return value (changed/no-op) is intentionally ignored —
|
|
2129
|
+
// for the summary we report coverage, not mtime bumps.
|
|
2130
|
+
// Idempotent re-runs report the same skill file list.
|
|
2131
|
+
await applyCustomizationsBlockToSkill(skillFile, block);
|
|
2132
|
+
skillFilesTouched.push(skillFile);
|
|
2133
|
+
} catch (err) {
|
|
2134
|
+
result.warnings.push(
|
|
2135
|
+
`Failed to apply translation to ${skillFile}: ${err.message}`
|
|
2136
|
+
);
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
// Always preserve the legacy file so the user can diff/re-apply, and
|
|
2142
|
+
// emit a dropped-field warning if any field could not translate 1:1.
|
|
2143
|
+
try {
|
|
2144
|
+
await fs.ensureDir(legacyPreserveDir);
|
|
2145
|
+
await fs.copy(backupPath, path.join(legacyPreserveDir, file), { overwrite: true });
|
|
2146
|
+
if (!result.preserved.includes(file)) result.preserved.push(file);
|
|
2147
|
+
} catch (err) {
|
|
2148
|
+
result.warnings.push(
|
|
2149
|
+
`Could not preserve legacy file ${file} at ${legacyPreserveDir}: ${err.message}`
|
|
2150
|
+
);
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
if (droppedFields.length > 0) {
|
|
2154
|
+
result.warnings.push(
|
|
2155
|
+
`${file}: ${droppedFields.length} field(s) need manual review — ` +
|
|
2156
|
+
`${droppedFields.join(', ')} — see ${LEGACY_CUSTOMIZATIONS_DIR}/${file}`
|
|
2157
|
+
);
|
|
2158
|
+
}
|
|
2159
|
+
|
|
2160
|
+
if (unknownKeys.length > 0) {
|
|
2161
|
+
result.warnings.push(
|
|
2162
|
+
`${file}: unknown top-level key(s) [${unknownKeys.join(', ')}] ` +
|
|
2163
|
+
`have no plugin-bundle equivalent — original preserved at ` +
|
|
2164
|
+
`${LEGACY_CUSTOMIZATIONS_DIR}/${file}`
|
|
2165
|
+
);
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
if (skillFilesTouched.length === 0) {
|
|
2169
|
+
// No deployed target matched this legacy file — user customizations
|
|
2170
|
+
// could not reach any live skill. Non-blocking but visible.
|
|
2171
|
+
result.noTargetFound.push(file);
|
|
2172
|
+
result.warnings.push(
|
|
2173
|
+
`${file}: no deployed SKILL.md matched candidates ` +
|
|
2174
|
+
`[${candidates.join(', ')}] — reapply manually from ` +
|
|
2175
|
+
`${LEGACY_CUSTOMIZATIONS_DIR}/${file}`
|
|
2176
|
+
);
|
|
2177
|
+
} else {
|
|
2178
|
+
result.translated.push({ file, skillFiles: skillFilesTouched });
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
return result;
|
|
2183
|
+
}
|
|
2184
|
+
|
|
1258
2185
|
/**
|
|
1259
2186
|
* Merge user customizations from backed-up files into new customize.yaml files.
|
|
1260
2187
|
* Detects user-added memories, extra critical_actions, and persona overrides.
|
|
1261
2188
|
*
|
|
2189
|
+
* As of F1b: after the legacy-format merge, also invokes
|
|
2190
|
+
* {@link translateUserCustomizations} so the user's edits reach the deployed
|
|
2191
|
+
* plugin-bundle SKILL.md files. The legacy-format write is retained for
|
|
2192
|
+
* backward compatibility with installs that still read `_bmad/_config/agents/`
|
|
2193
|
+
* (e.g. the hash-comparison path in bmad-method 6.3.0's installer.js@2706)
|
|
2194
|
+
* and for diagnostic visibility.
|
|
2195
|
+
*
|
|
1262
2196
|
* @param {string} projectRoot - Absolute path to the project root
|
|
1263
|
-
* @returns {Promise<{ merged: string[], skipped: string[] }>}
|
|
2197
|
+
* @returns {Promise<{ merged: string[], skipped: string[], translation?: object }>}
|
|
1264
2198
|
*/
|
|
1265
2199
|
async function mergeUserCustomizations(projectRoot) {
|
|
1266
2200
|
const configDir = path.join(projectRoot, CONFIG_DIR);
|
|
@@ -1412,6 +2346,49 @@ async function mergeUserCustomizations(projectRoot) {
|
|
|
1412
2346
|
console.log(chalk.gray(` ${result.skipped.length} file(s) had no user customizations to merge`));
|
|
1413
2347
|
}
|
|
1414
2348
|
|
|
2349
|
+
// F1b: translate user edits to the plugin-bundle format so they reach the
|
|
2350
|
+
// deployed SKILL.md files. The legacy merge above keeps
|
|
2351
|
+
// `_bmad/_config/agents/` consistent (for bmad-method's own hash-compare
|
|
2352
|
+
// path) but the LLM-readable skills live in `<tool>/skills/`; this is the
|
|
2353
|
+
// load-bearing step on upgrade.
|
|
2354
|
+
try {
|
|
2355
|
+
const translation = await translateUserCustomizations(projectRoot);
|
|
2356
|
+
result.translation = translation;
|
|
2357
|
+
|
|
2358
|
+
if (translation.translated.length > 0) {
|
|
2359
|
+
const totalSkillFiles = translation.translated.reduce(
|
|
2360
|
+
(acc, t) => acc + t.skillFiles.length, 0
|
|
2361
|
+
);
|
|
2362
|
+
console.log(chalk.green(
|
|
2363
|
+
` Translated ${translation.translated.length} customization(s) ` +
|
|
2364
|
+
`to ${totalSkillFiles} deployed SKILL.md file(s)`
|
|
2365
|
+
));
|
|
2366
|
+
}
|
|
2367
|
+
if (translation.preserved.length > 0) {
|
|
2368
|
+
console.log(chalk.gray(
|
|
2369
|
+
` Preserved ${translation.preserved.length} legacy customize.yaml ` +
|
|
2370
|
+
`file(s) at ${LEGACY_CUSTOMIZATIONS_DIR}/ for manual review`
|
|
2371
|
+
));
|
|
2372
|
+
}
|
|
2373
|
+
for (const warning of translation.warnings) {
|
|
2374
|
+
console.log(chalk.yellow(` ! ${warning}`));
|
|
2375
|
+
}
|
|
2376
|
+
if (translation.noTargetFound.length > 0) {
|
|
2377
|
+
console.log(chalk.yellow(
|
|
2378
|
+
` Summary: ${translation.translated.length} customization(s) migrated; ` +
|
|
2379
|
+
`${translation.noTargetFound.length} require manual reapplication — ` +
|
|
2380
|
+
`see ${LEGACY_CUSTOMIZATIONS_DIR}/`
|
|
2381
|
+
));
|
|
2382
|
+
}
|
|
2383
|
+
} catch (err) {
|
|
2384
|
+
// Translation failures are non-blocking: the legacy merge already ran,
|
|
2385
|
+
// and the preserved backup gives the user a path to re-apply by hand.
|
|
2386
|
+
console.log(chalk.yellow(
|
|
2387
|
+
` ! Customization translation failed: ${err.message} — ` +
|
|
2388
|
+
`legacy files preserved at ${BACKUP_DIR_NAME}/`
|
|
2389
|
+
));
|
|
2390
|
+
}
|
|
2391
|
+
|
|
1415
2392
|
return result;
|
|
1416
2393
|
}
|
|
1417
2394
|
|
|
@@ -1509,11 +2486,24 @@ function restoreGitDir(moduleDir) {
|
|
|
1509
2486
|
module.exports = {
|
|
1510
2487
|
isBmadInstalled,
|
|
1511
2488
|
buildBmadArgs,
|
|
2489
|
+
resolveCustomContentFlag,
|
|
1512
2490
|
installBmad,
|
|
1513
2491
|
updateBmad,
|
|
1514
|
-
applyCustomizations,
|
|
1515
2492
|
prePopulateBmadCache,
|
|
1516
2493
|
deployMethodology,
|
|
2494
|
+
// Story 22.7 — canonical config (_bmad/bmm/config.yaml) helpers
|
|
2495
|
+
readCanonicalBmadConfig,
|
|
2496
|
+
ensureCanonicalConfigLocation,
|
|
2497
|
+
CANONICAL_CONFIG_REL,
|
|
2498
|
+
LEGACY_MANIFEST_REL,
|
|
2499
|
+
// Story 22.6 — stage-and-invoke helpers (exported for unit tests)
|
|
2500
|
+
stagePlugin,
|
|
2501
|
+
cleanupStage,
|
|
2502
|
+
PLUGIN_STAGE_DIR_NAME,
|
|
2503
|
+
// F2a — Story 22.8 gitignore policy (project-root only). Exported so the
|
|
2504
|
+
// regression test can invoke it directly without spinning up the full
|
|
2505
|
+
// CLI / bmad-method pipeline.
|
|
2506
|
+
ensurePluginStageGitignoredForProject,
|
|
1517
2507
|
// Migration functions (exported for testing)
|
|
1518
2508
|
detectMigrationNeed,
|
|
1519
2509
|
compareVersions,
|
|
@@ -1522,9 +2512,26 @@ module.exports = {
|
|
|
1522
2512
|
mergeUserCustomizations,
|
|
1523
2513
|
cleanupLegacyArtifacts,
|
|
1524
2514
|
parseCustomizeYaml,
|
|
1525
|
-
|
|
2515
|
+
// F1b — exported for unit/integration tests
|
|
2516
|
+
translateUserCustomizations,
|
|
2517
|
+
buildCustomizationsMarkdownBlock,
|
|
2518
|
+
applyCustomizationsBlockToSkill,
|
|
2519
|
+
getCandidateSkillDirNames,
|
|
2520
|
+
getDeployedSkillsRoots,
|
|
2521
|
+
MA_CUSTOMIZATIONS_MARKER_START,
|
|
2522
|
+
MA_CUSTOMIZATIONS_MARKER_END,
|
|
2523
|
+
LEGACY_CUSTOMIZATIONS_DIR,
|
|
1526
2524
|
// Story 21.7 — phase-aware persona prefix (exported for testing)
|
|
1527
2525
|
applyPersonaPhasePrefix,
|
|
2526
|
+
// F1a — on-prem persona phase-prefix restoration post-22.6
|
|
2527
|
+
// (exported for integration testing)
|
|
2528
|
+
applyOnPremPhasePrefixToDeployedSkills,
|
|
2529
|
+
injectOnPremPrefixBlock,
|
|
2530
|
+
buildOnPremPrefixBlock,
|
|
2531
|
+
PERSONA_SKILL_MAP,
|
|
2532
|
+
TOOL_SKILL_DIRS,
|
|
2533
|
+
ON_PREM_PREFIX_MARKER_BEGIN,
|
|
2534
|
+
ON_PREM_PREFIX_MARKER_END,
|
|
1528
2535
|
// Offline-safe recompile helpers (exported for testing — see bug
|
|
1529
2536
|
// bug-bmad-recompile-fails-on-airgapped-network)
|
|
1530
2537
|
isOfflineModeDeclared,
|