bmad-method 6.0.0-alpha.15 → 6.0.0-alpha.17

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 (512) hide show
  1. package/.coderabbit.yaml +8 -4
  2. package/.github/scripts/discord-helpers.sh +21 -2
  3. package/.github/workflows/discord.yaml +31 -7
  4. package/.github/workflows/manual-release.yaml +12 -42
  5. package/.markdownlint-cli2.yaml +2 -2
  6. package/.prettierignore +2 -2
  7. package/.vscode/settings.json +1 -1
  8. package/CHANGELOG.md +126 -1
  9. package/LICENSE +1 -1
  10. package/README.md +29 -2
  11. package/docs/agent-customization-guide.md +10 -10
  12. package/docs/custom-content-installation.md +100 -196
  13. package/docs/custom-content.md +122 -0
  14. package/docs/ide-info/crush.md +1 -1
  15. package/docs/ide-info/cursor.md +7 -7
  16. package/docs/ide-info/iflow.md +3 -3
  17. package/docs/ide-info/opencode.md +1 -1
  18. package/docs/ide-info/rovo-dev.md +1 -1
  19. package/docs/index.md +2 -2
  20. package/docs/installers-bundlers/ide-injections.md +2 -2
  21. package/docs/installers-bundlers/installers-modules-platforms-reference.md +25 -25
  22. package/docs/sample-custom-modules/README.md +11 -0
  23. package/docs/sample-custom-modules/sample-unitary-module/README.md +8 -0
  24. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/agents/commit-poet/commit-poet.agent.yaml +1 -1
  25. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/agents/toolsmith/toolsmith.agent.yaml +14 -14
  26. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/module.yaml +5 -1
  27. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/steps/step-01-init.md +2 -2
  28. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/steps/step-02-q1.md +1 -1
  29. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/steps/step-03-q2.md +1 -1
  30. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/steps/step-04-q3.md +1 -1
  31. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/steps/step-05-q4.md +1 -1
  32. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/steps/step-06-q5.md +1 -1
  33. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/steps/step-07-q6.md +1 -1
  34. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/steps/step-08-q7.md +1 -1
  35. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/steps/step-09-q8.md +1 -1
  36. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/steps/step-10-q9.md +1 -1
  37. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/steps/step-11-q10.md +1 -1
  38. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/steps/step-12-results.md +1 -1
  39. package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/workflow.md +1 -1
  40. package/docs/sample-custom-modules/sample-wellness-module/README.md +6 -0
  41. package/{example-custom-module/mwm → docs/sample-custom-modules/sample-wellness-module}/agents/meditation-guide.agent.yaml +37 -39
  42. package/docs/sample-custom-modules/sample-wellness-module/agents/wellness-companion/foo.md +3 -0
  43. package/docs/sample-custom-modules/sample-wellness-module/agents/wellness-companion/wellness-companion-sidecar/addition1.md +1 -0
  44. package/{example-custom-module/mwm → docs/sample-custom-modules/sample-wellness-module}/agents/wellness-companion/wellness-companion.agent.yaml +8 -13
  45. package/docs/sample-custom-modules/sample-wellness-module/module.yaml +17 -0
  46. package/{example-custom-module/mwm → docs/sample-custom-modules/sample-wellness-module}/workflows/wellness-journal/workflow.md +3 -3
  47. package/docs/v4-to-v6-upgrade.md +27 -27
  48. package/docs/web-bundles-gemini-gpt-guide.md +6 -458
  49. package/eslint.config.mjs +2 -2
  50. package/package.json +1 -1
  51. package/src/core/agents/bmad-master.agent.yaml +6 -11
  52. package/src/core/module.yaml +10 -24
  53. package/src/core/resources/excalidraw/README.md +6 -6
  54. package/src/core/tasks/advanced-elicitation.xml +3 -3
  55. package/src/core/tasks/index-docs.xml +1 -1
  56. package/src/core/tasks/validate-workflow.xml +1 -1
  57. package/src/core/tasks/workflow.xml +4 -4
  58. package/src/core/tools/shard-doc.xml +12 -12
  59. package/src/core/workflows/brainstorming/workflow.md +3 -3
  60. package/src/core/workflows/party-mode/steps/step-01-agent-loading.md +2 -2
  61. package/src/core/workflows/party-mode/workflow.md +4 -4
  62. package/src/modules/bmb/agents/bmad-builder.agent.yaml +15 -15
  63. package/src/modules/bmb/{README.md → docs/README.md} +15 -27
  64. package/src/modules/bmb/docs/agents/agent-compilation.md +3 -3
  65. package/src/modules/bmb/docs/agents/agent-menu-patterns.md +23 -24
  66. package/src/modules/bmb/docs/agents/expert-agent-architecture.md +21 -22
  67. package/src/modules/bmb/docs/agents/index.md +1 -1
  68. package/src/modules/bmb/docs/agents/simple-agent-architecture.md +17 -52
  69. package/src/modules/bmb/docs/agents/understanding-agent-types.md +6 -6
  70. package/src/modules/bmb/docs/workflows/architecture.md +1 -1
  71. package/src/modules/bmb/docs/workflows/common-workflow-tools.csv +3 -3
  72. package/src/modules/bmb/docs/workflows/templates/step-01-init-continuable-template.md +1 -1
  73. package/src/modules/bmb/docs/workflows/templates/step-1b-template.md +1 -1
  74. package/src/modules/bmb/docs/workflows/templates/step-file.md +3 -3
  75. package/src/modules/bmb/docs/workflows/templates/step-template.md +3 -3
  76. package/src/modules/bmb/docs/workflows/templates/workflow-template.md +2 -2
  77. package/src/modules/bmb/docs/workflows/templates/workflow.md +1 -1
  78. package/src/modules/bmb/module.yaml +6 -16
  79. package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/journal-keeper.agent.yaml +7 -7
  80. package/src/modules/bmb/reference/agents/module-examples/README.md +3 -4
  81. package/src/modules/bmb/reference/agents/module-examples/security-engineer.agent.yaml +5 -5
  82. package/src/modules/bmb/reference/agents/module-examples/trend-analyst.agent.yaml +7 -7
  83. package/src/modules/bmb/reference/agents/simple-examples/README.md +1 -1
  84. package/src/modules/bmb/reference/agents/simple-examples/commit-poet.agent.yaml +1 -1
  85. package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-01-init.md +1 -1
  86. package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-01b-continue.md +1 -1
  87. package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-02-profile.md +3 -3
  88. package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-03-assessment.md +3 -3
  89. package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-04-strategy.md +5 -5
  90. package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-05-shopping.md +5 -5
  91. package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-06-prep-schedule.md +5 -5
  92. package/src/modules/bmb/reference/workflows/meal-prep-nutrition/workflow.md +2 -2
  93. package/src/modules/bmb/workflows/create-agent/data/reference/agents/module-examples/README.md +1 -3
  94. package/src/modules/bmb/workflows/create-agent/data/reference/agents/module-examples/security-engineer.agent.yaml +6 -6
  95. package/src/modules/bmb/workflows/create-agent/data/reference/agents/module-examples/trend-analyst.agent.yaml +7 -7
  96. package/src/modules/bmb/workflows/create-agent/data/reference/agents/simple-examples/README.md +1 -1
  97. package/src/modules/bmb/workflows/create-agent/data/reference/agents/simple-examples/commit-poet.agent.yaml +1 -1
  98. package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-01-init.md +1 -1
  99. package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-01b-continue.md +1 -1
  100. package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-02-profile.md +3 -3
  101. package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-03-assessment.md +3 -3
  102. package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-04-strategy.md +5 -5
  103. package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-05-shopping.md +5 -5
  104. package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-06-prep-schedule.md +5 -5
  105. package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/workflow.md +2 -2
  106. package/src/modules/bmb/workflows/create-agent/data/validation-complete.md +5 -5
  107. package/src/modules/bmb/workflows/create-agent/steps/step-01-brainstorm.md +5 -5
  108. package/src/modules/bmb/workflows/create-agent/steps/step-02-discover.md +7 -11
  109. package/src/modules/bmb/workflows/create-agent/steps/step-03-persona.md +7 -7
  110. package/src/modules/bmb/workflows/create-agent/steps/step-04-commands.md +10 -10
  111. package/src/modules/bmb/workflows/create-agent/steps/step-05-name.md +7 -6
  112. package/src/modules/bmb/workflows/create-agent/steps/step-06-build.md +20 -58
  113. package/src/modules/bmb/workflows/create-agent/steps/step-07-validate.md +6 -6
  114. package/src/modules/bmb/workflows/create-agent/steps/{step-11-celebrate.md → step-08-celebrate.md} +3 -7
  115. package/src/modules/bmb/workflows/create-agent/templates/agent-plan.template.md +3 -0
  116. package/src/modules/bmb/workflows/create-agent/templates/expert-agent.template.md +364 -0
  117. package/src/modules/bmb/workflows/create-agent/templates/simple-agent.template.md +257 -0
  118. package/src/modules/bmb/workflows/create-agent/workflow.md +2 -35
  119. package/src/modules/bmb/workflows/create-module/steps/step-01-init.md +4 -4
  120. package/src/modules/bmb/workflows/create-module/steps/step-01b-continue.md +2 -2
  121. package/src/modules/bmb/workflows/create-module/steps/step-02-concept.md +5 -5
  122. package/src/modules/bmb/workflows/create-module/steps/step-03-components.md +5 -5
  123. package/src/modules/bmb/workflows/create-module/steps/step-04-structure.md +6 -6
  124. package/src/modules/bmb/workflows/create-module/steps/step-05-config.md +5 -5
  125. package/src/modules/bmb/workflows/create-module/steps/step-06-agents.md +9 -9
  126. package/src/modules/bmb/workflows/create-module/steps/step-07-workflows.md +5 -5
  127. package/src/modules/bmb/workflows/create-module/steps/step-08-installer.md +8 -8
  128. package/src/modules/bmb/workflows/create-module/steps/step-09-documentation.md +7 -7
  129. package/src/modules/bmb/workflows/create-module/steps/step-10-roadmap.md +7 -7
  130. package/src/modules/bmb/workflows/create-module/steps/step-11-validate.md +6 -6
  131. package/src/modules/bmb/workflows/create-module/templates/agent.template.md +15 -19
  132. package/src/modules/bmb/workflows/create-module/templates/module.template.yaml +1 -1
  133. package/src/modules/bmb/workflows/create-module/workflow.md +3 -3
  134. package/src/modules/bmb/workflows/create-workflow/steps/step-01-init.md +4 -4
  135. package/src/modules/bmb/workflows/create-workflow/steps/step-02-gather.md +6 -6
  136. package/src/modules/bmb/workflows/create-workflow/steps/step-03-tools-configuration.md +5 -5
  137. package/src/modules/bmb/workflows/create-workflow/steps/step-04-plan-review.md +4 -4
  138. package/src/modules/bmb/workflows/create-workflow/steps/step-05-output-format-design.md +4 -4
  139. package/src/modules/bmb/workflows/create-workflow/steps/step-06-design.md +11 -11
  140. package/src/modules/bmb/workflows/create-workflow/steps/step-07-build.md +14 -14
  141. package/src/modules/bmb/workflows/create-workflow/steps/step-08-review.md +4 -4
  142. package/src/modules/bmb/workflows/create-workflow/steps/step-09-complete.md +2 -2
  143. package/src/modules/bmb/workflows/create-workflow/workflow.md +2 -2
  144. package/src/modules/bmb/workflows/edit-agent/steps/step-01-discover-intent.md +3 -3
  145. package/src/modules/bmb/workflows/edit-agent/steps/step-02-analyze-agent.md +13 -13
  146. package/src/modules/bmb/workflows/edit-agent/steps/step-03-propose-changes.md +5 -5
  147. package/src/modules/bmb/workflows/edit-agent/steps/step-04-apply-changes.md +3 -3
  148. package/src/modules/bmb/workflows/edit-agent/steps/step-05-validate.md +5 -5
  149. package/src/modules/bmb/workflows/edit-agent/workflow.md +1 -1
  150. package/src/modules/bmb/workflows/edit-workflow/steps/step-01-analyze.md +4 -4
  151. package/src/modules/bmb/workflows/edit-workflow/steps/step-02-discover.md +3 -3
  152. package/src/modules/bmb/workflows/edit-workflow/steps/step-03-improve.md +6 -6
  153. package/src/modules/bmb/workflows/edit-workflow/steps/step-04-validate.md +3 -3
  154. package/src/modules/bmb/workflows/edit-workflow/steps/step-05-compliance-check.md +3 -3
  155. package/src/modules/bmb/workflows/edit-workflow/workflow.md +1 -1
  156. package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-01-validate-goal.md +3 -3
  157. package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-02-workflow-validation.md +5 -5
  158. package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-03-step-validation.md +6 -6
  159. package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-04-file-validation.md +4 -4
  160. package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-05-intent-spectrum-validation.md +4 -4
  161. package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-06-web-subprocess-validation.md +4 -4
  162. package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-07-holistic-analysis.md +4 -4
  163. package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-08-generate-report.md +3 -3
  164. package/src/modules/bmb/workflows/workflow-compliance-check/workflow.md +1 -1
  165. package/src/modules/bmb/workflows-legacy/edit-module/README.md +1 -17
  166. package/src/modules/bmb/workflows-legacy/edit-module/checklist.md +3 -4
  167. package/src/modules/bmb/workflows-legacy/edit-module/instructions.md +4 -5
  168. package/src/modules/bmb/workflows-legacy/edit-module/workflow.yaml +10 -10
  169. package/src/modules/bmb/workflows-legacy/module-brief/README.md +2 -2
  170. package/src/modules/bmb/workflows-legacy/module-brief/instructions.md +2 -2
  171. package/src/modules/bmb/workflows-legacy/module-brief/workflow.yaml +4 -4
  172. package/src/modules/bmgd/README.md +1 -1
  173. package/src/modules/bmgd/agents/game-architect.agent.yaml +6 -6
  174. package/src/modules/bmgd/agents/game-designer.agent.yaml +7 -7
  175. package/src/modules/bmgd/agents/game-dev.agent.yaml +10 -10
  176. package/src/modules/bmgd/agents/game-scrum-master.agent.yaml +21 -21
  177. package/src/modules/bmgd/module.yaml +2 -8
  178. package/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/instructions.md +1 -1
  179. package/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/workflow.yaml +9 -9
  180. package/src/modules/bmgd/workflows/1-preproduction/game-brief/instructions.md +1 -1
  181. package/src/modules/bmgd/workflows/1-preproduction/game-brief/workflow.yaml +8 -8
  182. package/src/modules/bmgd/workflows/2-design/gdd/instructions-gdd.md +4 -4
  183. package/src/modules/bmgd/workflows/2-design/gdd/workflow.yaml +30 -30
  184. package/src/modules/bmgd/workflows/2-design/narrative/instructions-narrative.md +1 -1
  185. package/src/modules/bmgd/workflows/2-design/narrative/workflow.yaml +5 -5
  186. package/src/modules/bmgd/workflows/3-technical/game-architecture/instructions.md +1 -1
  187. package/src/modules/bmgd/workflows/3-technical/game-architecture/workflow.yaml +2 -2
  188. package/src/modules/bmgd/workflows/4-production/code-review/instructions.md +4 -4
  189. package/src/modules/bmgd/workflows/4-production/code-review/workflow.yaml +2 -2
  190. package/src/modules/bmgd/workflows/4-production/correct-course/checklist.md +1 -1
  191. package/src/modules/bmgd/workflows/4-production/correct-course/instructions.md +2 -2
  192. package/src/modules/bmgd/workflows/4-production/correct-course/workflow.yaml +2 -2
  193. package/src/modules/bmgd/workflows/4-production/create-story/instructions.md +2 -2
  194. package/src/modules/bmgd/workflows/4-production/create-story/workflow.yaml +2 -2
  195. package/src/modules/bmgd/workflows/4-production/dev-story/instructions.md +2 -2
  196. package/src/modules/bmgd/workflows/4-production/dev-story/workflow.yaml +2 -2
  197. package/src/modules/bmgd/workflows/4-production/epic-tech-context/checklist.md +1 -1
  198. package/src/modules/bmgd/workflows/4-production/epic-tech-context/instructions.md +2 -2
  199. package/src/modules/bmgd/workflows/4-production/epic-tech-context/workflow.yaml +2 -2
  200. package/src/modules/bmgd/workflows/4-production/retrospective/instructions.md +2 -2
  201. package/src/modules/bmgd/workflows/4-production/retrospective/workflow.yaml +3 -3
  202. package/src/modules/bmgd/workflows/4-production/sprint-planning/instructions.md +2 -2
  203. package/src/modules/bmgd/workflows/4-production/sprint-planning/workflow.yaml +2 -2
  204. package/src/modules/bmgd/workflows/4-production/story-context/checklist.md +1 -1
  205. package/src/modules/bmgd/workflows/4-production/story-context/context-template.xml +2 -2
  206. package/src/modules/bmgd/workflows/4-production/story-context/instructions.md +2 -2
  207. package/src/modules/bmgd/workflows/4-production/story-context/workflow.yaml +2 -2
  208. package/src/modules/bmgd/workflows/4-production/story-done/instructions.md +1 -1
  209. package/src/modules/bmgd/workflows/4-production/story-done/workflow.yaml +2 -2
  210. package/src/modules/bmgd/workflows/4-production/story-ready/instructions.md +1 -1
  211. package/src/modules/bmgd/workflows/4-production/story-ready/workflow.yaml +2 -2
  212. package/src/modules/bmm/README.md +1 -1
  213. package/src/modules/bmm/agents/analyst.agent.yaml +9 -9
  214. package/src/modules/bmm/agents/architect.agent.yaml +8 -8
  215. package/src/modules/bmm/agents/dev.agent.yaml +5 -5
  216. package/src/modules/bmm/agents/pm.agent.yaml +8 -8
  217. package/src/modules/bmm/agents/quick-flow-solo-dev.agent.yaml +5 -5
  218. package/src/modules/bmm/agents/sm.agent.yaml +11 -11
  219. package/src/modules/bmm/agents/tea.agent.yaml +13 -13
  220. package/src/modules/bmm/agents/tech-writer.agent.yaml +9 -9
  221. package/src/modules/bmm/agents/ux-designer.agent.yaml +6 -6
  222. package/src/modules/bmm/docs/README.md +0 -25
  223. package/src/modules/bmm/docs/agents-guide.md +16 -14
  224. package/src/modules/bmm/docs/brownfield-guide.md +6 -6
  225. package/src/modules/bmm/docs/enterprise-agentic-development.md +3 -3
  226. package/src/modules/bmm/docs/faq.md +5 -18
  227. package/src/modules/bmm/docs/glossary.md +3 -4
  228. package/src/modules/bmm/docs/images/README.md +1 -1
  229. package/src/modules/bmm/docs/images/workflow-method-greenfield.excalidraw +8 -8
  230. package/src/modules/bmm/docs/party-mode.md +3 -3
  231. package/src/modules/bmm/docs/quick-flow-solo-dev.md +5 -5
  232. package/src/modules/bmm/docs/quick-spec-flow.md +2 -16
  233. package/src/modules/bmm/docs/quick-start.md +3 -3
  234. package/src/modules/bmm/docs/test-architecture.md +15 -23
  235. package/src/modules/bmm/docs/troubleshooting.md +6 -25
  236. package/src/modules/bmm/docs/workflow-document-project-reference.md +1 -1
  237. package/src/modules/bmm/docs/workflows-implementation.md +3 -104
  238. package/src/modules/bmm/module.yaml +25 -24
  239. package/src/modules/bmm/testarch/knowledge/overview.md +0 -1
  240. package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-01-init.md +1 -1
  241. package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-01b-continue.md +1 -1
  242. package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-02-vision.md +3 -3
  243. package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-03-users.md +3 -3
  244. package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-04-metrics.md +3 -3
  245. package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-05-scope.md +3 -3
  246. package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-06-complete.md +5 -3
  247. package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/workflow.md +2 -2
  248. package/src/modules/bmm/workflows/1-analysis/research/workflow.md +2 -2
  249. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +4 -4
  250. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +4 -4
  251. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +4 -4
  252. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +4 -4
  253. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +4 -4
  254. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +4 -4
  255. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +4 -4
  256. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +4 -4
  257. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +4 -4
  258. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +4 -4
  259. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +4 -4
  260. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +4 -4
  261. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md +2 -2
  262. package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-01-init.md +1 -1
  263. package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-01b-continue.md +1 -1
  264. package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-02-discovery.md +3 -3
  265. package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-03-success.md +7 -7
  266. package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-04-journeys.md +8 -8
  267. package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-05-domain.md +12 -12
  268. package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-06-innovation.md +12 -12
  269. package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-07-project-type.md +10 -10
  270. package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-08-scoping.md +7 -7
  271. package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-09-functional.md +9 -9
  272. package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-10-nonfunctional.md +9 -9
  273. package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-11-complete.md +1 -1
  274. package/src/modules/bmm/workflows/2-plan-workflows/prd/workflow.md +2 -2
  275. package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/steps/step-01-document-discovery.md +1 -1
  276. package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/steps/step-02-prd-analysis.md +1 -1
  277. package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/steps/step-03-epic-coverage-validation.md +6 -6
  278. package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/steps/step-04-ux-alignment.md +1 -1
  279. package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/steps/step-05-epic-quality-review.md +2 -2
  280. package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/steps/step-06-final-assessment.md +1 -1
  281. package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/workflow.md +1 -1
  282. package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-01-init.md +1 -1
  283. package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-02-context.md +4 -4
  284. package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-03-starter.md +4 -4
  285. package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-04-decisions.md +4 -4
  286. package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-05-patterns.md +4 -4
  287. package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-06-structure.md +4 -4
  288. package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-07-validation.md +4 -4
  289. package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-08-complete.md +3 -3
  290. package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/workflow.md +2 -2
  291. package/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md +3 -3
  292. package/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +3 -3
  293. package/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +3 -3
  294. package/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +3 -3
  295. package/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md +3 -3
  296. package/src/modules/bmm/workflows/4-implementation/code-review/instructions.xml +4 -3
  297. package/src/modules/bmm/workflows/4-implementation/code-review/workflow.yaml +2 -2
  298. package/src/modules/bmm/workflows/4-implementation/correct-course/checklist.md +1 -1
  299. package/src/modules/bmm/workflows/4-implementation/correct-course/instructions.md +2 -2
  300. package/src/modules/bmm/workflows/4-implementation/correct-course/workflow.yaml +2 -2
  301. package/src/modules/bmm/workflows/4-implementation/create-story/checklist.md +2 -2
  302. package/src/modules/bmm/workflows/4-implementation/create-story/instructions.xml +5 -5
  303. package/src/modules/bmm/workflows/4-implementation/create-story/template.md +3 -5
  304. package/src/modules/bmm/workflows/4-implementation/create-story/workflow.yaml +2 -2
  305. package/src/modules/bmm/workflows/4-implementation/dev-story/checklist.md +2 -2
  306. package/src/modules/bmm/workflows/4-implementation/dev-story/instructions.xml +11 -8
  307. package/src/modules/bmm/workflows/4-implementation/dev-story/workflow.yaml +2 -2
  308. package/src/modules/bmm/workflows/4-implementation/retrospective/instructions.md +3 -3
  309. package/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml +3 -3
  310. package/src/modules/bmm/workflows/4-implementation/sprint-planning/instructions.md +15 -22
  311. package/src/modules/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +4 -5
  312. package/src/modules/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +2 -2
  313. package/src/modules/bmm/workflows/4-implementation/sprint-status/instructions.md +90 -35
  314. package/src/modules/bmm/workflows/4-implementation/sprint-status/workflow.yaml +2 -2
  315. package/src/modules/bmm/workflows/bmad-quick-flow/create-tech-spec/workflow.yaml +5 -5
  316. package/src/modules/bmm/workflows/bmad-quick-flow/quick-dev/workflow.yaml +7 -7
  317. package/src/modules/bmm/workflows/document-project/instructions.md +5 -5
  318. package/src/modules/bmm/workflows/document-project/workflow.yaml +2 -2
  319. package/src/modules/bmm/workflows/document-project/workflows/deep-dive.yaml +5 -5
  320. package/src/modules/bmm/workflows/document-project/workflows/full-scan.yaml +5 -5
  321. package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-dataflow/instructions.md +1 -1
  322. package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-dataflow/workflow.yaml +6 -6
  323. package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-diagram/instructions.md +2 -2
  324. package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-diagram/workflow.yaml +6 -6
  325. package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-flowchart/instructions.md +2 -2
  326. package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-flowchart/workflow.yaml +6 -6
  327. package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-wireframe/instructions.md +1 -1
  328. package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-wireframe/workflow.yaml +6 -6
  329. package/src/modules/bmm/workflows/generate-project-context/steps/step-01-discover.md +2 -2
  330. package/src/modules/bmm/workflows/generate-project-context/steps/step-02-generate.md +3 -3
  331. package/src/modules/bmm/workflows/generate-project-context/steps/step-03-complete.md +2 -2
  332. package/src/modules/bmm/workflows/generate-project-context/workflow.md +5 -5
  333. package/src/modules/bmm/workflows/testarch/atdd/instructions.md +2 -2
  334. package/src/modules/bmm/workflows/testarch/atdd/workflow.yaml +2 -2
  335. package/src/modules/bmm/workflows/testarch/automate/instructions.md +2 -2
  336. package/src/modules/bmm/workflows/testarch/automate/workflow.yaml +2 -2
  337. package/src/modules/bmm/workflows/testarch/ci/instructions.md +1 -1
  338. package/src/modules/bmm/workflows/testarch/ci/workflow.yaml +2 -2
  339. package/src/modules/bmm/workflows/testarch/framework/instructions.md +3 -3
  340. package/src/modules/bmm/workflows/testarch/framework/workflow.yaml +2 -2
  341. package/src/modules/bmm/workflows/testarch/nfr-assess/instructions.md +1 -1
  342. package/src/modules/bmm/workflows/testarch/nfr-assess/workflow.yaml +2 -2
  343. package/src/modules/bmm/workflows/testarch/test-design/instructions.md +3 -3
  344. package/src/modules/bmm/workflows/testarch/test-design/test-design-template.md +1 -1
  345. package/src/modules/bmm/workflows/testarch/test-design/workflow.yaml +10 -4
  346. package/src/modules/bmm/workflows/testarch/test-review/instructions.md +1 -1
  347. package/src/modules/bmm/workflows/testarch/test-review/workflow.yaml +2 -2
  348. package/src/modules/bmm/workflows/testarch/trace/instructions.md +6 -6
  349. package/src/modules/bmm/workflows/testarch/trace/workflow.yaml +2 -2
  350. package/src/modules/bmm/workflows/workflow-status/init/instructions.md +1 -1
  351. package/src/modules/bmm/workflows/workflow-status/init/workflow.yaml +4 -4
  352. package/src/modules/bmm/workflows/workflow-status/instructions.md +3 -3
  353. package/src/modules/bmm/workflows/workflow-status/project-levels.yaml +1 -1
  354. package/src/modules/bmm/workflows/workflow-status/workflow.yaml +2 -2
  355. package/src/modules/cis/agents/brainstorming-coach.agent.yaml +4 -4
  356. package/src/modules/cis/agents/creative-problem-solver.agent.yaml +4 -4
  357. package/src/modules/cis/agents/design-thinking-coach.agent.yaml +4 -4
  358. package/src/modules/cis/agents/innovation-strategist.agent.yaml +4 -4
  359. package/src/modules/cis/agents/presentation-master.agent.yaml +3 -3
  360. package/src/modules/cis/agents/storyteller/storyteller-sidecar/stories-told.md +7 -0
  361. package/src/modules/cis/agents/storyteller/storyteller-sidecar/story-preferences.md +7 -0
  362. package/src/modules/cis/agents/{storyteller.agent.yaml → storyteller/storyteller.agent.yaml} +9 -4
  363. package/src/modules/cis/module.yaml +3 -8
  364. package/src/modules/cis/{README.md → readme.md} +1 -1
  365. package/src/modules/cis/workflows/README.md +1 -1
  366. package/src/modules/cis/workflows/design-thinking/instructions.md +2 -2
  367. package/src/modules/cis/workflows/design-thinking/workflow.yaml +7 -7
  368. package/src/modules/cis/workflows/innovation-strategy/instructions.md +2 -2
  369. package/src/modules/cis/workflows/innovation-strategy/workflow.yaml +7 -7
  370. package/src/modules/cis/workflows/problem-solving/instructions.md +2 -2
  371. package/src/modules/cis/workflows/problem-solving/workflow.yaml +7 -7
  372. package/src/modules/cis/workflows/storytelling/instructions.md +2 -2
  373. package/src/modules/cis/workflows/storytelling/workflow.yaml +7 -7
  374. package/src/utility/agent-components/activation-rules.txt +7 -0
  375. package/src/utility/agent-components/activation-steps.txt +13 -0
  376. package/src/utility/agent-components/agent-command-header.md +1 -0
  377. package/src/utility/{templates → agent-components}/agent.customize.template.yaml +0 -1
  378. package/src/utility/agent-components/handler-action.txt +4 -0
  379. package/src/utility/agent-components/handler-exec.txt +6 -0
  380. package/src/utility/agent-components/handler-multi.txt +14 -0
  381. package/src/utility/agent-components/handler-tmpl.txt +5 -0
  382. package/src/utility/agent-components/handler-validate-workflow.txt +7 -0
  383. package/src/utility/agent-components/handler-workflow.txt +10 -0
  384. package/src/utility/agent-components/menu-handlers.txt +6 -0
  385. package/test/README.md +1 -1
  386. package/test/test-agent-schema.js +2 -2
  387. package/tools/cli/README.md +1 -607
  388. package/tools/cli/commands/build.js +7 -7
  389. package/tools/cli/commands/install.js +9 -20
  390. package/tools/cli/commands/list.js +13 -1
  391. package/tools/cli/installers/lib/core/config-collector.js +243 -73
  392. package/tools/cli/installers/lib/core/custom-module-cache.js +36 -16
  393. package/tools/cli/installers/lib/core/dependency-resolver.js +2 -2
  394. package/tools/cli/installers/lib/core/detector.js +16 -16
  395. package/tools/cli/installers/lib/core/ide-config-manager.js +9 -7
  396. package/tools/cli/installers/lib/core/installer.js +595 -1006
  397. package/tools/cli/installers/lib/core/manifest-generator.js +43 -40
  398. package/tools/cli/installers/lib/core/manifest.js +23 -20
  399. package/tools/cli/installers/lib/custom/handler.js +16 -49
  400. package/tools/cli/installers/lib/ide/_base-ide.js +26 -33
  401. package/tools/cli/installers/lib/ide/antigravity.js +3 -3
  402. package/tools/cli/installers/lib/ide/claude-code.js +3 -3
  403. package/tools/cli/installers/lib/ide/codex.js +2 -2
  404. package/tools/cli/installers/lib/ide/gemini.js +6 -6
  405. package/tools/cli/installers/lib/ide/kiro-cli.js +2 -2
  406. package/tools/cli/installers/lib/ide/opencode.js +2 -2
  407. package/tools/cli/installers/lib/ide/roo.js +15 -5
  408. package/tools/cli/installers/lib/ide/shared/agent-command-generator.js +2 -2
  409. package/tools/cli/installers/lib/ide/shared/module-injections.js +2 -2
  410. package/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +2 -2
  411. package/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +4 -4
  412. package/tools/cli/installers/lib/ide/templates/agent-command-template.md +1 -1
  413. package/tools/cli/installers/lib/ide/templates/gemini-agent-command.toml +3 -3
  414. package/tools/cli/installers/lib/ide/templates/gemini-task-command.toml +3 -3
  415. package/tools/cli/installers/lib/ide/templates/workflow-command-template.md +1 -1
  416. package/tools/cli/installers/lib/modules/manager.js +304 -313
  417. package/tools/cli/lib/activation-builder.js +8 -13
  418. package/tools/cli/lib/agent/compiler.js +68 -168
  419. package/tools/cli/lib/agent/installer.js +8 -128
  420. package/tools/cli/lib/agent-analyzer.js +2 -2
  421. package/tools/cli/lib/agent-party-generator.js +5 -17
  422. package/tools/cli/lib/config.js +2 -2
  423. package/tools/cli/lib/platform-codes.js +2 -2
  424. package/tools/cli/lib/ui.js +610 -551
  425. package/tools/cli/lib/xml-handler.js +3 -55
  426. package/tools/cli/lib/yaml-format.js +4 -6
  427. package/tools/cli/lib/yaml-xml-builder.js +14 -26
  428. package/tools/flattener/ignoreRules.js +1 -1
  429. package/tools/flattener/xml.js +1 -7
  430. package/tools/lib/xml-utils.js +13 -0
  431. package/tools/migrate-custom-module-paths.js +2 -2
  432. package/tools/validate-agent-schema.js +2 -2
  433. package/docs/v6-open-items.md +0 -17
  434. package/example-custom-content/README.md +0 -8
  435. package/example-custom-module/mwm/README.md +0 -9
  436. package/example-custom-module/mwm/agents/cbt-coach/cbt-coach-sidecar/cognitive-distortions.md +0 -47
  437. package/example-custom-module/mwm/agents/cbt-coach/cbt-coach-sidecar/thought-records.md +0 -17
  438. package/example-custom-module/mwm/agents/cbt-coach/cbt-coach.agent.yaml +0 -151
  439. package/example-custom-module/mwm/agents/crisis-navigator.agent.yaml +0 -138
  440. package/example-custom-module/mwm/module.yaml +0 -28
  441. package/example-custom-module/mwm/workflows/cbt-thought-record/README.md +0 -31
  442. package/example-custom-module/mwm/workflows/cbt-thought-record/workflow.md +0 -45
  443. package/example-custom-module/mwm/workflows/crisis-support/README.md +0 -31
  444. package/example-custom-module/mwm/workflows/crisis-support/workflow.md +0 -45
  445. package/src/core/agents/bmad-web-orchestrator.agent.xml +0 -113
  446. package/src/modules/bmb/_module-installer/installer.js +0 -76
  447. package/src/modules/bmb/docs/agents/module-agent-architecture.md +0 -367
  448. package/src/modules/bmb/workflows/create-agent/steps/step-08-setup.md +0 -179
  449. package/src/modules/bmb/workflows/create-agent/steps/step-09-customize.md +0 -197
  450. package/src/modules/bmb/workflows/create-agent/steps/step-10-build-tools.md +0 -180
  451. package/src/modules/bmb/workflows/create-agent/templates/agent_commands.md +0 -21
  452. package/src/modules/bmb/workflows/create-agent/templates/agent_persona.md +0 -25
  453. package/src/modules/bmb/workflows/create-agent/templates/agent_purpose_and_type.md +0 -23
  454. package/src/modules/bmm/tasks/daily-standup.xml +0 -85
  455. package/src/modules/cis/agents/README.md +0 -104
  456. package/src/utility/models/action-command-header.md +0 -0
  457. package/src/utility/models/agent-activation-ide.xml +0 -51
  458. package/src/utility/models/agent-activation-web.xml +0 -50
  459. package/src/utility/models/agent-command-header.md +0 -1
  460. package/src/utility/models/agent-config-template.md +0 -23
  461. package/src/utility/models/agent-in-team-activation.xml +0 -3
  462. package/src/utility/models/fragments/activation-rules.xml +0 -7
  463. package/src/utility/models/fragments/activation-steps.xml +0 -16
  464. package/src/utility/models/fragments/handler-action.xml +0 -4
  465. package/src/utility/models/fragments/handler-exec.xml +0 -6
  466. package/src/utility/models/fragments/handler-multi.xml +0 -14
  467. package/src/utility/models/fragments/handler-tmpl.xml +0 -5
  468. package/src/utility/models/fragments/handler-validate-workflow.xml +0 -7
  469. package/src/utility/models/fragments/handler-workflow.xml +0 -9
  470. package/src/utility/models/fragments/menu-handlers.xml +0 -6
  471. package/src/utility/models/fragments/web-bundle-activation-steps.xml +0 -32
  472. package/tools/cli/bundlers/bundle-web.js +0 -179
  473. package/tools/cli/bundlers/test-analyst.js +0 -28
  474. package/tools/cli/bundlers/test-bundler.js +0 -118
  475. package/tools/cli/bundlers/web-bundler.js +0 -1764
  476. package/tools/cli/installers/lib/core/post-install-sidecar-replacement.js +0 -79
  477. package/tools/cli/lib/replace-project-root.js +0 -239
  478. package/tools/cli/regenerate-manifests.js +0 -28
  479. package/tools/cli/test-yaml-builder.js +0 -43
  480. /package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/agents/toolsmith/toolsmith-sidecar/instructions.md +0 -0
  481. /package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/agents/toolsmith/toolsmith-sidecar/knowledge/bundlers.md +0 -0
  482. /package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/agents/toolsmith/toolsmith-sidecar/knowledge/deploy.md +0 -0
  483. /package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/agents/toolsmith/toolsmith-sidecar/knowledge/docs.md +0 -0
  484. /package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/agents/toolsmith/toolsmith-sidecar/knowledge/installers.md +0 -0
  485. /package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/agents/toolsmith/toolsmith-sidecar/knowledge/modules.md +0 -0
  486. /package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/agents/toolsmith/toolsmith-sidecar/knowledge/tests.md +0 -0
  487. /package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/agents/toolsmith/toolsmith-sidecar/memories.md +0 -0
  488. /package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/quiz-master/templates/csv-headers.template +0 -0
  489. /package/{example-custom-content → docs/sample-custom-modules/sample-unitary-module}/workflows/wassup/workflow.md +0 -0
  490. /package/{example-custom-module/mwm → docs/sample-custom-modules/sample-wellness-module}/agents/wellness-companion/wellness-companion-sidecar/insights.md +0 -0
  491. /package/{example-custom-module/mwm → docs/sample-custom-modules/sample-wellness-module}/agents/wellness-companion/wellness-companion-sidecar/instructions.md +0 -0
  492. /package/{example-custom-module/mwm → docs/sample-custom-modules/sample-wellness-module}/agents/wellness-companion/wellness-companion-sidecar/memories.md +0 -0
  493. /package/{example-custom-module/mwm → docs/sample-custom-modules/sample-wellness-module}/agents/wellness-companion/wellness-companion-sidecar/patterns.md +0 -0
  494. /package/{example-custom-module/mwm → docs/sample-custom-modules/sample-wellness-module}/workflows/daily-checkin/README.md +0 -0
  495. /package/{example-custom-module/mwm → docs/sample-custom-modules/sample-wellness-module}/workflows/daily-checkin/workflow.md +0 -0
  496. /package/{example-custom-module/mwm → docs/sample-custom-modules/sample-wellness-module}/workflows/guided-meditation/README.md +0 -0
  497. /package/{example-custom-module/mwm → docs/sample-custom-modules/sample-wellness-module}/workflows/guided-meditation/workflow.md +0 -0
  498. /package/{example-custom-module/mwm → docs/sample-custom-modules/sample-wellness-module}/workflows/wellness-journal/README.md +0 -0
  499. /package/src/modules/bmgd/workflows/4-production/code-review/{backlog_template.md → backlog-template.md} +0 -0
  500. /package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/product-brief.template.md +0 -0
  501. /package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/templates/readiness-report-template.md +0 -0
  502. /package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/architecture-decision-template.md +0 -0
  503. /package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/data/domain-complexity.csv +0 -0
  504. /package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/data/project-types.csv +0 -0
  505. /package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-01b-continue.md +0 -0
  506. /package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/_shared/excalidraw-library.json +0 -0
  507. /package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/_shared/excalidraw-templates.yaml +0 -0
  508. /package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-dataflow/checklist.md +0 -0
  509. /package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-diagram/checklist.md +0 -0
  510. /package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-flowchart/checklist.md +0 -0
  511. /package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-wireframe/checklist.md +0 -0
  512. /package/src/utility/{models/fragments/handler-data.xml → agent-components/handler-data.txt} +0 -0
