bmad-method 5.1.3 → 6.0.0-alpha.1

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 (948) hide show
  1. package/.claude/commands/bmad/bmb/agents/bmad-builder.md +70 -0
  2. package/.claude/commands/bmad/bmb/workflows/README.md +67 -0
  3. package/.claude/commands/bmad/bmb/workflows/audit-workflow.md +15 -0
  4. package/.claude/commands/bmad/bmb/workflows/convert-legacy.md +15 -0
  5. package/.claude/commands/bmad/bmb/workflows/create-agent.md +15 -0
  6. package/.claude/commands/bmad/bmb/workflows/create-module.md +15 -0
  7. package/.claude/commands/bmad/bmb/workflows/create-workflow.md +15 -0
  8. package/.claude/commands/bmad/bmb/workflows/edit-agent.md +15 -0
  9. package/.claude/commands/bmad/bmb/workflows/edit-module.md +15 -0
  10. package/.claude/commands/bmad/bmb/workflows/edit-workflow.md +15 -0
  11. package/.claude/commands/bmad/bmb/workflows/module-brief.md +15 -0
  12. package/.claude/commands/bmad/bmb/workflows/redoc.md +15 -0
  13. package/.claude/commands/bmad/bmd/agents/cli-chief.md +108 -0
  14. package/.claude/commands/bmad/bmd/agents/doc-keeper.md +115 -0
  15. package/.claude/commands/bmad/bmd/agents/release-chief.md +109 -0
  16. package/.claude/commands/bmad/core/agents/bmad-master.md +71 -0
  17. package/.claude/commands/bmad/core/tasks/index-docs.md +9 -0
  18. package/.claude/commands/bmad/core/tools/shard-doc.md +9 -0
  19. package/.claude/commands/bmad/core/workflows/README.md +27 -0
  20. package/.claude/commands/bmad/core/workflows/brainstorming.md +15 -0
  21. package/.claude/commands/bmad/core/workflows/party-mode.md +15 -0
  22. package/.claude/hooks/bmad-tts-injector.sh +415 -0
  23. package/.claude/hooks/bmad-voice-manager.sh +511 -0
  24. package/.claude/hooks/check-output-style.sh +112 -0
  25. package/.claude/hooks/download-extra-voices.sh +244 -0
  26. package/.claude/hooks/github-star-reminder.sh +154 -0
  27. package/.claude/hooks/language-manager.sh +392 -0
  28. package/.claude/hooks/learn-manager.sh +475 -0
  29. package/.claude/hooks/personality-manager.sh +438 -0
  30. package/.claude/hooks/piper-download-voices.sh +165 -0
  31. package/.claude/hooks/piper-installer.sh +178 -0
  32. package/.claude/hooks/piper-multispeaker-registry.sh +165 -0
  33. package/.claude/hooks/piper-voice-manager.sh +293 -0
  34. package/.claude/hooks/play-tts-elevenlabs.sh +404 -0
  35. package/.claude/hooks/play-tts-piper.sh +338 -0
  36. package/.claude/hooks/play-tts.sh +100 -0
  37. package/.claude/hooks/provider-commands.sh +540 -0
  38. package/.claude/hooks/provider-manager.sh +298 -0
  39. package/.claude/hooks/replay-target-audio.sh +95 -0
  40. package/.claude/hooks/sentiment-manager.sh +201 -0
  41. package/.claude/hooks/speed-manager.sh +291 -0
  42. package/.claude/hooks/voice-manager.sh +594 -0
  43. package/.claude/hooks/voices-config.sh +70 -0
  44. package/.claude/settings.local.json +41 -0
  45. package/.github/FUNDING.yaml +2 -2
  46. package/.github/ISSUE_TEMPLATE/config.yaml +5 -0
  47. package/.github/ISSUE_TEMPLATE/idea_submission.md +109 -0
  48. package/.github/workflows/discord.yaml +1 -10
  49. package/.github/workflows/{format-check.yaml → lint.yaml} +22 -3
  50. package/.github/workflows/manual-release.yaml +2 -2
  51. package/.nvmrc +1 -0
  52. package/.prettierignore +2 -0
  53. package/.vscode/settings.json +34 -9
  54. package/CHANGELOG.md +214 -574
  55. package/CONTRIBUTING.md +131 -60
  56. package/LICENSE +6 -1
  57. package/README.md +188 -148
  58. package/bmad/_cfg/agent-manifest.csv +7 -0
  59. package/bmad/_cfg/agents/bmb-bmad-builder.customize.yaml +42 -0
  60. package/bmad/_cfg/agents/bmd-cli-chief.customize.yaml +32 -0
  61. package/bmad/_cfg/agents/bmd-doc-keeper.customize.yaml +42 -0
  62. package/bmad/_cfg/agents/bmd-release-chief.customize.yaml +42 -0
  63. package/bmad/_cfg/agents/core-bmad-master.customize.yaml +42 -0
  64. package/bmad/_cfg/files-manifest.csv +83 -0
  65. package/bmad/_cfg/manifest.yaml +12 -0
  66. package/bmad/_cfg/task-manifest.csv +5 -0
  67. package/bmad/_cfg/tool-manifest.csv +2 -0
  68. package/bmad/_cfg/workflow-manifest.csv +15 -0
  69. package/bmad/bmb/README.md +132 -0
  70. package/bmad/bmb/agents/bmad-builder.md +70 -0
  71. package/bmad/bmb/config.yaml +14 -0
  72. package/bmad/bmb/workflows/audit-workflow/checklist.md +143 -0
  73. package/bmad/bmb/workflows/audit-workflow/instructions.md +341 -0
  74. package/bmad/bmb/workflows/audit-workflow/template.md +118 -0
  75. package/bmad/bmb/workflows/audit-workflow/workflow.yaml +23 -0
  76. package/bmad/bmb/workflows/audit-workflow/workflow.yaml.bak +21 -0
  77. package/bmad/bmb/workflows/convert-legacy/README.md +262 -0
  78. package/bmad/bmb/workflows/convert-legacy/checklist.md +205 -0
  79. package/bmad/bmb/workflows/convert-legacy/instructions.md +377 -0
  80. package/bmad/bmb/workflows/convert-legacy/workflow.yaml +32 -0
  81. package/bmad/bmb/workflows/create-agent/README.md +320 -0
  82. package/bmad/bmb/workflows/create-agent/agent-architecture.md +419 -0
  83. package/bmad/bmb/workflows/create-agent/agent-architecture.md.bak +412 -0
  84. package/bmad/bmb/workflows/create-agent/agent-command-patterns.md +759 -0
  85. package/bmad/bmb/workflows/create-agent/agent-command-patterns.md.bak +759 -0
  86. package/bmad/bmb/workflows/create-agent/agent-types.md +292 -0
  87. package/bmad/bmb/workflows/create-agent/brainstorm-context.md +174 -0
  88. package/bmad/bmb/workflows/create-agent/checklist.md +62 -0
  89. package/bmad/bmb/workflows/create-agent/communication-styles.md +202 -0
  90. package/bmad/bmb/workflows/create-agent/instructions.md +430 -0
  91. package/bmad/bmb/workflows/create-agent/workflow.yaml +37 -0
  92. package/bmad/bmb/workflows/create-module/README.md +220 -0
  93. package/bmad/bmb/workflows/create-module/README.md.bak +218 -0
  94. package/bmad/bmb/workflows/create-module/brainstorm-context.md +137 -0
  95. package/bmad/bmb/workflows/create-module/checklist.md +244 -0
  96. package/bmad/bmb/workflows/create-module/checklist.md.bak +245 -0
  97. package/bmad/bmb/workflows/create-module/installer-templates/install-config.yaml +92 -0
  98. package/bmad/bmb/workflows/create-module/installer-templates/installer.js +231 -0
  99. package/bmad/bmb/workflows/create-module/installer-templates/installer.js.bak +231 -0
  100. package/bmad/bmb/workflows/create-module/instructions.md +581 -0
  101. package/bmad/bmb/workflows/create-module/instructions.md.bak +521 -0
  102. package/bmad/bmb/workflows/create-module/module-structure.md +366 -0
  103. package/bmad/bmb/workflows/create-module/module-structure.md.bak +310 -0
  104. package/bmad/bmb/workflows/create-module/workflow.yaml +42 -0
  105. package/bmad/bmb/workflows/create-module/workflow.yaml.bak +40 -0
  106. package/bmad/bmb/workflows/create-workflow/README.md +277 -0
  107. package/bmad/bmb/workflows/create-workflow/brainstorm-context.md +197 -0
  108. package/bmad/bmb/workflows/create-workflow/checklist.md +94 -0
  109. package/bmad/bmb/workflows/create-workflow/instructions.md +716 -0
  110. package/bmad/bmb/workflows/create-workflow/workflow-creation-guide.md +1150 -0
  111. package/bmad/bmb/workflows/create-workflow/workflow-template/checklist.md +24 -0
  112. package/bmad/bmb/workflows/create-workflow/workflow-template/instructions.md +13 -0
  113. package/bmad/bmb/workflows/create-workflow/workflow-template/template.md +9 -0
  114. package/bmad/bmb/workflows/create-workflow/workflow-template/workflow.yaml +39 -0
  115. package/bmad/bmb/workflows/create-workflow/workflow-template/workflow.yaml.bak +39 -0
  116. package/bmad/bmb/workflows/create-workflow/workflow.yaml +40 -0
  117. package/bmad/bmb/workflows/create-workflow/workflow.yaml.bak +38 -0
  118. package/bmad/bmb/workflows/edit-agent/README.md +112 -0
  119. package/bmad/bmb/workflows/edit-agent/checklist.md +112 -0
  120. package/bmad/bmb/workflows/edit-agent/instructions.md +290 -0
  121. package/bmad/bmb/workflows/edit-agent/workflow.yaml +33 -0
  122. package/bmad/bmb/workflows/edit-module/README.md +187 -0
  123. package/bmad/bmb/workflows/edit-module/checklist.md +165 -0
  124. package/bmad/bmb/workflows/edit-module/instructions.md +339 -0
  125. package/bmad/bmb/workflows/edit-module/workflow.yaml +34 -0
  126. package/bmad/bmb/workflows/edit-workflow/README.md +119 -0
  127. package/bmad/bmb/workflows/edit-workflow/checklist.md +70 -0
  128. package/bmad/bmb/workflows/edit-workflow/instructions.md +342 -0
  129. package/bmad/bmb/workflows/edit-workflow/workflow.yaml +27 -0
  130. package/bmad/bmb/workflows/edit-workflow/workflow.yaml.bak +25 -0
  131. package/bmad/bmb/workflows/module-brief/README.md +264 -0
  132. package/bmad/bmb/workflows/module-brief/checklist.md +116 -0
  133. package/bmad/bmb/workflows/module-brief/instructions.md +267 -0
  134. package/bmad/bmb/workflows/module-brief/template.md +275 -0
  135. package/bmad/bmb/workflows/module-brief/workflow.yaml +29 -0
  136. package/bmad/bmb/workflows/module-brief/workflow.yaml.bak +27 -0
  137. package/bmad/bmb/workflows/redoc/README.md +87 -0
  138. package/bmad/bmb/workflows/redoc/checklist.md +99 -0
  139. package/bmad/bmb/workflows/redoc/instructions.md +265 -0
  140. package/bmad/bmb/workflows/redoc/workflow.yaml +32 -0
  141. package/bmad/bmb/workflows/redoc/workflow.yaml.bak +31 -0
  142. package/bmad/bmd/README.md +193 -0
  143. package/bmad/bmd/README.md.bak +193 -0
  144. package/bmad/bmd/agents/cli-chief-sidecar/instructions.md +102 -0
  145. package/bmad/bmd/agents/cli-chief-sidecar/instructions.md.bak +102 -0
  146. package/bmad/bmd/agents/cli-chief-sidecar/knowledge/README.md +68 -0
  147. package/bmad/bmd/agents/cli-chief-sidecar/knowledge/README.md.bak +68 -0
  148. package/bmad/bmd/agents/cli-chief-sidecar/knowledge/cli-reference.md +123 -0
  149. package/bmad/bmd/agents/cli-chief-sidecar/knowledge/cli-reference.md.bak +123 -0
  150. package/bmad/bmd/agents/cli-chief-sidecar/memories.md +53 -0
  151. package/bmad/bmd/agents/cli-chief-sidecar/memories.md.bak +53 -0
  152. package/bmad/bmd/agents/cli-chief.md +108 -0
  153. package/bmad/bmd/agents/cli-chief.md.bak +108 -0
  154. package/bmad/bmd/agents/doc-keeper-sidecar/instructions.md +177 -0
  155. package/bmad/bmd/agents/doc-keeper-sidecar/instructions.md.bak +177 -0
  156. package/bmad/bmd/agents/doc-keeper-sidecar/knowledge/README.md +81 -0
  157. package/bmad/bmd/agents/doc-keeper-sidecar/knowledge/README.md.bak +81 -0
  158. package/bmad/bmd/agents/doc-keeper-sidecar/memories.md +88 -0
  159. package/bmad/bmd/agents/doc-keeper-sidecar/memories.md.bak +88 -0
  160. package/bmad/bmd/agents/doc-keeper.md +115 -0
  161. package/bmad/bmd/agents/doc-keeper.md.bak +115 -0
  162. package/bmad/bmd/agents/release-chief-sidecar/instructions.md +164 -0
  163. package/bmad/bmd/agents/release-chief-sidecar/instructions.md.bak +164 -0
  164. package/bmad/bmd/agents/release-chief-sidecar/knowledge/README.md +82 -0
  165. package/bmad/bmd/agents/release-chief-sidecar/knowledge/README.md.bak +82 -0
  166. package/bmad/bmd/agents/release-chief-sidecar/memories.md +73 -0
  167. package/bmad/bmd/agents/release-chief-sidecar/memories.md.bak +73 -0
  168. package/bmad/bmd/agents/release-chief.md +109 -0
  169. package/bmad/bmd/agents/release-chief.md.bak +109 -0
  170. package/bmad/bmd/config.yaml +10 -0
  171. package/bmad/core/agents/bmad-master.md +71 -0
  172. package/bmad/core/agents/bmad-web-orchestrator.agent.xml +122 -0
  173. package/bmad/core/config.yaml +9 -0
  174. package/bmad/core/tasks/adv-elicit-methods.csv +39 -0
  175. package/bmad/core/tasks/adv-elicit.xml +104 -0
  176. package/bmad/core/tasks/index-docs.xml +65 -0
  177. package/bmad/core/tasks/validate-workflow.xml +89 -0
  178. package/bmad/core/tasks/workflow.xml +174 -0
  179. package/bmad/core/tools/shard-doc.xml +100 -0
  180. package/bmad/core/workflows/brainstorming/README.md +271 -0
  181. package/bmad/core/workflows/brainstorming/brain-methods.csv +36 -0
  182. package/bmad/core/workflows/brainstorming/instructions.md +314 -0
  183. package/bmad/core/workflows/brainstorming/template.md +102 -0
  184. package/bmad/core/workflows/brainstorming/workflow.yaml +43 -0
  185. package/bmad/core/workflows/party-mode/instructions.md +188 -0
  186. package/bmad/core/workflows/party-mode/workflow.yaml +23 -0
  187. package/bmad/docs/claude-code-instructions.md +25 -0
  188. package/bmad/docs/codex-instructions.md +21 -0
  189. package/bmd/README.md +193 -0
  190. package/bmd/agents/cli-chief-sidecar/instructions.md +102 -0
  191. package/bmd/agents/cli-chief-sidecar/knowledge/README.md +68 -0
  192. package/bmd/agents/cli-chief-sidecar/knowledge/cli-reference.md +123 -0
  193. package/bmd/agents/cli-chief-sidecar/memories.md +53 -0
  194. package/bmd/agents/cli-chief.agent.yaml +126 -0
  195. package/bmd/agents/doc-keeper-sidecar/instructions.md +177 -0
  196. package/bmd/agents/doc-keeper-sidecar/knowledge/README.md +81 -0
  197. package/bmd/agents/doc-keeper-sidecar/memories.md +88 -0
  198. package/bmd/agents/doc-keeper.agent.yaml +137 -0
  199. package/bmd/agents/release-chief-sidecar/instructions.md +164 -0
  200. package/bmd/agents/release-chief-sidecar/knowledge/README.md +82 -0
  201. package/bmd/agents/release-chief-sidecar/memories.md +73 -0
  202. package/bmd/agents/release-chief.agent.yaml +127 -0
  203. package/bmd/bmad-custom-module-installer-plan.md +1176 -0
  204. package/bmd/config.yaml +12 -0
  205. package/docs/bmad-brownfield-guide.md +1260 -0
  206. package/docs/conversion-report-shard-doc-2025-10-26.md +188 -0
  207. package/docs/ide-info/auggie.md +31 -0
  208. package/docs/ide-info/claude-code.md +25 -0
  209. package/docs/ide-info/cline.md +31 -0
  210. package/docs/ide-info/codex.md +21 -0
  211. package/docs/ide-info/crush.md +30 -0
  212. package/docs/ide-info/cursor.md +25 -0
  213. package/docs/ide-info/gemini.md +25 -0
  214. package/docs/ide-info/github-copilot.md +26 -0
  215. package/docs/ide-info/iflow.md +33 -0
  216. package/docs/ide-info/kilo.md +24 -0
  217. package/docs/ide-info/opencode.md +24 -0
  218. package/docs/ide-info/qwen.md +25 -0
  219. package/docs/ide-info/roo.md +27 -0
  220. package/docs/ide-info/trae.md +25 -0
  221. package/docs/ide-info/windsurf.md +22 -0
  222. package/docs/installers-bundlers/ide-injections.md +186 -0
  223. package/docs/installers-bundlers/installers-modules-platforms-reference.md +327 -0
  224. package/docs/installers-bundlers/web-bundler-usage.md +54 -0
  225. package/docs/v4-to-v6-upgrade.md +225 -0
  226. package/eslint.config.mjs +21 -9
  227. package/package.json +32 -36
  228. package/prettier.config.mjs +1 -1
  229. package/src/core/_module-installer/install-config.yaml +28 -0
  230. package/src/core/_module-installer/installer.js +68 -0
  231. package/src/core/agents/bmad-master.agent.yaml +39 -0
  232. package/src/core/agents/bmad-web-orchestrator.agent.xml +122 -0
  233. package/src/core/tasks/adv-elicit-methods.csv +39 -0
  234. package/src/core/tasks/adv-elicit.xml +104 -0
  235. package/src/core/tasks/index-docs.xml +65 -0
  236. package/src/core/tasks/validate-workflow.xml +89 -0
  237. package/src/core/tasks/workflow.xml +166 -0
  238. package/src/core/tools/shard-doc.xml +100 -0
  239. package/src/core/workflows/brainstorming/README.md +271 -0
  240. package/src/core/workflows/brainstorming/brain-methods.csv +36 -0
  241. package/src/core/workflows/brainstorming/instructions.md +314 -0
  242. package/src/core/workflows/brainstorming/template.md +102 -0
  243. package/src/core/workflows/brainstorming/workflow.yaml +43 -0
  244. package/src/core/workflows/party-mode/instructions.md +188 -0
  245. package/src/core/workflows/party-mode/workflow.yaml +23 -0
  246. package/src/modules/bmb/README.md +132 -0
  247. package/src/modules/bmb/_module-installer/install-config.yaml +26 -0
  248. package/src/modules/bmb/agents/bmad-builder.agent.yaml +58 -0
  249. package/src/modules/bmb/workflows/audit-workflow/checklist.md +143 -0
  250. package/src/modules/bmb/workflows/audit-workflow/instructions.md +341 -0
  251. package/src/modules/bmb/workflows/audit-workflow/template.md +118 -0
  252. package/src/modules/bmb/workflows/audit-workflow/workflow.yaml +25 -0
  253. package/src/modules/bmb/workflows/convert-legacy/README.md +262 -0
  254. package/src/modules/bmb/workflows/convert-legacy/checklist.md +205 -0
  255. package/src/modules/bmb/workflows/convert-legacy/instructions.md +377 -0
  256. package/src/modules/bmb/workflows/convert-legacy/workflow.yaml +34 -0
  257. package/src/modules/bmb/workflows/create-agent/README.md +320 -0
  258. package/src/modules/bmb/workflows/create-agent/agent-architecture.md +419 -0
  259. package/src/modules/bmb/workflows/create-agent/agent-command-patterns.md +759 -0
  260. package/src/modules/bmb/workflows/create-agent/agent-types.md +292 -0
  261. package/src/modules/bmb/workflows/create-agent/brainstorm-context.md +174 -0
  262. package/src/modules/bmb/workflows/create-agent/checklist.md +62 -0
  263. package/src/modules/bmb/workflows/create-agent/communication-styles.md +202 -0
  264. package/src/modules/bmb/workflows/create-agent/instructions.md +430 -0
  265. package/src/modules/bmb/workflows/create-agent/workflow.yaml +49 -0
  266. package/src/modules/bmb/workflows/create-module/README.md +220 -0
  267. package/src/modules/bmb/workflows/create-module/brainstorm-context.md +137 -0
  268. package/src/modules/bmb/workflows/create-module/checklist.md +244 -0
  269. package/src/modules/bmb/workflows/create-module/installer-templates/install-config.yaml +92 -0
  270. package/src/modules/bmb/workflows/create-module/installer-templates/installer.js +231 -0
  271. package/src/modules/bmb/workflows/create-module/instructions.md +581 -0
  272. package/src/modules/bmb/workflows/create-module/module-structure.md +366 -0
  273. package/src/modules/bmb/workflows/create-module/workflow.yaml +44 -0
  274. package/src/modules/bmb/workflows/create-workflow/README.md +277 -0
  275. package/src/modules/bmb/workflows/create-workflow/brainstorm-context.md +197 -0
  276. package/src/modules/bmb/workflows/create-workflow/checklist.md +94 -0
  277. package/src/modules/bmb/workflows/create-workflow/instructions.md +716 -0
  278. package/src/modules/bmb/workflows/create-workflow/workflow-creation-guide.md +1150 -0
  279. package/src/modules/bmb/workflows/create-workflow/workflow-template/checklist.md +24 -0
  280. package/src/modules/bmb/workflows/create-workflow/workflow-template/instructions.md +13 -0
  281. package/src/modules/bmb/workflows/create-workflow/workflow-template/template.md +9 -0
  282. package/src/modules/bmb/workflows/create-workflow/workflow-template/workflow.yaml +65 -0
  283. package/src/modules/bmb/workflows/create-workflow/workflow.yaml +42 -0
  284. package/src/modules/bmb/workflows/edit-agent/README.md +112 -0
  285. package/src/modules/bmb/workflows/edit-agent/checklist.md +112 -0
  286. package/src/modules/bmb/workflows/edit-agent/instructions.md +290 -0
  287. package/src/modules/bmb/workflows/edit-agent/workflow.yaml +35 -0
  288. package/src/modules/bmb/workflows/edit-module/README.md +187 -0
  289. package/src/modules/bmb/workflows/edit-module/checklist.md +165 -0
  290. package/src/modules/bmb/workflows/edit-module/instructions.md +339 -0
  291. package/src/modules/bmb/workflows/edit-module/workflow.yaml +36 -0
  292. package/src/modules/bmb/workflows/edit-workflow/README.md +119 -0
  293. package/src/modules/bmb/workflows/edit-workflow/checklist.md +70 -0
  294. package/src/modules/bmb/workflows/edit-workflow/instructions.md +342 -0
  295. package/src/modules/bmb/workflows/edit-workflow/workflow.yaml +29 -0
  296. package/src/modules/bmb/workflows/module-brief/README.md +264 -0
  297. package/src/modules/bmb/workflows/module-brief/checklist.md +116 -0
  298. package/src/modules/bmb/workflows/module-brief/instructions.md +267 -0
  299. package/src/modules/bmb/workflows/module-brief/template.md +275 -0
  300. package/src/modules/bmb/workflows/module-brief/workflow.yaml +31 -0
  301. package/src/modules/bmb/workflows/redoc/README.md +87 -0
  302. package/src/modules/bmb/workflows/redoc/checklist.md +99 -0
  303. package/src/modules/bmb/workflows/redoc/instructions.md +265 -0
  304. package/src/modules/bmb/workflows/redoc/workflow.yaml +34 -0
  305. package/src/modules/bmm/README.md +141 -0
  306. package/src/modules/bmm/_module-installer/assets/bmm-kb.md +1 -0
  307. package/src/modules/bmm/_module-installer/assets/technical-decisions.md +30 -0
  308. package/src/modules/bmm/_module-installer/install-config.yaml +74 -0
  309. package/src/modules/bmm/_module-installer/installer.js +131 -0
  310. package/src/modules/bmm/_module-installer/platform-specifics/claude-code.js +35 -0
  311. package/src/modules/bmm/_module-installer/platform-specifics/windsurf.js +32 -0
  312. package/src/modules/bmm/agents/analyst.agent.yaml +43 -0
  313. package/src/modules/bmm/agents/architect.agent.yaml +41 -0
  314. package/src/modules/bmm/agents/dev.agent.yaml +43 -0
  315. package/src/modules/bmm/agents/game-architect.agent.yaml +35 -0
  316. package/src/modules/bmm/agents/game-designer.agent.yaml +47 -0
  317. package/src/modules/bmm/agents/game-dev.agent.yaml +39 -0
  318. package/src/modules/bmm/agents/pm.agent.yaml +50 -0
  319. package/src/modules/bmm/agents/sm.agent.yaml +67 -0
  320. package/src/modules/bmm/agents/tea.agent.yaml +59 -0
  321. package/src/modules/bmm/agents/ux-designer.agent.yaml +33 -0
  322. package/src/modules/bmm/sub-modules/claude-code/config.yaml +5 -0
  323. package/src/modules/bmm/sub-modules/claude-code/injections.yaml +242 -0
  324. package/src/modules/bmm/sub-modules/claude-code/readme.md +87 -0
  325. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-analysis/api-documenter.md +102 -0
  326. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-analysis/codebase-analyzer.md +82 -0
  327. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-analysis/data-analyst.md +101 -0
  328. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-analysis/pattern-detector.md +84 -0
  329. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-planning/dependency-mapper.md +83 -0
  330. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-planning/epic-optimizer.md +81 -0
  331. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-planning/requirements-analyst.md +61 -0
  332. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-planning/technical-decisions-curator.md +168 -0
  333. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-planning/trend-spotter.md +115 -0
  334. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-planning/user-journey-mapper.md +123 -0
  335. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-planning/user-researcher.md +72 -0
  336. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-research/market-researcher.md +51 -0
  337. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-research/tech-debt-auditor.md +106 -0
  338. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-review/document-reviewer.md +102 -0
  339. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-review/technical-evaluator.md +68 -0
  340. package/src/modules/bmm/sub-modules/claude-code/sub-agents/bmad-review/test-coverage-analyzer.md +108 -0
  341. package/src/modules/bmm/tasks/daily-standup.xml +85 -0
  342. package/src/modules/bmm/tasks/retrospective.xml +104 -0
  343. package/src/modules/bmm/teams/team-fullstack.yaml +11 -0
  344. package/src/modules/bmm/teams/team-gamedev.yaml +14 -0
  345. package/src/modules/bmm/testarch/README.md +311 -0
  346. package/src/modules/bmm/testarch/knowledge/ci-burn-in.md +675 -0
  347. package/src/modules/bmm/testarch/knowledge/component-tdd.md +486 -0
  348. package/src/modules/bmm/testarch/knowledge/contract-testing.md +957 -0
  349. package/src/modules/bmm/testarch/knowledge/data-factories.md +500 -0
  350. package/src/modules/bmm/testarch/knowledge/email-auth.md +721 -0
  351. package/src/modules/bmm/testarch/knowledge/error-handling.md +725 -0
  352. package/src/modules/bmm/testarch/knowledge/feature-flags.md +750 -0
  353. package/src/modules/bmm/testarch/knowledge/fixture-architecture.md +401 -0
  354. package/src/modules/bmm/testarch/knowledge/network-first.md +486 -0
  355. package/src/modules/bmm/testarch/knowledge/nfr-criteria.md +670 -0
  356. package/src/modules/bmm/testarch/knowledge/playwright-config.md +730 -0
  357. package/src/modules/bmm/testarch/knowledge/probability-impact.md +601 -0
  358. package/src/modules/bmm/testarch/knowledge/risk-governance.md +615 -0
  359. package/src/modules/bmm/testarch/knowledge/selective-testing.md +732 -0
  360. package/src/modules/bmm/testarch/knowledge/selector-resilience.md +527 -0
  361. package/src/modules/bmm/testarch/knowledge/test-healing-patterns.md +644 -0
  362. package/src/modules/bmm/testarch/knowledge/test-levels-framework.md +473 -0
  363. package/src/modules/bmm/testarch/knowledge/test-priorities-matrix.md +373 -0
  364. package/src/modules/bmm/testarch/knowledge/test-quality.md +664 -0
  365. package/src/modules/bmm/testarch/knowledge/timing-debugging.md +372 -0
  366. package/src/modules/bmm/testarch/knowledge/visual-debugging.md +524 -0
  367. package/src/modules/bmm/testarch/tea-index.csv +22 -0
  368. package/src/modules/bmm/workflows/1-analysis/brainstorm-game/README.md +38 -0
  369. package/src/modules/bmm/workflows/1-analysis/brainstorm-game/game-brain-methods.csv +26 -0
  370. package/src/modules/bmm/workflows/1-analysis/brainstorm-game/game-context.md +115 -0
  371. package/src/modules/bmm/workflows/1-analysis/brainstorm-game/instructions.md +109 -0
  372. package/src/modules/bmm/workflows/1-analysis/brainstorm-game/workflow.yaml +41 -0
  373. package/src/modules/bmm/workflows/1-analysis/brainstorm-project/README.md +29 -0
  374. package/src/modules/bmm/workflows/1-analysis/brainstorm-project/instructions.md +91 -0
  375. package/src/modules/bmm/workflows/1-analysis/brainstorm-project/project-context.md +25 -0
  376. package/src/modules/bmm/workflows/1-analysis/brainstorm-project/workflow.yaml +39 -0
  377. package/src/modules/bmm/workflows/1-analysis/game-brief/README.md +221 -0
  378. package/src/modules/bmm/workflows/1-analysis/game-brief/checklist.md +128 -0
  379. package/src/modules/bmm/workflows/1-analysis/game-brief/instructions.md +357 -0
  380. package/src/modules/bmm/workflows/1-analysis/game-brief/template.md +205 -0
  381. package/src/modules/bmm/workflows/1-analysis/game-brief/workflow.yaml +44 -0
  382. package/src/modules/bmm/workflows/1-analysis/product-brief/README.md +180 -0
  383. package/src/modules/bmm/workflows/1-analysis/product-brief/checklist.md +115 -0
  384. package/src/modules/bmm/workflows/1-analysis/product-brief/instructions.md +321 -0
  385. package/src/modules/bmm/workflows/1-analysis/product-brief/template.md +165 -0
  386. package/src/modules/bmm/workflows/1-analysis/product-brief/workflow.yaml +43 -0
  387. package/src/modules/bmm/workflows/1-analysis/research/README.md +454 -0
  388. package/src/modules/bmm/workflows/1-analysis/research/checklist.md +202 -0
  389. package/src/modules/bmm/workflows/1-analysis/research/claude-code/injections.yaml +114 -0
  390. package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-competitor-analyzer.md +259 -0
  391. package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-data-analyst.md +190 -0
  392. package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-market-researcher.md +337 -0
  393. package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-trend-spotter.md +107 -0
  394. package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-user-researcher.md +329 -0
  395. package/src/modules/bmm/workflows/1-analysis/research/instructions-deep-prompt.md +433 -0
  396. package/src/modules/bmm/workflows/1-analysis/research/instructions-market.md +613 -0
  397. package/src/modules/bmm/workflows/1-analysis/research/instructions-router.md +125 -0
  398. package/src/modules/bmm/workflows/1-analysis/research/instructions-technical.md +501 -0
  399. package/src/modules/bmm/workflows/1-analysis/research/template-deep-prompt.md +94 -0
  400. package/src/modules/bmm/workflows/1-analysis/research/template-market.md +311 -0
  401. package/src/modules/bmm/workflows/1-analysis/research/template-technical.md +210 -0
  402. package/src/modules/bmm/workflows/1-analysis/research/workflow.yaml +49 -0
  403. package/src/modules/bmm/workflows/2-plan-workflows/README.md +258 -0
  404. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/checklist.md +310 -0
  405. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/instructions.md +1283 -0
  406. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/ux-design-template.md +145 -0
  407. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml +42 -0
  408. package/src/modules/bmm/workflows/2-plan-workflows/gdd/README.md +222 -0
  409. package/src/modules/bmm/workflows/2-plan-workflows/gdd/checklist.md +148 -0
  410. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/action-platformer.md +45 -0
  411. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/adventure.md +84 -0
  412. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/card-game.md +76 -0
  413. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/fighting.md +89 -0
  414. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/horror.md +86 -0
  415. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/idle-incremental.md +78 -0
  416. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/metroidvania.md +87 -0
  417. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/moba.md +74 -0
  418. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/party-game.md +79 -0
  419. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/puzzle.md +58 -0
  420. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/racing.md +88 -0
  421. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/rhythm.md +79 -0
  422. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/roguelike.md +69 -0
  423. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/rpg.md +70 -0
  424. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/sandbox.md +79 -0
  425. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/shooter.md +62 -0
  426. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/simulation.md +73 -0
  427. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/sports.md +75 -0
  428. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/strategy.md +71 -0
  429. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/survival.md +79 -0
  430. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/text-based.md +91 -0
  431. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/tower-defense.md +79 -0
  432. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/turn-based-tactics.md +88 -0
  433. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types/visual-novel.md +89 -0
  434. package/src/modules/bmm/workflows/2-plan-workflows/gdd/game-types.csv +25 -0
  435. package/src/modules/bmm/workflows/2-plan-workflows/gdd/gdd-template.md +153 -0
  436. package/src/modules/bmm/workflows/2-plan-workflows/gdd/instructions-gdd.md +475 -0
  437. package/src/modules/bmm/workflows/2-plan-workflows/gdd/workflow.yaml +67 -0
  438. package/src/modules/bmm/workflows/2-plan-workflows/narrative/checklist.md +139 -0
  439. package/src/modules/bmm/workflows/2-plan-workflows/narrative/instructions-narrative.md +557 -0
  440. package/src/modules/bmm/workflows/2-plan-workflows/narrative/narrative-template.md +195 -0
  441. package/src/modules/bmm/workflows/2-plan-workflows/narrative/workflow.yaml +38 -0
  442. package/src/modules/bmm/workflows/2-plan-workflows/prd/checklist.md +117 -0
  443. package/src/modules/bmm/workflows/2-plan-workflows/prd/epics-template.md +63 -0
  444. package/src/modules/bmm/workflows/2-plan-workflows/prd/instructions.md +449 -0
  445. package/src/modules/bmm/workflows/2-plan-workflows/prd/prd-template.md +62 -0
  446. package/src/modules/bmm/workflows/2-plan-workflows/prd/workflow.yaml +46 -0
  447. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/checklist.md +107 -0
  448. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/epics-template.md +11 -0
  449. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/instructions-level0-story.md +167 -0
  450. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/instructions-level1-stories.md +278 -0
  451. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/instructions.md +269 -0
  452. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/tech-spec-template.md +55 -0
  453. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/user-story-template.md +56 -0
  454. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/workflow.yaml +52 -0
  455. package/src/modules/bmm/workflows/3-solutioning/README.md +1 -0
  456. package/src/modules/bmm/workflows/3-solutioning/architecture/architecture-patterns.yaml +347 -0
  457. package/src/modules/bmm/workflows/3-solutioning/architecture/architecture-template.md +103 -0
  458. package/src/modules/bmm/workflows/3-solutioning/architecture/checklist.md +244 -0
  459. package/src/modules/bmm/workflows/3-solutioning/architecture/decision-catalog.yaml +222 -0
  460. package/src/modules/bmm/workflows/3-solutioning/architecture/instructions.md +703 -0
  461. package/src/modules/bmm/workflows/3-solutioning/architecture/pattern-categories.csv +13 -0
  462. package/src/modules/bmm/workflows/3-solutioning/architecture/readme.md +318 -0
  463. package/src/modules/bmm/workflows/3-solutioning/architecture/workflow.yaml +54 -0
  464. package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/README.md +177 -0
  465. package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/checklist.md +175 -0
  466. package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/instructions.md +273 -0
  467. package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/template.md +146 -0
  468. package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/validation-criteria.yaml +189 -0
  469. package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/workflow.yaml +40 -0
  470. package/src/modules/bmm/workflows/4-implementation/README.md +221 -0
  471. package/src/modules/bmm/workflows/4-implementation/code-review/README.md +69 -0
  472. package/src/modules/bmm/workflows/4-implementation/code-review/backlog_template.md +12 -0
  473. package/src/modules/bmm/workflows/4-implementation/code-review/checklist.md +22 -0
  474. package/src/modules/bmm/workflows/4-implementation/code-review/instructions.md +391 -0
  475. package/src/modules/bmm/workflows/4-implementation/code-review/workflow.yaml +56 -0
  476. package/src/modules/bmm/workflows/4-implementation/correct-course/README.md +73 -0
  477. package/src/modules/bmm/workflows/4-implementation/correct-course/checklist.md +279 -0
  478. package/src/modules/bmm/workflows/4-implementation/correct-course/instructions.md +201 -0
  479. package/src/modules/bmm/workflows/4-implementation/correct-course/workflow.yaml +45 -0
  480. package/src/modules/bmm/workflows/4-implementation/create-story/README.md +129 -0
  481. package/src/modules/bmm/workflows/4-implementation/create-story/checklist.md +240 -0
  482. package/src/modules/bmm/workflows/4-implementation/create-story/instructions.md +252 -0
  483. package/src/modules/bmm/workflows/4-implementation/create-story/template.md +51 -0
  484. package/src/modules/bmm/workflows/4-implementation/create-story/workflow.yaml +49 -0
  485. package/src/modules/bmm/workflows/4-implementation/dev-story/AUDIT-REPORT.md +367 -0
  486. package/src/modules/bmm/workflows/4-implementation/dev-story/README.md +206 -0
  487. package/src/modules/bmm/workflows/4-implementation/dev-story/checklist.md +38 -0
  488. package/src/modules/bmm/workflows/4-implementation/dev-story/instructions.md +262 -0
  489. package/src/modules/bmm/workflows/4-implementation/dev-story/workflow.yaml +28 -0
  490. package/src/modules/bmm/workflows/4-implementation/epic-tech-context/README.md +195 -0
  491. package/src/modules/bmm/workflows/4-implementation/epic-tech-context/checklist.md +17 -0
  492. package/src/modules/bmm/workflows/4-implementation/epic-tech-context/instructions.md +160 -0
  493. package/src/modules/bmm/workflows/4-implementation/epic-tech-context/template.md +76 -0
  494. package/src/modules/bmm/workflows/4-implementation/epic-tech-context/workflow.yaml +34 -0
  495. package/src/modules/bmm/workflows/4-implementation/retrospective/README.md +77 -0
  496. package/src/modules/bmm/workflows/4-implementation/retrospective/instructions.md +479 -0
  497. package/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml +45 -0
  498. package/src/modules/bmm/workflows/4-implementation/sprint-planning/README.md +156 -0
  499. package/src/modules/bmm/workflows/4-implementation/sprint-planning/checklist.md +33 -0
  500. package/src/modules/bmm/workflows/4-implementation/sprint-planning/instructions.md +221 -0
  501. package/src/modules/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +55 -0
  502. package/src/modules/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +41 -0
  503. package/src/modules/bmm/workflows/4-implementation/story-context/README.md +234 -0
  504. package/src/modules/bmm/workflows/4-implementation/story-context/checklist.md +16 -0
  505. package/src/modules/bmm/workflows/4-implementation/story-context/context-template.xml +34 -0
  506. package/src/modules/bmm/workflows/4-implementation/story-context/instructions.md +201 -0
  507. package/src/modules/bmm/workflows/4-implementation/story-context/workflow.yaml +32 -0
  508. package/src/modules/bmm/workflows/4-implementation/story-done/instructions.md +111 -0
  509. package/src/modules/bmm/workflows/4-implementation/story-done/workflow.yaml +27 -0
  510. package/src/modules/bmm/workflows/4-implementation/story-ready/instructions.md +117 -0
  511. package/src/modules/bmm/workflows/4-implementation/story-ready/workflow.yaml +27 -0
  512. package/src/modules/bmm/workflows/README.md +577 -0
  513. package/src/modules/bmm/workflows/document-project/README.md +444 -0
  514. package/src/modules/bmm/workflows/document-project/checklist.md +245 -0
  515. package/src/modules/bmm/workflows/document-project/documentation-requirements.csv +12 -0
  516. package/src/modules/bmm/workflows/document-project/instructions.md +222 -0
  517. package/src/modules/bmm/workflows/document-project/templates/README.md +38 -0
  518. package/src/modules/bmm/workflows/document-project/templates/deep-dive-template.md +345 -0
  519. package/src/modules/bmm/workflows/document-project/templates/index-template.md +169 -0
  520. package/src/modules/bmm/workflows/document-project/templates/project-overview-template.md +103 -0
  521. package/src/modules/bmm/workflows/document-project/templates/project-scan-report-schema.json +160 -0
  522. package/src/modules/bmm/workflows/document-project/templates/source-tree-template.md +135 -0
  523. package/src/modules/bmm/workflows/document-project/workflow.yaml +36 -0
  524. package/src/modules/bmm/workflows/document-project/workflows/deep-dive-instructions.md +298 -0
  525. package/src/modules/bmm/workflows/document-project/workflows/deep-dive.yaml +31 -0
  526. package/src/modules/bmm/workflows/document-project/workflows/full-scan-instructions.md +1106 -0
  527. package/src/modules/bmm/workflows/document-project/workflows/full-scan.yaml +31 -0
  528. package/src/modules/bmm/workflows/testarch/README.md +26 -0
  529. package/src/modules/bmm/workflows/testarch/atdd/README.md +672 -0
  530. package/src/modules/bmm/workflows/testarch/atdd/atdd-checklist-template.md +363 -0
  531. package/src/modules/bmm/workflows/testarch/atdd/checklist.md +373 -0
  532. package/src/modules/bmm/workflows/testarch/atdd/instructions.md +785 -0
  533. package/src/modules/bmm/workflows/testarch/atdd/workflow.yaml +54 -0
  534. package/src/modules/bmm/workflows/testarch/automate/README.md +869 -0
  535. package/src/modules/bmm/workflows/testarch/automate/checklist.md +580 -0
  536. package/src/modules/bmm/workflows/testarch/automate/instructions.md +1303 -0
  537. package/src/modules/bmm/workflows/testarch/automate/workflow.yaml +63 -0
  538. package/src/modules/bmm/workflows/testarch/ci/README.md +493 -0
  539. package/src/modules/bmm/workflows/testarch/ci/checklist.md +246 -0
  540. package/src/modules/bmm/workflows/testarch/ci/github-actions-template.yaml +165 -0
  541. package/src/modules/bmm/workflows/testarch/ci/gitlab-ci-template.yaml +128 -0
  542. package/src/modules/bmm/workflows/testarch/ci/instructions.md +517 -0
  543. package/src/modules/bmm/workflows/testarch/ci/workflow.yaml +55 -0
  544. package/src/modules/bmm/workflows/testarch/framework/README.md +340 -0
  545. package/src/modules/bmm/workflows/testarch/framework/checklist.md +321 -0
  546. package/src/modules/bmm/workflows/testarch/framework/instructions.md +455 -0
  547. package/src/modules/bmm/workflows/testarch/framework/workflow.yaml +55 -0
  548. package/src/modules/bmm/workflows/testarch/nfr-assess/README.md +469 -0
  549. package/src/modules/bmm/workflows/testarch/nfr-assess/checklist.md +405 -0
  550. package/src/modules/bmm/workflows/testarch/nfr-assess/instructions.md +722 -0
  551. package/src/modules/bmm/workflows/testarch/nfr-assess/nfr-report-template.md +443 -0
  552. package/src/modules/bmm/workflows/testarch/nfr-assess/workflow.yaml +58 -0
  553. package/src/modules/bmm/workflows/testarch/test-design/README.md +493 -0
  554. package/src/modules/bmm/workflows/testarch/test-design/checklist.md +234 -0
  555. package/src/modules/bmm/workflows/testarch/test-design/instructions.md +621 -0
  556. package/src/modules/bmm/workflows/testarch/test-design/test-design-template.md +285 -0
  557. package/src/modules/bmm/workflows/testarch/test-design/workflow.yaml +54 -0
  558. package/src/modules/bmm/workflows/testarch/test-review/README.md +775 -0
  559. package/src/modules/bmm/workflows/testarch/test-review/checklist.md +470 -0
  560. package/src/modules/bmm/workflows/testarch/test-review/instructions.md +608 -0
  561. package/src/modules/bmm/workflows/testarch/test-review/test-review-template.md +388 -0
  562. package/src/modules/bmm/workflows/testarch/test-review/workflow.yaml +55 -0
  563. package/src/modules/bmm/workflows/testarch/trace/README.md +802 -0
  564. package/src/modules/bmm/workflows/testarch/trace/checklist.md +654 -0
  565. package/src/modules/bmm/workflows/testarch/trace/instructions.md +1045 -0
  566. package/src/modules/bmm/workflows/testarch/trace/trace-template.md +673 -0
  567. package/src/modules/bmm/workflows/testarch/trace/workflow.yaml +68 -0
  568. package/src/modules/bmm/workflows/workflow-status/README.md +241 -0
  569. package/src/modules/bmm/workflows/workflow-status/init/instructions.md +297 -0
  570. package/src/modules/bmm/workflows/workflow-status/init/workflow.yaml +28 -0
  571. package/src/modules/bmm/workflows/workflow-status/instructions.md +324 -0
  572. package/src/modules/bmm/workflows/workflow-status/paths/brownfield-level-0.yaml +54 -0
  573. package/src/modules/bmm/workflows/workflow-status/paths/brownfield-level-1.yaml +58 -0
  574. package/src/modules/bmm/workflows/workflow-status/paths/brownfield-level-2.yaml +76 -0
  575. package/src/modules/bmm/workflows/workflow-status/paths/brownfield-level-3.yaml +95 -0
  576. package/src/modules/bmm/workflows/workflow-status/paths/brownfield-level-4.yaml +88 -0
  577. package/src/modules/bmm/workflows/workflow-status/paths/game-design.yaml +75 -0
  578. package/src/modules/bmm/workflows/workflow-status/paths/greenfield-level-0.yaml +45 -0
  579. package/src/modules/bmm/workflows/workflow-status/paths/greenfield-level-1.yaml +49 -0
  580. package/src/modules/bmm/workflows/workflow-status/paths/greenfield-level-2.yaml +78 -0
  581. package/src/modules/bmm/workflows/workflow-status/paths/greenfield-level-3.yaml +73 -0
  582. package/src/modules/bmm/workflows/workflow-status/paths/greenfield-level-4.yaml +75 -0
  583. package/src/modules/bmm/workflows/workflow-status/project-levels.yaml +59 -0
  584. package/src/modules/bmm/workflows/workflow-status/workflow-status-template.md +30 -0
  585. package/src/modules/bmm/workflows/workflow-status/workflow.yaml +30 -0
  586. package/src/modules/cis/_module-installer/install-config.yaml +14 -0
  587. package/src/modules/cis/_module-installer/installer.js +92 -0
  588. package/src/modules/cis/agents/README.md +104 -0
  589. package/src/modules/cis/agents/brainstorming-coach.agent.yaml +23 -0
  590. package/src/modules/cis/agents/creative-problem-solver.agent.yaml +23 -0
  591. package/src/modules/cis/agents/design-thinking-coach.agent.yaml +23 -0
  592. package/src/modules/cis/agents/innovation-strategist.agent.yaml +23 -0
  593. package/src/modules/cis/agents/storyteller.agent.yaml +23 -0
  594. package/src/modules/cis/readme.md +86 -0
  595. package/src/modules/cis/teams/creative-squad.yaml +6 -0
  596. package/src/modules/cis/workflows/README.md +67 -0
  597. package/src/modules/cis/workflows/design-thinking/README.md +56 -0
  598. package/src/modules/cis/workflows/design-thinking/design-methods.csv +31 -0
  599. package/src/modules/cis/workflows/design-thinking/instructions.md +200 -0
  600. package/src/modules/cis/workflows/design-thinking/template.md +111 -0
  601. package/src/modules/cis/workflows/design-thinking/workflow.yaml +43 -0
  602. package/src/modules/cis/workflows/innovation-strategy/README.md +56 -0
  603. package/src/modules/cis/workflows/innovation-strategy/innovation-frameworks.csv +31 -0
  604. package/src/modules/cis/workflows/innovation-strategy/instructions.md +274 -0
  605. package/src/modules/cis/workflows/innovation-strategy/template.md +189 -0
  606. package/src/modules/cis/workflows/innovation-strategy/workflow.yaml +43 -0
  607. package/src/modules/cis/workflows/problem-solving/README.md +56 -0
  608. package/src/modules/cis/workflows/problem-solving/instructions.md +250 -0
  609. package/src/modules/cis/workflows/problem-solving/solving-methods.csv +31 -0
  610. package/src/modules/cis/workflows/problem-solving/template.md +165 -0
  611. package/src/modules/cis/workflows/problem-solving/workflow.yaml +43 -0
  612. package/src/modules/cis/workflows/storytelling/README.md +58 -0
  613. package/src/modules/cis/workflows/storytelling/instructions.md +283 -0
  614. package/src/modules/cis/workflows/storytelling/story-types.csv +26 -0
  615. package/src/modules/cis/workflows/storytelling/template.md +113 -0
  616. package/src/modules/cis/workflows/storytelling/workflow.yaml +43 -0
  617. package/src/utility/models/agent-activation-ide.xml +51 -0
  618. package/src/utility/models/agent-activation-web.xml +60 -0
  619. package/src/utility/models/agent-config-template.md +23 -0
  620. package/src/utility/models/agent-in-team-activation.xml +3 -0
  621. package/src/utility/models/fragments/activation-rules.xml +8 -0
  622. package/src/utility/models/fragments/activation-steps.xml +15 -0
  623. package/src/utility/models/fragments/handler-action.xml +4 -0
  624. package/src/utility/models/fragments/handler-data.xml +5 -0
  625. package/src/utility/models/fragments/handler-exec.xml +5 -0
  626. package/src/utility/models/fragments/handler-tmpl.xml +5 -0
  627. package/src/utility/models/fragments/handler-validate-workflow.xml +7 -0
  628. package/src/utility/models/fragments/handler-workflow.xml +9 -0
  629. package/src/utility/models/fragments/menu-handlers.xml +6 -0
  630. package/src/utility/models/fragments/web-bundle-activation-steps.xml +32 -0
  631. package/src/utility/templates/agent.customize.template.yaml +42 -0
  632. package/test/README.md +295 -0
  633. package/test/fixtures/agent-schema/invalid/critical-actions/actions-as-string.agent.yaml +26 -0
  634. package/test/fixtures/agent-schema/invalid/critical-actions/empty-string-in-actions.agent.yaml +29 -0
  635. package/test/fixtures/agent-schema/invalid/menu/empty-menu.agent.yaml +21 -0
  636. package/test/fixtures/agent-schema/invalid/menu/missing-menu.agent.yaml +19 -0
  637. package/test/fixtures/agent-schema/invalid/menu-commands/empty-command-target.agent.yaml +24 -0
  638. package/test/fixtures/agent-schema/invalid/menu-commands/no-command-target.agent.yaml +23 -0
  639. package/test/fixtures/agent-schema/invalid/menu-triggers/camel-case.agent.yaml +24 -0
  640. package/test/fixtures/agent-schema/invalid/menu-triggers/duplicate-triggers.agent.yaml +30 -0
  641. package/test/fixtures/agent-schema/invalid/menu-triggers/empty-trigger.agent.yaml +24 -0
  642. package/test/fixtures/agent-schema/invalid/menu-triggers/leading-asterisk.agent.yaml +24 -0
  643. package/test/fixtures/agent-schema/invalid/menu-triggers/snake-case.agent.yaml +24 -0
  644. package/test/fixtures/agent-schema/invalid/menu-triggers/trigger-with-spaces.agent.yaml +24 -0
  645. package/test/fixtures/agent-schema/invalid/metadata/core-agent-with-module.agent.yaml +26 -0
  646. package/test/fixtures/agent-schema/invalid/metadata/empty-module-string.agent.yaml +26 -0
  647. package/test/fixtures/agent-schema/invalid/metadata/empty-name.agent.yaml +24 -0
  648. package/test/fixtures/agent-schema/invalid/metadata/extra-metadata-fields.agent.yaml +26 -0
  649. package/test/fixtures/agent-schema/invalid/metadata/missing-id.agent.yaml +23 -0
  650. package/test/fixtures/agent-schema/invalid/metadata/module-agent-missing-module.agent.yaml +25 -0
  651. package/test/fixtures/agent-schema/invalid/metadata/wrong-module-value.agent.yaml +26 -0
  652. package/test/fixtures/agent-schema/invalid/persona/empty-principles-array.agent.yaml +23 -0
  653. package/test/fixtures/agent-schema/invalid/persona/empty-string-in-principles.agent.yaml +26 -0
  654. package/test/fixtures/agent-schema/invalid/persona/extra-persona-fields.agent.yaml +26 -0
  655. package/test/fixtures/agent-schema/invalid/persona/missing-role.agent.yaml +23 -0
  656. package/test/fixtures/agent-schema/invalid/persona/principles-as-string.agent.yaml +23 -0
  657. package/test/fixtures/agent-schema/invalid/prompts/empty-content.agent.yaml +28 -0
  658. package/test/fixtures/agent-schema/invalid/prompts/extra-prompt-fields.agent.yaml +30 -0
  659. package/test/fixtures/agent-schema/invalid/prompts/missing-content.agent.yaml +27 -0
  660. package/test/fixtures/agent-schema/invalid/prompts/missing-id.agent.yaml +27 -0
  661. package/test/fixtures/agent-schema/invalid/top-level/empty-file.agent.yaml +5 -0
  662. package/test/fixtures/agent-schema/invalid/top-level/extra-top-level-keys.agent.yaml +27 -0
  663. package/test/fixtures/agent-schema/invalid/top-level/missing-agent-key.agent.yaml +11 -0
  664. package/test/fixtures/agent-schema/invalid/yaml-errors/invalid-indentation.agent.yaml +19 -0
  665. package/test/fixtures/agent-schema/invalid/yaml-errors/malformed-yaml.agent.yaml +18 -0
  666. package/test/fixtures/agent-schema/valid/critical-actions/empty-critical-actions.agent.yaml +23 -0
  667. package/test/fixtures/agent-schema/valid/critical-actions/no-critical-actions.agent.yaml +21 -0
  668. package/test/fixtures/agent-schema/valid/critical-actions/valid-critical-actions.agent.yaml +26 -0
  669. package/test/fixtures/agent-schema/valid/menu/multiple-menu-items.agent.yaml +30 -0
  670. package/test/fixtures/agent-schema/valid/menu/single-menu-item.agent.yaml +21 -0
  671. package/test/fixtures/agent-schema/valid/menu-commands/all-command-types.agent.yaml +39 -0
  672. package/test/fixtures/agent-schema/valid/menu-commands/multiple-commands.agent.yaml +23 -0
  673. package/test/fixtures/agent-schema/valid/menu-triggers/kebab-case-triggers.agent.yaml +33 -0
  674. package/test/fixtures/agent-schema/valid/metadata/empty-module-name-in-path.agent.yaml +23 -0
  675. package/test/fixtures/agent-schema/valid/metadata/malformed-path-treated-as-core.agent.yaml +23 -0
  676. package/test/fixtures/agent-schema/valid/metadata/module-agent-correct.agent.yaml +23 -0
  677. package/test/fixtures/agent-schema/valid/persona/complete-persona.agent.yaml +23 -0
  678. package/test/fixtures/agent-schema/valid/prompts/empty-prompts.agent.yaml +23 -0
  679. package/test/fixtures/agent-schema/valid/prompts/no-prompts.agent.yaml +21 -0
  680. package/test/fixtures/agent-schema/valid/prompts/valid-prompts-minimal.agent.yaml +27 -0
  681. package/test/fixtures/agent-schema/valid/prompts/valid-prompts-with-description.agent.yaml +29 -0
  682. package/test/fixtures/agent-schema/valid/top-level/minimal-core-agent.agent.yaml +23 -0
  683. package/test/test-agent-schema.js +387 -0
  684. package/test/test-cli-integration.sh +159 -0
  685. package/test/unit-test-schema.js +133 -0
  686. package/tools/bmad-npx-wrapper.js +100 -13
  687. package/tools/cli/README.md +590 -0
  688. package/tools/cli/bmad-cli.js +40 -0
  689. package/tools/cli/bundlers/bundle-web.js +179 -0
  690. package/tools/cli/bundlers/test-analyst.js +28 -0
  691. package/tools/cli/bundlers/test-bundler.js +118 -0
  692. package/tools/cli/bundlers/web-bundler.js +1479 -0
  693. package/tools/cli/commands/build.js +458 -0
  694. package/tools/cli/commands/install.js +82 -0
  695. package/tools/cli/commands/list.js +28 -0
  696. package/tools/cli/commands/status.js +47 -0
  697. package/tools/cli/commands/uninstall.js +44 -0
  698. package/tools/cli/commands/update.js +28 -0
  699. package/tools/cli/installers/lib/core/config-collector.js +590 -0
  700. package/tools/cli/installers/lib/core/dependency-resolver.js +725 -0
  701. package/tools/cli/installers/lib/core/detector.js +274 -0
  702. package/tools/cli/installers/lib/core/ide-config-manager.js +152 -0
  703. package/tools/cli/installers/lib/core/installer.js +2095 -0
  704. package/tools/cli/installers/lib/core/manifest-generator.js +776 -0
  705. package/tools/cli/installers/lib/core/manifest.js +536 -0
  706. package/tools/cli/installers/lib/ide/_base-ide.js +572 -0
  707. package/tools/cli/installers/lib/ide/auggie.js +336 -0
  708. package/tools/cli/installers/lib/ide/claude-code.js +449 -0
  709. package/tools/cli/installers/lib/ide/cline.js +223 -0
  710. package/tools/cli/installers/lib/ide/codex.js +234 -0
  711. package/tools/cli/installers/lib/ide/crush.js +276 -0
  712. package/tools/cli/installers/lib/ide/cursor.js +292 -0
  713. package/tools/cli/installers/lib/ide/gemini.js +156 -0
  714. package/tools/cli/installers/lib/ide/github-copilot.js +290 -0
  715. package/tools/cli/installers/lib/ide/iflow.js +142 -0
  716. package/tools/cli/installers/lib/ide/kilo.js +171 -0
  717. package/tools/cli/installers/lib/ide/manager.js +194 -0
  718. package/tools/cli/installers/lib/ide/opencode.js +213 -0
  719. package/tools/cli/installers/lib/ide/qwen.js +290 -0
  720. package/tools/cli/installers/lib/ide/roo.js +288 -0
  721. package/tools/cli/installers/lib/ide/shared/bmad-artifacts.js +143 -0
  722. package/tools/cli/installers/lib/ide/shared/module-injections.js +133 -0
  723. package/tools/cli/installers/lib/ide/task-tool-command-generator.js +119 -0
  724. package/tools/cli/installers/lib/ide/trae.js +278 -0
  725. package/tools/cli/installers/lib/ide/windsurf.js +201 -0
  726. package/tools/cli/installers/lib/ide/workflow-command-generator.js +235 -0
  727. package/tools/cli/installers/lib/ide/workflow-command-template.md +15 -0
  728. package/tools/cli/installers/lib/modules/manager.js +568 -0
  729. package/tools/cli/lib/activation-builder.js +168 -0
  730. package/tools/cli/lib/agent-analyzer.js +81 -0
  731. package/tools/cli/lib/agent-party-generator.js +206 -0
  732. package/tools/cli/lib/cli-utils.js +208 -0
  733. package/tools/cli/lib/config.js +210 -0
  734. package/tools/cli/lib/file-ops.js +204 -0
  735. package/tools/cli/lib/platform-codes.js +116 -0
  736. package/tools/cli/lib/project-root.js +71 -0
  737. package/tools/cli/lib/replace-project-root.js +239 -0
  738. package/tools/cli/lib/ui.js +591 -0
  739. package/tools/cli/lib/xml-handler.js +228 -0
  740. package/tools/cli/lib/xml-to-markdown.js +82 -0
  741. package/tools/{yaml-format.js → cli/lib/yaml-format.js} +3 -10
  742. package/tools/cli/lib/yaml-xml-builder.js +439 -0
  743. package/tools/cli/regenerate-manifests.js +28 -0
  744. package/tools/cli/test-yaml-builder.js +43 -0
  745. package/tools/flattener/ignoreRules.js +2 -6
  746. package/tools/flattener/main.js +31 -121
  747. package/tools/flattener/projectRoot.js +3 -8
  748. package/tools/flattener/stats.helpers.js +8 -35
  749. package/tools/flattener/stats.js +1 -6
  750. package/tools/flattener/test-matrix.js +1 -5
  751. package/tools/format-workflow-md.js +263 -0
  752. package/tools/platform-codes.yaml +133 -0
  753. package/tools/schema/agent.js +231 -0
  754. package/tools/validate-agent-schema.js +110 -0
  755. package/tools/validate-bundles.js +87 -0
  756. package/v6-open-items.md +23 -0
  757. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -22
  758. package/bmad-core/agent-teams/team-all.yaml +0 -14
  759. package/bmad-core/agent-teams/team-fullstack.yaml +0 -18
  760. package/bmad-core/agent-teams/team-ide-minimal.yaml +0 -10
  761. package/bmad-core/agent-teams/team-no-ui.yaml +0 -13
  762. package/bmad-core/agents/analyst.md +0 -81
  763. package/bmad-core/agents/architect.md +0 -83
  764. package/bmad-core/agents/bmad-master.md +0 -107
  765. package/bmad-core/agents/bmad-orchestrator.md +0 -149
  766. package/bmad-core/agents/dev.md +0 -75
  767. package/bmad-core/agents/pm.md +0 -81
  768. package/bmad-core/agents/po.md +0 -76
  769. package/bmad-core/agents/qa.md +0 -88
  770. package/bmad-core/agents/sm.md +0 -62
  771. package/bmad-core/agents/ux-expert.md +0 -66
  772. package/bmad-core/checklists/architect-checklist.md +0 -438
  773. package/bmad-core/checklists/change-checklist.md +0 -182
  774. package/bmad-core/checklists/pm-checklist.md +0 -370
  775. package/bmad-core/checklists/po-master-checklist.md +0 -432
  776. package/bmad-core/checklists/story-dod-checklist.md +0 -94
  777. package/bmad-core/checklists/story-draft-checklist.md +0 -153
  778. package/bmad-core/core-config.yaml +0 -20
  779. package/bmad-core/data/bmad-kb.md +0 -806
  780. package/bmad-core/data/brainstorming-techniques.md +0 -36
  781. package/bmad-core/data/elicitation-methods.md +0 -154
  782. package/bmad-core/data/technical-preferences.md +0 -3
  783. package/bmad-core/data/test-levels-framework.md +0 -146
  784. package/bmad-core/data/test-priorities-matrix.md +0 -172
  785. package/bmad-core/tasks/advanced-elicitation.md +0 -117
  786. package/bmad-core/tasks/brownfield-create-epic.md +0 -160
  787. package/bmad-core/tasks/brownfield-create-story.md +0 -147
  788. package/bmad-core/tasks/correct-course.md +0 -70
  789. package/bmad-core/tasks/create-brownfield-story.md +0 -312
  790. package/bmad-core/tasks/create-deep-research-prompt.md +0 -278
  791. package/bmad-core/tasks/create-next-story.md +0 -112
  792. package/bmad-core/tasks/document-project.md +0 -343
  793. package/bmad-core/tasks/facilitate-brainstorming-session.md +0 -136
  794. package/bmad-core/tasks/generate-ai-frontend-prompt.md +0 -51
  795. package/bmad-core/tasks/index-docs.md +0 -173
  796. package/bmad-core/tasks/kb-mode-interaction.md +0 -75
  797. package/bmad-core/tasks/nfr-assess.md +0 -343
  798. package/bmad-core/tasks/qa-gate.md +0 -159
  799. package/bmad-core/tasks/review-story.md +0 -314
  800. package/bmad-core/tasks/risk-profile.md +0 -353
  801. package/bmad-core/tasks/shard-doc.md +0 -185
  802. package/bmad-core/tasks/test-design.md +0 -174
  803. package/bmad-core/tasks/trace-requirements.md +0 -264
  804. package/bmad-core/tasks/validate-next-story.md +0 -134
  805. package/bmad-core/templates/architecture-tmpl.yaml +0 -650
  806. package/bmad-core/templates/brainstorming-output-tmpl.yaml +0 -156
  807. package/bmad-core/templates/brownfield-architecture-tmpl.yaml +0 -476
  808. package/bmad-core/templates/brownfield-prd-tmpl.yaml +0 -280
  809. package/bmad-core/templates/competitor-analysis-tmpl.yaml +0 -306
  810. package/bmad-core/templates/front-end-architecture-tmpl.yaml +0 -218
  811. package/bmad-core/templates/front-end-spec-tmpl.yaml +0 -349
  812. package/bmad-core/templates/fullstack-architecture-tmpl.yaml +0 -823
  813. package/bmad-core/templates/market-research-tmpl.yaml +0 -252
  814. package/bmad-core/templates/prd-tmpl.yaml +0 -202
  815. package/bmad-core/templates/project-brief-tmpl.yaml +0 -221
  816. package/bmad-core/templates/qa-gate-tmpl.yaml +0 -102
  817. package/bmad-core/templates/story-tmpl.yaml +0 -137
  818. package/bmad-core/workflows/brownfield-fullstack.yaml +0 -297
  819. package/bmad-core/workflows/brownfield-service.yaml +0 -187
  820. package/bmad-core/workflows/brownfield-ui.yaml +0 -197
  821. package/bmad-core/workflows/greenfield-fullstack.yaml +0 -240
  822. package/bmad-core/workflows/greenfield-service.yaml +0 -206
  823. package/bmad-core/workflows/greenfield-ui.yaml +0 -235
  824. package/common/tasks/create-doc.md +0 -101
  825. package/common/tasks/execute-checklist.md +0 -86
  826. package/common/utils/bmad-doc-template.md +0 -325
  827. package/common/utils/workflow-management.md +0 -69
  828. package/dist/agents/analyst.txt +0 -2889
  829. package/dist/agents/architect.txt +0 -3552
  830. package/dist/agents/bmad-master.txt +0 -8769
  831. package/dist/agents/bmad-orchestrator.txt +0 -1513
  832. package/dist/agents/dev.txt +0 -414
  833. package/dist/agents/pm.txt +0 -2204
  834. package/dist/agents/po.txt +0 -1346
  835. package/dist/agents/qa.txt +0 -1987
  836. package/dist/agents/sm.txt +0 -658
  837. package/dist/agents/ux-expert.txt +0 -694
  838. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +0 -2371
  839. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +0 -1620
  840. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +0 -815
  841. package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +0 -10952
  842. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.txt +0 -4012
  843. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.txt +0 -3698
  844. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.txt +0 -450
  845. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.txt +0 -973
  846. package/dist/expansion-packs/bmad-2d-unity-game-dev/teams/unity-2d-game-team.txt +0 -15376
  847. package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +0 -2075
  848. package/dist/teams/team-all.txt +0 -12682
  849. package/dist/teams/team-fullstack.txt +0 -10421
  850. package/dist/teams/team-ide-minimal.txt +0 -5103
  851. package/dist/teams/team-no-ui.txt +0 -8980
  852. package/docs/GUIDING-PRINCIPLES.md +0 -91
  853. package/docs/core-architecture.md +0 -219
  854. package/docs/enhanced-ide-development-workflow.md +0 -248
  855. package/docs/expansion-packs.md +0 -280
  856. package/docs/how-to-contribute-with-pull-requests.md +0 -158
  857. package/docs/user-guide.md +0 -504
  858. package/docs/versioning-and-releases.md +0 -147
  859. package/docs/versions.md +0 -48
  860. package/docs/working-in-the-brownfield.md +0 -597
  861. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/Complete AI Agent System - Flowchart.svg +0 -102
  862. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.1 Google Cloud Project Setup/1.1.1 - Initial Project Configuration - bash copy.txt +0 -13
  863. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.1 Google Cloud Project Setup/1.1.1 - Initial Project Configuration - bash.txt +0 -13
  864. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.2 Agent Development Kit Installation/1.2.2 - Basic Project Structure - txt.txt +0 -25
  865. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.3 Core Configuration Files/1.3.1 - settings.py +0 -34
  866. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.3 Core Configuration Files/1.3.2 - main.py - Base Application.py +0 -70
  867. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.4 Deployment Configuration/1.4.2 - cloudbuild.yaml +0 -26
  868. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/README.md +0 -109
  869. package/expansion-packs/README.md +0 -3
  870. package/expansion-packs/bmad-2d-phaser-game-dev/agent-teams/phaser-2d-nodejs-game-team.yaml +0 -13
  871. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.md +0 -71
  872. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.md +0 -78
  873. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.md +0 -64
  874. package/expansion-packs/bmad-2d-phaser-game-dev/checklists/game-design-checklist.md +0 -201
  875. package/expansion-packs/bmad-2d-phaser-game-dev/checklists/game-story-dod-checklist.md +0 -160
  876. package/expansion-packs/bmad-2d-phaser-game-dev/config.yaml +0 -8
  877. package/expansion-packs/bmad-2d-phaser-game-dev/data/bmad-kb.md +0 -250
  878. package/expansion-packs/bmad-2d-phaser-game-dev/data/development-guidelines.md +0 -647
  879. package/expansion-packs/bmad-2d-phaser-game-dev/tasks/advanced-elicitation.md +0 -110
  880. package/expansion-packs/bmad-2d-phaser-game-dev/tasks/create-game-story.md +0 -216
  881. package/expansion-packs/bmad-2d-phaser-game-dev/tasks/game-design-brainstorming.md +0 -290
  882. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-architecture-tmpl.yaml +0 -613
  883. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-brief-tmpl.yaml +0 -356
  884. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-design-doc-tmpl.yaml +0 -343
  885. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-story-tmpl.yaml +0 -253
  886. package/expansion-packs/bmad-2d-phaser-game-dev/templates/level-design-doc-tmpl.yaml +0 -484
  887. package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-dev-greenfield.yaml +0 -183
  888. package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-prototype.yaml +0 -175
  889. package/expansion-packs/bmad-2d-unity-game-dev/agent-teams/unity-2d-game-team.yaml +0 -14
  890. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.md +0 -80
  891. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.md +0 -77
  892. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.md +0 -78
  893. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.md +0 -65
  894. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-architect-checklist.md +0 -391
  895. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-change-checklist.md +0 -203
  896. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-design-checklist.md +0 -201
  897. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-story-dod-checklist.md +0 -124
  898. package/expansion-packs/bmad-2d-unity-game-dev/config.yaml +0 -6
  899. package/expansion-packs/bmad-2d-unity-game-dev/data/bmad-kb.md +0 -769
  900. package/expansion-packs/bmad-2d-unity-game-dev/data/development-guidelines.md +0 -586
  901. package/expansion-packs/bmad-2d-unity-game-dev/tasks/advanced-elicitation.md +0 -110
  902. package/expansion-packs/bmad-2d-unity-game-dev/tasks/correct-course-game.md +0 -141
  903. package/expansion-packs/bmad-2d-unity-game-dev/tasks/create-game-story.md +0 -184
  904. package/expansion-packs/bmad-2d-unity-game-dev/tasks/game-design-brainstorming.md +0 -290
  905. package/expansion-packs/bmad-2d-unity-game-dev/tasks/validate-game-story.md +0 -200
  906. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-architecture-tmpl.yaml +0 -1030
  907. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-brief-tmpl.yaml +0 -356
  908. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-design-doc-tmpl.yaml +0 -705
  909. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-story-tmpl.yaml +0 -256
  910. package/expansion-packs/bmad-2d-unity-game-dev/templates/level-design-doc-tmpl.yaml +0 -484
  911. package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-dev-greenfield.yaml +0 -183
  912. package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-prototype.yaml +0 -175
  913. package/expansion-packs/bmad-infrastructure-devops/README.md +0 -147
  914. package/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.md +0 -71
  915. package/expansion-packs/bmad-infrastructure-devops/checklists/infrastructure-checklist.md +0 -484
  916. package/expansion-packs/bmad-infrastructure-devops/config.yaml +0 -9
  917. package/expansion-packs/bmad-infrastructure-devops/data/bmad-kb.md +0 -305
  918. package/expansion-packs/bmad-infrastructure-devops/tasks/review-infrastructure.md +0 -159
  919. package/expansion-packs/bmad-infrastructure-devops/tasks/validate-infrastructure.md +0 -153
  920. package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-architecture-tmpl.yaml +0 -424
  921. package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.yaml +0 -629
  922. package/release_notes.md +0 -33
  923. package/tools/builders/web-builder.js +0 -675
  924. package/tools/bump-all-versions.js +0 -115
  925. package/tools/bump-expansion-version.js +0 -90
  926. package/tools/cli.js +0 -152
  927. package/tools/installer/README.md +0 -8
  928. package/tools/installer/bin/bmad.js +0 -585
  929. package/tools/installer/config/ide-agent-config.yaml +0 -58
  930. package/tools/installer/config/install.config.yaml +0 -123
  931. package/tools/installer/lib/config-loader.js +0 -257
  932. package/tools/installer/lib/file-manager.js +0 -389
  933. package/tools/installer/lib/ide-base-setup.js +0 -228
  934. package/tools/installer/lib/ide-setup.js +0 -1441
  935. package/tools/installer/lib/installer.js +0 -1995
  936. package/tools/installer/lib/memory-profiler.js +0 -225
  937. package/tools/installer/lib/module-manager.js +0 -114
  938. package/tools/installer/lib/resource-locator.js +0 -308
  939. package/tools/installer/package.json +0 -44
  940. package/tools/lib/dependency-resolver.js +0 -175
  941. package/tools/lib/yaml-utils.js +0 -29
  942. package/tools/md-assets/web-agent-startup-instructions.md +0 -39
  943. package/tools/preview-release-notes.js +0 -66
  944. package/tools/shared/bannerArt.js +0 -105
  945. package/tools/sync-installer-version.js +0 -32
  946. package/tools/update-expansion-version.js +0 -53
  947. package/tools/upgraders/v3-to-v4-upgrader.js +0 -672
  948. package/tools/version-bump.js +0 -94
