ma-agents 3.12.0 → 3.12.2

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 (1310) hide show
  1. package/CONTRIBUTING.md +235 -235
  2. package/LICENSE +20 -20
  3. package/QUICK_START.md +154 -154
  4. package/README.md +731 -731
  5. package/SKILLS_STRUCTURE.md +392 -392
  6. package/bin/cli.js +1681 -1573
  7. package/docs/architecture.md +284 -284
  8. package/docs/deployment/vllm-nemotron.md +132 -132
  9. package/docs/development-guide.md +122 -122
  10. package/docs/index.md +48 -48
  11. package/docs/project-overview.md +56 -56
  12. package/docs/project-scan-report.json +50 -50
  13. package/docs/source-tree-analysis.md +84 -84
  14. package/docs/technical-notes/context-persistence-research.md +434 -434
  15. package/docs/validation/bundled-installation-validation.md +52 -52
  16. package/examples/programmatic-usage.js +62 -62
  17. package/index.js +22 -22
  18. package/lib/agents.js +370 -370
  19. package/lib/bmad-cache/bmb/.claude-plugin/marketplace.json +50 -50
  20. package/lib/bmad-cache/bmb/.markdownlint-cli2.yaml +36 -36
  21. package/lib/bmad-cache/bmb/.prettierignore +9 -9
  22. package/lib/bmad-cache/bmb/CNAME +1 -1
  23. package/lib/bmad-cache/bmb/LICENSE +30 -30
  24. package/lib/bmad-cache/bmb/README.md +75 -75
  25. package/lib/bmad-cache/bmb/_git_preserved/HEAD +1 -1
  26. package/lib/bmad-cache/bmb/_git_preserved/config +13 -13
  27. package/lib/bmad-cache/bmb/_git_preserved/description +1 -1
  28. package/lib/bmad-cache/bmb/_git_preserved/hooks/applypatch-msg.sample +15 -15
  29. package/lib/bmad-cache/bmb/_git_preserved/hooks/commit-msg.sample +24 -24
  30. package/lib/bmad-cache/bmb/_git_preserved/hooks/fsmonitor-watchman.sample +174 -174
  31. package/lib/bmad-cache/bmb/_git_preserved/hooks/post-update.sample +8 -8
  32. package/lib/bmad-cache/bmb/_git_preserved/hooks/pre-applypatch.sample +14 -14
  33. package/lib/bmad-cache/bmb/_git_preserved/hooks/pre-commit.sample +49 -49
  34. package/lib/bmad-cache/bmb/_git_preserved/hooks/pre-merge-commit.sample +13 -13
  35. package/lib/bmad-cache/bmb/_git_preserved/hooks/pre-push.sample +53 -53
  36. package/lib/bmad-cache/bmb/_git_preserved/hooks/pre-rebase.sample +169 -169
  37. package/lib/bmad-cache/bmb/_git_preserved/hooks/pre-receive.sample +24 -24
  38. package/lib/bmad-cache/bmb/_git_preserved/hooks/prepare-commit-msg.sample +42 -42
  39. package/lib/bmad-cache/bmb/_git_preserved/hooks/push-to-checkout.sample +78 -78
  40. package/lib/bmad-cache/bmb/_git_preserved/hooks/sendemail-validate.sample +77 -77
  41. package/lib/bmad-cache/bmb/_git_preserved/hooks/update.sample +128 -128
  42. package/lib/bmad-cache/bmb/_git_preserved/info/exclude +6 -6
  43. package/lib/bmad-cache/bmb/_git_preserved/packed-refs +2 -2
  44. package/lib/bmad-cache/bmb/_git_preserved/refs/heads/main +1 -1
  45. package/lib/bmad-cache/bmb/_git_preserved/refs/remotes/origin/HEAD +1 -1
  46. package/lib/bmad-cache/bmb/_git_preserved/refs/tags/v1.7.0 +1 -1
  47. package/lib/bmad-cache/bmb/_git_preserved/shallow +1 -1
  48. package/lib/bmad-cache/bmb/eslint.config.mjs +141 -141
  49. package/lib/bmad-cache/bmb/package-lock.json +15283 -15283
  50. package/lib/bmad-cache/bmb/package.json +86 -86
  51. package/lib/bmad-cache/bmb/prettier.config.mjs +32 -32
  52. package/lib/bmad-cache/bmb/samples/bmad-agent-code-coach/scripts/init-sanctum.py +288 -288
  53. package/lib/bmad-cache/bmb/samples/bmad-agent-creative-muse/scripts/init-sanctum.py +274 -274
  54. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/assets/module-help.csv +9 -9
  55. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/assets/module.yaml +8 -8
  56. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/scripts/merge-config.py +408 -408
  57. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/scripts/merge-help-csv.py +218 -218
  58. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/scripts/recall_metrics.py +229 -229
  59. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/scripts/seed_tracker.py +156 -156
  60. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/scripts/symbol_stats.py +162 -162
  61. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/scripts/tests/test_recall_metrics.py +115 -115
  62. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/scripts/tests/test_seed_tracker.py +140 -140
  63. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/scripts/tests/test_symbol_stats.py +113 -113
  64. package/lib/bmad-cache/bmb/samples/bmad-agent-sentinel/scripts/init-sanctum.py +285 -285
  65. package/lib/bmad-cache/bmb/samples/bmad-agent-sentinel/scripts/tests/test-init-sanctum.py +174 -174
  66. package/lib/bmad-cache/bmb/samples/bmad-excalidraw/scripts/generate_excalidraw.py +605 -605
  67. package/lib/bmad-cache/bmb/samples/bmad-excalidraw/scripts/tests/test_generate_excalidraw.py +360 -360
  68. package/lib/bmad-cache/bmb/samples/bmad-excalidraw/scripts/tests/test_validate_excalidraw.py +246 -246
  69. package/lib/bmad-cache/bmb/samples/bmad-excalidraw/scripts/validate_excalidraw.py +264 -264
  70. package/lib/bmad-cache/bmb/samples/sample-module-setup/assets/module-help.csv +16 -16
  71. package/lib/bmad-cache/bmb/samples/sample-module-setup/assets/module.yaml +13 -13
  72. package/lib/bmad-cache/bmb/samples/sample-module-setup/scripts/cleanup-legacy.py +259 -259
  73. package/lib/bmad-cache/bmb/samples/sample-module-setup/scripts/merge-config.py +408 -408
  74. package/lib/bmad-cache/bmb/samples/sample-module-setup/scripts/merge-help-csv.py +218 -218
  75. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/customize-template.toml +62 -62
  76. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/init-sanctum-template.py +277 -277
  77. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/sample-customize-analyst.toml +87 -87
  78. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/references/sample-init-sanctum.py +274 -274
  79. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/generate-html-report.py +534 -534
  80. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-execution-deps.py +337 -337
  81. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-prompt-metrics.py +425 -425
  82. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-sanctum-architecture.py +385 -385
  83. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-structure-capabilities.py +482 -482
  84. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/process-template.py +190 -190
  85. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/scan-path-standards.py +324 -324
  86. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/scan-scripts.py +747 -747
  87. package/lib/bmad-cache/bmb/skills/bmad-bmb-setup/assets/module-help.csv +10 -10
  88. package/lib/bmad-cache/bmb/skills/bmad-bmb-setup/assets/module.yaml +20 -20
  89. package/lib/bmad-cache/bmb/skills/bmad-bmb-setup/scripts/cleanup-legacy.py +259 -259
  90. package/lib/bmad-cache/bmb/skills/bmad-bmb-setup/scripts/merge-config.py +408 -408
  91. package/lib/bmad-cache/bmb/skills/bmad-bmb-setup/scripts/merge-help-csv.py +218 -218
  92. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/setup-skill-template/assets/module-help.csv +1 -1
  93. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/setup-skill-template/assets/module.yaml +6 -6
  94. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/setup-skill-template/scripts/cleanup-legacy.py +259 -259
  95. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/setup-skill-template/scripts/merge-config.py +408 -408
  96. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/setup-skill-template/scripts/merge-help-csv.py +218 -218
  97. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/standalone-module-template/merge-config.py +408 -408
  98. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/standalone-module-template/merge-help-csv.py +218 -218
  99. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/scaffold-setup-skill.py +124 -124
  100. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/scaffold-standalone-module.py +190 -190
  101. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/tests/test-scaffold-setup-skill.py +230 -230
  102. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/tests/test-scaffold-standalone-module.py +266 -266
  103. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/tests/test-validate-module.py +314 -314
  104. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/validate-module.py +293 -293
  105. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/assets/customize-template.toml +56 -56
  106. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/assets/sample-customize-product-brief.toml +51 -51
  107. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/generate-convert-report.py +406 -406
  108. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/generate-html-report.py +539 -539
  109. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/prepass-execution-deps.py +288 -288
  110. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/prepass-prompt-metrics.py +285 -285
  111. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/prepass-workflow-integrity.py +475 -475
  112. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/scan-path-standards.py +298 -298
  113. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/scan-scripts.py +745 -745
  114. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/tests/test_generate_convert_report.py +243 -243
  115. package/lib/bmad-cache/bmb/skills/module-help.csv +11 -11
  116. package/lib/bmad-cache/bmb/skills/module.yaml +20 -20
  117. package/lib/bmad-cache/bmb/tools/build-docs.mjs +448 -448
  118. package/lib/bmad-cache/bmb/tools/validate-doc-links.cjs +412 -412
  119. package/lib/bmad-cache/bmb/tools/validate-file-refs.mjs +657 -657
  120. package/lib/bmad-cache/bmb/website/astro.config.mjs +142 -142
  121. package/lib/bmad-cache/bmb/website/src/components/Banner.astro +57 -57
  122. package/lib/bmad-cache/bmb/website/src/components/Header.astro +94 -94
  123. package/lib/bmad-cache/bmb/website/src/components/MobileMenuFooter.astro +33 -33
  124. package/lib/bmad-cache/bmb/website/src/content/config.ts +6 -6
  125. package/lib/bmad-cache/bmb/website/src/lib/site-url.mjs +25 -25
  126. package/lib/bmad-cache/bmb/website/src/rehype-base-paths.js +88 -88
  127. package/lib/bmad-cache/bmb/website/src/rehype-markdown-links.js +117 -117
  128. package/lib/bmad-cache/bmb/website/src/styles/custom.css +502 -502
  129. package/lib/bmad-cache/cache-manifest.json +37 -37
  130. package/lib/bmad-cache/cis/.claude-plugin/marketplace.json +33 -33
  131. package/lib/bmad-cache/cis/.markdownlint-cli2.yaml +35 -35
  132. package/lib/bmad-cache/cis/.prettierignore +9 -9
  133. package/lib/bmad-cache/cis/CNAME +1 -1
  134. package/lib/bmad-cache/cis/LICENSE +26 -26
  135. package/lib/bmad-cache/cis/README.md +114 -114
  136. package/lib/bmad-cache/cis/_git_preserved/HEAD +1 -1
  137. package/lib/bmad-cache/cis/_git_preserved/config +13 -13
  138. package/lib/bmad-cache/cis/_git_preserved/description +1 -1
  139. package/lib/bmad-cache/cis/_git_preserved/hooks/applypatch-msg.sample +15 -15
  140. package/lib/bmad-cache/cis/_git_preserved/hooks/commit-msg.sample +24 -24
  141. package/lib/bmad-cache/cis/_git_preserved/hooks/fsmonitor-watchman.sample +174 -174
  142. package/lib/bmad-cache/cis/_git_preserved/hooks/post-update.sample +8 -8
  143. package/lib/bmad-cache/cis/_git_preserved/hooks/pre-applypatch.sample +14 -14
  144. package/lib/bmad-cache/cis/_git_preserved/hooks/pre-commit.sample +49 -49
  145. package/lib/bmad-cache/cis/_git_preserved/hooks/pre-merge-commit.sample +13 -13
  146. package/lib/bmad-cache/cis/_git_preserved/hooks/pre-push.sample +53 -53
  147. package/lib/bmad-cache/cis/_git_preserved/hooks/pre-rebase.sample +169 -169
  148. package/lib/bmad-cache/cis/_git_preserved/hooks/pre-receive.sample +24 -24
  149. package/lib/bmad-cache/cis/_git_preserved/hooks/prepare-commit-msg.sample +42 -42
  150. package/lib/bmad-cache/cis/_git_preserved/hooks/push-to-checkout.sample +78 -78
  151. package/lib/bmad-cache/cis/_git_preserved/hooks/sendemail-validate.sample +77 -77
  152. package/lib/bmad-cache/cis/_git_preserved/hooks/update.sample +128 -128
  153. package/lib/bmad-cache/cis/_git_preserved/info/exclude +6 -6
  154. package/lib/bmad-cache/cis/_git_preserved/packed-refs +2 -2
  155. package/lib/bmad-cache/cis/_git_preserved/refs/heads/main +1 -1
  156. package/lib/bmad-cache/cis/_git_preserved/refs/remotes/origin/HEAD +1 -1
  157. package/lib/bmad-cache/cis/_git_preserved/shallow +1 -1
  158. package/lib/bmad-cache/cis/eslint.config.mjs +141 -141
  159. package/lib/bmad-cache/cis/package-lock.json +17015 -17015
  160. package/lib/bmad-cache/cis/package.json +91 -91
  161. package/lib/bmad-cache/cis/prettier.config.mjs +32 -32
  162. package/lib/bmad-cache/cis/src/module-help.csv +7 -7
  163. package/lib/bmad-cache/cis/src/module.yaml +76 -76
  164. package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-brainstorming-coach/customize.toml +38 -38
  165. package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-creative-problem-solver/customize.toml +38 -38
  166. package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-design-thinking-coach/customize.toml +39 -39
  167. package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-innovation-strategist/customize.toml +38 -38
  168. package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-presentation-master/customize.toml +73 -73
  169. package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-storyteller/customize.toml +60 -60
  170. package/lib/bmad-cache/cis/src/skills/bmad-cis-design-thinking/customize.toml +41 -41
  171. package/lib/bmad-cache/cis/src/skills/bmad-cis-design-thinking/design-methods.csv +30 -30
  172. package/lib/bmad-cache/cis/src/skills/bmad-cis-innovation-strategy/customize.toml +41 -41
  173. package/lib/bmad-cache/cis/src/skills/bmad-cis-innovation-strategy/innovation-frameworks.csv +30 -30
  174. package/lib/bmad-cache/cis/src/skills/bmad-cis-problem-solving/customize.toml +42 -42
  175. package/lib/bmad-cache/cis/src/skills/bmad-cis-problem-solving/solving-methods.csv +30 -30
  176. package/lib/bmad-cache/cis/src/skills/bmad-cis-storytelling/customize.toml +41 -41
  177. package/lib/bmad-cache/cis/src/skills/bmad-cis-storytelling/story-types.csv +25 -25
  178. package/lib/bmad-cache/cis/tools/build-docs.mjs +456 -456
  179. package/lib/bmad-cache/cis/website/astro.config.mjs +172 -172
  180. package/lib/bmad-cache/cis/website/src/components/Banner.astro +71 -71
  181. package/lib/bmad-cache/cis/website/src/components/Header.astro +94 -94
  182. package/lib/bmad-cache/cis/website/src/components/MobileMenuFooter.astro +33 -33
  183. package/lib/bmad-cache/cis/website/src/content/config.ts +7 -7
  184. package/lib/bmad-cache/cis/website/src/content/i18n/zh-CN.json +28 -28
  185. package/lib/bmad-cache/cis/website/src/lib/locales.mjs +27 -27
  186. package/lib/bmad-cache/cis/website/src/lib/site-url.mjs +25 -25
  187. package/lib/bmad-cache/cis/website/src/rehype-base-paths.js +88 -88
  188. package/lib/bmad-cache/cis/website/src/rehype-markdown-links.js +117 -117
  189. package/lib/bmad-cache/cis/website/src/styles/custom.css +503 -503
  190. package/lib/bmad-cache/gds/.claude-plugin/marketplace.json +59 -59
  191. package/lib/bmad-cache/gds/.markdownlint-cli2.yaml +35 -35
  192. package/lib/bmad-cache/gds/.prettierignore +9 -9
  193. package/lib/bmad-cache/gds/CNAME +1 -1
  194. package/lib/bmad-cache/gds/LICENSE +26 -26
  195. package/lib/bmad-cache/gds/README.md +132 -132
  196. package/lib/bmad-cache/gds/_git_preserved/HEAD +1 -1
  197. package/lib/bmad-cache/gds/_git_preserved/config +13 -13
  198. package/lib/bmad-cache/gds/_git_preserved/description +1 -1
  199. package/lib/bmad-cache/gds/_git_preserved/hooks/applypatch-msg.sample +15 -15
  200. package/lib/bmad-cache/gds/_git_preserved/hooks/commit-msg.sample +24 -24
  201. package/lib/bmad-cache/gds/_git_preserved/hooks/fsmonitor-watchman.sample +174 -174
  202. package/lib/bmad-cache/gds/_git_preserved/hooks/post-update.sample +8 -8
  203. package/lib/bmad-cache/gds/_git_preserved/hooks/pre-applypatch.sample +14 -14
  204. package/lib/bmad-cache/gds/_git_preserved/hooks/pre-commit.sample +49 -49
  205. package/lib/bmad-cache/gds/_git_preserved/hooks/pre-merge-commit.sample +13 -13
  206. package/lib/bmad-cache/gds/_git_preserved/hooks/pre-push.sample +53 -53
  207. package/lib/bmad-cache/gds/_git_preserved/hooks/pre-rebase.sample +169 -169
  208. package/lib/bmad-cache/gds/_git_preserved/hooks/pre-receive.sample +24 -24
  209. package/lib/bmad-cache/gds/_git_preserved/hooks/prepare-commit-msg.sample +42 -42
  210. package/lib/bmad-cache/gds/_git_preserved/hooks/push-to-checkout.sample +78 -78
  211. package/lib/bmad-cache/gds/_git_preserved/hooks/sendemail-validate.sample +77 -77
  212. package/lib/bmad-cache/gds/_git_preserved/hooks/update.sample +128 -128
  213. package/lib/bmad-cache/gds/_git_preserved/info/exclude +6 -6
  214. package/lib/bmad-cache/gds/_git_preserved/packed-refs +2 -2
  215. package/lib/bmad-cache/gds/_git_preserved/refs/heads/main +1 -1
  216. package/lib/bmad-cache/gds/_git_preserved/refs/remotes/origin/HEAD +1 -1
  217. package/lib/bmad-cache/gds/_git_preserved/shallow +1 -1
  218. package/lib/bmad-cache/gds/eslint.config.mjs +141 -141
  219. package/lib/bmad-cache/gds/package.json +91 -91
  220. package/lib/bmad-cache/gds/prettier.config.mjs +32 -32
  221. package/lib/bmad-cache/gds/src/agents/gds-agent-game-architect/customize.toml +57 -57
  222. package/lib/bmad-cache/gds/src/agents/gds-agent-game-designer/customize.toml +59 -59
  223. package/lib/bmad-cache/gds/src/agents/gds-agent-game-dev/customize.toml +129 -129
  224. package/lib/bmad-cache/gds/src/agents/gds-agent-game-dev/gametest/qa-index.csv +18 -18
  225. package/lib/bmad-cache/gds/src/agents/gds-agent-game-solo-dev/customize.toml +60 -60
  226. package/lib/bmad-cache/gds/src/agents/gds-agent-tech-writer/customize.toml +65 -65
  227. package/lib/bmad-cache/gds/src/module-help.csv +36 -36
  228. package/lib/bmad-cache/gds/src/module.yaml +113 -113
  229. package/lib/bmad-cache/gds/src/workflows/1-preproduction/gds-brainstorm-game/customize.toml +41 -41
  230. package/lib/bmad-cache/gds/src/workflows/1-preproduction/gds-brainstorm-game/game-brain-methods.csv +25 -25
  231. package/lib/bmad-cache/gds/src/workflows/1-preproduction/gds-create-game-brief/customize.toml +41 -41
  232. package/lib/bmad-cache/gds/src/workflows/1-preproduction/research/gds-domain-research/customize.toml +41 -41
  233. package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-gdd/customize.toml +41 -41
  234. package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-gdd/game-types.csv +24 -24
  235. package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-narrative/customize.toml +41 -41
  236. package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-prd/customize.toml +41 -41
  237. package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-prd/data/domain-complexity.csv +14 -14
  238. package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-prd/data/project-types.csv +10 -10
  239. package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-ux-design/customize.toml +41 -41
  240. package/lib/bmad-cache/gds/src/workflows/2-design/gds-edit-gdd/customize.toml +41 -41
  241. package/lib/bmad-cache/gds/src/workflows/2-design/gds-edit-prd/customize.toml +41 -41
  242. package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-gdd/customize.toml +41 -41
  243. package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-gdd/data/genre-complexity.csv +26 -26
  244. package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-prd/customize.toml +41 -41
  245. package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-prd/data/domain-complexity.csv +14 -14
  246. package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-prd/data/project-types.csv +10 -10
  247. package/lib/bmad-cache/gds/src/workflows/3-technical/gds-check-implementation-readiness/customize.toml +41 -41
  248. package/lib/bmad-cache/gds/src/workflows/3-technical/gds-create-epics-and-stories/customize.toml +41 -41
  249. package/lib/bmad-cache/gds/src/workflows/3-technical/gds-game-architecture/architecture-patterns.yaml +507 -507
  250. package/lib/bmad-cache/gds/src/workflows/3-technical/gds-game-architecture/customize.toml +41 -41
  251. package/lib/bmad-cache/gds/src/workflows/3-technical/gds-game-architecture/decision-catalog.yaml +340 -340
  252. package/lib/bmad-cache/gds/src/workflows/3-technical/gds-game-architecture/engine-mcps.yaml +270 -270
  253. package/lib/bmad-cache/gds/src/workflows/3-technical/gds-game-architecture/pattern-categories.csv +12 -12
  254. package/lib/bmad-cache/gds/src/workflows/3-technical/gds-generate-project-context/customize.toml +41 -41
  255. package/lib/bmad-cache/gds/src/workflows/4-production/gds-code-review/customize.toml +41 -41
  256. package/lib/bmad-cache/gds/src/workflows/4-production/gds-correct-course/customize.toml +41 -41
  257. package/lib/bmad-cache/gds/src/workflows/4-production/gds-create-story/customize.toml +41 -41
  258. package/lib/bmad-cache/gds/src/workflows/4-production/gds-dev-story/customize.toml +41 -41
  259. package/lib/bmad-cache/gds/src/workflows/4-production/gds-retrospective/customize.toml +41 -41
  260. package/lib/bmad-cache/gds/src/workflows/4-production/gds-sprint-planning/customize.toml +41 -41
  261. package/lib/bmad-cache/gds/src/workflows/4-production/gds-sprint-planning/sprint-status-template.yaml +55 -55
  262. package/lib/bmad-cache/gds/src/workflows/4-production/gds-sprint-status/customize.toml +41 -41
  263. package/lib/bmad-cache/gds/src/workflows/gametest/gds-e2e-scaffold/customize.toml +41 -41
  264. package/lib/bmad-cache/gds/src/workflows/gametest/gds-performance-test/customize.toml +41 -41
  265. package/lib/bmad-cache/gds/src/workflows/gametest/gds-playtest-plan/customize.toml +41 -41
  266. package/lib/bmad-cache/gds/src/workflows/gametest/gds-test-automate/customize.toml +41 -41
  267. package/lib/bmad-cache/gds/src/workflows/gametest/gds-test-design/customize.toml +41 -41
  268. package/lib/bmad-cache/gds/src/workflows/gametest/gds-test-framework/customize.toml +41 -41
  269. package/lib/bmad-cache/gds/src/workflows/gametest/gds-test-review/customize.toml +41 -41
  270. package/lib/bmad-cache/gds/src/workflows/gds-document-project/customize.toml +41 -41
  271. package/lib/bmad-cache/gds/src/workflows/gds-document-project/documentation-requirements.csv +12 -12
  272. package/lib/bmad-cache/gds/src/workflows/gds-document-project/templates/project-scan-report-schema.json +160 -160
  273. package/lib/bmad-cache/gds/src/workflows/gds-quick-flow/gds-quick-dev/customize.toml +41 -41
  274. package/lib/bmad-cache/gds/tools/build-docs.mjs +450 -450
  275. package/lib/bmad-cache/gds/website/astro.config.mjs +142 -142
  276. package/lib/bmad-cache/gds/website/src/components/Banner.astro +71 -71
  277. package/lib/bmad-cache/gds/website/src/components/Header.astro +94 -94
  278. package/lib/bmad-cache/gds/website/src/components/MobileMenuFooter.astro +33 -33
  279. package/lib/bmad-cache/gds/website/src/content/config.ts +6 -6
  280. package/lib/bmad-cache/gds/website/src/lib/site-url.mjs +25 -25
  281. package/lib/bmad-cache/gds/website/src/rehype-base-paths.js +88 -88
  282. package/lib/bmad-cache/gds/website/src/rehype-markdown-links.js +117 -117
  283. package/lib/bmad-cache/gds/website/src/styles/custom.css +503 -503
  284. package/lib/bmad-cache/tea/.claude-plugin/marketplace.json +33 -33
  285. package/lib/bmad-cache/tea/.coderabbit.yaml +40 -40
  286. package/lib/bmad-cache/tea/.github/CODE_OF_CONDUCT.md +128 -128
  287. package/lib/bmad-cache/tea/.github/FUNDING.yaml +15 -15
  288. package/lib/bmad-cache/tea/.github/ISSUE_TEMPLATE/config.yaml +11 -11
  289. package/lib/bmad-cache/tea/.github/ISSUE_TEMPLATE/feature_request.md +70 -70
  290. package/lib/bmad-cache/tea/.github/ISSUE_TEMPLATE/issue.md +61 -61
  291. package/lib/bmad-cache/tea/.github/workflows/docs.yaml +66 -66
  292. package/lib/bmad-cache/tea/.github/workflows/quality.yaml +117 -117
  293. package/lib/bmad-cache/tea/.husky/pre-commit +20 -20
  294. package/lib/bmad-cache/tea/.markdownlint-cli2.yaml +36 -36
  295. package/lib/bmad-cache/tea/.prettierignore +9 -9
  296. package/lib/bmad-cache/tea/CHANGELOG.md +241 -241
  297. package/lib/bmad-cache/tea/CONTRIBUTING.md +268 -268
  298. package/lib/bmad-cache/tea/LICENSE +26 -26
  299. package/lib/bmad-cache/tea/README.md +416 -416
  300. package/lib/bmad-cache/tea/SECURITY.md +85 -85
  301. package/lib/bmad-cache/tea/_git_preserved/HEAD +1 -1
  302. package/lib/bmad-cache/tea/_git_preserved/config +13 -13
  303. package/lib/bmad-cache/tea/_git_preserved/description +1 -1
  304. package/lib/bmad-cache/tea/_git_preserved/hooks/applypatch-msg.sample +15 -15
  305. package/lib/bmad-cache/tea/_git_preserved/hooks/commit-msg.sample +24 -24
  306. package/lib/bmad-cache/tea/_git_preserved/hooks/fsmonitor-watchman.sample +174 -174
  307. package/lib/bmad-cache/tea/_git_preserved/hooks/post-update.sample +8 -8
  308. package/lib/bmad-cache/tea/_git_preserved/hooks/pre-applypatch.sample +14 -14
  309. package/lib/bmad-cache/tea/_git_preserved/hooks/pre-commit.sample +49 -49
  310. package/lib/bmad-cache/tea/_git_preserved/hooks/pre-merge-commit.sample +13 -13
  311. package/lib/bmad-cache/tea/_git_preserved/hooks/pre-push.sample +53 -53
  312. package/lib/bmad-cache/tea/_git_preserved/hooks/pre-rebase.sample +169 -169
  313. package/lib/bmad-cache/tea/_git_preserved/hooks/pre-receive.sample +24 -24
  314. package/lib/bmad-cache/tea/_git_preserved/hooks/prepare-commit-msg.sample +42 -42
  315. package/lib/bmad-cache/tea/_git_preserved/hooks/push-to-checkout.sample +78 -78
  316. package/lib/bmad-cache/tea/_git_preserved/hooks/sendemail-validate.sample +77 -77
  317. package/lib/bmad-cache/tea/_git_preserved/hooks/update.sample +128 -128
  318. package/lib/bmad-cache/tea/_git_preserved/info/exclude +6 -6
  319. package/lib/bmad-cache/tea/_git_preserved/packed-refs +2 -2
  320. package/lib/bmad-cache/tea/_git_preserved/refs/heads/main +1 -1
  321. package/lib/bmad-cache/tea/_git_preserved/refs/remotes/origin/HEAD +1 -1
  322. package/lib/bmad-cache/tea/_git_preserved/shallow +1 -1
  323. package/lib/bmad-cache/tea/docs/404.md +20 -20
  324. package/lib/bmad-cache/tea/docs/explanation/engagement-models.md +767 -767
  325. package/lib/bmad-cache/tea/docs/explanation/fixture-architecture.md +484 -484
  326. package/lib/bmad-cache/tea/docs/explanation/knowledge-base-system.md +601 -601
  327. package/lib/bmad-cache/tea/docs/explanation/network-first-patterns.md +884 -884
  328. package/lib/bmad-cache/tea/docs/explanation/risk-based-testing.md +628 -628
  329. package/lib/bmad-cache/tea/docs/explanation/step-file-architecture.md +599 -599
  330. package/lib/bmad-cache/tea/docs/explanation/subagent-architecture.md +189 -189
  331. package/lib/bmad-cache/tea/docs/explanation/tea-overview.md +474 -474
  332. package/lib/bmad-cache/tea/docs/explanation/test-quality-standards.md +965 -965
  333. package/lib/bmad-cache/tea/docs/explanation/testing-as-engineering.md +115 -115
  334. package/lib/bmad-cache/tea/docs/glossary/index.md +160 -160
  335. package/lib/bmad-cache/tea/docs/how-to/brownfield/use-tea-for-enterprise.md +571 -571
  336. package/lib/bmad-cache/tea/docs/how-to/brownfield/use-tea-with-existing-tests.md +631 -631
  337. package/lib/bmad-cache/tea/docs/how-to/customization/configure-browser-automation.md +243 -243
  338. package/lib/bmad-cache/tea/docs/how-to/customization/extend-tea-with-custom-workflows.md +102 -102
  339. package/lib/bmad-cache/tea/docs/how-to/customization/integrate-playwright-utils.md +846 -846
  340. package/lib/bmad-cache/tea/docs/how-to/workflows/run-atdd.md +462 -462
  341. package/lib/bmad-cache/tea/docs/how-to/workflows/run-automate.md +693 -693
  342. package/lib/bmad-cache/tea/docs/how-to/workflows/run-nfr-assess.md +731 -731
  343. package/lib/bmad-cache/tea/docs/how-to/workflows/run-test-design.md +144 -144
  344. package/lib/bmad-cache/tea/docs/how-to/workflows/run-test-review.md +634 -634
  345. package/lib/bmad-cache/tea/docs/how-to/workflows/run-trace.md +966 -966
  346. package/lib/bmad-cache/tea/docs/how-to/workflows/setup-ci.md +763 -763
  347. package/lib/bmad-cache/tea/docs/how-to/workflows/setup-test-framework.md +122 -122
  348. package/lib/bmad-cache/tea/docs/how-to/workflows/teach-me-testing.md +302 -302
  349. package/lib/bmad-cache/tea/docs/index.md +65 -65
  350. package/lib/bmad-cache/tea/docs/reference/commands.md +356 -356
  351. package/lib/bmad-cache/tea/docs/reference/configuration.md +1144 -1144
  352. package/lib/bmad-cache/tea/docs/reference/knowledge-base.md +406 -406
  353. package/lib/bmad-cache/tea/docs/reference/troubleshooting.md +837 -837
  354. package/lib/bmad-cache/tea/docs/tutorials/learn-testing-tea-academy.md +266 -266
  355. package/lib/bmad-cache/tea/docs/tutorials/tea-lite-quickstart.md +465 -465
  356. package/lib/bmad-cache/tea/eslint.config.mjs +141 -141
  357. package/lib/bmad-cache/tea/package-lock.json +16046 -16046
  358. package/lib/bmad-cache/tea/package.json +118 -118
  359. package/lib/bmad-cache/tea/prettier.config.mjs +32 -32
  360. package/lib/bmad-cache/tea/src/agents/bmad-tea/SKILL.md +80 -80
  361. package/lib/bmad-cache/tea/src/agents/bmad-tea/customize.toml +104 -104
  362. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/adr-quality-readiness-checklist.md +377 -377
  363. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/api-request.md +563 -563
  364. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/api-testing-patterns.md +915 -915
  365. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/auth-session.md +548 -548
  366. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/burn-in.md +273 -273
  367. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/ci-burn-in.md +717 -717
  368. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/component-tdd.md +486 -486
  369. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/contract-testing.md +1066 -1066
  370. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/data-factories.md +500 -500
  371. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/email-auth.md +721 -721
  372. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/error-handling.md +725 -725
  373. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/feature-flags.md +750 -750
  374. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/file-utils.md +456 -456
  375. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/fixture-architecture.md +401 -401
  376. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/fixtures-composition.md +382 -382
  377. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/intercept-network-call.md +426 -426
  378. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/log.md +426 -426
  379. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/network-error-monitor.md +401 -401
  380. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/network-first.md +486 -486
  381. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/network-recorder.md +527 -527
  382. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/nfr-criteria.md +670 -670
  383. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/overview.md +286 -286
  384. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pact-broker-webhooks.md +237 -237
  385. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pact-consumer-di.md +310 -310
  386. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pact-consumer-framework-setup.md +704 -704
  387. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pact-mcp.md +205 -205
  388. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-consumer-helpers.md +379 -379
  389. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-overview.md +219 -219
  390. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-provider-verifier.md +397 -397
  391. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-request-filter.md +224 -224
  392. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-zod-to-pact.md +262 -262
  393. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/playwright-cli.md +280 -280
  394. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/playwright-config.md +734 -734
  395. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/probability-impact.md +601 -601
  396. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/recurse.md +421 -421
  397. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/risk-governance.md +615 -615
  398. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/selective-testing.md +732 -732
  399. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/selector-resilience.md +527 -527
  400. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/test-healing-patterns.md +644 -644
  401. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/test-levels-framework.md +473 -473
  402. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/test-priorities-matrix.md +373 -373
  403. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/test-quality.md +664 -664
  404. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/timing-debugging.md +372 -372
  405. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/visual-debugging.md +527 -527
  406. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-module-setup.md +122 -122
  407. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-providers.md +155 -155
  408. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-risk-guidance.md +114 -114
  409. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-template-matchers.md +160 -160
  410. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-testing-fundamentals.md +42 -42
  411. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-timeout-error.md +130 -130
  412. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/webhook-waiting-querying.md +167 -167
  413. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/tea-index.csv +52 -52
  414. package/lib/bmad-cache/tea/src/module-help.csv +11 -11
  415. package/lib/bmad-cache/tea/src/module.yaml +307 -307
  416. package/lib/bmad-cache/tea/src/workflows/testarch/README.md +76 -76
  417. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/SKILL.md +129 -129
  418. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/checklist.md +198 -198
  419. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/customize.toml +40 -40
  420. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/data/curriculum.yaml +129 -129
  421. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/data/quiz-questions.yaml +206 -206
  422. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/data/role-paths.yaml +136 -136
  423. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/data/session-content-map.yaml +219 -219
  424. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/data/tea-resources-index.yaml +394 -394
  425. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/instructions.md +137 -137
  426. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-01-init.md +235 -235
  427. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-01b-continue.md +147 -147
  428. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-02-assess.md +258 -258
  429. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-03-session-menu.md +219 -219
  430. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-01.md +460 -460
  431. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-02.md +465 -465
  432. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-03.md +301 -301
  433. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-04.md +234 -234
  434. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-05.md +234 -234
  435. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-06.md +209 -209
  436. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-07.md +220 -220
  437. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-05-completion.md +347 -347
  438. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-e/step-e-01-assess-workflow.md +141 -141
  439. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-e/step-e-02-apply-edits.md +130 -130
  440. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-v/step-v-01-validate.md +272 -272
  441. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/templates/certificate-template.md +86 -86
  442. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/templates/progress-template.yaml +95 -95
  443. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/templates/session-notes-template.md +83 -83
  444. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/workflow-plan-teach-me-testing.md +950 -950
  445. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/SKILL.md +85 -85
  446. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/atdd-checklist-template.md +394 -394
  447. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/checklist.md +375 -375
  448. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/customize.toml +40 -40
  449. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/instructions.md +44 -44
  450. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/adr-quality-readiness-checklist.md +377 -377
  451. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/api-request.md +563 -563
  452. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/api-testing-patterns.md +915 -915
  453. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/auth-session.md +548 -548
  454. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/burn-in.md +273 -273
  455. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/ci-burn-in.md +717 -717
  456. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/component-tdd.md +486 -486
  457. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/contract-testing.md +1067 -1067
  458. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/data-factories.md +500 -500
  459. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/email-auth.md +721 -721
  460. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/error-handling.md +725 -725
  461. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/feature-flags.md +750 -750
  462. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/file-utils.md +456 -456
  463. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/fixture-architecture.md +401 -401
  464. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/fixtures-composition.md +382 -382
  465. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/intercept-network-call.md +426 -426
  466. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/log.md +426 -426
  467. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/network-error-monitor.md +401 -401
  468. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/network-first.md +486 -486
  469. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/network-recorder.md +527 -527
  470. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/nfr-criteria.md +670 -670
  471. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/overview.md +286 -286
  472. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pact-broker-webhooks.md +237 -237
  473. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pact-consumer-di.md +310 -310
  474. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pact-consumer-framework-setup.md +757 -757
  475. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pact-mcp.md +205 -205
  476. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pactjs-utils-consumer-helpers.md +380 -380
  477. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pactjs-utils-overview.md +219 -219
  478. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pactjs-utils-provider-verifier.md +397 -397
  479. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pactjs-utils-request-filter.md +224 -224
  480. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/pactjs-utils-zod-to-pact.md +262 -262
  481. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/playwright-cli.md +280 -280
  482. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/playwright-config.md +734 -734
  483. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/probability-impact.md +601 -601
  484. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/recurse.md +421 -421
  485. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/risk-governance.md +615 -615
  486. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/selective-testing.md +732 -732
  487. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/selector-resilience.md +527 -527
  488. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/test-healing-patterns.md +644 -644
  489. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/test-levels-framework.md +473 -473
  490. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/test-priorities-matrix.md +373 -373
  491. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/test-quality.md +664 -664
  492. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/timing-debugging.md +372 -372
  493. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/visual-debugging.md +527 -527
  494. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-module-setup.md +122 -122
  495. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-providers.md +155 -155
  496. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-risk-guidance.md +114 -114
  497. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-template-matchers.md +160 -160
  498. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-testing-fundamentals.md +42 -42
  499. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-timeout-error.md +130 -130
  500. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/knowledge/webhook-waiting-querying.md +167 -167
  501. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/tea-index.csv +52 -52
  502. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-01-preflight-and-context.md +244 -244
  503. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-01b-resume.md +96 -96
  504. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-02-generation-mode.md +125 -125
  505. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-03-test-strategy.md +110 -110
  506. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04-generate-tests.md +335 -335
  507. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04a-subagent-api-failing.md +294 -294
  508. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04b-subagent-e2e-failing.md +244 -244
  509. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04c-aggregate.md +394 -394
  510. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-05-validate-and-complete.md +123 -123
  511. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-e/step-01-assess.md +65 -65
  512. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-e/step-02-apply-edit.md +68 -68
  513. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-v/step-01-validate.md +75 -75
  514. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/validation-report-20260127-095021.md +73 -73
  515. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/validation-report-20260127-102401.md +116 -116
  516. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/workflow-plan.md +21 -21
  517. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/workflow.yaml +46 -46
  518. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/SKILL.md +85 -85
  519. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/checklist.md +611 -611
  520. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/customize.toml +40 -40
  521. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/instructions.md +49 -49
  522. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/adr-quality-readiness-checklist.md +377 -377
  523. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/api-request.md +563 -563
  524. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/api-testing-patterns.md +915 -915
  525. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/auth-session.md +548 -548
  526. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/burn-in.md +273 -273
  527. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/ci-burn-in.md +717 -717
  528. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/component-tdd.md +486 -486
  529. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/contract-testing.md +1066 -1066
  530. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/data-factories.md +500 -500
  531. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/email-auth.md +721 -721
  532. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/error-handling.md +725 -725
  533. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/feature-flags.md +750 -750
  534. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/file-utils.md +456 -456
  535. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/fixture-architecture.md +401 -401
  536. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/fixtures-composition.md +382 -382
  537. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/intercept-network-call.md +426 -426
  538. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/log.md +426 -426
  539. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/network-error-monitor.md +401 -401
  540. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/network-first.md +486 -486
  541. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/network-recorder.md +527 -527
  542. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/nfr-criteria.md +670 -670
  543. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/overview.md +286 -286
  544. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pact-broker-webhooks.md +237 -237
  545. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pact-consumer-di.md +310 -310
  546. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pact-consumer-framework-setup.md +757 -757
  547. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pact-mcp.md +205 -205
  548. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pactjs-utils-consumer-helpers.md +380 -380
  549. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pactjs-utils-overview.md +216 -216
  550. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pactjs-utils-provider-verifier.md +397 -397
  551. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/pactjs-utils-request-filter.md +224 -224
  552. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/playwright-cli.md +280 -280
  553. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/playwright-config.md +734 -734
  554. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/probability-impact.md +601 -601
  555. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/recurse.md +421 -421
  556. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/risk-governance.md +615 -615
  557. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/selective-testing.md +732 -732
  558. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/selector-resilience.md +527 -527
  559. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/test-healing-patterns.md +644 -644
  560. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/test-levels-framework.md +473 -473
  561. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/test-priorities-matrix.md +373 -373
  562. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/test-quality.md +664 -664
  563. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/timing-debugging.md +372 -372
  564. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/visual-debugging.md +527 -527
  565. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-module-setup.md +122 -122
  566. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-providers.md +155 -155
  567. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-risk-guidance.md +114 -114
  568. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-template-matchers.md +160 -160
  569. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-testing-fundamentals.md +42 -42
  570. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-timeout-error.md +130 -130
  571. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/knowledge/webhook-waiting-querying.md +167 -167
  572. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/tea-index.csv +51 -51
  573. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-01-preflight-and-context.md +237 -237
  574. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-01b-resume.md +94 -94
  575. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-02-identify-targets.md +169 -169
  576. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-03-generate-tests.md +394 -394
  577. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-03a-subagent-api.md +271 -271
  578. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-03b-subagent-backend.md +246 -246
  579. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-03b-subagent-e2e.md +213 -213
  580. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-03c-aggregate.md +398 -398
  581. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-04-validate-and-summarize.md +114 -114
  582. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-e/step-01-assess.md +65 -65
  583. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-e/step-02-apply-edit.md +68 -68
  584. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-v/step-01-validate.md +75 -75
  585. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/validation-report-20260127-095021.md +72 -72
  586. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/validation-report-20260127-102401.md +114 -114
  587. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/workflow-plan.md +20 -20
  588. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/workflow.yaml +53 -53
  589. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/SKILL.md +85 -85
  590. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/azure-pipelines-template.yaml +155 -155
  591. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/checklist.md +289 -289
  592. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/customize.toml +40 -40
  593. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/github-actions-template.yaml +328 -328
  594. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/gitlab-ci-template.yaml +158 -158
  595. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/harness-pipeline-template.yaml +160 -160
  596. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/instructions.md +44 -44
  597. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/jenkins-pipeline-template.groovy +129 -129
  598. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/adr-quality-readiness-checklist.md +377 -377
  599. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/api-request.md +563 -563
  600. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/api-testing-patterns.md +915 -915
  601. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/auth-session.md +548 -548
  602. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/burn-in.md +273 -273
  603. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/ci-burn-in.md +717 -717
  604. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/component-tdd.md +486 -486
  605. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/contract-testing.md +1066 -1066
  606. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/data-factories.md +500 -500
  607. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/email-auth.md +721 -721
  608. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/error-handling.md +725 -725
  609. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/feature-flags.md +750 -750
  610. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/file-utils.md +456 -456
  611. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/fixture-architecture.md +401 -401
  612. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/fixtures-composition.md +382 -382
  613. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/intercept-network-call.md +426 -426
  614. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/log.md +426 -426
  615. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/network-error-monitor.md +401 -401
  616. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/network-first.md +486 -486
  617. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/network-recorder.md +527 -527
  618. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/nfr-criteria.md +670 -670
  619. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/overview.md +286 -286
  620. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pact-broker-webhooks.md +237 -237
  621. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pact-consumer-di.md +310 -310
  622. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pact-consumer-framework-setup.md +757 -757
  623. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pact-mcp.md +205 -205
  624. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pactjs-utils-consumer-helpers.md +380 -380
  625. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pactjs-utils-overview.md +216 -216
  626. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pactjs-utils-provider-verifier.md +397 -397
  627. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/pactjs-utils-request-filter.md +224 -224
  628. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/playwright-cli.md +280 -280
  629. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/playwright-config.md +734 -734
  630. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/probability-impact.md +601 -601
  631. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/recurse.md +421 -421
  632. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/risk-governance.md +615 -615
  633. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/selective-testing.md +732 -732
  634. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/selector-resilience.md +527 -527
  635. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/test-healing-patterns.md +644 -644
  636. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/test-levels-framework.md +473 -473
  637. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/test-priorities-matrix.md +373 -373
  638. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/test-quality.md +664 -664
  639. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/timing-debugging.md +372 -372
  640. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/visual-debugging.md +527 -527
  641. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-module-setup.md +122 -122
  642. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-providers.md +155 -155
  643. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-risk-guidance.md +114 -114
  644. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-template-matchers.md +160 -160
  645. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-testing-fundamentals.md +42 -42
  646. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-timeout-error.md +130 -130
  647. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/knowledge/webhook-waiting-querying.md +167 -167
  648. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/tea-index.csv +51 -51
  649. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-c/step-01-preflight.md +158 -158
  650. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-c/step-01b-resume.md +110 -110
  651. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-c/step-02-generate-pipeline.md +293 -293
  652. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-c/step-03-configure-quality-gates.md +145 -145
  653. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-c/step-04-validate-and-summary.md +100 -100
  654. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-e/step-01-assess.md +65 -65
  655. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-e/step-02-apply-edit.md +68 -68
  656. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-v/step-01-validate.md +89 -89
  657. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/validation-report-20260127-095021.md +72 -72
  658. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/validation-report-20260127-102401.md +114 -114
  659. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/workflow-plan.md +20 -20
  660. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/workflow.yaml +48 -48
  661. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/SKILL.md +85 -85
  662. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/checklist.md +345 -345
  663. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/customize.toml +40 -40
  664. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/instructions.md +44 -44
  665. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/adr-quality-readiness-checklist.md +377 -377
  666. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/api-request.md +563 -563
  667. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/api-testing-patterns.md +915 -915
  668. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/auth-session.md +548 -548
  669. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/burn-in.md +273 -273
  670. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/ci-burn-in.md +717 -717
  671. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/component-tdd.md +486 -486
  672. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/contract-testing.md +1066 -1066
  673. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/data-factories.md +500 -500
  674. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/email-auth.md +721 -721
  675. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/error-handling.md +725 -725
  676. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/feature-flags.md +750 -750
  677. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/file-utils.md +456 -456
  678. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/fixture-architecture.md +401 -401
  679. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/fixtures-composition.md +382 -382
  680. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/intercept-network-call.md +426 -426
  681. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/log.md +426 -426
  682. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/network-error-monitor.md +401 -401
  683. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/network-first.md +486 -486
  684. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/network-recorder.md +527 -527
  685. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/nfr-criteria.md +670 -670
  686. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/overview.md +286 -286
  687. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pact-broker-webhooks.md +237 -237
  688. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pact-consumer-di.md +310 -310
  689. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pact-consumer-framework-setup.md +757 -757
  690. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pact-mcp.md +205 -205
  691. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pactjs-utils-consumer-helpers.md +380 -380
  692. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pactjs-utils-overview.md +216 -216
  693. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pactjs-utils-provider-verifier.md +397 -397
  694. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/pactjs-utils-request-filter.md +224 -224
  695. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/playwright-cli.md +280 -280
  696. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/playwright-config.md +734 -734
  697. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/probability-impact.md +601 -601
  698. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/recurse.md +421 -421
  699. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/risk-governance.md +615 -615
  700. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/selective-testing.md +732 -732
  701. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/selector-resilience.md +527 -527
  702. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/test-healing-patterns.md +644 -644
  703. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/test-levels-framework.md +473 -473
  704. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/test-priorities-matrix.md +373 -373
  705. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/test-quality.md +664 -664
  706. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/timing-debugging.md +372 -372
  707. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/visual-debugging.md +527 -527
  708. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-module-setup.md +122 -122
  709. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-providers.md +155 -155
  710. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-risk-guidance.md +114 -114
  711. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-template-matchers.md +160 -160
  712. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-testing-fundamentals.md +42 -42
  713. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-timeout-error.md +130 -130
  714. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/knowledge/webhook-waiting-querying.md +167 -167
  715. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/tea-index.csv +51 -51
  716. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-c/step-01-preflight.md +132 -132
  717. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-c/step-01b-resume.md +116 -116
  718. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-c/step-02-select-framework.md +117 -117
  719. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-c/step-03-scaffold-framework.md +328 -328
  720. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-c/step-04-docs-and-scripts.md +105 -105
  721. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-c/step-05-validate-and-summary.md +101 -101
  722. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-e/step-01-assess.md +65 -65
  723. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-e/step-02-apply-edit.md +68 -68
  724. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-v/step-01-validate.md +75 -75
  725. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/validation-report-20260127-095021.md +73 -73
  726. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/validation-report-20260127-102401.md +116 -116
  727. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/workflow-plan.md +22 -22
  728. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/workflow.yaml +48 -48
  729. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/SKILL.md +85 -85
  730. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/checklist.md +407 -407
  731. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/customize.toml +40 -40
  732. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/instructions.md +43 -43
  733. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/nfr-report-template.md +470 -470
  734. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/adr-quality-readiness-checklist.md +377 -377
  735. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/api-request.md +563 -563
  736. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/api-testing-patterns.md +915 -915
  737. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/auth-session.md +548 -548
  738. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/burn-in.md +273 -273
  739. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/ci-burn-in.md +717 -717
  740. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/component-tdd.md +486 -486
  741. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/contract-testing.md +1066 -1066
  742. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/data-factories.md +500 -500
  743. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/email-auth.md +721 -721
  744. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/error-handling.md +725 -725
  745. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/feature-flags.md +750 -750
  746. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/file-utils.md +456 -456
  747. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/fixture-architecture.md +401 -401
  748. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/fixtures-composition.md +382 -382
  749. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/intercept-network-call.md +426 -426
  750. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/log.md +426 -426
  751. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/network-error-monitor.md +401 -401
  752. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/network-first.md +486 -486
  753. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/network-recorder.md +527 -527
  754. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/nfr-criteria.md +670 -670
  755. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/overview.md +286 -286
  756. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pact-broker-webhooks.md +237 -237
  757. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pact-consumer-di.md +310 -310
  758. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pact-consumer-framework-setup.md +757 -757
  759. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pact-mcp.md +205 -205
  760. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pactjs-utils-consumer-helpers.md +380 -380
  761. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pactjs-utils-overview.md +216 -216
  762. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pactjs-utils-provider-verifier.md +397 -397
  763. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/pactjs-utils-request-filter.md +224 -224
  764. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/playwright-cli.md +280 -280
  765. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/playwright-config.md +734 -734
  766. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/probability-impact.md +601 -601
  767. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/recurse.md +421 -421
  768. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/risk-governance.md +615 -615
  769. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/selective-testing.md +732 -732
  770. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/selector-resilience.md +527 -527
  771. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/test-healing-patterns.md +644 -644
  772. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/test-levels-framework.md +473 -473
  773. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/test-priorities-matrix.md +373 -373
  774. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/test-quality.md +664 -664
  775. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/timing-debugging.md +372 -372
  776. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/visual-debugging.md +527 -527
  777. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-module-setup.md +122 -122
  778. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-providers.md +155 -155
  779. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-risk-guidance.md +114 -114
  780. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-template-matchers.md +160 -160
  781. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-testing-fundamentals.md +42 -42
  782. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-timeout-error.md +130 -130
  783. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/knowledge/webhook-waiting-querying.md +167 -167
  784. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/tea-index.csv +51 -51
  785. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-01-load-context.md +138 -138
  786. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-01b-resume.md +106 -106
  787. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-02-define-thresholds.md +107 -107
  788. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-03-gather-evidence.md +108 -108
  789. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04-evaluate-and-score.md +254 -254
  790. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04a-subagent-security.md +138 -138
  791. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04b-subagent-performance.md +84 -84
  792. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04c-subagent-reliability.md +85 -85
  793. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04d-subagent-scalability.md +88 -88
  794. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04e-aggregate-nfr.md +264 -264
  795. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-05-generate-report.md +116 -116
  796. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-e/step-01-assess.md +65 -65
  797. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-e/step-02-apply-edit.md +68 -68
  798. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-v/step-01-validate.md +75 -75
  799. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/validation-report-20260127-095021.md +73 -73
  800. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/validation-report-20260127-102401.md +116 -116
  801. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/workflow-plan.md +19 -19
  802. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/workflow.yaml +48 -48
  803. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/SKILL.md +87 -87
  804. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/checklist.md +464 -464
  805. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/customize.toml +40 -40
  806. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/instructions.md +104 -104
  807. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/adr-quality-readiness-checklist.md +377 -377
  808. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/api-request.md +563 -563
  809. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/api-testing-patterns.md +915 -915
  810. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/auth-session.md +548 -548
  811. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/burn-in.md +273 -273
  812. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/ci-burn-in.md +717 -717
  813. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/component-tdd.md +486 -486
  814. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/contract-testing.md +1066 -1066
  815. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/data-factories.md +500 -500
  816. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/email-auth.md +721 -721
  817. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/error-handling.md +725 -725
  818. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/feature-flags.md +750 -750
  819. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/file-utils.md +456 -456
  820. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/fixture-architecture.md +401 -401
  821. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/fixtures-composition.md +382 -382
  822. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/intercept-network-call.md +426 -426
  823. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/log.md +426 -426
  824. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/network-error-monitor.md +401 -401
  825. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/network-first.md +486 -486
  826. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/network-recorder.md +527 -527
  827. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/nfr-criteria.md +670 -670
  828. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/overview.md +286 -286
  829. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pact-broker-webhooks.md +237 -237
  830. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pact-consumer-di.md +310 -310
  831. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pact-consumer-framework-setup.md +757 -757
  832. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pact-mcp.md +205 -205
  833. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pactjs-utils-consumer-helpers.md +380 -380
  834. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pactjs-utils-overview.md +216 -216
  835. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pactjs-utils-provider-verifier.md +397 -397
  836. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/pactjs-utils-request-filter.md +224 -224
  837. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/playwright-cli.md +280 -280
  838. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/playwright-config.md +734 -734
  839. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/probability-impact.md +601 -601
  840. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/recurse.md +421 -421
  841. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/risk-governance.md +615 -615
  842. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/selective-testing.md +732 -732
  843. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/selector-resilience.md +527 -527
  844. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/test-healing-patterns.md +644 -644
  845. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/test-levels-framework.md +473 -473
  846. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/test-priorities-matrix.md +373 -373
  847. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/test-quality.md +664 -664
  848. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/timing-debugging.md +372 -372
  849. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/visual-debugging.md +527 -527
  850. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-module-setup.md +122 -122
  851. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-providers.md +155 -155
  852. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-risk-guidance.md +114 -114
  853. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-template-matchers.md +160 -160
  854. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-testing-fundamentals.md +42 -42
  855. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-timeout-error.md +130 -130
  856. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/knowledge/webhook-waiting-querying.md +167 -167
  857. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/tea-index.csv +51 -51
  858. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-01-detect-mode.md +140 -140
  859. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-01b-resume.md +116 -116
  860. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-02-load-context.md +248 -248
  861. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-03-risk-and-testability.md +116 -116
  862. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-04-coverage-plan.md +129 -129
  863. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-05-generate-output.md +236 -236
  864. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-e/step-01-assess.md +65 -65
  865. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-e/step-02-apply-edit.md +68 -68
  866. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-v/step-01-validate.md +75 -75
  867. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/test-design-architecture-template.md +233 -233
  868. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/test-design-handoff-template.md +70 -70
  869. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/test-design-qa-template.md +399 -399
  870. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/test-design-template.md +347 -347
  871. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/validation-report-20260127-095021.md +73 -73
  872. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/validation-report-20260127-102401.md +116 -116
  873. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/workflow-plan.md +22 -22
  874. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/workflow.yaml +77 -77
  875. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/SKILL.md +85 -85
  876. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/checklist.md +475 -475
  877. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/customize.toml +40 -40
  878. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/instructions.md +45 -45
  879. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/adr-quality-readiness-checklist.md +377 -377
  880. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/api-request.md +563 -563
  881. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/api-testing-patterns.md +915 -915
  882. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/auth-session.md +548 -548
  883. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/burn-in.md +273 -273
  884. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/ci-burn-in.md +717 -717
  885. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/component-tdd.md +486 -486
  886. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/contract-testing.md +1066 -1066
  887. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/data-factories.md +500 -500
  888. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/email-auth.md +721 -721
  889. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/error-handling.md +725 -725
  890. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/feature-flags.md +750 -750
  891. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/file-utils.md +456 -456
  892. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/fixture-architecture.md +401 -401
  893. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/fixtures-composition.md +382 -382
  894. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/intercept-network-call.md +426 -426
  895. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/log.md +426 -426
  896. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/network-error-monitor.md +401 -401
  897. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/network-first.md +486 -486
  898. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/network-recorder.md +527 -527
  899. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/nfr-criteria.md +670 -670
  900. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/overview.md +286 -286
  901. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pact-broker-webhooks.md +237 -237
  902. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pact-consumer-di.md +310 -310
  903. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pact-consumer-framework-setup.md +757 -757
  904. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pact-mcp.md +205 -205
  905. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pactjs-utils-consumer-helpers.md +380 -380
  906. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pactjs-utils-overview.md +216 -216
  907. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pactjs-utils-provider-verifier.md +397 -397
  908. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/pactjs-utils-request-filter.md +224 -224
  909. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/playwright-cli.md +280 -280
  910. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/playwright-config.md +734 -734
  911. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/probability-impact.md +601 -601
  912. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/recurse.md +421 -421
  913. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/risk-governance.md +615 -615
  914. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/selective-testing.md +732 -732
  915. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/selector-resilience.md +527 -527
  916. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/test-healing-patterns.md +644 -644
  917. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/test-levels-framework.md +473 -473
  918. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/test-priorities-matrix.md +373 -373
  919. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/test-quality.md +664 -664
  920. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/timing-debugging.md +372 -372
  921. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/visual-debugging.md +527 -527
  922. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-module-setup.md +122 -122
  923. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-providers.md +155 -155
  924. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-risk-guidance.md +114 -114
  925. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-template-matchers.md +160 -160
  926. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-testing-fundamentals.md +42 -42
  927. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-timeout-error.md +130 -130
  928. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/knowledge/webhook-waiting-querying.md +167 -167
  929. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/tea-index.csv +51 -51
  930. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-01-load-context.md +197 -197
  931. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-01b-resume.md +104 -104
  932. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-02-discover-tests.md +120 -120
  933. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-03-quality-evaluation.md +274 -274
  934. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-03a-subagent-determinism.md +257 -257
  935. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-03b-subagent-isolation.md +125 -125
  936. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-03c-subagent-maintainability.md +102 -102
  937. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-03e-subagent-performance.md +117 -117
  938. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-03f-aggregate-scores.md +277 -277
  939. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-04-generate-report.md +119 -119
  940. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-e/step-01-assess.md +65 -65
  941. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-e/step-02-apply-edit.md +68 -68
  942. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-v/step-01-validate.md +75 -75
  943. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/test-review-template.md +387 -387
  944. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/validation-report-20260127-095021.md +72 -72
  945. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/validation-report-20260127-102401.md +114 -114
  946. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/workflow-plan.md +18 -18
  947. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/workflow.yaml +48 -48
  948. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/SKILL.md +87 -87
  949. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/checklist.md +671 -671
  950. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/customize.toml +40 -40
  951. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/instructions.md +45 -45
  952. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/adr-quality-readiness-checklist.md +377 -377
  953. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/api-request.md +563 -563
  954. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/api-testing-patterns.md +915 -915
  955. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/auth-session.md +548 -548
  956. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/burn-in.md +273 -273
  957. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/ci-burn-in.md +717 -717
  958. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/component-tdd.md +486 -486
  959. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/contract-testing.md +1066 -1066
  960. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/data-factories.md +500 -500
  961. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/email-auth.md +721 -721
  962. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/error-handling.md +725 -725
  963. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/feature-flags.md +750 -750
  964. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/file-utils.md +456 -456
  965. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/fixture-architecture.md +401 -401
  966. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/fixtures-composition.md +382 -382
  967. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/intercept-network-call.md +426 -426
  968. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/log.md +426 -426
  969. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/network-error-monitor.md +401 -401
  970. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/network-first.md +486 -486
  971. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/network-recorder.md +527 -527
  972. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/nfr-criteria.md +670 -670
  973. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/overview.md +286 -286
  974. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pact-broker-webhooks.md +237 -237
  975. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pact-consumer-di.md +310 -310
  976. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pact-consumer-framework-setup.md +757 -757
  977. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pact-mcp.md +205 -205
  978. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pactjs-utils-consumer-helpers.md +380 -380
  979. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pactjs-utils-overview.md +216 -216
  980. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pactjs-utils-provider-verifier.md +397 -397
  981. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/pactjs-utils-request-filter.md +224 -224
  982. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/playwright-cli.md +280 -280
  983. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/playwright-config.md +734 -734
  984. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/probability-impact.md +601 -601
  985. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/recurse.md +421 -421
  986. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/risk-governance.md +615 -615
  987. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/selective-testing.md +732 -732
  988. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/selector-resilience.md +527 -527
  989. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/test-healing-patterns.md +644 -644
  990. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/test-levels-framework.md +473 -473
  991. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/test-priorities-matrix.md +373 -373
  992. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/test-quality.md +664 -664
  993. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/timing-debugging.md +372 -372
  994. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/visual-debugging.md +527 -527
  995. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-module-setup.md +122 -122
  996. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-providers.md +155 -155
  997. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-risk-guidance.md +114 -114
  998. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-template-matchers.md +160 -160
  999. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-testing-fundamentals.md +42 -42
  1000. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-timeout-error.md +130 -130
  1001. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/knowledge/webhook-waiting-querying.md +167 -167
  1002. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/tea-index.csv +51 -51
  1003. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-01-load-context.md +166 -166
  1004. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-01b-resume.md +102 -102
  1005. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-02-discover-tests.md +132 -132
  1006. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-03-map-criteria.md +101 -101
  1007. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-04-analyze-gaps.md +628 -628
  1008. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-05-gate-decision.md +681 -681
  1009. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-e/step-01-assess.md +65 -65
  1010. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-e/step-02-apply-edit.md +68 -68
  1011. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-v/step-01-validate.md +75 -75
  1012. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/trace-template.md +716 -716
  1013. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/validation-report-20260127-095021.md +73 -73
  1014. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/validation-report-20260127-102401.md +116 -116
  1015. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/workflow-plan.md +24 -24
  1016. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/workflow.yaml +80 -80
  1017. package/lib/bmad-cache/tea/test/README.md +23 -23
  1018. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/critical-actions/actions-as-string.agent.yaml +27 -27
  1019. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/critical-actions/empty-string-in-actions.agent.yaml +30 -30
  1020. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/menu/empty-menu.agent.yaml +22 -22
  1021. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/menu/missing-menu.agent.yaml +20 -20
  1022. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/menu-commands/empty-command-target.agent.yaml +25 -25
  1023. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/menu-commands/no-command-target.agent.yaml +24 -24
  1024. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/menu-triggers/camel-case.agent.yaml +25 -25
  1025. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/menu-triggers/compound-invalid-format.agent.yaml +25 -25
  1026. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/menu-triggers/compound-mismatched-kebab.agent.yaml +25 -25
  1027. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/menu-triggers/duplicate-triggers.agent.yaml +31 -31
  1028. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/menu-triggers/empty-trigger.agent.yaml +25 -25
  1029. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/menu-triggers/leading-asterisk.agent.yaml +25 -25
  1030. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/menu-triggers/snake-case.agent.yaml +25 -25
  1031. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/menu-triggers/trigger-with-spaces.agent.yaml +25 -25
  1032. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/metadata/empty-module-string.agent.yaml +26 -26
  1033. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/metadata/empty-name.agent.yaml +24 -24
  1034. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/metadata/extra-metadata-fields.agent.yaml +27 -27
  1035. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/metadata/missing-id.agent.yaml +23 -23
  1036. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/persona/empty-principles-array.agent.yaml +24 -24
  1037. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/persona/empty-string-in-principles.agent.yaml +27 -27
  1038. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/persona/extra-persona-fields.agent.yaml +27 -27
  1039. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/persona/missing-role.agent.yaml +24 -24
  1040. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/prompts/empty-content.agent.yaml +29 -29
  1041. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/prompts/extra-prompt-fields.agent.yaml +31 -31
  1042. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/prompts/missing-content.agent.yaml +28 -28
  1043. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/prompts/missing-id.agent.yaml +28 -28
  1044. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/top-level/empty-file.agent.yaml +5 -5
  1045. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/top-level/extra-top-level-keys.agent.yaml +28 -28
  1046. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/top-level/missing-agent-key.agent.yaml +11 -11
  1047. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/yaml-errors/invalid-indentation.agent.yaml +19 -19
  1048. package/lib/bmad-cache/tea/test/fixtures/agent-schema/invalid/yaml-errors/malformed-yaml.agent.yaml +18 -18
  1049. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/critical-actions/empty-critical-actions.agent.yaml +24 -24
  1050. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/critical-actions/no-critical-actions.agent.yaml +22 -22
  1051. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/critical-actions/valid-critical-actions.agent.yaml +27 -27
  1052. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/menu/multiple-menu-items.agent.yaml +31 -31
  1053. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/menu/single-menu-item.agent.yaml +22 -22
  1054. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/menu-commands/all-command-types.agent.yaml +37 -37
  1055. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/menu-commands/multiple-commands.agent.yaml +24 -24
  1056. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/menu-triggers/compound-triggers.agent.yaml +31 -31
  1057. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/menu-triggers/kebab-case-triggers.agent.yaml +34 -34
  1058. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/metadata/core-agent-with-module.agent.yaml +24 -24
  1059. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/metadata/empty-module-name-in-path.agent.yaml +24 -24
  1060. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/metadata/malformed-path-treated-as-core.agent.yaml +24 -24
  1061. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/metadata/module-agent-correct.agent.yaml +24 -24
  1062. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/metadata/module-agent-missing-module.agent.yaml +23 -23
  1063. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/metadata/wrong-module-value.agent.yaml +24 -24
  1064. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/persona/complete-persona.agent.yaml +24 -24
  1065. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/prompts/empty-prompts.agent.yaml +24 -24
  1066. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/prompts/no-prompts.agent.yaml +22 -22
  1067. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/prompts/valid-prompts-minimal.agent.yaml +28 -28
  1068. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/prompts/valid-prompts-with-description.agent.yaml +30 -30
  1069. package/lib/bmad-cache/tea/test/fixtures/agent-schema/valid/top-level/minimal-core-agent.agent.yaml +24 -24
  1070. package/lib/bmad-cache/tea/test/schema/agent.js +491 -491
  1071. package/lib/bmad-cache/tea/test/test-agent-schema.js +387 -387
  1072. package/lib/bmad-cache/tea/test/test-installation-components.js +422 -422
  1073. package/lib/bmad-cache/tea/test/test-knowledge-base.js +213 -213
  1074. package/lib/bmad-cache/tea/test/test-release-metadata.js +71 -71
  1075. package/lib/bmad-cache/tea/test/unit-test-schema.js +133 -133
  1076. package/lib/bmad-cache/tea/test/validate-agent-schema.js +110 -110
  1077. package/lib/bmad-cache/tea/tools/build-docs.js +575 -575
  1078. package/lib/bmad-cache/tea/tools/fix-doc-links.js +288 -288
  1079. package/lib/bmad-cache/tea/tools/schema/agent.js +491 -491
  1080. package/lib/bmad-cache/tea/tools/validate-agent-schema.js +284 -284
  1081. package/lib/bmad-cache/tea/tools/validate-doc-links.js +371 -371
  1082. package/lib/bmad-cache/tea/tools/validate-tea-workflow-descriptions.js +122 -122
  1083. package/lib/bmad-cache/tea/tools/verify-paths.js +100 -100
  1084. package/lib/bmad-cache/tea/website/README.md +137 -137
  1085. package/lib/bmad-cache/tea/website/astro.config.mjs +183 -183
  1086. package/lib/bmad-cache/tea/website/package-lock.json +6856 -6856
  1087. package/lib/bmad-cache/tea/website/package.json +24 -24
  1088. package/lib/bmad-cache/tea/website/public/img/tea-logo.svg +7 -7
  1089. package/lib/bmad-cache/tea/website/public/robots.txt +37 -37
  1090. package/lib/bmad-cache/tea/website/src/components/Banner.astro +74 -74
  1091. package/lib/bmad-cache/tea/website/src/components/Header.astro +121 -121
  1092. package/lib/bmad-cache/tea/website/src/components/MobileMenuFooter.astro +53 -53
  1093. package/lib/bmad-cache/tea/website/src/content/config.ts +6 -6
  1094. package/lib/bmad-cache/tea/website/src/lib/site-url.js +25 -25
  1095. package/lib/bmad-cache/tea/website/src/pages/404.astro +11 -11
  1096. package/lib/bmad-cache/tea/website/src/rehype-base-paths.js +89 -89
  1097. package/lib/bmad-cache/tea/website/src/rehype-markdown-links.js +117 -117
  1098. package/lib/bmad-cache/tea/website/src/styles/custom.css +518 -518
  1099. package/lib/bmad-cache/tea/website/tsconfig.json +9 -9
  1100. package/lib/bmad-cache/wds/.claude-plugin/marketplace.json +35 -35
  1101. package/lib/bmad-cache/wds/.markdownlint-cli2.yaml +38 -38
  1102. package/lib/bmad-cache/wds/.prettierignore +9 -9
  1103. package/lib/bmad-cache/wds/LICENSE +27 -27
  1104. package/lib/bmad-cache/wds/README.md +139 -139
  1105. package/lib/bmad-cache/wds/_git_preserved/HEAD +1 -1
  1106. package/lib/bmad-cache/wds/_git_preserved/config +13 -13
  1107. package/lib/bmad-cache/wds/_git_preserved/description +1 -1
  1108. package/lib/bmad-cache/wds/_git_preserved/hooks/applypatch-msg.sample +15 -15
  1109. package/lib/bmad-cache/wds/_git_preserved/hooks/commit-msg.sample +24 -24
  1110. package/lib/bmad-cache/wds/_git_preserved/hooks/fsmonitor-watchman.sample +174 -174
  1111. package/lib/bmad-cache/wds/_git_preserved/hooks/post-update.sample +8 -8
  1112. package/lib/bmad-cache/wds/_git_preserved/hooks/pre-applypatch.sample +14 -14
  1113. package/lib/bmad-cache/wds/_git_preserved/hooks/pre-commit.sample +49 -49
  1114. package/lib/bmad-cache/wds/_git_preserved/hooks/pre-merge-commit.sample +13 -13
  1115. package/lib/bmad-cache/wds/_git_preserved/hooks/pre-push.sample +53 -53
  1116. package/lib/bmad-cache/wds/_git_preserved/hooks/pre-rebase.sample +169 -169
  1117. package/lib/bmad-cache/wds/_git_preserved/hooks/pre-receive.sample +24 -24
  1118. package/lib/bmad-cache/wds/_git_preserved/hooks/prepare-commit-msg.sample +42 -42
  1119. package/lib/bmad-cache/wds/_git_preserved/hooks/push-to-checkout.sample +78 -78
  1120. package/lib/bmad-cache/wds/_git_preserved/hooks/sendemail-validate.sample +77 -77
  1121. package/lib/bmad-cache/wds/_git_preserved/hooks/update.sample +128 -128
  1122. package/lib/bmad-cache/wds/_git_preserved/info/exclude +6 -6
  1123. package/lib/bmad-cache/wds/_git_preserved/packed-refs +2 -2
  1124. package/lib/bmad-cache/wds/_git_preserved/refs/heads/main +1 -1
  1125. package/lib/bmad-cache/wds/_git_preserved/refs/remotes/origin/HEAD +1 -1
  1126. package/lib/bmad-cache/wds/_git_preserved/shallow +1 -1
  1127. package/lib/bmad-cache/wds/eslint.config.mjs +152 -152
  1128. package/lib/bmad-cache/wds/package.json +82 -82
  1129. package/lib/bmad-cache/wds/prettier.config.mjs +32 -32
  1130. package/lib/bmad-cache/wds/src/agents/wds-agent-freya-ux/bmad-skill-manifest.yaml +12 -12
  1131. package/lib/bmad-cache/wds/src/agents/wds-agent-saga-analyst/bmad-skill-manifest.yaml +12 -12
  1132. package/lib/bmad-cache/wds/src/module-help.csv +19 -19
  1133. package/lib/bmad-cache/wds/src/module.yaml +145 -145
  1134. package/lib/bmad-cache/wds/src/workflows/wds-0-alignment-signoff/bmad-skill-manifest.yaml +1 -1
  1135. package/lib/bmad-cache/wds/src/workflows/wds-0-project-setup/bmad-skill-manifest.yaml +1 -1
  1136. package/lib/bmad-cache/wds/src/workflows/wds-0-project-setup/resources/wds-1-project-brief/templates/platform-requirements.template.yaml +69 -69
  1137. package/lib/bmad-cache/wds/src/workflows/wds-0-project-setup/resources/wds-7-design-system/templates/catalog.template.html +363 -363
  1138. package/lib/bmad-cache/wds/src/workflows/wds-1-project-brief/bmad-skill-manifest.yaml +1 -1
  1139. package/lib/bmad-cache/wds/src/workflows/wds-1-project-brief/templates/platform-requirements.template.yaml +69 -69
  1140. package/lib/bmad-cache/wds/src/workflows/wds-2-trigger-mapping/bmad-skill-manifest.yaml +1 -1
  1141. package/lib/bmad-cache/wds/src/workflows/wds-3-scenarios/bmad-skill-manifest.yaml +1 -1
  1142. package/lib/bmad-cache/wds/src/workflows/wds-4-ux-design/bmad-skill-manifest.yaml +1 -1
  1143. package/lib/bmad-cache/wds/src/workflows/wds-4-ux-design/templates/design-delivery.template.yaml +104 -104
  1144. package/lib/bmad-cache/wds/src/workflows/wds-4-ux-design/templates/test-scenario.template.yaml +192 -192
  1145. package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/bmad-skill-manifest.yaml +1 -1
  1146. package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/templates/components/dev-mode.css +164 -164
  1147. package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/templates/components/dev-mode.html +18 -18
  1148. package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/templates/components/dev-mode.js +430 -430
  1149. package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/templates/demo-data-template.json +63 -63
  1150. package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/templates/page-template.html +465 -465
  1151. package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/templates/work-file-template.yaml +264 -264
  1152. package/lib/bmad-cache/wds/src/workflows/wds-6-asset-generation/bmad-skill-manifest.yaml +1 -1
  1153. package/lib/bmad-cache/wds/src/workflows/wds-7-design-system/bmad-skill-manifest.yaml +1 -1
  1154. package/lib/bmad-cache/wds/src/workflows/wds-7-design-system/templates/catalog.template.html +363 -363
  1155. package/lib/bmad-cache/wds/src/workflows/wds-8-product-evolution/bmad-skill-manifest.yaml +1 -1
  1156. package/lib/bmad-customize/bmm-analyst.customize.yaml +8 -8
  1157. package/lib/bmad-customize/bmm-architect.customize.yaml +8 -8
  1158. package/lib/bmad-customize/bmm-bmad-master.customize.yaml +6 -6
  1159. package/lib/bmad-customize/bmm-dev.customize.yaml +8 -8
  1160. package/lib/bmad-customize/bmm-pm.customize.yaml +8 -8
  1161. package/lib/bmad-customize/bmm-qa.customize.yaml +26 -26
  1162. package/lib/bmad-customize/bmm-sm.customize.yaml +8 -8
  1163. package/lib/bmad-customize/bmm-tech-writer.customize.yaml +8 -8
  1164. package/lib/bmad-customize/bmm-ux-designer.customize.yaml +8 -8
  1165. package/lib/bmad-extension-plugin/.claude-plugin/marketplace.json +1 -1
  1166. package/lib/bmad.js +191 -1
  1167. package/lib/installer.js +2024 -2024
  1168. package/lib/merge/roomodes.js +125 -125
  1169. package/lib/methodology/version.json +7 -7
  1170. package/lib/mil498-templates/OCD.md +169 -169
  1171. package/lib/mil498-templates/README.md +4 -4
  1172. package/lib/mil498-templates/SDD.md +163 -163
  1173. package/lib/mil498-templates/SDP.md +307 -307
  1174. package/lib/mil498-templates/SRS.md +219 -219
  1175. package/lib/mil498-templates/SSDD.md +154 -154
  1176. package/lib/mil498-templates/SSS.md +225 -225
  1177. package/lib/mil498-templates/STD.md +188 -188
  1178. package/lib/profile.js +130 -130
  1179. package/lib/reconfigure.js +334 -334
  1180. package/lib/skill-authoring.js +732 -732
  1181. package/lib/templates/agents-md.template.md +67 -67
  1182. package/lib/templates/clinerules.template.md +13 -13
  1183. package/lib/templates/instruction-block-onprem.template.md +86 -86
  1184. package/lib/templates/instruction-block-universal.template.md +29 -29
  1185. package/lib/templates/project-context.template.md +47 -47
  1186. package/lib/templates/roomodes.template.yaml +96 -96
  1187. package/lib/uninstall.js +314 -314
  1188. package/lib/warning-filter.js +245 -245
  1189. package/mil498/OCD.md +169 -169
  1190. package/mil498/README.md +4 -4
  1191. package/mil498/SDP.md +307 -307
  1192. package/mil498/SRS.md +219 -219
  1193. package/mil498/SSDD.md +154 -154
  1194. package/mil498/SSS.md +225 -225
  1195. package/mil498/STD.md +188 -188
  1196. package/package.json +57 -57
  1197. package/scripts/build-bmad-cache.js +494 -494
  1198. package/skills/README.md +473 -473
  1199. package/skills/add-sprint/SKILL.md +204 -204
  1200. package/skills/add-sprint/skill.json +7 -7
  1201. package/skills/add-to-sprint/SKILL.md +270 -270
  1202. package/skills/add-to-sprint/skill.json +7 -7
  1203. package/skills/ai-audit-trail/SKILL.md +19 -19
  1204. package/skills/ai-audit-trail/skill.json +20 -20
  1205. package/skills/auto-bug-detection/SKILL.md +165 -165
  1206. package/skills/auto-bug-detection/skill.json +8 -8
  1207. package/skills/bmad-sprint-planning/SKILL.md +362 -362
  1208. package/skills/bmad-sprint-planning/skill.json +7 -7
  1209. package/skills/bmad-sprint-status/SKILL.md +312 -312
  1210. package/skills/bmad-sprint-status/skill.json +7 -7
  1211. package/skills/cleanup-done/SKILL.md +242 -242
  1212. package/skills/cleanup-done/skill.json +7 -7
  1213. package/skills/close-sprint/SKILL.md +409 -409
  1214. package/skills/close-sprint/skill.json +7 -7
  1215. package/skills/code-review/SKILL.md +79 -79
  1216. package/skills/code-review/claude-code.md +64 -64
  1217. package/skills/code-review/cline.md +55 -55
  1218. package/skills/code-review/generic.md +39 -39
  1219. package/skills/code-review/skill.json +7 -7
  1220. package/skills/commit-message/SKILL.md +75 -75
  1221. package/skills/commit-message/generic.md +75 -75
  1222. package/skills/commit-message/skill.json +7 -7
  1223. package/skills/cpp-best-practices/SKILL.md +230 -230
  1224. package/skills/cpp-best-practices/examples/modern-idioms.md +189 -189
  1225. package/skills/cpp-best-practices/examples/naming-and-organization.md +102 -102
  1226. package/skills/cpp-best-practices/skill.json +25 -25
  1227. package/skills/create-hardened-docker-skill/README.md +85 -85
  1228. package/skills/create-hardened-docker-skill/SKILL.md +633 -633
  1229. package/skills/create-hardened-docker-skill/scripts/create-all.sh +489 -489
  1230. package/skills/create-hardened-docker-skill/skill.json +7 -7
  1231. package/skills/csharp-best-practices/SKILL.md +274 -274
  1232. package/skills/csharp-best-practices/skill.json +23 -23
  1233. package/skills/docker-hardening-verification/scripts/verify-hardening.sh +39 -39
  1234. package/skills/docker-image-signing/scripts/sign-image.sh +33 -33
  1235. package/skills/document-revision-history/SKILL.md +100 -100
  1236. package/skills/document-revision-history/skill.json +18 -18
  1237. package/skills/generate-backlog/SKILL.md +219 -219
  1238. package/skills/generate-backlog/skill.json +7 -7
  1239. package/skills/git-workflow-skill/README.md +135 -135
  1240. package/skills/git-workflow-skill/SKILL.md +190 -190
  1241. package/skills/git-workflow-skill/hooks/commit-msg +61 -61
  1242. package/skills/git-workflow-skill/hooks/pre-commit +38 -38
  1243. package/skills/git-workflow-skill/hooks/prepare-commit-msg +56 -56
  1244. package/skills/git-workflow-skill/scripts/finish-feature.sh +192 -192
  1245. package/skills/git-workflow-skill/scripts/install-hooks.sh +55 -55
  1246. package/skills/git-workflow-skill/scripts/start-feature.sh +110 -110
  1247. package/skills/git-workflow-skill/scripts/validate-workflow.sh +229 -229
  1248. package/skills/git-workflow-skill/skill.json +21 -21
  1249. package/skills/js-ts-security-skill/scripts/verify-security.sh +136 -136
  1250. package/skills/js-ts-security-skill/skill.json +17 -17
  1251. package/skills/modify-sprint/SKILL.md +341 -341
  1252. package/skills/modify-sprint/skill.json +7 -7
  1253. package/skills/open-presentation/SKILL.md +31 -31
  1254. package/skills/open-presentation/skill.json +11 -11
  1255. package/skills/prioritize-backlog/SKILL.md +242 -242
  1256. package/skills/prioritize-backlog/skill.json +7 -7
  1257. package/skills/python-best-practices/SKILL.md +381 -381
  1258. package/skills/python-best-practices/skill.json +26 -26
  1259. package/skills/remove-from-sprint/SKILL.md +213 -213
  1260. package/skills/remove-from-sprint/skill.json +7 -7
  1261. package/skills/self-signed-cert/scripts/generate-cert.sh +43 -43
  1262. package/skills/skill-creator/SKILL.md +211 -211
  1263. package/skills/skill-creator/claude-code.md +64 -64
  1264. package/skills/skill-creator/generic.md +192 -192
  1265. package/skills/skill-creator/references/output-patterns.md +82 -82
  1266. package/skills/skill-creator/references/workflows.md +28 -28
  1267. package/skills/skill-creator/scripts/init_skill.py +208 -208
  1268. package/skills/skill-creator/scripts/package_skill.py +99 -99
  1269. package/skills/skill-creator/scripts/quick_validate.py +113 -113
  1270. package/skills/skill-creator/skill.json +8 -8
  1271. package/skills/sprint-status-view/SKILL.md +212 -212
  1272. package/skills/sprint-status-view/skill.json +7 -7
  1273. package/skills/story-status-lookup/SKILL.md +106 -106
  1274. package/skills/story-status-lookup/skill.json +8 -8
  1275. package/skills/test-generator/SKILL.md +74 -74
  1276. package/skills/test-generator/claude-code.md +103 -103
  1277. package/skills/test-generator/cline.md +69 -69
  1278. package/skills/test-generator/generic.md +61 -61
  1279. package/skills/test-generator/skill.json +18 -18
  1280. package/skills/vercel-react-best-practices/SKILL.md +105 -105
  1281. package/skills/vercel-react-best-practices/claude-code.md +80 -80
  1282. package/skills/vercel-react-best-practices/generic.md +105 -105
  1283. package/skills/vercel-react-best-practices/skill.json +19 -19
  1284. package/skills/verify-hardened-docker-skill/README.md +85 -85
  1285. package/skills/verify-hardened-docker-skill/SKILL.md +438 -438
  1286. package/skills/verify-hardened-docker-skill/scripts/verify-docker-hardening.sh +439 -439
  1287. package/skills/verify-hardened-docker-skill/skill.json +7 -7
  1288. package/lib/.bmad-extension-plugin.build-1264-1777348888201/.claude-plugin/marketplace.json +0 -109
  1289. package/lib/.bmad-extension-plugin.build-1264-1777348888201/skills/module-help.csv +0 -62
  1290. package/lib/.bmad-extension-plugin.build-1264-1777348888201/skills/module.yaml +0 -20
  1291. package/lib/.bmad-extension-plugin.build-24696-1777348768444/.claude-plugin/marketplace.json +0 -109
  1292. package/lib/.bmad-extension-plugin.build-24696-1777348768444/skills/module-help.csv +0 -62
  1293. package/lib/.bmad-extension-plugin.build-24696-1777348768444/skills/module.yaml +0 -20
  1294. package/lib/.bmad-extension-plugin.build-25428-1777348694953/.claude-plugin/marketplace.json +0 -109
  1295. package/lib/.bmad-extension-plugin.build-25428-1777348694953/skills/module-help.csv +0 -62
  1296. package/lib/.bmad-extension-plugin.build-25428-1777348694953/skills/module.yaml +0 -20
  1297. package/lib/bmad-cache/bmb/_git_preserved/logs/HEAD +0 -1
  1298. package/lib/bmad-cache/bmb/_git_preserved/logs/refs/heads/main +0 -1
  1299. package/lib/bmad-cache/bmb/_git_preserved/logs/refs/remotes/origin/HEAD +0 -1
  1300. package/lib/bmad-cache/cis/_git_preserved/logs/HEAD +0 -1
  1301. package/lib/bmad-cache/cis/_git_preserved/logs/refs/heads/main +0 -1
  1302. package/lib/bmad-cache/cis/_git_preserved/logs/refs/remotes/origin/HEAD +0 -1
  1303. package/lib/bmad-cache/gds/_git_preserved/logs/HEAD +0 -1
  1304. package/lib/bmad-cache/gds/_git_preserved/logs/refs/heads/main +0 -1
  1305. package/lib/bmad-cache/gds/_git_preserved/logs/refs/remotes/origin/HEAD +0 -1
  1306. package/lib/bmad-cache/tea/.github/workflows/publish.yaml +0 -168
  1307. package/lib/bmad-cache/tea/.vscode/settings.json +0 -47
  1308. package/lib/bmad-cache/wds/_git_preserved/logs/HEAD +0 -1
  1309. package/lib/bmad-cache/wds/_git_preserved/logs/refs/heads/main +0 -1
  1310. package/lib/bmad-cache/wds/_git_preserved/logs/refs/remotes/origin/HEAD +0 -1
