bmad-method 6.0.0-alpha.0 → 6.0.0-alpha.10

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 (704) hide show
  1. package/.github/ISSUE_TEMPLATE/config.yaml +4 -0
  2. package/.github/ISSUE_TEMPLATE/idea_submission.md +3 -3
  3. package/.github/workflows/bundle-latest.yaml +277 -0
  4. package/.github/workflows/manual-release.yaml +64 -17
  5. package/.github/workflows/quality.yaml +78 -0
  6. package/.husky/pre-commit +4 -0
  7. package/.prettierignore +6 -0
  8. package/.vscode/settings.json +3 -1
  9. package/CHANGELOG.md +1211 -2
  10. package/CONTRIBUTING.md +2 -13
  11. package/README.md +442 -0
  12. package/docs/BUNDLE_DISTRIBUTION_SETUP.md +95 -0
  13. package/docs/agent-customization-guide.md +208 -0
  14. package/docs/document-sharding-guide.md +449 -0
  15. package/docs/ide-info/auggie.md +2 -2
  16. package/docs/ide-info/claude-code.md +4 -4
  17. package/docs/ide-info/codex.md +9 -20
  18. package/docs/ide-info/crush.md +1 -1
  19. package/docs/ide-info/cursor.md +7 -7
  20. package/docs/ide-info/iflow.md +3 -3
  21. package/docs/ide-info/opencode.md +24 -0
  22. package/docs/index.md +227 -0
  23. package/docs/installers-bundlers/ide-injections.md +2 -12
  24. package/docs/installers-bundlers/installers-modules-platforms-reference.md +100 -67
  25. package/docs/v4-to-v6-upgrade.md +227 -0
  26. package/docs/web-bundles-gemini-gpt-guide.md +473 -0
  27. package/eslint.config.mjs +6 -2
  28. package/package.json +13 -6
  29. package/src/core/_module-installer/install-config.yaml +35 -0
  30. package/src/core/_module-installer/installer.js +1 -9
  31. package/src/core/agents/bmad-master.agent.yaml +39 -0
  32. package/src/core/agents/bmad-web-orchestrator.agent.xml +113 -0
  33. package/src/core/tasks/advanced-elicitation-methods.csv +21 -0
  34. package/src/core/tasks/{adv-elicit.md → advanced-elicitation.xml} +11 -14
  35. package/src/core/tasks/{index-docs.md → index-docs.xml} +6 -10
  36. package/src/core/tasks/{validate-workflow.md → validate-workflow.xml} +4 -7
  37. package/src/core/tasks/workflow.xml +270 -0
  38. package/src/core/tools/shard-doc.xml +109 -0
  39. package/src/{modules/cis → core}/workflows/brainstorming/README.md +8 -18
  40. package/src/{modules/cis → core}/workflows/brainstorming/instructions.md +29 -24
  41. package/src/{modules/cis → core}/workflows/brainstorming/template.md +6 -2
  42. package/src/{modules/cis → core}/workflows/brainstorming/workflow.yaml +17 -9
  43. package/src/core/workflows/party-mode/instructions.md +27 -25
  44. package/src/core/workflows/party-mode/workflow.yaml +14 -10
  45. package/src/modules/bmb/README.md +194 -0
  46. package/src/modules/bmb/_module-installer/install-config.yaml +31 -0
  47. package/src/modules/bmb/agents/bmad-builder.agent.yaml +57 -0
  48. package/src/modules/bmb/workflows/audit-workflow/checklist.md +142 -0
  49. package/src/modules/bmb/workflows/audit-workflow/instructions.md +341 -0
  50. package/src/modules/bmb/workflows/audit-workflow/template.md +118 -0
  51. package/src/modules/bmb/workflows/audit-workflow/workflow.yaml +25 -0
  52. package/src/modules/bmb/workflows/convert-legacy/README.md +34 -34
  53. package/src/modules/bmb/workflows/convert-legacy/checklist.md +22 -21
  54. package/src/modules/bmb/workflows/convert-legacy/instructions.md +135 -86
  55. package/src/modules/bmb/workflows/convert-legacy/workflow.yaml +10 -15
  56. package/src/modules/bmb/workflows/create-agent/README.md +144 -209
  57. package/src/modules/bmb/workflows/create-agent/agent-architecture.md +68 -65
  58. package/src/modules/bmb/workflows/create-agent/agent-command-patterns.md +174 -172
  59. package/src/modules/bmb/workflows/create-agent/agent-types.md +139 -24
  60. package/src/modules/bmb/workflows/create-agent/brainstorm-context.md +4 -4
  61. package/src/modules/bmb/workflows/create-agent/checklist.md +30 -102
  62. package/src/modules/bmb/workflows/create-agent/communication-styles.md +22 -60
  63. package/src/modules/bmb/workflows/create-agent/instructions.md +339 -221
  64. package/src/modules/bmb/workflows/create-agent/workflow.yaml +28 -19
  65. package/src/modules/bmb/workflows/create-module/README.md +164 -153
  66. package/src/modules/bmb/workflows/create-module/brainstorm-context.md +1 -1
  67. package/src/modules/bmb/workflows/create-module/checklist.md +21 -31
  68. package/src/modules/bmb/workflows/create-module/installer-templates/install-config.yaml +92 -0
  69. package/src/modules/bmb/workflows/create-module/installer-templates/installer.js +1 -1
  70. package/src/modules/bmb/workflows/create-module/instructions.md +306 -238
  71. package/src/modules/bmb/workflows/create-module/module-structure.md +135 -45
  72. package/src/modules/bmb/workflows/create-module/workflow.yaml +32 -27
  73. package/src/modules/bmb/workflows/create-workflow/README.md +70 -9
  74. package/src/modules/bmb/workflows/create-workflow/brainstorm-context.md +4 -4
  75. package/src/modules/bmb/workflows/create-workflow/checklist.md +22 -0
  76. package/src/modules/bmb/workflows/create-workflow/instructions.md +505 -47
  77. package/src/modules/bmb/workflows/create-workflow/workflow-creation-guide.md +939 -68
  78. package/src/modules/bmb/workflows/create-workflow/workflow-template/instructions.md +6 -3
  79. package/src/modules/bmb/workflows/create-workflow/workflow-template/workflow.yaml +31 -5
  80. package/src/modules/bmb/workflows/create-workflow/workflow.yaml +16 -17
  81. package/src/modules/bmb/workflows/edit-agent/README.md +112 -0
  82. package/src/modules/bmb/workflows/edit-agent/checklist.md +112 -0
  83. package/src/modules/bmb/workflows/edit-agent/instructions.md +290 -0
  84. package/src/modules/bmb/workflows/edit-agent/workflow.yaml +33 -0
  85. package/src/modules/bmb/workflows/edit-module/README.md +187 -0
  86. package/src/modules/bmb/workflows/edit-module/checklist.md +165 -0
  87. package/src/modules/bmb/workflows/edit-module/instructions.md +341 -0
  88. package/src/modules/bmb/workflows/edit-module/workflow.yaml +34 -0
  89. package/src/modules/bmb/workflows/edit-workflow/README.md +58 -2
  90. package/src/modules/bmb/workflows/edit-workflow/instructions.md +290 -118
  91. package/src/modules/bmb/workflows/edit-workflow/workflow.yaml +9 -16
  92. package/src/modules/bmb/workflows/module-brief/README.md +17 -17
  93. package/src/modules/bmb/workflows/module-brief/checklist.md +6 -6
  94. package/src/modules/bmb/workflows/module-brief/instructions.md +10 -7
  95. package/src/modules/bmb/workflows/module-brief/template.md +9 -9
  96. package/src/modules/bmb/workflows/module-brief/workflow.yaml +16 -10
  97. package/src/modules/bmb/workflows/redoc/README.md +5 -5
  98. package/src/modules/bmb/workflows/redoc/checklist.md +2 -2
  99. package/src/modules/bmb/workflows/redoc/instructions.md +20 -10
  100. package/src/modules/bmb/workflows/redoc/workflow.yaml +6 -5
  101. package/src/modules/bmgd/README.md +208 -0
  102. package/src/modules/bmgd/_module-installer/install-config.yaml +54 -0
  103. package/src/modules/bmgd/agents/game-architect.agent.yaml +33 -0
  104. package/src/modules/bmgd/agents/game-designer.agent.yaml +40 -0
  105. package/src/modules/bmgd/agents/game-dev.agent.yaml +40 -0
  106. package/src/modules/bmgd/agents/game-scrum-master.agent.yaml +75 -0
  107. package/src/modules/bmgd/teams/default-party.csv +10 -0
  108. package/src/modules/bmgd/teams/team-gamedev.yaml +18 -0
  109. package/src/modules/{bmm/workflows/1-analysis → bmgd/workflows/1-preproduction}/brainstorm-game/game-context.md +3 -3
  110. package/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/instructions.md +130 -0
  111. package/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/workflow.yaml +41 -0
  112. package/src/modules/{bmm/workflows/1-analysis → bmgd/workflows/1-preproduction}/game-brief/checklist.md +2 -2
  113. package/src/modules/bmgd/workflows/1-preproduction/game-brief/instructions.md +373 -0
  114. package/src/modules/{bmm/workflows/1-analysis → bmgd/workflows/1-preproduction}/game-brief/template.md +2 -2
  115. package/src/modules/bmgd/workflows/1-preproduction/game-brief/workflow.yaml +36 -0
  116. package/src/modules/bmgd/workflows/2-design/gdd/checklist.md +148 -0
  117. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/action-platformer.md +1 -1
  118. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/adventure.md +1 -1
  119. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/card-game.md +2 -2
  120. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/fighting.md +1 -1
  121. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/horror.md +2 -2
  122. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/idle-incremental.md +1 -1
  123. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/moba.md +4 -4
  124. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/party-game.md +1 -1
  125. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/racing.md +3 -3
  126. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/rhythm.md +1 -1
  127. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/roguelike.md +2 -2
  128. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/rpg.md +3 -3
  129. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/sandbox.md +4 -4
  130. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/shooter.md +3 -3
  131. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/simulation.md +3 -3
  132. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/sports.md +3 -3
  133. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/strategy.md +3 -3
  134. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/survival.md +2 -2
  135. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/text-based.md +3 -3
  136. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/tower-defense.md +5 -5
  137. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/turn-based-tactics.md +4 -4
  138. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/visual-novel.md +1 -1
  139. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/gdd-template.md +6 -12
  140. package/src/modules/bmgd/workflows/2-design/gdd/instructions-gdd.md +502 -0
  141. package/src/modules/bmgd/workflows/2-design/gdd/workflow.yaml +81 -0
  142. package/src/modules/bmgd/workflows/2-design/narrative/checklist.md +139 -0
  143. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/narrative/instructions-narrative.md +99 -12
  144. package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/narrative/narrative-template.md +8 -8
  145. package/src/modules/bmgd/workflows/2-design/narrative/workflow.yaml +32 -0
  146. package/src/modules/bmgd/workflows/3-technical/game-architecture/architecture-patterns.yaml +321 -0
  147. package/src/modules/bmgd/workflows/3-technical/game-architecture/architecture-template.md +103 -0
  148. package/src/modules/bmgd/workflows/3-technical/game-architecture/checklist.md +240 -0
  149. package/src/modules/bmgd/workflows/3-technical/game-architecture/decision-catalog.yaml +222 -0
  150. package/src/modules/bmgd/workflows/3-technical/game-architecture/instructions.md +701 -0
  151. package/src/modules/bmgd/workflows/3-technical/game-architecture/pattern-categories.csv +13 -0
  152. package/src/modules/bmgd/workflows/3-technical/game-architecture/workflow.yaml +69 -0
  153. package/src/modules/bmgd/workflows/4-production/code-review/instructions.md +398 -0
  154. package/src/modules/bmgd/workflows/4-production/code-review/workflow.yaml +61 -0
  155. package/src/modules/bmgd/workflows/4-production/correct-course/checklist.md +279 -0
  156. package/src/modules/bmgd/workflows/4-production/correct-course/instructions.md +206 -0
  157. package/src/modules/bmgd/workflows/4-production/correct-course/workflow.yaml +58 -0
  158. package/src/modules/bmgd/workflows/4-production/create-story/checklist.md +240 -0
  159. package/src/modules/bmgd/workflows/4-production/create-story/instructions.md +256 -0
  160. package/src/modules/bmgd/workflows/4-production/create-story/template.md +51 -0
  161. package/src/modules/bmgd/workflows/4-production/create-story/workflow.yaml +74 -0
  162. package/src/modules/bmgd/workflows/4-production/dev-story/checklist.md +38 -0
  163. package/src/modules/bmgd/workflows/4-production/dev-story/instructions.md +267 -0
  164. package/src/modules/bmgd/workflows/4-production/dev-story/workflow.yaml +58 -0
  165. package/src/modules/{bmm/workflows/3-solutioning/tech-spec → bmgd/workflows/4-production/epic-tech-context}/checklist.md +1 -1
  166. package/src/modules/bmgd/workflows/4-production/epic-tech-context/instructions.md +164 -0
  167. package/src/modules/{bmm/workflows/3-solutioning/tech-spec → bmgd/workflows/4-production/epic-tech-context}/template.md +1 -1
  168. package/src/modules/bmgd/workflows/4-production/epic-tech-context/workflow.yaml +58 -0
  169. package/src/modules/bmgd/workflows/4-production/retrospective/instructions.md +1443 -0
  170. package/src/modules/bmgd/workflows/4-production/retrospective/workflow.yaml +57 -0
  171. package/src/modules/bmgd/workflows/4-production/sprint-planning/checklist.md +33 -0
  172. package/src/modules/bmgd/workflows/4-production/sprint-planning/instructions.md +234 -0
  173. package/src/modules/bmgd/workflows/4-production/sprint-planning/sprint-status-template.yaml +55 -0
  174. package/src/modules/bmgd/workflows/4-production/sprint-planning/workflow.yaml +51 -0
  175. package/src/modules/bmgd/workflows/4-production/story-context/checklist.md +16 -0
  176. package/src/modules/bmgd/workflows/4-production/story-context/context-template.xml +34 -0
  177. package/src/modules/bmgd/workflows/4-production/story-context/instructions.md +209 -0
  178. package/src/modules/bmgd/workflows/4-production/story-context/workflow.yaml +63 -0
  179. package/src/modules/bmgd/workflows/4-production/story-done/instructions.md +111 -0
  180. package/src/modules/bmgd/workflows/4-production/story-done/workflow.yaml +28 -0
  181. package/src/modules/bmgd/workflows/4-production/story-ready/instructions.md +117 -0
  182. package/src/modules/bmgd/workflows/4-production/story-ready/workflow.yaml +25 -0
  183. package/src/modules/bmm/README.md +128 -0
  184. package/src/modules/bmm/_module-installer/install-config.yaml +60 -0
  185. package/src/modules/bmm/_module-installer/installer.js +3 -3
  186. package/src/modules/bmm/_module-installer/platform-specifics/claude-code.js +1 -1
  187. package/src/modules/bmm/_module-installer/platform-specifics/windsurf.js +1 -1
  188. package/src/modules/bmm/agents/analyst.agent.yaml +49 -0
  189. package/src/modules/bmm/agents/architect.agent.yaml +42 -0
  190. package/src/modules/bmm/agents/dev.agent.yaml +40 -0
  191. package/src/modules/bmm/agents/frame-expert.agent.yaml +42 -0
  192. package/src/modules/bmm/agents/pm.agent.yaml +64 -0
  193. package/src/modules/bmm/agents/sm.agent.yaml +73 -0
  194. package/src/modules/bmm/agents/tea.agent.yaml +67 -0
  195. package/src/modules/bmm/agents/tech-writer.agent.yaml +68 -0
  196. package/src/modules/bmm/agents/ux-designer.agent.yaml +39 -0
  197. package/src/modules/bmm/docs/README.md +236 -0
  198. package/src/modules/bmm/docs/agents-guide.md +1058 -0
  199. package/src/modules/bmm/docs/brownfield-guide.md +762 -0
  200. package/src/modules/bmm/docs/enterprise-agentic-development.md +686 -0
  201. package/src/modules/bmm/docs/faq.md +588 -0
  202. package/src/modules/bmm/docs/glossary.md +320 -0
  203. package/src/modules/bmm/docs/party-mode.md +224 -0
  204. package/src/modules/bmm/docs/quick-spec-flow.md +652 -0
  205. package/src/modules/bmm/docs/quick-start.md +376 -0
  206. package/src/modules/bmm/docs/scale-adaptive-system.md +612 -0
  207. package/src/modules/bmm/docs/test-architecture.md +396 -0
  208. package/src/modules/bmm/docs/workflow-architecture-reference.md +366 -0
  209. package/src/modules/bmm/docs/workflow-document-project-reference.md +489 -0
  210. package/src/modules/bmm/docs/workflows-analysis.md +370 -0
  211. package/src/modules/bmm/docs/workflows-implementation.md +286 -0
  212. package/src/modules/bmm/docs/workflows-planning.md +612 -0
  213. package/src/modules/bmm/docs/workflows-solutioning.md +554 -0
  214. package/src/modules/bmm/teams/default-party.csv +20 -0
  215. package/src/modules/bmm/teams/team-fullstack.yaml +13 -0
  216. package/src/modules/bmm/testarch/knowledge/ci-burn-in.md +675 -0
  217. package/src/modules/bmm/testarch/knowledge/component-tdd.md +486 -0
  218. package/src/modules/bmm/testarch/knowledge/contract-testing.md +957 -0
  219. package/src/modules/bmm/testarch/knowledge/data-factories.md +500 -0
  220. package/src/modules/bmm/testarch/knowledge/email-auth.md +721 -0
  221. package/src/modules/bmm/testarch/knowledge/error-handling.md +725 -0
  222. package/src/modules/bmm/testarch/knowledge/feature-flags.md +750 -0
  223. package/src/modules/bmm/testarch/knowledge/fixture-architecture.md +401 -0
  224. package/src/modules/bmm/testarch/knowledge/network-first.md +486 -0
  225. package/src/modules/bmm/testarch/knowledge/nfr-criteria.md +670 -0
  226. package/src/modules/bmm/testarch/knowledge/playwright-config.md +730 -0
  227. package/src/modules/bmm/testarch/knowledge/probability-impact.md +601 -0
  228. package/src/modules/bmm/testarch/knowledge/risk-governance.md +615 -0
  229. package/src/modules/bmm/testarch/knowledge/selective-testing.md +732 -0
  230. package/src/modules/bmm/testarch/knowledge/selector-resilience.md +527 -0
  231. package/src/modules/bmm/testarch/knowledge/test-healing-patterns.md +644 -0
  232. package/src/modules/bmm/testarch/knowledge/test-levels-framework.md +473 -0
  233. package/src/modules/bmm/testarch/knowledge/test-priorities-matrix.md +373 -0
  234. package/src/modules/bmm/testarch/knowledge/test-quality.md +664 -0
  235. package/src/modules/bmm/testarch/knowledge/timing-debugging.md +372 -0
  236. package/src/modules/bmm/testarch/knowledge/visual-debugging.md +524 -0
  237. package/src/modules/bmm/testarch/tea-index.csv +22 -0
  238. package/src/modules/bmm/workflows/1-analysis/brainstorm-project/instructions.md +82 -8
  239. package/src/modules/bmm/workflows/1-analysis/brainstorm-project/project-context.md +4 -4
  240. package/src/modules/bmm/workflows/1-analysis/brainstorm-project/workflow.yaml +23 -5
  241. package/src/modules/bmm/workflows/1-analysis/domain-research/instructions.md +425 -0
  242. package/src/modules/bmm/workflows/1-analysis/domain-research/template.md +180 -0
  243. package/src/modules/bmm/workflows/1-analysis/domain-research/workflow.yaml +56 -0
  244. package/src/modules/bmm/workflows/1-analysis/product-brief/checklist.md +2 -2
  245. package/src/modules/bmm/workflows/1-analysis/product-brief/instructions.md +418 -247
  246. package/src/modules/bmm/workflows/1-analysis/product-brief/template.md +93 -77
  247. package/src/modules/bmm/workflows/1-analysis/product-brief/workflow.yaml +42 -14
  248. package/src/modules/bmm/workflows/1-analysis/research/checklist-deep-prompt.md +144 -0
  249. package/src/modules/bmm/workflows/1-analysis/research/checklist-technical.md +249 -0
  250. package/src/modules/bmm/workflows/1-analysis/research/checklist.md +156 -59
  251. package/src/modules/bmm/workflows/1-analysis/research/instructions-deep-prompt.md +115 -47
  252. package/src/modules/bmm/workflows/1-analysis/research/instructions-market.md +236 -114
  253. package/src/modules/bmm/workflows/1-analysis/research/instructions-router.md +109 -66
  254. package/src/modules/bmm/workflows/1-analysis/research/instructions-technical.md +147 -55
  255. package/src/modules/bmm/workflows/1-analysis/research/template-deep-prompt.md +1 -1
  256. package/src/modules/bmm/workflows/1-analysis/research/template-market.md +38 -2
  257. package/src/modules/bmm/workflows/1-analysis/research/template-technical.md +36 -1
  258. package/src/modules/bmm/workflows/1-analysis/research/workflow.yaml +36 -123
  259. package/src/modules/bmm/workflows/2-plan-workflows/create-epics-and-stories/epics-template.md +80 -0
  260. package/src/modules/bmm/workflows/2-plan-workflows/create-epics-and-stories/instructions.md +616 -0
  261. package/src/modules/bmm/workflows/2-plan-workflows/create-epics-and-stories/workflow.yaml +63 -0
  262. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/checklist.md +310 -0
  263. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/instructions.md +1308 -0
  264. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/ux-design-template.md +145 -0
  265. package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml +93 -0
  266. package/src/modules/bmm/workflows/2-plan-workflows/prd/checklist.md +346 -0
  267. package/src/modules/bmm/workflows/2-plan-workflows/prd/domain-complexity.csv +13 -0
  268. package/src/modules/bmm/workflows/2-plan-workflows/prd/instructions.md +703 -0
  269. package/src/modules/bmm/workflows/2-plan-workflows/prd/prd-template.md +204 -0
  270. package/src/modules/bmm/workflows/2-plan-workflows/prd/project-types.csv +11 -0
  271. package/src/modules/bmm/workflows/2-plan-workflows/prd/workflow.yaml +78 -0
  272. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/checklist.md +217 -0
  273. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/epics-template.md +74 -0
  274. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/instructions-generate-stories.md +436 -0
  275. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/instructions.md +980 -0
  276. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/tech-spec-template.md +181 -0
  277. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/user-story-template.md +90 -0
  278. package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/workflow.yaml +60 -0
  279. package/src/modules/bmm/workflows/3-solutioning/architecture/architecture-patterns.yaml +321 -0
  280. package/src/modules/bmm/workflows/3-solutioning/architecture/architecture-template.md +103 -0
  281. package/src/modules/bmm/workflows/3-solutioning/architecture/checklist.md +240 -0
  282. package/src/modules/bmm/workflows/3-solutioning/architecture/decision-catalog.yaml +222 -0
  283. package/src/modules/bmm/workflows/3-solutioning/architecture/instructions.md +768 -0
  284. package/src/modules/bmm/workflows/3-solutioning/architecture/pattern-categories.csv +13 -0
  285. package/src/modules/bmm/workflows/3-solutioning/architecture/workflow.yaml +100 -0
  286. package/src/modules/bmm/workflows/3-solutioning/implementation-readiness/checklist.md +169 -0
  287. package/src/modules/bmm/workflows/3-solutioning/implementation-readiness/instructions.md +332 -0
  288. package/src/modules/bmm/workflows/3-solutioning/implementation-readiness/template.md +146 -0
  289. package/src/modules/bmm/workflows/3-solutioning/implementation-readiness/workflow.yaml +64 -0
  290. package/src/modules/bmm/workflows/4-implementation/code-review/backlog_template.md +12 -0
  291. package/src/modules/bmm/workflows/4-implementation/code-review/checklist.md +22 -0
  292. package/src/modules/bmm/workflows/4-implementation/code-review/instructions.md +398 -0
  293. package/src/modules/bmm/workflows/4-implementation/code-review/workflow.yaml +61 -0
  294. package/src/modules/bmm/workflows/4-implementation/correct-course/checklist.md +6 -6
  295. package/src/modules/bmm/workflows/4-implementation/correct-course/instructions.md +70 -54
  296. package/src/modules/bmm/workflows/4-implementation/correct-course/workflow.yaml +44 -21
  297. package/src/modules/bmm/workflows/4-implementation/create-story/checklist.md +240 -39
  298. package/src/modules/bmm/workflows/4-implementation/create-story/instructions.md +203 -28
  299. package/src/modules/bmm/workflows/4-implementation/create-story/template.md +2 -8
  300. package/src/modules/bmm/workflows/4-implementation/create-story/workflow.yaml +43 -42
  301. package/src/modules/bmm/workflows/4-implementation/dev-story/checklist.md +1 -1
  302. package/src/modules/bmm/workflows/4-implementation/dev-story/instructions.md +220 -40
  303. package/src/modules/bmm/workflows/4-implementation/dev-story/workflow.yaml +43 -38
  304. package/src/modules/bmm/workflows/4-implementation/epic-tech-context/checklist.md +17 -0
  305. package/src/modules/bmm/workflows/4-implementation/epic-tech-context/instructions.md +164 -0
  306. package/src/modules/bmm/workflows/4-implementation/epic-tech-context/template.md +76 -0
  307. package/src/modules/bmm/workflows/4-implementation/epic-tech-context/workflow.yaml +58 -0
  308. package/src/modules/bmm/workflows/4-implementation/retrospective/instructions.md +1280 -228
  309. package/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml +41 -25
  310. package/src/modules/bmm/workflows/4-implementation/sprint-planning/checklist.md +33 -0
  311. package/src/modules/bmm/workflows/4-implementation/sprint-planning/instructions.md +234 -0
  312. package/src/modules/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +55 -0
  313. package/src/modules/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +51 -0
  314. package/src/modules/bmm/workflows/4-implementation/story-context/checklist.md +1 -1
  315. package/src/modules/bmm/workflows/4-implementation/story-context/context-template.xml +1 -1
  316. package/src/modules/bmm/workflows/4-implementation/story-context/instructions.md +155 -22
  317. package/src/modules/bmm/workflows/4-implementation/story-context/workflow.yaml +43 -36
  318. package/src/modules/bmm/workflows/4-implementation/story-done/instructions.md +111 -0
  319. package/src/modules/bmm/workflows/4-implementation/story-done/workflow.yaml +28 -0
  320. package/src/modules/bmm/workflows/4-implementation/story-ready/instructions.md +117 -0
  321. package/src/modules/bmm/workflows/4-implementation/story-ready/workflow.yaml +25 -0
  322. package/src/modules/bmm/workflows/document-project/checklist.md +245 -0
  323. package/src/modules/bmm/workflows/document-project/documentation-requirements.csv +12 -0
  324. package/src/modules/bmm/workflows/document-project/instructions.md +222 -0
  325. package/src/modules/bmm/workflows/document-project/templates/deep-dive-template.md +345 -0
  326. package/src/modules/bmm/workflows/document-project/templates/index-template.md +169 -0
  327. package/src/modules/bmm/workflows/document-project/templates/project-overview-template.md +103 -0
  328. package/src/modules/bmm/workflows/document-project/templates/project-scan-report-schema.json +160 -0
  329. package/src/modules/bmm/workflows/document-project/templates/source-tree-template.md +135 -0
  330. package/src/modules/bmm/workflows/document-project/workflow.yaml +31 -0
  331. package/src/modules/bmm/workflows/document-project/workflows/deep-dive-instructions.md +298 -0
  332. package/src/modules/bmm/workflows/document-project/workflows/deep-dive.yaml +31 -0
  333. package/src/modules/bmm/workflows/document-project/workflows/full-scan-instructions.md +1106 -0
  334. package/src/modules/bmm/workflows/document-project/workflows/full-scan.yaml +31 -0
  335. package/src/modules/bmm/workflows/frame-expert/_shared/excalidraw-helpers.md +127 -0
  336. package/src/modules/bmm/workflows/frame-expert/_shared/excalidraw-library.json +90 -0
  337. package/src/modules/bmm/workflows/frame-expert/_shared/excalidraw-templates.yaml +127 -0
  338. package/src/modules/bmm/workflows/frame-expert/_shared/validate-json-instructions.md +79 -0
  339. package/src/modules/bmm/workflows/frame-expert/create-dataflow/checklist.md +39 -0
  340. package/src/modules/bmm/workflows/frame-expert/create-dataflow/instructions.md +131 -0
  341. package/src/modules/bmm/workflows/frame-expert/create-dataflow/workflow.yaml +24 -0
  342. package/src/modules/bmm/workflows/frame-expert/create-diagram/checklist.md +43 -0
  343. package/src/modules/bmm/workflows/frame-expert/create-diagram/instructions.md +142 -0
  344. package/src/modules/bmm/workflows/frame-expert/create-diagram/workflow.yaml +25 -0
  345. package/src/modules/bmm/workflows/frame-expert/create-flowchart/checklist.md +49 -0
  346. package/src/modules/bmm/workflows/frame-expert/create-flowchart/instructions.md +242 -0
  347. package/src/modules/bmm/workflows/frame-expert/create-flowchart/workflow.yaml +28 -0
  348. package/src/modules/bmm/workflows/frame-expert/create-wireframe/checklist.md +38 -0
  349. package/src/modules/bmm/workflows/frame-expert/create-wireframe/instructions.md +133 -0
  350. package/src/modules/bmm/workflows/frame-expert/create-wireframe/workflow.yaml +24 -0
  351. package/src/modules/bmm/workflows/techdoc/documentation-standards.md +262 -0
  352. package/src/modules/bmm/workflows/testarch/atdd/atdd-checklist-template.md +363 -0
  353. package/src/modules/bmm/workflows/testarch/atdd/checklist.md +373 -0
  354. package/src/modules/bmm/workflows/testarch/atdd/instructions.md +785 -0
  355. package/src/modules/bmm/workflows/testarch/atdd/workflow.yaml +47 -0
  356. package/src/modules/bmm/workflows/testarch/automate/checklist.md +580 -0
  357. package/src/modules/bmm/workflows/testarch/automate/instructions.md +1303 -0
  358. package/src/modules/bmm/workflows/testarch/automate/workflow.yaml +54 -0
  359. package/src/modules/bmm/workflows/testarch/ci/checklist.md +246 -0
  360. package/src/modules/bmm/workflows/testarch/ci/github-actions-template.yaml +165 -0
  361. package/src/modules/bmm/workflows/testarch/ci/gitlab-ci-template.yaml +128 -0
  362. package/src/modules/bmm/workflows/testarch/ci/instructions.md +517 -0
  363. package/src/modules/bmm/workflows/testarch/ci/workflow.yaml +47 -0
  364. package/src/modules/bmm/workflows/testarch/framework/checklist.md +321 -0
  365. package/src/modules/bmm/workflows/testarch/framework/instructions.md +455 -0
  366. package/src/modules/bmm/workflows/testarch/framework/workflow.yaml +49 -0
  367. package/src/modules/bmm/workflows/testarch/nfr-assess/checklist.md +405 -0
  368. package/src/modules/bmm/workflows/testarch/nfr-assess/instructions.md +722 -0
  369. package/src/modules/bmm/workflows/testarch/nfr-assess/nfr-report-template.md +443 -0
  370. package/src/modules/bmm/workflows/testarch/nfr-assess/workflow.yaml +49 -0
  371. package/src/modules/bmm/workflows/testarch/test-design/checklist.md +234 -0
  372. package/src/modules/bmm/workflows/testarch/test-design/instructions.md +782 -0
  373. package/src/modules/bmm/workflows/testarch/test-design/test-design-template.md +285 -0
  374. package/src/modules/bmm/workflows/testarch/test-design/workflow.yaml +50 -0
  375. package/src/modules/bmm/workflows/testarch/test-review/checklist.md +470 -0
  376. package/src/modules/bmm/workflows/testarch/test-review/instructions.md +608 -0
  377. package/src/modules/bmm/workflows/testarch/test-review/test-review-template.md +388 -0
  378. package/src/modules/bmm/workflows/testarch/test-review/workflow.yaml +48 -0
  379. package/src/modules/bmm/workflows/testarch/trace/checklist.md +654 -0
  380. package/src/modules/bmm/workflows/testarch/trace/instructions.md +1045 -0
  381. package/src/modules/bmm/workflows/testarch/trace/trace-template.md +673 -0
  382. package/src/modules/bmm/workflows/testarch/trace/workflow.yaml +57 -0
  383. package/src/modules/bmm/workflows/workflow-status/init/instructions.md +334 -0
  384. package/src/modules/bmm/workflows/workflow-status/init/workflow.yaml +29 -0
  385. package/src/modules/bmm/workflows/workflow-status/instructions.md +388 -0
  386. package/src/modules/bmm/workflows/workflow-status/paths/enterprise-brownfield.yaml +138 -0
  387. package/src/modules/bmm/workflows/workflow-status/paths/enterprise-greenfield.yaml +126 -0
  388. package/src/modules/bmm/workflows/workflow-status/paths/game-design.yaml +52 -0
  389. package/src/modules/bmm/workflows/workflow-status/paths/method-brownfield.yaml +122 -0
  390. package/src/modules/bmm/workflows/workflow-status/paths/method-greenfield.yaml +113 -0
  391. package/src/modules/bmm/workflows/workflow-status/paths/quick-flow-brownfield.yaml +58 -0
  392. package/src/modules/bmm/workflows/workflow-status/paths/quick-flow-greenfield.yaml +47 -0
  393. package/src/modules/bmm/workflows/workflow-status/project-levels.yaml +59 -0
  394. package/src/modules/bmm/workflows/workflow-status/workflow-status-template.yaml +24 -0
  395. package/src/modules/bmm/workflows/workflow-status/workflow.yaml +30 -0
  396. package/src/modules/cis/README.md +153 -0
  397. package/src/modules/cis/_module-installer/{install-menu-config.yaml → install-config.yaml} +6 -4
  398. package/src/modules/cis/_module-installer/installer.js +1 -1
  399. package/src/modules/cis/agents/README.md +1 -1
  400. package/src/modules/cis/agents/brainstorming-coach.agent.yaml +28 -0
  401. package/src/modules/cis/agents/creative-problem-solver.agent.yaml +28 -0
  402. package/src/modules/cis/agents/design-thinking-coach.agent.yaml +28 -0
  403. package/src/modules/cis/agents/innovation-strategist.agent.yaml +28 -0
  404. package/src/modules/cis/agents/storyteller.agent.yaml +28 -0
  405. package/src/modules/cis/teams/creative-squad.yaml +1 -0
  406. package/src/modules/cis/teams/default-party.csv +11 -0
  407. package/src/modules/cis/workflows/README.md +102 -30
  408. package/src/modules/cis/workflows/design-thinking/design-methods.csv +1 -1
  409. package/src/modules/cis/workflows/design-thinking/instructions.md +4 -2
  410. package/src/modules/cis/workflows/design-thinking/workflow.yaml +16 -7
  411. package/src/modules/cis/workflows/innovation-strategy/innovation-frameworks.csv +2 -2
  412. package/src/modules/cis/workflows/innovation-strategy/instructions.md +7 -5
  413. package/src/modules/cis/workflows/innovation-strategy/template.md +6 -6
  414. package/src/modules/cis/workflows/innovation-strategy/workflow.yaml +16 -7
  415. package/src/modules/cis/workflows/problem-solving/instructions.md +4 -2
  416. package/src/modules/cis/workflows/problem-solving/solving-methods.csv +6 -6
  417. package/src/modules/cis/workflows/problem-solving/template.md +3 -3
  418. package/src/modules/cis/workflows/problem-solving/workflow.yaml +16 -7
  419. package/src/modules/cis/workflows/storytelling/instructions.md +48 -30
  420. package/src/modules/cis/workflows/storytelling/template.md +2 -2
  421. package/src/modules/cis/workflows/storytelling/workflow.yaml +16 -7
  422. package/src/utility/models/action-command-header.md +0 -0
  423. package/src/utility/models/agent-activation-ide.xml +4 -4
  424. package/src/utility/models/agent-activation-web.xml +60 -0
  425. package/src/utility/models/agent-command-header.md +1 -0
  426. package/src/utility/models/agent-in-team-activation.xml +3 -0
  427. package/src/utility/models/fragments/activation-rules.xml +8 -0
  428. package/src/utility/models/fragments/activation-steps.xml +16 -0
  429. package/src/utility/models/fragments/handler-action.xml +4 -0
  430. package/src/utility/models/fragments/handler-data.xml +5 -0
  431. package/src/utility/models/fragments/handler-exec.xml +5 -0
  432. package/src/utility/models/fragments/handler-tmpl.xml +5 -0
  433. package/src/utility/models/fragments/handler-validate-workflow.xml +7 -0
  434. package/src/utility/models/fragments/handler-workflow.xml +9 -0
  435. package/src/utility/models/fragments/menu-handlers.xml +6 -0
  436. package/src/utility/models/fragments/web-bundle-activation-steps.xml +32 -0
  437. package/src/utility/templates/agent.customize.template.yaml +42 -0
  438. package/test/README.md +295 -0
  439. package/test/fixtures/agent-schema/invalid/critical-actions/actions-as-string.agent.yaml +26 -0
  440. package/test/fixtures/agent-schema/invalid/critical-actions/empty-string-in-actions.agent.yaml +29 -0
  441. package/test/fixtures/agent-schema/invalid/menu/empty-menu.agent.yaml +21 -0
  442. package/test/fixtures/agent-schema/invalid/menu/missing-menu.agent.yaml +19 -0
  443. package/test/fixtures/agent-schema/invalid/menu-commands/empty-command-target.agent.yaml +24 -0
  444. package/test/fixtures/agent-schema/invalid/menu-commands/no-command-target.agent.yaml +23 -0
  445. package/test/fixtures/agent-schema/invalid/menu-triggers/camel-case.agent.yaml +24 -0
  446. package/test/fixtures/agent-schema/invalid/menu-triggers/duplicate-triggers.agent.yaml +30 -0
  447. package/test/fixtures/agent-schema/invalid/menu-triggers/empty-trigger.agent.yaml +24 -0
  448. package/test/fixtures/agent-schema/invalid/menu-triggers/leading-asterisk.agent.yaml +24 -0
  449. package/test/fixtures/agent-schema/invalid/menu-triggers/snake-case.agent.yaml +24 -0
  450. package/test/fixtures/agent-schema/invalid/menu-triggers/trigger-with-spaces.agent.yaml +24 -0
  451. package/test/fixtures/agent-schema/invalid/metadata/core-agent-with-module.agent.yaml +26 -0
  452. package/test/fixtures/agent-schema/invalid/metadata/empty-module-string.agent.yaml +26 -0
  453. package/test/fixtures/agent-schema/invalid/metadata/empty-name.agent.yaml +24 -0
  454. package/test/fixtures/agent-schema/invalid/metadata/extra-metadata-fields.agent.yaml +26 -0
  455. package/test/fixtures/agent-schema/invalid/metadata/missing-id.agent.yaml +23 -0
  456. package/test/fixtures/agent-schema/invalid/metadata/module-agent-missing-module.agent.yaml +25 -0
  457. package/test/fixtures/agent-schema/invalid/metadata/wrong-module-value.agent.yaml +26 -0
  458. package/test/fixtures/agent-schema/invalid/persona/empty-principles-array.agent.yaml +23 -0
  459. package/test/fixtures/agent-schema/invalid/persona/empty-string-in-principles.agent.yaml +26 -0
  460. package/test/fixtures/agent-schema/invalid/persona/extra-persona-fields.agent.yaml +26 -0
  461. package/test/fixtures/agent-schema/invalid/persona/missing-role.agent.yaml +23 -0
  462. package/test/fixtures/agent-schema/invalid/prompts/empty-content.agent.yaml +28 -0
  463. package/test/fixtures/agent-schema/invalid/prompts/extra-prompt-fields.agent.yaml +30 -0
  464. package/test/fixtures/agent-schema/invalid/prompts/missing-content.agent.yaml +27 -0
  465. package/test/fixtures/agent-schema/invalid/prompts/missing-id.agent.yaml +27 -0
  466. package/test/fixtures/agent-schema/invalid/top-level/empty-file.agent.yaml +5 -0
  467. package/test/fixtures/agent-schema/invalid/top-level/extra-top-level-keys.agent.yaml +27 -0
  468. package/test/fixtures/agent-schema/invalid/top-level/missing-agent-key.agent.yaml +11 -0
  469. package/test/fixtures/agent-schema/invalid/yaml-errors/invalid-indentation.agent.yaml +19 -0
  470. package/test/fixtures/agent-schema/invalid/yaml-errors/malformed-yaml.agent.yaml +18 -0
  471. package/test/fixtures/agent-schema/valid/critical-actions/empty-critical-actions.agent.yaml +23 -0
  472. package/test/fixtures/agent-schema/valid/critical-actions/no-critical-actions.agent.yaml +21 -0
  473. package/test/fixtures/agent-schema/valid/critical-actions/valid-critical-actions.agent.yaml +26 -0
  474. package/test/fixtures/agent-schema/valid/menu/multiple-menu-items.agent.yaml +30 -0
  475. package/test/fixtures/agent-schema/valid/menu/single-menu-item.agent.yaml +21 -0
  476. package/test/fixtures/agent-schema/valid/menu-commands/all-command-types.agent.yaml +39 -0
  477. package/test/fixtures/agent-schema/valid/menu-commands/multiple-commands.agent.yaml +23 -0
  478. package/test/fixtures/agent-schema/valid/menu-triggers/kebab-case-triggers.agent.yaml +33 -0
  479. package/test/fixtures/agent-schema/valid/metadata/empty-module-name-in-path.agent.yaml +23 -0
  480. package/test/fixtures/agent-schema/valid/metadata/malformed-path-treated-as-core.agent.yaml +23 -0
  481. package/test/fixtures/agent-schema/valid/metadata/module-agent-correct.agent.yaml +23 -0
  482. package/test/fixtures/agent-schema/valid/persona/complete-persona.agent.yaml +23 -0
  483. package/test/fixtures/agent-schema/valid/prompts/empty-prompts.agent.yaml +23 -0
  484. package/test/fixtures/agent-schema/valid/prompts/no-prompts.agent.yaml +21 -0
  485. package/test/fixtures/agent-schema/valid/prompts/valid-prompts-minimal.agent.yaml +27 -0
  486. package/test/fixtures/agent-schema/valid/prompts/valid-prompts-with-description.agent.yaml +29 -0
  487. package/test/fixtures/agent-schema/valid/top-level/minimal-core-agent.agent.yaml +23 -0
  488. package/test/test-agent-schema.js +387 -0
  489. package/test/test-cli-integration.sh +159 -0
  490. package/test/test-installation-components.js +214 -0
  491. package/test/unit-test-schema.js +133 -0
  492. package/tools/bmad-npx-wrapper.js +38 -0
  493. package/tools/cli/README.md +608 -0
  494. package/tools/cli/bmad-cli.js +0 -2
  495. package/tools/cli/bundlers/bundle-web.js +24 -2
  496. package/tools/cli/bundlers/test-bundler.js +1 -1
  497. package/tools/cli/bundlers/web-bundler.js +944 -49
  498. package/tools/cli/commands/build.js +458 -0
  499. package/tools/cli/commands/install.js +46 -8
  500. package/tools/cli/installers/lib/core/config-collector.js +490 -43
  501. package/tools/cli/installers/lib/core/dependency-resolver.js +5 -1
  502. package/tools/cli/installers/lib/core/detector.js +134 -13
  503. package/tools/cli/installers/lib/core/ide-config-manager.js +154 -0
  504. package/tools/cli/installers/lib/core/installer.js +1365 -167
  505. package/tools/cli/installers/lib/core/manifest-generator.js +388 -81
  506. package/tools/cli/installers/lib/core/manifest.js +100 -44
  507. package/tools/cli/installers/lib/ide/_base-ide.js +368 -23
  508. package/tools/cli/installers/lib/ide/auggie.js +100 -192
  509. package/tools/cli/installers/lib/ide/claude-code.js +167 -321
  510. package/tools/cli/installers/lib/ide/cline.js +146 -227
  511. package/tools/cli/installers/lib/ide/codex.js +138 -202
  512. package/tools/cli/installers/lib/ide/crush.js +108 -72
  513. package/tools/cli/installers/lib/ide/cursor.js +148 -20
  514. package/tools/cli/installers/lib/ide/gemini.js +109 -63
  515. package/tools/cli/installers/lib/ide/github-copilot.js +60 -47
  516. package/tools/cli/installers/lib/ide/iflow.js +13 -30
  517. package/tools/cli/installers/lib/ide/kilo.js +20 -16
  518. package/tools/cli/installers/lib/ide/manager.js +41 -35
  519. package/tools/cli/installers/lib/ide/opencode.js +212 -0
  520. package/tools/cli/installers/lib/ide/qwen.js +198 -68
  521. package/tools/cli/installers/lib/ide/roo.js +27 -62
  522. package/tools/cli/installers/lib/ide/shared/agent-command-generator.js +90 -0
  523. package/tools/cli/installers/lib/ide/shared/bmad-artifacts.js +143 -0
  524. package/tools/cli/installers/lib/ide/shared/module-injections.js +133 -0
  525. package/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +119 -0
  526. package/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +237 -0
  527. package/tools/cli/installers/lib/ide/templates/agent-command-template.md +14 -0
  528. package/tools/cli/installers/lib/ide/templates/gemini-agent-command.toml +14 -0
  529. package/tools/cli/installers/lib/ide/templates/gemini-task-command.toml +12 -0
  530. package/tools/cli/installers/lib/ide/{workflow-command-template.md → templates/workflow-command-template.md} +7 -5
  531. package/tools/cli/installers/lib/ide/trae.js +138 -54
  532. package/tools/cli/installers/lib/ide/windsurf.js +104 -42
  533. package/tools/cli/installers/lib/modules/manager.js +332 -10
  534. package/tools/cli/lib/activation-builder.js +168 -0
  535. package/tools/cli/lib/agent-analyzer.js +81 -0
  536. package/tools/cli/lib/agent-party-generator.js +3 -3
  537. package/tools/cli/lib/cli-utils.js +52 -50
  538. package/tools/cli/lib/config.js +3 -1
  539. package/tools/cli/lib/ui.js +106 -14
  540. package/tools/cli/lib/xml-handler.js +47 -1
  541. package/tools/cli/lib/yaml-format.js +2 -1
  542. package/tools/cli/lib/yaml-xml-builder.js +507 -0
  543. package/tools/cli/regenerate-manifests.js +1 -1
  544. package/tools/cli/test-yaml-builder.js +43 -0
  545. package/tools/format-workflow-md.js +263 -0
  546. package/tools/platform-codes.yaml +6 -0
  547. package/tools/schema/agent.js +240 -0
  548. package/tools/validate-agent-schema.js +110 -0
  549. package/v6-open-items.md +17 -0
  550. package/.github/workflows/format-check.yaml +0 -43
  551. package/docs/codebase-flattener.md +0 -19
  552. package/readme.md +0 -216
  553. package/src/core/_module-installer/install-menu-config.yaml +0 -24
  554. package/src/core/agents/bmad-master.md +0 -27
  555. package/src/core/agents/bmad-web-orchestrator.md +0 -71
  556. package/src/core/tasks/shard-doc.md +0 -57
  557. package/src/core/tasks/workflow.md +0 -141
  558. package/src/core/workflows/bmad-init/instructions.md +0 -79
  559. package/src/core/workflows/bmad-init/workflow.yaml +0 -24
  560. package/src/modules/bmb/_module-installer/install-menu-config.yaml +0 -16
  561. package/src/modules/bmb/agents/bmad-builder.md +0 -30
  562. package/src/modules/bmb/workflows/create-module/installer-templates/install-module-config.yaml +0 -132
  563. package/src/modules/bmm/_module-installer/install-menu-config.yaml +0 -49
  564. package/src/modules/bmm/agents/analyst.md +0 -26
  565. package/src/modules/bmm/agents/architect.md +0 -29
  566. package/src/modules/bmm/agents/dev.md +0 -61
  567. package/src/modules/bmm/agents/game-architect.md +0 -26
  568. package/src/modules/bmm/agents/game-designer.md +0 -27
  569. package/src/modules/bmm/agents/game-dev.md +0 -28
  570. package/src/modules/bmm/agents/pm.md +0 -26
  571. package/src/modules/bmm/agents/po.md +0 -25
  572. package/src/modules/bmm/agents/sm.md +0 -29
  573. package/src/modules/bmm/agents/tea.md +0 -32
  574. package/src/modules/bmm/agents/ux-expert.md +0 -24
  575. package/src/modules/bmm/sub-modules/claude-code/config.yaml +0 -5
  576. package/src/modules/bmm/sub-modules/claude-code/injections.yaml +0 -242
  577. package/src/modules/bmm/sub-modules/claude-code/readme.md +0 -87
  578. package/src/modules/bmm/sub-modules/claude-code/sub-agents/api-documenter.md +0 -85
  579. package/src/modules/bmm/sub-modules/claude-code/sub-agents/codebase-analyzer.md +0 -64
  580. package/src/modules/bmm/sub-modules/claude-code/sub-agents/data-analyst.md +0 -84
  581. package/src/modules/bmm/sub-modules/claude-code/sub-agents/dependency-mapper.md +0 -67
  582. package/src/modules/bmm/sub-modules/claude-code/sub-agents/document-reviewer.md +0 -85
  583. package/src/modules/bmm/sub-modules/claude-code/sub-agents/epic-optimizer.md +0 -66
  584. package/src/modules/bmm/sub-modules/claude-code/sub-agents/market-researcher.md +0 -34
  585. package/src/modules/bmm/sub-modules/claude-code/sub-agents/pattern-detector.md +0 -67
  586. package/src/modules/bmm/sub-modules/claude-code/sub-agents/requirements-analyst.md +0 -61
  587. package/src/modules/bmm/sub-modules/claude-code/sub-agents/tech-debt-auditor.md +0 -89
  588. package/src/modules/bmm/sub-modules/claude-code/sub-agents/technical-decisions-curator.md +0 -146
  589. package/src/modules/bmm/sub-modules/claude-code/sub-agents/technical-evaluator.md +0 -51
  590. package/src/modules/bmm/sub-modules/claude-code/sub-agents/test-coverage-analyzer.md +0 -91
  591. package/src/modules/bmm/sub-modules/claude-code/sub-agents/trend-spotter.md +0 -99
  592. package/src/modules/bmm/sub-modules/claude-code/sub-agents/user-journey-mapper.md +0 -101
  593. package/src/modules/bmm/sub-modules/claude-code/sub-agents/user-researcher.md +0 -56
  594. package/src/modules/bmm/tasks/daily-standup.md +0 -91
  595. package/src/modules/bmm/tasks/retrospective.md +0 -110
  596. package/src/modules/bmm/teams/team-all.yaml +0 -7
  597. package/src/modules/bmm/teams/team-dev.yaml +0 -14
  598. package/src/modules/bmm/teams/team-gamedev.yaml +0 -9
  599. package/src/modules/bmm/testarch/atdd.md +0 -40
  600. package/src/modules/bmm/testarch/automate.md +0 -38
  601. package/src/modules/bmm/testarch/ci.md +0 -39
  602. package/src/modules/bmm/testarch/framework.md +0 -41
  603. package/src/modules/bmm/testarch/nfr-assess.md +0 -38
  604. package/src/modules/bmm/testarch/risk-profile.md +0 -38
  605. package/src/modules/bmm/testarch/tea-commands.csv +0 -11
  606. package/src/modules/bmm/testarch/tea-gate.md +0 -38
  607. package/src/modules/bmm/testarch/tea-knowledge.md +0 -275
  608. package/src/modules/bmm/testarch/test-design.md +0 -39
  609. package/src/modules/bmm/testarch/test-levels-framework.md +0 -148
  610. package/src/modules/bmm/testarch/test-priorities-matrix.md +0 -174
  611. package/src/modules/bmm/testarch/trace-requirements.md +0 -38
  612. package/src/modules/bmm/workflows/1-analysis/brainstorm-game/instructions.md +0 -47
  613. package/src/modules/bmm/workflows/1-analysis/brainstorm-game/workflow.yaml +0 -22
  614. package/src/modules/bmm/workflows/1-analysis/game-brief/README.md +0 -221
  615. package/src/modules/bmm/workflows/1-analysis/game-brief/instructions.md +0 -517
  616. package/src/modules/bmm/workflows/1-analysis/game-brief/workflow.yaml +0 -34
  617. package/src/modules/bmm/workflows/1-analysis/product-brief/README.md +0 -180
  618. package/src/modules/bmm/workflows/1-analysis/research/README.md +0 -454
  619. package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-competitor-analyzer.md +0 -259
  620. package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-data-analyst.md +0 -190
  621. package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-market-researcher.md +0 -337
  622. package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-trend-spotter.md +0 -107
  623. package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-user-researcher.md +0 -329
  624. package/src/modules/bmm/workflows/2-plan/README.md +0 -203
  625. package/src/modules/bmm/workflows/2-plan/checklist.md +0 -369
  626. package/src/modules/bmm/workflows/2-plan/gdd/README.md +0 -222
  627. package/src/modules/bmm/workflows/2-plan/gdd/instructions-gdd.md +0 -480
  628. package/src/modules/bmm/workflows/2-plan/instructions-router.md +0 -222
  629. package/src/modules/bmm/workflows/2-plan/prd/analysis-template.md +0 -53
  630. package/src/modules/bmm/workflows/2-plan/prd/epics-template.md +0 -18
  631. package/src/modules/bmm/workflows/2-plan/prd/instructions-lg.md +0 -267
  632. package/src/modules/bmm/workflows/2-plan/prd/instructions-med.md +0 -251
  633. package/src/modules/bmm/workflows/2-plan/prd/prd-template.md +0 -73
  634. package/src/modules/bmm/workflows/2-plan/tech-spec/instructions-sm.md +0 -137
  635. package/src/modules/bmm/workflows/2-plan/tech-spec/tech-spec-template.md +0 -59
  636. package/src/modules/bmm/workflows/2-plan/ux/instructions-ux.md +0 -360
  637. package/src/modules/bmm/workflows/2-plan/ux/ux-spec-template.md +0 -162
  638. package/src/modules/bmm/workflows/2-plan/workflow.yaml +0 -60
  639. package/src/modules/bmm/workflows/3-solutioning/ADR-template.md +0 -74
  640. package/src/modules/bmm/workflows/3-solutioning/README.md +0 -565
  641. package/src/modules/bmm/workflows/3-solutioning/checklist.md +0 -170
  642. package/src/modules/bmm/workflows/3-solutioning/instructions.md +0 -661
  643. package/src/modules/bmm/workflows/3-solutioning/project-types/backend-questions.md +0 -490
  644. package/src/modules/bmm/workflows/3-solutioning/project-types/cli-questions.md +0 -337
  645. package/src/modules/bmm/workflows/3-solutioning/project-types/data-questions.md +0 -472
  646. package/src/modules/bmm/workflows/3-solutioning/project-types/desktop-questions.md +0 -299
  647. package/src/modules/bmm/workflows/3-solutioning/project-types/embedded-questions.md +0 -118
  648. package/src/modules/bmm/workflows/3-solutioning/project-types/extension-questions.md +0 -374
  649. package/src/modules/bmm/workflows/3-solutioning/project-types/game-questions.md +0 -133
  650. package/src/modules/bmm/workflows/3-solutioning/project-types/infra-questions.md +0 -484
  651. package/src/modules/bmm/workflows/3-solutioning/project-types/library-questions.md +0 -146
  652. package/src/modules/bmm/workflows/3-solutioning/project-types/mobile-questions.md +0 -110
  653. package/src/modules/bmm/workflows/3-solutioning/project-types/project-types.csv +0 -12
  654. package/src/modules/bmm/workflows/3-solutioning/project-types/web-questions.md +0 -136
  655. package/src/modules/bmm/workflows/3-solutioning/tech-spec/README.md +0 -195
  656. package/src/modules/bmm/workflows/3-solutioning/tech-spec/instructions.md +0 -73
  657. package/src/modules/bmm/workflows/3-solutioning/tech-spec/workflow.yaml +0 -51
  658. package/src/modules/bmm/workflows/3-solutioning/templates/backend-service-architecture.md +0 -66
  659. package/src/modules/bmm/workflows/3-solutioning/templates/cli-tool-architecture.md +0 -66
  660. package/src/modules/bmm/workflows/3-solutioning/templates/data-pipeline-architecture.md +0 -66
  661. package/src/modules/bmm/workflows/3-solutioning/templates/desktop-app-architecture.md +0 -66
  662. package/src/modules/bmm/workflows/3-solutioning/templates/embedded-firmware-architecture.md +0 -66
  663. package/src/modules/bmm/workflows/3-solutioning/templates/game-engine-architecture.md +0 -244
  664. package/src/modules/bmm/workflows/3-solutioning/templates/game-engine-godot-guide.md +0 -428
  665. package/src/modules/bmm/workflows/3-solutioning/templates/game-engine-unity-guide.md +0 -333
  666. package/src/modules/bmm/workflows/3-solutioning/templates/game-engine-web-guide.md +0 -528
  667. package/src/modules/bmm/workflows/3-solutioning/templates/infrastructure-architecture.md +0 -66
  668. package/src/modules/bmm/workflows/3-solutioning/templates/library-package-architecture.md +0 -66
  669. package/src/modules/bmm/workflows/3-solutioning/templates/mobile-app-architecture.md +0 -66
  670. package/src/modules/bmm/workflows/3-solutioning/templates/registry.csv +0 -172
  671. package/src/modules/bmm/workflows/3-solutioning/templates/web-api-architecture.md +0 -66
  672. package/src/modules/bmm/workflows/3-solutioning/templates/web-fullstack-architecture.md +0 -277
  673. package/src/modules/bmm/workflows/3-solutioning/workflow.yaml +0 -65
  674. package/src/modules/bmm/workflows/4-implementation/create-story/README.md +0 -42
  675. package/src/modules/bmm/workflows/4-implementation/dev-story/README.md +0 -84
  676. package/src/modules/bmm/workflows/4-implementation/review-story/README.md +0 -72
  677. package/src/modules/bmm/workflows/4-implementation/review-story/instructions.md +0 -176
  678. package/src/modules/bmm/workflows/4-implementation/review-story/workflow.yaml +0 -99
  679. package/src/modules/bmm/workflows/4-implementation/story-context/README.md +0 -234
  680. package/src/modules/cis/agents/brainstorming-coach.md +0 -24
  681. package/src/modules/cis/agents/creative-problem-solver.md +0 -24
  682. package/src/modules/cis/agents/design-thinking-coach.md +0 -24
  683. package/src/modules/cis/agents/innovation-strategist.md +0 -24
  684. package/src/modules/cis/agents/storyteller.md +0 -24
  685. package/src/modules/cis/readme.md +0 -86
  686. package/tools/cli/installers/lib/ide/workflow-command-generator.js +0 -162
  687. package/tools/test-agents/captain-kirk-commander.md +0 -110
  688. package/tools/test-agents/data-operations-android.md +0 -123
  689. package/tools/test-agents/geordi-chief-engineer.md +0 -135
  690. package/tools/test-agents/isabella-martinez-ethicist.md +0 -109
  691. package/tools/test-agents/marcus-thompson-security.md +0 -109
  692. package/tools/test-agents/maya-patel-pragmatist.md +0 -82
  693. package/tools/test-agents/picard-diplomat-captain.md +0 -134
  694. package/tools/test-agents/spock-science-officer.md +0 -124
  695. package/tools/test-agents/william-smithers-technocrat.md +0 -71
  696. package/tools/test-agents/zara-chen-designer.md +0 -94
  697. /package/src/{modules/cis → core}/workflows/brainstorming/brain-methods.csv +0 -0
  698. /package/src/modules/{bmm/workflows/1-analysis → bmgd/workflows/1-preproduction}/brainstorm-game/game-brain-methods.csv +0 -0
  699. /package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/metroidvania.md +0 -0
  700. /package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types/puzzle.md +0 -0
  701. /package/src/modules/{bmm/workflows/2-plan → bmgd/workflows/2-design}/gdd/game-types.csv +0 -0
  702. /package/src/modules/{bmm/workflows/4-implementation/review-story → bmgd/workflows/4-production/code-review}/backlog_template.md +0 -0
  703. /package/src/modules/{bmm/workflows/4-implementation/review-story → bmgd/workflows/4-production/code-review}/checklist.md +0 -0
  704. /package/src/modules/bmm/_module-installer/assets/{technical-decisions-template.md → technical-decisions.md} +0 -0