@@ -0,0 +1,2095 @@
1
+ const path = require('node:path');
2
+ const fs = require('fs-extra');
3
+ const chalk = require('chalk');
4
+ const ora = require('ora');
5
+ const { Detector } = require('./detector');
6
+ const { Manifest } = require('./manifest');
7
+ const { ModuleManager } = require('../modules/manager');
8
+ const { IdeManager } = require('../ide/manager');
9
+ const { FileOps } = require('../../../lib/file-ops');
10
+ const { Config } = require('../../../lib/config');
11
+ const { XmlHandler } = require('../../../lib/xml-handler');
12
+ const { DependencyResolver } = require('./dependency-resolver');
13
+ const { ConfigCollector } = require('./config-collector');
14
+ // processInstallation no longer needed - LLMs understand {project-root}
15
+ const { getProjectRoot, getSourcePath, getModulePath } = require('../../../lib/project-root');
16
+ const { AgentPartyGenerator } = require('../../../lib/agent-party-generator');
17
+ const { CLIUtils } = require('../../../lib/cli-utils');
18
+ const { ManifestGenerator } = require('./manifest-generator');
19
+ const { IdeConfigManager } = require('./ide-config-manager');
20
+
21
+ class Installer {
22
+ constructor() {
23
+ this.detector = new Detector();
24
+ this.manifest = new Manifest();
25
+ this.moduleManager = new ModuleManager();
26
+ this.ideManager = new IdeManager();
27
+ this.fileOps = new FileOps();
28
+ this.config = new Config();
29
+ this.xmlHandler = new XmlHandler();
30
+ this.dependencyResolver = new DependencyResolver();
31
+ this.configCollector = new ConfigCollector();
32
+ this.ideConfigManager = new IdeConfigManager();
33
+ this.installedFiles = []; // Track all installed files
34
+ }
35
+
36
+ /**
37
+ * Collect Tool/IDE configurations after module configuration
38
+ * @param {string} projectDir - Project directory
39
+ * @param {Array} selectedModules - Selected modules from configuration
40
+ * @param {boolean} isFullReinstall - Whether this is a full reinstall
41
+ * @param {Array} previousIdes - Previously configured IDEs (for reinstalls)
42
+ * @param {Array} preSelectedIdes - Pre-selected IDEs from early prompt (optional)
43
+ * @returns {Object} Tool/IDE selection and configurations
44
+ */
45
+ async collectToolConfigurations(projectDir, selectedModules, isFullReinstall = false, previousIdes = [], preSelectedIdes = null) {
46
+ // Use pre-selected IDEs if provided, otherwise prompt
47
+ let toolConfig;
48
+ if (preSelectedIdes === null) {
49
+ // Fallback: prompt for tool selection (backwards compatibility)
50
+ const { UI } = require('../../../lib/ui');
51
+ const ui = new UI();
52
+ toolConfig = await ui.promptToolSelection(projectDir, selectedModules);
53
+ } else {
54
+ // IDEs were already selected during initial prompts
55
+ toolConfig = {
56
+ ides: preSelectedIdes,
57
+ skipIde: !preSelectedIdes || preSelectedIdes.length === 0,
58
+ };
59
+ }
60
+
61
+ // Check for already configured IDEs
62
+ const { Detector } = require('./detector');
63
+ const detector = new Detector();
64
+ const bmadDir = path.join(projectDir, 'bmad');
65
+
66
+ // During full reinstall, use the saved previous IDEs since bmad dir was deleted
67
+ // Otherwise detect from existing installation
68
+ let previouslyConfiguredIdes;
69
+ if (isFullReinstall) {
70
+ // During reinstall, treat all IDEs as new (need configuration)
71
+ previouslyConfiguredIdes = [];
72
+ } else {
73
+ const existingInstall = await detector.detect(bmadDir);
74
+ previouslyConfiguredIdes = existingInstall.ides || [];
75
+ }
76
+
77
+ // Load saved IDE configurations for already-configured IDEs
78
+ const savedIdeConfigs = await this.ideConfigManager.loadAllIdeConfigs(bmadDir);
79
+
80
+ // Collect IDE-specific configurations if any were selected
81
+ const ideConfigurations = {};
82
+
83
+ // First, add saved configs for already-configured IDEs
84
+ for (const ide of toolConfig.ides || []) {
85
+ if (previouslyConfiguredIdes.includes(ide) && savedIdeConfigs[ide]) {
86
+ ideConfigurations[ide] = savedIdeConfigs[ide];
87
+ }
88
+ }
89
+
90
+ if (!toolConfig.skipIde && toolConfig.ides && toolConfig.ides.length > 0) {
91
+ // Determine which IDEs are newly selected (not previously configured)
92
+ const newlySelectedIdes = toolConfig.ides.filter((ide) => !previouslyConfiguredIdes.includes(ide));
93
+
94
+ if (newlySelectedIdes.length > 0) {
95
+ console.log('\n'); // Add spacing before IDE questions
96
+
97
+ for (const ide of newlySelectedIdes) {
98
+ // List of IDEs that have interactive prompts
99
+ const needsPrompts = ['claude-code', 'github-copilot', 'roo', 'cline', 'auggie', 'codex', 'qwen', 'gemini'].includes(ide);
100
+
101
+ if (needsPrompts) {
102
+ // Get IDE handler and collect configuration
103
+ try {
104
+ // Dynamically load the IDE setup module
105
+ const ideModule = require(`../ide/${ide}`);
106
+
107
+ // Get the setup class (handle different export formats)
108
+ let SetupClass;
109
+ const className =
110
+ ide
111
+ .split('-')
112
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
113
+ .join('') + 'Setup';
114
+
115
+ if (ideModule[className]) {
116
+ SetupClass = ideModule[className];
117
+ } else if (ideModule.default) {
118
+ SetupClass = ideModule.default;
119
+ } else {
120
+ // Skip if no setup class found
121
+ continue;
122
+ }
123
+
124
+ const ideSetup = new SetupClass();
125
+
126
+ // Check if this IDE has a collectConfiguration method
127
+ if (typeof ideSetup.collectConfiguration === 'function') {
128
+ console.log(chalk.cyan(`\nConfiguring ${ide}...`));
129
+ ideConfigurations[ide] = await ideSetup.collectConfiguration({
130
+ selectedModules: selectedModules || [],
131
+ projectDir,
132
+ bmadDir,
133
+ });
134
+ }
135
+ } catch {
136
+ // IDE doesn't have a setup file or collectConfiguration method
137
+ console.warn(chalk.yellow(`Warning: Could not load configuration for ${ide}`));
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ // Log which IDEs are already configured and being kept
144
+ const keptIdes = toolConfig.ides.filter((ide) => previouslyConfiguredIdes.includes(ide));
145
+ if (keptIdes.length > 0) {
146
+ console.log(chalk.dim(`\nKeeping existing configuration for: ${keptIdes.join(', ')}`));
147
+ }
148
+ }
149
+
150
+ return {
151
+ ides: toolConfig.ides,
152
+ skipIde: toolConfig.skipIde,
153
+ configurations: ideConfigurations,
154
+ };
155
+ }
156
+
157
+ /**
158
+ * Main installation method
159
+ * @param {Object} config - Installation configuration
160
+ * @param {string} config.directory - Target directory
161
+ * @param {boolean} config.installCore - Whether to install core
162
+ * @param {string[]} config.modules - Modules to install
163
+ * @param {string[]} config.ides - IDEs to configure
164
+ * @param {boolean} config.skipIde - Skip IDE configuration
165
+ */
166
+ async install(config) {
167
+ // Display BMAD logo
168
+ CLIUtils.displayLogo();
169
+
170
+ // Display welcome message
171
+ CLIUtils.displaySection('BMAD™ Installation', 'Version ' + require(path.join(getProjectRoot(), 'package.json')).version);
172
+
173
+ // Preflight: Handle legacy BMAD v4 footprints before any prompts/writes
174
+ const projectDir = path.resolve(config.directory);
175
+ const legacyV4 = await this.detector.detectLegacyV4(projectDir);
176
+ if (legacyV4.hasLegacyV4) {
177
+ await this.handleLegacyV4Migration(projectDir, legacyV4);
178
+ }
179
+
180
+ // If core config was pre-collected (from interactive mode), use it
181
+ if (config.coreConfig) {
182
+ this.configCollector.collectedConfig.core = config.coreConfig;
183
+ // Also store in allAnswers for cross-referencing
184
+ this.configCollector.allAnswers = {};
185
+ for (const [key, value] of Object.entries(config.coreConfig)) {
186
+ this.configCollector.allAnswers[`core_${key}`] = value;
187
+ }
188
+ }
189
+
190
+ // Collect configurations for modules (skip if quick update already collected them)
191
+ let moduleConfigs;
192
+ if (config._quickUpdate) {
193
+ // Quick update already collected all configs, use them directly
194
+ moduleConfigs = this.configCollector.collectedConfig;
195
+ } else {
196
+ // Regular install - collect configurations (core was already collected in UI.promptInstall if interactive)
197
+ moduleConfigs = await this.configCollector.collectAllConfigurations(config.modules || [], path.resolve(config.directory));
198
+ }
199
+
200
+ // Tool selection will be collected after we determine if it's a reinstall/update/new install
201
+
202
+ const spinner = ora('Preparing installation...').start();
203
+
204
+ try {
205
+ // Resolve target directory (path.resolve handles platform differences)
206
+ const projectDir = path.resolve(config.directory);
207
+
208
+ // Create a project directory if it doesn't exist (user already confirmed)
209
+ if (!(await fs.pathExists(projectDir))) {
210
+ spinner.text = 'Creating installation directory...';
211
+ try {
212
+ // fs.ensureDir handles platform-specific directory creation
213
+ // It will recursively create all necessary parent directories
214
+ await fs.ensureDir(projectDir);
215
+ } catch (error) {
216
+ spinner.fail('Failed to create installation directory');
217
+ console.error(chalk.red(`Error: ${error.message}`));
218
+ // More detailed error for common issues
219
+ if (error.code === 'EACCES') {
220
+ console.error(chalk.red('Permission denied. Check parent directory permissions.'));
221
+ } else if (error.code === 'ENOSPC') {
222
+ console.error(chalk.red('No space left on device.'));
223
+ }
224
+ throw new Error(`Cannot create directory: ${projectDir}`);
225
+ }
226
+ }
227
+
228
+ const bmadDir = path.join(projectDir, 'bmad');
229
+
230
+ // Check existing installation
231
+ spinner.text = 'Checking for existing installation...';
232
+ const existingInstall = await this.detector.detect(bmadDir);
233
+
234
+ if (existingInstall.installed && !config.force && !config._quickUpdate) {
235
+ spinner.stop();
236
+
237
+ // Check if user already decided what to do (from early menu in ui.js)
238
+ let action = null;
239
+ if (config._requestedReinstall) {
240
+ action = 'reinstall';
241
+ } else if (config.actionType === 'update') {
242
+ action = 'update';
243
+ } else {
244
+ // Fallback: Ask the user (backwards compatibility for other code paths)
245
+ console.log(chalk.yellow('\n⚠️ Existing BMAD installation detected'));
246
+ console.log(chalk.dim(` Location: ${bmadDir}`));
247
+ console.log(chalk.dim(` Version: ${existingInstall.version}`));
248
+
249
+ const promptResult = await this.promptUpdateAction();
250
+ action = promptResult.action;
251
+ }
252
+
253
+ if (action === 'cancel') {
254
+ console.log('Installation cancelled.');
255
+ return { success: false, cancelled: true };
256
+ }
257
+
258
+ if (action === 'reinstall') {
259
+ // Warn about destructive operation
260
+ console.log(chalk.red.bold('\n⚠️ WARNING: This is a destructive operation!'));
261
+ console.log(chalk.red('All custom files and modifications in the bmad directory will be lost.'));
262
+
263
+ const inquirer = require('inquirer');
264
+ const { confirmReinstall } = await inquirer.prompt([
265
+ {
266
+ type: 'confirm',
267
+ name: 'confirmReinstall',
268
+ message: chalk.yellow('Are you sure you want to delete and reinstall?'),
269
+ default: false,
270
+ },
271
+ ]);
272
+
273
+ if (!confirmReinstall) {
274
+ console.log('Installation cancelled.');
275
+ return { success: false, cancelled: true };
276
+ }
277
+
278
+ // Remember previously configured IDEs before deleting
279
+ config._previouslyConfiguredIdes = existingInstall.ides || [];
280
+
281
+ // Remove existing installation
282
+ await fs.remove(bmadDir);
283
+ console.log(chalk.green('✓ Removed existing installation\n'));
284
+
285
+ // Mark this as a full reinstall so we re-collect IDE configurations
286
+ config._isFullReinstall = true;
287
+ } else if (action === 'update') {
288
+ // Store that we're updating for later processing
289
+ config._isUpdate = true;
290
+ config._existingInstall = existingInstall;
291
+
292
+ // Detect custom and modified files BEFORE updating (compare current files vs files-manifest.csv)
293
+ const existingFilesManifest = await this.readFilesManifest(bmadDir);
294
+ console.log(chalk.dim(`DEBUG: Read ${existingFilesManifest.length} files from manifest`));
295
+ console.log(chalk.dim(`DEBUG: Manifest has hashes: ${existingFilesManifest.some((f) => f.hash)}`));
296
+
297
+ const { customFiles, modifiedFiles } = await this.detectCustomFiles(bmadDir, existingFilesManifest);
298
+
299
+ console.log(chalk.dim(`DEBUG: Found ${customFiles.length} custom files, ${modifiedFiles.length} modified files`));
300
+ if (modifiedFiles.length > 0) {
301
+ console.log(chalk.yellow('DEBUG: Modified files:'));
302
+ for (const f of modifiedFiles) console.log(chalk.dim(` - ${f.path}`));
303
+ }
304
+
305
+ config._customFiles = customFiles;
306
+ config._modifiedFiles = modifiedFiles;
307
+
308
+ // If there are custom files, back them up temporarily
309
+ if (customFiles.length > 0) {
310
+ const tempBackupDir = path.join(projectDir, '.bmad-custom-backup-temp');
311
+ await fs.ensureDir(tempBackupDir);
312
+
313
+ spinner.start(`Backing up ${customFiles.length} custom files...`);
314
+ for (const customFile of customFiles) {
315
+ const relativePath = path.relative(bmadDir, customFile);
316
+ const backupPath = path.join(tempBackupDir, relativePath);
317
+ await fs.ensureDir(path.dirname(backupPath));
318
+ await fs.copy(customFile, backupPath);
319
+ }
320
+ spinner.succeed(`Backed up ${customFiles.length} custom files`);
321
+
322
+ config._tempBackupDir = tempBackupDir;
323
+ }
324
+
325
+ // For modified files, back them up to temp directory (will be restored as .bak files after install)
326
+ if (modifiedFiles.length > 0) {
327
+ const tempModifiedBackupDir = path.join(projectDir, '.bmad-modified-backup-temp');
328
+ await fs.ensureDir(tempModifiedBackupDir);
329
+
330
+ console.log(chalk.yellow(`\nDEBUG: Backing up ${modifiedFiles.length} modified files to temp location`));
331
+ spinner.start(`Backing up ${modifiedFiles.length} modified files...`);
332
+ for (const modifiedFile of modifiedFiles) {
333
+ const relativePath = path.relative(bmadDir, modifiedFile.path);
334
+ const tempBackupPath = path.join(tempModifiedBackupDir, relativePath);
335
+ console.log(chalk.dim(`DEBUG: Backing up ${relativePath} to temp`));
336
+ await fs.ensureDir(path.dirname(tempBackupPath));
337
+ await fs.copy(modifiedFile.path, tempBackupPath, { overwrite: true });
338
+ }
339
+ spinner.succeed(`Backed up ${modifiedFiles.length} modified files`);
340
+
341
+ config._tempModifiedBackupDir = tempModifiedBackupDir;
342
+ } else {
343
+ console.log(chalk.dim('DEBUG: No modified files detected'));
344
+ }
345
+ }
346
+ } else if (existingInstall.installed && config._quickUpdate) {
347
+ // Quick update mode - automatically treat as update without prompting
348
+ spinner.text = 'Preparing quick update...';
349
+ config._isUpdate = true;
350
+ config._existingInstall = existingInstall;
351
+
352
+ // Detect custom and modified files BEFORE updating
353
+ const existingFilesManifest = await this.readFilesManifest(bmadDir);
354
+ const { customFiles, modifiedFiles } = await this.detectCustomFiles(bmadDir, existingFilesManifest);
355
+
356
+ config._customFiles = customFiles;
357
+ config._modifiedFiles = modifiedFiles;
358
+
359
+ // Back up custom files
360
+ if (customFiles.length > 0) {
361
+ const tempBackupDir = path.join(projectDir, '.bmad-custom-backup-temp');
362
+ await fs.ensureDir(tempBackupDir);
363
+
364
+ spinner.start(`Backing up ${customFiles.length} custom files...`);
365
+ for (const customFile of customFiles) {
366
+ const relativePath = path.relative(bmadDir, customFile);
367
+ const backupPath = path.join(tempBackupDir, relativePath);
368
+ await fs.ensureDir(path.dirname(backupPath));
369
+ await fs.copy(customFile, backupPath);
370
+ }
371
+ spinner.succeed(`Backed up ${customFiles.length} custom files`);
372
+ config._tempBackupDir = tempBackupDir;
373
+ }
374
+
375
+ // Back up modified files
376
+ if (modifiedFiles.length > 0) {
377
+ const tempModifiedBackupDir = path.join(projectDir, '.bmad-modified-backup-temp');
378
+ await fs.ensureDir(tempModifiedBackupDir);
379
+
380
+ spinner.start(`Backing up ${modifiedFiles.length} modified files...`);
381
+ for (const modifiedFile of modifiedFiles) {
382
+ const relativePath = path.relative(bmadDir, modifiedFile.path);
383
+ const tempBackupPath = path.join(tempModifiedBackupDir, relativePath);
384
+ await fs.ensureDir(path.dirname(tempBackupPath));
385
+ await fs.copy(modifiedFile.path, tempBackupPath, { overwrite: true });
386
+ }
387
+ spinner.succeed(`Backed up ${modifiedFiles.length} modified files`);
388
+ config._tempModifiedBackupDir = tempModifiedBackupDir;
389
+ }
390
+ }
391
+
392
+ // Now collect tool configurations after we know if it's a reinstall
393
+ // Skip for quick update since we already have the IDE list
394
+ spinner.stop();
395
+ let toolSelection;
396
+ if (config._quickUpdate) {
397
+ // Quick update already has IDEs configured, use saved configurations
398
+ const preConfiguredIdes = {};
399
+ const savedIdeConfigs = config._savedIdeConfigs || {};
400
+
401
+ for (const ide of config.ides || []) {
402
+ // Use saved config if available, otherwise mark as already configured (legacy)
403
+ if (savedIdeConfigs[ide]) {
404
+ preConfiguredIdes[ide] = savedIdeConfigs[ide];
405
+ } else {
406
+ preConfiguredIdes[ide] = { _alreadyConfigured: true };
407
+ }
408
+ }
409
+ toolSelection = {
410
+ ides: config.ides || [],
411
+ skipIde: !config.ides || config.ides.length === 0,
412
+ configurations: preConfiguredIdes,
413
+ };
414
+ } else {
415
+ // Pass pre-selected IDEs from early prompt (if available)
416
+ // This allows IDE selection to happen before file copying, improving UX
417
+ const preSelectedIdes = config.ides && config.ides.length > 0 ? config.ides : null;
418
+ toolSelection = await this.collectToolConfigurations(
419
+ path.resolve(config.directory),
420
+ config.modules,
421
+ config._isFullReinstall || false,
422
+ config._previouslyConfiguredIdes || [],
423
+ preSelectedIdes,
424
+ );
425
+ }
426
+
427
+ // Merge tool selection into config (for both quick update and regular flow)
428
+ config.ides = toolSelection.ides;
429
+ config.skipIde = toolSelection.skipIde;
430
+ const ideConfigurations = toolSelection.configurations;
431
+
432
+ spinner.start('Continuing installation...');
433
+
434
+ // Create bmad directory structure
435
+ spinner.text = 'Creating directory structure...';
436
+ await this.createDirectoryStructure(bmadDir);
437
+
438
+ // Resolve dependencies for selected modules
439
+ spinner.text = 'Resolving dependencies...';
440
+ const projectRoot = getProjectRoot();
441
+ const modulesToInstall = config.installCore ? ['core', ...config.modules] : config.modules;
442
+
443
+ // For dependency resolution, we need to pass the project root
444
+ const resolution = await this.dependencyResolver.resolve(projectRoot, config.modules || [], { verbose: config.verbose });
445
+
446
+ if (config.verbose) {
447
+ spinner.succeed('Dependencies resolved');
448
+ } else {
449
+ spinner.succeed('Dependencies resolved');
450
+ }
451
+
452
+ // Install core if requested or if dependencies require it
453
+ if (config.installCore || resolution.byModule.core) {
454
+ spinner.start('Installing BMAD core...');
455
+ await this.installCoreWithDependencies(bmadDir, resolution.byModule.core);
456
+ spinner.succeed('Core installed');
457
+ }
458
+
459
+ // Install modules with their dependencies
460
+ if (config.modules && config.modules.length > 0) {
461
+ for (const moduleName of config.modules) {
462
+ spinner.start(`Installing module: ${moduleName}...`);
463
+ await this.installModuleWithDependencies(moduleName, bmadDir, resolution.byModule[moduleName]);
464
+ spinner.succeed(`Module installed: ${moduleName}`);
465
+ }
466
+
467
+ // Install partial modules (only dependencies)
468
+ for (const [module, files] of Object.entries(resolution.byModule)) {
469
+ if (!config.modules.includes(module) && module !== 'core') {
470
+ const totalFiles =
471
+ files.agents.length +
472
+ files.tasks.length +
473
+ files.tools.length +
474
+ files.templates.length +
475
+ files.data.length +
476
+ files.other.length;
477
+ if (totalFiles > 0) {
478
+ spinner.start(`Installing ${module} dependencies...`);
479
+ await this.installPartialModule(module, bmadDir, files);
480
+ spinner.succeed(`${module} dependencies installed`);
481
+ }
482
+ }
483
+ }
484
+ }
485
+
486
+ // Generate clean config.yaml files for each installed module
487
+ spinner.start('Generating module configurations...');
488
+ await this.generateModuleConfigs(bmadDir, moduleConfigs);
489
+ spinner.succeed('Module configurations generated');
490
+
491
+ // Create agent configuration files
492
+ // Note: Legacy createAgentConfigs removed - using YAML customize system instead
493
+ // Customize templates are now created in processAgentFiles when building YAML agents
494
+
495
+ // Pre-register manifest files that will be created (except files-manifest.csv to avoid recursion)
496
+ const cfgDir = path.join(bmadDir, '_cfg');
497
+ this.installedFiles.push(
498
+ path.join(cfgDir, 'manifest.yaml'),
499
+ path.join(cfgDir, 'workflow-manifest.csv'),
500
+ path.join(cfgDir, 'agent-manifest.csv'),
501
+ path.join(cfgDir, 'task-manifest.csv'),
502
+ );
503
+
504
+ // Generate CSV manifests for workflows, agents, tasks AND ALL FILES with hashes BEFORE IDE setup
505
+ spinner.start('Generating workflow and agent manifests...');
506
+ const manifestGen = new ManifestGenerator();
507
+
508
+ // Include preserved modules (from quick update) in the manifest
509
+ const allModulesToList = config._preserveModules ? [...(config.modules || []), ...config._preserveModules] : config.modules || [];
510
+
511
+ const manifestStats = await manifestGen.generateManifests(bmadDir, config.modules || [], this.installedFiles, {
512
+ ides: config.ides || [],
513
+ preservedModules: config._preserveModules || [], // Scan these from installed bmad/ dir
514
+ });
515
+
516
+ spinner.succeed(
517
+ `Manifests generated: ${manifestStats.workflows} workflows, ${manifestStats.agents} agents, ${manifestStats.tasks} tasks, ${manifestStats.tools} tools, ${manifestStats.files} files`,
518
+ );
519
+
520
+ // Configure IDEs and copy documentation
521
+ if (!config.skipIde && config.ides && config.ides.length > 0) {
522
+ // Filter out any undefined/null values from the IDE list
523
+ const validIdes = config.ides.filter((ide) => ide && typeof ide === 'string');
524
+
525
+ if (validIdes.length === 0) {
526
+ console.log(chalk.yellow('⚠️ No valid IDEs selected. Skipping IDE configuration.'));
527
+ } else {
528
+ // Check if any IDE might need prompting (no pre-collected config)
529
+ const needsPrompting = validIdes.some((ide) => !ideConfigurations[ide]);
530
+
531
+ if (!needsPrompting) {
532
+ spinner.start('Configuring IDEs...');
533
+ }
534
+
535
+ // Temporarily suppress console output if not verbose
536
+ const originalLog = console.log;
537
+ if (!config.verbose) {
538
+ console.log = () => {};
539
+ }
540
+
541
+ for (const ide of validIdes) {
542
+ // Only show spinner if we have pre-collected config (no prompts expected)
543
+ if (ideConfigurations[ide] && !needsPrompting) {
544
+ spinner.text = `Configuring ${ide}...`;
545
+ } else if (!ideConfigurations[ide]) {
546
+ // Stop spinner before prompting
547
+ if (spinner.isSpinning) {
548
+ spinner.stop();
549
+ }
550
+ console.log(chalk.cyan(`\nConfiguring ${ide}...`));
551
+ }
552
+
553
+ // Pass pre-collected configuration to avoid re-prompting
554
+ await this.ideManager.setup(ide, projectDir, bmadDir, {
555
+ selectedModules: config.modules || [],
556
+ preCollectedConfig: ideConfigurations[ide] || null,
557
+ verbose: config.verbose,
558
+ });
559
+
560
+ // Save IDE configuration for future updates
561
+ if (ideConfigurations[ide] && !ideConfigurations[ide]._alreadyConfigured) {
562
+ await this.ideConfigManager.saveIdeConfig(bmadDir, ide, ideConfigurations[ide]);
563
+ }
564
+
565
+ // Restart spinner if we stopped it
566
+ if (!ideConfigurations[ide] && !spinner.isSpinning) {
567
+ spinner.start('Configuring IDEs...');
568
+ }
569
+ }
570
+
571
+ // Restore console.log
572
+ console.log = originalLog;
573
+
574
+ if (spinner.isSpinning) {
575
+ spinner.succeed(`Configured ${validIdes.length} IDE${validIdes.length > 1 ? 's' : ''}`);
576
+ } else {
577
+ console.log(chalk.green(`✓ Configured ${validIdes.length} IDE${validIdes.length > 1 ? 's' : ''}`));
578
+ }
579
+ }
580
+
581
+ // Copy IDE-specific documentation (only for valid IDEs)
582
+ const validIdesForDocs = (config.ides || []).filter((ide) => ide && typeof ide === 'string');
583
+ if (validIdesForDocs.length > 0) {
584
+ spinner.start('Copying IDE documentation...');
585
+ await this.copyIdeDocumentation(validIdesForDocs, bmadDir);
586
+ spinner.succeed('IDE documentation copied');
587
+ }
588
+ }
589
+
590
+ // Run module-specific installers after IDE setup
591
+ spinner.start('Running module-specific installers...');
592
+
593
+ // Run core module installer if core was installed
594
+ if (config.installCore || resolution.byModule.core) {
595
+ spinner.text = 'Running core module installer...';
596
+
597
+ await this.moduleManager.runModuleInstaller('core', bmadDir, {
598
+ installedIDEs: config.ides || [],
599
+ moduleConfig: moduleConfigs.core || {},
600
+ logger: {
601
+ log: (msg) => console.log(msg),
602
+ error: (msg) => console.error(msg),
603
+ warn: (msg) => console.warn(msg),
604
+ },
605
+ });
606
+ }
607
+
608
+ // Run installers for user-selected modules
609
+ if (config.modules && config.modules.length > 0) {
610
+ for (const moduleName of config.modules) {
611
+ spinner.text = `Running ${moduleName} module installer...`;
612
+
613
+ // Pass installed IDEs and module config to module installer
614
+ await this.moduleManager.runModuleInstaller(moduleName, bmadDir, {
615
+ installedIDEs: config.ides || [],
616
+ moduleConfig: moduleConfigs[moduleName] || {},
617
+ logger: {
618
+ log: (msg) => console.log(msg),
619
+ error: (msg) => console.error(msg),
620
+ warn: (msg) => console.warn(msg),
621
+ },
622
+ });
623
+ }
624
+ }
625
+
626
+ spinner.succeed('Module-specific installers completed');
627
+
628
+ // Note: Manifest files are already created by ManifestGenerator above
629
+ // No need to create legacy manifest.csv anymore
630
+
631
+ // If this was an update, restore custom files
632
+ let customFiles = [];
633
+ let modifiedFiles = [];
634
+ if (config._isUpdate) {
635
+ if (config._customFiles && config._customFiles.length > 0) {
636
+ spinner.start(`Restoring ${config._customFiles.length} custom files...`);
637
+
638
+ for (const originalPath of config._customFiles) {
639
+ const relativePath = path.relative(bmadDir, originalPath);
640
+ const backupPath = path.join(config._tempBackupDir, relativePath);
641
+
642
+ if (await fs.pathExists(backupPath)) {
643
+ await fs.ensureDir(path.dirname(originalPath));
644
+ await fs.copy(backupPath, originalPath, { overwrite: true });
645
+ }
646
+ }
647
+
648
+ // Clean up temp backup
649
+ if (config._tempBackupDir && (await fs.pathExists(config._tempBackupDir))) {
650
+ await fs.remove(config._tempBackupDir);
651
+ }
652
+
653
+ spinner.succeed(`Restored ${config._customFiles.length} custom files`);
654
+ customFiles = config._customFiles;
655
+ }
656
+
657
+ if (config._modifiedFiles && config._modifiedFiles.length > 0) {
658
+ modifiedFiles = config._modifiedFiles;
659
+
660
+ // Restore modified files as .bak files
661
+ if (config._tempModifiedBackupDir && (await fs.pathExists(config._tempModifiedBackupDir))) {
662
+ spinner.start(`Restoring ${modifiedFiles.length} modified files as .bak...`);
663
+
664
+ for (const modifiedFile of modifiedFiles) {
665
+ const relativePath = path.relative(bmadDir, modifiedFile.path);
666
+ const tempBackupPath = path.join(config._tempModifiedBackupDir, relativePath);
667
+ const bakPath = modifiedFile.path + '.bak';
668
+
669
+ if (await fs.pathExists(tempBackupPath)) {
670
+ await fs.ensureDir(path.dirname(bakPath));
671
+ await fs.copy(tempBackupPath, bakPath, { overwrite: true });
672
+ }
673
+ }
674
+
675
+ // Clean up temp backup
676
+ await fs.remove(config._tempModifiedBackupDir);
677
+
678
+ spinner.succeed(`Restored ${modifiedFiles.length} modified files as .bak`);
679
+ }
680
+ }
681
+ }
682
+
683
+ spinner.stop();
684
+
685
+ // Report custom and modified files if any were found
686
+ if (customFiles.length > 0) {
687
+ console.log(chalk.cyan(`\n📁 Custom files preserved: ${customFiles.length}`));
688
+ console.log(chalk.dim('The following custom files were found and restored:\n'));
689
+ for (const file of customFiles) {
690
+ console.log(chalk.dim(` - ${path.relative(bmadDir, file)}`));
691
+ }
692
+ console.log('');
693
+ }
694
+
695
+ if (modifiedFiles.length > 0) {
696
+ console.log(chalk.yellow(`\n⚠️ Modified files detected: ${modifiedFiles.length}`));
697
+ console.log(chalk.dim('The following files were modified and backed up with .bak extension:\n'));
698
+ for (const file of modifiedFiles) {
699
+ console.log(chalk.dim(` - ${file.relativePath} → ${file.relativePath}.bak`));
700
+ }
701
+ console.log(chalk.dim('\nThese files have been updated with the new version.'));
702
+ console.log(chalk.dim('Review the .bak files to see your changes and merge if needed.\n'));
703
+ }
704
+
705
+ // Display completion message
706
+ const { UI } = require('../../../lib/ui');
707
+ const ui = new UI();
708
+ ui.showInstallSummary({
709
+ path: bmadDir,
710
+ modules: config.modules,
711
+ ides: config.ides,
712
+ customFiles: customFiles.length > 0 ? customFiles : undefined,
713
+ });
714
+
715
+ return { success: true, path: bmadDir, modules: config.modules, ides: config.ides };
716
+ } catch (error) {
717
+ spinner.fail('Installation failed');
718
+ throw error;
719
+ }
720
+ }
721
+
722
+ /**
723
+ * Update existing installation
724
+ */
725
+ async update(config) {
726
+ const spinner = ora('Checking installation...').start();
727
+
728
+ try {
729
+ const bmadDir = path.join(path.resolve(config.directory), 'bmad');
730
+ const existingInstall = await this.detector.detect(bmadDir);
731
+
732
+ if (!existingInstall.installed) {
733
+ spinner.fail('No BMAD installation found');
734
+ throw new Error(`No BMAD installation found at ${bmadDir}`);
735
+ }
736
+
737
+ spinner.text = 'Analyzing update requirements...';
738
+
739
+ // Compare versions and determine what needs updating
740
+ const currentVersion = existingInstall.version;
741
+ const newVersion = require(path.join(getProjectRoot(), 'package.json')).version;
742
+
743
+ if (config.dryRun) {
744
+ spinner.stop();
745
+ console.log(chalk.cyan('\n🔍 Update Preview (Dry Run)\n'));
746
+ console.log(chalk.bold('Current version:'), currentVersion);
747
+ console.log(chalk.bold('New version:'), newVersion);
748
+ console.log(chalk.bold('Core:'), existingInstall.hasCore ? 'Will be updated' : 'Not installed');
749
+
750
+ if (existingInstall.modules.length > 0) {
751
+ console.log(chalk.bold('\nModules to update:'));
752
+ for (const mod of existingInstall.modules) {
753
+ console.log(` - ${mod.id}`);
754
+ }
755
+ }
756
+ return;
757
+ }
758
+
759
+ // Perform actual update
760
+ if (existingInstall.hasCore) {
761
+ spinner.text = 'Updating core...';
762
+ await this.updateCore(bmadDir, config.force);
763
+ }
764
+
765
+ for (const module of existingInstall.modules) {
766
+ spinner.text = `Updating module: ${module.id}...`;
767
+ await this.moduleManager.update(module.id, bmadDir, config.force);
768
+ }
769
+
770
+ // Update manifest
771
+ spinner.text = 'Updating manifest...';
772
+ await this.manifest.update(bmadDir, {
773
+ version: newVersion,
774
+ updateDate: new Date().toISOString(),
775
+ });
776
+
777
+ spinner.succeed('Update complete');
778
+ return { success: true };
779
+ } catch (error) {
780
+ spinner.fail('Update failed');
781
+ throw error;
782
+ }
783
+ }
784
+
785
+ /**
786
+ * Get installation status
787
+ */
788
+ async getStatus(directory) {
789
+ const bmadDir = path.join(path.resolve(directory), 'bmad');
790
+ return await this.detector.detect(bmadDir);
791
+ }
792
+
793
+ /**
794
+ * Get available modules
795
+ */
796
+ async getAvailableModules() {
797
+ return await this.moduleManager.listAvailable();
798
+ }
799
+
800
+ /**
801
+ * Uninstall BMAD
802
+ */
803
+ async uninstall(directory) {
804
+ const bmadDir = path.join(path.resolve(directory), 'bmad');
805
+
806
+ if (await fs.pathExists(bmadDir)) {
807
+ await fs.remove(bmadDir);
808
+ }
809
+
810
+ // Clean up IDE configurations
811
+ await this.ideManager.cleanup(path.resolve(directory));
812
+
813
+ return { success: true };
814
+ }
815
+
816
+ /**
817
+ * Private: Create directory structure
818
+ */
819
+ async createDirectoryStructure(bmadDir) {
820
+ await fs.ensureDir(bmadDir);
821
+ await fs.ensureDir(path.join(bmadDir, '_cfg'));
822
+ await fs.ensureDir(path.join(bmadDir, '_cfg', 'agents'));
823
+ }
824
+
825
+ /**
826
+ * Generate clean config.yaml files for each installed module
827
+ * @param {string} bmadDir - BMAD installation directory
828
+ * @param {Object} moduleConfigs - Collected configuration values
829
+ */
830
+ async generateModuleConfigs(bmadDir, moduleConfigs) {
831
+ const yaml = require('js-yaml');
832
+
833
+ // Extract core config values to share with other modules
834
+ const coreConfig = moduleConfigs.core || {};
835
+
836
+ // Get all installed module directories
837
+ const entries = await fs.readdir(bmadDir, { withFileTypes: true });
838
+ const installedModules = entries
839
+ .filter((entry) => entry.isDirectory() && entry.name !== '_cfg' && entry.name !== 'docs')
840
+ .map((entry) => entry.name);
841
+
842
+ // Generate config.yaml for each installed module
843
+ for (const moduleName of installedModules) {
844
+ const modulePath = path.join(bmadDir, moduleName);
845
+
846
+ // Get module-specific config or use empty object if none
847
+ const config = moduleConfigs[moduleName] || {};
848
+
849
+ if (await fs.pathExists(modulePath)) {
850
+ const configPath = path.join(modulePath, 'config.yaml');
851
+
852
+ // Create header
853
+ const packageJson = require(path.join(getProjectRoot(), 'package.json'));
854
+ const header = `# ${moduleName.toUpperCase()} Module Configuration
855
+ # Generated by BMAD installer
856
+ # Version: ${packageJson.version}
857
+ # Date: ${new Date().toISOString()}
858
+
859
+ `;
860
+
861
+ // For non-core modules, add core config values directly
862
+ let finalConfig = { ...config };
863
+ let coreSection = '';
864
+
865
+ if (moduleName !== 'core' && coreConfig && Object.keys(coreConfig).length > 0) {
866
+ // Add core values directly to the module config
867
+ // These will be available for reference in the module
868
+ finalConfig = {
869
+ ...config,
870
+ ...coreConfig, // Spread core config values directly into the module config
871
+ };
872
+
873
+ // Create a comment section to identify core values
874
+ coreSection = '\n# Core Configuration Values\n';
875
+ }
876
+
877
+ // Convert config to YAML
878
+ let yamlContent = yaml.dump(finalConfig, {
879
+ indent: 2,
880
+ lineWidth: -1,
881
+ noRefs: true,
882
+ sortKeys: false,
883
+ });
884
+
885
+ // If we have core values, reorganize the YAML to group them with their comment
886
+ if (coreSection && moduleName !== 'core') {
887
+ // Split the YAML into lines
888
+ const lines = yamlContent.split('\n');
889
+ const moduleConfigLines = [];
890
+ const coreConfigLines = [];
891
+
892
+ // Separate module-specific and core config lines
893
+ for (const line of lines) {
894
+ const key = line.split(':')[0].trim();
895
+ if (Object.prototype.hasOwnProperty.call(coreConfig, key)) {
896
+ coreConfigLines.push(line);
897
+ } else {
898
+ moduleConfigLines.push(line);
899
+ }
900
+ }
901
+
902
+ // Rebuild YAML with module config first, then core config with comment
903
+ yamlContent = moduleConfigLines.join('\n');
904
+ if (coreConfigLines.length > 0) {
905
+ yamlContent += coreSection + coreConfigLines.join('\n');
906
+ }
907
+ }
908
+
909
+ // Write the clean config file
910
+ await fs.writeFile(configPath, header + yamlContent, 'utf8');
911
+
912
+ // Track the config file in installedFiles
913
+ this.installedFiles.push(configPath);
914
+ }
915
+ }
916
+ }
917
+
918
+ /**
919
+ * Install core with resolved dependencies
920
+ * @param {string} bmadDir - BMAD installation directory
921
+ * @param {Object} coreFiles - Core files to install
922
+ */
923
+ async installCoreWithDependencies(bmadDir, coreFiles) {
924
+ const sourcePath = getModulePath('core');
925
+ const targetPath = path.join(bmadDir, 'core');
926
+
927
+ // Install full core
928
+ await this.installCore(bmadDir);
929
+
930
+ // If there are specific dependency files, ensure they're included
931
+ if (coreFiles) {
932
+ // Already handled by installCore for core module
933
+ }
934
+ }
935
+
936
+ /**
937
+ * Install module with resolved dependencies
938
+ * @param {string} moduleName - Module name
939
+ * @param {string} bmadDir - BMAD installation directory
940
+ * @param {Object} moduleFiles - Module files to install
941
+ */
942
+ async installModuleWithDependencies(moduleName, bmadDir, moduleFiles) {
943
+ // Get module configuration for conditional installation
944
+ const moduleConfig = this.configCollector.collectedConfig[moduleName] || {};
945
+
946
+ // Use existing module manager for full installation with file tracking
947
+ // Note: Module-specific installers are called separately after IDE setup
948
+ await this.moduleManager.install(
949
+ moduleName,
950
+ bmadDir,
951
+ (filePath) => {
952
+ this.installedFiles.push(filePath);
953
+ },
954
+ {
955
+ skipModuleInstaller: true, // We'll run it later after IDE setup
956
+ moduleConfig: moduleConfig, // Pass module config for conditional filtering
957
+ },
958
+ );
959
+
960
+ // Process agent files to build YAML agents and create customize templates
961
+ const modulePath = path.join(bmadDir, moduleName);
962
+ await this.processAgentFiles(modulePath, moduleName);
963
+
964
+ // Dependencies are already included in full module install
965
+ }
966
+
967
+ /**
968
+ * Install partial module (only dependencies needed by other modules)
969
+ */
970
+ async installPartialModule(moduleName, bmadDir, files) {
971
+ const sourceBase = getModulePath(moduleName);
972
+ const targetBase = path.join(bmadDir, moduleName);
973
+
974
+ // Create module directory
975
+ await fs.ensureDir(targetBase);
976
+
977
+ // Copy only the required dependency files
978
+ if (files.agents && files.agents.length > 0) {
979
+ const agentsDir = path.join(targetBase, 'agents');
980
+ await fs.ensureDir(agentsDir);
981
+
982
+ for (const agentPath of files.agents) {
983
+ const fileName = path.basename(agentPath);
984
+ const sourcePath = path.join(sourceBase, 'agents', fileName);
985
+ const targetPath = path.join(agentsDir, fileName);
986
+
987
+ if (await fs.pathExists(sourcePath)) {
988
+ await fs.copy(sourcePath, targetPath);
989
+ this.installedFiles.push(targetPath);
990
+ }
991
+ }
992
+ }
993
+
994
+ if (files.tasks && files.tasks.length > 0) {
995
+ const tasksDir = path.join(targetBase, 'tasks');
996
+ await fs.ensureDir(tasksDir);
997
+
998
+ for (const taskPath of files.tasks) {
999
+ const fileName = path.basename(taskPath);
1000
+ const sourcePath = path.join(sourceBase, 'tasks', fileName);
1001
+ const targetPath = path.join(tasksDir, fileName);
1002
+
1003
+ if (await fs.pathExists(sourcePath)) {
1004
+ await fs.copy(sourcePath, targetPath);
1005
+ this.installedFiles.push(targetPath);
1006
+ }
1007
+ }
1008
+ }
1009
+
1010
+ if (files.tools && files.tools.length > 0) {
1011
+ const toolsDir = path.join(targetBase, 'tools');
1012
+ await fs.ensureDir(toolsDir);
1013
+
1014
+ for (const toolPath of files.tools) {
1015
+ const fileName = path.basename(toolPath);
1016
+ const sourcePath = path.join(sourceBase, 'tools', fileName);
1017
+ const targetPath = path.join(toolsDir, fileName);
1018
+
1019
+ if (await fs.pathExists(sourcePath)) {
1020
+ await fs.copy(sourcePath, targetPath);
1021
+ this.installedFiles.push(targetPath);
1022
+ }
1023
+ }
1024
+ }
1025
+
1026
+ if (files.templates && files.templates.length > 0) {
1027
+ const templatesDir = path.join(targetBase, 'templates');
1028
+ await fs.ensureDir(templatesDir);
1029
+
1030
+ for (const templatePath of files.templates) {
1031
+ const fileName = path.basename(templatePath);
1032
+ const sourcePath = path.join(sourceBase, 'templates', fileName);
1033
+ const targetPath = path.join(templatesDir, fileName);
1034
+
1035
+ if (await fs.pathExists(sourcePath)) {
1036
+ await fs.copy(sourcePath, targetPath);
1037
+ this.installedFiles.push(targetPath);
1038
+ }
1039
+ }
1040
+ }
1041
+
1042
+ if (files.data && files.data.length > 0) {
1043
+ for (const dataPath of files.data) {
1044
+ // Preserve directory structure for data files
1045
+ const relative = path.relative(sourceBase, dataPath);
1046
+ const targetPath = path.join(targetBase, relative);
1047
+
1048
+ await fs.ensureDir(path.dirname(targetPath));
1049
+
1050
+ if (await fs.pathExists(dataPath)) {
1051
+ await fs.copy(dataPath, targetPath);
1052
+ this.installedFiles.push(targetPath);
1053
+ }
1054
+ }
1055
+ }
1056
+
1057
+ // Create a marker file to indicate this is a partial installation
1058
+ const markerPath = path.join(targetBase, '.partial');
1059
+ await fs.writeFile(
1060
+ markerPath,
1061
+ `This module contains only dependencies required by other modules.\nInstalled: ${new Date().toISOString()}\n`,
1062
+ );
1063
+ }
1064
+
1065
+ /**
1066
+ * Private: Install core
1067
+ * @param {string} bmadDir - BMAD installation directory
1068
+ */
1069
+ async installCore(bmadDir) {
1070
+ const sourcePath = getModulePath('core');
1071
+ const targetPath = path.join(bmadDir, 'core');
1072
+
1073
+ // Copy core files with filtering for localskip agents
1074
+ await this.copyDirectoryWithFiltering(sourcePath, targetPath);
1075
+
1076
+ // Process agent files to inject activation block
1077
+ await this.processAgentFiles(targetPath, 'core');
1078
+ }
1079
+
1080
+ /**
1081
+ * Copy directory with filtering for localskip agents
1082
+ * @param {string} sourcePath - Source directory path
1083
+ * @param {string} targetPath - Target directory path
1084
+ */
1085
+ async copyDirectoryWithFiltering(sourcePath, targetPath) {
1086
+ // Get all files in source directory
1087
+ const files = await this.getFileList(sourcePath);
1088
+
1089
+ for (const file of files) {
1090
+ // Skip config.yaml templates - we'll generate clean ones with actual values
1091
+ if (file === 'config.yaml' || file.endsWith('/config.yaml')) {
1092
+ continue;
1093
+ }
1094
+
1095
+ const sourceFile = path.join(sourcePath, file);
1096
+ const targetFile = path.join(targetPath, file);
1097
+
1098
+ // Check if this is an agent file
1099
+ if (file.includes('agents/') && file.endsWith('.md')) {
1100
+ // Read the file to check for localskip
1101
+ const content = await fs.readFile(sourceFile, 'utf8');
1102
+
1103
+ // Check for localskip="true" in the agent tag
1104
+ const agentMatch = content.match(/<agent[^>]*\slocalskip="true"[^>]*>/);
1105
+ if (agentMatch) {
1106
+ console.log(chalk.dim(` Skipping web-only agent: ${path.basename(file)}`));
1107
+ continue; // Skip this agent
1108
+ }
1109
+ }
1110
+
1111
+ // Copy the file
1112
+ await fs.ensureDir(path.dirname(targetFile));
1113
+ await fs.copy(sourceFile, targetFile, { overwrite: true });
1114
+
1115
+ // Track the installed file
1116
+ this.installedFiles.push(targetFile);
1117
+ }
1118
+ }
1119
+
1120
+ /**
1121
+ * Get list of all files in a directory recursively
1122
+ * @param {string} dir - Directory path
1123
+ * @param {string} baseDir - Base directory for relative paths
1124
+ * @returns {Array} List of relative file paths
1125
+ */
1126
+ async getFileList(dir, baseDir = dir) {
1127
+ const files = [];
1128
+ const entries = await fs.readdir(dir, { withFileTypes: true });
1129
+
1130
+ for (const entry of entries) {
1131
+ const fullPath = path.join(dir, entry.name);
1132
+
1133
+ if (entry.isDirectory()) {
1134
+ // Skip _module-installer directories
1135
+ if (entry.name === '_module-installer') {
1136
+ continue;
1137
+ }
1138
+ const subFiles = await this.getFileList(fullPath, baseDir);
1139
+ files.push(...subFiles);
1140
+ } else {
1141
+ files.push(path.relative(baseDir, fullPath));
1142
+ }
1143
+ }
1144
+
1145
+ return files;
1146
+ }
1147
+
1148
+ /**
1149
+ * Process agent files to build YAML agents and inject activation blocks
1150
+ * @param {string} modulePath - Path to module in bmad/ installation
1151
+ * @param {string} moduleName - Module name
1152
+ */
1153
+ async processAgentFiles(modulePath, moduleName) {
1154
+ const agentsPath = path.join(modulePath, 'agents');
1155
+
1156
+ // Check if agents directory exists
1157
+ if (!(await fs.pathExists(agentsPath))) {
1158
+ return; // No agents to process
1159
+ }
1160
+
1161
+ // Determine project directory (parent of bmad/ directory)
1162
+ const bmadDir = path.dirname(modulePath);
1163
+ const projectDir = path.dirname(bmadDir);
1164
+ const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
1165
+
1166
+ // Ensure _cfg/agents directory exists
1167
+ await fs.ensureDir(cfgAgentsDir);
1168
+
1169
+ // Get all agent files
1170
+ const agentFiles = await fs.readdir(agentsPath);
1171
+
1172
+ for (const agentFile of agentFiles) {
1173
+ // Handle YAML agents - build them to .md
1174
+ if (agentFile.endsWith('.agent.yaml')) {
1175
+ const agentName = agentFile.replace('.agent.yaml', '');
1176
+ const yamlPath = path.join(agentsPath, agentFile);
1177
+ const mdPath = path.join(agentsPath, `${agentName}.md`);
1178
+ const customizePath = path.join(cfgAgentsDir, `${moduleName}-${agentName}.customize.yaml`);
1179
+
1180
+ // Create customize template if it doesn't exist
1181
+ if (!(await fs.pathExists(customizePath))) {
1182
+ const genericTemplatePath = getSourcePath('utility', 'templates', 'agent.customize.template.yaml');
1183
+ if (await fs.pathExists(genericTemplatePath)) {
1184
+ await fs.copy(genericTemplatePath, customizePath);
1185
+ console.log(chalk.dim(` Created customize: ${moduleName}-${agentName}.customize.yaml`));
1186
+ }
1187
+ }
1188
+
1189
+ // Build YAML + customize to .md
1190
+ const customizeExists = await fs.pathExists(customizePath);
1191
+ const xmlContent = await this.xmlHandler.buildFromYaml(yamlPath, customizeExists ? customizePath : null, {
1192
+ includeMetadata: true,
1193
+ });
1194
+
1195
+ // DO NOT replace {project-root} - LLMs understand this placeholder at runtime
1196
+ // const processedContent = xmlContent.replaceAll('{project-root}', projectDir);
1197
+
1198
+ // Write the built .md file to bmad/{module}/agents/
1199
+ await fs.writeFile(mdPath, xmlContent, 'utf8');
1200
+ this.installedFiles.push(mdPath);
1201
+
1202
+ // Remove the source YAML file - we can regenerate from installer source if needed
1203
+ await fs.remove(yamlPath);
1204
+
1205
+ console.log(chalk.dim(` Built agent: ${agentName}.md`));
1206
+ }
1207
+ // Handle legacy .md agents - inject activation if needed
1208
+ else if (agentFile.endsWith('.md')) {
1209
+ const agentPath = path.join(agentsPath, agentFile);
1210
+ let content = await fs.readFile(agentPath, 'utf8');
1211
+
1212
+ // Check if content has agent XML and no activation block
1213
+ if (content.includes('<agent') && !content.includes('<activation')) {
1214
+ // Inject the activation block using XML handler
1215
+ content = this.xmlHandler.injectActivationSimple(content);
1216
+ await fs.writeFile(agentPath, content, 'utf8');
1217
+ }
1218
+ }
1219
+ }
1220
+ }
1221
+
1222
+ /**
1223
+ * Build standalone agents in bmad/agents/ directory
1224
+ * @param {string} bmadDir - Path to bmad directory
1225
+ * @param {string} projectDir - Path to project directory
1226
+ */
1227
+ async buildStandaloneAgents(bmadDir, projectDir) {
1228
+ const standaloneAgentsPath = path.join(bmadDir, 'agents');
1229
+ const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
1230
+
1231
+ // Check if standalone agents directory exists
1232
+ if (!(await fs.pathExists(standaloneAgentsPath))) {
1233
+ return;
1234
+ }
1235
+
1236
+ // Get all subdirectories in agents/
1237
+ const agentDirs = await fs.readdir(standaloneAgentsPath, { withFileTypes: true });
1238
+
1239
+ for (const agentDir of agentDirs) {
1240
+ if (!agentDir.isDirectory()) continue;
1241
+
1242
+ const agentDirPath = path.join(standaloneAgentsPath, agentDir.name);
1243
+
1244
+ // Find any .agent.yaml file in the directory
1245
+ const files = await fs.readdir(agentDirPath);
1246
+ const yamlFile = files.find((f) => f.endsWith('.agent.yaml'));
1247
+
1248
+ if (!yamlFile) continue;
1249
+
1250
+ const agentName = path.basename(yamlFile, '.agent.yaml');
1251
+ const sourceYamlPath = path.join(agentDirPath, yamlFile);
1252
+ const targetMdPath = path.join(agentDirPath, `${agentName}.md`);
1253
+ const customizePath = path.join(cfgAgentsDir, `${agentName}.customize.yaml`);
1254
+
1255
+ // Check for customizations
1256
+ const customizeExists = await fs.pathExists(customizePath);
1257
+ let customizedFields = [];
1258
+
1259
+ if (customizeExists) {
1260
+ const customizeContent = await fs.readFile(customizePath, 'utf8');
1261
+ const yaml = require('js-yaml');
1262
+ const customizeYaml = yaml.load(customizeContent);
1263
+
1264
+ // Detect what fields are customized (similar to rebuildAgentFiles)
1265
+ if (customizeYaml) {
1266
+ if (customizeYaml.persona) {
1267
+ for (const [key, value] of Object.entries(customizeYaml.persona)) {
1268
+ if (value !== '' && value !== null && !(Array.isArray(value) && value.length === 0)) {
1269
+ customizedFields.push(`persona.${key}`);
1270
+ }
1271
+ }
1272
+ }
1273
+ if (customizeYaml.agent?.metadata) {
1274
+ for (const [key, value] of Object.entries(customizeYaml.agent.metadata)) {
1275
+ if (value !== '' && value !== null) {
1276
+ customizedFields.push(`metadata.${key}`);
1277
+ }
1278
+ }
1279
+ }
1280
+ if (customizeYaml.critical_actions && customizeYaml.critical_actions.length > 0) {
1281
+ customizedFields.push('critical_actions');
1282
+ }
1283
+ if (customizeYaml.menu && customizeYaml.menu.length > 0) {
1284
+ customizedFields.push('menu');
1285
+ }
1286
+ }
1287
+ }
1288
+
1289
+ // Build YAML to XML .md
1290
+ const xmlContent = await this.xmlHandler.buildFromYaml(sourceYamlPath, customizeExists ? customizePath : null, {
1291
+ includeMetadata: true,
1292
+ });
1293
+
1294
+ // DO NOT replace {project-root} - LLMs understand this placeholder at runtime
1295
+ // const processedContent = xmlContent.replaceAll('{project-root}', projectDir);
1296
+
1297
+ // Write the built .md file
1298
+ await fs.writeFile(targetMdPath, xmlContent, 'utf8');
1299
+
1300
+ // Display result
1301
+ if (customizedFields.length > 0) {
1302
+ console.log(chalk.dim(` Built standalone agent: ${agentName}.md `) + chalk.yellow(`(customized: ${customizedFields.join(', ')})`));
1303
+ } else {
1304
+ console.log(chalk.dim(` Built standalone agent: ${agentName}.md`));
1305
+ }
1306
+ }
1307
+ }
1308
+
1309
+ /**
1310
+ * Rebuild agent files from installer source (for compile command)
1311
+ * @param {string} modulePath - Path to module in bmad/ installation
1312
+ * @param {string} moduleName - Module name
1313
+ */
1314
+ async rebuildAgentFiles(modulePath, moduleName) {
1315
+ // Get source agents directory from installer
1316
+ const sourceAgentsPath =
1317
+ moduleName === 'core' ? path.join(getModulePath('core'), 'agents') : path.join(getSourcePath(`modules/${moduleName}`), 'agents');
1318
+
1319
+ if (!(await fs.pathExists(sourceAgentsPath))) {
1320
+ return; // No source agents to rebuild
1321
+ }
1322
+
1323
+ // Determine project directory (parent of bmad/ directory)
1324
+ const bmadDir = path.dirname(modulePath);
1325
+ const projectDir = path.dirname(bmadDir);
1326
+ const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
1327
+ const targetAgentsPath = path.join(modulePath, 'agents');
1328
+
1329
+ // Ensure target directory exists
1330
+ await fs.ensureDir(targetAgentsPath);
1331
+
1332
+ // Get all YAML agent files from source
1333
+ const sourceFiles = await fs.readdir(sourceAgentsPath);
1334
+
1335
+ for (const file of sourceFiles) {
1336
+ if (file.endsWith('.agent.yaml')) {
1337
+ const agentName = file.replace('.agent.yaml', '');
1338
+ const sourceYamlPath = path.join(sourceAgentsPath, file);
1339
+ const targetMdPath = path.join(targetAgentsPath, `${agentName}.md`);
1340
+ const customizePath = path.join(cfgAgentsDir, `${moduleName}-${agentName}.customize.yaml`);
1341
+
1342
+ // Check for customizations
1343
+ const customizeExists = await fs.pathExists(customizePath);
1344
+ let customizedFields = [];
1345
+
1346
+ if (customizeExists) {
1347
+ const customizeContent = await fs.readFile(customizePath, 'utf8');
1348
+ const yaml = require('js-yaml');
1349
+ const customizeYaml = yaml.load(customizeContent);
1350
+
1351
+ // Detect what fields are customized
1352
+ if (customizeYaml) {
1353
+ if (customizeYaml.persona) {
1354
+ for (const [key, value] of Object.entries(customizeYaml.persona)) {
1355
+ if (value !== '' && value !== null && !(Array.isArray(value) && value.length === 0)) {
1356
+ customizedFields.push(`persona.${key}`);
1357
+ }
1358
+ }
1359
+ }
1360
+ if (customizeYaml.agent?.metadata) {
1361
+ for (const [key, value] of Object.entries(customizeYaml.agent.metadata)) {
1362
+ if (value !== '' && value !== null) {
1363
+ customizedFields.push(`metadata.${key}`);
1364
+ }
1365
+ }
1366
+ }
1367
+ if (customizeYaml.critical_actions && customizeYaml.critical_actions.length > 0) {
1368
+ customizedFields.push('critical_actions');
1369
+ }
1370
+ if (customizeYaml.memories && customizeYaml.memories.length > 0) {
1371
+ customizedFields.push('memories');
1372
+ }
1373
+ if (customizeYaml.menu && customizeYaml.menu.length > 0) {
1374
+ customizedFields.push('menu');
1375
+ }
1376
+ if (customizeYaml.prompts && customizeYaml.prompts.length > 0) {
1377
+ customizedFields.push('prompts');
1378
+ }
1379
+ }
1380
+ }
1381
+
1382
+ // Build YAML + customize to .md
1383
+ const xmlContent = await this.xmlHandler.buildFromYaml(sourceYamlPath, customizeExists ? customizePath : null, {
1384
+ includeMetadata: true,
1385
+ });
1386
+
1387
+ // DO NOT replace {project-root} - LLMs understand this placeholder at runtime
1388
+ // const processedContent = xmlContent.replaceAll('{project-root}', projectDir);
1389
+
1390
+ // Write the rebuilt .md file
1391
+ await fs.writeFile(targetMdPath, xmlContent, 'utf8');
1392
+
1393
+ // Display result with customizations if any
1394
+ if (customizedFields.length > 0) {
1395
+ console.log(chalk.dim(` Rebuilt agent: ${agentName}.md `) + chalk.yellow(`(customized: ${customizedFields.join(', ')})`));
1396
+ } else {
1397
+ console.log(chalk.dim(` Rebuilt agent: ${agentName}.md`));
1398
+ }
1399
+ }
1400
+ }
1401
+ }
1402
+
1403
+ /**
1404
+ * Compile/rebuild all agents and tasks for quick updates
1405
+ * @param {Object} config - Compilation configuration
1406
+ * @returns {Object} Compilation results
1407
+ */
1408
+ async compileAgents(config) {
1409
+ const ora = require('ora');
1410
+ const spinner = ora('Starting agent compilation...').start();
1411
+
1412
+ try {
1413
+ const projectDir = path.resolve(config.directory);
1414
+ const bmadDir = path.join(projectDir, 'bmad');
1415
+
1416
+ // Check if bmad directory exists
1417
+ if (!(await fs.pathExists(bmadDir))) {
1418
+ spinner.fail('No BMAD installation found');
1419
+ throw new Error(`BMAD not installed at ${bmadDir}`);
1420
+ }
1421
+
1422
+ let agentCount = 0;
1423
+ let taskCount = 0;
1424
+
1425
+ // Process all modules in bmad directory
1426
+ spinner.text = 'Rebuilding agent files...';
1427
+ const entries = await fs.readdir(bmadDir, { withFileTypes: true });
1428
+
1429
+ for (const entry of entries) {
1430
+ if (entry.isDirectory() && entry.name !== '_cfg' && entry.name !== 'docs') {
1431
+ const modulePath = path.join(bmadDir, entry.name);
1432
+
1433
+ // Special handling for standalone agents in bmad/agents/ directory
1434
+ if (entry.name === 'agents') {
1435
+ spinner.text = 'Building standalone agents...';
1436
+ await this.buildStandaloneAgents(bmadDir, projectDir);
1437
+
1438
+ // Count standalone agents
1439
+ const standaloneAgentsPath = path.join(bmadDir, 'agents');
1440
+ const standaloneAgentDirs = await fs.readdir(standaloneAgentsPath, { withFileTypes: true });
1441
+ for (const agentDir of standaloneAgentDirs) {
1442
+ if (agentDir.isDirectory()) {
1443
+ const agentDirPath = path.join(standaloneAgentsPath, agentDir.name);
1444
+ const agentFiles = await fs.readdir(agentDirPath);
1445
+ agentCount += agentFiles.filter((f) => f.endsWith('.md') && !f.endsWith('.agent.yaml')).length;
1446
+ }
1447
+ }
1448
+ } else {
1449
+ // Rebuild module agents from installer source
1450
+ const agentsPath = path.join(modulePath, 'agents');
1451
+ if (await fs.pathExists(agentsPath)) {
1452
+ await this.rebuildAgentFiles(modulePath, entry.name);
1453
+ const agentFiles = await fs.readdir(agentsPath);
1454
+ agentCount += agentFiles.filter((f) => f.endsWith('.md')).length;
1455
+ }
1456
+
1457
+ // Count tasks (already built)
1458
+ const tasksPath = path.join(modulePath, 'tasks');
1459
+ if (await fs.pathExists(tasksPath)) {
1460
+ const taskFiles = await fs.readdir(tasksPath);
1461
+ taskCount += taskFiles.filter((f) => f.endsWith('.md')).length;
1462
+ }
1463
+ }
1464
+ }
1465
+ }
1466
+
1467
+ // Regenerate manifests after compilation
1468
+ spinner.start('Regenerating manifests...');
1469
+ const installedModules = entries
1470
+ .filter((e) => e.isDirectory() && e.name !== '_cfg' && e.name !== 'docs' && e.name !== 'agents' && e.name !== 'core')
1471
+ .map((e) => e.name);
1472
+ const manifestGen = new ManifestGenerator();
1473
+
1474
+ // Get existing IDE list from manifest
1475
+ const existingManifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml');
1476
+ let existingIdes = [];
1477
+ if (await fs.pathExists(existingManifestPath)) {
1478
+ const manifestContent = await fs.readFile(existingManifestPath, 'utf8');
1479
+ const yaml = require('js-yaml');
1480
+ const manifest = yaml.load(manifestContent);
1481
+ existingIdes = manifest.ides || [];
1482
+ }
1483
+
1484
+ await manifestGen.generateManifests(bmadDir, installedModules, [], {
1485
+ ides: existingIdes,
1486
+ });
1487
+ spinner.succeed('Manifests regenerated');
1488
+
1489
+ // Ask for IDE to update
1490
+ spinner.stop();
1491
+ // Note: UI lives in tools/cli/lib/ui.js; from installers/lib/core use '../../../lib/ui'
1492
+ const { UI } = require('../../../lib/ui');
1493
+ const ui = new UI();
1494
+ const toolConfig = await ui.promptToolSelection(projectDir, []);
1495
+
1496
+ if (!toolConfig.skipIde && toolConfig.ides && toolConfig.ides.length > 0) {
1497
+ spinner.start('Updating IDE configurations...');
1498
+
1499
+ for (const ide of toolConfig.ides) {
1500
+ spinner.text = `Updating ${ide}...`;
1501
+ await this.ideManager.setup(ide, projectDir, bmadDir, {
1502
+ selectedModules: installedModules,
1503
+ skipModuleInstall: true, // Skip module installation, just update IDE files
1504
+ verbose: config.verbose,
1505
+ });
1506
+ }
1507
+
1508
+ spinner.succeed('IDE configurations updated');
1509
+ }
1510
+
1511
+ return { agentCount, taskCount };
1512
+ } catch (error) {
1513
+ spinner.fail('Compilation failed');
1514
+ throw error;
1515
+ }
1516
+ }
1517
+
1518
+ /**
1519
+ * Private: Update core
1520
+ */
1521
+ async updateCore(bmadDir, force = false) {
1522
+ const sourcePath = getModulePath('core');
1523
+ const targetPath = path.join(bmadDir, 'core');
1524
+
1525
+ if (force) {
1526
+ await fs.remove(targetPath);
1527
+ await this.installCore(bmadDir);
1528
+ } else {
1529
+ // Selective update - preserve user modifications
1530
+ await this.fileOps.syncDirectory(sourcePath, targetPath);
1531
+ }
1532
+ }
1533
+
1534
+ /**
1535
+ * Quick update method - preserves all settings and only prompts for new config fields
1536
+ * @param {Object} config - Configuration with directory
1537
+ * @returns {Object} Update result
1538
+ */
1539
+ async quickUpdate(config) {
1540
+ const ora = require('ora');
1541
+ const spinner = ora('Starting quick update...').start();
1542
+
1543
+ try {
1544
+ const projectDir = path.resolve(config.directory);
1545
+ const bmadDir = path.join(projectDir, 'bmad');
1546
+
1547
+ // Check if bmad directory exists
1548
+ if (!(await fs.pathExists(bmadDir))) {
1549
+ spinner.fail('No BMAD installation found');
1550
+ throw new Error(`BMAD not installed at ${bmadDir}. Use regular install for first-time setup.`);
1551
+ }
1552
+
1553
+ spinner.text = 'Detecting installed modules and configuration...';
1554
+
1555
+ // Detect existing installation
1556
+ const existingInstall = await this.detector.detect(bmadDir);
1557
+ const installedModules = existingInstall.modules.map((m) => m.id);
1558
+ const configuredIdes = existingInstall.ides || [];
1559
+
1560
+ // Load saved IDE configurations
1561
+ const savedIdeConfigs = await this.ideConfigManager.loadAllIdeConfigs(bmadDir);
1562
+
1563
+ // Get available modules (what we have source for)
1564
+ const availableModules = await this.moduleManager.listAvailable();
1565
+ const availableModuleIds = new Set(availableModules.map((m) => m.id));
1566
+
1567
+ // Only update modules that are BOTH installed AND available (we have source for)
1568
+ const modulesToUpdate = installedModules.filter((id) => availableModuleIds.has(id));
1569
+ const skippedModules = installedModules.filter((id) => !availableModuleIds.has(id));
1570
+
1571
+ spinner.succeed(`Found ${modulesToUpdate.length} module(s) to update and ${configuredIdes.length} configured tool(s)`);
1572
+
1573
+ if (skippedModules.length > 0) {
1574
+ console.log(chalk.yellow(`⚠️ Skipping ${skippedModules.length} module(s) - no source available: ${skippedModules.join(', ')}`));
1575
+ }
1576
+
1577
+ // Load existing configs and collect new fields (if any)
1578
+ console.log(chalk.cyan('\n📋 Checking for new configuration options...'));
1579
+ await this.configCollector.loadExistingConfig(projectDir);
1580
+
1581
+ let promptedForNewFields = false;
1582
+
1583
+ // Check core config for new fields
1584
+ const corePrompted = await this.configCollector.collectModuleConfigQuick('core', projectDir, true);
1585
+ if (corePrompted) {
1586
+ promptedForNewFields = true;
1587
+ }
1588
+
1589
+ // Check each module we're updating for new fields (NOT skipped modules)
1590
+ for (const moduleName of modulesToUpdate) {
1591
+ const modulePrompted = await this.configCollector.collectModuleConfigQuick(moduleName, projectDir, true);
1592
+ if (modulePrompted) {
1593
+ promptedForNewFields = true;
1594
+ }
1595
+ }
1596
+
1597
+ if (!promptedForNewFields) {
1598
+ console.log(chalk.green('✓ All configuration is up to date, no new options to configure'));
1599
+ }
1600
+
1601
+ // Add metadata
1602
+ this.configCollector.collectedConfig._meta = {
1603
+ version: require(path.join(getProjectRoot(), 'package.json')).version,
1604
+ installDate: new Date().toISOString(),
1605
+ lastModified: new Date().toISOString(),
1606
+ };
1607
+
1608
+ // Now run the full installation with the collected configs
1609
+ spinner.start('Updating BMAD installation...');
1610
+
1611
+ // Build the config object for the installer
1612
+ const installConfig = {
1613
+ directory: projectDir,
1614
+ installCore: true,
1615
+ modules: modulesToUpdate, // Only update modules we have source for
1616
+ ides: configuredIdes,
1617
+ skipIde: configuredIdes.length === 0,
1618
+ coreConfig: this.configCollector.collectedConfig.core,
1619
+ actionType: 'install', // Use regular install flow
1620
+ _quickUpdate: true, // Flag to skip certain prompts
1621
+ _preserveModules: skippedModules, // Preserve these in manifest even though we didn't update them
1622
+ _savedIdeConfigs: savedIdeConfigs, // Pass saved IDE configs to installer
1623
+ };
1624
+
1625
+ // Call the standard install method
1626
+ const result = await this.install(installConfig);
1627
+
1628
+ spinner.succeed('Quick update complete!');
1629
+
1630
+ return {
1631
+ success: true,
1632
+ moduleCount: modulesToUpdate.length + 1, // +1 for core
1633
+ hadNewFields: promptedForNewFields,
1634
+ modules: ['core', ...modulesToUpdate],
1635
+ skippedModules: skippedModules,
1636
+ ides: configuredIdes,
1637
+ };
1638
+ } catch (error) {
1639
+ spinner.fail('Quick update failed');
1640
+ throw error;
1641
+ }
1642
+ }
1643
+
1644
+ /**
1645
+ * Private: Prompt for update action
1646
+ */
1647
+ async promptUpdateAction() {
1648
+ const inquirer = require('inquirer');
1649
+ return await inquirer.prompt([
1650
+ {
1651
+ type: 'list',
1652
+ name: 'action',
1653
+ message: 'What would you like to do?',
1654
+ choices: [
1655
+ { name: 'Update existing installation', value: 'update' },
1656
+ { name: 'Remove and reinstall', value: 'reinstall' },
1657
+ { name: 'Cancel', value: 'cancel' },
1658
+ ],
1659
+ },
1660
+ ]);
1661
+ }
1662
+
1663
+ /**
1664
+ * Handle legacy BMAD v4 migration with automatic backup
1665
+ * @param {string} projectDir - Project directory
1666
+ * @param {Object} legacyV4 - Legacy V4 detection result with offenders array
1667
+ */
1668
+ async handleLegacyV4Migration(projectDir, legacyV4) {
1669
+ console.log(chalk.yellow.bold('\n⚠️ Legacy BMAD v4 detected'));
1670
+ console.log(chalk.dim('The installer found legacy artefacts in your project.\n'));
1671
+
1672
+ // Separate .bmad* folders (auto-backup) from other offending paths (manual cleanup)
1673
+ const bmadFolders = legacyV4.offenders.filter((p) => {
1674
+ const name = path.basename(p);
1675
+ return name.startsWith('.bmad'); // Only dot-prefixed folders get auto-backed up
1676
+ });
1677
+ const otherOffenders = legacyV4.offenders.filter((p) => {
1678
+ const name = path.basename(p);
1679
+ return !name.startsWith('.bmad'); // Everything else is manual cleanup
1680
+ });
1681
+
1682
+ const inquirer = require('inquirer');
1683
+
1684
+ // Show warning for other offending paths FIRST
1685
+ if (otherOffenders.length > 0) {
1686
+ console.log(chalk.yellow('⚠️ Recommended cleanup:'));
1687
+ console.log(chalk.dim('It is recommended to remove the following items before proceeding:\n'));
1688
+ for (const p of otherOffenders) console.log(chalk.dim(` - ${p}`));
1689
+
1690
+ console.log(chalk.cyan('\nCleanup commands you can copy/paste:'));
1691
+ console.log(chalk.dim('macOS/Linux:'));
1692
+ for (const p of otherOffenders) console.log(chalk.dim(` rm -rf '${p}'`));
1693
+ console.log(chalk.dim('Windows:'));
1694
+ for (const p of otherOffenders) console.log(chalk.dim(` rmdir /S /Q "${p}"`));
1695
+
1696
+ const { cleanedUp } = await inquirer.prompt([
1697
+ {
1698
+ type: 'confirm',
1699
+ name: 'cleanedUp',
1700
+ message: 'Have you completed the recommended cleanup? (You can proceed without it, but it is recommended)',
1701
+ default: false,
1702
+ },
1703
+ ]);
1704
+
1705
+ if (cleanedUp) {
1706
+ console.log(chalk.green('✓ Cleanup acknowledged\n'));
1707
+ } else {
1708
+ console.log(chalk.yellow('⚠️ Proceeding without recommended cleanup\n'));
1709
+ }
1710
+ }
1711
+
1712
+ // Handle .bmad* folders with automatic backup
1713
+ if (bmadFolders.length > 0) {
1714
+ console.log(chalk.cyan('The following legacy folders will be moved to v4-backup:'));
1715
+ for (const p of bmadFolders) console.log(chalk.dim(` - ${p}`));
1716
+
1717
+ const { proceed } = await inquirer.prompt([
1718
+ {
1719
+ type: 'confirm',
1720
+ name: 'proceed',
1721
+ message: 'Proceed with backing up legacy v4 folders?',
1722
+ default: true,
1723
+ },
1724
+ ]);
1725
+
1726
+ if (proceed) {
1727
+ const backupDir = path.join(projectDir, 'v4-backup');
1728
+ await fs.ensureDir(backupDir);
1729
+
1730
+ for (const folder of bmadFolders) {
1731
+ const folderName = path.basename(folder);
1732
+ const backupPath = path.join(backupDir, folderName);
1733
+
1734
+ // If backup already exists, add timestamp
1735
+ let finalBackupPath = backupPath;
1736
+ if (await fs.pathExists(backupPath)) {
1737
+ const timestamp = new Date().toISOString().replaceAll(/[:.]/g, '-').split('T')[0];
1738
+ finalBackupPath = path.join(backupDir, `${folderName}-${timestamp}`);
1739
+ }
1740
+
1741
+ await fs.move(folder, finalBackupPath, { overwrite: false });
1742
+ console.log(chalk.green(`✓ Moved ${folderName} to ${path.relative(projectDir, finalBackupPath)}`));
1743
+ }
1744
+ } else {
1745
+ throw new Error('Installation cancelled by user');
1746
+ }
1747
+ }
1748
+ }
1749
+
1750
+ /**
1751
+ * Read files-manifest.csv
1752
+ * @param {string} bmadDir - BMAD installation directory
1753
+ * @returns {Array} Array of file entries from files-manifest.csv
1754
+ */
1755
+ async readFilesManifest(bmadDir) {
1756
+ const filesManifestPath = path.join(bmadDir, '_cfg', 'files-manifest.csv');
1757
+ if (!(await fs.pathExists(filesManifestPath))) {
1758
+ return [];
1759
+ }
1760
+
1761
+ try {
1762
+ const content = await fs.readFile(filesManifestPath, 'utf8');
1763
+ const lines = content.split('\n');
1764
+ const files = [];
1765
+
1766
+ for (let i = 1; i < lines.length; i++) {
1767
+ // Skip header
1768
+ const line = lines[i].trim();
1769
+ if (!line) continue;
1770
+
1771
+ // Parse CSV line properly handling quoted values
1772
+ const parts = [];
1773
+ let current = '';
1774
+ let inQuotes = false;
1775
+
1776
+ for (const char of line) {
1777
+ if (char === '"') {
1778
+ inQuotes = !inQuotes;
1779
+ } else if (char === ',' && !inQuotes) {
1780
+ parts.push(current);
1781
+ current = '';
1782
+ } else {
1783
+ current += char;
1784
+ }
1785
+ }
1786
+ parts.push(current); // Add last part
1787
+
1788
+ if (parts.length >= 4) {
1789
+ files.push({
1790
+ type: parts[0],
1791
+ name: parts[1],
1792
+ module: parts[2],
1793
+ path: parts[3],
1794
+ hash: parts[4] || null, // Hash may not exist in old manifests
1795
+ });
1796
+ }
1797
+ }
1798
+
1799
+ return files;
1800
+ } catch (error) {
1801
+ console.warn('Warning: Could not read files-manifest.csv:', error.message);
1802
+ return [];
1803
+ }
1804
+ }
1805
+
1806
+ /**
1807
+ * Detect custom and modified files
1808
+ * @param {string} bmadDir - BMAD installation directory
1809
+ * @param {Array} existingFilesManifest - Previous files from files-manifest.csv
1810
+ * @returns {Object} Object with customFiles and modifiedFiles arrays
1811
+ */
1812
+ async detectCustomFiles(bmadDir, existingFilesManifest) {
1813
+ const customFiles = [];
1814
+ const modifiedFiles = [];
1815
+
1816
+ // Check if the manifest has hashes - if not, we can't detect modifications
1817
+ let manifestHasHashes = false;
1818
+ if (existingFilesManifest && existingFilesManifest.length > 0) {
1819
+ manifestHasHashes = existingFilesManifest.some((f) => f.hash);
1820
+ }
1821
+
1822
+ // Build map of previously installed files from files-manifest.csv with their hashes
1823
+ const installedFilesMap = new Map();
1824
+ for (const fileEntry of existingFilesManifest) {
1825
+ if (fileEntry.path) {
1826
+ // Files in manifest are stored as relative paths starting with 'bmad/'
1827
+ // Convert to absolute path
1828
+ const relativePath = fileEntry.path.startsWith('bmad/') ? fileEntry.path.slice(5) : fileEntry.path;
1829
+ const absolutePath = path.join(bmadDir, relativePath);
1830
+ installedFilesMap.set(path.normalize(absolutePath), {
1831
+ hash: fileEntry.hash,
1832
+ relativePath: relativePath,
1833
+ });
1834
+ }
1835
+ }
1836
+
1837
+ // Recursively scan bmadDir for all files
1838
+ const scanDirectory = async (dir) => {
1839
+ try {
1840
+ const entries = await fs.readdir(dir, { withFileTypes: true });
1841
+ for (const entry of entries) {
1842
+ const fullPath = path.join(dir, entry.name);
1843
+
1844
+ if (entry.isDirectory()) {
1845
+ // Skip certain directories
1846
+ if (entry.name === 'node_modules' || entry.name === '.git') {
1847
+ continue;
1848
+ }
1849
+ await scanDirectory(fullPath);
1850
+ } else if (entry.isFile()) {
1851
+ const normalizedPath = path.normalize(fullPath);
1852
+ const fileInfo = installedFilesMap.get(normalizedPath);
1853
+
1854
+ // Skip certain system files that are auto-generated
1855
+ const relativePath = path.relative(bmadDir, fullPath);
1856
+ const fileName = path.basename(fullPath);
1857
+
1858
+ // Skip _cfg directory - system files
1859
+ if (relativePath.startsWith('_cfg/') || relativePath.startsWith('_cfg\\')) {
1860
+ continue;
1861
+ }
1862
+
1863
+ // Skip config.yaml files - these are regenerated on each install/update
1864
+ // Users should use _cfg/agents/ override files instead
1865
+ if (fileName === 'config.yaml') {
1866
+ continue;
1867
+ }
1868
+
1869
+ if (!fileInfo) {
1870
+ // File not in manifest = custom file
1871
+ customFiles.push(fullPath);
1872
+ } else if (manifestHasHashes && fileInfo.hash) {
1873
+ // File in manifest with hash - check if it was modified
1874
+ const currentHash = await this.manifest.calculateFileHash(fullPath);
1875
+ if (currentHash && currentHash !== fileInfo.hash) {
1876
+ // Hash changed = file was modified
1877
+ modifiedFiles.push({
1878
+ path: fullPath,
1879
+ relativePath: fileInfo.relativePath,
1880
+ });
1881
+ }
1882
+ }
1883
+ // If manifest doesn't have hashes, we can't detect modifications
1884
+ // so we just skip files that are in the manifest
1885
+ }
1886
+ }
1887
+ } catch {
1888
+ // Ignore errors scanning directories
1889
+ }
1890
+ };
1891
+
1892
+ await scanDirectory(bmadDir);
1893
+ return { customFiles, modifiedFiles };
1894
+ }
1895
+
1896
+ /**
1897
+ * Private: Create agent configuration files
1898
+ * @param {string} bmadDir - BMAD installation directory
1899
+ * @param {Object} userInfo - User information including name and language
1900
+ */
1901
+ async createAgentConfigs(bmadDir, userInfo = null) {
1902
+ const agentConfigDir = path.join(bmadDir, '_cfg', 'agents');
1903
+ await fs.ensureDir(agentConfigDir);
1904
+
1905
+ // Get all agents from all modules
1906
+ const agents = [];
1907
+ const agentDetails = []; // For manifest generation
1908
+
1909
+ // Check modules for agents (including core)
1910
+ const entries = await fs.readdir(bmadDir, { withFileTypes: true });
1911
+ for (const entry of entries) {
1912
+ if (entry.isDirectory() && entry.name !== '_cfg') {
1913
+ const moduleAgentsPath = path.join(bmadDir, entry.name, 'agents');
1914
+ if (await fs.pathExists(moduleAgentsPath)) {
1915
+ const agentFiles = await fs.readdir(moduleAgentsPath);
1916
+ for (const agentFile of agentFiles) {
1917
+ if (agentFile.endsWith('.md')) {
1918
+ const agentPath = path.join(moduleAgentsPath, agentFile);
1919
+ const agentContent = await fs.readFile(agentPath, 'utf8');
1920
+
1921
+ // Skip agents with localskip="true"
1922
+ const hasLocalSkip = agentContent.match(/<agent[^>]*\slocalskip="true"[^>]*>/);
1923
+ if (hasLocalSkip) {
1924
+ continue; // Skip this agent - it should not have been installed
1925
+ }
1926
+
1927
+ const agentName = path.basename(agentFile, '.md');
1928
+
1929
+ // Extract any nodes with agentConfig="true"
1930
+ const agentConfigNodes = this.extractAgentConfigNodes(agentContent);
1931
+
1932
+ agents.push({
1933
+ name: agentName,
1934
+ module: entry.name,
1935
+ agentConfigNodes: agentConfigNodes,
1936
+ });
1937
+
1938
+ // Use shared AgentPartyGenerator to extract details
1939
+ let details = AgentPartyGenerator.extractAgentDetails(agentContent, entry.name, agentName);
1940
+
1941
+ // Apply config overrides if they exist
1942
+ if (details) {
1943
+ const configPath = path.join(agentConfigDir, `${entry.name}-${agentName}.md`);
1944
+ if (await fs.pathExists(configPath)) {
1945
+ const configContent = await fs.readFile(configPath, 'utf8');
1946
+ details = AgentPartyGenerator.applyConfigOverrides(details, configContent);
1947
+ }
1948
+ agentDetails.push(details);
1949
+ }
1950
+ }
1951
+ }
1952
+ }
1953
+ }
1954
+ }
1955
+
1956
+ // Create config file for each agent
1957
+ let createdCount = 0;
1958
+ let skippedCount = 0;
1959
+
1960
+ // Load agent config template
1961
+ const templatePath = getSourcePath('utility', 'models', 'agent-config-template.md');
1962
+ const templateContent = await fs.readFile(templatePath, 'utf8');
1963
+
1964
+ for (const agent of agents) {
1965
+ const configPath = path.join(agentConfigDir, `${agent.module}-${agent.name}.md`);
1966
+
1967
+ // Skip if config file already exists (preserve custom configurations)
1968
+ if (await fs.pathExists(configPath)) {
1969
+ skippedCount++;
1970
+ continue;
1971
+ }
1972
+
1973
+ // Build config content header
1974
+ let configContent = `# Agent Config: ${agent.name}\n\n`;
1975
+
1976
+ // Process template and add agent-specific config nodes
1977
+ let processedTemplate = templateContent;
1978
+
1979
+ // Replace {core:user_name} placeholder with actual user name if available
1980
+ if (userInfo && userInfo.userName) {
1981
+ processedTemplate = processedTemplate.replaceAll('{core:user_name}', userInfo.userName);
1982
+ }
1983
+
1984
+ // Replace {core:communication_language} placeholder with actual language if available
1985
+ if (userInfo && userInfo.responseLanguage) {
1986
+ processedTemplate = processedTemplate.replaceAll('{core:communication_language}', userInfo.responseLanguage);
1987
+ }
1988
+
1989
+ // If this agent has agentConfig nodes, add them after the existing comment
1990
+ if (agent.agentConfigNodes && agent.agentConfigNodes.length > 0) {
1991
+ // Find the agent-specific configuration nodes comment
1992
+ const commentPattern = /(\s*<!-- Agent-specific configuration nodes -->)/;
1993
+ const commentMatch = processedTemplate.match(commentPattern);
1994
+
1995
+ if (commentMatch) {
1996
+ // Add nodes right after the comment
1997
+ let agentSpecificNodes = '';
1998
+ for (const node of agent.agentConfigNodes) {
1999
+ agentSpecificNodes += `\n ${node}`;
2000
+ }
2001
+
2002
+ processedTemplate = processedTemplate.replace(commentPattern, `$1${agentSpecificNodes}`);
2003
+ }
2004
+ }
2005
+
2006
+ configContent += processedTemplate;
2007
+
2008
+ await fs.writeFile(configPath, configContent, 'utf8');
2009
+ this.installedFiles.push(configPath); // Track agent config files
2010
+ createdCount++;
2011
+ }
2012
+
2013
+ // Generate agent manifest with overrides applied
2014
+ await this.generateAgentManifest(bmadDir, agentDetails);
2015
+
2016
+ return { total: agents.length, created: createdCount, skipped: skippedCount };
2017
+ }
2018
+
2019
+ /**
2020
+ * Generate agent manifest XML file
2021
+ * @param {string} bmadDir - BMAD installation directory
2022
+ * @param {Array} agentDetails - Array of agent details
2023
+ */
2024
+ async generateAgentManifest(bmadDir, agentDetails) {
2025
+ const manifestPath = path.join(bmadDir, '_cfg', 'agent-manifest.csv');
2026
+ await AgentPartyGenerator.writeAgentParty(manifestPath, agentDetails, { forWeb: false });
2027
+ }
2028
+
2029
+ /**
2030
+ * Extract nodes with agentConfig="true" from agent content
2031
+ * @param {string} content - Agent file content
2032
+ * @returns {Array} Array of XML nodes that should be added to agent config
2033
+ */
2034
+ extractAgentConfigNodes(content) {
2035
+ const nodes = [];
2036
+
2037
+ try {
2038
+ // Find all XML nodes with agentConfig="true"
2039
+ // Match self-closing tags and tags with content
2040
+ const selfClosingPattern = /<([a-zA-Z][a-zA-Z0-9_-]*)\s+[^>]*agentConfig="true"[^>]*\/>/g;
2041
+ const withContentPattern = /<([a-zA-Z][a-zA-Z0-9_-]*)\s+[^>]*agentConfig="true"[^>]*>([\s\S]*?)<\/\1>/g;
2042
+
2043
+ // Extract self-closing tags
2044
+ let match;
2045
+ while ((match = selfClosingPattern.exec(content)) !== null) {
2046
+ // Extract just the tag without children (structure only)
2047
+ const tagMatch = match[0].match(/<([a-zA-Z][a-zA-Z0-9_-]*)([^>]*)\/>/);
2048
+ if (tagMatch) {
2049
+ const tagName = tagMatch[1];
2050
+ const attributes = tagMatch[2].replace(/\s*agentConfig="true"/, ''); // Remove agentConfig attribute
2051
+ nodes.push(`<${tagName}${attributes}></${tagName}>`);
2052
+ }
2053
+ }
2054
+
2055
+ // Extract tags with content
2056
+ while ((match = withContentPattern.exec(content)) !== null) {
2057
+ const fullMatch = match[0];
2058
+ const tagName = match[1];
2059
+
2060
+ // Extract opening tag with attributes (removing agentConfig="true")
2061
+ const openingTagMatch = fullMatch.match(new RegExp(`<${tagName}([^>]*)>`));
2062
+ if (openingTagMatch) {
2063
+ const attributes = openingTagMatch[1].replace(/\s*agentConfig="true"/, '');
2064
+ // Add empty node structure (no children)
2065
+ nodes.push(`<${tagName}${attributes}></${tagName}>`);
2066
+ }
2067
+ }
2068
+ } catch (error) {
2069
+ console.error('Error extracting agentConfig nodes:', error);
2070
+ }
2071
+
2072
+ return nodes;
2073
+ }
2074
+
2075
+ /**
2076
+ * Copy IDE-specific documentation to BMAD docs
2077
+ * @param {Array} ides - List of selected IDEs
2078
+ * @param {string} bmadDir - BMAD installation directory
2079
+ */
2080
+ async copyIdeDocumentation(ides, bmadDir) {
2081
+ const docsDir = path.join(bmadDir, 'docs');
2082
+ await fs.ensureDir(docsDir);
2083
+
2084
+ for (const ide of ides) {
2085
+ const sourceDocPath = path.join(getProjectRoot(), 'docs', 'ide-info', `${ide}.md`);
2086
+ const targetDocPath = path.join(docsDir, `${ide}-instructions.md`);
2087
+
2088
+ if (await fs.pathExists(sourceDocPath)) {
2089
+ await fs.copy(sourceDocPath, targetDocPath, { overwrite: true });
2090
+ }
2091
+ }
2092
+ }
2093
+ }
2094
+
2095
+ module.exports = { Installer };