@@ -1,44 +1,24 @@
1
- /**
2
- * File: tools/cli/lib/ui.js
3
- *
4
- * BMAD Method - Business Model Agile Development Method
5
- * Repository: https://github.com/paulpreibisch/BMAD-METHOD
6
- *
7
- * Copyright (c) 2025 Paul Preibisch
8
- * Licensed under the Apache License, Version 2.0
9
- *
10
- * ---
11
- *
12
- * @fileoverview Interactive installation prompts and user input collection for BMAD CLI
13
- * @context Guides users through installation configuration including core settings, modules, IDEs, and optional AgentVibes TTS
14
- * @architecture Facade pattern - presents unified installation flow, delegates to Detector/ConfigCollector/IdeManager for specifics
15
- * @dependencies inquirer (prompts), chalk (formatting), detector.js (existing installation detection)
16
- * @entrypoints Called by install.js command via ui.promptInstall(), returns complete configuration object
17
- * @patterns Progressive disclosure (prompts in order), early IDE selection (Windows compat), AgentVibes auto-detection
18
- * @related installer.js (consumes config), AgentVibes#34 (TTS integration), promptAgentVibes()
19
- */
20
-
21
1
  const chalk = require('chalk');
22
2
  const inquirer = require('inquirer');
23
3
  const path = require('node:path');