package/bin/cli.js CHANGED
@@ -1,1573 +1,1681 @@
1
- #!/usr/bin/env node
2
-
3
- // Bug A fix — suppress the cosmetic Node.js ExperimentalWarning about
4
- // CommonJS require() of an ES Module. Must be installed BEFORE any
5
- // other require() so the filter catches warnings fired by the very
6
- // first dependency-loading call below. See lib/warning-filter.js.
7
- //
8
- // Re-exec gating:
9
- // - Only when this file is launched as the CLI (require.main === module).
10
- // When imported by the test suite or another script, skip the re-exec
11
- // path — otherwise the importing process would silently fork itself.
12
- // - Only for commands that can trigger the CJS-require-ESM warning,
13
- // i.e. those that spawn bmad-method or otherwise load the heavy
14
- // transitive dependency graph. Informational commands (--help,
15
- // --version, status, list, agents) stay single-process for fast
16
- // cold start. The listener-only fallback is still attached so
17
- // in-process warnings still route through our filter.
18
- const { installExperimentalWarningFilter } = require('../lib/warning-filter');
19
- const _reexecCommands = new Set([
20
- 'install', 'uninstall', 'remove',
21
- 'create-skill', 'validate-skill', 'set-mandatory',
22
- 'customize-agent', 'create-agent',
23
- 'config',
24
- undefined, // bare `ma-agents` → interactive wizard
25
- ]);
26
- const _firstArg = process.argv[2];
27
- installExperimentalWarningFilter({
28
- reexec: require.main === module && _reexecCommands.has(_firstArg),
29
- });
30
-
31
- const prompts = require('prompts');
32
- const chalk = require('chalk');
33
- const path = require('path');
34
- const fs = require('fs');
35
- const { execFileSync } = require('child_process');
36
- const { installSkill, uninstallSkill, getStatus, listSkills, listAgents, updateProjectContextRepoLayout, migrateRetiredSkills } = require('../lib/installer');
37
- const { getProfile, setProfile, resolveProfile } = require('../lib/profile');
38
- const { reconfigure: runReconfigure, ReconfigureYesRejectedError, ManifestNotFoundError, RoomodesSlugDivergenceError } = require('../lib/reconfigure');
39
- const { uninstallProfileArtifacts } = require('../lib/uninstall');
40
- const bmad = require('../lib/bmad');
41
- const { getBmadPlatformCode } = require('../lib/agents');
42
- const { handleCreateSkill, handleValidateSkill, handleSetMandatory, handleCustomizeAgent, handleCreateAgent } = require('../lib/skill-authoring');
43
-
44
- const PKG = require('../package.json');
45
- const NAME = PKG.name;
46
- const VERSION = PKG.version;
47
-
48
- /**
49
- * Set up logging to tee all stdout/stderr output to a file.
50
- * Returns a cleanup function to close the file descriptor.
51
- *
52
- * @param {string} logFilePath - Path to the log file
53
- * @returns {Function} cleanup function
54
- */
55
- function setupLogging(logFilePath) {
56
- const logFd = fs.openSync(logFilePath, 'w');
57
- const header = `[${new Date().toISOString()}] ${NAME} v${VERSION} — log started\n`;
58
- fs.writeSync(logFd, header);
59
-
60
- const origStdoutWrite = process.stdout.write.bind(process.stdout);
61
- const origStderrWrite = process.stderr.write.bind(process.stderr);
62
-
63
- process.stdout.write = function (chunk, encoding, callback) {
64
- const str = typeof chunk === 'string' ? chunk : chunk.toString();
65
- try { fs.writeSync(logFd, str); } catch { /* ignore write errors */ }
66
- return origStdoutWrite(chunk, encoding, callback);
67
- };
68
-
69
- process.stderr.write = function (chunk, encoding, callback) {
70
- const str = typeof chunk === 'string' ? chunk : chunk.toString();
71
- try { fs.writeSync(logFd, str); } catch { /* ignore write errors */ }
72
- return origStderrWrite(chunk, encoding, callback);
73
- };
74
-
75
- // Store log fd globally so bmad.js can use pipe mode
76
- process.env.MA_AGENTS_LOG_ACTIVE = '1';
77
-
78
- return function cleanup() {
79
- process.stdout.write = origStdoutWrite;
80
- process.stderr.write = origStderrWrite;
81
- const footer = `\n[${new Date().toISOString()}] log ended\n`;
82
- try { fs.writeSync(logFd, footer); } catch { /* ignore */ }
83
- try { fs.closeSync(logFd); } catch { /* ignore */ }
84
- delete process.env.MA_AGENTS_LOG_ACTIVE;
85
- };
86
- }
87
-
88
- function showHelp() {
89
- console.log(`
90
- ${chalk.bold.cyan(NAME)} ${chalk.gray(`v${VERSION}`)}
91
-
92
- ${chalk.bold('Usage:')}
93
- ${chalk.cyan(`npx ${NAME}`)} Interactive wizard
94
- ${chalk.cyan(`npx ${NAME} install`)} Interactive install wizard
95
- ${chalk.cyan(`npx ${NAME} install`)} <skill> <agents...> Install directly
96
- ${chalk.cyan(`npx ${NAME} uninstall`)} <skill> <agents..> Uninstall a skill
97
- ${chalk.cyan(`npx ${NAME} uninstall --profile-artifacts`)} Remove ma-agents-owned profile content from all injection files
98
- ${chalk.cyan(`npx ${NAME} status`)} Show installed skills
99
- ${chalk.cyan(`npx ${NAME} list`)} List available skills
100
- ${chalk.cyan(`npx ${NAME} agents`)} List supported agents
101
- ${chalk.cyan(`npx ${NAME} create-skill`)} <name> Scaffold a new skill directory
102
- ${chalk.cyan(`npx ${NAME} validate-skill`)} <name> Validate a skill against the schema
103
- ${chalk.cyan(`npx ${NAME} set-mandatory`)} <name> [--off] Mark a skill as always-load (or remove)
104
- ${chalk.cyan(`npx ${NAME} customize-agent`)} <agent> Customize a BMAD agent persona and actions
105
- ${chalk.cyan(`npx ${NAME} create-agent`)} <name> Create a new specialized BMAD agent
106
- ${chalk.cyan(`npx ${NAME} reconfigure`)} Re-run the profile prompt and re-stamp artifacts
107
- ${chalk.cyan(`npx ${NAME} config layout`)} Reconfigure repository layout
108
- ${chalk.cyan(`npx ${NAME} config layout --show`)} Show current layout (read-only)
109
- ${chalk.cyan(`npx ${NAME} help`)} Show this help
110
-
111
- ${chalk.bold('Install options:')}
112
- ${chalk.cyan('--global')} Install to global/user-level paths (default: project-level)
113
- ${chalk.cyan('--path <dir>')} Custom installation directory
114
- ${chalk.cyan('--force')} Skip upgrade prompts, always overwrite
115
- ${chalk.cyan('--yes')} Skip all prompts, use defaults (for CI/CD)
116
- ${chalk.cyan('--agent <name>')} Target a specific agent (skip agent selection)
117
- ${chalk.cyan('--log')} Log all console output to install_<datetime>.log
118
-
119
- ${chalk.bold('Reconfigure options:')}
120
- ${chalk.cyan('--force-roomodes-overwrite')} Accept slug-stomp on user-edited ma-agents slugs
121
- ${chalk.gray('(reconfigure rejects --yes by design — it is interactive only)')}
122
-
123
- ${chalk.bold('Uninstall --profile-artifacts options:')}
124
- ${chalk.cyan('--yes')} Skip confirmation prompt (supported for CI decommissioning)
125
- ${chalk.gray('(asymmetry note: uninstall --profile-artifacts accepts --yes; reconfigure does not)')}
126
-
127
- ${chalk.bold('Notes:')}
128
- Divergent \`.cline/clinerules.md\` vs. \`.clinerules\` marker blocks require
129
- manual reconciliation \`--yes\` does not bypass this check.
130
-
131
- ${chalk.bold('Examples:')}
132
- npx ${NAME} install
133
- npx ${NAME} install code-review claude-code
134
- npx ${NAME} install code-review claude-code --force
135
- npx ${NAME} install --yes
136
- npx ${NAME} install --yes --agent claude-code
137
- npx ${NAME} install --yes --global
138
- npx ${NAME} uninstall code-review claude-code
139
- npx ${NAME} status
140
- npx ${NAME} status --global
141
- `);
142
- }
143
-
144
- function showSkills(args) {
145
- const mandatoryOnly = args && args.includes('--mandatory');
146
- let skills = listSkills();
147
- if (mandatoryOnly) {
148
- skills = skills.filter(s => s.always_load === true);
149
- console.log(chalk.bold('\n Mandatory Skills (always_load: true):\n'));
150
- } else {
151
- console.log(chalk.bold('\n Available Skills:\n'));
152
- }
153
- skills.forEach(skill => {
154
- console.log(chalk.cyan(` ${skill.id.padEnd(35)}`) + chalk.white(`${skill.name}`) + chalk.gray(` v${skill.version}`));
155
- console.log(chalk.gray(` ${''.padEnd(35)}${skill.description}\n`));
156
- });
157
- }
158
-
159
- function showAgents() {
160
- const agents = listAgents();
161
- console.log(chalk.bold('\n Supported Agents:\n'));
162
-
163
- const ideAgents = agents.filter(a => a.category !== 'bmad');
164
- const bmadAgents = agents.filter(a => a.category === 'bmad');
165
-
166
- console.log(chalk.bold.yellow(' AI Coding Assistants:'));
167
- ideAgents.forEach(agent => {
168
- console.log(chalk.cyan(` ${agent.id.padEnd(20)}`) + chalk.white(agent.name) + chalk.gray(` v${agent.version} - ${agent.description}`));
169
- });
170
-
171
- console.log(chalk.bold.yellow('\n BMAD Method Agents:'));
172
- bmadAgents.forEach(agent => {
173
- console.log(chalk.cyan(` ${agent.id.padEnd(20)}`) + chalk.white(agent.name) + chalk.gray(` v${agent.version} - ${agent.description}`));
174
- });
175
- console.log('');
176
- }
177
-
178
- function showStatus(args) {
179
- const globalFlag = args.includes('--global');
180
- const scope = globalFlag ? 'global' : 'project';
181
- const positional = args.filter(a => a !== '--global');
182
-
183
- const results = getStatus(positional, '', scope);
184
-
185
- if (results.length === 0) {
186
- console.log(chalk.gray(`\n No skills installed (${scope} scope)\n`));
187
- return;
188
- }
189
-
190
- console.log(chalk.bold(`\n Installed Skills:\n`));
191
-
192
- for (const entry of results) {
193
- console.log(chalk.cyan(` ${entry.agent.name}`) + chalk.gray(` (${entry.scope}: ${entry.installPath})`));
194
-
195
- const skillIds = Object.keys(entry.skills);
196
- for (const skillId of skillIds) {
197
- const info = entry.skills[skillId];
198
- const installed = new Date(info.installedAt).toLocaleDateString();
199
- const updated = info.updatedAt !== info.installedAt
200
- ? chalk.gray(` updated ${new Date(info.updatedAt).toLocaleDateString()}`)
201
- : '';
202
- console.log(
203
- chalk.white(` ${skillId.padEnd(35)}`) +
204
- chalk.green(`v${info.version}`) +
205
- chalk.gray(` installed ${installed}`) +
206
- updated
207
- );
208
- }
209
- console.log('');
210
- }
211
- }
212
-
213
- // --- Parse common flags from args ---
214
-
215
- function parseFlags(args) {
216
- const globalFlag = args.includes('--global');
217
- const forceFlag = args.includes('--force');
218
- const yesFlag = args.includes('--yes');
219
- let customPath = '';
220
- let agentFlag = '';
221
-
222
- let positional = [...args].filter(a =>
223
- a !== '--global' && a !== '--force' && a !== '--yes'
224
- );
225
-
226
- const pathIdx = positional.indexOf('--path');
227
- if (pathIdx !== -1) {
228
- customPath = positional[pathIdx + 1] || '';
229
- positional.splice(pathIdx, 2);
230
- }
231
-
232
- const agentIdx = positional.indexOf('--agent');
233
- if (agentIdx !== -1) {
234
- const agentName = positional[agentIdx + 1];
235
- if (!agentName || agentName.startsWith('--')) {
236
- console.error(chalk.red('Error: --agent requires an agent name'));
237
- console.error(chalk.gray(' Hint: Run "list" to see available agents'));
238
- process.exit(1);
239
- }
240
- agentFlag = agentName;
241
- positional.splice(agentIdx, 2);
242
- }
243
-
244
- return {
245
- globalFlag,
246
- forceFlag,
247
- yesFlag,
248
- agentFlag,
249
- customPath,
250
- scope: globalFlag ? 'global' : 'project',
251
- positional
252
- };
253
- }
254
-
255
- // --- Repository layout wizard ---
256
-
257
- async function collectLocalPath(concern) {
258
- while (true) {
259
- const { localPath } = await prompts({
260
- type: 'text',
261
- name: 'localPath',
262
- message: `Enter local path for ${concern}:`
263
- });
264
-
265
- if (!localPath || !localPath.trim()) {
266
- console.log(chalk.red(' Path cannot be empty. Please try again.'));
267
- continue;
268
- }
269
-
270
- const resolved = path.resolve(process.cwd(), localPath.trim());
271
-
272
- if (fs.existsSync(resolved)) {
273
- if (!fs.statSync(resolved).isDirectory()) {
274
- console.log(chalk.red(` "${resolved}" exists but is a file, not a directory. Please try again.`));
275
- continue;
276
- }
277
- } else {
278
- console.log(chalk.yellow(` Warning: "${resolved}" does not exist.`));
279
- const { confirmed } = await prompts({
280
- type: 'confirm',
281
- name: 'confirmed',
282
- message: 'Use this path anyway? (It must exist before agents run)',
283
- initial: false
284
- });
285
- if (!confirmed) continue;
286
- console.log(chalk.yellow(` Note: Path "${resolved}" must exist before agents run.`));
287
- }
288
-
289
- if (resolved.startsWith(process.cwd())) {
290
- console.log(chalk.yellow(` Warning: Path is inside the current repository. Nested repos may cause git confusion.`));
291
- }
292
-
293
- return { mode: 'local', path: resolved };
294
- }
295
- }
296
-
297
- async function collectRemotePath(concern) {
298
- while (true) {
299
- // Collect git URL
300
- let gitUrl;
301
- while (true) {
302
- const { url } = await prompts({
303
- type: 'text',
304
- name: 'url',
305
- message: `Enter git URL for ${concern}:`
306
- });
307
- if (!url || !url.trim()) {
308
- console.log(chalk.red(' Git URL cannot be empty. Please try again.'));
309
- continue;
310
- }
311
- gitUrl = url.trim();
312
- break;
313
- }
314
-
315
- // Collect destination path
316
- let destPath;
317
- while (true) {
318
- const { dest } = await prompts({
319
- type: 'text',
320
- name: 'dest',
321
- message: `Enter local destination path for clone:`
322
- });
323
- if (!dest || !dest.trim()) {
324
- console.log(chalk.red(' Destination path cannot be empty. Please try again.'));
325
- continue;
326
- }
327
- destPath = path.resolve(process.cwd(), dest.trim());
328
- break;
329
- }
330
-
331
- // Check destination
332
- if (fs.existsSync(destPath)) {
333
- if (!fs.statSync(destPath).isDirectory()) {
334
- console.log(chalk.red(` "${destPath}" exists but is a file, not a directory. Please try again.`));
335
- continue;
336
- }
337
- // Existing directory — show summary and confirm
338
- const files = fs.readdirSync(destPath);
339
- const isGitRepo = fs.existsSync(path.join(destPath, '.git'));
340
- console.log(chalk.blue(` Directory exists: ${files.length} items${isGitRepo ? ' (git repo)' : ''}`));
341
- const { confirmed } = await prompts({
342
- type: 'confirm',
343
- name: 'confirmed',
344
- message: 'Use this existing directory?',
345
- initial: true
346
- });
347
- if (!confirmed) continue;
348
- } else {
349
- // Clone
350
- const existedBefore = fs.existsSync(destPath);
351
- try {
352
- console.log(chalk.cyan(` Cloning ${gitUrl}...`));
353
- execFileSync('git', ['clone', gitUrl, destPath], {
354
- timeout: 120000,
355
- env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
356
- stdio: 'inherit'
357
- });
358
- } catch (err) {
359
- console.log(chalk.red(` Clone failed: ${err.message}`));
360
- if (!existedBefore && fs.existsSync(destPath)) {
361
- fs.rmSync(destPath, { recursive: true, force: true });
362
- }
363
- const { retry } = await prompts({
364
- type: 'confirm',
365
- name: 'retry',
366
- message: 'Retry?',
367
- initial: true
368
- });
369
- if (retry) continue;
370
- console.log(chalk.yellow(` Falling back to current repository for ${concern}`));
371
- return { mode: 'same', path: '.' };
372
- }
373
- }
374
-
375
- if (destPath.startsWith(process.cwd())) {
376
- console.log(chalk.yellow(` Warning: Destination is inside the current repository. Nested repos may cause git confusion.`));
377
- }
378
-
379
- return { mode: 'remote', path: destPath, gitUrl };
380
- }
381
- }
382
-
383
- async function collectJiraConfig() {
384
- // Collect Jira server URL
385
- let jiraUrl;
386
- while (true) {
387
- const { url } = await prompts({
388
- type: 'text',
389
- name: 'url',
390
- message: 'Jira server URL (e.g. https://mycompany.atlassian.net):'
391
- });
392
- if (!url || !url.trim()) {
393
- console.log(chalk.red(' Jira server URL cannot be empty. Please try again.'));
394
- continue;
395
- }
396
- jiraUrl = url.trim();
397
- break;
398
- }
399
-
400
- // Collect Jira project key
401
- let jiraProjectKey;
402
- while (true) {
403
- const { key } = await prompts({
404
- type: 'text',
405
- name: 'key',
406
- message: 'Jira project key (e.g. MYPROJ):'
407
- });
408
- if (!key || !key.trim()) {
409
- console.log(chalk.red(' Jira project key cannot be empty. Please try again.'));
410
- continue;
411
- }
412
- if (!/^[A-Z][A-Z0-9]+$/.test(key.trim())) {
413
- console.log(chalk.red(' Jira project key must be uppercase alphanumeric (e.g. MYPROJ). Please try again.'));
414
- continue;
415
- }
416
- jiraProjectKey = key.trim();
417
- break;
418
- }
419
-
420
- return { mode: 'jira', jiraUrl, jiraProjectKey };
421
- }
422
-
423
- function normalizePath(p) {
424
- return p.replace(/\\/g, '/');
425
- }
426
-
427
- function yamlEscapeValue(v) {
428
- if (!v) return '""';
429
- const s = String(v);
430
- if (/[:"#\[\]{}&*!|>%@`]/.test(s) || s !== s.trim() || s === '') {
431
- return '"' + s.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
432
- }
433
- return '"' + s + '"';
434
- }
435
-
436
- function toPortablePath(absolutePath, projectRoot) {
437
- if (!absolutePath || absolutePath === '.') return { portable: '.', isAbsolute: false };
438
-
439
- const rel = normalizePath(path.relative(projectRoot, absolutePath));
440
-
441
- // Same directory: path.relative returns '' — treat as '.'
442
- if (rel === '') return { portable: '.', isAbsolute: false };
443
-
444
- // Cross-drive on Windows: path.relative returns the absolute target unchanged
445
- if (path.isAbsolute(rel) || /^[A-Za-z]:/.test(rel)) {
446
- return { portable: normalizePath(absolutePath), isAbsolute: true };
447
- }
448
-
449
- // Too many levels up — treat as non-portable
450
- const upLevels = (rel.match(/\.\./g) || []).length;
451
- if (upLevels > 3) {
452
- return { portable: normalizePath(absolutePath), isAbsolute: true };
453
- }
454
-
455
- return { portable: rel, isAbsolute: false };
456
- }
457
-
458
- function writeConfigField(content, fieldName, value) {
459
- const regex = new RegExp(`^${fieldName}:.*$`, 'm');
460
- const newLine = `${fieldName}: ${yamlEscapeValue(value)}`;
461
- if (regex.test(content)) {
462
- return content.replace(regex, newLine);
463
- }
464
- return content.trimEnd() + '\n' + newLine + '\n';
465
- }
466
-
467
- function writeRepoLayoutConfig(layout) {
468
- const configPath = path.join(process.cwd(), '_bmad', 'bmm', 'config.yaml');
469
- try {
470
- if (!fs.existsSync(configPath)) {
471
- // Create an empty file so writeConfigField can append to it
472
- fs.mkdirSync(path.join(process.cwd(), '_bmad', 'bmm'), { recursive: true });
473
- fs.writeFileSync(configPath, '', 'utf-8');
474
- }
475
- let content = fs.readFileSync(configPath, 'utf-8');
476
- const projectRoot = process.cwd();
477
- const kbPortable = toPortablePath(layout.knowledgebase.path, projectRoot);
478
- const kbPath = kbPortable.portable;
479
- content = writeConfigField(content, 'knowledgebase_path', kbPath);
480
-
481
- const spMode = layout.sprintManagement.mode;
482
- if (spMode === 'jira') {
483
- // Jira backend: write sprint_backend + Jira config; no sprint_management_path
484
- content = writeConfigField(content, 'sprint_backend', 'jira');
485
- content = writeConfigField(content, 'jira_url', layout.sprintManagement.jiraUrl);
486
- content = writeConfigField(content, 'jira_project_key', layout.sprintManagement.jiraProjectKey);
487
- // Derive artifact paths from kb only
488
- const planningArtifacts = kbPath === '.' ? '_bmad-output/planning-artifacts' : `${kbPath}/_bmad-output/planning-artifacts`;
489
- const implArtifacts = '_bmad-output/implementation-artifacts';
490
- content = writeConfigField(content, 'planning_artifacts', planningArtifacts);
491
- content = writeConfigField(content, 'implementation_artifacts', implArtifacts);
492
- fs.writeFileSync(configPath, content, 'utf-8');
493
- console.log(chalk.gray(` Config: knowledgebase_path="${kbPath}", sprint_backend=jira, jira_url="${layout.sprintManagement.jiraUrl}", jira_project_key="${layout.sprintManagement.jiraProjectKey}"`));
494
- } else {
495
- // File-system backend
496
- const spPortable = toPortablePath(layout.sprintManagement.path, projectRoot);
497
- const spPath = spPortable.portable;
498
- content = writeConfigField(content, 'sprint_backend', 'file-system');
499
- content = writeConfigField(content, 'sprint_management_path', spPath);
500
- // Derive workflow-consumable artifact paths from layout paths (relative when base is relative)
501
- const planningArtifacts = kbPath === '.' ? '_bmad-output/planning-artifacts' : `${kbPath}/_bmad-output/planning-artifacts`;
502
- const implArtifacts = spPath === '.' ? '_bmad-output/implementation-artifacts' : `${spPath}/_bmad-output/implementation-artifacts`;
503
- content = writeConfigField(content, 'planning_artifacts', planningArtifacts);
504
- content = writeConfigField(content, 'implementation_artifacts', implArtifacts);
505
- fs.writeFileSync(configPath, content, 'utf-8');
506
- console.log(chalk.gray(` Config: knowledgebase_path="${kbPath}", sprint_backend=file-system, sprint_management_path="${spPath}"`));
507
- }
508
- } catch (e) {
509
- console.log(chalk.red(` Cannot write config.yaml: ${e.message}`));
510
- }
511
- }
512
-
513
- function writeProjectLayoutYaml(layout) {
514
- const layoutPath = path.join(process.cwd(), '_bmad-output', 'project-layout.yaml');
515
- // Only skip writing when BOTH concerns are truly same-repo (jira requires config recording)
516
- const bothSame = layout.knowledgebase.mode === 'same' && layout.sprintManagement.mode === 'same';
517
-
518
- if (bothSame) {
519
- // Single-repo mode: delete stale file if exists
520
- if (fs.existsSync(layoutPath)) {
521
- fs.unlinkSync(layoutPath);
522
- console.log(chalk.blue(' Removed stale project-layout.yaml (now in single-repo mode)'));
523
- }
524
- return;
525
- }
526
-
527
- // Multi-repo or Jira mode: generate project-layout.yaml
528
- fs.mkdirSync(path.join(process.cwd(), '_bmad-output'), { recursive: true });
529
-
530
- const date = new Date().toISOString().slice(0, 10);
531
- let content = `# Generated by ma-agents do not edit manually\n`;
532
- content += `# Tells agents where to find planning and sprint data\n`;
533
- content += `generated: "${date}"\n`;
534
-
535
- const projectRoot = process.cwd();
536
-
537
- // Knowledgebase section
538
- const kbPortable = toPortablePath(layout.knowledgebase.path, projectRoot);
539
- content += `knowledgebase:\n`;
540
- content += ` mode: ${layout.knowledgebase.mode}\n`;
541
- content += ` path: ${yamlEscapeValue(kbPortable.portable)}\n`;
542
- if (kbPortable.isAbsolute) {
543
- content += ` # PORTABILITY: absolute path — other developers may need to reconfigure\n`;
544
- }
545
- if (layout.knowledgebase.mode === 'remote' && layout.knowledgebase.gitUrl) {
546
- content += ` gitUrl: ${yamlEscapeValue(layout.knowledgebase.gitUrl)}\n`;
547
- }
548
-
549
- // Sprint management section
550
- content += `sprint_management:\n`;
551
- content += ` mode: ${layout.sprintManagement.mode}\n`;
552
- if (layout.sprintManagement.mode === 'jira') {
553
- content += ` jira_url: ${yamlEscapeValue(layout.sprintManagement.jiraUrl)}\n`;
554
- content += ` jira_project_key: ${yamlEscapeValue(layout.sprintManagement.jiraProjectKey)}\n`;
555
- } else {
556
- const spPortable = toPortablePath(layout.sprintManagement.path, projectRoot);
557
- content += ` path: ${yamlEscapeValue(spPortable.portable)}\n`;
558
- if (spPortable.isAbsolute) {
559
- content += ` # PORTABILITY: absolute path other developers may need to reconfigure\n`;
560
- }
561
- if (layout.sprintManagement.mode === 'remote' && layout.sprintManagement.gitUrl) {
562
- content += ` gitUrl: ${yamlEscapeValue(layout.sprintManagement.gitUrl)}\n`;
563
- }
564
- }
565
-
566
- fs.writeFileSync(layoutPath, content, 'utf-8');
567
- console.log(chalk.gray(` Created _bmad-output/project-layout.yaml`));
568
- }
569
-
570
- function resolveStoredPath(storedPath, projectRoot) {
571
- if (!storedPath) return '.';
572
- if (storedPath === '.') return storedPath;
573
- // If already absolute, use as-is (backward compat)
574
- if (path.isAbsolute(storedPath) || /^[A-Za-z]:/.test(storedPath)) return storedPath;
575
- // Relative path — resolve from project root
576
- return normalizePath(path.resolve(projectRoot, storedPath));
577
- }
578
-
579
- function readExistingLayout() {
580
- const projectRoot = process.cwd();
581
- // Try project-layout.yaml first (authoritative source written by Story 16.2)
582
- const layoutPath = path.join(projectRoot, '_bmad-output', 'project-layout.yaml');
583
- try {
584
- if (fs.existsSync(layoutPath)) {
585
- const content = fs.readFileSync(layoutPath, 'utf-8');
586
- const layout = { knowledgebase: null, sprintManagement: null };
587
-
588
- // Parse each concern section from the simple YAML
589
- for (const [section, key] of [['knowledgebase', 'knowledgebase'], ['sprint_management', 'sprintManagement']]) {
590
- const sectionMatch = content.match(new RegExp(`^${section}:\\s*$`, 'm'));
591
- if (!sectionMatch) continue;
592
-
593
- const afterSection = content.slice(sectionMatch.index + sectionMatch[0].length);
594
- const modeMatch = afterSection.match(/^\s+mode:\s*(\S+)/m);
595
- const pathMatch = afterSection.match(/^\s+path:\s*"?([^"\n]+)"?/m);
596
- const gitUrlMatch = afterSection.match(/^\s+gitUrl:\s*"?([^"\n]+)"?/m);
597
- const jiraUrlMatch = afterSection.match(/^\s+jira_url:\s*"?([^"\n]+)"?/m);
598
- const jiraProjectKeyMatch = afterSection.match(/^\s+jira_project_key:\s*"?([^"\n]+)"?/m);
599
-
600
- if (modeMatch) {
601
- const mode = modeMatch[1];
602
- if (mode === 'jira') {
603
- const jiraUrl = jiraUrlMatch ? jiraUrlMatch[1].replace(/^"(.*)"$/, '$1') : '';
604
- const jiraProjectKey = jiraProjectKeyMatch ? jiraProjectKeyMatch[1].replace(/^"(.*)"$/, '$1') : '';
605
- layout[key] = { mode: 'jira', jiraUrl, jiraProjectKey };
606
- } else if (pathMatch) {
607
- const resolvedPath = resolveStoredPath(pathMatch[1], projectRoot);
608
- const entry = { mode, path: resolvedPath };
609
- if (mode === 'remote' && gitUrlMatch) {
610
- entry.gitUrl = gitUrlMatch[1];
611
- }
612
- layout[key] = entry;
613
- }
614
- }
615
- }
616
-
617
- // Only return if we parsed at least one valid concern
618
- if (layout.knowledgebase || layout.sprintManagement) {
619
- // Fill in defaults for any missing section
620
- if (!layout.knowledgebase) layout.knowledgebase = { mode: 'same', path: '.' };
621
- if (!layout.sprintManagement) layout.sprintManagement = { mode: 'same', path: '.' };
622
- return layout;
623
- }
624
- }
625
- } catch (e) {
626
- console.log(chalk.yellow(` Warning: could not read project-layout.yaml: ${e.message}`));
627
- }
628
-
629
- // Fallback: check config.yaml for path fields
630
- const configPath = path.join(projectRoot, '_bmad', 'bmm', 'config.yaml');
631
- try {
632
- if (fs.existsSync(configPath)) {
633
- const content = fs.readFileSync(configPath, 'utf-8');
634
- const kbMatch = content.match(/^knowledgebase_path:\s*"?([^"\n]+)"?/m);
635
- const spMatch = content.match(/^sprint_management_path:\s*"?([^"\n]+)"?/m);
636
-
637
- const kbPath = kbMatch ? resolveStoredPath(kbMatch[1], projectRoot) : null;
638
- const spPath = spMatch ? resolveStoredPath(spMatch[1], projectRoot) : null;
639
-
640
- // Only return if at least one non-default path exists
641
- if ((kbPath && kbPath !== '.') || (spPath && spPath !== '.')) {
642
- return {
643
- knowledgebase: kbPath && kbPath !== '.'
644
- ? { mode: 'local', path: kbPath }
645
- : { mode: 'same', path: '.' },
646
- sprintManagement: spPath && spPath !== '.'
647
- ? { mode: 'local', path: spPath }
648
- : { mode: 'same', path: '.' },
649
- };
650
- }
651
- }
652
- } catch (e) {
653
- console.log(chalk.yellow(` Warning: could not read config.yaml layout: ${e.message}`));
654
- }
655
-
656
- return null;
657
- }
658
-
659
- function ciCloneIfNeeded(destPath, gitUrl, clonedRepos) {
660
- // Deduplicate: same URL + path already cloned
661
- const key = `${gitUrl}::${destPath}`;
662
- if (clonedRepos.has(key)) return;
663
-
664
- if (fs.existsSync(destPath)) {
665
- if (fs.existsSync(path.join(destPath, '.git'))) {
666
- console.log(chalk.gray(` Using existing clone at ${destPath}`));
667
- clonedRepos.set(key, true);
668
- return;
669
- }
670
- throw new Error(`Destination exists but is not a git repo — remove it or use a different path: ${destPath}`);
671
- }
672
-
673
- try {
674
- console.log(chalk.cyan(` Cloning ${gitUrl} ${destPath}`));
675
- execFileSync('git', ['clone', '--depth', '1', gitUrl, destPath], { stdio: 'pipe' });
676
- clonedRepos.set(key, true);
677
- } catch (e) {
678
- throw new Error(`Failed to clone ${gitUrl}: ${e.message}`);
679
- }
680
- }
681
-
682
- async function collectRepoLayout(flags, existingLayout = null) {
683
- // CI/CD mode: env vars > existing layout > defaults
684
- if (flags.yes) {
685
- const kbPath = process.env.MA_KNOWLEDGEBASE_PATH;
686
- const sprintPath = process.env.MA_SPRINT_PATH;
687
- const kbGitUrl = process.env.MA_KNOWLEDGEBASE_GIT_URL;
688
- const sprintGitUrl = process.env.MA_SPRINT_GIT_URL;
689
-
690
- // Validate: git URL requires corresponding path
691
- if (kbGitUrl && !kbPath) {
692
- throw new Error('MA_KNOWLEDGEBASE_GIT_URL requires MA_KNOWLEDGEBASE_PATH to be set (clone destination)');
693
- }
694
- if (sprintGitUrl && !sprintPath) {
695
- throw new Error('MA_SPRINT_GIT_URL requires MA_SPRINT_PATH to be set (clone destination)');
696
- }
697
-
698
- // Env vars take precedence
699
- if (kbPath || sprintPath || kbGitUrl || sprintGitUrl) {
700
- const result = { knowledgebase: null, sprintManagement: null };
701
-
702
- // Track cloned repos to avoid duplicate clones (AC #8)
703
- const clonedRepos = new Map();
704
-
705
- for (const [concern, envPath, envGitUrl] of [
706
- ['knowledgebase', kbPath, kbGitUrl],
707
- ['sprintManagement', sprintPath, sprintGitUrl],
708
- ]) {
709
- if (envGitUrl && envPath) {
710
- const resolvedPath = path.resolve(envPath);
711
- // Clone if needed (CI-mode: fail loudly, no fallback)
712
- ciCloneIfNeeded(resolvedPath, envGitUrl, clonedRepos);
713
- result[concern] = { mode: 'remote', path: resolvedPath, gitUrl: envGitUrl };
714
- } else if (envPath) {
715
- result[concern] = { mode: 'local', path: path.resolve(envPath) };
716
- } else {
717
- result[concern] = existingLayout ? existingLayout[concern] : { mode: 'same', path: '.' };
718
- }
719
- }
720
-
721
- return result;
722
- }
723
- // No env vars: preserve existing layout if available
724
- if (existingLayout) {
725
- return existingLayout;
726
- }
727
- // No env vars, no existing layout: default to single-repo
728
- return {
729
- knowledgebase: { mode: 'same', path: '.' },
730
- sprintManagement: { mode: 'same', path: '.' },
731
- };
732
- }
733
-
734
- const layout = { knowledgebase: null, sprintManagement: null };
735
- const labels = { knowledgebase: 'knowledgebase', sprintManagement: 'sprint management' };
736
-
737
- for (const concern of ['knowledgebase', 'sprintManagement']) {
738
- const existingMode = existingLayout && existingLayout[concern] ? existingLayout[concern].mode : null;
739
- const modeChoices = [
740
- { title: 'Current repository (default)', value: 'same' },
741
- { title: 'Local path', value: 'local' },
742
- { title: 'Remote git repository', value: 'remote' },
743
- ...(concern === 'sprintManagement' ? [{ title: 'Jira', value: 'jira' }] : []),
744
- ];
745
- // Pre-select existing mode if available
746
- const initialIndex = existingMode ? modeChoices.findIndex(c => c.value === existingMode) : 0;
747
-
748
- const { mode } = await prompts({
749
- type: 'select',
750
- name: 'mode',
751
- message: `Where is your ${labels[concern]} managed?`,
752
- choices: modeChoices,
753
- initial: initialIndex >= 0 ? initialIndex : 0
754
- });
755
-
756
- if (!mode) process.exit(0);
757
-
758
- if (mode === 'same') {
759
- layout[concern] = { mode: 'same', path: '.' };
760
- } else if (mode === 'local') {
761
- layout[concern] = await collectLocalPath(labels[concern]);
762
- } else if (mode === 'remote') {
763
- layout[concern] = await collectRemotePath(labels[concern]);
764
- } else if (mode === 'jira') {
765
- layout[concern] = await collectJiraConfig();
766
- }
767
- }
768
-
769
- // Check if both concerns point to same external path
770
- if (layout.knowledgebase.mode !== 'same' && layout.sprintManagement.mode !== 'same'
771
- && layout.knowledgebase.path === layout.sprintManagement.path) {
772
- console.log(chalk.cyan(' Both concerns point to same external repository'));
773
- }
774
-
775
- return layout;
776
- }
777
-
778
- // --- Install wizard ---
779
-
780
- async function installWizard(preselectedSkill, preselectedAgents, customPath, forceFlag, yesFlag = false, cliScope) {
781
- const skills = listSkills();
782
- const agents = listAgents();
783
-
784
- let selectedSkillIds = preselectedSkill ? [preselectedSkill] : [];
785
- let selectedAgentIds = preselectedAgents || [];
786
- let installScope = cliScope || 'project';
787
- let installPath = customPath || '';
788
-
789
- const existingStatus = getStatus([], '', 'project');
790
- let isUpdate = false;
791
-
792
- // Step 0: Check for existing installation ONLY in interactive mode (no preselected skill)
793
- if (!preselectedSkill && !customPath && existingStatus.length > 0) {
794
- if (yesFlag) {
795
- // Default: clean reinstall (avoids isUpdate path which re-triggers skill selection prompts)
796
- for (const entry of existingStatus) {
797
- for (const skillId of Object.keys(entry.skills)) {
798
- await uninstallSkill(skillId, [entry.agent.id], '', 'project');
799
- }
800
- }
801
- console.log(chalk.gray(' Clean slate prepared.'));
802
- } else {
803
- console.log(chalk.cyan('\n Existing installation detected in project.'));
804
-
805
- const { action } = await prompts({
806
- type: 'select',
807
- name: 'action',
808
- message: 'What would you like to do?',
809
- choices: [
810
- { title: 'Update (add/remove skills)', value: 'update' },
811
- { title: 'Clean reinstall (remove all first)', value: 'reinstall' },
812
- { title: 'Uninstall all skills', value: 'uninstall' },
813
- { title: 'Cancel', value: 'cancel' }
814
- ]
815
- });
816
-
817
- if (!action || action === 'cancel') process.exit(0);
818
-
819
- if (action === 'uninstall') {
820
- const { confirmed } = await prompts({
821
- type: 'confirm',
822
- name: 'confirmed',
823
- message: 'This will remove all ma-agents skills from this project. Are you sure?',
824
- initial: false
825
- });
826
- if (!confirmed) process.exit(0);
827
-
828
- for (const entry of existingStatus) {
829
- for (const skillId of Object.keys(entry.skills)) {
830
- await uninstallSkill(skillId, [entry.agent.id], '', 'project');
831
- }
832
- }
833
- console.log(chalk.bold.green('\n All skills successfully removed!\n'));
834
- return;
835
- }
836
-
837
- if (action === 'reinstall') {
838
- for (const entry of existingStatus) {
839
- for (const skillId of Object.keys(entry.skills)) {
840
- await uninstallSkill(skillId, [entry.agent.id], '', 'project');
841
- }
842
- }
843
- console.log(chalk.gray(' Clean slate prepared.'));
844
- }
845
-
846
- if (action === 'update') {
847
- isUpdate = true;
848
- // Pre-populate selections from existing status
849
- const existingSkillIds = new Set();
850
- const existingAgentIds = new Set();
851
- existingStatus.forEach(entry => {
852
- existingAgentIds.add(entry.agent.id);
853
- Object.keys(entry.skills).forEach(id => existingSkillIds.add(id));
854
- });
855
- selectedSkillIds = Array.from(existingSkillIds);
856
- selectedAgentIds = Array.from(existingAgentIds);
857
- }
858
- }
859
- }
860
-
861
- // Step 1: Select skills
862
- if (yesFlag || selectedSkillIds.length === 0 || isUpdate) {
863
- if (yesFlag) {
864
- selectedSkillIds = skills.map(s => s.id);
865
- } else {
866
- const { selectionType } = await prompts({
867
- type: 'select',
868
- name: 'selectionType',
869
- message: 'Would you like to install all available skills or choose specific ones?',
870
- choices: [
871
- { title: 'Install all available skills', value: 'all' },
872
- { title: 'Choose which skills to install', value: 'custom' }
873
- ]
874
- });
875
-
876
- if (!selectionType) process.exit(0);
877
-
878
- if (selectionType === 'all') {
879
- selectedSkillIds = skills.map(s => s.id);
880
- } else {
881
- const { skills: chosen } = await prompts({
882
- type: 'multiselect',
883
- name: 'skills',
884
- message: 'Select the skills you want to have installed:',
885
- choices: skills.map(s => ({
886
- title: chalk.white(s.name) + chalk.gray(` v${s.version} - ${s.description}`),
887
- value: s.id,
888
- selected: selectedSkillIds.includes(s.id)
889
- })),
890
- instructions: chalk.gray(' Use space to select, enter to confirm'),
891
- min: 1
892
- });
893
-
894
- if (!chosen) process.exit(0);
895
- selectedSkillIds = chosen;
896
- }
897
- }
898
- }
899
-
900
- // Step 2: Select agents
901
- if (yesFlag || selectedAgentIds.length === 0 || isUpdate) {
902
- const ideAgents = agents.filter(a => a.category !== 'bmad');
903
- const bmadAgents = agents.filter(a => a.category === 'bmad');
904
-
905
- if (yesFlag) {
906
- // Bug B1 fix: when --agent flag is present (preselectedAgents already
907
- // populated selectedAgentIds), do NOT overwrite with all agents.
908
- // Only fall back to all agents when no agent was pre-selected.
909
- if (selectedAgentIds.length === 0) {
910
- selectedAgentIds = [...ideAgents.map(a => a.id), ...bmadAgents.map(a => a.id)];
911
- }
912
- if (selectedAgentIds.length === 0) {
913
- console.error(chalk.red('Error: No agents detected'));
914
- console.error(chalk.gray(' Hint: Ensure at least one supported IDE is present'));
915
- process.exit(1);
916
- }
917
- } else {
918
- // 2.1 Coding Assistants
919
- const { ideChosen } = await prompts({
920
- type: 'multiselect',
921
- name: 'ideChosen',
922
- message: 'Select AI Coding Assistants:',
923
- choices: ideAgents.map(a => ({
924
- title: chalk.white(a.name) + chalk.gray(` v${a.version} - ${a.description}`),
925
- value: a.id,
926
- selected: selectedAgentIds.includes(a.id)
927
- })),
928
- instructions: chalk.gray(' Use space to select, enter to confirm'),
929
- });
930
-
931
- if (ideChosen === undefined) process.exit(0);
932
-
933
- // 2.2 BMAD Method Agents
934
- const { bmadChosen } = await prompts({
935
- type: 'multiselect',
936
- name: 'bmadChosen',
937
- message: 'Select BMAD Method Agents:',
938
- choices: bmadAgents.map(a => ({
939
- title: chalk.white(a.name) + chalk.gray(` v${a.version} - ${a.description}`),
940
- value: a.id,
941
- selected: selectedAgentIds.includes(a.id)
942
- })),
943
- instructions: chalk.gray(' Use space to select, enter to confirm'),
944
- });
945
-
946
- if (bmadChosen === undefined) process.exit(0);
947
-
948
- selectedAgentIds = [...ideChosen, ...bmadChosen];
949
-
950
- if (selectedAgentIds.length === 0) {
951
- console.log(chalk.yellow('No agents selected. Please select at least one agent to install skills.'));
952
- process.exit(1);
953
- }
954
- }
955
- }
956
-
957
- // Step 2.4: Profile resolution (Story 21.1, ACs #7–#9)
958
- // Must run AFTER agent selection and BEFORE repo layout, so downstream stories
959
- // can gate layout-related guidance on profile. setProfile() is called BEFORE
960
- // any agent install runs — guaranteeing persistence even if a later step fails.
961
- // Profile lives at the project root (cwd), NOT the custom skills-install path.
962
- const projectRootForProfile = process.cwd();
963
- const persistedProfile = getProfile(projectRootForProfile);
964
- let resolvedProfile = resolveProfile({
965
- persisted: persistedProfile,
966
- yesMode: yesFlag
967
- });
968
- let profileSource;
969
- if (persistedProfile) profileSource = '.ma-agents.json';
970
- else if (resolvedProfile === 'standard' && yesFlag) profileSource = '--yes default';
971
-
972
- if (resolvedProfile === null) {
973
- const { chosenProfile } = await prompts({
974
- type: 'select',
975
- name: 'chosenProfile',
976
- message: 'Is this an on-prem / air-gapped install using a local LLM (e.g. Nemotron)?',
977
- choices: [
978
- { title: 'Yes — apply local-LLM guardrails (recommended for non-Claude models)', value: 'on-prem' },
979
- { title: 'No — standard install (Claude on web, Anthropic API, etc.)', value: 'standard' }
980
- ],
981
- initial: 1
982
- });
983
- if (!chosenProfile) process.exit(0);
984
- resolvedProfile = chosenProfile;
985
- profileSource = 'interactive prompt';
986
- }
987
-
988
- console.log(chalk.cyan(`Using profile: ${resolvedProfile} (from ${profileSource})`));
989
-
990
- // Persist BEFORE any agent install step (AC #9). setProfile bootstraps the
991
- // manifest via ensureManifest when absent.
992
- setProfile(projectRootForProfile, resolvedProfile);
993
-
994
- // Step 2.5: Repository layout (preserve existing config on update)
995
- const existingLayout = isUpdate ? readExistingLayout() : null;
996
- const repoLayout = await collectRepoLayout({ yes: yesFlag }, existingLayout);
997
-
998
- // Step 3: Scope (Skip if update, yesFlag, CLI --global flag, or path already set)
999
- if (!isUpdate && !installPath && !yesFlag && !cliScope) {
1000
- const { pathChoice } = await prompts({
1001
- type: 'select',
1002
- name: 'pathChoice',
1003
- message: 'Installation scope:',
1004
- choices: [
1005
- { title: 'Project level (current directory)', value: 'project' },
1006
- { title: 'Global (user-level settings)', value: 'global' },
1007
- { title: 'Custom path...', value: 'custom' }
1008
- ]
1009
- });
1010
-
1011
- if (pathChoice === 'global') {
1012
- installScope = 'global';
1013
- } else if (pathChoice === 'custom') {
1014
- const { customDir } = await prompts({
1015
- type: 'text',
1016
- name: 'customDir',
1017
- message: 'Enter installation directory:',
1018
- initial: './skills'
1019
- });
1020
- installPath = customDir || '';
1021
- }
1022
- }
1023
-
1024
- // Step 3.4: Filter out BMAD agents for global scope (they require project-level install)
1025
- if (installScope === 'global') {
1026
- const bmadAgentIds = selectedAgentIds.filter(id => {
1027
- const agent = agents.find(a => a.id === id);
1028
- return agent && agent.category === 'bmad';
1029
- });
1030
- if (bmadAgentIds.length > 0) {
1031
- console.log(chalk.yellow(`\n Warning: BMAD agents require project-level installation and will be skipped for global scope:`));
1032
- console.log(chalk.yellow(` ${bmadAgentIds.join(', ')}`));
1033
- console.log(chalk.gray(` Run again without --global to install BMAD agents into the current project.`));
1034
- selectedAgentIds = selectedAgentIds.filter(id => !bmadAgentIds.includes(id));
1035
- }
1036
- }
1037
-
1038
- // Step 3.5: BMAD-METHOD Integration
1039
- if (installScope === 'project') {
1040
- const bmadToolsFilter = agents.filter(a => a.category === 'ide').map(a => a.id);
1041
-
1042
- if (yesFlag) {
1043
- // Warn about IDE agents not supported for BMAD customizations
1044
- const ideAgentIds = agents.filter(a => a.category !== 'bmad').map(a => a.id);
1045
- const unsupported = selectedAgentIds.filter(id => ideAgentIds.includes(id) && !bmadToolsFilter.includes(id));
1046
- unsupported.forEach(id => {
1047
- console.log(chalk.yellow(` Warning: Agent '${id}' is not supported for BMAD customizations`));
1048
- });
1049
- }
1050
-
1051
- const bmadInstalled = bmad.isBmadInstalled();
1052
- const bmadTools = selectedAgentIds.filter(id => bmadToolsFilter.includes(id)).map(id => getBmadPlatformCode(id));
1053
- // Story 22.6 — ma-agents customizations are now packaged as a BMAD plugin
1054
- // and installed by bmad-method itself via --custom-source. The separate
1055
- // `applyCustomizations()` call has been removed; installBmad()/updateBmad()
1056
- // stage the plugin and invoke the installer in one pass.
1057
- // v6.6.0: --tools none is rejected for fresh installs; skip BMAD entirely when no IDE tools selected.
1058
- if (bmadTools.length > 0) {
1059
- if (!bmadInstalled) {
1060
- if (yesFlag) {
1061
- console.log(chalk.cyan('\n Installing BMAD-METHOD...'));
1062
- const success = await bmad.installBmad(['bmm'], bmadTools);
1063
- if (success) {
1064
- console.log(chalk.green(' BMAD-METHOD installed successfully!'));
1065
- }
1066
- } else {
1067
- const { installBmad } = await prompts({
1068
- type: 'confirm',
1069
- name: 'installBmad',
1070
- message: 'BMAD-METHOD not detected. Would you like to install it?',
1071
- initial: true
1072
- });
1073
-
1074
- if (installBmad) {
1075
- console.log(chalk.cyan('\n Installing BMAD-METHOD...'));
1076
- const success = await bmad.installBmad(['bmm'], bmadTools);
1077
- if (success) {
1078
- console.log(chalk.green(' BMAD-METHOD installed successfully!'));
1079
- }
1080
- }
1081
- }
1082
- } else {
1083
- if (yesFlag) {
1084
- console.log(chalk.cyan('\n Updating BMAD-METHOD...'));
1085
- const success = await bmad.updateBmad(['bmm'], bmadTools);
1086
- if (success) {
1087
- console.log(chalk.green(' BMAD-METHOD updated successfully!'));
1088
- }
1089
- } else {
1090
- const { updateBmad } = await prompts({
1091
- type: 'confirm',
1092
- name: 'updateBmad',
1093
- message: 'BMAD-METHOD installation detected. Would you like to update it?',
1094
- initial: true
1095
- });
1096
-
1097
- if (updateBmad) {
1098
- console.log(chalk.cyan('\n Updating BMAD-METHOD...'));
1099
- const success = await bmad.updateBmad(['bmm'], bmadTools);
1100
- if (success) {
1101
- console.log(chalk.green(' BMAD-METHOD updated successfully!'));
1102
- }
1103
- }
1104
- }
1105
- }
1106
- }
1107
- }
1108
-
1109
- // Step 3.6: Write repo layout config (after BMAD install creates config.yaml)
1110
- if (installScope === 'project') {
1111
- writeRepoLayoutConfig(repoLayout);
1112
- writeProjectLayoutYaml(repoLayout);
1113
- }
1114
-
1115
- // Step 4: Confirm
1116
- console.log('');
1117
- console.log(chalk.bold(' Summary:'));
1118
- console.log(chalk.cyan(' Skills: ') + selectedSkillIds.join(', '));
1119
- console.log(chalk.cyan(' Agents: ') + selectedAgentIds.join(', '));
1120
- console.log(chalk.cyan(' Path: ') + (installPath || (installScope === 'global' ? 'global (user-level)' : 'project (current directory)')));
1121
- console.log('');
1122
-
1123
- if (!yesFlag) {
1124
- const { confirmed } = await prompts({
1125
- type: 'confirm',
1126
- name: 'confirmed',
1127
- message: isUpdate ? 'Apply changes?' : 'Proceed with installation?',
1128
- initial: true
1129
- });
1130
-
1131
- if (!confirmed) {
1132
- console.log(chalk.yellow('Operation cancelled.'));
1133
- process.exit(0);
1134
- }
1135
- }
1136
-
1137
- // Step 5: Execution
1138
- if (isUpdate) {
1139
- // Build a map: skillId -> set of agent IDs that originally had it installed
1140
- const originalAgentsBySkill = new Map();
1141
- const originalAllAgentIds = new Set();
1142
- existingStatus.forEach(entry => {
1143
- originalAllAgentIds.add(entry.agent.id);
1144
- Object.keys(entry.skills).forEach(skillId => {
1145
- if (!originalAgentsBySkill.has(skillId)) {
1146
- originalAgentsBySkill.set(skillId, new Set());
1147
- }
1148
- originalAgentsBySkill.get(skillId).add(entry.agent.id);
1149
- });
1150
- });
1151
-
1152
- const finalSkills = new Set(selectedSkillIds);
1153
-
1154
- // Skills to fully remove (deselected from skill list)
1155
- const toRemove = [...originalAgentsBySkill.keys()].filter(id => !finalSkills.has(id));
1156
-
1157
- if (toRemove.length > 0) {
1158
- console.log(chalk.gray(`\n Cleaning up ${toRemove.length} removed skills...`));
1159
- for (const skillId of toRemove) {
1160
- // Use the ORIGINAL agent IDs, not the new selection
1161
- const originalAgents = [...originalAgentsBySkill.get(skillId)];
1162
- await uninstallSkill(skillId, originalAgents, installPath, 'project');
1163
- }
1164
- }
1165
-
1166
- // Also handle agents that were deselected: uninstall their skills
1167
- const deselectedAgents = [...originalAllAgentIds].filter(id => !selectedAgentIds.includes(id));
1168
-
1169
- if (deselectedAgents.length > 0) {
1170
- console.log(chalk.gray(`\n Removing skills from ${deselectedAgents.length} deselected agents...`));
1171
- for (const [skillId, agentSet] of originalAgentsBySkill) {
1172
- const agentsToRemoveFrom = deselectedAgents.filter(id => agentSet.has(id));
1173
- if (agentsToRemoveFrom.length > 0) {
1174
- await uninstallSkill(skillId, agentsToRemoveFrom, installPath, 'project');
1175
- }
1176
- }
1177
- }
1178
- }
1179
-
1180
- // Story 22.3 — Legacy skill retirement migration (AC 7).
1181
- // Sweep every agent install path and remove any of the four retired skill IDs
1182
- // (bmad-init, bmad-agent-qa, bmad-agent-sm, bmad-agent-quick-flow-solo-dev)
1183
- // from the manifest and the installed skill directories. Idempotent — safe
1184
- // to run on fresh installs where nothing is retired.
1185
- try {
1186
- await migrateRetiredSkills({ scope: installScope, customPath: installPath });
1187
- } catch (err) {
1188
- console.log(chalk.yellow(`\n Retired-skill migration skipped: ${err.message}`));
1189
- }
1190
-
1191
- // Install requested skills
1192
- const batchState = {};
1193
- if (yesFlag) {
1194
- batchState.globalAction = 'update';
1195
- }
1196
- for (const skillId of selectedSkillIds) {
1197
- try {
1198
- await installSkill(skillId, selectedAgentIds, installPath, installScope, { force: !!forceFlag, yes: yesFlag, batchState });
1199
- } catch (error) {
1200
- console.error(chalk.red(`\n Failed to install ${skillId}:`), error.message);
1201
- }
1202
- }
1203
-
1204
- // Step 6: Update project-context.md with repo layout section (after skills installed project-context.md)
1205
- if (installScope === 'project') {
1206
- const outputPath = path.join(process.cwd(), '_bmad-output', 'project-context.md');
1207
- try {
1208
- if (fs.existsSync(outputPath)) {
1209
- const updated = await updateProjectContextRepoLayout(outputPath, repoLayout);
1210
- if (updated) {
1211
- console.log(chalk.green(' project-context.md repo layout section updated'));
1212
- }
1213
- }
1214
- } catch (err) {
1215
- console.log(chalk.yellow(` project-context repo layout update skipped: ${err.message}`));
1216
- }
1217
- }
1218
-
1219
- console.log(chalk.bold.green('\n Done!\n'));
1220
- }
1221
-
1222
- // --- Command handlers ---
1223
-
1224
- async function handleInstall(args) {
1225
- const { globalFlag, forceFlag, yesFlag, agentFlag, customPath, scope, positional } = parseFlags(args);
1226
-
1227
- // Task 3.2: Validate agentFlag against known agents
1228
- if (agentFlag) {
1229
- const knownAgents = listAgents();
1230
- const isKnown = knownAgents.some(a => a.id === agentFlag);
1231
- if (!isKnown) {
1232
- console.error(chalk.red(`Error: Unknown agent '${agentFlag}'`));
1233
- console.error(chalk.gray(' Hint: Run "list" to see available agents'));
1234
- process.exit(1);
1235
- }
1236
- }
1237
-
1238
- const skillId = positional[0];
1239
- const agentIds = positional.slice(1);
1240
- const preselectedAgents = agentFlag ? [agentFlag] : null;
1241
-
1242
- // No skill → launch wizard (Task 3.3, 3.4)
1243
- if (!skillId) {
1244
- await installWizard(null, preselectedAgents, customPath, forceFlag, yesFlag, scope);
1245
- return;
1246
- }
1247
-
1248
- // Skill but no agents (and no agentFlag) → wizard with skill preselected
1249
- if (!agentFlag && agentIds.length === 0) {
1250
- await installWizard(skillId, null, customPath, forceFlag, yesFlag, scope);
1251
- return;
1252
- }
1253
-
1254
- // Direct install path — Story 21.1 AC #9, #11: resolve + persist profile BEFORE install.
1255
- // Profile lives at the project root (cwd), not the custom skills-install path.
1256
- // When stdin is not a TTY and nothing is resolvable, default to 'standard' (same
1257
- // behavior as --yes) rather than aborting — keeps CI/CD direct installs working.
1258
- const projectRootForProfile = process.cwd();
1259
- const persistedProfile = getProfile(projectRootForProfile);
1260
- let resolvedProfile = resolveProfile({
1261
- persisted: persistedProfile,
1262
- yesMode: yesFlag
1263
- });
1264
- let profileSource;
1265
- if (persistedProfile) profileSource = '.ma-agents.json';
1266
- else if (resolvedProfile === 'standard' && yesFlag) profileSource = '--yes default';
1267
-
1268
- if (resolvedProfile === null) {
1269
- if (!process.stdin.isTTY) {
1270
- // Non-interactive fallback: default to 'standard' and persist (mirrors --yes).
1271
- resolvedProfile = 'standard';
1272
- profileSource = '--yes default';
1273
- } else {
1274
- const { chosenProfile } = await prompts({
1275
- type: 'select',
1276
- name: 'chosenProfile',
1277
- message: 'Is this an on-prem / air-gapped install using a local LLM (e.g. Nemotron)?',
1278
- choices: [
1279
- { title: 'Yes apply local-LLM guardrails (recommended for non-Claude models)', value: 'on-prem' },
1280
- { title: 'No — standard install (Claude on web, Anthropic API, etc.)', value: 'standard' }
1281
- ],
1282
- initial: 1
1283
- });
1284
- if (!chosenProfile) process.exit(0);
1285
- resolvedProfile = chosenProfile;
1286
- profileSource = 'interactive prompt';
1287
- }
1288
- }
1289
-
1290
- console.log(chalk.cyan(`Using profile: ${resolvedProfile} (from ${profileSource})`));
1291
- setProfile(projectRootForProfile, resolvedProfile);
1292
-
1293
- // Full args → direct install (Task 3.5)
1294
- const targetAgents = agentFlag ? [agentFlag] : agentIds;
1295
-
1296
- // Story 22.3 (AC 7) sweep retired legacy skills before installing.
1297
- // When a customPath is given we narrow the sweep to that single path;
1298
- // otherwise migrateRetiredSkills sweeps every registered agent under the
1299
- // current scope (the retirement is agent-agnostic, so broader sweep is
1300
- // the intended behavior even when --agent restricts the install to one).
1301
- try {
1302
- await migrateRetiredSkills({ scope, customPath: customPath || '' });
1303
- } catch (err) {
1304
- console.log(chalk.yellow(`\n Retired-skill migration skipped: ${err.message}`));
1305
- }
1306
-
1307
- try {
1308
- await installSkill(skillId, targetAgents, customPath, scope, { force: forceFlag, yes: yesFlag });
1309
- console.log(chalk.bold.green('\n Installation complete!\n'));
1310
- } catch (error) {
1311
- console.error(chalk.red('\n Installation failed:'), error.message);
1312
- process.exit(1);
1313
- }
1314
- }
1315
-
1316
- async function handleUninstall(args) {
1317
- // Story 21.11 if --profile-artifacts flag is present, route to uninstallProfileArtifacts.
1318
- // --yes IS supported for profile-artifact uninstall (CI decommissioning use-case).
1319
- // This is an intentional asymmetry vs. `reconfigure` which REJECTS --yes.
1320
- if (args.includes('--profile-artifacts')) {
1321
- const yesFlag = args.includes('--yes');
1322
- try {
1323
- await uninstallProfileArtifacts(process.cwd(), { yes: yesFlag });
1324
- } catch (error) {
1325
- console.error(chalk.red('\n Profile artifact uninstall failed:'), error.message);
1326
- process.exit(1);
1327
- }
1328
- return;
1329
- }
1330
-
1331
- const { globalFlag, customPath, scope, positional } = parseFlags(args);
1332
-
1333
- const skillId = positional[0];
1334
- const agentIds = positional.slice(1);
1335
-
1336
- if (!skillId) {
1337
- console.error(chalk.red('Usage: npx ma-agents uninstall <skill> <agents...>'));
1338
- process.exit(1);
1339
- }
1340
-
1341
- if (agentIds.length === 0) {
1342
- console.error(chalk.red('Please specify at least one agent. Run "npx ma-agents agents" to see options.'));
1343
- process.exit(1);
1344
- }
1345
-
1346
- try {
1347
- await uninstallSkill(skillId, agentIds, customPath, scope);
1348
- console.log(chalk.bold.green('\n Uninstall complete!\n'));
1349
- } catch (error) {
1350
- console.error(chalk.red('\n Uninstall failed:'), error.message);
1351
- process.exit(1);
1352
- }
1353
- }
1354
-
1355
- // --- Config layout command ---
1356
-
1357
- function showCurrentLayout() {
1358
- const layout = readExistingLayout();
1359
- if (!layout) {
1360
- console.log(chalk.cyan('\n Single-repo layout (default)'));
1361
- console.log(chalk.gray(' Knowledgebase: . (current repository)'));
1362
- console.log(chalk.gray(' Sprint management: . (current repository)'));
1363
- return;
1364
- }
1365
-
1366
- console.log(chalk.bold.cyan('\n Current Repository Layout:\n'));
1367
- for (const [label, key] of [['Knowledgebase', 'knowledgebase'], ['Sprint Management', 'sprintManagement']]) {
1368
- const concern = layout[key];
1369
- console.log(chalk.white(` ${label}:`));
1370
- console.log(chalk.gray(` Mode: ${concern.mode}`));
1371
- console.log(chalk.gray(` Path: ${concern.path}`));
1372
- if (concern.gitUrl) {
1373
- console.log(chalk.gray(` Git URL: ${concern.gitUrl}`));
1374
- }
1375
- }
1376
- console.log('');
1377
- }
1378
-
1379
- async function handleConfigLayout(args) {
1380
- const { yesFlag } = parseFlags(args);
1381
- const showOnly = args.includes('--show');
1382
-
1383
- if (showOnly) {
1384
- showCurrentLayout();
1385
- return;
1386
- }
1387
-
1388
- // Show current before reconfiguring
1389
- showCurrentLayout();
1390
-
1391
- // Read existing and present pre-populated wizard
1392
- const existingLayout = readExistingLayout();
1393
- const newLayout = await collectRepoLayout({ yes: yesFlag }, existingLayout);
1394
-
1395
- // Write updated config
1396
- writeRepoLayoutConfig(newLayout);
1397
- writeProjectLayoutYaml(newLayout);
1398
-
1399
- // Update project-context.md
1400
- const outputPath = path.join(process.cwd(), '_bmad-output', 'project-context.md');
1401
- try {
1402
- if (fs.existsSync(outputPath)) {
1403
- const updated = await updateProjectContextRepoLayout(outputPath, newLayout);
1404
- if (updated) {
1405
- console.log(chalk.green(' project-context.md repo layout section updated'));
1406
- }
1407
- }
1408
- } catch (err) {
1409
- console.log(chalk.yellow(` project-context repo layout update skipped: ${err.message}`));
1410
- }
1411
-
1412
- console.log(chalk.bold.green('\n Layout reconfigured!\n'));
1413
- }
1414
-
1415
- // --- Profile reconfigure (Story 21.10) ---
1416
- async function handleReconfigure(args) {
1417
- try {
1418
- await runReconfigure({ projectRoot: process.cwd(), argv: args });
1419
- } catch (err) {
1420
- if (err instanceof ReconfigureYesRejectedError) {
1421
- console.error(chalk.red(err.message));
1422
- process.exit(1);
1423
- }
1424
- if (err instanceof ManifestNotFoundError) {
1425
- console.error(chalk.red(err.message));
1426
- console.error(chalk.gray(' Hint: run `npx ma-agents install` before `reconfigure`.'));
1427
- process.exit(1);
1428
- }
1429
- if (err instanceof RoomodesSlugDivergenceError) {
1430
- console.error(chalk.red(err.message));
1431
- process.exit(1);
1432
- }
1433
- if (err && err.name === 'ClinerulesDualFileDriftError') {
1434
- console.error(chalk.red(err.message));
1435
- process.exit(1);
1436
- }
1437
- throw err;
1438
- }
1439
- }
1440
-
1441
- // --- Interactive mode ---
1442
-
1443
- async function interactiveMode() {
1444
- console.log(chalk.bold.cyan(`\n ${NAME} v${VERSION}\n`));
1445
-
1446
- const { action } = await prompts({
1447
- type: 'select',
1448
- name: 'action',
1449
- message: 'What would you like to do?',
1450
- choices: [
1451
- { title: 'Install skills', value: 'install' },
1452
- { title: 'Show installed skills', value: 'status' },
1453
- { title: 'List available skills', value: 'list-skills' },
1454
- { title: 'List supported agents', value: 'list-agents' },
1455
- { title: 'Exit', value: 'exit' }
1456
- ]
1457
- });
1458
-
1459
- if (!action || action === 'exit') {
1460
- console.log(chalk.yellow('Goodbye!'));
1461
- process.exit(0);
1462
- }
1463
-
1464
- if (action === 'status') {
1465
- showStatus([]);
1466
- process.exit(0);
1467
- }
1468
-
1469
- if (action === 'list-skills') {
1470
- showSkills();
1471
- process.exit(0);
1472
- }
1473
-
1474
- if (action === 'list-agents') {
1475
- showAgents();
1476
- process.exit(0);
1477
- }
1478
-
1479
- if (action === 'install') {
1480
- await installWizard();
1481
- }
1482
- }
1483
-
1484
- // --- Main ---
1485
-
1486
- async function main() {
1487
- const args = process.argv.slice(2);
1488
-
1489
- // Handle --log flag globally (before command routing)
1490
- let cleanupLog = null;
1491
- const logIdx = args.indexOf('--log');
1492
- if (logIdx !== -1) {
1493
- const ts = new Date().toISOString().replace(/[:.]/g, '-').replace('T', '_').replace('Z', '');
1494
- const logFile = `install_${ts}.log`;
1495
- cleanupLog = setupLogging(logFile);
1496
- console.log(chalk.gray(` Logging to ${logFile}`));
1497
- args.splice(logIdx, 1);
1498
- }
1499
-
1500
- const command = args[0];
1501
-
1502
- switch (command) {
1503
- case 'install':
1504
- await handleInstall(args.slice(1));
1505
- break;
1506
- case 'uninstall':
1507
- case 'remove':
1508
- await handleUninstall(args.slice(1));
1509
- break;
1510
- case 'status':
1511
- showStatus(args.slice(1));
1512
- break;
1513
- case 'list':
1514
- case 'list-skills':
1515
- showSkills(args.slice(1));
1516
- break;
1517
- case 'agents':
1518
- case 'list-agents':
1519
- showAgents();
1520
- break;
1521
- case 'create-skill':
1522
- await handleCreateSkill(args.slice(1));
1523
- break;
1524
- case 'validate-skill':
1525
- await handleValidateSkill(args.slice(1));
1526
- break;
1527
- case 'set-mandatory':
1528
- await handleSetMandatory(args.slice(1));
1529
- break;
1530
- case 'customize-agent':
1531
- await handleCustomizeAgent(args.slice(1));
1532
- break;
1533
- case 'create-agent':
1534
- await handleCreateAgent(args.slice(1));
1535
- break;
1536
- case 'config':
1537
- if (args[1] === 'layout') {
1538
- await handleConfigLayout(args.slice(2));
1539
- } else {
1540
- console.error(chalk.red(`Unknown config subcommand: ${args[1] || '(none)'}`));
1541
- console.error(chalk.gray(' Usage: npx ma-agents config layout [--show] [--yes]'));
1542
- process.exit(1);
1543
- }
1544
- break;
1545
- case 'reconfigure':
1546
- await handleReconfigure(args.slice(1));
1547
- break;
1548
- case 'help':
1549
- case '--help':
1550
- case '-h':
1551
- showHelp();
1552
- break;
1553
- case 'version':
1554
- case '--version':
1555
- case '-v':
1556
- console.log(`${NAME} v${VERSION}`);
1557
- break;
1558
- default:
1559
- await interactiveMode();
1560
- break;
1561
- }
1562
-
1563
- if (cleanupLog) cleanupLog();
1564
- }
1565
-
1566
- if (require.main === module) {
1567
- main().catch(error => {
1568
- console.error(chalk.red('Error:'), error);
1569
- process.exit(1);
1570
- });
1571
- }
1572
-
1573
- module.exports = { parseFlags, collectRepoLayout, readExistingLayout, writeRepoLayoutConfig, writeProjectLayoutYaml, writeConfigField, normalizePath, toPortablePath, resolveStoredPath, ciCloneIfNeeded, showCurrentLayout, handleConfigLayout, yamlEscapeValue };
1
+ #!/usr/bin/env node
2
+
3
+ // Bug A fix — suppress the cosmetic Node.js ExperimentalWarning about
4
+ // CommonJS require() of an ES Module. Must be installed BEFORE any
5
+ // other require() so the filter catches warnings fired by the very
6
+ // first dependency-loading call below. See lib/warning-filter.js.
7
+ //
8
+ // Re-exec gating:
9
+ // - Only when this file is launched as the CLI (require.main === module).
10
+ // When imported by the test suite or another script, skip the re-exec
11
+ // path — otherwise the importing process would silently fork itself.
12
+ // - Only for commands that can trigger the CJS-require-ESM warning,
13
+ // i.e. those that spawn bmad-method or otherwise load the heavy
14
+ // transitive dependency graph. Informational commands (--help,
15
+ // --version, status, list, agents) stay single-process for fast
16
+ // cold start. The listener-only fallback is still attached so
17
+ // in-process warnings still route through our filter.
18
+ const { installExperimentalWarningFilter } = require('../lib/warning-filter');
19
+ const _reexecCommands = new Set([
20
+ 'install', 'uninstall', 'remove',
21
+ 'create-skill', 'validate-skill', 'set-mandatory',
22
+ 'customize-agent', 'create-agent',
23
+ 'config',
24
+ undefined, // bare `ma-agents` → interactive wizard
25
+ ]);
26
+ const _firstArg = process.argv[2];
27
+ installExperimentalWarningFilter({
28
+ reexec: require.main === module && _reexecCommands.has(_firstArg),
29
+ });
30
+
31
+ const prompts = require('prompts');
32
+ const chalk = require('chalk');
33
+ const path = require('path');
34
+ const fs = require('fs');
35
+ const { execFileSync } = require('child_process');
36
+ const { installSkill, uninstallSkill, getStatus, listSkills, listAgents, updateProjectContextRepoLayout, migrateRetiredSkills } = require('../lib/installer');
37
+ const { getProfile, setProfile, resolveProfile } = require('../lib/profile');
38
+ const { reconfigure: runReconfigure, ReconfigureYesRejectedError, ManifestNotFoundError, RoomodesSlugDivergenceError } = require('../lib/reconfigure');
39
+ const { uninstallProfileArtifacts } = require('../lib/uninstall');
40
+ const bmad = require('../lib/bmad');
41
+ const { getBmadPlatformCode } = require('../lib/agents');
42
+ const { handleCreateSkill, handleValidateSkill, handleSetMandatory, handleCustomizeAgent, handleCreateAgent } = require('../lib/skill-authoring');
43
+
44
+ const PKG = require('../package.json');
45
+ const NAME = PKG.name;
46
+ const VERSION = PKG.version;
47
+
48
+ /**
49
+ * Set up logging to tee all stdout/stderr output to a file.
50
+ * Returns a cleanup function to close the file descriptor.
51
+ *
52
+ * @param {string} logFilePath - Path to the log file
53
+ * @returns {Function} cleanup function
54
+ */
55
+ function setupLogging(logFilePath) {
56
+ const logFd = fs.openSync(logFilePath, 'w');
57
+ const header = `[${new Date().toISOString()}] ${NAME} v${VERSION} — log started\n`;
58
+ fs.writeSync(logFd, header);
59
+
60
+ const origStdoutWrite = process.stdout.write.bind(process.stdout);
61
+ const origStderrWrite = process.stderr.write.bind(process.stderr);
62
+
63
+ process.stdout.write = function (chunk, encoding, callback) {
64
+ const str = typeof chunk === 'string' ? chunk : chunk.toString();
65
+ try { fs.writeSync(logFd, str); } catch { /* ignore write errors */ }
66
+ return origStdoutWrite(chunk, encoding, callback);
67
+ };
68
+
69
+ process.stderr.write = function (chunk, encoding, callback) {
70
+ const str = typeof chunk === 'string' ? chunk : chunk.toString();
71
+ try { fs.writeSync(logFd, str); } catch { /* ignore write errors */ }
72
+ return origStderrWrite(chunk, encoding, callback);
73
+ };
74
+
75
+ // Store log fd globally so bmad.js can use pipe mode
76
+ process.env.MA_AGENTS_LOG_ACTIVE = '1';
77
+
78
+ return function cleanup() {
79
+ process.stdout.write = origStdoutWrite;
80
+ process.stderr.write = origStderrWrite;
81
+ const footer = `\n[${new Date().toISOString()}] log ended\n`;
82
+ try { fs.writeSync(logFd, footer); } catch { /* ignore */ }
83
+ try { fs.closeSync(logFd); } catch { /* ignore */ }
84
+ delete process.env.MA_AGENTS_LOG_ACTIVE;
85
+ };
86
+ }
87
+
88
+ function showHelp() {
89
+ console.log(`
90
+ ${chalk.bold.cyan(NAME)} ${chalk.gray(`v${VERSION}`)}
91
+
92
+ ${chalk.bold('Usage:')}
93
+ ${chalk.cyan(`npx ${NAME}`)} Interactive wizard
94
+ ${chalk.cyan(`npx ${NAME} install`)} Interactive install wizard
95
+ ${chalk.cyan(`npx ${NAME} install`)} <skill> <agents...> Install directly
96
+ ${chalk.cyan(`npx ${NAME} uninstall`)} <skill> <agents..> Uninstall a skill
97
+ ${chalk.cyan(`npx ${NAME} uninstall --profile-artifacts`)} Remove ma-agents-owned profile content from all injection files
98
+ ${chalk.cyan(`npx ${NAME} status`)} Show installed skills
99
+ ${chalk.cyan(`npx ${NAME} list`)} List available skills
100
+ ${chalk.cyan(`npx ${NAME} agents`)} List supported agents
101
+ ${chalk.cyan(`npx ${NAME} create-skill`)} <name> Scaffold a new skill directory
102
+ ${chalk.cyan(`npx ${NAME} validate-skill`)} <name> Validate a skill against the schema
103
+ ${chalk.cyan(`npx ${NAME} set-mandatory`)} <name> [--off] Mark a skill as always-load (or remove)
104
+ ${chalk.cyan(`npx ${NAME} customize-agent`)} <agent> Customize a BMAD agent persona and actions
105
+ ${chalk.cyan(`npx ${NAME} create-agent`)} <name> Create a new specialized BMAD agent
106
+ ${chalk.cyan(`npx ${NAME} reconfigure`)} Re-run the profile prompt and re-stamp artifacts
107
+ ${chalk.cyan(`npx ${NAME} config layout`)} Reconfigure repository layout
108
+ ${chalk.cyan(`npx ${NAME} config layout --show`)} Show current layout (read-only)
109
+ ${chalk.cyan(`npx ${NAME} help`)} Show this help
110
+
111
+ ${chalk.bold('Install options:')}
112
+ ${chalk.cyan('--global')} Install to global/user-level paths (default: project-level)
113
+ ${chalk.cyan('--path <dir>')} Custom installation directory
114
+ ${chalk.cyan('--force')} Skip upgrade prompts, always overwrite
115
+ ${chalk.cyan('--yes')} Skip all prompts, use defaults (for CI/CD)
116
+ ${chalk.cyan('--agent <name>')} Target a specific agent (skip agent selection)
117
+ ${chalk.cyan('--bmad-modules [csv]')} Control BMAD module selection.
118
+ Bare: open a multiselect prompt
119
+ With CSV: install exactly those (e.g. tea,bmb)
120
+ Omitted: install every non-retired module (default)
121
+ 'bmm' is always force-included.
122
+ ${chalk.cyan('--log')} Log all console output to install_<datetime>.log
123
+
124
+ ${chalk.bold('Reconfigure options:')}
125
+ ${chalk.cyan('--force-roomodes-overwrite')} Accept slug-stomp on user-edited ma-agents slugs
126
+ ${chalk.gray('(reconfigure rejects --yes by design — it is interactive only)')}
127
+
128
+ ${chalk.bold('Uninstall --profile-artifacts options:')}
129
+ ${chalk.cyan('--yes')} Skip confirmation prompt (supported for CI decommissioning)
130
+ ${chalk.gray('(asymmetry note: uninstall --profile-artifacts accepts --yes; reconfigure does not)')}
131
+
132
+ ${chalk.bold('Notes:')}
133
+ Divergent \`.cline/clinerules.md\` vs. \`.clinerules\` marker blocks require
134
+ manual reconciliation \`--yes\` does not bypass this check.
135
+
136
+ ${chalk.bold('Examples:')}
137
+ npx ${NAME} install
138
+ npx ${NAME} install code-review claude-code
139
+ npx ${NAME} install code-review claude-code --force
140
+ npx ${NAME} install --yes
141
+ npx ${NAME} install --yes --agent claude-code
142
+ npx ${NAME} install --yes --global
143
+ npx ${NAME} install --yes --bmad-modules bmm,tea,bmb
144
+ npx ${NAME} install --bmad-modules # prompt for modules
145
+ npx ${NAME} uninstall code-review claude-code
146
+ npx ${NAME} status
147
+ npx ${NAME} status --global
148
+ `);
149
+ }
150
+
151
+ function showSkills(args) {
152
+ const mandatoryOnly = args && args.includes('--mandatory');
153
+ let skills = listSkills();
154
+ if (mandatoryOnly) {
155
+ skills = skills.filter(s => s.always_load === true);
156
+ console.log(chalk.bold('\n Mandatory Skills (always_load: true):\n'));
157
+ } else {
158
+ console.log(chalk.bold('\n Available Skills:\n'));
159
+ }
160
+ skills.forEach(skill => {
161
+ console.log(chalk.cyan(` ${skill.id.padEnd(35)}`) + chalk.white(`${skill.name}`) + chalk.gray(` v${skill.version}`));
162
+ console.log(chalk.gray(` ${''.padEnd(35)}${skill.description}\n`));
163
+ });
164
+ }
165
+
166
+ function showAgents() {
167
+ const agents = listAgents();
168
+ console.log(chalk.bold('\n Supported Agents:\n'));
169
+
170
+ const ideAgents = agents.filter(a => a.category !== 'bmad');
171
+ const bmadAgents = agents.filter(a => a.category === 'bmad');
172
+
173
+ console.log(chalk.bold.yellow(' AI Coding Assistants:'));
174
+ ideAgents.forEach(agent => {
175
+ console.log(chalk.cyan(` ${agent.id.padEnd(20)}`) + chalk.white(agent.name) + chalk.gray(` v${agent.version} - ${agent.description}`));
176
+ });
177
+
178
+ console.log(chalk.bold.yellow('\n BMAD Method Agents:'));
179
+ bmadAgents.forEach(agent => {
180
+ console.log(chalk.cyan(` ${agent.id.padEnd(20)}`) + chalk.white(agent.name) + chalk.gray(` v${agent.version} - ${agent.description}`));
181
+ });
182
+ console.log('');
183
+ }
184
+
185
+ function showStatus(args) {
186
+ const globalFlag = args.includes('--global');
187
+ const scope = globalFlag ? 'global' : 'project';
188
+ const positional = args.filter(a => a !== '--global');
189
+
190
+ const results = getStatus(positional, '', scope);
191
+
192
+ if (results.length === 0) {
193
+ console.log(chalk.gray(`\n No skills installed (${scope} scope)\n`));
194
+ return;
195
+ }
196
+
197
+ console.log(chalk.bold(`\n Installed Skills:\n`));
198
+
199
+ for (const entry of results) {
200
+ console.log(chalk.cyan(` ${entry.agent.name}`) + chalk.gray(` (${entry.scope}: ${entry.installPath})`));
201
+
202
+ const skillIds = Object.keys(entry.skills);
203
+ for (const skillId of skillIds) {
204
+ const info = entry.skills[skillId];
205
+ const installed = new Date(info.installedAt).toLocaleDateString();
206
+ const updated = info.updatedAt !== info.installedAt
207
+ ? chalk.gray(` updated ${new Date(info.updatedAt).toLocaleDateString()}`)
208
+ : '';
209
+ console.log(
210
+ chalk.white(` ${skillId.padEnd(35)}`) +
211
+ chalk.green(`v${info.version}`) +
212
+ chalk.gray(` installed ${installed}`) +
213
+ updated
214
+ );
215
+ }
216
+ console.log('');
217
+ }
218
+ }
219
+
220
+ // --- Parse common flags from args ---
221
+
222
+ function parseFlags(args) {
223
+ const globalFlag = args.includes('--global');
224
+ const forceFlag = args.includes('--force');
225
+ const yesFlag = args.includes('--yes');
226
+ let customPath = '';
227
+ let agentFlag = '';
228
+
229
+ let positional = [...args].filter(a =>
230
+ a !== '--global' && a !== '--force' && a !== '--yes'
231
+ );
232
+
233
+ const pathIdx = positional.indexOf('--path');
234
+ if (pathIdx !== -1) {
235
+ customPath = positional[pathIdx + 1] || '';
236
+ positional.splice(pathIdx, 2);
237
+ }
238
+
239
+ const agentIdx = positional.indexOf('--agent');
240
+ if (agentIdx !== -1) {
241
+ const agentName = positional[agentIdx + 1];
242
+ if (!agentName || agentName.startsWith('--')) {
243
+ console.error(chalk.red('Error: --agent requires an agent name'));
244
+ console.error(chalk.gray(' Hint: Run "list" to see available agents'));
245
+ process.exit(1);
246
+ }
247
+ agentFlag = agentName;
248
+ positional.splice(agentIdx, 2);
249
+ }
250
+
251
+ // --bmad-modules — controls BMad module selection. Optional-value flag:
252
+ // bare → ask the user via multiselect prompt
253
+ // with CSV → install exactly those (bmm force-prepended, unknowns rejected)
254
+ // not present → install all non-retired modules (no prompt)
255
+ // Force-prepending of `bmm` and validation of unknown ids is handled
256
+ // centrally by lib/bmad.resolveBmadModules.
257
+ let bmadModulesFlag = '';
258
+ let bmadModulesPrompt = false;
259
+ const bmadModulesIdx = positional.indexOf('--bmad-modules');
260
+ if (bmadModulesIdx !== -1) {
261
+ const value = positional[bmadModulesIdx + 1];
262
+ if (!value || value.startsWith('--')) {
263
+ // Bare flag — the next token is another flag or the end of args.
264
+ // Treat as a request to prompt the user.
265
+ bmadModulesPrompt = true;
266
+ positional.splice(bmadModulesIdx, 1);
267
+ } else {
268
+ bmadModulesFlag = value;
269
+ positional.splice(bmadModulesIdx, 2);
270
+ }
271
+ }
272
+
273
+ return {
274
+ globalFlag,
275
+ forceFlag,
276
+ yesFlag,
277
+ agentFlag,
278
+ customPath,
279
+ bmadModulesFlag,
280
+ bmadModulesPrompt,
281
+ scope: globalFlag ? 'global' : 'project',
282
+ positional
283
+ };
284
+ }
285
+
286
+ // --- Repository layout wizard ---
287
+
288
+ async function collectLocalPath(concern) {
289
+ while (true) {
290
+ const { localPath } = await prompts({
291
+ type: 'text',
292
+ name: 'localPath',
293
+ message: `Enter local path for ${concern}:`
294
+ });
295
+
296
+ if (!localPath || !localPath.trim()) {
297
+ console.log(chalk.red(' Path cannot be empty. Please try again.'));
298
+ continue;
299
+ }
300
+
301
+ const resolved = path.resolve(process.cwd(), localPath.trim());
302
+
303
+ if (fs.existsSync(resolved)) {
304
+ if (!fs.statSync(resolved).isDirectory()) {
305
+ console.log(chalk.red(` "${resolved}" exists but is a file, not a directory. Please try again.`));
306
+ continue;
307
+ }
308
+ } else {
309
+ console.log(chalk.yellow(` Warning: "${resolved}" does not exist.`));
310
+ const { confirmed } = await prompts({
311
+ type: 'confirm',
312
+ name: 'confirmed',
313
+ message: 'Use this path anyway? (It must exist before agents run)',
314
+ initial: false
315
+ });
316
+ if (!confirmed) continue;
317
+ console.log(chalk.yellow(` Note: Path "${resolved}" must exist before agents run.`));
318
+ }
319
+
320
+ if (resolved.startsWith(process.cwd())) {
321
+ console.log(chalk.yellow(` Warning: Path is inside the current repository. Nested repos may cause git confusion.`));
322
+ }
323
+
324
+ return { mode: 'local', path: resolved };
325
+ }
326
+ }
327
+
328
+ async function collectRemotePath(concern) {
329
+ while (true) {
330
+ // Collect git URL
331
+ let gitUrl;
332
+ while (true) {
333
+ const { url } = await prompts({
334
+ type: 'text',
335
+ name: 'url',
336
+ message: `Enter git URL for ${concern}:`
337
+ });
338
+ if (!url || !url.trim()) {
339
+ console.log(chalk.red(' Git URL cannot be empty. Please try again.'));
340
+ continue;
341
+ }
342
+ gitUrl = url.trim();
343
+ break;
344
+ }
345
+
346
+ // Collect destination path
347
+ let destPath;
348
+ while (true) {
349
+ const { dest } = await prompts({
350
+ type: 'text',
351
+ name: 'dest',
352
+ message: `Enter local destination path for clone:`
353
+ });
354
+ if (!dest || !dest.trim()) {
355
+ console.log(chalk.red(' Destination path cannot be empty. Please try again.'));
356
+ continue;
357
+ }
358
+ destPath = path.resolve(process.cwd(), dest.trim());
359
+ break;
360
+ }
361
+
362
+ // Check destination
363
+ if (fs.existsSync(destPath)) {
364
+ if (!fs.statSync(destPath).isDirectory()) {
365
+ console.log(chalk.red(` "${destPath}" exists but is a file, not a directory. Please try again.`));
366
+ continue;
367
+ }
368
+ // Existing directory — show summary and confirm
369
+ const files = fs.readdirSync(destPath);
370
+ const isGitRepo = fs.existsSync(path.join(destPath, '.git'));
371
+ console.log(chalk.blue(` Directory exists: ${files.length} items${isGitRepo ? ' (git repo)' : ''}`));
372
+ const { confirmed } = await prompts({
373
+ type: 'confirm',
374
+ name: 'confirmed',
375
+ message: 'Use this existing directory?',
376
+ initial: true
377
+ });
378
+ if (!confirmed) continue;
379
+ } else {
380
+ // Clone
381
+ const existedBefore = fs.existsSync(destPath);
382
+ try {
383
+ console.log(chalk.cyan(` Cloning ${gitUrl}...`));
384
+ execFileSync('git', ['clone', gitUrl, destPath], {
385
+ timeout: 120000,
386
+ env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
387
+ stdio: 'inherit'
388
+ });
389
+ } catch (err) {
390
+ console.log(chalk.red(` Clone failed: ${err.message}`));
391
+ if (!existedBefore && fs.existsSync(destPath)) {
392
+ fs.rmSync(destPath, { recursive: true, force: true });
393
+ }
394
+ const { retry } = await prompts({
395
+ type: 'confirm',
396
+ name: 'retry',
397
+ message: 'Retry?',
398
+ initial: true
399
+ });
400
+ if (retry) continue;
401
+ console.log(chalk.yellow(` Falling back to current repository for ${concern}`));
402
+ return { mode: 'same', path: '.' };
403
+ }
404
+ }
405
+
406
+ if (destPath.startsWith(process.cwd())) {
407
+ console.log(chalk.yellow(` Warning: Destination is inside the current repository. Nested repos may cause git confusion.`));
408
+ }
409
+
410
+ return { mode: 'remote', path: destPath, gitUrl };
411
+ }
412
+ }
413
+
414
+ async function collectJiraConfig() {
415
+ // Collect Jira server URL
416
+ let jiraUrl;
417
+ while (true) {
418
+ const { url } = await prompts({
419
+ type: 'text',
420
+ name: 'url',
421
+ message: 'Jira server URL (e.g. https://mycompany.atlassian.net):'
422
+ });
423
+ if (!url || !url.trim()) {
424
+ console.log(chalk.red(' Jira server URL cannot be empty. Please try again.'));
425
+ continue;
426
+ }
427
+ jiraUrl = url.trim();
428
+ break;
429
+ }
430
+
431
+ // Collect Jira project key
432
+ let jiraProjectKey;
433
+ while (true) {
434
+ const { key } = await prompts({
435
+ type: 'text',
436
+ name: 'key',
437
+ message: 'Jira project key (e.g. MYPROJ):'
438
+ });
439
+ if (!key || !key.trim()) {
440
+ console.log(chalk.red(' Jira project key cannot be empty. Please try again.'));
441
+ continue;
442
+ }
443
+ if (!/^[A-Z][A-Z0-9]+$/.test(key.trim())) {
444
+ console.log(chalk.red(' Jira project key must be uppercase alphanumeric (e.g. MYPROJ). Please try again.'));
445
+ continue;
446
+ }
447
+ jiraProjectKey = key.trim();
448
+ break;
449
+ }
450
+
451
+ return { mode: 'jira', jiraUrl, jiraProjectKey };
452
+ }
453
+
454
+ function normalizePath(p) {
455
+ return p.replace(/\\/g, '/');
456
+ }
457
+
458
+ function yamlEscapeValue(v) {
459
+ if (!v) return '""';
460
+ const s = String(v);
461
+ if (/[:"#\[\]{}&*!|>%@`]/.test(s) || s !== s.trim() || s === '') {
462
+ return '"' + s.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
463
+ }
464
+ return '"' + s + '"';
465
+ }
466
+
467
+ function toPortablePath(absolutePath, projectRoot) {
468
+ if (!absolutePath || absolutePath === '.') return { portable: '.', isAbsolute: false };
469
+
470
+ const rel = normalizePath(path.relative(projectRoot, absolutePath));
471
+
472
+ // Same directory: path.relative returns '' treat as '.'
473
+ if (rel === '') return { portable: '.', isAbsolute: false };
474
+
475
+ // Cross-drive on Windows: path.relative returns the absolute target unchanged
476
+ if (path.isAbsolute(rel) || /^[A-Za-z]:/.test(rel)) {
477
+ return { portable: normalizePath(absolutePath), isAbsolute: true };
478
+ }
479
+
480
+ // Too many levels up — treat as non-portable
481
+ const upLevels = (rel.match(/\.\./g) || []).length;
482
+ if (upLevels > 3) {
483
+ return { portable: normalizePath(absolutePath), isAbsolute: true };
484
+ }
485
+
486
+ return { portable: rel, isAbsolute: false };
487
+ }
488
+
489
+ function writeConfigField(content, fieldName, value) {
490
+ const regex = new RegExp(`^${fieldName}:.*$`, 'm');
491
+ const newLine = `${fieldName}: ${yamlEscapeValue(value)}`;
492
+ if (regex.test(content)) {
493
+ return content.replace(regex, newLine);
494
+ }
495
+ return content.trimEnd() + '\n' + newLine + '\n';
496
+ }
497
+
498
+ function writeRepoLayoutConfig(layout) {
499
+ const configPath = path.join(process.cwd(), '_bmad', 'bmm', 'config.yaml');
500
+ try {
501
+ if (!fs.existsSync(configPath)) {
502
+ // Create an empty file so writeConfigField can append to it
503
+ fs.mkdirSync(path.join(process.cwd(), '_bmad', 'bmm'), { recursive: true });
504
+ fs.writeFileSync(configPath, '', 'utf-8');
505
+ }
506
+ let content = fs.readFileSync(configPath, 'utf-8');
507
+ const projectRoot = process.cwd();
508
+ const kbPortable = toPortablePath(layout.knowledgebase.path, projectRoot);
509
+ const kbPath = kbPortable.portable;
510
+ content = writeConfigField(content, 'knowledgebase_path', kbPath);
511
+
512
+ const spMode = layout.sprintManagement.mode;
513
+ if (spMode === 'jira') {
514
+ // Jira backend: write sprint_backend + Jira config; no sprint_management_path
515
+ content = writeConfigField(content, 'sprint_backend', 'jira');
516
+ content = writeConfigField(content, 'jira_url', layout.sprintManagement.jiraUrl);
517
+ content = writeConfigField(content, 'jira_project_key', layout.sprintManagement.jiraProjectKey);
518
+ // Derive artifact paths from kb only
519
+ const planningArtifacts = kbPath === '.' ? '_bmad-output/planning-artifacts' : `${kbPath}/_bmad-output/planning-artifacts`;
520
+ const implArtifacts = '_bmad-output/implementation-artifacts';
521
+ content = writeConfigField(content, 'planning_artifacts', planningArtifacts);
522
+ content = writeConfigField(content, 'implementation_artifacts', implArtifacts);
523
+ fs.writeFileSync(configPath, content, 'utf-8');
524
+ console.log(chalk.gray(` Config: knowledgebase_path="${kbPath}", sprint_backend=jira, jira_url="${layout.sprintManagement.jiraUrl}", jira_project_key="${layout.sprintManagement.jiraProjectKey}"`));
525
+ } else {
526
+ // File-system backend
527
+ const spPortable = toPortablePath(layout.sprintManagement.path, projectRoot);
528
+ const spPath = spPortable.portable;
529
+ content = writeConfigField(content, 'sprint_backend', 'file-system');
530
+ content = writeConfigField(content, 'sprint_management_path', spPath);
531
+ // Derive workflow-consumable artifact paths from layout paths (relative when base is relative)
532
+ const planningArtifacts = kbPath === '.' ? '_bmad-output/planning-artifacts' : `${kbPath}/_bmad-output/planning-artifacts`;
533
+ const implArtifacts = spPath === '.' ? '_bmad-output/implementation-artifacts' : `${spPath}/_bmad-output/implementation-artifacts`;
534
+ content = writeConfigField(content, 'planning_artifacts', planningArtifacts);
535
+ content = writeConfigField(content, 'implementation_artifacts', implArtifacts);
536
+ fs.writeFileSync(configPath, content, 'utf-8');
537
+ console.log(chalk.gray(` Config: knowledgebase_path="${kbPath}", sprint_backend=file-system, sprint_management_path="${spPath}"`));
538
+ }
539
+ } catch (e) {
540
+ console.log(chalk.red(` Cannot write config.yaml: ${e.message}`));
541
+ }
542
+ }
543
+
544
+ function writeProjectLayoutYaml(layout) {
545
+ const layoutPath = path.join(process.cwd(), '_bmad-output', 'project-layout.yaml');
546
+ // Only skip writing when BOTH concerns are truly same-repo (jira requires config recording)
547
+ const bothSame = layout.knowledgebase.mode === 'same' && layout.sprintManagement.mode === 'same';
548
+
549
+ if (bothSame) {
550
+ // Single-repo mode: delete stale file if exists
551
+ if (fs.existsSync(layoutPath)) {
552
+ fs.unlinkSync(layoutPath);
553
+ console.log(chalk.blue(' Removed stale project-layout.yaml (now in single-repo mode)'));
554
+ }
555
+ return;
556
+ }
557
+
558
+ // Multi-repo or Jira mode: generate project-layout.yaml
559
+ fs.mkdirSync(path.join(process.cwd(), '_bmad-output'), { recursive: true });
560
+
561
+ const date = new Date().toISOString().slice(0, 10);
562
+ let content = `# Generated by ma-agents — do not edit manually\n`;
563
+ content += `# Tells agents where to find planning and sprint data\n`;
564
+ content += `generated: "${date}"\n`;
565
+
566
+ const projectRoot = process.cwd();
567
+
568
+ // Knowledgebase section
569
+ const kbPortable = toPortablePath(layout.knowledgebase.path, projectRoot);
570
+ content += `knowledgebase:\n`;
571
+ content += ` mode: ${layout.knowledgebase.mode}\n`;
572
+ content += ` path: ${yamlEscapeValue(kbPortable.portable)}\n`;
573
+ if (kbPortable.isAbsolute) {
574
+ content += ` # PORTABILITY: absolute path other developers may need to reconfigure\n`;
575
+ }
576
+ if (layout.knowledgebase.mode === 'remote' && layout.knowledgebase.gitUrl) {
577
+ content += ` gitUrl: ${yamlEscapeValue(layout.knowledgebase.gitUrl)}\n`;
578
+ }
579
+
580
+ // Sprint management section
581
+ content += `sprint_management:\n`;
582
+ content += ` mode: ${layout.sprintManagement.mode}\n`;
583
+ if (layout.sprintManagement.mode === 'jira') {
584
+ content += ` jira_url: ${yamlEscapeValue(layout.sprintManagement.jiraUrl)}\n`;
585
+ content += ` jira_project_key: ${yamlEscapeValue(layout.sprintManagement.jiraProjectKey)}\n`;
586
+ } else {
587
+ const spPortable = toPortablePath(layout.sprintManagement.path, projectRoot);
588
+ content += ` path: ${yamlEscapeValue(spPortable.portable)}\n`;
589
+ if (spPortable.isAbsolute) {
590
+ content += ` # PORTABILITY: absolute path — other developers may need to reconfigure\n`;
591
+ }
592
+ if (layout.sprintManagement.mode === 'remote' && layout.sprintManagement.gitUrl) {
593
+ content += ` gitUrl: ${yamlEscapeValue(layout.sprintManagement.gitUrl)}\n`;
594
+ }
595
+ }
596
+
597
+ fs.writeFileSync(layoutPath, content, 'utf-8');
598
+ console.log(chalk.gray(` Created _bmad-output/project-layout.yaml`));
599
+ }
600
+
601
+ function resolveStoredPath(storedPath, projectRoot) {
602
+ if (!storedPath) return '.';
603
+ if (storedPath === '.') return storedPath;
604
+ // If already absolute, use as-is (backward compat)
605
+ if (path.isAbsolute(storedPath) || /^[A-Za-z]:/.test(storedPath)) return storedPath;
606
+ // Relative path resolve from project root
607
+ return normalizePath(path.resolve(projectRoot, storedPath));
608
+ }
609
+
610
+ function readExistingLayout() {
611
+ const projectRoot = process.cwd();
612
+ // Try project-layout.yaml first (authoritative source written by Story 16.2)
613
+ const layoutPath = path.join(projectRoot, '_bmad-output', 'project-layout.yaml');
614
+ try {
615
+ if (fs.existsSync(layoutPath)) {
616
+ const content = fs.readFileSync(layoutPath, 'utf-8');
617
+ const layout = { knowledgebase: null, sprintManagement: null };
618
+
619
+ // Parse each concern section from the simple YAML
620
+ for (const [section, key] of [['knowledgebase', 'knowledgebase'], ['sprint_management', 'sprintManagement']]) {
621
+ const sectionMatch = content.match(new RegExp(`^${section}:\\s*$`, 'm'));
622
+ if (!sectionMatch) continue;
623
+
624
+ const afterSection = content.slice(sectionMatch.index + sectionMatch[0].length);
625
+ const modeMatch = afterSection.match(/^\s+mode:\s*(\S+)/m);
626
+ const pathMatch = afterSection.match(/^\s+path:\s*"?([^"\n]+)"?/m);
627
+ const gitUrlMatch = afterSection.match(/^\s+gitUrl:\s*"?([^"\n]+)"?/m);
628
+ const jiraUrlMatch = afterSection.match(/^\s+jira_url:\s*"?([^"\n]+)"?/m);
629
+ const jiraProjectKeyMatch = afterSection.match(/^\s+jira_project_key:\s*"?([^"\n]+)"?/m);
630
+
631
+ if (modeMatch) {
632
+ const mode = modeMatch[1];
633
+ if (mode === 'jira') {
634
+ const jiraUrl = jiraUrlMatch ? jiraUrlMatch[1].replace(/^"(.*)"$/, '$1') : '';
635
+ const jiraProjectKey = jiraProjectKeyMatch ? jiraProjectKeyMatch[1].replace(/^"(.*)"$/, '$1') : '';
636
+ layout[key] = { mode: 'jira', jiraUrl, jiraProjectKey };
637
+ } else if (pathMatch) {
638
+ const resolvedPath = resolveStoredPath(pathMatch[1], projectRoot);
639
+ const entry = { mode, path: resolvedPath };
640
+ if (mode === 'remote' && gitUrlMatch) {
641
+ entry.gitUrl = gitUrlMatch[1];
642
+ }
643
+ layout[key] = entry;
644
+ }
645
+ }
646
+ }
647
+
648
+ // Only return if we parsed at least one valid concern
649
+ if (layout.knowledgebase || layout.sprintManagement) {
650
+ // Fill in defaults for any missing section
651
+ if (!layout.knowledgebase) layout.knowledgebase = { mode: 'same', path: '.' };
652
+ if (!layout.sprintManagement) layout.sprintManagement = { mode: 'same', path: '.' };
653
+ return layout;
654
+ }
655
+ }
656
+ } catch (e) {
657
+ console.log(chalk.yellow(` Warning: could not read project-layout.yaml: ${e.message}`));
658
+ }
659
+
660
+ // Fallback: check config.yaml for path fields
661
+ const configPath = path.join(projectRoot, '_bmad', 'bmm', 'config.yaml');
662
+ try {
663
+ if (fs.existsSync(configPath)) {
664
+ const content = fs.readFileSync(configPath, 'utf-8');
665
+ const kbMatch = content.match(/^knowledgebase_path:\s*"?([^"\n]+)"?/m);
666
+ const spMatch = content.match(/^sprint_management_path:\s*"?([^"\n]+)"?/m);
667
+
668
+ const kbPath = kbMatch ? resolveStoredPath(kbMatch[1], projectRoot) : null;
669
+ const spPath = spMatch ? resolveStoredPath(spMatch[1], projectRoot) : null;
670
+
671
+ // Only return if at least one non-default path exists
672
+ if ((kbPath && kbPath !== '.') || (spPath && spPath !== '.')) {
673
+ return {
674
+ knowledgebase: kbPath && kbPath !== '.'
675
+ ? { mode: 'local', path: kbPath }
676
+ : { mode: 'same', path: '.' },
677
+ sprintManagement: spPath && spPath !== '.'
678
+ ? { mode: 'local', path: spPath }
679
+ : { mode: 'same', path: '.' },
680
+ };
681
+ }
682
+ }
683
+ } catch (e) {
684
+ console.log(chalk.yellow(` Warning: could not read config.yaml layout: ${e.message}`));
685
+ }
686
+
687
+ return null;
688
+ }
689
+
690
+ function ciCloneIfNeeded(destPath, gitUrl, clonedRepos) {
691
+ // Deduplicate: same URL + path already cloned
692
+ const key = `${gitUrl}::${destPath}`;
693
+ if (clonedRepos.has(key)) return;
694
+
695
+ if (fs.existsSync(destPath)) {
696
+ if (fs.existsSync(path.join(destPath, '.git'))) {
697
+ console.log(chalk.gray(` Using existing clone at ${destPath}`));
698
+ clonedRepos.set(key, true);
699
+ return;
700
+ }
701
+ throw new Error(`Destination exists but is not a git repo — remove it or use a different path: ${destPath}`);
702
+ }
703
+
704
+ try {
705
+ console.log(chalk.cyan(` Cloning ${gitUrl} ${destPath}`));
706
+ execFileSync('git', ['clone', '--depth', '1', gitUrl, destPath], { stdio: 'pipe' });
707
+ clonedRepos.set(key, true);
708
+ } catch (e) {
709
+ throw new Error(`Failed to clone ${gitUrl}: ${e.message}`);
710
+ }
711
+ }
712
+
713
+ async function collectRepoLayout(flags, existingLayout = null) {
714
+ // CI/CD mode: env vars > existing layout > defaults
715
+ if (flags.yes) {
716
+ const kbPath = process.env.MA_KNOWLEDGEBASE_PATH;
717
+ const sprintPath = process.env.MA_SPRINT_PATH;
718
+ const kbGitUrl = process.env.MA_KNOWLEDGEBASE_GIT_URL;
719
+ const sprintGitUrl = process.env.MA_SPRINT_GIT_URL;
720
+
721
+ // Validate: git URL requires corresponding path
722
+ if (kbGitUrl && !kbPath) {
723
+ throw new Error('MA_KNOWLEDGEBASE_GIT_URL requires MA_KNOWLEDGEBASE_PATH to be set (clone destination)');
724
+ }
725
+ if (sprintGitUrl && !sprintPath) {
726
+ throw new Error('MA_SPRINT_GIT_URL requires MA_SPRINT_PATH to be set (clone destination)');
727
+ }
728
+
729
+ // Env vars take precedence
730
+ if (kbPath || sprintPath || kbGitUrl || sprintGitUrl) {
731
+ const result = { knowledgebase: null, sprintManagement: null };
732
+
733
+ // Track cloned repos to avoid duplicate clones (AC #8)
734
+ const clonedRepos = new Map();
735
+
736
+ for (const [concern, envPath, envGitUrl] of [
737
+ ['knowledgebase', kbPath, kbGitUrl],
738
+ ['sprintManagement', sprintPath, sprintGitUrl],
739
+ ]) {
740
+ if (envGitUrl && envPath) {
741
+ const resolvedPath = path.resolve(envPath);
742
+ // Clone if needed (CI-mode: fail loudly, no fallback)
743
+ ciCloneIfNeeded(resolvedPath, envGitUrl, clonedRepos);
744
+ result[concern] = { mode: 'remote', path: resolvedPath, gitUrl: envGitUrl };
745
+ } else if (envPath) {
746
+ result[concern] = { mode: 'local', path: path.resolve(envPath) };
747
+ } else {
748
+ result[concern] = existingLayout ? existingLayout[concern] : { mode: 'same', path: '.' };
749
+ }
750
+ }
751
+
752
+ return result;
753
+ }
754
+ // No env vars: preserve existing layout if available
755
+ if (existingLayout) {
756
+ return existingLayout;
757
+ }
758
+ // No env vars, no existing layout: default to single-repo
759
+ return {
760
+ knowledgebase: { mode: 'same', path: '.' },
761
+ sprintManagement: { mode: 'same', path: '.' },
762
+ };
763
+ }
764
+
765
+ const layout = { knowledgebase: null, sprintManagement: null };
766
+ const labels = { knowledgebase: 'knowledgebase', sprintManagement: 'sprint management' };
767
+
768
+ for (const concern of ['knowledgebase', 'sprintManagement']) {
769
+ const existingMode = existingLayout && existingLayout[concern] ? existingLayout[concern].mode : null;
770
+ const modeChoices = [
771
+ { title: 'Current repository (default)', value: 'same' },
772
+ { title: 'Local path', value: 'local' },
773
+ { title: 'Remote git repository', value: 'remote' },
774
+ ...(concern === 'sprintManagement' ? [{ title: 'Jira', value: 'jira' }] : []),
775
+ ];
776
+ // Pre-select existing mode if available
777
+ const initialIndex = existingMode ? modeChoices.findIndex(c => c.value === existingMode) : 0;
778
+
779
+ const { mode } = await prompts({
780
+ type: 'select',
781
+ name: 'mode',
782
+ message: `Where is your ${labels[concern]} managed?`,
783
+ choices: modeChoices,
784
+ initial: initialIndex >= 0 ? initialIndex : 0
785
+ });
786
+
787
+ if (!mode) process.exit(0);
788
+
789
+ if (mode === 'same') {
790
+ layout[concern] = { mode: 'same', path: '.' };
791
+ } else if (mode === 'local') {
792
+ layout[concern] = await collectLocalPath(labels[concern]);
793
+ } else if (mode === 'remote') {
794
+ layout[concern] = await collectRemotePath(labels[concern]);
795
+ } else if (mode === 'jira') {
796
+ layout[concern] = await collectJiraConfig();
797
+ }
798
+ }
799
+
800
+ // Check if both concerns point to same external path
801
+ if (layout.knowledgebase.mode !== 'same' && layout.sprintManagement.mode !== 'same'
802
+ && layout.knowledgebase.path === layout.sprintManagement.path) {
803
+ console.log(chalk.cyan(' Both concerns point to same external repository'));
804
+ }
805
+
806
+ return layout;
807
+ }
808
+
809
+ // --- BMad module selection ---
810
+
811
+ /**
812
+ * Resolve which BMAD modules to install for this run.
813
+ *
814
+ * Three branches:
815
+ * 1. `--bmad-modules <csv>` → install exactly those (bmm force-prepended,
816
+ * unknowns rejected with a clear error)
817
+ * 2. `--bmad-modules` bare → multiselect prompt; bmm is required and
818
+ * pre-checked, others default-checked so a no-op confirmation matches
819
+ * the no-flag default
820
+ * 3. (no flag) → install every non-retired module from the
821
+ * cache manifest, no prompt — restores the originally-intended
822
+ * behavior that the hardcoded ['bmm'] literal had been suppressing
823
+ *
824
+ * `bmm` is force-included in every path because the BMad core agents
825
+ * (analyst, PM, dev, architect, ...) live there and downstream skills
826
+ * break without them. Retired modules (currently only `wds`) are filtered
827
+ * out unconditionally.
828
+ */
829
+ async function selectBmadModules({ bmadModulesFlag, bmadModulesPrompt }) {
830
+ const installable = bmad.getInstallableBmadModules().filter(m => !m.retired);
831
+
832
+ // Branch 1: explicit CSV — validate + use as-is.
833
+ if (bmadModulesFlag) {
834
+ const requested = bmadModulesFlag.split(',').map(s => s.trim()).filter(Boolean);
835
+ try {
836
+ return bmad.resolveBmadModules({ requested, available: installable });
837
+ } catch (err) {
838
+ console.error(chalk.red(`Error: ${err.message}`));
839
+ process.exit(1);
840
+ }
841
+ }
842
+
843
+ // Branch 2: bare --bmad-modules → multiselect prompt.
844
+ if (bmadModulesPrompt) {
845
+ const choices = installable.map(m => {
846
+ const isCore = m.id === 'bmm';
847
+ const requiredTag = isCore ? chalk.yellow(' (required)') : '';
848
+ return {
849
+ title: chalk.white(m.id) + requiredTag + chalk.gray(` — ${m.description}`),
850
+ value: m.id,
851
+ // Default-check everything so hitting Enter matches the no-flag
852
+ // "install all" default. Users uncheck what they want to skip.
853
+ selected: true,
854
+ };
855
+ });
856
+
857
+ const { chosenModules } = await prompts({
858
+ type: 'multiselect',
859
+ name: 'chosenModules',
860
+ message: 'Select BMAD-METHOD modules to install:',
861
+ choices,
862
+ instructions: chalk.gray(' Use space to toggle, enter to confirm. bmm is required and will be installed regardless.'),
863
+ min: 1,
864
+ });
865
+
866
+ if (chosenModules === undefined) process.exit(0);
867
+
868
+ // Belt-and-suspenders: force bmm back in if the user managed to uncheck
869
+ // it despite the (required) tag.
870
+ return bmad.resolveBmadModules({ requested: chosenModules, available: installable });
871
+ }
872
+
873
+ // Branch 3: no flag → install everything available.
874
+ return installable.map(m => m.id);
875
+ }
876
+
877
+ // --- Install wizard ---
878
+
879
+ async function installWizard(preselectedSkill, preselectedAgents, customPath, forceFlag, yesFlag = false, cliScope, bmadModulesFlag = '', bmadModulesPrompt = false) {
880
+ const skills = listSkills();
881
+ const agents = listAgents();
882
+
883
+ let selectedSkillIds = preselectedSkill ? [preselectedSkill] : [];
884
+ let selectedAgentIds = preselectedAgents || [];
885
+ let installScope = cliScope || 'project';
886
+ let installPath = customPath || '';
887
+
888
+ const existingStatus = getStatus([], '', 'project');
889
+ let isUpdate = false;
890
+
891
+ // Step 0: Check for existing installation ONLY in interactive mode (no preselected skill)
892
+ if (!preselectedSkill && !customPath && existingStatus.length > 0) {
893
+ if (yesFlag) {
894
+ // Default: clean reinstall (avoids isUpdate path which re-triggers skill selection prompts)
895
+ for (const entry of existingStatus) {
896
+ for (const skillId of Object.keys(entry.skills)) {
897
+ await uninstallSkill(skillId, [entry.agent.id], '', 'project');
898
+ }
899
+ }
900
+ console.log(chalk.gray(' Clean slate prepared.'));
901
+ } else {
902
+ console.log(chalk.cyan('\n Existing installation detected in project.'));
903
+
904
+ const { action } = await prompts({
905
+ type: 'select',
906
+ name: 'action',
907
+ message: 'What would you like to do?',
908
+ choices: [
909
+ { title: 'Update (add/remove skills)', value: 'update' },
910
+ { title: 'Clean reinstall (remove all first)', value: 'reinstall' },
911
+ { title: 'Uninstall all skills', value: 'uninstall' },
912
+ { title: 'Cancel', value: 'cancel' }
913
+ ]
914
+ });
915
+
916
+ if (!action || action === 'cancel') process.exit(0);
917
+
918
+ if (action === 'uninstall') {
919
+ const { confirmed } = await prompts({
920
+ type: 'confirm',
921
+ name: 'confirmed',
922
+ message: 'This will remove all ma-agents skills from this project. Are you sure?',
923
+ initial: false
924
+ });
925
+ if (!confirmed) process.exit(0);
926
+
927
+ for (const entry of existingStatus) {
928
+ for (const skillId of Object.keys(entry.skills)) {
929
+ await uninstallSkill(skillId, [entry.agent.id], '', 'project');
930
+ }
931
+ }
932
+ console.log(chalk.bold.green('\n All skills successfully removed!\n'));
933
+ return;
934
+ }
935
+
936
+ if (action === 'reinstall') {
937
+ for (const entry of existingStatus) {
938
+ for (const skillId of Object.keys(entry.skills)) {
939
+ await uninstallSkill(skillId, [entry.agent.id], '', 'project');
940
+ }
941
+ }
942
+ console.log(chalk.gray(' Clean slate prepared.'));
943
+ }
944
+
945
+ if (action === 'update') {
946
+ isUpdate = true;
947
+ // Pre-populate selections from existing status
948
+ const existingSkillIds = new Set();
949
+ const existingAgentIds = new Set();
950
+ existingStatus.forEach(entry => {
951
+ existingAgentIds.add(entry.agent.id);
952
+ Object.keys(entry.skills).forEach(id => existingSkillIds.add(id));
953
+ });
954
+ selectedSkillIds = Array.from(existingSkillIds);
955
+ selectedAgentIds = Array.from(existingAgentIds);
956
+ }
957
+ }
958
+ }
959
+
960
+ // Step 1: Select skills
961
+ if (yesFlag || selectedSkillIds.length === 0 || isUpdate) {
962
+ if (yesFlag) {
963
+ selectedSkillIds = skills.map(s => s.id);
964
+ } else {
965
+ const { selectionType } = await prompts({
966
+ type: 'select',
967
+ name: 'selectionType',
968
+ message: 'Would you like to install all available skills or choose specific ones?',
969
+ choices: [
970
+ { title: 'Install all available skills', value: 'all' },
971
+ { title: 'Choose which skills to install', value: 'custom' }
972
+ ]
973
+ });
974
+
975
+ if (!selectionType) process.exit(0);
976
+
977
+ if (selectionType === 'all') {
978
+ selectedSkillIds = skills.map(s => s.id);
979
+ } else {
980
+ const { skills: chosen } = await prompts({
981
+ type: 'multiselect',
982
+ name: 'skills',
983
+ message: 'Select the skills you want to have installed:',
984
+ choices: skills.map(s => ({
985
+ title: chalk.white(s.name) + chalk.gray(` v${s.version} - ${s.description}`),
986
+ value: s.id,
987
+ selected: selectedSkillIds.includes(s.id)
988
+ })),
989
+ instructions: chalk.gray(' Use space to select, enter to confirm'),
990
+ min: 1
991
+ });
992
+
993
+ if (!chosen) process.exit(0);
994
+ selectedSkillIds = chosen;
995
+ }
996
+ }
997
+ }
998
+
999
+ // Step 2: Select agents
1000
+ if (yesFlag || selectedAgentIds.length === 0 || isUpdate) {
1001
+ const ideAgents = agents.filter(a => a.category !== 'bmad');
1002
+ const bmadAgents = agents.filter(a => a.category === 'bmad');
1003
+
1004
+ if (yesFlag) {
1005
+ // Bug B1 fix: when --agent flag is present (preselectedAgents already
1006
+ // populated selectedAgentIds), do NOT overwrite with all agents.
1007
+ // Only fall back to all agents when no agent was pre-selected.
1008
+ if (selectedAgentIds.length === 0) {
1009
+ selectedAgentIds = [...ideAgents.map(a => a.id), ...bmadAgents.map(a => a.id)];
1010
+ }
1011
+ if (selectedAgentIds.length === 0) {
1012
+ console.error(chalk.red('Error: No agents detected'));
1013
+ console.error(chalk.gray(' Hint: Ensure at least one supported IDE is present'));
1014
+ process.exit(1);
1015
+ }
1016
+ } else {
1017
+ // 2.1 Coding Assistants
1018
+ const { ideChosen } = await prompts({
1019
+ type: 'multiselect',
1020
+ name: 'ideChosen',
1021
+ message: 'Select AI Coding Assistants:',
1022
+ choices: ideAgents.map(a => ({
1023
+ title: chalk.white(a.name) + chalk.gray(` v${a.version} - ${a.description}`),
1024
+ value: a.id,
1025
+ selected: selectedAgentIds.includes(a.id)
1026
+ })),
1027
+ instructions: chalk.gray(' Use space to select, enter to confirm'),
1028
+ });
1029
+
1030
+ if (ideChosen === undefined) process.exit(0);
1031
+
1032
+ // 2.2 BMAD Method Agents
1033
+ const { bmadChosen } = await prompts({
1034
+ type: 'multiselect',
1035
+ name: 'bmadChosen',
1036
+ message: 'Select BMAD Method Agents:',
1037
+ choices: bmadAgents.map(a => ({
1038
+ title: chalk.white(a.name) + chalk.gray(` v${a.version} - ${a.description}`),
1039
+ value: a.id,
1040
+ selected: selectedAgentIds.includes(a.id)
1041
+ })),
1042
+ instructions: chalk.gray(' Use space to select, enter to confirm'),
1043
+ });
1044
+
1045
+ if (bmadChosen === undefined) process.exit(0);
1046
+
1047
+ selectedAgentIds = [...ideChosen, ...bmadChosen];
1048
+
1049
+ if (selectedAgentIds.length === 0) {
1050
+ console.log(chalk.yellow('No agents selected. Please select at least one agent to install skills.'));
1051
+ process.exit(1);
1052
+ }
1053
+ }
1054
+ }
1055
+
1056
+ // Step 2.4: Profile resolution (Story 21.1, ACs #7–#9)
1057
+ // Must run AFTER agent selection and BEFORE repo layout, so downstream stories
1058
+ // can gate layout-related guidance on profile. setProfile() is called BEFORE
1059
+ // any agent install runs — guaranteeing persistence even if a later step fails.
1060
+ // Profile lives at the project root (cwd), NOT the custom skills-install path.
1061
+ const projectRootForProfile = process.cwd();
1062
+ const persistedProfile = getProfile(projectRootForProfile);
1063
+ let resolvedProfile = resolveProfile({
1064
+ persisted: persistedProfile,
1065
+ yesMode: yesFlag
1066
+ });
1067
+ let profileSource;
1068
+ if (persistedProfile) profileSource = '.ma-agents.json';
1069
+ else if (resolvedProfile === 'standard' && yesFlag) profileSource = '--yes default';
1070
+
1071
+ if (resolvedProfile === null) {
1072
+ const { chosenProfile } = await prompts({
1073
+ type: 'select',
1074
+ name: 'chosenProfile',
1075
+ message: 'Is this an on-prem / air-gapped install using a local LLM (e.g. Nemotron)?',
1076
+ choices: [
1077
+ { title: 'Yes — apply local-LLM guardrails (recommended for non-Claude models)', value: 'on-prem' },
1078
+ { title: 'No — standard install (Claude on web, Anthropic API, etc.)', value: 'standard' }
1079
+ ],
1080
+ initial: 1
1081
+ });
1082
+ if (!chosenProfile) process.exit(0);
1083
+ resolvedProfile = chosenProfile;
1084
+ profileSource = 'interactive prompt';
1085
+ }
1086
+
1087
+ console.log(chalk.cyan(`Using profile: ${resolvedProfile} (from ${profileSource})`));
1088
+
1089
+ // Persist BEFORE any agent install step (AC #9). setProfile bootstraps the
1090
+ // manifest via ensureManifest when absent.
1091
+ setProfile(projectRootForProfile, resolvedProfile);
1092
+
1093
+ // Step 2.5: Repository layout (preserve existing config on update)
1094
+ const existingLayout = isUpdate ? readExistingLayout() : null;
1095
+ const repoLayout = await collectRepoLayout({ yes: yesFlag }, existingLayout);
1096
+
1097
+ // Step 3: Scope (Skip if update, yesFlag, CLI --global flag, or path already set)
1098
+ if (!isUpdate && !installPath && !yesFlag && !cliScope) {
1099
+ const { pathChoice } = await prompts({
1100
+ type: 'select',
1101
+ name: 'pathChoice',
1102
+ message: 'Installation scope:',
1103
+ choices: [
1104
+ { title: 'Project level (current directory)', value: 'project' },
1105
+ { title: 'Global (user-level settings)', value: 'global' },
1106
+ { title: 'Custom path...', value: 'custom' }
1107
+ ]
1108
+ });
1109
+
1110
+ if (pathChoice === 'global') {
1111
+ installScope = 'global';
1112
+ } else if (pathChoice === 'custom') {
1113
+ const { customDir } = await prompts({
1114
+ type: 'text',
1115
+ name: 'customDir',
1116
+ message: 'Enter installation directory:',
1117
+ initial: './skills'
1118
+ });
1119
+ installPath = customDir || '';
1120
+ }
1121
+ }
1122
+
1123
+ // Step 3.4: Filter out BMAD agents for global scope (they require project-level install)
1124
+ if (installScope === 'global') {
1125
+ const bmadAgentIds = selectedAgentIds.filter(id => {
1126
+ const agent = agents.find(a => a.id === id);
1127
+ return agent && agent.category === 'bmad';
1128
+ });
1129
+ if (bmadAgentIds.length > 0) {
1130
+ console.log(chalk.yellow(`\n Warning: BMAD agents require project-level installation and will be skipped for global scope:`));
1131
+ console.log(chalk.yellow(` ${bmadAgentIds.join(', ')}`));
1132
+ console.log(chalk.gray(` Run again without --global to install BMAD agents into the current project.`));
1133
+ selectedAgentIds = selectedAgentIds.filter(id => !bmadAgentIds.includes(id));
1134
+ }
1135
+ }
1136
+
1137
+ // Step 3.5: BMAD-METHOD Integration
1138
+ if (installScope === 'project') {
1139
+ const bmadToolsFilter = agents.filter(a => a.category === 'ide').map(a => a.id);
1140
+
1141
+ if (yesFlag) {
1142
+ // Warn about IDE agents not supported for BMAD customizations
1143
+ const ideAgentIds = agents.filter(a => a.category !== 'bmad').map(a => a.id);
1144
+ const unsupported = selectedAgentIds.filter(id => ideAgentIds.includes(id) && !bmadToolsFilter.includes(id));
1145
+ unsupported.forEach(id => {
1146
+ console.log(chalk.yellow(` Warning: Agent '${id}' is not supported for BMAD customizations`));
1147
+ });
1148
+ }
1149
+
1150
+ const bmadInstalled = bmad.isBmadInstalled();
1151
+ const bmadTools = selectedAgentIds.filter(id => bmadToolsFilter.includes(id)).map(id => getBmadPlatformCode(id));
1152
+ // Story 22.6 ma-agents customizations are now packaged as a BMAD plugin
1153
+ // and installed by bmad-method itself via --custom-source. The separate
1154
+ // `applyCustomizations()` call has been removed; installBmad()/updateBmad()
1155
+ // stage the plugin and invoke the installer in one pass.
1156
+ // v6.6.0: --tools none is rejected for fresh installs; skip BMAD entirely when no IDE tools selected.
1157
+ if (bmadTools.length > 0) {
1158
+ // Resolve module set once per BMAD invocation. Default is "install
1159
+ // every non-retired module"; users opt into a specific subset with
1160
+ // --bmad-modules <csv> or open a multiselect prompt with --bmad-modules
1161
+ // (bare).
1162
+ const bmadModules = await selectBmadModules({
1163
+ bmadModulesFlag,
1164
+ bmadModulesPrompt,
1165
+ });
1166
+
1167
+ if (!bmadInstalled) {
1168
+ if (yesFlag) {
1169
+ console.log(chalk.cyan(`\n Installing BMAD-METHOD (modules: ${bmadModules.join(', ')})...`));
1170
+ const success = await bmad.installBmad(bmadModules, bmadTools);
1171
+ if (success) {
1172
+ console.log(chalk.green(' BMAD-METHOD installed successfully!'));
1173
+ }
1174
+ } else {
1175
+ const { installBmad } = await prompts({
1176
+ type: 'confirm',
1177
+ name: 'installBmad',
1178
+ message: 'BMAD-METHOD not detected. Would you like to install it?',
1179
+ initial: true
1180
+ });
1181
+
1182
+ if (installBmad) {
1183
+ console.log(chalk.cyan(`\n Installing BMAD-METHOD (modules: ${bmadModules.join(', ')})...`));
1184
+ const success = await bmad.installBmad(bmadModules, bmadTools);
1185
+ if (success) {
1186
+ console.log(chalk.green(' BMAD-METHOD installed successfully!'));
1187
+ }
1188
+ }
1189
+ }
1190
+ } else {
1191
+ if (yesFlag) {
1192
+ console.log(chalk.cyan(`\n Updating BMAD-METHOD (modules: ${bmadModules.join(', ')})...`));
1193
+ const success = await bmad.updateBmad(bmadModules, bmadTools);
1194
+ if (success) {
1195
+ console.log(chalk.green(' BMAD-METHOD updated successfully!'));
1196
+ }
1197
+ } else {
1198
+ const { updateBmad } = await prompts({
1199
+ type: 'confirm',
1200
+ name: 'updateBmad',
1201
+ message: 'BMAD-METHOD installation detected. Would you like to update it?',
1202
+ initial: true
1203
+ });
1204
+
1205
+ if (updateBmad) {
1206
+ console.log(chalk.cyan(`\n Updating BMAD-METHOD (modules: ${bmadModules.join(', ')})...`));
1207
+ const success = await bmad.updateBmad(bmadModules, bmadTools);
1208
+ if (success) {
1209
+ console.log(chalk.green(' BMAD-METHOD updated successfully!'));
1210
+ }
1211
+ }
1212
+ }
1213
+ }
1214
+ }
1215
+ }
1216
+
1217
+ // Step 3.6: Write repo layout config (after BMAD install creates config.yaml)
1218
+ if (installScope === 'project') {
1219
+ writeRepoLayoutConfig(repoLayout);
1220
+ writeProjectLayoutYaml(repoLayout);
1221
+ }
1222
+
1223
+ // Step 4: Confirm
1224
+ console.log('');
1225
+ console.log(chalk.bold(' Summary:'));
1226
+ console.log(chalk.cyan(' Skills: ') + selectedSkillIds.join(', '));
1227
+ console.log(chalk.cyan(' Agents: ') + selectedAgentIds.join(', '));
1228
+ console.log(chalk.cyan(' Path: ') + (installPath || (installScope === 'global' ? 'global (user-level)' : 'project (current directory)')));
1229
+ console.log('');
1230
+
1231
+ if (!yesFlag) {
1232
+ const { confirmed } = await prompts({
1233
+ type: 'confirm',
1234
+ name: 'confirmed',
1235
+ message: isUpdate ? 'Apply changes?' : 'Proceed with installation?',
1236
+ initial: true
1237
+ });
1238
+
1239
+ if (!confirmed) {
1240
+ console.log(chalk.yellow('Operation cancelled.'));
1241
+ process.exit(0);
1242
+ }
1243
+ }
1244
+
1245
+ // Step 5: Execution
1246
+ if (isUpdate) {
1247
+ // Build a map: skillId -> set of agent IDs that originally had it installed
1248
+ const originalAgentsBySkill = new Map();
1249
+ const originalAllAgentIds = new Set();
1250
+ existingStatus.forEach(entry => {
1251
+ originalAllAgentIds.add(entry.agent.id);
1252
+ Object.keys(entry.skills).forEach(skillId => {
1253
+ if (!originalAgentsBySkill.has(skillId)) {
1254
+ originalAgentsBySkill.set(skillId, new Set());
1255
+ }
1256
+ originalAgentsBySkill.get(skillId).add(entry.agent.id);
1257
+ });
1258
+ });
1259
+
1260
+ const finalSkills = new Set(selectedSkillIds);
1261
+
1262
+ // Skills to fully remove (deselected from skill list)
1263
+ const toRemove = [...originalAgentsBySkill.keys()].filter(id => !finalSkills.has(id));
1264
+
1265
+ if (toRemove.length > 0) {
1266
+ console.log(chalk.gray(`\n Cleaning up ${toRemove.length} removed skills...`));
1267
+ for (const skillId of toRemove) {
1268
+ // Use the ORIGINAL agent IDs, not the new selection
1269
+ const originalAgents = [...originalAgentsBySkill.get(skillId)];
1270
+ await uninstallSkill(skillId, originalAgents, installPath, 'project');
1271
+ }
1272
+ }
1273
+
1274
+ // Also handle agents that were deselected: uninstall their skills
1275
+ const deselectedAgents = [...originalAllAgentIds].filter(id => !selectedAgentIds.includes(id));
1276
+
1277
+ if (deselectedAgents.length > 0) {
1278
+ console.log(chalk.gray(`\n Removing skills from ${deselectedAgents.length} deselected agents...`));
1279
+ for (const [skillId, agentSet] of originalAgentsBySkill) {
1280
+ const agentsToRemoveFrom = deselectedAgents.filter(id => agentSet.has(id));
1281
+ if (agentsToRemoveFrom.length > 0) {
1282
+ await uninstallSkill(skillId, agentsToRemoveFrom, installPath, 'project');
1283
+ }
1284
+ }
1285
+ }
1286
+ }
1287
+
1288
+ // Story 22.3 — Legacy skill retirement migration (AC 7).
1289
+ // Sweep every agent install path and remove any of the four retired skill IDs
1290
+ // (bmad-init, bmad-agent-qa, bmad-agent-sm, bmad-agent-quick-flow-solo-dev)
1291
+ // from the manifest and the installed skill directories. Idempotent — safe
1292
+ // to run on fresh installs where nothing is retired.
1293
+ try {
1294
+ await migrateRetiredSkills({ scope: installScope, customPath: installPath });
1295
+ } catch (err) {
1296
+ console.log(chalk.yellow(`\n Retired-skill migration skipped: ${err.message}`));
1297
+ }
1298
+
1299
+ // Install requested skills
1300
+ const batchState = {};
1301
+ if (yesFlag) {
1302
+ batchState.globalAction = 'update';
1303
+ }
1304
+ for (const skillId of selectedSkillIds) {
1305
+ try {
1306
+ await installSkill(skillId, selectedAgentIds, installPath, installScope, { force: !!forceFlag, yes: yesFlag, batchState });
1307
+ } catch (error) {
1308
+ console.error(chalk.red(`\n Failed to install ${skillId}:`), error.message);
1309
+ }
1310
+ }
1311
+
1312
+ // Step 6: Update project-context.md with repo layout section (after skills installed project-context.md)
1313
+ if (installScope === 'project') {
1314
+ const outputPath = path.join(process.cwd(), '_bmad-output', 'project-context.md');
1315
+ try {
1316
+ if (fs.existsSync(outputPath)) {
1317
+ const updated = await updateProjectContextRepoLayout(outputPath, repoLayout);
1318
+ if (updated) {
1319
+ console.log(chalk.green(' project-context.md repo layout section updated'));
1320
+ }
1321
+ }
1322
+ } catch (err) {
1323
+ console.log(chalk.yellow(` project-context repo layout update skipped: ${err.message}`));
1324
+ }
1325
+ }
1326
+
1327
+ console.log(chalk.bold.green('\n Done!\n'));
1328
+ }
1329
+
1330
+ // --- Command handlers ---
1331
+
1332
+ async function handleInstall(args) {
1333
+ const { globalFlag, forceFlag, yesFlag, agentFlag, customPath, bmadModulesFlag, bmadModulesPrompt, scope, positional } = parseFlags(args);
1334
+
1335
+ // Task 3.2: Validate agentFlag against known agents
1336
+ if (agentFlag) {
1337
+ const knownAgents = listAgents();
1338
+ const isKnown = knownAgents.some(a => a.id === agentFlag);
1339
+ if (!isKnown) {
1340
+ console.error(chalk.red(`Error: Unknown agent '${agentFlag}'`));
1341
+ console.error(chalk.gray(' Hint: Run "list" to see available agents'));
1342
+ process.exit(1);
1343
+ }
1344
+ }
1345
+
1346
+ const skillId = positional[0];
1347
+ const agentIds = positional.slice(1);
1348
+ const preselectedAgents = agentFlag ? [agentFlag] : null;
1349
+
1350
+ // No skill → launch wizard (Task 3.3, 3.4)
1351
+ if (!skillId) {
1352
+ await installWizard(null, preselectedAgents, customPath, forceFlag, yesFlag, scope, bmadModulesFlag, bmadModulesPrompt);
1353
+ return;
1354
+ }
1355
+
1356
+ // Skill but no agents (and no agentFlag) → wizard with skill preselected
1357
+ if (!agentFlag && agentIds.length === 0) {
1358
+ await installWizard(skillId, null, customPath, forceFlag, yesFlag, scope, bmadModulesFlag, bmadModulesPrompt);
1359
+ return;
1360
+ }
1361
+
1362
+ // Direct install path — Story 21.1 AC #9, #11: resolve + persist profile BEFORE install.
1363
+ // Profile lives at the project root (cwd), not the custom skills-install path.
1364
+ // When stdin is not a TTY and nothing is resolvable, default to 'standard' (same
1365
+ // behavior as --yes) rather than aborting — keeps CI/CD direct installs working.
1366
+ const projectRootForProfile = process.cwd();
1367
+ const persistedProfile = getProfile(projectRootForProfile);
1368
+ let resolvedProfile = resolveProfile({
1369
+ persisted: persistedProfile,
1370
+ yesMode: yesFlag
1371
+ });
1372
+ let profileSource;
1373
+ if (persistedProfile) profileSource = '.ma-agents.json';
1374
+ else if (resolvedProfile === 'standard' && yesFlag) profileSource = '--yes default';
1375
+
1376
+ if (resolvedProfile === null) {
1377
+ if (!process.stdin.isTTY) {
1378
+ // Non-interactive fallback: default to 'standard' and persist (mirrors --yes).
1379
+ resolvedProfile = 'standard';
1380
+ profileSource = '--yes default';
1381
+ } else {
1382
+ const { chosenProfile } = await prompts({
1383
+ type: 'select',
1384
+ name: 'chosenProfile',
1385
+ message: 'Is this an on-prem / air-gapped install using a local LLM (e.g. Nemotron)?',
1386
+ choices: [
1387
+ { title: 'Yes — apply local-LLM guardrails (recommended for non-Claude models)', value: 'on-prem' },
1388
+ { title: 'No standard install (Claude on web, Anthropic API, etc.)', value: 'standard' }
1389
+ ],
1390
+ initial: 1
1391
+ });
1392
+ if (!chosenProfile) process.exit(0);
1393
+ resolvedProfile = chosenProfile;
1394
+ profileSource = 'interactive prompt';
1395
+ }
1396
+ }
1397
+
1398
+ console.log(chalk.cyan(`Using profile: ${resolvedProfile} (from ${profileSource})`));
1399
+ setProfile(projectRootForProfile, resolvedProfile);
1400
+
1401
+ // Full args → direct install (Task 3.5)
1402
+ const targetAgents = agentFlag ? [agentFlag] : agentIds;
1403
+
1404
+ // Story 22.3 (AC 7) — sweep retired legacy skills before installing.
1405
+ // When a customPath is given we narrow the sweep to that single path;
1406
+ // otherwise migrateRetiredSkills sweeps every registered agent under the
1407
+ // current scope (the retirement is agent-agnostic, so broader sweep is
1408
+ // the intended behavior even when --agent restricts the install to one).
1409
+ try {
1410
+ await migrateRetiredSkills({ scope, customPath: customPath || '' });
1411
+ } catch (err) {
1412
+ console.log(chalk.yellow(`\n Retired-skill migration skipped: ${err.message}`));
1413
+ }
1414
+
1415
+ try {
1416
+ await installSkill(skillId, targetAgents, customPath, scope, { force: forceFlag, yes: yesFlag });
1417
+ console.log(chalk.bold.green('\n Installation complete!\n'));
1418
+ } catch (error) {
1419
+ console.error(chalk.red('\n Installation failed:'), error.message);
1420
+ process.exit(1);
1421
+ }
1422
+ }
1423
+
1424
+ async function handleUninstall(args) {
1425
+ // Story 21.11 — if --profile-artifacts flag is present, route to uninstallProfileArtifacts.
1426
+ // --yes IS supported for profile-artifact uninstall (CI decommissioning use-case).
1427
+ // This is an intentional asymmetry vs. `reconfigure` which REJECTS --yes.
1428
+ if (args.includes('--profile-artifacts')) {
1429
+ const yesFlag = args.includes('--yes');
1430
+ try {
1431
+ await uninstallProfileArtifacts(process.cwd(), { yes: yesFlag });
1432
+ } catch (error) {
1433
+ console.error(chalk.red('\n Profile artifact uninstall failed:'), error.message);
1434
+ process.exit(1);
1435
+ }
1436
+ return;
1437
+ }
1438
+
1439
+ const { globalFlag, customPath, scope, positional } = parseFlags(args);
1440
+
1441
+ const skillId = positional[0];
1442
+ const agentIds = positional.slice(1);
1443
+
1444
+ if (!skillId) {
1445
+ console.error(chalk.red('Usage: npx ma-agents uninstall <skill> <agents...>'));
1446
+ process.exit(1);
1447
+ }
1448
+
1449
+ if (agentIds.length === 0) {
1450
+ console.error(chalk.red('Please specify at least one agent. Run "npx ma-agents agents" to see options.'));
1451
+ process.exit(1);
1452
+ }
1453
+
1454
+ try {
1455
+ await uninstallSkill(skillId, agentIds, customPath, scope);
1456
+ console.log(chalk.bold.green('\n Uninstall complete!\n'));
1457
+ } catch (error) {
1458
+ console.error(chalk.red('\n Uninstall failed:'), error.message);
1459
+ process.exit(1);
1460
+ }
1461
+ }
1462
+
1463
+ // --- Config layout command ---
1464
+
1465
+ function showCurrentLayout() {
1466
+ const layout = readExistingLayout();
1467
+ if (!layout) {
1468
+ console.log(chalk.cyan('\n Single-repo layout (default)'));
1469
+ console.log(chalk.gray(' Knowledgebase: . (current repository)'));
1470
+ console.log(chalk.gray(' Sprint management: . (current repository)'));
1471
+ return;
1472
+ }
1473
+
1474
+ console.log(chalk.bold.cyan('\n Current Repository Layout:\n'));
1475
+ for (const [label, key] of [['Knowledgebase', 'knowledgebase'], ['Sprint Management', 'sprintManagement']]) {
1476
+ const concern = layout[key];
1477
+ console.log(chalk.white(` ${label}:`));
1478
+ console.log(chalk.gray(` Mode: ${concern.mode}`));
1479
+ console.log(chalk.gray(` Path: ${concern.path}`));
1480
+ if (concern.gitUrl) {
1481
+ console.log(chalk.gray(` Git URL: ${concern.gitUrl}`));
1482
+ }
1483
+ }
1484
+ console.log('');
1485
+ }
1486
+
1487
+ async function handleConfigLayout(args) {
1488
+ const { yesFlag } = parseFlags(args);
1489
+ const showOnly = args.includes('--show');
1490
+
1491
+ if (showOnly) {
1492
+ showCurrentLayout();
1493
+ return;
1494
+ }
1495
+
1496
+ // Show current before reconfiguring
1497
+ showCurrentLayout();
1498
+
1499
+ // Read existing and present pre-populated wizard
1500
+ const existingLayout = readExistingLayout();
1501
+ const newLayout = await collectRepoLayout({ yes: yesFlag }, existingLayout);
1502
+
1503
+ // Write updated config
1504
+ writeRepoLayoutConfig(newLayout);
1505
+ writeProjectLayoutYaml(newLayout);
1506
+
1507
+ // Update project-context.md
1508
+ const outputPath = path.join(process.cwd(), '_bmad-output', 'project-context.md');
1509
+ try {
1510
+ if (fs.existsSync(outputPath)) {
1511
+ const updated = await updateProjectContextRepoLayout(outputPath, newLayout);
1512
+ if (updated) {
1513
+ console.log(chalk.green(' project-context.md repo layout section updated'));
1514
+ }
1515
+ }
1516
+ } catch (err) {
1517
+ console.log(chalk.yellow(` project-context repo layout update skipped: ${err.message}`));
1518
+ }
1519
+
1520
+ console.log(chalk.bold.green('\n Layout reconfigured!\n'));
1521
+ }
1522
+
1523
+ // --- Profile reconfigure (Story 21.10) ---
1524
+ async function handleReconfigure(args) {
1525
+ try {
1526
+ await runReconfigure({ projectRoot: process.cwd(), argv: args });
1527
+ } catch (err) {
1528
+ if (err instanceof ReconfigureYesRejectedError) {
1529
+ console.error(chalk.red(err.message));
1530
+ process.exit(1);
1531
+ }
1532
+ if (err instanceof ManifestNotFoundError) {
1533
+ console.error(chalk.red(err.message));
1534
+ console.error(chalk.gray(' Hint: run `npx ma-agents install` before `reconfigure`.'));
1535
+ process.exit(1);
1536
+ }
1537
+ if (err instanceof RoomodesSlugDivergenceError) {
1538
+ console.error(chalk.red(err.message));
1539
+ process.exit(1);
1540
+ }
1541
+ if (err && err.name === 'ClinerulesDualFileDriftError') {
1542
+ console.error(chalk.red(err.message));
1543
+ process.exit(1);
1544
+ }
1545
+ throw err;
1546
+ }
1547
+ }
1548
+
1549
+ // --- Interactive mode ---
1550
+
1551
+ async function interactiveMode() {
1552
+ console.log(chalk.bold.cyan(`\n ${NAME} v${VERSION}\n`));
1553
+
1554
+ const { action } = await prompts({
1555
+ type: 'select',
1556
+ name: 'action',
1557
+ message: 'What would you like to do?',
1558
+ choices: [
1559
+ { title: 'Install skills', value: 'install' },
1560
+ { title: 'Show installed skills', value: 'status' },
1561
+ { title: 'List available skills', value: 'list-skills' },
1562
+ { title: 'List supported agents', value: 'list-agents' },
1563
+ { title: 'Exit', value: 'exit' }
1564
+ ]
1565
+ });
1566
+
1567
+ if (!action || action === 'exit') {
1568
+ console.log(chalk.yellow('Goodbye!'));
1569
+ process.exit(0);
1570
+ }
1571
+
1572
+ if (action === 'status') {
1573
+ showStatus([]);
1574
+ process.exit(0);
1575
+ }
1576
+
1577
+ if (action === 'list-skills') {
1578
+ showSkills();
1579
+ process.exit(0);
1580
+ }
1581
+
1582
+ if (action === 'list-agents') {
1583
+ showAgents();
1584
+ process.exit(0);
1585
+ }
1586
+
1587
+ if (action === 'install') {
1588
+ await installWizard();
1589
+ }
1590
+ }
1591
+
1592
+ // --- Main ---
1593
+
1594
+ async function main() {
1595
+ const args = process.argv.slice(2);
1596
+
1597
+ // Handle --log flag globally (before command routing)
1598
+ let cleanupLog = null;
1599
+ const logIdx = args.indexOf('--log');
1600
+ if (logIdx !== -1) {
1601
+ const ts = new Date().toISOString().replace(/[:.]/g, '-').replace('T', '_').replace('Z', '');
1602
+ const logFile = `install_${ts}.log`;
1603
+ cleanupLog = setupLogging(logFile);
1604
+ console.log(chalk.gray(` Logging to ${logFile}`));
1605
+ args.splice(logIdx, 1);
1606
+ }
1607
+
1608
+ const command = args[0];
1609
+
1610
+ switch (command) {
1611
+ case 'install':
1612
+ await handleInstall(args.slice(1));
1613
+ break;
1614
+ case 'uninstall':
1615
+ case 'remove':
1616
+ await handleUninstall(args.slice(1));
1617
+ break;
1618
+ case 'status':
1619
+ showStatus(args.slice(1));
1620
+ break;
1621
+ case 'list':
1622
+ case 'list-skills':
1623
+ showSkills(args.slice(1));
1624
+ break;
1625
+ case 'agents':
1626
+ case 'list-agents':
1627
+ showAgents();
1628
+ break;
1629
+ case 'create-skill':
1630
+ await handleCreateSkill(args.slice(1));
1631
+ break;
1632
+ case 'validate-skill':
1633
+ await handleValidateSkill(args.slice(1));
1634
+ break;
1635
+ case 'set-mandatory':
1636
+ await handleSetMandatory(args.slice(1));
1637
+ break;
1638
+ case 'customize-agent':
1639
+ await handleCustomizeAgent(args.slice(1));
1640
+ break;
1641
+ case 'create-agent':
1642
+ await handleCreateAgent(args.slice(1));
1643
+ break;
1644
+ case 'config':
1645
+ if (args[1] === 'layout') {
1646
+ await handleConfigLayout(args.slice(2));
1647
+ } else {
1648
+ console.error(chalk.red(`Unknown config subcommand: ${args[1] || '(none)'}`));
1649
+ console.error(chalk.gray(' Usage: npx ma-agents config layout [--show] [--yes]'));
1650
+ process.exit(1);
1651
+ }
1652
+ break;
1653
+ case 'reconfigure':
1654
+ await handleReconfigure(args.slice(1));
1655
+ break;
1656
+ case 'help':
1657
+ case '--help':
1658
+ case '-h':
1659
+ showHelp();
1660
+ break;
1661
+ case 'version':
1662
+ case '--version':
1663
+ case '-v':
1664
+ console.log(`${NAME} v${VERSION}`);
1665
+ break;
1666
+ default:
1667
+ await interactiveMode();
1668
+ break;
1669
+ }
1670
+
1671
+ if (cleanupLog) cleanupLog();
1672
+ }
1673
+
1674
+ if (require.main === module) {
1675
+ main().catch(error => {
1676
+ console.error(chalk.red('Error:'), error);
1677
+ process.exit(1);
1678
+ });
1679
+ }
1680
+
1681
+ module.exports = { parseFlags, collectRepoLayout, readExistingLayout, writeRepoLayoutConfig, writeProjectLayoutYaml, writeConfigField, normalizePath, toPortablePath, resolveStoredPath, ciCloneIfNeeded, showCurrentLayout, handleConfigLayout, yamlEscapeValue };