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