24
4
  const os = require('node:os');
25
5
  const fs = require('fs-extra');
26
6
  const { CLIUtils } = require('./cli-utils');
7
+ const { CustomHandler } = require('../installers/lib/custom/handler');
27
8
 
28
9
  /**
29
10
  * UI utilities for the installer
30
11
  */
31
12
  class UI {
32
- constructor() {}
33
-
34
13
  /**
35
14
  * Prompt for installation configuration
36
15
  * @returns {Object} Installation configuration
37
16
  */
38
17
  async promptInstall() {
39
18
  CLIUtils.displayLogo();
40
- const version = CLIUtils.getVersion();
41
- CLIUtils.displaySection('BMAD™ Setup', `Build More, Architect Dreams v${version}`);
19
+
20
+ // Display changelog link
21
+ console.log(chalk.cyan('\n📋 Read the latest updates: https://github.com/bmad-code-org/BMAD-METHOD/blob/main/CHANGELOG.md\n'));
42
22
 
43
23
  const confirmedDirectory = await this.getConfirmedDirectory();
44
24
 
@@ -52,21 +32,138 @@ class UI {
52
32
  await installer.handleLegacyV4Migration(confirmedDirectory, legacyV4);
53
33
  }
54
34
 
55
- // Check if there's an existing BMAD installation
56
- const fs = require('fs-extra');
57
- const path = require('node:path');
58
- // Use findBmadDir to detect any custom folder names (V6+)
59
- const bmadDir = await installer.findBmadDir(confirmedDirectory);
35
+ // Check for legacy folders and prompt for rename before showing any menus
36
+ let hasLegacyCfg = false;
37
+ let hasLegacyBmadFolder = false;
38
+ let bmadDir = null;
39
+ let legacyBmadPath = null;
40
+
41
+ // First check for legacy .bmad folder (instead of _bmad)
42
+ // Only check if directory exists
43
+ if (await fs.pathExists(confirmedDirectory)) {
44
+ const entries = await fs.readdir(confirmedDirectory, { withFileTypes: true });
45
+ for (const entry of entries) {
46
+ if (entry.isDirectory() && entry.name === '.bmad') {
47
+ hasLegacyBmadFolder = true;
48
+ legacyBmadPath = path.join(confirmedDirectory, '.bmad');
49
+ bmadDir = legacyBmadPath;
50
+
51
+ // Check if it has _cfg folder
52
+ const cfgPath = path.join(legacyBmadPath, '_cfg');
53
+ if (await fs.pathExists(cfgPath)) {
54
+ hasLegacyCfg = true;
55
+ }
56
+ break;
57
+ }
58
+ }
59
+ }
60
+
61
+ // If no .bmad found, check for current installations
62
+ if (!hasLegacyBmadFolder) {
63
+ const bmadResult = await installer.findBmadDir(confirmedDirectory);
64
+ bmadDir = bmadResult.bmadDir;
65
+ hasLegacyCfg = bmadResult.hasLegacyCfg;
66
+ }
67
+
68
+ if (hasLegacyBmadFolder || hasLegacyCfg) {
69
+ console.log(chalk.yellow('\n⚠️ Legacy folder structure detected'));
70
+
71
+ let message = 'The following folders need to be renamed:\n';
72
+ if (hasLegacyBmadFolder) {
73
+ message += chalk.dim(` • ".bmad" → "_bmad"\n`);
74
+ }
75
+ if (hasLegacyCfg) {
76
+ message += chalk.dim(` • "_cfg" → "_config"\n`);
77
+ }
78
+ console.log(message);
79
+
80
+ const { shouldRename } = await inquirer.prompt([
81
+ {
82
+ type: 'confirm',
83
+ name: 'shouldRename',
84
+ message: 'Would you like the installer to rename these folders for you?',
85
+ default: true,
86
+ },
87
+ ]);
88
+
89
+ if (!shouldRename) {
90
+ console.log(chalk.red('\n❌ Installation cancelled'));
91
+ console.log(chalk.dim('You must manually rename the folders before proceeding:'));
92
+ if (hasLegacyBmadFolder) {
93
+ console.log(chalk.dim(` • Rename ".bmad" to "_bmad"`));
94
+ }
95
+ if (hasLegacyCfg) {
96
+ console.log(chalk.dim(` • Rename "_cfg" to "_config"`));
97
+ }
98
+ process.exit(0);
99
+ return;
100
+ }
101
+
102
+ // Perform the renames
103
+ const ora = require('ora');
104
+ const spinner = ora('Updating folder structure...').start();
105
+
106
+ try {
107
+ // First rename .bmad to _bmad if needed
108
+ if (hasLegacyBmadFolder) {
109
+ const newBmadPath = path.join(confirmedDirectory, '_bmad');
110
+ await fs.move(legacyBmadPath, newBmadPath);
111
+ bmadDir = newBmadPath;
112
+ spinner.succeed('Renamed ".bmad" to "_bmad"');
113
+ }
114
+
115
+ // Then rename _cfg to _config if needed
116
+ if (hasLegacyCfg) {
117
+ spinner.start('Renaming configuration folder...');
118
+ const oldCfgPath = path.join(bmadDir, '_cfg');
119
+ const newCfgPath = path.join(bmadDir, '_config');
120
+ await fs.move(oldCfgPath, newCfgPath);
121
+ spinner.succeed('Renamed "_cfg" to "_config"');
122
+ }
123
+
124
+ spinner.succeed('Folder structure updated successfully');
125
+ } catch (error) {
126
+ spinner.fail('Failed to update folder structure');
127
+ console.error(chalk.red(`Error: ${error.message}`));
128
+ process.exit(1);
129
+ }
130
+ }
131
+
132
+ // Check if there's an existing BMAD installation (after any folder renames)
60
133
  const hasExistingInstall = await fs.pathExists(bmadDir);
61
134
 
62
- // Always ask for custom content, but we'll handle it differently for new installs
135
+ // Collect IDE tool selection early - we need this to know if we should ask about TTS
136
+ let toolSelection;
137
+ let agentVibesConfig = { enabled: false, alreadyInstalled: false };
138
+ let claudeCodeSelected = false;
139
+
140
+ if (!hasExistingInstall) {
141
+ // For new installations, collect IDE selection first
142
+ // We don't have modules yet, so pass empty array
143
+ toolSelection = await this.promptToolSelection(confirmedDirectory, []);
144
+
145
+ // Check if Claude Code was selected
146
+ claudeCodeSelected = toolSelection.ides && toolSelection.ides.includes('claude-code');
147
+
148
+ // If Claude Code was selected, ask about TTS
149
+ if (claudeCodeSelected) {
150
+ const { enableTts } = await inquirer.prompt([
151
+ {
152
+ type: 'confirm',
153
+ name: 'enableTts',
154
+ message: 'Claude Code supports TTS (Text-to-Speech). Would you like to enable it?',
155
+ default: false,
156
+ },
157
+ ]);
158
+
159
+ if (enableTts) {
160
+ agentVibesConfig = { enabled: true, alreadyInstalled: false };
161
+ }
162
+ }
163
+ }
164
+
63
165
  let customContentConfig = { hasCustomContent: false };
64
- if (hasExistingInstall) {
65
- // Existing installation - prompt to add/update custom content
66
- customContentConfig = await this.promptCustomContentForExisting();
67
- } else {
68
- // New installation - we'll prompt after creating the directory structure
69
- // For now, set a flag to indicate we should ask later
166
+ if (!hasExistingInstall) {
70
167
  customContentConfig._shouldAsk = true;
71
168
  }
72
169
 
@@ -75,19 +172,33 @@ class UI {
75
172
 
76
173
  // Only show action menu if there's an existing installation
77
174
  if (hasExistingInstall) {
175
+ // Get version information
176
+ const { existingInstall } = await this.getExistingInstallation(confirmedDirectory);
177
+ const packageJsonPath = path.join(__dirname, '../../../package.json');
178
+ const currentVersion = require(packageJsonPath).version;
179
+ const installedVersion = existingInstall.version || 'unknown';
180
+
181
+ // Build menu choices dynamically
182
+ const choices = [];
183
+
184
+ // Always show Quick Update first (allows refreshing installation even on same version)
185
+ if (installedVersion !== 'unknown') {
186
+ choices.push({
187
+ name: `Quick Update (v${installedVersion} → v${currentVersion})`,
188
+ value: 'quick-update',
189
+ });
190
+ }
191
+
192
+ // Common actions
193
+ choices.push({ name: 'Modify BMAD Installation', value: 'update' });
194
+
78
195
  const promptResult = await inquirer.prompt([
79
196
  {
80
197
  type: 'list',
81
198
  name: 'actionType',
82
199
  message: 'What would you like to do?',
83
- choices: [
84
- { name: 'Quick Update (Settings Preserved)', value: 'quick-update' },
85
- { name: 'Modify BMAD Installation (Confirm or change each setting)', value: 'update' },
86
- { name: 'Remove BMad Folder and Reinstall (Full clean install - BMad Customization Will Be Lost)', value: 'reinstall' },
87
- { name: 'Compile Agents (Quick rebuild of all agent .md files)', value: 'compile' },
88
- { name: 'Cancel', value: 'cancel' },
89
- ],
90
- default: 'quick-update',
200
+ choices: choices,
201
+ default: choices[0].value, // Use the first option as default
91
202
  },
92
203
  ]);
93
204
 
@@ -104,165 +215,141 @@ class UI {
104
215
  };
105
216
  }
106
217
 
107
- // Handle agent compilation separately
108
- if (actionType === 'compile') {
109
- return {
110
- actionType: 'compile',
111
- directory: confirmedDirectory,
112
- };
113
- }
218
+ // If actionType === 'update', handle it with the new flow
219
+ // Return early with modify configuration
220
+ if (actionType === 'update') {
221
+ // Get existing installation info
222
+ const { installedModuleIds } = await this.getExistingInstallation(confirmedDirectory);
223
+
224
+ console.log(chalk.dim(` Found existing modules: ${[...installedModuleIds].join(', ')}`));
225
+ const { changeModuleSelection } = await inquirer.prompt([
226
+ {
227
+ type: 'confirm',
228
+ name: 'changeModuleSelection',
229
+ message: 'Modify official module selection (BMad Method, BMad Builder, Creative Innovation Suite)?',
230
+ default: false,
231
+ },
232
+ ]);
233
+
234
+ let selectedModules = [];
235
+ if (changeModuleSelection) {
236
+ // Show module selection with existing modules pre-selected
237
+ const moduleChoices = await this.getModuleChoices(new Set(installedModuleIds), { hasCustomContent: false });
238
+ selectedModules = await this.selectModules(moduleChoices, [...installedModuleIds]);
239
+ } else {
240
+ selectedModules = [...installedModuleIds];
241
+ }
242
+
243
+ // After module selection, ask about custom modules
244
+ const customModuleResult = await this.handleCustomModulesInModifyFlow(confirmedDirectory, selectedModules);
245
+
246
+ // Merge any selected custom modules
247
+ if (customModuleResult.selectedCustomModules.length > 0) {
248
+ selectedModules.push(...customModuleResult.selectedCustomModules);
249
+ }
250
+
251
+ // Get tool selection
252
+ const toolSelection = await this.promptToolSelection(confirmedDirectory, selectedModules);
253
+
254
+ // TTS configuration - ask right after tool selection (matches new install flow)
255
+ const hasClaudeCode = toolSelection.ides && toolSelection.ides.includes('claude-code');
256
+ let enableTts = false;
257
+
258
+ if (hasClaudeCode) {
259
+ const { enableTts: enable } = await inquirer.prompt([
260
+ {
261
+ type: 'confirm',
262
+ name: 'enableTts',
263
+ message: 'Claude Code supports TTS (Text-to-Speech). Would you like to enable it?',
264
+ default: false,
265
+ },
266
+ ]);
267
+ enableTts = enable;
268
+ }
269
+
270
+ // Core config with existing defaults (ask after TTS)
271
+ const coreConfig = await this.collectCoreConfig(confirmedDirectory);
114
272
 
115
- // Handle cancel
116
- if (actionType === 'cancel') {
117
273
  return {
118
- actionType: 'cancel',
274
+ actionType: 'update',
119
275
  directory: confirmedDirectory,
276
+ installCore: true,
277
+ modules: selectedModules,
278
+ ides: toolSelection.ides,
279
+ skipIde: toolSelection.skipIde,
280
+ coreConfig: coreConfig,
281
+ customContent: customModuleResult.customContentConfig,
282
+ enableAgentVibes: enableTts,
283
+ agentVibesInstalled: false,
120
284
  };
121
285
  }
122
-
123
- // Handle reinstall - DON'T return early, let it flow through configuration collection
124
- // The installer will handle deletion when it sees actionType === 'reinstall'
125
- // For now, just note that we're in reinstall mode and continue below
126
-
127
- // If actionType === 'update' or 'reinstall', continue with normal flow below
128
286
  }
129
287
 
288
+ // This section is only for new installations (update returns early above)
130
289
  const { installedModuleIds } = await this.getExistingInstallation(confirmedDirectory);
131
- const coreConfig = await this.collectCoreConfig(confirmedDirectory);
132
290
 
133
- // For new installations, create the directory structure first so we can cache custom content
134
- if (!hasExistingInstall && customContentConfig._shouldAsk) {
135
- // Create the bmad directory based on core config
136
- const path = require('node:path');
137
- const fs = require('fs-extra');
138
- const bmadFolderName = coreConfig.bmad_folder || 'bmad';
139
- const bmadDir = path.join(confirmedDirectory, bmadFolderName);
140
-
141
- await fs.ensureDir(bmadDir);
142
- await fs.ensureDir(path.join(bmadDir, '_cfg'));
143
- await fs.ensureDir(path.join(bmadDir, '_cfg', 'custom'));
144
-
145
- // Now prompt for custom content
146
- customContentConfig = await this.promptCustomContentLocation();
147
-
148
- // If custom content found, cache it
149
- if (customContentConfig.hasCustomContent) {
150
- const { CustomModuleCache } = require('../installers/lib/core/custom-module-cache');
151
- const cache = new CustomModuleCache(bmadDir);
152
-
153
- const { CustomHandler } = require('../installers/lib/custom/handler');
154
- const customHandler = new CustomHandler();
155
- const customFiles = await customHandler.findCustomContent(customContentConfig.customPath);
156
-
157
- for (const customFile of customFiles) {
158
- const customInfo = await customHandler.getCustomInfo(customFile);
159
- if (customInfo && customInfo.id) {
160
- // Cache the module source
161
- await cache.cacheModule(customInfo.id, customInfo.path, {
162
- name: customInfo.name,
163
- type: 'custom',
164
- });
165
-
166
- console.log(chalk.dim(` Cached ${customInfo.name} to _cfg/custom/${customInfo.id}`));
167
- }
168
- }
291
+ // Ask about official modules for new installations
292
+ const { wantsOfficialModules } = await inquirer.prompt([
293
+ {
294
+ type: 'confirm',
295
+ name: 'wantsOfficialModules',
296
+ message: 'Will you be installing any official BMad modules (BMad Method, BMad Builder, Creative Innovation Suite)?',
297
+ default: true,
298
+ },
299
+ ]);
169
300
 
170
- // Update config to use cached modules
171
- customContentConfig.cachedModules = [];
172
- for (const customFile of customFiles) {
173
- const customInfo = await customHandler.getCustomInfo(customFile);
174
- if (customInfo && customInfo.id) {
175
- customContentConfig.cachedModules.push({
176
- id: customInfo.id,
177
- cachePath: path.join(bmadDir, '_cfg', 'custom', customInfo.id),
178
- // Store relative path from cache for the manifest
179
- relativePath: path.join('_cfg', 'custom', customInfo.id),
180
- });
181
- }
182
- }
301
+ let selectedOfficialModules = [];
302
+ if (wantsOfficialModules) {
303
+ const moduleChoices = await this.getModuleChoices(installedModuleIds, { hasCustomContent: false });
304
+ selectedOfficialModules = await this.selectModules(moduleChoices);
305
+ }
183
306
 
184
- console.log(chalk.green(`✓ Cached ${customFiles.length} custom module(s)`));
185
- }
307
+ // Ask about custom content
308
+ const { wantsCustomContent } = await inquirer.prompt([
309
+ {
310
+ type: 'confirm',
311
+ name: 'wantsCustomContent',
312
+ message: 'Would you like to install a local custom module (this includes custom agents and workflows also)?',
313
+ default: false,
314
+ },
315
+ ]);
186
316
 
187
- // Clear the flag
188
- delete customContentConfig._shouldAsk;
317
+ if (wantsCustomContent) {
318
+ customContentConfig = await this.promptCustomContentSource();
189
319
  }
190
320
 
191
- // Skip module selection during update/reinstall - keep existing modules
192
- let selectedModules;
193
- if (actionType === 'update' || actionType === 'reinstall') {
194
- // Keep all existing installed modules during update/reinstall
195
- selectedModules = [...installedModuleIds];
196
- console.log(chalk.cyan('\n📦 Keeping existing modules: ') + selectedModules.join(', '));
197
- } else {
198
- // Only show module selection for new installs
199
- const moduleChoices = await this.getModuleChoices(installedModuleIds, customContentConfig);
200
- selectedModules = await this.selectModules(moduleChoices);
201
-
202
- // Check which custom content items were selected
203
- const selectedCustomContent = selectedModules.filter((mod) => mod.startsWith('__CUSTOM_CONTENT__'));
204
-
205
- // For cached modules (new installs), check if any cached modules were selected
206
- let selectedCachedModules = [];
207
- if (customContentConfig.cachedModules) {
208
- selectedCachedModules = selectedModules.filter(
209
- (mod) => !mod.startsWith('__CUSTOM_CONTENT__') && customContentConfig.cachedModules.some((cm) => cm.id === mod),
210
- );
211
- }
321
+ // Store the selected modules for later
322
+ customContentConfig._selectedOfficialModules = selectedOfficialModules;
212
323
 
213
- if (selectedCustomContent.length > 0 || selectedCachedModules.length > 0) {
214
- customContentConfig.selected = true;
215
-
216
- // Handle directory-based custom content (existing installs)
217
- if (selectedCustomContent.length > 0) {
218
- customContentConfig.selectedFiles = selectedCustomContent.map((mod) => mod.replace('__CUSTOM_CONTENT__', ''));
219
- // Convert custom content to module IDs for installation
220
- const customContentModuleIds = [];
221
- const { CustomHandler } = require('../installers/lib/custom/handler');
222
- const customHandler = new CustomHandler();
223
- for (const customFile of customContentConfig.selectedFiles) {
224
- // Get the module info to extract the ID
225
- const customInfo = await customHandler.getCustomInfo(customFile);
226
- if (customInfo) {
227
- customContentModuleIds.push(customInfo.id);
228
- }
229
- }
230
- // Filter out custom content markers and add module IDs
231
- selectedModules = [...selectedModules.filter((mod) => !mod.startsWith('__CUSTOM_CONTENT__')), ...customContentModuleIds];
232
- }
324
+ // Build the final list of selected modules
325
+ let selectedModules = customContentConfig._selectedOfficialModules || [];
233
326
 
234
- // For cached modules, they're already module IDs, just mark as selected
235
- if (selectedCachedModules.length > 0) {
236
- customContentConfig.selectedCachedModules = selectedCachedModules;
237
- // No need to filter since they're already proper module IDs
238
- }
239
- } else if (customContentConfig.hasCustomContent) {
240
- // User provided custom content but didn't select any
241
- customContentConfig.selected = false;
242
- customContentConfig.selectedFiles = [];
243
- customContentConfig.selectedCachedModules = [];
244
- }
327
+ // Add custom content modules if any were selected
328
+ if (customContentConfig && customContentConfig.selectedModuleIds) {
329
+ selectedModules = [...selectedModules, ...customContentConfig.selectedModuleIds];
245
330
  }
246
331
 
247
- // Prompt for AgentVibes TTS integration
248
- const agentVibesConfig = await this.promptAgentVibes(confirmedDirectory);
332
+ // Remove core if it's in the list (it's always installed)
333
+ selectedModules = selectedModules.filter((m) => m !== 'core');
249
334
 
250
- // Collect IDE tool selection AFTER configuration prompts (fixes Windows/PowerShell hang)
251
- // This allows text-based prompts to complete before the checkbox prompt
252
- const toolSelection = await this.promptToolSelection(confirmedDirectory, selectedModules);
335
+ // Tool selection (already done for new installs at the beginning)
336
+ if (!toolSelection) {
337
+ toolSelection = await this.promptToolSelection(confirmedDirectory, selectedModules);
338
+ }
339
+
340
+ // Collect configurations for new installations
341
+ const coreConfig = await this.collectCoreConfig(confirmedDirectory);
253
342
 
254
- // No more screen clearing - keep output flowing
343
+ // TTS already handled at the beginning for new installs
255
344
 
256
345
  return {
257
- actionType: actionType || 'update', // Preserve reinstall or update action
346
+ actionType: 'install',
258
347
  directory: confirmedDirectory,
259
- installCore: true, // Always install core
348
+ installCore: true,
260
349
  modules: selectedModules,
261
- // IDE selection collected after config, will be configured later
262
350
  ides: toolSelection.ides,
263
351
  skipIde: toolSelection.skipIde,
264
- coreConfig: coreConfig, // Pass collected core config to installer
265
- // Custom content configuration
352
+ coreConfig: coreConfig,
266
353
  customContent: customContentConfig,
267
354
  enableAgentVibes: agentVibesConfig.enabled,
268
355
  agentVibesInstalled: agentVibesConfig.alreadyInstalled,
@@ -281,7 +368,8 @@ class UI {
281
368
  const { Installer } = require('../installers/lib/core/installer');
282
369
  const detector = new Detector();
283
370
  const installer = new Installer();
284
- const bmadDir = await installer.findBmadDir(projectDir || process.cwd());
371
+ const bmadResult = await installer.findBmadDir(projectDir || process.cwd());
372
+ const bmadDir = bmadResult.bmadDir;
285
373
  const existingInstall = await detector.detect(bmadDir);
286
374
  const configuredIdes = existingInstall.ides || [];
287
375
 
@@ -351,8 +439,6 @@ class UI {
351
439
  }
352
440
  }
353
441
 
354
- CLIUtils.displaySection('Tool Integration', 'Select AI coding assistants and IDEs to configure');
355
-
356
442
  let answers;
357
443
  let userConfirmedNoTools = false;
358
444
 
@@ -364,7 +450,7 @@ class UI {
364
450
  name: 'ides',
365
451
  message: 'Select tools to configure:',
366
452
  choices: ideChoices,
367
- pageSize: 15,
453
+ pageSize: 30,
368
454
  },
369
455
  ]);
370
456
 
@@ -390,9 +476,8 @@ class UI {
390
476
  ]);
391
477
 
392
478
  if (goBack) {
393
- // Re-display the section header before looping back
479
+ // Re-display a message before looping back
394
480
  console.log();
395
- CLIUtils.displaySection('Tool Integration', 'Select AI coding assistants and IDEs to configure');
396
481
  } else {
397
482
  // User explicitly chose to proceed without tools
398
483
  userConfirmedNoTools = true;
@@ -482,69 +567,33 @@ class UI {
482
567
  * @param {Object} result - Installation result
483
568
  */
484
569
  showInstallSummary(result) {
485
- CLIUtils.displaySection('Installation Complete', 'BMAD™ has been successfully installed');
486
-
487
- const summary = [
488
- `📁 Installation Path: ${result.path}`,
489
- `📦 Modules Installed: ${result.modules?.length > 0 ? result.modules.join(', ') : 'core only'}`,
490
- `🔧 Tools Configured: ${result.ides?.length > 0 ? result.ides.join(', ') : 'none'}`,
491
- ];
570
+ // Clean, simple completion message
571
+ console.log('\n' + chalk.green.bold('✨ BMAD is ready to use!'));
492
572
 
493
- // Add AgentVibes TTS info if enabled
573
+ // Show installation summary in a simple format
574
+ console.log(chalk.dim(`Installed to: ${result.path}`));
575
+ if (result.modules && result.modules.length > 0) {
576
+ console.log(chalk.dim(`Modules: ${result.modules.join(', ')}`));
577
+ }
494
578
  if (result.agentVibesEnabled) {
495
- summary.push(`🎤 AgentVibes TTS: Enabled`);
579
+ console.log(chalk.dim(`TTS: Enabled`));
496
580
  }
497
581
 
498
- CLIUtils.displayBox(summary.join('\n\n'), {
499
- borderColor: 'green',
500
- borderStyle: 'round',
501
- });
502
-
503
- // Display TTS injection details if present
582
+ // TTS injection info (simplified)
504
583
  if (result.ttsInjectedFiles && result.ttsInjectedFiles.length > 0) {
505
- console.log('\n' + chalk.cyan.bold('═══════════════════════════════════════════════════'));
506
- console.log(chalk.cyan.bold(' AgentVibes TTS Injection Summary'));
507
- console.log(chalk.cyan.bold('═══════════════════════════════════════════════════\n'));
508
-
509
- // Explain what TTS injection is
510
- console.log(chalk.white.bold('What is TTS Injection?\n'));
511
- console.log(chalk.dim(' TTS (Text-to-Speech) injection adds voice instructions to BMAD agents,'));
512
- console.log(chalk.dim(' enabling them to speak their responses aloud using AgentVibes.\n'));
513
- console.log(chalk.dim(' Example: When you activate the PM agent, it will greet you with'));
514
- console.log(chalk.dim(' spoken audio like "Hey! I\'m your Project Manager. How can I help?"\n'));
515
-
516
- console.log(chalk.green(`✅ TTS injection applied to ${result.ttsInjectedFiles.length} file(s):\n`));
517
-
518
- // Group by type
519
- const partyModeFiles = result.ttsInjectedFiles.filter((f) => f.type === 'party-mode');
520
- const agentTTSFiles = result.ttsInjectedFiles.filter((f) => f.type === 'agent-tts');
521
-
522
- if (partyModeFiles.length > 0) {
523
- console.log(chalk.yellow(' Party Mode (multi-agent conversations):'));
524
- for (const file of partyModeFiles) {
525
- console.log(chalk.dim(` • ${file.path}`));
526
- }
527
- }
528
-
529
- if (agentTTSFiles.length > 0) {
530
- console.log(chalk.yellow(' Agent TTS (individual agent voices):'));
531
- for (const file of agentTTSFiles) {
532
- console.log(chalk.dim(` • ${file.path}`));
533
- }
534
- }
535
-
536
- // Show backup info and restore command
537
- console.log('\n' + chalk.white.bold('Backups & Recovery:\n'));
538
- console.log(chalk.dim(' Pre-injection backups are stored in:'));
539
- console.log(chalk.cyan(' ~/.bmad-tts-backups/\n'));
540
- console.log(chalk.dim(' To restore original files (removes TTS instructions):'));
541
- console.log(chalk.cyan(` bmad-tts-injector.sh --restore ${result.path}\n`));
542
-
543
- console.log(chalk.cyan('💡 BMAD agents will now speak when activated!'));
544
- console.log(chalk.dim(' Ensure AgentVibes is installed: https://agentvibes.org'));
584
+ console.log(chalk.dim(`\n💡 TTS enabled for ${result.ttsInjectedFiles.length} agent(s)`));
585
+ console.log(chalk.dim(' Agents will now speak when using AgentVibes'));
545
586
  }
546
587
 
547
- console.log('\n' + chalk.green.bold(' BMAD is ready to use!'));
588
+ console.log(chalk.yellow('\nThank you for helping test the early release version of the new BMad Core and BMad Method!'));
589
+ console.log(chalk.cyan('Stable Beta coming soon - please read the full README.md and linked documentation to get started!'));
590
+
591
+ // Add changelog link at the end
592
+ console.log(
593
+ chalk.magenta(
594
+ "\n📋 Want to see what's new? Check out the changelog: https://github.com/bmad-code-org/BMAD-METHOD/blob/main/CHANGELOG.md",
595
+ ),
596
+ );
548
597
  }
549
598
 
550
599
  /**
@@ -574,8 +623,8 @@ class UI {
574
623
  const { Installer } = require('../installers/lib/core/installer');
575
624
  const detector = new Detector();
576
625
  const installer = new Installer();
577
- const bmadDir = await installer.findBmadDir(directory);
578
- const existingInstall = await detector.detect(bmadDir);
626
+ const bmadDirResult = await installer.findBmadDir(directory);
627
+ const existingInstall = await detector.detect(bmadDirResult.bmadDir);
579
628
  const installedModuleIds = new Set(existingInstall.modules.map((mod) => mod.id));
580
629
 
581
630
  return { existingInstall, installedModuleIds };
@@ -594,7 +643,9 @@ class UI {
594
643
  // Now collect with existing values as defaults (false = don't skip loading, true = skip completion message)
595
644
  await configCollector.collectModuleConfig('core', directory, false, true);
596
645
 
597
- return configCollector.collectedConfig.core;
646
+ const coreConfig = configCollector.collectedConfig.core;
647
+ // Ensure we always have a core config object, even if empty
648
+ return coreConfig || {};
598
649
  }
599
650
 
600
651
  /**
@@ -611,90 +662,28 @@ class UI {
611
662
  const hasCustomContentItems = false;
612
663
 
613
664
  // Add custom content items
614
- if (customContentConfig && customContentConfig.hasCustomContent) {
615
- if (customContentConfig.cachedModules) {
616
- // New installation - show cached modules
617
- for (const cachedModule of customContentConfig.cachedModules) {
618
- // Get the module info from cache
619
- const yaml = require('js-yaml');
620
- const fs = require('fs-extra');
621
-
622
- // Try multiple possible config file locations
623
- const possibleConfigPaths = [
624
- path.join(cachedModule.cachePath, 'module.yaml'),
625
- path.join(cachedModule.cachePath, 'custom.yaml'),
626
- path.join(cachedModule.cachePath, '_module-installer', 'module.yaml'),
627
- path.join(cachedModule.cachePath, '_module-installer', 'custom.yaml'),
628
- ];
629
-
630
- let moduleData = null;
631
- let foundPath = null;
632
-
633
- for (const configPath of possibleConfigPaths) {
634
- if (await fs.pathExists(configPath)) {
635
- try {
636
- const yamlContent = await fs.readFile(configPath, 'utf8');
637
- moduleData = yaml.load(yamlContent);
638
- foundPath = configPath;
639
- break;
640
- } catch {
641
- // Continue to next path
642
- }
643
- }
644
- }
645
-
646
- if (moduleData) {
647
- // Use the name from the custom info if we have it
648
- const moduleName = cachedModule.name || moduleData.name || cachedModule.id;
665
+ if (customContentConfig && customContentConfig.hasCustomContent && customContentConfig.customPath) {
666
+ // Existing installation - show from directory
667
+ const customHandler = new CustomHandler();
668
+ const customFiles = await customHandler.findCustomContent(customContentConfig.customPath);
649
669
 
650
- customContentItems.push({
651
- name: `${chalk.cyan('✓')} ${moduleName} ${chalk.gray('(cached)')}`,
652
- value: cachedModule.id, // Use module ID directly
653
- checked: true, // Default to selected
654
- cached: true,
655
- });
656
- } else {
657
- // Debug: show what paths we tried to check
658
- console.log(chalk.dim(`DEBUG: No module config found for ${cachedModule.id}`));
659
- console.log(
660
- chalk.dim(
661
- `DEBUG: Tried paths:`,
662
- possibleConfigPaths.map((p) => p.replace(cachedModule.cachePath, '.')),
663
- ),
664
- );
665
- console.log(chalk.dim(`DEBUG: cachedModule:`, JSON.stringify(cachedModule, null, 2)));
666
- }
667
- }
668
- } else if (customContentConfig.customPath) {
669
- // Existing installation - show from directory
670
- const { CustomHandler } = require('../installers/lib/custom/handler');
671
- const customHandler = new CustomHandler();
672
- const customFiles = await customHandler.findCustomContent(customContentConfig.customPath);
673
-
674
- for (const customFile of customFiles) {
675
- const customInfo = await customHandler.getCustomInfo(customFile);
676
- if (customInfo) {
677
- customContentItems.push({
678
- name: `${chalk.cyan('✓')} ${customInfo.name} ${chalk.gray(`(${customInfo.relativePath})`)}`,
679
- value: `__CUSTOM_CONTENT__${customFile}`, // Unique value for each custom content
680
- checked: true, // Default to selected since user chose to provide custom content
681
- path: customInfo.path, // Track path to avoid duplicates
682
- });
683
- }
670
+ for (const customFile of customFiles) {
671
+ const customInfo = await customHandler.getCustomInfo(customFile);
672
+ if (customInfo) {
673
+ customContentItems.push({
674
+ name: `${chalk.cyan('✓')} ${customInfo.name} ${chalk.gray(`(${customInfo.relativePath})`)}`,
675
+ value: `__CUSTOM_CONTENT__${customFile}`, // Unique value for each custom content
676
+ checked: true, // Default to selected since user chose to provide custom content
677
+ path: customInfo.path, // Track path to avoid duplicates
678
+ });
684
679
  }
685
680
  }
686
681
  }
687
682
 
688
683
  // Add official modules
689
684
  const { ModuleManager } = require('../installers/lib/modules/manager');
690
- // For new installations, don't scan project yet (will do after custom content is discovered)
691
- // For existing installations, scan if user selected custom content
692
- const shouldScanProject =
693
- !isNewInstallation && customContentConfig && customContentConfig.hasCustomContent && customContentConfig.selected;
694
- const moduleManager = new ModuleManager({
695
- scanProjectForModules: shouldScanProject,
696
- });
697
- const { modules: availableModules, customModules: customModulesFromProject } = await moduleManager.listAvailable();
685
+ const moduleManager = new ModuleManager();
686
+ const { modules: availableModules, customModules: customModulesFromCache } = await moduleManager.listAvailable();
698
687
 
699
688
  // First, add all items to appropriate sections
700
689
  const allCustomModules = [];
@@ -702,14 +691,14 @@ class UI {
702
691
  // Add custom content items from directory
703
692
  allCustomModules.push(...customContentItems);
704
693
 
705
- // Add custom modules from project scan (if scanning is enabled)
706
- for (const mod of customModulesFromProject) {
694
+ // Add custom modules from cache
695
+ for (const mod of customModulesFromCache) {
707
696
  // Skip if this module is already in customContentItems (by path)
708
697
  const isDuplicate = allCustomModules.some((item) => item.path && mod.path && path.resolve(item.path) === path.resolve(mod.path));
709
698
 
710
699
  if (!isDuplicate) {
711
700
  allCustomModules.push({
712
- name: `${chalk.cyan('✓')} ${mod.name} ${chalk.gray(`(${mod.source})`)}`,
701
+ name: `${chalk.cyan('✓')} ${mod.name} ${chalk.gray(`(cached)`)}`,
713
702
  value: mod.id,
714
703
  checked: isNewInstallation ? mod.defaultSelected || false : installedModuleIds.has(mod.id),
715
704
  });
@@ -745,19 +734,20 @@ class UI {
745
734
  * @param {Array} moduleChoices - Available module choices
746
735
  * @returns {Array} Selected module IDs
747
736
  */
748
- async selectModules(moduleChoices) {
749
- CLIUtils.displaySection('Module Selection', 'Choose the BMAD modules to install');
750
-
737
+ async selectModules(moduleChoices, defaultSelections = []) {
751
738
  const moduleAnswer = await inquirer.prompt([
752
739
  {
753
740
  type: 'checkbox',
754
741
  name: 'modules',
755
742
  message: 'Select modules to install:',
756
743
  choices: moduleChoices,
744
+ default: defaultSelections,
757
745
  },
758
746
  ]);
759
747
 
760
- return moduleAnswer.modules || [];
748
+ const selected = moduleAnswer.modules || [];
749
+
750
+ return selected;
761
751
  }
762
752
 
763
753
  /**
@@ -797,15 +787,16 @@ class UI {
797
787
  if (stats.isDirectory()) {
798
788
  const files = await fs.readdir(directory);
799
789
  if (files.length > 0) {
800
- // Check for any bmad installation (any folder with _cfg/manifest.yaml)
790
+ // Check for any bmad installation (any folder with _config/manifest.yaml)
801
791
  const { Installer } = require('../installers/lib/core/installer');
802
792
  const installer = new Installer();
803
- const bmadDir = await installer.findBmadDir(directory);
804
- const hasBmadInstall = (await fs.pathExists(bmadDir)) && (await fs.pathExists(path.join(bmadDir, '_cfg', 'manifest.yaml')));
793
+ const bmadResult = await installer.findBmadDir(directory);
794
+ const hasBmadInstall =
795
+ (await fs.pathExists(bmadResult.bmadDir)) && (await fs.pathExists(path.join(bmadResult.bmadDir, '_config', 'manifest.yaml')));
805
796
 
806
797
  console.log(
807
798
  chalk.gray(`Directory exists and contains ${files.length} item(s)`) +
808
- (hasBmadInstall ? chalk.yellow(` including existing BMAD installation (${path.basename(bmadDir)})`) : ''),
799
+ (hasBmadInstall ? chalk.yellow(` including existing BMAD installation (${path.basename(bmadResult.bmadDir)})`) : ''),
809
800
  );
810
801
  } else {
811
802
  console.log(chalk.gray('Directory exists and is empty'));
@@ -814,116 +805,6 @@ class UI {
814
805
  }
815
806
  }
816
807
 
817
- /**
818
- * Prompt for custom content location
819
- * @returns {Object} Custom content configuration
820
- */
821
- async promptCustomContentLocation() {
822
- try {
823
- CLIUtils.displaySection('Custom Content', 'Optional: Add custom agents, workflows, and modules');
824
-
825
- const { hasCustomContent } = await inquirer.prompt([
826
- {
827
- type: 'list',
828
- name: 'hasCustomContent',
829
- message: 'Do you have custom content to install?',
830
- choices: [
831
- { name: 'No (skip custom content)', value: 'none' },
832
- { name: 'Enter a directory path', value: 'directory' },
833
- { name: 'Enter a URL', value: 'url' },
834
- ],
835
- default: 'none',
836
- },
837
- ]);
838
-
839
- if (hasCustomContent === 'none') {
840
- return { hasCustomContent: false };
841
- }
842
-
843
- if (hasCustomContent === 'url') {
844
- console.log(chalk.yellow('\nURL-based custom content installation is coming soon!'));
845
- console.log(chalk.cyan('For now, please download your custom content and choose "Enter a directory path".\n'));
846
- return { hasCustomContent: false };
847
- }
848
-
849
- if (hasCustomContent === 'directory') {
850
- let customPath;
851
- while (!customPath) {
852
- let expandedPath;
853
- const { directory } = await inquirer.prompt([
854
- {
855
- type: 'input',
856
- name: 'directory',
857
- message: 'Enter directory to search for custom content (will scan subfolders):',
858
- default: process.cwd(), // Use actual current working directory
859
- validate: async (input) => {
860
- if (!input || input.trim() === '') {
861
- return 'Please enter a directory path';
862
- }
863
-
864
- try {
865
- expandedPath = this.expandUserPath(input.trim());
866
- } catch (error) {
867
- return error.message;
868
- }
869
-
870
- // Check if the path exists
871
- const pathExists = await fs.pathExists(expandedPath);
872
- if (!pathExists) {
873
- return 'Directory does not exist';
874
- }
875
-
876
- return true;
877
- },
878
- },
879
- ]);
880
-
881
- // Now expand the path for use after the prompt
882
- expandedPath = this.expandUserPath(directory.trim());
883
-
884
- // Check if directory has custom content
885
- const { CustomHandler } = require('../installers/lib/custom/handler');
886
- const customHandler = new CustomHandler();
887
- const customFiles = await customHandler.findCustomContent(expandedPath);
888
-
889
- if (customFiles.length === 0) {
890
- console.log(chalk.yellow(`\nNo custom content found in ${expandedPath}`));
891
-
892
- const { tryAgain } = await inquirer.prompt([
893
- {
894
- type: 'confirm',
895
- name: 'tryAgain',
896
- message: 'Try a different directory?',
897
- default: true,
898
- },
899
- ]);
900
-
901
- if (tryAgain) {
902
- continue;
903
- } else {
904
- return { hasCustomContent: false };
905
- }
906
- }
907
-
908
- customPath = expandedPath;
909
- console.log(chalk.green(`\n✓ Found ${customFiles.length} custom content item(s):`));
910
- for (const file of customFiles) {
911
- const relativePath = path.relative(expandedPath, path.dirname(file));
912
- const folderName = path.dirname(file).split(path.sep).pop();
913
- console.log(chalk.dim(` • ${folderName} ${chalk.gray(`(${relativePath})`)}`));
914
- }
915
- }
916
-
917
- return { hasCustomContent: true, customPath };
918
- }
919
-
920
- return { hasCustomContent: false };
921
- } catch (error) {
922
- console.error(chalk.red('Error in custom content prompt:'), error);
923
- return { hasCustomContent: false };
924
- }
925
- }
926
-
927
808
  /**
928
809
  * Confirm directory selection
929
810
  * @param {string} directory - The directory path
@@ -1088,7 +969,7 @@ class UI {
1088
969
  * @calls checkAgentVibesInstalled(), inquirer.prompt(), chalk.green/yellow/dim()
1089
970
  *
1090
971
  * AI NOTE: This prompt is strategically positioned in installation flow:
1091
- * - AFTER core config (bmad_folder, user_name, etc)
972
+ * - AFTER core config (user_name, etc)
1092
973
  * - BEFORE IDE selection (which can hang on Windows/PowerShell)
1093
974
  *
1094
975
  * Flow Logic:
@@ -1211,141 +1092,319 @@ class UI {
1211
1092
  }
1212
1093
 
1213
1094
  /**
1214
- * Prompt for custom content for existing installations
1215
- * @returns {Object} Custom content configuration
1095
+ * Load existing configurations to use as defaults
1096
+ * @param {string} directory - Installation directory
1097
+ * @returns {Object} Existing configurations
1216
1098
  */
1217
- async promptCustomContentForExisting() {
1099
+ async loadExistingConfigurations(directory) {
1100
+ const configs = {
1101
+ hasCustomContent: false,
1102
+ coreConfig: {},
1103
+ ideConfig: { ides: [], skipIde: false },
1104
+ agentVibesConfig: { enabled: false, alreadyInstalled: false },
1105
+ };
1106
+
1218
1107
  try {
1219
- CLIUtils.displaySection('Custom Content', 'Add new custom agents, workflows, or modules to your installation');
1108
+ // Load core config
1109
+ configs.coreConfig = await this.collectCoreConfig(directory);
1110
+
1111
+ // Load IDE configuration
1112
+ const configuredIdes = await this.getConfiguredIdes(directory);
1113
+ if (configuredIdes.length > 0) {
1114
+ configs.ideConfig.ides = configuredIdes;
1115
+ configs.ideConfig.skipIde = false;
1116
+ }
1220
1117
 
1221
- const { hasCustomContent } = await inquirer.prompt([
1222
- {
1223
- type: 'list',
1224
- name: 'hasCustomContent',
1225
- message: 'Do you want to add or update custom content?',
1226
- choices: [
1227
- {
1228
- name: 'No, continue with current installation only',
1229
- value: false,
1230
- },
1231
- {
1232
- name: 'Yes, I have custom content to add or update',
1233
- value: true,
1234
- },
1235
- ],
1236
- default: false,
1237
- },
1238
- ]);
1118
+ // Load AgentVibes configuration
1119
+ const agentVibesInstalled = await this.checkAgentVibesInstalled(directory);
1120
+ configs.agentVibesConfig = { enabled: agentVibesInstalled, alreadyInstalled: agentVibesInstalled };
1239
1121
 
1240
- if (!hasCustomContent) {
1241
- return { hasCustomContent: false };
1242
- }
1122
+ return configs;
1123
+ } catch {
1124
+ // If loading fails, return empty configs
1125
+ console.warn('Warning: Could not load existing configurations');
1126
+ return configs;
1127
+ }
1128
+ }
1243
1129
 
1244
- // Get directory path
1245
- const { customPath } = await inquirer.prompt([
1246
- {
1247
- type: 'input',
1248
- name: 'customPath',
1249
- message: 'Enter directory to search for custom content (will scan subfolders):',
1250
- default: process.cwd(),
1251
- validate: async (input) => {
1252
- if (!input || input.trim() === '') {
1253
- return 'Please enter a directory path';
1254
- }
1255
-
1256
- // Normalize and check if path exists
1257
- const expandedPath = CLIUtils.expandPath(input.trim());
1258
- const pathExists = await fs.pathExists(expandedPath);
1259
- if (!pathExists) {
1260
- return 'Directory does not exist';
1261
- }
1262
-
1263
- // Check if it's actually a directory
1264
- const stats = await fs.stat(expandedPath);
1265
- if (!stats.isDirectory()) {
1266
- return 'Path must be a directory';
1267
- }
1268
-
1269
- return true;
1270
- },
1271
- transformer: (input) => {
1272
- return CLIUtils.expandPath(input);
1273
- },
1274
- },
1275
- ]);
1130
+ /**
1131
+ * Get configured IDEs from existing installation
1132
+ * @param {string} directory - Installation directory
1133
+ * @returns {Array} List of configured IDEs
1134
+ */
1135
+ async getConfiguredIdes(directory) {
1136
+ const { Detector } = require('../installers/lib/core/detector');
1137
+ const { Installer } = require('../installers/lib/core/installer');
1138
+ const detector = new Detector();
1139
+ const installer = new Installer();
1140
+ const bmadResult = await installer.findBmadDir(directory);
1141
+ const existingInstall = await detector.detect(bmadResult.bmadDir);
1142
+ return existingInstall.ides || [];
1143
+ }
1276
1144
 
1277
- const resolvedPath = CLIUtils.expandPath(customPath);
1145
+ /**
1146
+ * Prompt user for custom content source location
1147
+ * @returns {Object} Custom content configuration
1148
+ */
1149
+ async promptCustomContentSource() {
1150
+ const customContentConfig = { hasCustomContent: true, sources: [] };
1151
+
1152
+ // Keep asking for more sources until user is done
1153
+ while (true) {
1154
+ // First ask if user wants to add another module or continue
1155
+ if (customContentConfig.sources.length > 0) {
1156
+ const { action } = await inquirer.prompt([
1157
+ {
1158
+ type: 'list',
1159
+ name: 'action',
1160
+ message: 'Would you like to:',
1161
+ choices: [
1162
+ { name: 'Add another custom module', value: 'add' },
1163
+ { name: 'Continue with installation', value: 'continue' },
1164
+ ],
1165
+ default: 'continue',
1166
+ },
1167
+ ]);
1278
1168
 
1279
- // Find custom content
1280
- const { CustomHandler } = require('../installers/lib/custom/handler');
1281
- const customHandler = new CustomHandler();
1282
- const customFiles = await customHandler.findCustomContent(resolvedPath);
1169
+ if (action === 'continue') {
1170
+ break;
1171
+ }
1172
+ }
1283
1173
 
1284
- if (customFiles.length === 0) {
1285
- console.log(chalk.yellow(`\nNo custom content found in ${resolvedPath}`));
1174
+ let sourcePath;
1175
+ let isValid = false;
1286
1176
 
1287
- const { tryDifferent } = await inquirer.prompt([
1177
+ while (!isValid) {
1178
+ const { path: inputPath } = await inquirer.prompt([
1288
1179
  {
1289
- type: 'confirm',
1290
- name: 'tryDifferent',
1291
- message: 'Try a different directory?',
1292
- default: true,
1180
+ type: 'input',
1181
+ name: 'path',
1182
+ message: 'Enter the path to your custom content folder (or press Enter to cancel):',
1183
+ validate: async (input) => {
1184
+ // Allow empty input to cancel
1185
+ if (!input || input.trim() === '') {
1186
+ return true; // Allow empty to exit
1187
+ }
1188
+
1189
+ try {
1190
+ // Expand the path
1191
+ const expandedPath = this.expandUserPath(input.trim());
1192
+
1193
+ // Check if path exists
1194
+ if (!(await fs.pathExists(expandedPath))) {
1195
+ return 'Path does not exist';
1196
+ }
1197
+
1198
+ // Check if it's a directory
1199
+ const stat = await fs.stat(expandedPath);
1200
+ if (!stat.isDirectory()) {
1201
+ return 'Path must be a directory';
1202
+ }
1203
+
1204
+ // Check for module.yaml in the root
1205
+ const moduleYamlPath = path.join(expandedPath, 'module.yaml');
1206
+ if (!(await fs.pathExists(moduleYamlPath))) {
1207
+ return 'Directory must contain a module.yaml file in the root';
1208
+ }
1209
+
1210
+ // Try to parse the module.yaml to get the module ID
1211
+ try {
1212
+ const yaml = require('yaml');
1213
+ const content = await fs.readFile(moduleYamlPath, 'utf8');
1214
+ const moduleData = yaml.parse(content);
1215
+ if (!moduleData.code) {
1216
+ return 'module.yaml must contain a "code" field for the module ID';
1217
+ }
1218
+ } catch (error) {
1219
+ return 'Invalid module.yaml file: ' + error.message;
1220
+ }
1221
+
1222
+ return true;
1223
+ } catch (error) {
1224
+ return 'Error validating path: ' + error.message;
1225
+ }
1226
+ },
1293
1227
  },
1294
1228
  ]);
1295
1229
 
1296
- if (tryDifferent) {
1297
- return await this.promptCustomContentForExisting();
1230
+ // If user pressed Enter without typing anything, exit the loop
1231
+ if (!inputPath || inputPath.trim() === '') {
1232
+ // If we have no modules yet, return false for no custom content
1233
+ if (customContentConfig.sources.length === 0) {
1234
+ return { hasCustomContent: false };
1235
+ }
1236
+ return customContentConfig;
1298
1237
  }
1299
1238
 
1300
- return { hasCustomContent: false };
1239
+ sourcePath = this.expandUserPath(inputPath);
1240
+ isValid = true;
1301
1241
  }
1302
1242
 
1303
- // Display found items
1304
- console.log(chalk.cyan(`\nFound ${customFiles.length} custom content file(s):`));
1305
- const { CustomHandler: CustomHandler2 } = require('../installers/lib/custom/handler');
1306
- const customHandler2 = new CustomHandler2();
1307
- const customContentItems = [];
1243
+ // Read module.yaml to get module info
1244
+ const yaml = require('yaml');
1245
+ const moduleYamlPath = path.join(sourcePath, 'module.yaml');
1246
+ const moduleContent = await fs.readFile(moduleYamlPath, 'utf8');
1247
+ const moduleData = yaml.parse(moduleContent);
1308
1248
 
1309
- for (const customFile of customFiles) {
1310
- const customInfo = await customHandler2.getCustomInfo(customFile);
1311
- if (customInfo) {
1312
- customContentItems.push({
1313
- name: `${chalk.cyan('✓')} ${customInfo.name} ${chalk.gray(`(${customInfo.relativePath})`)}`,
1314
- value: `__CUSTOM_CONTENT__${customFile}`,
1315
- checked: true,
1316
- });
1249
+ // Add to sources
1250
+ customContentConfig.sources.push({
1251
+ path: sourcePath,
1252
+ id: moduleData.code,
1253
+ name: moduleData.name || moduleData.code,
1254
+ });
1255
+
1256
+ console.log(chalk.green(`✓ Confirmed local custom module: ${moduleData.name || moduleData.code}`));
1257
+ }
1258
+
1259
+ // Ask if user wants to add these to the installation
1260
+ const { shouldInstall } = await inquirer.prompt([
1261
+ {
1262
+ type: 'confirm',
1263
+ name: 'shouldInstall',
1264
+ message: `Install ${customContentConfig.sources.length} custom module(s) now?`,
1265
+ default: true,
1266
+ },
1267
+ ]);
1268
+
1269
+ if (shouldInstall) {
1270
+ customContentConfig.selected = true;
1271
+ // Store paths to module.yaml files, not directories
1272
+ customContentConfig.selectedFiles = customContentConfig.sources.map((s) => path.join(s.path, 'module.yaml'));
1273
+ // Also include module IDs for installation
1274
+ customContentConfig.selectedModuleIds = customContentConfig.sources.map((s) => s.id);
1275
+ }
1276
+
1277
+ return customContentConfig;
1278
+ }
1279
+
1280
+ /**
1281
+ * Handle custom modules in the modify flow
1282
+ * @param {string} directory - Installation directory
1283
+ * @param {Array} selectedModules - Currently selected modules
1284
+ * @returns {Object} Result with selected custom modules and custom content config
1285
+ */
1286
+ async handleCustomModulesInModifyFlow(directory, selectedModules) {
1287
+ // Get existing installation to find custom modules
1288
+ const { existingInstall } = await this.getExistingInstallation(directory);
1289
+
1290
+ // Check if there are any custom modules in cache
1291
+ const { Installer } = require('../installers/lib/core/installer');
1292
+ const installer = new Installer();
1293
+ const { bmadDir } = await installer.findBmadDir(directory);
1294
+
1295
+ const cacheDir = path.join(bmadDir, '_config', 'custom');
1296
+ const cachedCustomModules = [];
1297
+
1298
+ if (await fs.pathExists(cacheDir)) {
1299
+ const entries = await fs.readdir(cacheDir, { withFileTypes: true });
1300
+ for (const entry of entries) {
1301
+ if (entry.isDirectory()) {
1302
+ const moduleYamlPath = path.join(cacheDir, entry.name, 'module.yaml');
1303
+ if (await fs.pathExists(moduleYamlPath)) {
1304
+ const yaml = require('yaml');
1305
+ const content = await fs.readFile(moduleYamlPath, 'utf8');
1306
+ const moduleData = yaml.parse(content);
1307
+
1308
+ cachedCustomModules.push({
1309
+ id: entry.name,
1310
+ name: moduleData.name || entry.name,
1311
+ description: moduleData.description || 'Custom module from cache',
1312
+ checked: selectedModules.includes(entry.name),
1313
+ fromCache: true,
1314
+ });
1315
+ }
1317
1316
  }
1318
1317
  }
1318
+ }
1319
1319
 
1320
- // Add option to keep existing custom content
1321
- console.log(chalk.yellow('\nExisting custom modules will be preserved unless you remove them'));
1320
+ const result = {
1321
+ selectedCustomModules: [],
1322
+ customContentConfig: { hasCustomContent: false },
1323
+ };
1322
1324
 
1323
- const { selectedFiles } = await inquirer.prompt([
1324
- {
1325
- type: 'checkbox',
1326
- name: 'selectedFiles',
1327
- message: 'Select custom content to add:',
1328
- choices: customContentItems,
1329
- pageSize: 15,
1330
- validate: (answer) => {
1331
- if (answer.length === 0) {
1332
- return 'You must select at least one item';
1333
- }
1334
- return true;
1325
+ if (cachedCustomModules.length === 0) {
1326
+ return result;
1327
+ }
1328
+
1329
+ // Ask user about custom modules
1330
+ console.log(chalk.cyan('\n⚙️ Custom Modules'));
1331
+ console.log(chalk.dim('Found custom modules in your installation:'));
1332
+
1333
+ const { customAction } = await inquirer.prompt([
1334
+ {
1335
+ type: 'list',
1336
+ name: 'customAction',
1337
+ message: 'What would you like to do with custom modules?',
1338
+ choices: [
1339
+ { name: 'Keep all existing custom modules', value: 'keep' },
1340
+ { name: 'Select which custom modules to keep', value: 'select' },
1341
+ { name: 'Add new custom modules', value: 'add' },
1342
+ { name: 'Remove all custom modules', value: 'remove' },
1343
+ ],
1344
+ default: 'keep',
1345
+ },
1346
+ ]);
1347
+
1348
+ switch (customAction) {
1349
+ case 'keep': {
1350
+ // Keep all existing custom modules
1351
+ result.selectedCustomModules = cachedCustomModules.map((m) => m.id);
1352
+ console.log(chalk.dim(`Keeping ${result.selectedCustomModules.length} custom module(s)`));
1353
+ break;
1354
+ }
1355
+
1356
+ case 'select': {
1357
+ // Let user choose which to keep
1358
+ const choices = cachedCustomModules.map((m) => ({
1359
+ name: `${m.name} ${chalk.gray(`(${m.id})`)}`,
1360
+ value: m.id,
1361
+ }));
1362
+
1363
+ const { keepModules } = await inquirer.prompt([
1364
+ {
1365
+ type: 'checkbox',
1366
+ name: 'keepModules',
1367
+ message: 'Select custom modules to keep:',
1368
+ choices: choices,
1369
+ default: cachedCustomModules.filter((m) => m.checked).map((m) => m.id),
1335
1370
  },
1336
- },
1337
- ]);
1371
+ ]);
1372
+ result.selectedCustomModules = keepModules;
1373
+ break;
1374
+ }
1338
1375
 
1339
- return {
1340
- hasCustomContent: true,
1341
- customPath: resolvedPath,
1342
- selected: true,
1343
- selectedFiles: selectedFiles,
1344
- };
1345
- } catch (error) {
1346
- console.error(chalk.red('Error configuring custom content:'), error);
1347
- return { hasCustomContent: false };
1376
+ case 'add': {
1377
+ // First ask to keep existing ones
1378
+ const { keepExisting } = await inquirer.prompt([
1379
+ {
1380
+ type: 'confirm',
1381
+ name: 'keepExisting',
1382
+ message: 'Keep existing custom modules?',
1383
+ default: true,
1384
+ },
1385
+ ]);
1386
+
1387
+ if (keepExisting) {
1388
+ result.selectedCustomModules = cachedCustomModules.map((m) => m.id);
1389
+ }
1390
+
1391
+ // Then prompt for new ones (reuse existing method)
1392
+ const newCustomContent = await this.promptCustomContentSource();
1393
+ if (newCustomContent.hasCustomContent && newCustomContent.selected) {
1394
+ result.selectedCustomModules.push(...newCustomContent.selectedModuleIds);
1395
+ result.customContentConfig = newCustomContent;
1396
+ }
1397
+ break;
1398
+ }
1399
+
1400
+ case 'remove': {
1401
+ // Remove all custom modules
1402
+ console.log(chalk.yellow('All custom modules will be removed from the installation'));
1403
+ break;
1404
+ }
1348
1405
  }
1406
+
1407
+ return result;
1349
1408
  }
1350
1409
  }
1351
1410