@@ -16,6 +16,7 @@ const { getProjectRoot, getSourcePath, getModulePath } = require('../../../lib/p
16
16
  const { AgentPartyGenerator } = require('../../../lib/agent-party-generator');
17
17
  const { CLIUtils } = require('../../../lib/cli-utils');
18
18
  const { ManifestGenerator } = require('./manifest-generator');
19
+ const { IdeConfigManager } = require('./ide-config-manager');
19
20
 
20
21
  class Installer {
21
22
  constructor() {
@@ -28,72 +29,192 @@ class Installer {
28
29
  this.xmlHandler = new XmlHandler();
29
30
  this.dependencyResolver = new DependencyResolver();
30
31
  this.configCollector = new ConfigCollector();
32
+ this.ideConfigManager = new IdeConfigManager();
31
33
  this.installedFiles = []; // Track all installed files
32
34
  }
33
35
 
36
+ /**
37
+ * Find the bmad installation directory in a project
38
+ * V6+ installations can use ANY folder name but ALWAYS have _cfg/manifest.yaml
39
+ * @param {string} projectDir - Project directory
40
+ * @returns {Promise<string>} Path to bmad directory
41
+ */
42
+ async findBmadDir(projectDir) {
43
+ // Check if project directory exists
44
+ if (!(await fs.pathExists(projectDir))) {
45
+ // Project doesn't exist yet, return default
46
+ return path.join(projectDir, 'bmad');
47
+ }
48
+
49
+ // V6+ strategy: Look for ANY directory with _cfg/manifest.yaml
50
+ // This is the definitive marker of a V6+ installation
51
+ try {
52
+ const entries = await fs.readdir(projectDir, { withFileTypes: true });
53
+ for (const entry of entries) {
54
+ if (entry.isDirectory()) {
55
+ const manifestPath = path.join(projectDir, entry.name, '_cfg', 'manifest.yaml');
56
+ if (await fs.pathExists(manifestPath)) {
57
+ // Found a V6+ installation
58
+ return path.join(projectDir, entry.name);
59
+ }
60
+ }
61
+ }
62
+ } catch {
63
+ // Ignore errors, fall through to default
64
+ }
65
+
66
+ // No V6+ installation found, return default
67
+ // This will be used for new installations
68
+ return path.join(projectDir, 'bmad');
69
+ }
70
+
71
+ /**
72
+ * Copy a file and replace {bmad_folder} placeholder with actual folder name
73
+ * @param {string} sourcePath - Source file path
74
+ * @param {string} targetPath - Target file path
75
+ * @param {string} bmadFolderName - The bmad folder name to use for replacement
76
+ */
77
+ async copyFileWithPlaceholderReplacement(sourcePath, targetPath, bmadFolderName) {
78
+ // List of text file extensions that should have placeholder replacement
79
+ const textExtensions = ['.md', '.yaml', '.yml', '.txt', '.json', '.js', '.ts', '.html', '.css', '.sh', '.bat', '.csv'];
80
+ const ext = path.extname(sourcePath).toLowerCase();
81
+
82
+ // Check if this is a text file that might contain placeholders
83
+ if (textExtensions.includes(ext)) {
84
+ try {
85
+ // Read the file content
86
+ let content = await fs.readFile(sourcePath, 'utf8');
87
+
88
+ // Replace {bmad_folder} placeholder with actual folder name
89
+ if (content.includes('{bmad_folder}')) {
90
+ content = content.replaceAll('{bmad_folder}', bmadFolderName);
91
+ }
92
+
93
+ // Write to target with replaced content
94
+ await fs.ensureDir(path.dirname(targetPath));
95
+ await fs.writeFile(targetPath, content, 'utf8');
96
+ } catch {
97
+ // If reading as text fails (might be binary despite extension), fall back to regular copy
98
+ await fs.copy(sourcePath, targetPath, { overwrite: true });
99
+ }
100
+ } else {
101
+ // Binary file or other file type - just copy directly
102
+ await fs.copy(sourcePath, targetPath, { overwrite: true });
103
+ }
104
+ }
105
+
34
106
  /**
35
107
  * Collect Tool/IDE configurations after module configuration
36
108
  * @param {string} projectDir - Project directory
37
109
  * @param {Array} selectedModules - Selected modules from configuration
110
+ * @param {boolean} isFullReinstall - Whether this is a full reinstall
111
+ * @param {Array} previousIdes - Previously configured IDEs (for reinstalls)
112
+ * @param {Array} preSelectedIdes - Pre-selected IDEs from early prompt (optional)
38
113
  * @returns {Object} Tool/IDE selection and configurations
39
114
  */
40
- async collectToolConfigurations(projectDir, selectedModules) {
41
- // Prompt for tool selection
42
- const { UI } = require('../../../lib/ui');
43
- const ui = new UI();
44
- const toolConfig = await ui.promptToolSelection(projectDir, selectedModules);
115
+ async collectToolConfigurations(projectDir, selectedModules, isFullReinstall = false, previousIdes = [], preSelectedIdes = null) {
116
+ // Use pre-selected IDEs if provided, otherwise prompt
117
+ let toolConfig;
118
+ if (preSelectedIdes === null) {
119
+ // Fallback: prompt for tool selection (backwards compatibility)
120
+ const { UI } = require('../../../lib/ui');
121
+ const ui = new UI();
122
+ toolConfig = await ui.promptToolSelection(projectDir, selectedModules);
123
+ } else {
124
+ // IDEs were already selected during initial prompts
125
+ toolConfig = {
126
+ ides: preSelectedIdes,
127
+ skipIde: !preSelectedIdes || preSelectedIdes.length === 0,
128
+ };
129
+ }
130
+
131
+ // Check for already configured IDEs
132
+ const { Detector } = require('./detector');
133
+ const detector = new Detector();
134
+ const bmadDir = path.join(projectDir, this.bmadFolderName || 'bmad');
135
+
136
+ // During full reinstall, use the saved previous IDEs since bmad dir was deleted
137
+ // Otherwise detect from existing installation
138
+ let previouslyConfiguredIdes;
139
+ if (isFullReinstall) {
140
+ // During reinstall, treat all IDEs as new (need configuration)
141
+ previouslyConfiguredIdes = [];
142
+ } else {
143
+ const existingInstall = await detector.detect(bmadDir);
144
+ previouslyConfiguredIdes = existingInstall.ides || [];
145
+ }
146
+
147
+ // Load saved IDE configurations for already-configured IDEs
148
+ const savedIdeConfigs = await this.ideConfigManager.loadAllIdeConfigs(bmadDir);
45
149
 
46
150
  // Collect IDE-specific configurations if any were selected
47
151
  const ideConfigurations = {};
48
- const bmadDir = path.join(projectDir, 'bmad');
152
+
153
+ // First, add saved configs for already-configured IDEs
154
+ for (const ide of toolConfig.ides || []) {
155
+ if (previouslyConfiguredIdes.includes(ide) && savedIdeConfigs[ide]) {
156
+ ideConfigurations[ide] = savedIdeConfigs[ide];
157
+ }
158
+ }
49
159
 
50
160
  if (!toolConfig.skipIde && toolConfig.ides && toolConfig.ides.length > 0) {
51
- console.log('\n'); // Add spacing before IDE questions
52
-
53
- for (const ide of toolConfig.ides) {
54
- // List of IDEs that have interactive prompts
55
- const needsPrompts = ['claude-code', 'github-copilot', 'roo', 'cline', 'auggie', 'codex', 'qwen', 'gemini'].includes(ide);
56
-
57
- if (needsPrompts) {
58
- // Get IDE handler and collect configuration
59
- try {
60
- // Dynamically load the IDE setup module
61
- const ideModule = require(`../ide/${ide}`);
62
-
63
- // Get the setup class (handle different export formats)
64
- let SetupClass;
65
- const className =
66
- ide
67
- .split('-')
68
- .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
69
- .join('') + 'Setup';
70
-
71
- if (ideModule[className]) {
72
- SetupClass = ideModule[className];
73
- } else if (ideModule.default) {
74
- SetupClass = ideModule.default;
75
- } else {
76
- // Skip if no setup class found
77
- continue;
78
- }
161
+ // Determine which IDEs are newly selected (not previously configured)
162
+ const newlySelectedIdes = toolConfig.ides.filter((ide) => !previouslyConfiguredIdes.includes(ide));
163
+
164
+ if (newlySelectedIdes.length > 0) {
165
+ console.log('\n'); // Add spacing before IDE questions
166
+
167
+ for (const ide of newlySelectedIdes) {
168
+ // List of IDEs that have interactive prompts
169
+ const needsPrompts = ['claude-code', 'github-copilot', 'roo', 'cline', 'auggie', 'codex', 'qwen', 'gemini'].includes(ide);
170
+
171
+ if (needsPrompts) {
172
+ // Get IDE handler and collect configuration
173
+ try {
174
+ // Dynamically load the IDE setup module
175
+ const ideModule = require(`../ide/${ide}`);
176
+
177
+ // Get the setup class (handle different export formats)
178
+ let SetupClass;
179
+ const className =
180
+ ide
181
+ .split('-')
182
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
183
+ .join('') + 'Setup';
184
+
185
+ if (ideModule[className]) {
186
+ SetupClass = ideModule[className];
187
+ } else if (ideModule.default) {
188
+ SetupClass = ideModule.default;
189
+ } else {
190
+ // Skip if no setup class found
191
+ continue;
192
+ }
79
193
 
80
- const ideSetup = new SetupClass();
194
+ const ideSetup = new SetupClass();
81
195
 
82
- // Check if this IDE has a collectConfiguration method
83
- if (typeof ideSetup.collectConfiguration === 'function') {
84
- console.log(chalk.cyan(`\nConfiguring ${ide}...`));
85
- ideConfigurations[ide] = await ideSetup.collectConfiguration({
86
- selectedModules: selectedModules || [],
87
- projectDir,
88
- bmadDir,
89
- });
196
+ // Check if this IDE has a collectConfiguration method
197
+ if (typeof ideSetup.collectConfiguration === 'function') {
198
+ console.log(chalk.cyan(`\nConfiguring ${ide}...`));
199
+ ideConfigurations[ide] = await ideSetup.collectConfiguration({
200
+ selectedModules: selectedModules || [],
201
+ projectDir,
202
+ bmadDir,
203
+ });
204
+ }
205
+ } catch {
206
+ // IDE doesn't have a setup file or collectConfiguration method
207
+ console.warn(chalk.yellow(`Warning: Could not load configuration for ${ide}`));
90
208
  }
91
- } catch {
92
- // IDE doesn't have a setup file or collectConfiguration method
93
- console.warn(chalk.yellow(`Warning: Could not load configuration for ${ide}`));
94
209
  }
95
210
  }
96
211
  }
212
+
213
+ // Log which IDEs are already configured and being kept
214
+ const keptIdes = toolConfig.ides.filter((ide) => previouslyConfiguredIdes.includes(ide));
215
+ if (keptIdes.length > 0) {
216
+ console.log(chalk.dim(`\nKeeping existing configuration for: ${keptIdes.join(', ')}`));
217
+ }
97
218
  }
98
219
 
99
220
  return {
@@ -119,13 +240,10 @@ class Installer {
119
240
  // Display welcome message
120
241
  CLIUtils.displaySection('BMAD™ Installation', 'Version ' + require(path.join(getProjectRoot(), 'package.json')).version);
121
242
 
122
- // Preflight: Block legacy BMAD v4 footprints before any prompts/writes
243
+ // Note: Legacy V4 detection now happens earlier in UI.promptInstall()
244
+ // before any config collection, so we don't need to check again here
245
+
123
246
  const projectDir = path.resolve(config.directory);
124
- const legacyV4 = await this.detector.detectLegacyV4(projectDir);
125
- if (legacyV4.hasLegacyV4) {
126
- const error = this.createLegacyV4Error(legacyV4);
127
- throw error;
128
- }
129
247
 
130
248
  // If core config was pre-collected (from interactive mode), use it
131
249
  if (config.coreConfig) {
@@ -137,15 +255,25 @@ class Installer {
137
255
  }
138
256
  }
139
257
 
140
- // Collect configurations for modules (core was already collected in UI.promptInstall if interactive)
141
- const moduleConfigs = await this.configCollector.collectAllConfigurations(config.modules || [], path.resolve(config.directory));
258
+ // Collect configurations for modules (skip if quick update already collected them)
259
+ let moduleConfigs;
260
+ if (config._quickUpdate) {
261
+ // Quick update already collected all configs, use them directly
262
+ moduleConfigs = this.configCollector.collectedConfig;
263
+ } else {
264
+ // Regular install - collect configurations (core was already collected in UI.promptInstall if interactive)
265
+ moduleConfigs = await this.configCollector.collectAllConfigurations(config.modules || [], path.resolve(config.directory));
266
+ }
267
+
268
+ // Get bmad_folder from config (default to 'bmad' for backwards compatibility)
269
+ const bmadFolderName = moduleConfigs.core && moduleConfigs.core.bmad_folder ? moduleConfigs.core.bmad_folder : 'bmad';
270
+ this.bmadFolderName = bmadFolderName; // Store for use in other methods
142
271
 
143
- const toolSelection = await this.collectToolConfigurations(path.resolve(config.directory), config.modules);
272
+ // Set bmad folder name on module manager and IDE manager for placeholder replacement
273
+ this.moduleManager.setBmadFolderName(bmadFolderName);
274
+ this.ideManager.setBmadFolderName(bmadFolderName);
144
275
 
145
- // Merge tool selection into config
146
- config.ides = toolSelection.ides;
147
- config.skipIde = toolSelection.skipIde;
148
- const ideConfigurations = toolSelection.configurations;
276
+ // Tool selection will be collected after we determine if it's a reinstall/update/new install
149
277
 
150
278
  const spinner = ora('Preparing installation...').start();
151
279
 
@@ -153,6 +281,63 @@ class Installer {
153
281
  // Resolve target directory (path.resolve handles platform differences)
154
282
  const projectDir = path.resolve(config.directory);
155
283
 
284
+ // Check if bmad_folder has changed from existing installation (only if project dir exists)
285
+ let existingBmadDir = null;
286
+ let existingBmadFolderName = null;
287
+
288
+ if (await fs.pathExists(projectDir)) {
289
+ existingBmadDir = await this.findBmadDir(projectDir);
290
+ existingBmadFolderName = path.basename(existingBmadDir);
291
+ }
292
+
293
+ const targetBmadDir = path.join(projectDir, bmadFolderName);
294
+
295
+ // If bmad_folder changed during update/upgrade, back up old folder and do fresh install
296
+ if (existingBmadDir && (await fs.pathExists(existingBmadDir)) && existingBmadFolderName !== bmadFolderName) {
297
+ spinner.stop();
298
+ console.log(chalk.yellow(`\n⚠️ bmad_folder has changed: ${existingBmadFolderName} → ${bmadFolderName}`));
299
+ console.log(chalk.yellow('This will result in a fresh installation to the new folder.'));
300
+
301
+ const inquirer = require('inquirer');
302
+ const { confirmFreshInstall } = await inquirer.prompt([
303
+ {
304
+ type: 'confirm',
305
+ name: 'confirmFreshInstall',
306
+ message: chalk.cyan('Proceed with fresh install? (Your old folder will be backed up)'),
307
+ default: true,
308
+ },
309
+ ]);
310
+
311
+ if (!confirmFreshInstall) {
312
+ console.log(chalk.yellow('Installation cancelled.'));
313
+ return { success: false, cancelled: true };
314
+ }
315
+
316
+ spinner.start('Backing up existing installation...');
317
+
318
+ // Find a unique backup name
319
+ let backupDir = `${existingBmadDir}-bak`;
320
+ let counter = 1;
321
+ while (await fs.pathExists(backupDir)) {
322
+ backupDir = `${existingBmadDir}-bak-${counter}`;
323
+ counter++;
324
+ }
325
+
326
+ // Rename the old folder to backup
327
+ await fs.move(existingBmadDir, backupDir);
328
+
329
+ spinner.succeed(`Backed up ${existingBmadFolderName} → ${path.basename(backupDir)}`);
330
+ console.log(chalk.cyan('\n📋 Important:'));
331
+ console.log(chalk.dim(` - Your old installation has been backed up to: ${path.basename(backupDir)}`));
332
+ console.log(chalk.dim(` - If you had custom agents or configurations, copy them from:`));
333
+ console.log(chalk.dim(` ${path.basename(backupDir)}/_cfg/`));
334
+ console.log(chalk.dim(` - To the new location:`));
335
+ console.log(chalk.dim(` ${bmadFolderName}/_cfg/`));
336
+ console.log('');
337
+
338
+ spinner.start('Starting fresh installation...');
339
+ }
340
+
156
341
  // Create a project directory if it doesn't exist (user already confirmed)
157
342
  if (!(await fs.pathExists(projectDir))) {
158
343
  spinner.text = 'Creating installation directory...';
@@ -173,27 +358,217 @@ class Installer {
173
358
  }
174
359
  }
175
360
 
176
- const bmadDir = path.join(projectDir, 'bmad');
361
+ const bmadDir = path.join(projectDir, bmadFolderName);
177
362
 
178
363
  // Check existing installation
179
364
  spinner.text = 'Checking for existing installation...';
180
365
  const existingInstall = await this.detector.detect(bmadDir);
181
366
 
182
- if (existingInstall.installed && !config.force) {
367
+ if (existingInstall.installed && !config.force && !config._quickUpdate) {
183
368
  spinner.stop();
184
369
 
185
- console.log(chalk.yellow('\n⚠️ Existing BMAD installation detected'));
186
- console.log(chalk.dim(` Location: ${bmadDir}`));
187
- console.log(chalk.dim(` Version: ${existingInstall.version}`));
370
+ // Check if user already decided what to do (from early menu in ui.js)
371
+ let action = null;
372
+ if (config._requestedReinstall) {
373
+ action = 'reinstall';
374
+ } else if (config.actionType === 'update') {
375
+ action = 'update';
376
+ } else {
377
+ // Fallback: Ask the user (backwards compatibility for other code paths)
378
+ console.log(chalk.yellow('\n⚠️ Existing BMAD installation detected'));
379
+ console.log(chalk.dim(` Location: ${bmadDir}`));
380
+ console.log(chalk.dim(` Version: ${existingInstall.version}`));
381
+
382
+ const promptResult = await this.promptUpdateAction();
383
+ action = promptResult.action;
384
+ }
188
385
 
189
- // TODO: Handle update scenario
190
- const { action } = await this.promptUpdateAction();
191
386
  if (action === 'cancel') {
192
387
  console.log('Installation cancelled.');
193
- return;
388
+ return { success: false, cancelled: true };
389
+ }
390
+
391
+ if (action === 'reinstall') {
392
+ // Warn about destructive operation
393
+ console.log(chalk.red.bold('\n⚠️ WARNING: This is a destructive operation!'));
394
+ console.log(chalk.red('All custom files and modifications in the bmad directory will be lost.'));
395
+
396
+ const inquirer = require('inquirer');
397
+ const { confirmReinstall } = await inquirer.prompt([
398
+ {
399
+ type: 'confirm',
400
+ name: 'confirmReinstall',
401
+ message: chalk.yellow('Are you sure you want to delete and reinstall?'),
402
+ default: false,
403
+ },
404
+ ]);
405
+
406
+ if (!confirmReinstall) {
407
+ console.log('Installation cancelled.');
408
+ return { success: false, cancelled: true };
409
+ }
410
+
411
+ // Remember previously configured IDEs before deleting
412
+ config._previouslyConfiguredIdes = existingInstall.ides || [];
413
+
414
+ // Remove existing installation
415
+ await fs.remove(bmadDir);
416
+ console.log(chalk.green('✓ Removed existing installation\n'));
417
+
418
+ // Mark this as a full reinstall so we re-collect IDE configurations
419
+ config._isFullReinstall = true;
420
+ } else if (action === 'update') {
421
+ // Store that we're updating for later processing
422
+ config._isUpdate = true;
423
+ config._existingInstall = existingInstall;
424
+
425
+ // Detect custom and modified files BEFORE updating (compare current files vs files-manifest.csv)
426
+ const existingFilesManifest = await this.readFilesManifest(bmadDir);
427
+ console.log(chalk.dim(`DEBUG: Read ${existingFilesManifest.length} files from manifest`));
428
+ console.log(chalk.dim(`DEBUG: Manifest has hashes: ${existingFilesManifest.some((f) => f.hash)}`));
429
+
430
+ const { customFiles, modifiedFiles } = await this.detectCustomFiles(bmadDir, existingFilesManifest);
431
+
432
+ console.log(chalk.dim(`DEBUG: Found ${customFiles.length} custom files, ${modifiedFiles.length} modified files`));
433
+ if (modifiedFiles.length > 0) {
434
+ console.log(chalk.yellow('DEBUG: Modified files:'));
435
+ for (const f of modifiedFiles) console.log(chalk.dim(` - ${f.path}`));
436
+ }
437
+
438
+ config._customFiles = customFiles;
439
+ config._modifiedFiles = modifiedFiles;
440
+
441
+ // If there are custom files, back them up temporarily
442
+ if (customFiles.length > 0) {
443
+ const tempBackupDir = path.join(projectDir, '.bmad-custom-backup-temp');
444
+ await fs.ensureDir(tempBackupDir);
445
+
446
+ spinner.start(`Backing up ${customFiles.length} custom files...`);
447
+ for (const customFile of customFiles) {
448
+ const relativePath = path.relative(bmadDir, customFile);
449
+ const backupPath = path.join(tempBackupDir, relativePath);
450
+ await fs.ensureDir(path.dirname(backupPath));
451
+ await fs.copy(customFile, backupPath);
452
+ }
453
+ spinner.succeed(`Backed up ${customFiles.length} custom files`);
454
+
455
+ config._tempBackupDir = tempBackupDir;
456
+ }
457
+
458
+ // For modified files, back them up to temp directory (will be restored as .bak files after install)
459
+ if (modifiedFiles.length > 0) {
460
+ const tempModifiedBackupDir = path.join(projectDir, '.bmad-modified-backup-temp');
461
+ await fs.ensureDir(tempModifiedBackupDir);
462
+
463
+ console.log(chalk.yellow(`\nDEBUG: Backing up ${modifiedFiles.length} modified files to temp location`));
464
+ spinner.start(`Backing up ${modifiedFiles.length} modified files...`);
465
+ for (const modifiedFile of modifiedFiles) {
466
+ const relativePath = path.relative(bmadDir, modifiedFile.path);
467
+ const tempBackupPath = path.join(tempModifiedBackupDir, relativePath);
468
+ console.log(chalk.dim(`DEBUG: Backing up ${relativePath} to temp`));
469
+ await fs.ensureDir(path.dirname(tempBackupPath));
470
+ await fs.copy(modifiedFile.path, tempBackupPath, { overwrite: true });
471
+ }
472
+ spinner.succeed(`Backed up ${modifiedFiles.length} modified files`);
473
+
474
+ config._tempModifiedBackupDir = tempModifiedBackupDir;
475
+ } else {
476
+ console.log(chalk.dim('DEBUG: No modified files detected'));
477
+ }
478
+ }
479
+ } else if (existingInstall.installed && config._quickUpdate) {
480
+ // Quick update mode - automatically treat as update without prompting
481
+ spinner.text = 'Preparing quick update...';
482
+ config._isUpdate = true;
483
+ config._existingInstall = existingInstall;
484
+
485
+ // Detect custom and modified files BEFORE updating
486
+ const existingFilesManifest = await this.readFilesManifest(bmadDir);
487
+ const { customFiles, modifiedFiles } = await this.detectCustomFiles(bmadDir, existingFilesManifest);
488
+
489
+ config._customFiles = customFiles;
490
+ config._modifiedFiles = modifiedFiles;
491
+
492
+ // Back up custom files
493
+ if (customFiles.length > 0) {
494
+ const tempBackupDir = path.join(projectDir, '.bmad-custom-backup-temp');
495
+ await fs.ensureDir(tempBackupDir);
496
+
497
+ spinner.start(`Backing up ${customFiles.length} custom files...`);
498
+ for (const customFile of customFiles) {
499
+ const relativePath = path.relative(bmadDir, customFile);
500
+ const backupPath = path.join(tempBackupDir, relativePath);
501
+ await fs.ensureDir(path.dirname(backupPath));
502
+ await fs.copy(customFile, backupPath);
503
+ }
504
+ spinner.succeed(`Backed up ${customFiles.length} custom files`);
505
+ config._tempBackupDir = tempBackupDir;
506
+ }
507
+
508
+ // Back up modified files
509
+ if (modifiedFiles.length > 0) {
510
+ const tempModifiedBackupDir = path.join(projectDir, '.bmad-modified-backup-temp');
511
+ await fs.ensureDir(tempModifiedBackupDir);
512
+
513
+ spinner.start(`Backing up ${modifiedFiles.length} modified files...`);
514
+ for (const modifiedFile of modifiedFiles) {
515
+ const relativePath = path.relative(bmadDir, modifiedFile.path);
516
+ const tempBackupPath = path.join(tempModifiedBackupDir, relativePath);
517
+ await fs.ensureDir(path.dirname(tempBackupPath));
518
+ await fs.copy(modifiedFile.path, tempBackupPath, { overwrite: true });
519
+ }
520
+ spinner.succeed(`Backed up ${modifiedFiles.length} modified files`);
521
+ config._tempModifiedBackupDir = tempModifiedBackupDir;
194
522
  }
195
523
  }
196
524
 
525
+ // Now collect tool configurations after we know if it's a reinstall
526
+ // Skip for quick update since we already have the IDE list
527
+ spinner.stop();
528
+ let toolSelection;
529
+ if (config._quickUpdate) {
530
+ // Quick update already has IDEs configured, use saved configurations
531
+ const preConfiguredIdes = {};
532
+ const savedIdeConfigs = config._savedIdeConfigs || {};
533
+
534
+ for (const ide of config.ides || []) {
535
+ // Use saved config if available, otherwise mark as already configured (legacy)
536
+ if (savedIdeConfigs[ide]) {
537
+ preConfiguredIdes[ide] = savedIdeConfigs[ide];
538
+ } else {
539
+ preConfiguredIdes[ide] = { _alreadyConfigured: true };
540
+ }
541
+ }
542
+ toolSelection = {
543
+ ides: config.ides || [],
544
+ skipIde: !config.ides || config.ides.length === 0,
545
+ configurations: preConfiguredIdes,
546
+ };
547
+ } else {
548
+ // Pass pre-selected IDEs from early prompt (if available)
549
+ // This allows IDE selection to happen before file copying, improving UX
550
+ const preSelectedIdes = config.ides && config.ides.length > 0 ? config.ides : null;
551
+ toolSelection = await this.collectToolConfigurations(
552
+ path.resolve(config.directory),
553
+ config.modules,
554
+ config._isFullReinstall || false,
555
+ config._previouslyConfiguredIdes || [],
556
+ preSelectedIdes,
557
+ );
558
+ }
559
+
560
+ // Merge tool selection into config (for both quick update and regular flow)
561
+ config.ides = toolSelection.ides;
562
+ config.skipIde = toolSelection.skipIde;
563
+ const ideConfigurations = toolSelection.configurations;
564
+
565
+ // Check if spinner is already running (e.g., from folder name change scenario)
566
+ if (spinner.isSpinning) {
567
+ spinner.text = 'Continuing installation...';
568
+ } else {
569
+ spinner.start('Continuing installation...');
570
+ }
571
+
197
572
  // Create bmad directory structure
198
573
  spinner.text = 'Creating directory structure...';
199
574
  await this.createDirectoryStructure(bmadDir);
@@ -230,7 +605,13 @@ class Installer {
230
605
  // Install partial modules (only dependencies)
231
606
  for (const [module, files] of Object.entries(resolution.byModule)) {
232
607
  if (!config.modules.includes(module) && module !== 'core') {
233
- const totalFiles = files.agents.length + files.tasks.length + files.templates.length + files.data.length + files.other.length;
608
+ const totalFiles =
609
+ files.agents.length +
610
+ files.tasks.length +
611
+ files.tools.length +
612
+ files.templates.length +
613
+ files.data.length +
614
+ files.other.length;
234
615
  if (totalFiles > 0) {
235
616
  spinner.start(`Installing ${module} dependencies...`);
236
617
  await this.installPartialModule(module, bmadDir, files);
@@ -246,57 +627,102 @@ class Installer {
246
627
  spinner.succeed('Module configurations generated');
247
628
 
248
629
  // Create agent configuration files
249
- spinner.start('Creating agent configurations...');
250
- // Get user info from collected config if available
251
- const userInfo = {
252
- userName: moduleConfigs.core?.['user_name'] || null,
253
- responseLanguage: moduleConfigs.core?.['communication_language'] || null,
254
- };
255
- const agentConfigResult = await this.createAgentConfigs(bmadDir, userInfo);
256
- if (agentConfigResult.skipped > 0) {
257
- spinner.succeed(`Agent configurations: ${agentConfigResult.created} created, ${agentConfigResult.skipped} preserved`);
258
- } else {
259
- spinner.succeed(`Agent configurations created: ${agentConfigResult.created}`);
260
- }
630
+ // Note: Legacy createAgentConfigs removed - using YAML customize system instead
631
+ // Customize templates are now created in processAgentFiles when building YAML agents
632
+
633
+ // Pre-register manifest files that will be created (except files-manifest.csv to avoid recursion)
634
+ const cfgDir = path.join(bmadDir, '_cfg');
635
+ this.installedFiles.push(
636
+ path.join(cfgDir, 'manifest.yaml'),
637
+ path.join(cfgDir, 'workflow-manifest.csv'),
638
+ path.join(cfgDir, 'agent-manifest.csv'),
639
+ path.join(cfgDir, 'task-manifest.csv'),
640
+ );
261
641
 
262
- // Generate CSV manifests for workflows, agents, and tasks BEFORE IDE setup
642
+ // Generate CSV manifests for workflows, agents, tasks AND ALL FILES with hashes BEFORE IDE setup
263
643
  spinner.start('Generating workflow and agent manifests...');
264
644
  const manifestGen = new ManifestGenerator();
265
- const manifestStats = await manifestGen.generateManifests(bmadDir, config.modules || []);
645
+
646
+ // Include preserved modules (from quick update) in the manifest
647
+ const allModulesToList = config._preserveModules ? [...(config.modules || []), ...config._preserveModules] : config.modules || [];
648
+
649
+ const manifestStats = await manifestGen.generateManifests(bmadDir, config.modules || [], this.installedFiles, {
650
+ ides: config.ides || [],
651
+ preservedModules: config._preserveModules || [], // Scan these from installed bmad/ dir
652
+ });
653
+
266
654
  spinner.succeed(
267
- `Manifests generated: ${manifestStats.workflows} workflows, ${manifestStats.agents} agents, ${manifestStats.tasks} tasks`,
655
+ `Manifests generated: ${manifestStats.workflows} workflows, ${manifestStats.agents} agents, ${manifestStats.tasks} tasks, ${manifestStats.tools} tools, ${manifestStats.files} files`,
268
656
  );
269
657
 
270
658
  // Configure IDEs and copy documentation
271
659
  if (!config.skipIde && config.ides && config.ides.length > 0) {
272
- spinner.start('Configuring IDEs...');
660
+ // Filter out any undefined/null values from the IDE list
661
+ const validIdes = config.ides.filter((ide) => ide && typeof ide === 'string');
273
662
 
274
- // Temporarily suppress console output if not verbose
275
- const originalLog = console.log;
276
- if (!config.verbose) {
277
- console.log = () => {};
278
- }
663
+ if (validIdes.length === 0) {
664
+ console.log(chalk.yellow('⚠️ No valid IDEs selected. Skipping IDE configuration.'));
665
+ } else {
666
+ // Check if any IDE might need prompting (no pre-collected config)
667
+ const needsPrompting = validIdes.some((ide) => !ideConfigurations[ide]);
279
668
 
280
- for (const ide of config.ides) {
281
- spinner.text = `Configuring ${ide}...`;
669
+ if (!needsPrompting) {
670
+ spinner.start('Configuring IDEs...');
671
+ }
282
672
 
283
- // Pass pre-collected configuration to avoid re-prompting
284
- await this.ideManager.setup(ide, projectDir, bmadDir, {
285
- selectedModules: config.modules || [],
286
- preCollectedConfig: ideConfigurations[ide] || null,
287
- verbose: config.verbose,
288
- });
289
- }
673
+ // Temporarily suppress console output if not verbose
674
+ const originalLog = console.log;
675
+ if (!config.verbose) {
676
+ console.log = () => {};
677
+ }
678
+
679
+ for (const ide of validIdes) {
680
+ // Only show spinner if we have pre-collected config (no prompts expected)
681
+ if (ideConfigurations[ide] && !needsPrompting) {
682
+ spinner.text = `Configuring ${ide}...`;
683
+ } else if (!ideConfigurations[ide]) {
684
+ // Stop spinner before prompting
685
+ if (spinner.isSpinning) {
686
+ spinner.stop();
687
+ }
688
+ console.log(chalk.cyan(`\nConfiguring ${ide}...`));
689
+ }
690
+
691
+ // Pass pre-collected configuration to avoid re-prompting
692
+ await this.ideManager.setup(ide, projectDir, bmadDir, {
693
+ selectedModules: config.modules || [],
694
+ preCollectedConfig: ideConfigurations[ide] || null,
695
+ verbose: config.verbose,
696
+ });
290
697
 
291
- // Restore console.log
292
- console.log = originalLog;
698
+ // Save IDE configuration for future updates
699
+ if (ideConfigurations[ide] && !ideConfigurations[ide]._alreadyConfigured) {
700
+ await this.ideConfigManager.saveIdeConfig(bmadDir, ide, ideConfigurations[ide]);
701
+ }
702
+
703
+ // Restart spinner if we stopped it
704
+ if (!ideConfigurations[ide] && !spinner.isSpinning) {
705
+ spinner.start('Configuring IDEs...');
706
+ }
707
+ }
293
708
 
294
- spinner.succeed(`Configured ${config.ides.length} IDE${config.ides.length > 1 ? 's' : ''}`);
709
+ // Restore console.log
710
+ console.log = originalLog;
711
+
712
+ if (spinner.isSpinning) {
713
+ spinner.succeed(`Configured ${validIdes.length} IDE${validIdes.length > 1 ? 's' : ''}`);
714
+ } else {
715
+ console.log(chalk.green(`✓ Configured ${validIdes.length} IDE${validIdes.length > 1 ? 's' : ''}`));
716
+ }
717
+ }
295
718
 
296
- // Copy IDE-specific documentation
297
- spinner.start('Copying IDE documentation...');
298
- await this.copyIdeDocumentation(config.ides, bmadDir);
299
- spinner.succeed('IDE documentation copied');
719
+ // Copy IDE-specific documentation (only for valid IDEs)
720
+ const validIdesForDocs = (config.ides || []).filter((ide) => ide && typeof ide === 'string');
721
+ if (validIdesForDocs.length > 0) {
722
+ spinner.start('Copying IDE documentation...');
723
+ await this.copyIdeDocumentation(validIdesForDocs, bmadDir);
724
+ spinner.succeed('IDE documentation copied');
725
+ }
300
726
  }
301
727
 
302
728
  // Run module-specific installers after IDE setup
@@ -337,24 +763,83 @@ class Installer {
337
763
 
338
764
  spinner.succeed('Module-specific installers completed');
339
765
 
340
- // Create manifest
341
- spinner.start('Creating installation manifest...');
342
- const manifestResult = await this.manifest.create(
343
- bmadDir,
344
- {
345
- version: require(path.join(getProjectRoot(), 'package.json')).version,
346
- installDate: new Date().toISOString(),
347
- core: config.installCore,
348
- modules: config.modules || [],
349
- ides: config.ides || [],
350
- language: config.language || null,
351
- },
352
- this.installedFiles,
353
- );
354
- spinner.succeed(`Manifest created (${manifestResult.filesTracked} files tracked)`);
766
+ // Note: Manifest files are already created by ManifestGenerator above
767
+ // No need to create legacy manifest.csv anymore
768
+
769
+ // If this was an update, restore custom files
770
+ let customFiles = [];
771
+ let modifiedFiles = [];
772
+ if (config._isUpdate) {
773
+ if (config._customFiles && config._customFiles.length > 0) {
774
+ spinner.start(`Restoring ${config._customFiles.length} custom files...`);
775
+
776
+ for (const originalPath of config._customFiles) {
777
+ const relativePath = path.relative(bmadDir, originalPath);
778
+ const backupPath = path.join(config._tempBackupDir, relativePath);
779
+
780
+ if (await fs.pathExists(backupPath)) {
781
+ await fs.ensureDir(path.dirname(originalPath));
782
+ await fs.copy(backupPath, originalPath, { overwrite: true });
783
+ }
784
+ }
785
+
786
+ // Clean up temp backup
787
+ if (config._tempBackupDir && (await fs.pathExists(config._tempBackupDir))) {
788
+ await fs.remove(config._tempBackupDir);
789
+ }
790
+
791
+ spinner.succeed(`Restored ${config._customFiles.length} custom files`);
792
+ customFiles = config._customFiles;
793
+ }
794
+
795
+ if (config._modifiedFiles && config._modifiedFiles.length > 0) {
796
+ modifiedFiles = config._modifiedFiles;
797
+
798
+ // Restore modified files as .bak files
799
+ if (config._tempModifiedBackupDir && (await fs.pathExists(config._tempModifiedBackupDir))) {
800
+ spinner.start(`Restoring ${modifiedFiles.length} modified files as .bak...`);
801
+
802
+ for (const modifiedFile of modifiedFiles) {
803
+ const relativePath = path.relative(bmadDir, modifiedFile.path);
804
+ const tempBackupPath = path.join(config._tempModifiedBackupDir, relativePath);
805
+ const bakPath = modifiedFile.path + '.bak';
806
+
807
+ if (await fs.pathExists(tempBackupPath)) {
808
+ await fs.ensureDir(path.dirname(bakPath));
809
+ await fs.copy(tempBackupPath, bakPath, { overwrite: true });
810
+ }
811
+ }
812
+
813
+ // Clean up temp backup
814
+ await fs.remove(config._tempModifiedBackupDir);
815
+
816
+ spinner.succeed(`Restored ${modifiedFiles.length} modified files as .bak`);
817
+ }
818
+ }
819
+ }
355
820
 
356
821
  spinner.stop();
357
822
 
823
+ // Report custom and modified files if any were found
824
+ if (customFiles.length > 0) {
825
+ console.log(chalk.cyan(`\n📁 Custom files preserved: ${customFiles.length}`));
826
+ console.log(chalk.dim('The following custom files were found and restored:\n'));
827
+ for (const file of customFiles) {
828
+ console.log(chalk.dim(` - ${path.relative(bmadDir, file)}`));
829
+ }
830
+ console.log('');
831
+ }
832
+
833
+ if (modifiedFiles.length > 0) {
834
+ console.log(chalk.yellow(`\n⚠️ Modified files detected: ${modifiedFiles.length}`));
835
+ console.log(chalk.dim('The following files were modified and backed up with .bak extension:\n'));
836
+ for (const file of modifiedFiles) {
837
+ console.log(chalk.dim(` - ${file.relativePath} → ${file.relativePath}.bak`));
838
+ }
839
+ console.log(chalk.dim('\nThese files have been updated with the new version.'));
840
+ console.log(chalk.dim('Review the .bak files to see your changes and merge if needed.\n'));
841
+ }
842
+
358
843
  // Display completion message
359
844
  const { UI } = require('../../../lib/ui');
360
845
  const ui = new UI();
@@ -362,6 +847,7 @@ class Installer {
362
847
  path: bmadDir,
363
848
  modules: config.modules,
364
849
  ides: config.ides,
850
+ customFiles: customFiles.length > 0 ? customFiles : undefined,
365
851
  });
366
852
 
367
853
  return { success: true, path: bmadDir, modules: config.modules, ides: config.ides };
@@ -378,7 +864,8 @@ class Installer {
378
864
  const spinner = ora('Checking installation...').start();
379
865
 
380
866
  try {
381
- const bmadDir = path.join(path.resolve(config.directory), 'bmad');
867
+ const projectDir = path.resolve(config.directory);
868
+ const bmadDir = await this.findBmadDir(projectDir);
382
869
  const existingInstall = await this.detector.detect(bmadDir);
383
870
 
384
871
  if (!existingInstall.installed) {
@@ -438,7 +925,8 @@ class Installer {
438
925
  * Get installation status
439
926
  */
440
927
  async getStatus(directory) {
441
- const bmadDir = path.join(path.resolve(directory), 'bmad');
928
+ const projectDir = path.resolve(directory);
929
+ const bmadDir = await this.findBmadDir(projectDir);
442
930
  return await this.detector.detect(bmadDir);
443
931
  }
444
932
 
@@ -453,14 +941,15 @@ class Installer {
453
941
  * Uninstall BMAD
454
942
  */
455
943
  async uninstall(directory) {
456
- const bmadDir = path.join(path.resolve(directory), 'bmad');
944
+ const projectDir = path.resolve(directory);
945
+ const bmadDir = await this.findBmadDir(projectDir);
457
946
 
458
947
  if (await fs.pathExists(bmadDir)) {
459
948
  await fs.remove(bmadDir);
460
949
  }
461
950
 
462
951
  // Clean up IDE configurations
463
- await this.ideManager.cleanup(path.resolve(directory));
952
+ await this.ideManager.cleanup(projectDir);
464
953
 
465
954
  return { success: true };
466
955
  }
@@ -558,8 +1047,12 @@ class Installer {
558
1047
  }
559
1048
  }
560
1049
 
561
- // Write the clean config file
562
- await fs.writeFile(configPath, header + yamlContent, 'utf8');
1050
+ // Write the clean config file with POSIX-compliant final newline
1051
+ const content = header + yamlContent;
1052
+ await fs.writeFile(configPath, content.endsWith('\n') ? content : content + '\n', 'utf8');
1053
+
1054
+ // Track the config file in installedFiles
1055
+ this.installedFiles.push(configPath);
563
1056
  }
564
1057
  }
565
1058
  }
@@ -589,6 +1082,9 @@ class Installer {
589
1082
  * @param {Object} moduleFiles - Module files to install
590
1083
  */
591
1084
  async installModuleWithDependencies(moduleName, bmadDir, moduleFiles) {
1085
+ // Get module configuration for conditional installation
1086
+ const moduleConfig = this.configCollector.collectedConfig[moduleName] || {};
1087
+
592
1088
  // Use existing module manager for full installation with file tracking
593
1089
  // Note: Module-specific installers are called separately after IDE setup
594
1090
  await this.moduleManager.install(
@@ -599,9 +1095,14 @@ class Installer {
599
1095
  },
600
1096
  {
601
1097
  skipModuleInstaller: true, // We'll run it later after IDE setup
1098
+ moduleConfig: moduleConfig, // Pass module config for conditional filtering
602
1099
  },
603
1100
  );
604
1101
 
1102
+ // Process agent files to build YAML agents and create customize templates
1103
+ const modulePath = path.join(bmadDir, moduleName);
1104
+ await this.processAgentFiles(modulePath, moduleName);
1105
+
605
1106
  // Dependencies are already included in full module install
606
1107
  }
607
1108
 
@@ -626,7 +1127,7 @@ class Installer {
626
1127
  const targetPath = path.join(agentsDir, fileName);
627
1128
 
628
1129
  if (await fs.pathExists(sourcePath)) {
629
- await fs.copy(sourcePath, targetPath);
1130
+ await this.copyFileWithPlaceholderReplacement(sourcePath, targetPath, this.bmadFolderName || 'bmad');
630
1131
  this.installedFiles.push(targetPath);
631
1132
  }
632
1133
  }
@@ -642,7 +1143,23 @@ class Installer {
642
1143
  const targetPath = path.join(tasksDir, fileName);
643
1144
 
644
1145
  if (await fs.pathExists(sourcePath)) {
645
- await fs.copy(sourcePath, targetPath);
1146
+ await this.copyFileWithPlaceholderReplacement(sourcePath, targetPath, this.bmadFolderName || 'bmad');
1147
+ this.installedFiles.push(targetPath);
1148
+ }
1149
+ }
1150
+ }
1151
+
1152
+ if (files.tools && files.tools.length > 0) {
1153
+ const toolsDir = path.join(targetBase, 'tools');
1154
+ await fs.ensureDir(toolsDir);
1155
+
1156
+ for (const toolPath of files.tools) {
1157
+ const fileName = path.basename(toolPath);
1158
+ const sourcePath = path.join(sourceBase, 'tools', fileName);
1159
+ const targetPath = path.join(toolsDir, fileName);
1160
+
1161
+ if (await fs.pathExists(sourcePath)) {
1162
+ await this.copyFileWithPlaceholderReplacement(sourcePath, targetPath, this.bmadFolderName || 'bmad');
646
1163
  this.installedFiles.push(targetPath);
647
1164
  }
648
1165
  }
@@ -658,7 +1175,7 @@ class Installer {
658
1175
  const targetPath = path.join(templatesDir, fileName);
659
1176
 
660
1177
  if (await fs.pathExists(sourcePath)) {
661
- await fs.copy(sourcePath, targetPath);
1178
+ await this.copyFileWithPlaceholderReplacement(sourcePath, targetPath, this.bmadFolderName || 'bmad');
662
1179
  this.installedFiles.push(targetPath);
663
1180
  }
664
1181
  }
@@ -673,7 +1190,7 @@ class Installer {
673
1190
  await fs.ensureDir(path.dirname(targetPath));
674
1191
 
675
1192
  if (await fs.pathExists(dataPath)) {
676
- await fs.copy(dataPath, targetPath);
1193
+ await this.copyFileWithPlaceholderReplacement(dataPath, targetPath, this.bmadFolderName || 'bmad');
677
1194
  this.installedFiles.push(targetPath);
678
1195
  }
679
1196
  }
@@ -733,9 +1250,8 @@ class Installer {
733
1250
  }
734
1251
  }
735
1252
 
736
- // Copy the file
737
- await fs.ensureDir(path.dirname(targetFile));
738
- await fs.copy(sourceFile, targetFile, { overwrite: true });
1253
+ // Copy the file with placeholder replacement
1254
+ await this.copyFileWithPlaceholderReplacement(sourceFile, targetFile, this.bmadFolderName || 'bmad');
739
1255
 
740
1256
  // Track the installed file
741
1257
  this.installedFiles.push(targetFile);
@@ -771,8 +1287,8 @@ class Installer {
771
1287
  }
772
1288
 
773
1289
  /**
774
- * Process agent files to inject activation block
775
- * @param {string} modulePath - Path to module
1290
+ * Process agent files to build YAML agents and inject activation blocks
1291
+ * @param {string} modulePath - Path to module in bmad/ installation
776
1292
  * @param {string} moduleName - Module name
777
1293
  */
778
1294
  async processAgentFiles(modulePath, moduleName) {
@@ -783,24 +1299,375 @@ class Installer {
783
1299
  return; // No agents to process
784
1300
  }
785
1301
 
1302
+ // Determine project directory (parent of bmad/ directory)
1303
+ const bmadDir = path.dirname(modulePath);
1304
+ const projectDir = path.dirname(bmadDir);
1305
+ const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
1306
+
1307
+ // Ensure _cfg/agents directory exists
1308
+ await fs.ensureDir(cfgAgentsDir);
1309
+
786
1310
  // Get all agent files
787
1311
  const agentFiles = await fs.readdir(agentsPath);
788
1312
 
789
1313
  for (const agentFile of agentFiles) {
790
- if (!agentFile.endsWith('.md')) continue;
1314
+ // Handle YAML agents - build them to .md
1315
+ if (agentFile.endsWith('.agent.yaml')) {
1316
+ const agentName = agentFile.replace('.agent.yaml', '');
1317
+ const yamlPath = path.join(agentsPath, agentFile);
1318
+ const mdPath = path.join(agentsPath, `${agentName}.md`);
1319
+ const customizePath = path.join(cfgAgentsDir, `${moduleName}-${agentName}.customize.yaml`);
1320
+
1321
+ // Create customize template if it doesn't exist
1322
+ if (!(await fs.pathExists(customizePath))) {
1323
+ const genericTemplatePath = getSourcePath('utility', 'templates', 'agent.customize.template.yaml');
1324
+ if (await fs.pathExists(genericTemplatePath)) {
1325
+ await this.copyFileWithPlaceholderReplacement(genericTemplatePath, customizePath, this.bmadFolderName || 'bmad');
1326
+ console.log(chalk.dim(` Created customize: ${moduleName}-${agentName}.customize.yaml`));
1327
+ }
1328
+ }
1329
+
1330
+ // Build YAML + customize to .md
1331
+ const customizeExists = await fs.pathExists(customizePath);
1332
+ const xmlContent = await this.xmlHandler.buildFromYaml(yamlPath, customizeExists ? customizePath : null, {
1333
+ includeMetadata: true,
1334
+ });
1335
+
1336
+ // DO NOT replace {project-root} - LLMs understand this placeholder at runtime
1337
+ // const processedContent = xmlContent.replaceAll('{project-root}', projectDir);
791
1338
 
792
- const agentPath = path.join(agentsPath, agentFile);
793
- let content = await fs.readFile(agentPath, 'utf8');
1339
+ // Write the built .md file to bmad/{module}/agents/ with POSIX-compliant final newline
1340
+ const content = xmlContent.endsWith('\n') ? xmlContent : xmlContent + '\n';
1341
+ await fs.writeFile(mdPath, content, 'utf8');
1342
+ this.installedFiles.push(mdPath);
794
1343
 
795
- // Check if content has agent XML and no activation block
796
- if (content.includes('<agent') && !content.includes('<activation')) {
797
- // Inject the activation block using XML handler
798
- content = this.xmlHandler.injectActivationSimple(content);
799
- await fs.writeFile(agentPath, content, 'utf8');
1344
+ // Remove the source YAML file - we can regenerate from installer source if needed
1345
+ await fs.remove(yamlPath);
1346
+
1347
+ console.log(chalk.dim(` Built agent: ${agentName}.md`));
1348
+ }
1349
+ // Handle legacy .md agents - inject activation if needed
1350
+ else if (agentFile.endsWith('.md')) {
1351
+ const agentPath = path.join(agentsPath, agentFile);
1352
+ let content = await fs.readFile(agentPath, 'utf8');
1353
+
1354
+ // Check if content has agent XML and no activation block
1355
+ if (content.includes('<agent') && !content.includes('<activation')) {
1356
+ // Inject the activation block using XML handler
1357
+ content = this.xmlHandler.injectActivationSimple(content);
1358
+ // Ensure POSIX-compliant final newline
1359
+ const finalContent = content.endsWith('\n') ? content : content + '\n';
1360
+ await fs.writeFile(agentPath, finalContent, 'utf8');
1361
+ }
800
1362
  }
801
1363
  }
802
1364
  }
803
1365
 
1366
+ /**
1367
+ * Build standalone agents in bmad/agents/ directory
1368
+ * @param {string} bmadDir - Path to bmad directory
1369
+ * @param {string} projectDir - Path to project directory
1370
+ */
1371
+ async buildStandaloneAgents(bmadDir, projectDir) {
1372
+ const standaloneAgentsPath = path.join(bmadDir, 'agents');
1373
+ const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
1374
+
1375
+ // Check if standalone agents directory exists
1376
+ if (!(await fs.pathExists(standaloneAgentsPath))) {
1377
+ return;
1378
+ }
1379
+
1380
+ // Get all subdirectories in agents/
1381
+ const agentDirs = await fs.readdir(standaloneAgentsPath, { withFileTypes: true });
1382
+
1383
+ for (const agentDir of agentDirs) {
1384
+ if (!agentDir.isDirectory()) continue;
1385
+
1386
+ const agentDirPath = path.join(standaloneAgentsPath, agentDir.name);
1387
+
1388
+ // Find any .agent.yaml file in the directory
1389
+ const files = await fs.readdir(agentDirPath);
1390
+ const yamlFile = files.find((f) => f.endsWith('.agent.yaml'));
1391
+
1392
+ if (!yamlFile) continue;
1393
+
1394
+ const agentName = path.basename(yamlFile, '.agent.yaml');
1395
+ const sourceYamlPath = path.join(agentDirPath, yamlFile);
1396
+ const targetMdPath = path.join(agentDirPath, `${agentName}.md`);
1397
+ const customizePath = path.join(cfgAgentsDir, `${agentName}.customize.yaml`);
1398
+
1399
+ // Check for customizations
1400
+ const customizeExists = await fs.pathExists(customizePath);
1401
+ let customizedFields = [];
1402
+
1403
+ if (customizeExists) {
1404
+ const customizeContent = await fs.readFile(customizePath, 'utf8');
1405
+ const yaml = require('js-yaml');
1406
+ const customizeYaml = yaml.load(customizeContent);
1407
+
1408
+ // Detect what fields are customized (similar to rebuildAgentFiles)
1409
+ if (customizeYaml) {
1410
+ if (customizeYaml.persona) {
1411
+ for (const [key, value] of Object.entries(customizeYaml.persona)) {
1412
+ if (value !== '' && value !== null && !(Array.isArray(value) && value.length === 0)) {
1413
+ customizedFields.push(`persona.${key}`);
1414
+ }
1415
+ }
1416
+ }
1417
+ if (customizeYaml.agent?.metadata) {
1418
+ for (const [key, value] of Object.entries(customizeYaml.agent.metadata)) {
1419
+ if (value !== '' && value !== null) {
1420
+ customizedFields.push(`metadata.${key}`);
1421
+ }
1422
+ }
1423
+ }
1424
+ if (customizeYaml.critical_actions && customizeYaml.critical_actions.length > 0) {
1425
+ customizedFields.push('critical_actions');
1426
+ }
1427
+ if (customizeYaml.menu && customizeYaml.menu.length > 0) {
1428
+ customizedFields.push('menu');
1429
+ }
1430
+ }
1431
+ }
1432
+
1433
+ // Build YAML to XML .md
1434
+ const xmlContent = await this.xmlHandler.buildFromYaml(sourceYamlPath, customizeExists ? customizePath : null, {
1435
+ includeMetadata: true,
1436
+ });
1437
+
1438
+ // DO NOT replace {project-root} - LLMs understand this placeholder at runtime
1439
+ // const processedContent = xmlContent.replaceAll('{project-root}', projectDir);
1440
+
1441
+ // Write the built .md file with POSIX-compliant final newline
1442
+ const content = xmlContent.endsWith('\n') ? xmlContent : xmlContent + '\n';
1443
+ await fs.writeFile(targetMdPath, content, 'utf8');
1444
+
1445
+ // Display result
1446
+ if (customizedFields.length > 0) {
1447
+ console.log(chalk.dim(` Built standalone agent: ${agentName}.md `) + chalk.yellow(`(customized: ${customizedFields.join(', ')})`));
1448
+ } else {
1449
+ console.log(chalk.dim(` Built standalone agent: ${agentName}.md`));
1450
+ }
1451
+ }
1452
+ }
1453
+
1454
+ /**
1455
+ * Rebuild agent files from installer source (for compile command)
1456
+ * @param {string} modulePath - Path to module in bmad/ installation
1457
+ * @param {string} moduleName - Module name
1458
+ */
1459
+ async rebuildAgentFiles(modulePath, moduleName) {
1460
+ // Get source agents directory from installer
1461
+ const sourceAgentsPath =
1462
+ moduleName === 'core' ? path.join(getModulePath('core'), 'agents') : path.join(getSourcePath(`modules/${moduleName}`), 'agents');
1463
+
1464
+ if (!(await fs.pathExists(sourceAgentsPath))) {
1465
+ return; // No source agents to rebuild
1466
+ }
1467
+
1468
+ // Determine project directory (parent of bmad/ directory)
1469
+ const bmadDir = path.dirname(modulePath);
1470
+ const projectDir = path.dirname(bmadDir);
1471
+ const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
1472
+ const targetAgentsPath = path.join(modulePath, 'agents');
1473
+
1474
+ // Ensure target directory exists
1475
+ await fs.ensureDir(targetAgentsPath);
1476
+
1477
+ // Get all YAML agent files from source
1478
+ const sourceFiles = await fs.readdir(sourceAgentsPath);
1479
+
1480
+ for (const file of sourceFiles) {
1481
+ if (file.endsWith('.agent.yaml')) {
1482
+ const agentName = file.replace('.agent.yaml', '');
1483
+ const sourceYamlPath = path.join(sourceAgentsPath, file);
1484
+ const targetMdPath = path.join(targetAgentsPath, `${agentName}.md`);
1485
+ const customizePath = path.join(cfgAgentsDir, `${moduleName}-${agentName}.customize.yaml`);
1486
+
1487
+ // Check for customizations
1488
+ const customizeExists = await fs.pathExists(customizePath);
1489
+ let customizedFields = [];
1490
+
1491
+ if (customizeExists) {
1492
+ const customizeContent = await fs.readFile(customizePath, 'utf8');
1493
+ const yaml = require('js-yaml');
1494
+ const customizeYaml = yaml.load(customizeContent);
1495
+
1496
+ // Detect what fields are customized
1497
+ if (customizeYaml) {
1498
+ if (customizeYaml.persona) {
1499
+ for (const [key, value] of Object.entries(customizeYaml.persona)) {
1500
+ if (value !== '' && value !== null && !(Array.isArray(value) && value.length === 0)) {
1501
+ customizedFields.push(`persona.${key}`);
1502
+ }
1503
+ }
1504
+ }
1505
+ if (customizeYaml.agent?.metadata) {
1506
+ for (const [key, value] of Object.entries(customizeYaml.agent.metadata)) {
1507
+ if (value !== '' && value !== null) {
1508
+ customizedFields.push(`metadata.${key}`);
1509
+ }
1510
+ }
1511
+ }
1512
+ if (customizeYaml.critical_actions && customizeYaml.critical_actions.length > 0) {
1513
+ customizedFields.push('critical_actions');
1514
+ }
1515
+ if (customizeYaml.memories && customizeYaml.memories.length > 0) {
1516
+ customizedFields.push('memories');
1517
+ }
1518
+ if (customizeYaml.menu && customizeYaml.menu.length > 0) {
1519
+ customizedFields.push('menu');
1520
+ }
1521
+ if (customizeYaml.prompts && customizeYaml.prompts.length > 0) {
1522
+ customizedFields.push('prompts');
1523
+ }
1524
+ }
1525
+ }
1526
+
1527
+ // Build YAML + customize to .md
1528
+ const xmlContent = await this.xmlHandler.buildFromYaml(sourceYamlPath, customizeExists ? customizePath : null, {
1529
+ includeMetadata: true,
1530
+ });
1531
+
1532
+ // DO NOT replace {project-root} - LLMs understand this placeholder at runtime
1533
+ // const processedContent = xmlContent.replaceAll('{project-root}', projectDir);
1534
+
1535
+ // Write the rebuilt .md file with POSIX-compliant final newline
1536
+ const content = xmlContent.endsWith('\n') ? xmlContent : xmlContent + '\n';
1537
+ await fs.writeFile(targetMdPath, content, 'utf8');
1538
+
1539
+ // Display result with customizations if any
1540
+ if (customizedFields.length > 0) {
1541
+ console.log(chalk.dim(` Rebuilt agent: ${agentName}.md `) + chalk.yellow(`(customized: ${customizedFields.join(', ')})`));
1542
+ } else {
1543
+ console.log(chalk.dim(` Rebuilt agent: ${agentName}.md`));
1544
+ }
1545
+ }
1546
+ }
1547
+ }
1548
+
1549
+ /**
1550
+ * Compile/rebuild all agents and tasks for quick updates
1551
+ * @param {Object} config - Compilation configuration
1552
+ * @returns {Object} Compilation results
1553
+ */
1554
+ async compileAgents(config) {
1555
+ const ora = require('ora');
1556
+ const spinner = ora('Starting agent compilation...').start();
1557
+
1558
+ try {
1559
+ const projectDir = path.resolve(config.directory);
1560
+ const bmadDir = await this.findBmadDir(projectDir);
1561
+
1562
+ // Check if bmad directory exists
1563
+ if (!(await fs.pathExists(bmadDir))) {
1564
+ spinner.fail('No BMAD installation found');
1565
+ throw new Error(`BMAD not installed at ${bmadDir}`);
1566
+ }
1567
+
1568
+ let agentCount = 0;
1569
+ let taskCount = 0;
1570
+
1571
+ // Process all modules in bmad directory
1572
+ spinner.text = 'Rebuilding agent files...';
1573
+ const entries = await fs.readdir(bmadDir, { withFileTypes: true });
1574
+
1575
+ for (const entry of entries) {
1576
+ if (entry.isDirectory() && entry.name !== '_cfg' && entry.name !== 'docs') {
1577
+ const modulePath = path.join(bmadDir, entry.name);
1578
+
1579
+ // Special handling for standalone agents in bmad/agents/ directory
1580
+ if (entry.name === 'agents') {
1581
+ spinner.text = 'Building standalone agents...';
1582
+ await this.buildStandaloneAgents(bmadDir, projectDir);
1583
+
1584
+ // Count standalone agents
1585
+ const standaloneAgentsPath = path.join(bmadDir, 'agents');
1586
+ const standaloneAgentDirs = await fs.readdir(standaloneAgentsPath, { withFileTypes: true });
1587
+ for (const agentDir of standaloneAgentDirs) {
1588
+ if (agentDir.isDirectory()) {
1589
+ const agentDirPath = path.join(standaloneAgentsPath, agentDir.name);
1590
+ const agentFiles = await fs.readdir(agentDirPath);
1591
+ agentCount += agentFiles.filter((f) => f.endsWith('.md') && !f.endsWith('.agent.yaml')).length;
1592
+ }
1593
+ }
1594
+ } else {
1595
+ // Rebuild module agents from installer source
1596
+ const agentsPath = path.join(modulePath, 'agents');
1597
+ if (await fs.pathExists(agentsPath)) {
1598
+ await this.rebuildAgentFiles(modulePath, entry.name);
1599
+ const agentFiles = await fs.readdir(agentsPath);
1600
+ agentCount += agentFiles.filter((f) => f.endsWith('.md')).length;
1601
+ }
1602
+
1603
+ // Count tasks (already built)
1604
+ const tasksPath = path.join(modulePath, 'tasks');
1605
+ if (await fs.pathExists(tasksPath)) {
1606
+ const taskFiles = await fs.readdir(tasksPath);
1607
+ taskCount += taskFiles.filter((f) => f.endsWith('.md')).length;
1608
+ }
1609
+ }
1610
+ }
1611
+ }
1612
+
1613
+ // Regenerate manifests after compilation
1614
+ spinner.start('Regenerating manifests...');
1615
+ const installedModules = entries
1616
+ .filter((e) => e.isDirectory() && e.name !== '_cfg' && e.name !== 'docs' && e.name !== 'agents' && e.name !== 'core')
1617
+ .map((e) => e.name);
1618
+ const manifestGen = new ManifestGenerator();
1619
+
1620
+ // Get existing IDE list from manifest
1621
+ const existingManifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml');
1622
+ let existingIdes = [];
1623
+ if (await fs.pathExists(existingManifestPath)) {
1624
+ const manifestContent = await fs.readFile(existingManifestPath, 'utf8');
1625
+ const yaml = require('js-yaml');
1626
+ const manifest = yaml.load(manifestContent);
1627
+ existingIdes = manifest.ides || [];
1628
+ }
1629
+
1630
+ await manifestGen.generateManifests(bmadDir, installedModules, [], {
1631
+ ides: existingIdes,
1632
+ });
1633
+ spinner.succeed('Manifests regenerated');
1634
+
1635
+ // Update IDE configurations using the existing IDE list from manifest
1636
+ if (existingIdes && existingIdes.length > 0) {
1637
+ spinner.start('Updating IDE configurations...');
1638
+
1639
+ for (const ide of existingIdes) {
1640
+ spinner.text = `Updating ${ide}...`;
1641
+
1642
+ // Stop spinner before IDE setup to prevent blocking any potential prompts
1643
+ // However, we pass _alreadyConfigured to skip all prompts during compile
1644
+ spinner.stop();
1645
+
1646
+ await this.ideManager.setup(ide, projectDir, bmadDir, {
1647
+ selectedModules: installedModules,
1648
+ skipModuleInstall: true, // Skip module installation, just update IDE files
1649
+ verbose: config.verbose,
1650
+ preCollectedConfig: { _alreadyConfigured: true }, // Skip all interactive prompts during compile
1651
+ });
1652
+
1653
+ // Restart spinner for next IDE
1654
+ if (existingIdes.indexOf(ide) < existingIdes.length - 1) {
1655
+ spinner.start('Updating IDE configurations...');
1656
+ }
1657
+ }
1658
+
1659
+ console.log(chalk.green('✓ IDE configurations updated'));
1660
+ } else {
1661
+ console.log(chalk.yellow('⚠️ No IDEs configured. Skipping IDE update.'));
1662
+ }
1663
+
1664
+ return { agentCount, taskCount };
1665
+ } catch (error) {
1666
+ spinner.fail('Compilation failed');
1667
+ throw error;
1668
+ }
1669
+ }
1670
+
804
1671
  /**
805
1672
  * Private: Update core
806
1673
  */
@@ -817,6 +1684,131 @@ class Installer {
817
1684
  }
818
1685
  }
819
1686
 
1687
+ /**
1688
+ * Quick update method - preserves all settings and only prompts for new config fields
1689
+ * @param {Object} config - Configuration with directory
1690
+ * @returns {Object} Update result
1691
+ */
1692
+ async quickUpdate(config) {
1693
+ const ora = require('ora');
1694
+ const spinner = ora('Starting quick update...').start();
1695
+
1696
+ try {
1697
+ const projectDir = path.resolve(config.directory);
1698
+ const bmadDir = await this.findBmadDir(projectDir);
1699
+
1700
+ // Check if bmad directory exists
1701
+ if (!(await fs.pathExists(bmadDir))) {
1702
+ spinner.fail('No BMAD installation found');
1703
+ throw new Error(`BMAD not installed at ${bmadDir}. Use regular install for first-time setup.`);
1704
+ }
1705
+
1706
+ spinner.text = 'Detecting installed modules and configuration...';
1707
+
1708
+ // Detect existing installation
1709
+ const existingInstall = await this.detector.detect(bmadDir);
1710
+ const installedModules = existingInstall.modules.map((m) => m.id);
1711
+ const configuredIdes = existingInstall.ides || [];
1712
+
1713
+ // Load saved IDE configurations
1714
+ const savedIdeConfigs = await this.ideConfigManager.loadAllIdeConfigs(bmadDir);
1715
+
1716
+ // Get available modules (what we have source for)
1717
+ const availableModules = await this.moduleManager.listAvailable();
1718
+ const availableModuleIds = new Set(availableModules.map((m) => m.id));
1719
+
1720
+ // Only update modules that are BOTH installed AND available (we have source for)
1721
+ const modulesToUpdate = installedModules.filter((id) => availableModuleIds.has(id));
1722
+ const skippedModules = installedModules.filter((id) => !availableModuleIds.has(id));
1723
+
1724
+ spinner.succeed(`Found ${modulesToUpdate.length} module(s) to update and ${configuredIdes.length} configured tool(s)`);
1725
+
1726
+ if (skippedModules.length > 0) {
1727
+ console.log(chalk.yellow(`⚠️ Skipping ${skippedModules.length} module(s) - no source available: ${skippedModules.join(', ')}`));
1728
+ }
1729
+
1730
+ // Load existing configs and collect new fields (if any)
1731
+ console.log(chalk.cyan('\n📋 Checking for new configuration options...'));
1732
+ await this.configCollector.loadExistingConfig(projectDir);
1733
+
1734
+ let promptedForNewFields = false;
1735
+
1736
+ // Check core config for new fields
1737
+ const corePrompted = await this.configCollector.collectModuleConfigQuick('core', projectDir, true);
1738
+ if (corePrompted) {
1739
+ promptedForNewFields = true;
1740
+ }
1741
+
1742
+ // Check each module we're updating for new fields (NOT skipped modules)
1743
+ for (const moduleName of modulesToUpdate) {
1744
+ const modulePrompted = await this.configCollector.collectModuleConfigQuick(moduleName, projectDir, true);
1745
+ if (modulePrompted) {
1746
+ promptedForNewFields = true;
1747
+ }
1748
+ }
1749
+
1750
+ if (!promptedForNewFields) {
1751
+ console.log(chalk.green('✓ All configuration is up to date, no new options to configure'));
1752
+ }
1753
+
1754
+ // Add metadata
1755
+ this.configCollector.collectedConfig._meta = {
1756
+ version: require(path.join(getProjectRoot(), 'package.json')).version,
1757
+ installDate: new Date().toISOString(),
1758
+ lastModified: new Date().toISOString(),
1759
+ };
1760
+
1761
+ // Check if bmad_folder has changed
1762
+ const existingBmadFolderName = path.basename(bmadDir);
1763
+ const newBmadFolderName = this.configCollector.collectedConfig.core?.bmad_folder || existingBmadFolderName;
1764
+
1765
+ if (existingBmadFolderName === newBmadFolderName) {
1766
+ // Normal quick update - start the spinner
1767
+ spinner.start('Updating BMAD installation...');
1768
+ } else {
1769
+ // Folder name has changed - stop spinner and let install() handle it
1770
+ spinner.stop();
1771
+ console.log(chalk.yellow(`\n⚠️ Folder name will change: ${existingBmadFolderName} → ${newBmadFolderName}`));
1772
+ console.log(chalk.yellow('The installer will handle the folder migration.\n'));
1773
+ }
1774
+
1775
+ // Build the config object for the installer
1776
+ const installConfig = {
1777
+ directory: projectDir,
1778
+ installCore: true,
1779
+ modules: modulesToUpdate, // Only update modules we have source for
1780
+ ides: configuredIdes,
1781
+ skipIde: configuredIdes.length === 0,
1782
+ coreConfig: this.configCollector.collectedConfig.core,
1783
+ actionType: 'install', // Use regular install flow
1784
+ _quickUpdate: true, // Flag to skip certain prompts
1785
+ _preserveModules: skippedModules, // Preserve these in manifest even though we didn't update them
1786
+ _savedIdeConfigs: savedIdeConfigs, // Pass saved IDE configs to installer
1787
+ };
1788
+
1789
+ // Call the standard install method
1790
+ const result = await this.install(installConfig);
1791
+
1792
+ // Only succeed the spinner if it's still spinning
1793
+ // (install method might have stopped it if folder name changed)
1794
+ if (spinner.isSpinning) {
1795
+ spinner.succeed('Quick update complete!');
1796
+ }
1797
+
1798
+ return {
1799
+ success: true,
1800
+ moduleCount: modulesToUpdate.length + 1, // +1 for core
1801
+ hadNewFields: promptedForNewFields,
1802
+ modules: ['core', ...modulesToUpdate],
1803
+ skippedModules: skippedModules,
1804
+ ides: configuredIdes,
1805
+ };
1806
+ } catch (error) {
1807
+ spinner.fail('Quick update failed');
1808
+ throw error;
1809
+ }
1810
+ }
1811
+
820
1812
  /**
821
1813
  * Private: Prompt for update action
822
1814
  */
@@ -837,36 +1829,236 @@ class Installer {
837
1829
  }
838
1830
 
839
1831
  /**
840
- * Private: Create formatted error for legacy BMAD v4 detection
1832
+ * Handle legacy BMAD v4 migration with automatic backup
1833
+ * @param {string} projectDir - Project directory
841
1834
  * @param {Object} legacyV4 - Legacy V4 detection result with offenders array
842
- * @returns {Error} Formatted error with fullMessage property
843
1835
  */
844
- createLegacyV4Error(legacyV4) {
845
- const error = new Error('Legacy BMAD v4 artefacts detected in project. Remove them to continue.');
1836
+ async handleLegacyV4Migration(projectDir, legacyV4) {
1837
+ console.log(chalk.yellow.bold('\n⚠️ Legacy BMAD v4 detected'));
1838
+ console.log(chalk.dim('The installer found legacy artefacts in your project.\n'));
1839
+
1840
+ // Separate .bmad* folders (auto-backup) from other offending paths (manual cleanup)
1841
+ const bmadFolders = legacyV4.offenders.filter((p) => {
1842
+ const name = path.basename(p);
1843
+ return name.startsWith('.bmad'); // Only dot-prefixed folders get auto-backed up
1844
+ });
1845
+ const otherOffenders = legacyV4.offenders.filter((p) => {
1846
+ const name = path.basename(p);
1847
+ return !name.startsWith('.bmad'); // Everything else is manual cleanup
1848
+ });
846
1849
 
847
- // Build the complete formatted message using template literals
848
- const headerMessage = `
849
- ${chalk.red.bold('Blocked: Legacy BMAD v4 detected')}
850
- The installer found legacy artefacts in your project.`;
1850
+ const inquirer = require('inquirer');
851
1851
 
852
- const offendersMessage = `
853
- Offending paths:
854
- ${legacyV4.offenders.map((p) => ` - ${p}`).join('\n')}
1852
+ // Show warning for other offending paths FIRST
1853
+ if (otherOffenders.length > 0) {
1854
+ console.log(chalk.yellow('⚠️ Recommended cleanup:'));
1855
+ console.log(chalk.dim('It is recommended to remove the following items before proceeding:\n'));
1856
+ for (const p of otherOffenders) console.log(chalk.dim(` - ${p}`));
855
1857
 
856
- Cleanup commands you can copy/paste:
857
- ${chalk.cyan('macOS/Linux:')}
858
- ${legacyV4.offenders.map((p) => ` rm -rf '${p}'`).join('\n')}
859
- ${chalk.cyan('Windows:')}
860
- ${legacyV4.offenders.map((p) => ` rmdir /S /Q "${p}"`).join('\n')}`;
1858
+ console.log(chalk.cyan('\nCleanup commands you can copy/paste:'));
1859
+ console.log(chalk.dim('macOS/Linux:'));
1860
+ for (const p of otherOffenders) console.log(chalk.dim(` rm -rf '${p}'`));
1861
+ console.log(chalk.dim('Windows:'));
1862
+ for (const p of otherOffenders) console.log(chalk.dim(` rmdir /S /Q "${p}"`));
861
1863
 
862
- const footerMessage = `
863
- Remove the listed paths (case sensitive) and rerun install.
864
- Note: You may also want to remove other BMAD-related v4 files/folders left over in this project. If you have customizations, back them up or migrate them before deleting.`;
1864
+ const { cleanedUp } = await inquirer.prompt([
1865
+ {
1866
+ type: 'confirm',
1867
+ name: 'cleanedUp',
1868
+ message: 'Have you completed the recommended cleanup? (You can proceed without it, but it is recommended)',
1869
+ default: false,
1870
+ },
1871
+ ]);
865
1872
 
866
- // Attach the complete formatted message
867
- error.fullMessage = headerMessage + offendersMessage + footerMessage;
1873
+ if (cleanedUp) {
1874
+ console.log(chalk.green('✓ Cleanup acknowledged\n'));
1875
+ } else {
1876
+ console.log(chalk.yellow('⚠️ Proceeding without recommended cleanup\n'));
1877
+ }
1878
+ }
1879
+
1880
+ // Handle .bmad* folders with automatic backup
1881
+ if (bmadFolders.length > 0) {
1882
+ console.log(chalk.cyan('The following legacy folders will be moved to v4-backup:'));
1883
+ for (const p of bmadFolders) console.log(chalk.dim(` - ${p}`));
1884
+
1885
+ const { proceed } = await inquirer.prompt([
1886
+ {
1887
+ type: 'confirm',
1888
+ name: 'proceed',
1889
+ message: 'Proceed with backing up legacy v4 folders?',
1890
+ default: true,
1891
+ },
1892
+ ]);
868
1893
 
869
- return error;
1894
+ if (proceed) {
1895
+ const backupDir = path.join(projectDir, 'v4-backup');
1896
+ await fs.ensureDir(backupDir);
1897
+
1898
+ for (const folder of bmadFolders) {
1899
+ const folderName = path.basename(folder);
1900
+ const backupPath = path.join(backupDir, folderName);
1901
+
1902
+ // If backup already exists, add timestamp
1903
+ let finalBackupPath = backupPath;
1904
+ if (await fs.pathExists(backupPath)) {
1905
+ const timestamp = new Date().toISOString().replaceAll(/[:.]/g, '-').split('T')[0];
1906
+ finalBackupPath = path.join(backupDir, `${folderName}-${timestamp}`);
1907
+ }
1908
+
1909
+ await fs.move(folder, finalBackupPath, { overwrite: false });
1910
+ console.log(chalk.green(`✓ Moved ${folderName} to ${path.relative(projectDir, finalBackupPath)}`));
1911
+ }
1912
+ } else {
1913
+ throw new Error('Installation cancelled by user');
1914
+ }
1915
+ }
1916
+ }
1917
+
1918
+ /**
1919
+ * Read files-manifest.csv
1920
+ * @param {string} bmadDir - BMAD installation directory
1921
+ * @returns {Array} Array of file entries from files-manifest.csv
1922
+ */
1923
+ async readFilesManifest(bmadDir) {
1924
+ const filesManifestPath = path.join(bmadDir, '_cfg', 'files-manifest.csv');
1925
+ if (!(await fs.pathExists(filesManifestPath))) {
1926
+ return [];
1927
+ }
1928
+
1929
+ try {
1930
+ const content = await fs.readFile(filesManifestPath, 'utf8');
1931
+ const lines = content.split('\n');
1932
+ const files = [];
1933
+
1934
+ for (let i = 1; i < lines.length; i++) {
1935
+ // Skip header
1936
+ const line = lines[i].trim();
1937
+ if (!line) continue;
1938
+
1939
+ // Parse CSV line properly handling quoted values
1940
+ const parts = [];
1941
+ let current = '';
1942
+ let inQuotes = false;
1943
+
1944
+ for (const char of line) {
1945
+ if (char === '"') {
1946
+ inQuotes = !inQuotes;
1947
+ } else if (char === ',' && !inQuotes) {
1948
+ parts.push(current);
1949
+ current = '';
1950
+ } else {
1951
+ current += char;
1952
+ }
1953
+ }
1954
+ parts.push(current); // Add last part
1955
+
1956
+ if (parts.length >= 4) {
1957
+ files.push({
1958
+ type: parts[0],
1959
+ name: parts[1],
1960
+ module: parts[2],
1961
+ path: parts[3],
1962
+ hash: parts[4] || null, // Hash may not exist in old manifests
1963
+ });
1964
+ }
1965
+ }
1966
+
1967
+ return files;
1968
+ } catch (error) {
1969
+ console.warn('Warning: Could not read files-manifest.csv:', error.message);
1970
+ return [];
1971
+ }
1972
+ }
1973
+
1974
+ /**
1975
+ * Detect custom and modified files
1976
+ * @param {string} bmadDir - BMAD installation directory
1977
+ * @param {Array} existingFilesManifest - Previous files from files-manifest.csv
1978
+ * @returns {Object} Object with customFiles and modifiedFiles arrays
1979
+ */
1980
+ async detectCustomFiles(bmadDir, existingFilesManifest) {
1981
+ const customFiles = [];
1982
+ const modifiedFiles = [];
1983
+
1984
+ // Check if the manifest has hashes - if not, we can't detect modifications
1985
+ let manifestHasHashes = false;
1986
+ if (existingFilesManifest && existingFilesManifest.length > 0) {
1987
+ manifestHasHashes = existingFilesManifest.some((f) => f.hash);
1988
+ }
1989
+
1990
+ // Build map of previously installed files from files-manifest.csv with their hashes
1991
+ const installedFilesMap = new Map();
1992
+ for (const fileEntry of existingFilesManifest) {
1993
+ if (fileEntry.path) {
1994
+ // Files in manifest are stored as relative paths starting with 'bmad/'
1995
+ // Convert to absolute path
1996
+ const relativePath = fileEntry.path.startsWith('bmad/') ? fileEntry.path.slice(5) : fileEntry.path;
1997
+ const absolutePath = path.join(bmadDir, relativePath);
1998
+ installedFilesMap.set(path.normalize(absolutePath), {
1999
+ hash: fileEntry.hash,
2000
+ relativePath: relativePath,
2001
+ });
2002
+ }
2003
+ }
2004
+
2005
+ // Recursively scan bmadDir for all files
2006
+ const scanDirectory = async (dir) => {
2007
+ try {
2008
+ const entries = await fs.readdir(dir, { withFileTypes: true });
2009
+ for (const entry of entries) {
2010
+ const fullPath = path.join(dir, entry.name);
2011
+
2012
+ if (entry.isDirectory()) {
2013
+ // Skip certain directories
2014
+ if (entry.name === 'node_modules' || entry.name === '.git') {
2015
+ continue;
2016
+ }
2017
+ await scanDirectory(fullPath);
2018
+ } else if (entry.isFile()) {
2019
+ const normalizedPath = path.normalize(fullPath);
2020
+ const fileInfo = installedFilesMap.get(normalizedPath);
2021
+
2022
+ // Skip certain system files that are auto-generated
2023
+ const relativePath = path.relative(bmadDir, fullPath);
2024
+ const fileName = path.basename(fullPath);
2025
+
2026
+ // Skip _cfg directory - system files
2027
+ if (relativePath.startsWith('_cfg/') || relativePath.startsWith('_cfg\\')) {
2028
+ continue;
2029
+ }
2030
+
2031
+ // Skip config.yaml files - these are regenerated on each install/update
2032
+ // Users should use _cfg/agents/ override files instead
2033
+ if (fileName === 'config.yaml') {
2034
+ continue;
2035
+ }
2036
+
2037
+ if (!fileInfo) {
2038
+ // File not in manifest = custom file
2039
+ customFiles.push(fullPath);
2040
+ } else if (manifestHasHashes && fileInfo.hash) {
2041
+ // File in manifest with hash - check if it was modified
2042
+ const currentHash = await this.manifest.calculateFileHash(fullPath);
2043
+ if (currentHash && currentHash !== fileInfo.hash) {
2044
+ // Hash changed = file was modified
2045
+ modifiedFiles.push({
2046
+ path: fullPath,
2047
+ relativePath: fileInfo.relativePath,
2048
+ });
2049
+ }
2050
+ }
2051
+ // If manifest doesn't have hashes, we can't detect modifications
2052
+ // so we just skip files that are in the manifest
2053
+ }
2054
+ }
2055
+ } catch {
2056
+ // Ignore errors scanning directories
2057
+ }
2058
+ };
2059
+
2060
+ await scanDirectory(bmadDir);
2061
+ return { customFiles, modifiedFiles };
870
2062
  }
871
2063
 
872
2064
  /**
@@ -981,7 +2173,13 @@ Note: You may also want to remove other BMAD-related v4 files/folders left over
981
2173
 
982
2174
  configContent += processedTemplate;
983
2175
 
2176
+ // Ensure POSIX-compliant final newline
2177
+ if (!configContent.endsWith('\n')) {
2178
+ configContent += '\n';
2179
+ }
2180
+
984
2181
  await fs.writeFile(configPath, configContent, 'utf8');
2182
+ this.installedFiles.push(configPath); // Track agent config files
985
2183
  createdCount++;
986
2184
  }
987
2185
 
@@ -997,7 +2195,7 @@ Note: You may also want to remove other BMAD-related v4 files/folders left over
997
2195
  * @param {Array} agentDetails - Array of agent details
998
2196
  */
999
2197
  async generateAgentManifest(bmadDir, agentDetails) {
1000
- const manifestPath = path.join(bmadDir, '_cfg', 'agent-party.xml');
2198
+ const manifestPath = path.join(bmadDir, '_cfg', 'agent-manifest.csv');
1001
2199
  await AgentPartyGenerator.writeAgentParty(manifestPath, agentDetails, { forWeb: false });
1002
2200
  }
1003
2201
 
@@ -1061,7 +2259,7 @@ Note: You may also want to remove other BMAD-related v4 files/folders left over
1061
2259
  const targetDocPath = path.join(docsDir, `${ide}-instructions.md`);
1062
2260
 
1063
2261
  if (await fs.pathExists(sourceDocPath)) {
1064
- await fs.copy(sourceDocPath, targetDocPath, { overwrite: true });
2262
+ await this.copyFileWithPlaceholderReplacement(sourceDocPath, targetDocPath, this.bmadFolderName || 'bmad');
1065
2263
  }
1066
2264
  }
1067
2265
  }