bmad-method 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/.github/FUNDING.yaml +15 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
  4. package/.github/workflows/discord.yaml +25 -0
  5. package/.github/workflows/format-check.yaml +42 -0
  6. package/.github/workflows/manual-release.yaml +173 -0
  7. package/.husky/pre-commit +3 -2
  8. package/.vscode/settings.json +67 -74
  9. package/CHANGELOG.md +564 -19
  10. package/CONTRIBUTING.md +168 -5
  11. package/LICENSE +1 -1
  12. package/README.md +146 -218
  13. package/bmad-core/agent-teams/team-all.yaml +14 -0
  14. package/bmad-core/agent-teams/team-fullstack.yaml +18 -0
  15. package/bmad-core/agent-teams/team-ide-minimal.yaml +10 -0
  16. package/bmad-core/agent-teams/team-no-ui.yaml +13 -0
  17. package/bmad-core/agents/analyst.md +81 -0
  18. package/bmad-core/agents/architect.md +83 -0
  19. package/bmad-core/agents/bmad-master.md +107 -0
  20. package/bmad-core/agents/bmad-orchestrator.md +149 -0
  21. package/bmad-core/agents/dev.md +75 -0
  22. package/bmad-core/agents/pm.md +81 -0
  23. package/bmad-core/agents/po.md +76 -0
  24. package/bmad-core/agents/qa.md +88 -0
  25. package/bmad-core/agents/sm.md +62 -0
  26. package/bmad-core/agents/ux-expert.md +66 -0
  27. package/{.bmad-core → bmad-core}/checklists/architect-checklist.md +0 -5
  28. package/{.bmad-core → bmad-core}/checklists/change-checklist.md +2 -2
  29. package/{.bmad-core → bmad-core}/checklists/pm-checklist.md +0 -5
  30. package/{.bmad-core → bmad-core}/checklists/po-master-checklist.md +0 -9
  31. package/{.bmad-core → bmad-core}/checklists/story-dod-checklist.md +0 -7
  32. package/{.bmad-core → bmad-core}/checklists/story-draft-checklist.md +1 -4
  33. package/bmad-core/core-config.yaml +20 -0
  34. package/bmad-core/data/bmad-kb.md +806 -0
  35. package/bmad-core/data/brainstorming-techniques.md +36 -0
  36. package/bmad-core/data/elicitation-methods.md +154 -0
  37. package/bmad-core/data/test-levels-framework.md +146 -0
  38. package/bmad-core/data/test-priorities-matrix.md +172 -0
  39. package/bmad-core/tasks/advanced-elicitation.md +117 -0
  40. package/{.bmad-core → bmad-core}/tasks/correct-course.md +9 -12
  41. package/bmad-core/tasks/create-brownfield-story.md +312 -0
  42. package/{.bmad-core → bmad-core}/tasks/create-deep-research-prompt.md +4 -27
  43. package/bmad-core/tasks/create-next-story.md +112 -0
  44. package/bmad-core/tasks/document-project.md +343 -0
  45. package/bmad-core/tasks/facilitate-brainstorming-session.md +136 -0
  46. package/bmad-core/tasks/generate-ai-frontend-prompt.md +51 -0
  47. package/{.bmad-core → bmad-core}/tasks/index-docs.md +3 -13
  48. package/bmad-core/tasks/kb-mode-interaction.md +75 -0
  49. package/bmad-core/tasks/nfr-assess.md +343 -0
  50. package/bmad-core/tasks/qa-gate.md +159 -0
  51. package/bmad-core/tasks/review-story.md +314 -0
  52. package/bmad-core/tasks/risk-profile.md +353 -0
  53. package/{.bmad-core → bmad-core}/tasks/shard-doc.md +27 -15
  54. package/bmad-core/tasks/test-design.md +174 -0
  55. package/bmad-core/tasks/trace-requirements.md +264 -0
  56. package/bmad-core/tasks/validate-next-story.md +134 -0
  57. package/bmad-core/templates/architecture-tmpl.yaml +650 -0
  58. package/bmad-core/templates/brainstorming-output-tmpl.yaml +156 -0
  59. package/bmad-core/templates/brownfield-architecture-tmpl.yaml +476 -0
  60. package/bmad-core/templates/brownfield-prd-tmpl.yaml +280 -0
  61. package/bmad-core/templates/competitor-analysis-tmpl.yaml +306 -0
  62. package/bmad-core/templates/front-end-architecture-tmpl.yaml +218 -0
  63. package/bmad-core/templates/front-end-spec-tmpl.yaml +349 -0
  64. package/bmad-core/templates/fullstack-architecture-tmpl.yaml +823 -0
  65. package/bmad-core/templates/market-research-tmpl.yaml +252 -0
  66. package/bmad-core/templates/prd-tmpl.yaml +202 -0
  67. package/bmad-core/templates/project-brief-tmpl.yaml +221 -0
  68. package/bmad-core/templates/qa-gate-tmpl.yaml +102 -0
  69. package/bmad-core/templates/story-tmpl.yaml +137 -0
  70. package/bmad-core/workflows/brownfield-fullstack.yaml +297 -0
  71. package/bmad-core/workflows/brownfield-service.yaml +187 -0
  72. package/bmad-core/workflows/brownfield-ui.yaml +197 -0
  73. package/{.bmad-core/workflows/greenfield-fullstack.yml → bmad-core/workflows/greenfield-fullstack.yaml} +140 -77
  74. package/bmad-core/workflows/greenfield-service.yaml +206 -0
  75. package/bmad-core/workflows/greenfield-ui.yaml +235 -0
  76. package/common/tasks/create-doc.md +101 -0
  77. package/{.bmad-core → common}/tasks/execute-checklist.md +2 -13
  78. package/common/utils/bmad-doc-template.md +325 -0
  79. package/common/utils/workflow-management.md +69 -0
  80. package/dist/agents/analyst.txt +2889 -0
  81. package/dist/agents/architect.txt +3552 -0
  82. package/dist/agents/bmad-master.txt +8769 -0
  83. package/dist/agents/bmad-orchestrator.txt +1513 -0
  84. package/dist/agents/dev.txt +414 -0
  85. package/{.bmad-core/web-bundles → dist}/agents/pm.txt +668 -1119
  86. package/{.bmad-core/web-bundles → dist}/agents/po.txt +341 -484
  87. package/dist/agents/qa.txt +1987 -0
  88. package/dist/agents/sm.txt +658 -0
  89. package/dist/agents/ux-expert.txt +694 -0
  90. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +2371 -0
  91. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +1620 -0
  92. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +815 -0
  93. package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +10952 -0
  94. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.txt +4012 -0
  95. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.txt +3698 -0
  96. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.txt +450 -0
  97. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.txt +973 -0
  98. package/dist/expansion-packs/bmad-2d-unity-game-dev/teams/unity-2d-game-team.txt +15376 -0
  99. package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +2075 -0
  100. package/dist/teams/team-all.txt +12682 -0
  101. package/dist/teams/team-fullstack.txt +10421 -0
  102. package/dist/teams/team-ide-minimal.txt +5103 -0
  103. package/dist/teams/team-no-ui.txt +8980 -0
  104. package/docs/GUIDING-PRINCIPLES.md +91 -0
  105. package/docs/core-architecture.md +219 -0
  106. package/docs/enhanced-ide-development-workflow.md +248 -0
  107. package/docs/expansion-packs.md +280 -0
  108. package/docs/how-to-contribute-with-pull-requests.md +158 -0
  109. package/docs/user-guide.md +504 -0
  110. package/docs/versioning-and-releases.md +8 -16
  111. package/docs/versions.md +4 -5
  112. package/docs/working-in-the-brownfield.md +597 -0
  113. package/eslint.config.mjs +119 -0
  114. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/Complete AI Agent System - Flowchart.svg +102 -0
  115. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.1 Google Cloud Project Setup/1.1.1 - Initial Project Configuration - bash copy.txt +13 -0
  116. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.1 Google Cloud Project Setup/1.1.1 - Initial Project Configuration - bash.txt +13 -0
  117. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.2 Agent Development Kit Installation/1.2.2 - Basic Project Structure - txt.txt +25 -0
  118. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.3 Core Configuration Files/1.3.1 - settings.py +34 -0
  119. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.3 Core Configuration Files/1.3.2 - main.py - Base Application.py +70 -0
  120. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.4 Deployment Configuration/1.4.2 - cloudbuild.yaml +26 -0
  121. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/README.md +109 -0
  122. package/expansion-packs/README.md +2 -112
  123. package/expansion-packs/bmad-2d-phaser-game-dev/agent-teams/phaser-2d-nodejs-game-team.yaml +13 -0
  124. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.md +71 -0
  125. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.md +78 -0
  126. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.md +64 -0
  127. package/expansion-packs/bmad-2d-phaser-game-dev/checklists/game-design-checklist.md +201 -0
  128. package/expansion-packs/bmad-2d-phaser-game-dev/checklists/game-story-dod-checklist.md +160 -0
  129. package/expansion-packs/bmad-2d-phaser-game-dev/config.yaml +8 -0
  130. package/expansion-packs/bmad-2d-phaser-game-dev/data/bmad-kb.md +250 -0
  131. package/expansion-packs/bmad-2d-phaser-game-dev/data/development-guidelines.md +647 -0
  132. package/expansion-packs/bmad-2d-phaser-game-dev/tasks/advanced-elicitation.md +110 -0
  133. package/expansion-packs/bmad-2d-phaser-game-dev/tasks/create-game-story.md +216 -0
  134. package/expansion-packs/bmad-2d-phaser-game-dev/tasks/game-design-brainstorming.md +290 -0
  135. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-architecture-tmpl.yaml +613 -0
  136. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-brief-tmpl.yaml +356 -0
  137. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-design-doc-tmpl.yaml +343 -0
  138. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-story-tmpl.yaml +253 -0
  139. package/expansion-packs/bmad-2d-phaser-game-dev/templates/level-design-doc-tmpl.yaml +484 -0
  140. package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-dev-greenfield.yaml +183 -0
  141. package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-prototype.yaml +175 -0
  142. package/expansion-packs/bmad-2d-unity-game-dev/agent-teams/unity-2d-game-team.yaml +14 -0
  143. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.md +80 -0
  144. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.md +77 -0
  145. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.md +78 -0
  146. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.md +65 -0
  147. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-architect-checklist.md +391 -0
  148. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-change-checklist.md +203 -0
  149. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-design-checklist.md +201 -0
  150. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-story-dod-checklist.md +124 -0
  151. package/expansion-packs/bmad-2d-unity-game-dev/config.yaml +6 -0
  152. package/expansion-packs/bmad-2d-unity-game-dev/data/bmad-kb.md +769 -0
  153. package/expansion-packs/bmad-2d-unity-game-dev/data/development-guidelines.md +586 -0
  154. package/expansion-packs/bmad-2d-unity-game-dev/tasks/advanced-elicitation.md +110 -0
  155. package/expansion-packs/bmad-2d-unity-game-dev/tasks/correct-course-game.md +141 -0
  156. package/expansion-packs/bmad-2d-unity-game-dev/tasks/create-game-story.md +184 -0
  157. package/expansion-packs/bmad-2d-unity-game-dev/tasks/game-design-brainstorming.md +290 -0
  158. package/expansion-packs/bmad-2d-unity-game-dev/tasks/validate-game-story.md +200 -0
  159. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-architecture-tmpl.yaml +1030 -0
  160. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-brief-tmpl.yaml +356 -0
  161. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-design-doc-tmpl.yaml +705 -0
  162. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-story-tmpl.yaml +256 -0
  163. package/expansion-packs/bmad-2d-unity-game-dev/templates/level-design-doc-tmpl.yaml +484 -0
  164. package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-dev-greenfield.yaml +183 -0
  165. package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-prototype.yaml +175 -0
  166. package/expansion-packs/{infrastructure-devops → bmad-infrastructure-devops}/README.md +9 -9
  167. package/expansion-packs/{infrastructure-devops → bmad-infrastructure-devops}/agents/infra-devops-platform.md +30 -18
  168. package/expansion-packs/{infrastructure-devops → bmad-infrastructure-devops}/checklists/infrastructure-checklist.md +1 -1
  169. package/expansion-packs/bmad-infrastructure-devops/config.yaml +9 -0
  170. package/expansion-packs/bmad-infrastructure-devops/data/bmad-kb.md +305 -0
  171. package/expansion-packs/{infrastructure-devops → bmad-infrastructure-devops}/tasks/review-infrastructure.md +4 -5
  172. package/expansion-packs/{infrastructure-devops → bmad-infrastructure-devops}/tasks/validate-infrastructure.md +4 -5
  173. package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-architecture-tmpl.yaml +424 -0
  174. package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.yaml +629 -0
  175. package/package.json +74 -42
  176. package/prettier.config.mjs +32 -0
  177. package/release_notes.md +25 -0
  178. package/tools/bmad-npx-wrapper.js +13 -15
  179. package/tools/builders/web-builder.js +544 -15
  180. package/tools/bump-all-versions.js +115 -0
  181. package/tools/bump-expansion-version.js +90 -0
  182. package/tools/cli.js +65 -32
  183. package/tools/flattener/aggregate.js +76 -0
  184. package/tools/flattener/binary.js +80 -0
  185. package/tools/flattener/discovery.js +71 -0
  186. package/tools/flattener/files.js +35 -0
  187. package/tools/flattener/ignoreRules.js +176 -0
  188. package/tools/flattener/main.js +573 -0
  189. package/tools/flattener/projectRoot.js +206 -0
  190. package/tools/flattener/prompts.js +44 -0
  191. package/tools/flattener/stats.helpers.js +395 -0
  192. package/tools/flattener/stats.js +80 -0
  193. package/tools/flattener/test-matrix.js +413 -0
  194. package/tools/flattener/xml.js +88 -0
  195. package/tools/installer/README.md +3 -53
  196. package/tools/installer/bin/bmad.js +475 -90
  197. package/tools/installer/config/ide-agent-config.yaml +58 -0
  198. package/tools/installer/config/install.config.yaml +123 -0
  199. package/tools/installer/lib/config-loader.js +208 -40
  200. package/tools/installer/lib/file-manager.js +258 -55
  201. package/tools/installer/lib/ide-base-setup.js +228 -0
  202. package/tools/installer/lib/ide-setup.js +1265 -253
  203. package/tools/installer/lib/installer.js +1651 -310
  204. package/tools/installer/lib/memory-profiler.js +225 -0
  205. package/tools/installer/lib/module-manager.js +114 -0
  206. package/tools/installer/lib/resource-locator.js +308 -0
  207. package/tools/installer/package.json +25 -24
  208. package/tools/lib/dependency-resolver.js +44 -48
  209. package/tools/lib/yaml-utils.js +29 -0
  210. package/tools/md-assets/web-agent-startup-instructions.md +39 -0
  211. package/tools/preview-release-notes.js +66 -0
  212. package/tools/shared/bannerArt.js +105 -0
  213. package/tools/sync-installer-version.js +7 -9
  214. package/tools/update-expansion-version.js +53 -0
  215. package/tools/upgraders/v3-to-v4-upgrader.js +221 -320
  216. package/tools/version-bump.js +42 -27
  217. package/tools/yaml-format.js +57 -44
  218. package/.bmad-core/agent-teams/team-all.yml +0 -16
  219. package/.bmad-core/agent-teams/team-fullstack.yml +0 -26
  220. package/.bmad-core/agent-teams/team-no-ui.yml +0 -15
  221. package/.bmad-core/agents/analyst.md +0 -59
  222. package/.bmad-core/agents/architect.md +0 -66
  223. package/.bmad-core/agents/bmad-master.md +0 -104
  224. package/.bmad-core/agents/bmad-orchestrator.md +0 -81
  225. package/.bmad-core/agents/dev.md +0 -70
  226. package/.bmad-core/agents/pm.md +0 -59
  227. package/.bmad-core/agents/po.md +0 -60
  228. package/.bmad-core/agents/qa.md +0 -52
  229. package/.bmad-core/agents/sm.md +0 -55
  230. package/.bmad-core/agents/ux-expert.md +0 -66
  231. package/.bmad-core/data/bmad-kb.md +0 -47
  232. package/.bmad-core/schemas/agent-team-schema.yml +0 -153
  233. package/.bmad-core/tasks/advanced-elicitation.md +0 -92
  234. package/.bmad-core/tasks/brainstorming-techniques.md +0 -238
  235. package/.bmad-core/tasks/core-dump.md +0 -74
  236. package/.bmad-core/tasks/create-agent.md +0 -202
  237. package/.bmad-core/tasks/create-doc.md +0 -74
  238. package/.bmad-core/tasks/create-expansion-pack.md +0 -425
  239. package/.bmad-core/tasks/create-next-story.md +0 -206
  240. package/.bmad-core/tasks/create-team.md +0 -229
  241. package/.bmad-core/tasks/doc-migration-task.md +0 -143
  242. package/.bmad-core/tasks/generate-ai-frontend-prompt.md +0 -58
  243. package/.bmad-core/templates/agent-tmpl.md +0 -58
  244. package/.bmad-core/templates/architecture-tmpl.md +0 -771
  245. package/.bmad-core/templates/brownfield-architecture-tmpl.md +0 -542
  246. package/.bmad-core/templates/brownfield-prd-tmpl.md +0 -240
  247. package/.bmad-core/templates/competitor-analysis-tmpl.md +0 -289
  248. package/.bmad-core/templates/expansion-pack-plan-tmpl.md +0 -91
  249. package/.bmad-core/templates/front-end-architecture-tmpl.md +0 -173
  250. package/.bmad-core/templates/front-end-spec-tmpl.md +0 -411
  251. package/.bmad-core/templates/fullstack-architecture-tmpl.md +0 -1016
  252. package/.bmad-core/templates/market-research-tmpl.md +0 -261
  253. package/.bmad-core/templates/prd-tmpl.md +0 -200
  254. package/.bmad-core/templates/project-brief-tmpl.md +0 -228
  255. package/.bmad-core/templates/simple-project-prd-tmpl.md +0 -461
  256. package/.bmad-core/templates/story-tmpl.md +0 -61
  257. package/.bmad-core/templates/web-agent-startup-instructions-template.md +0 -39
  258. package/.bmad-core/utils/agent-switcher.ide.md +0 -112
  259. package/.bmad-core/utils/template-format.md +0 -26
  260. package/.bmad-core/utils/workflow-management.md +0 -224
  261. package/.bmad-core/web-bundles/agents/analyst.txt +0 -1684
  262. package/.bmad-core/web-bundles/agents/architect.txt +0 -3584
  263. package/.bmad-core/web-bundles/agents/bmad-master.txt +0 -9491
  264. package/.bmad-core/web-bundles/agents/bmad-orchestrator.txt +0 -1466
  265. package/.bmad-core/web-bundles/agents/dev.txt +0 -316
  266. package/.bmad-core/web-bundles/agents/qa.txt +0 -129
  267. package/.bmad-core/web-bundles/agents/sm.txt +0 -658
  268. package/.bmad-core/web-bundles/agents/ux-expert.txt +0 -1099
  269. package/.bmad-core/web-bundles/teams/team-all.txt +0 -10757
  270. package/.bmad-core/web-bundles/teams/team-fullstack.txt +0 -10109
  271. package/.bmad-core/web-bundles/teams/team-no-ui.txt +0 -8950
  272. package/.bmad-core/workflows/brownfield-fullstack.yml +0 -116
  273. package/.bmad-core/workflows/brownfield-service.yml +0 -117
  274. package/.bmad-core/workflows/brownfield-ui.yml +0 -127
  275. package/.bmad-core/workflows/greenfield-service.yml +0 -143
  276. package/.bmad-core/workflows/greenfield-ui.yml +0 -172
  277. package/.claude/commands/analyst.md +0 -63
  278. package/.claude/commands/architect.md +0 -70
  279. package/.claude/commands/bmad-master.md +0 -108
  280. package/.claude/commands/bmad-orchestrator.md +0 -85
  281. package/.claude/commands/dev.md +0 -74
  282. package/.claude/commands/pm.md +0 -63
  283. package/.claude/commands/po.md +0 -64
  284. package/.claude/commands/qa.md +0 -56
  285. package/.claude/commands/sm.md +0 -59
  286. package/.claude/commands/ux-expert.md +0 -70
  287. package/.cursor/rules/analyst.mdc +0 -77
  288. package/.cursor/rules/architect.mdc +0 -84
  289. package/.cursor/rules/bmad-master.mdc +0 -122
  290. package/.cursor/rules/bmad-orchestrator.mdc +0 -99
  291. package/.cursor/rules/dev.mdc +0 -88
  292. package/.cursor/rules/pm.mdc +0 -77
  293. package/.cursor/rules/po.mdc +0 -78
  294. package/.cursor/rules/qa.mdc +0 -70
  295. package/.cursor/rules/sm.mdc +0 -73
  296. package/.cursor/rules/ux-expert.mdc +0 -84
  297. package/.github/workflows/release.yml +0 -59
  298. package/.releaserc.json +0 -18
  299. package/.roo/.roomodes +0 -95
  300. package/.roo/README.md +0 -38
  301. package/.vscode/extensions.json +0 -6
  302. package/.windsurf/rules/analyst.md +0 -71
  303. package/.windsurf/rules/architect.md +0 -78
  304. package/.windsurf/rules/bmad-master.md +0 -116
  305. package/.windsurf/rules/bmad-orchestrator.md +0 -93
  306. package/.windsurf/rules/dev.md +0 -82
  307. package/.windsurf/rules/pm.md +0 -71
  308. package/.windsurf/rules/po.md +0 -72
  309. package/.windsurf/rules/qa.md +0 -64
  310. package/.windsurf/rules/sm.md +0 -67
  311. package/.windsurf/rules/ux-expert.md +0 -78
  312. package/docs/bmad-workflow-guide.md +0 -161
  313. package/docs/claude-code-guide.md +0 -119
  314. package/docs/cursor-guide.md +0 -127
  315. package/docs/roo-code-guide.md +0 -140
  316. package/docs/sample-output/simple-fullstack-greenfield/prd.md +0 -42
  317. package/docs/windsurf-guide.md +0 -127
  318. package/expansion-packs/infrastructure-devops/manifest.yml +0 -38
  319. package/expansion-packs/infrastructure-devops/templates/infrastructure-architecture-tmpl.md +0 -415
  320. package/expansion-packs/infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.md +0 -0
  321. package/tools/installer/config/install.config.yml +0 -139
  322. package/tools/installer/package-lock.json +0 -906
  323. package/tools/installer/templates/claude-commands.md +0 -7
  324. package/tools/installer/templates/cursor-rules.md +0 -22
  325. package/tools/installer/templates/windsurf-rules.md +0 -22
  326. package/tools/semantic-release-sync-installer.js +0 -31
  327. /package/{.bmad-core → bmad-core}/data/technical-preferences.md +0 -0
  328. /package/{.bmad-core → bmad-core}/tasks/brownfield-create-epic.md +0 -0
  329. /package/{.bmad-core → bmad-core}/tasks/brownfield-create-story.md +0 -0
@@ -0,0 +1,80 @@
1
+ const H = require('./stats.helpers.js');
2
+
3
+ async function calculateStatistics(aggregatedContent, xmlFileSize, rootDir) {
4
+ const { textFiles, binaryFiles, errors } = aggregatedContent;
5
+
6
+ const totalLines = textFiles.reduce((sum, f) => sum + (f.lines || 0), 0);
7
+ const estimatedTokens = Math.ceil(xmlFileSize / 4);
8
+
9
+ // Build enriched file list
10
+ const allFiles = await H.enrichAllFiles(textFiles, binaryFiles);
11
+ const totalBytes = allFiles.reduce((s, f) => s + f.size, 0);
12
+ const sizes = allFiles.map((f) => f.size).sort((a, b) => a - b);
13
+ const avgSize = sizes.length > 0 ? totalBytes / sizes.length : 0;
14
+ const medianSize = sizes.length > 0 ? H.percentile(sizes, 50) : 0;
15
+ const p90 = H.percentile(sizes, 90);
16
+ const p95 = H.percentile(sizes, 95);
17
+ const p99 = H.percentile(sizes, 99);
18
+
19
+ const histogram = H.buildHistogram(allFiles);
20
+ const byExtensionArr = H.aggregateByExtension(allFiles);
21
+ const byDirectoryArr = H.aggregateByDirectory(allFiles);
22
+ const { depthDist, longestPaths } = H.computeDepthAndLongest(allFiles);
23
+ const temporal = H.computeTemporal(allFiles, Date.now());
24
+ const quality = H.computeQuality(allFiles, textFiles);
25
+ const duplicateCandidates = H.computeDuplicates(allFiles, textFiles);
26
+ const compressibilityRatio = H.estimateCompressibility(textFiles);
27
+ const git = H.computeGitInfo(allFiles, rootDir, quality.largeThreshold);
28
+ const largestFiles = H.computeLargestFiles(allFiles, totalBytes);
29
+ const markdownReport = H.buildMarkdownReport(
30
+ largestFiles,
31
+ byExtensionArr,
32
+ byDirectoryArr,
33
+ totalBytes,
34
+ );
35
+
36
+ return {
37
+ // Back-compat summary
38
+ totalFiles: textFiles.length + binaryFiles.length,
39
+ textFiles: textFiles.length,
40
+ binaryFiles: binaryFiles.length,
41
+ errorFiles: errors.length,
42
+ totalSize: H.formatSize(totalBytes),
43
+ totalBytes,
44
+ xmlSize: H.formatSize(xmlFileSize),
45
+ totalLines,
46
+ estimatedTokens: estimatedTokens.toLocaleString(),
47
+
48
+ // Distributions and percentiles
49
+ avgFileSize: avgSize,
50
+ medianFileSize: medianSize,
51
+ p90,
52
+ p95,
53
+ p99,
54
+ histogram,
55
+
56
+ // Extensions and directories
57
+ byExtension: byExtensionArr,
58
+ byDirectory: byDirectoryArr,
59
+ depthDistribution: depthDist,
60
+ longestPaths,
61
+
62
+ // Temporal
63
+ temporal,
64
+
65
+ // Quality signals
66
+ quality,
67
+
68
+ // Duplicates and compressibility
69
+ duplicateCandidates,
70
+ compressibilityRatio,
71
+
72
+ // Git-aware
73
+ git,
74
+
75
+ largestFiles,
76
+ markdownReport,
77
+ };
78
+ }
79
+
80
+ module.exports = { calculateStatistics };
@@ -0,0 +1,413 @@
1
+ /* deno-lint-ignore-file */
2
+ /*
3
+ Automatic test matrix for project root detection.
4
+ Creates temporary fixtures for various ecosystems and validates findProjectRoot().
5
+ No external options or flags required. Safe to run multiple times.
6
+ */
7
+
8
+ const os = require('node:os');
9
+ const path = require('node:path');
10
+ const fs = require('fs-extra');
11
+ const { promisify } = require('node:util');
12
+ const { execFile } = require('node:child_process');
13
+ const process = require('node:process');
14
+ const execFileAsync = promisify(execFile);
15
+
16
+ const { findProjectRoot } = require('./projectRoot.js');
17
+
18
+ async function cmdAvailable(cmd) {
19
+ try {
20
+ await execFileAsync(cmd, ['--version'], { timeout: 500, windowsHide: true });
21
+ return true;
22
+ } catch {
23
+ return false;
24
+ }
25
+
26
+ async function testSvnMarker() {
27
+ const root = await mkTmpDir('svn');
28
+ const nested = path.join(root, 'proj', 'code');
29
+ await fs.ensureDir(nested);
30
+ await fs.ensureDir(path.join(root, '.svn'));
31
+ const found = await findProjectRoot(nested);
32
+ assertEqual(found, root, '.svn marker should be detected');
33
+ return { name: 'svn-marker', ok: true };
34
+ }
35
+
36
+ async function testSymlinkStart() {
37
+ const root = await mkTmpDir('symlink-start');
38
+ const nested = path.join(root, 'a', 'b');
39
+ await fs.ensureDir(nested);
40
+ await fs.writeFile(path.join(root, '.project-root'), '\n');
41
+ const tmp = await mkTmpDir('symlink-tmp');
42
+ const link = path.join(tmp, 'link-to-b');
43
+ try {
44
+ await fs.symlink(nested, link);
45
+ } catch {
46
+ // symlink may not be permitted on some systems; skip
47
+ return { name: 'symlink-start', ok: true, skipped: true };
48
+ }
49
+ const found = await findProjectRoot(link);
50
+ assertEqual(found, root, 'should resolve symlinked start to real root');
51
+ return { name: 'symlink-start', ok: true };
52
+ }
53
+
54
+ async function testSubmoduleLikeInnerGitFile() {
55
+ const root = await mkTmpDir('submodule-like');
56
+ const mid = path.join(root, 'mid');
57
+ const leaf = path.join(mid, 'leaf');
58
+ await fs.ensureDir(leaf);
59
+ // outer repo
60
+ await fs.ensureDir(path.join(root, '.git'));
61
+ // inner submodule-like .git file
62
+ await fs.writeFile(path.join(mid, '.git'), 'gitdir: ../.git/modules/mid\n');
63
+ const found = await findProjectRoot(leaf);
64
+ assertEqual(found, root, 'outermost .git should win on tie weight');
65
+ return { name: 'submodule-like-gitfile', ok: true };
66
+ }
67
+ }
68
+
69
+ async function mkTmpDir(name) {
70
+ const base = await fs.realpath(os.tmpdir());
71
+ const dir = await fs.mkdtemp(path.join(base, `flattener-${name}-`));
72
+ return dir;
73
+ }
74
+
75
+ function assertEqual(actual, expected, msg) {
76
+ if (actual !== expected) {
77
+ throw new Error(`${msg}: expected="${expected}" actual="${actual}"`);
78
+ }
79
+ }
80
+
81
+ async function testSentinel() {
82
+ const root = await mkTmpDir('sentinel');
83
+ const nested = path.join(root, 'a', 'b', 'c');
84
+ await fs.ensureDir(nested);
85
+ await fs.writeFile(path.join(root, '.project-root'), '\n');
86
+ const found = await findProjectRoot(nested);
87
+ await assertEqual(found, root, 'sentinel .project-root should win');
88
+ return { name: 'sentinel', ok: true };
89
+ }
90
+
91
+ async function testOtherSentinels() {
92
+ const root = await mkTmpDir('other-sentinels');
93
+ const nested = path.join(root, 'x', 'y');
94
+ await fs.ensureDir(nested);
95
+ await fs.writeFile(path.join(root, '.workspace-root'), '\n');
96
+ const found1 = await findProjectRoot(nested);
97
+ assertEqual(found1, root, 'sentinel .workspace-root should win');
98
+
99
+ await fs.remove(path.join(root, '.workspace-root'));
100
+ await fs.writeFile(path.join(root, '.repo-root'), '\n');
101
+ const found2 = await findProjectRoot(nested);
102
+ assertEqual(found2, root, 'sentinel .repo-root should win');
103
+ return { name: 'other-sentinels', ok: true };
104
+ }
105
+
106
+ async function testGitCliAndMarker() {
107
+ const hasGit = await cmdAvailable('git');
108
+ if (!hasGit) return { name: 'git-cli', ok: true, skipped: true };
109
+
110
+ const root = await mkTmpDir('git');
111
+ const nested = path.join(root, 'pkg', 'src');
112
+ await fs.ensureDir(nested);
113
+ await execFileAsync('git', ['init'], { cwd: root, timeout: 2000 });
114
+ const found = await findProjectRoot(nested);
115
+ await assertEqual(found, root, 'git toplevel should be detected');
116
+ return { name: 'git-cli', ok: true };
117
+ }
118
+
119
+ async function testHgMarkerOrCli() {
120
+ // Prefer simple marker test to avoid requiring Mercurial install
121
+ const root = await mkTmpDir('hg');
122
+ const nested = path.join(root, 'lib');
123
+ await fs.ensureDir(nested);
124
+ await fs.ensureDir(path.join(root, '.hg'));
125
+ const found = await findProjectRoot(nested);
126
+ await assertEqual(found, root, '.hg marker should be detected');
127
+ return { name: 'hg-marker', ok: true };
128
+ }
129
+
130
+ async function testWorkspacePnpm() {
131
+ const root = await mkTmpDir('pnpm-workspace');
132
+ const pkgA = path.join(root, 'packages', 'a');
133
+ await fs.ensureDir(pkgA);
134
+ await fs.writeFile(path.join(root, 'pnpm-workspace.yaml'), 'packages:\n - packages/*\n');
135
+ const found = await findProjectRoot(pkgA);
136
+ await assertEqual(found, root, 'pnpm-workspace.yaml should be detected');
137
+ return { name: 'pnpm-workspace', ok: true };
138
+ }
139
+
140
+ async function testPackageJsonWorkspaces() {
141
+ const root = await mkTmpDir('package-workspaces');
142
+ const pkgA = path.join(root, 'packages', 'a');
143
+ await fs.ensureDir(pkgA);
144
+ await fs.writeJson(
145
+ path.join(root, 'package.json'),
146
+ { private: true, workspaces: ['packages/*'] },
147
+ { spaces: 2 },
148
+ );
149
+ const found = await findProjectRoot(pkgA);
150
+ await assertEqual(found, root, 'package.json workspaces should be detected');
151
+ return { name: 'package.json-workspaces', ok: true };
152
+ }
153
+
154
+ async function testLockfiles() {
155
+ const root = await mkTmpDir('lockfiles');
156
+ const nested = path.join(root, 'src');
157
+ await fs.ensureDir(nested);
158
+ await fs.writeFile(path.join(root, 'yarn.lock'), '\n');
159
+ const found = await findProjectRoot(nested);
160
+ await assertEqual(found, root, 'yarn.lock should be detected');
161
+ return { name: 'lockfiles', ok: true };
162
+ }
163
+
164
+ async function testLanguageConfigs() {
165
+ const root = await mkTmpDir('lang-configs');
166
+ const nested = path.join(root, 'x', 'y');
167
+ await fs.ensureDir(nested);
168
+ await fs.writeFile(path.join(root, 'pyproject.toml'), "[tool.poetry]\nname='tmp'\n");
169
+ const found = await findProjectRoot(nested);
170
+ await assertEqual(found, root, 'pyproject.toml should be detected');
171
+ return { name: 'language-configs', ok: true };
172
+ }
173
+
174
+ async function testPreferOuterOnTie() {
175
+ const root = await mkTmpDir('tie');
176
+ const mid = path.join(root, 'mid');
177
+ const leaf = path.join(mid, 'leaf');
178
+ await fs.ensureDir(leaf);
179
+ // same weight marker at two levels
180
+ await fs.writeFile(path.join(root, 'requirements.txt'), '\n');
181
+ await fs.writeFile(path.join(mid, 'requirements.txt'), '\n');
182
+ const found = await findProjectRoot(leaf);
183
+ await assertEqual(found, root, 'outermost directory should win on equal weight');
184
+ return { name: 'prefer-outermost-tie', ok: true };
185
+ }
186
+
187
+ // Additional coverage: Bazel, Nx/Turbo/Rush, Go workspaces, Deno, Java/Scala, PHP, Rust, Nix, Changesets, env markers,
188
+ // and priority interaction between package.json and lockfiles.
189
+
190
+ async function testBazelWorkspace() {
191
+ const root = await mkTmpDir('bazel');
192
+ const nested = path.join(root, 'apps', 'svc');
193
+ await fs.ensureDir(nested);
194
+ await fs.writeFile(path.join(root, 'WORKSPACE'), 'workspace(name="tmp")\n');
195
+ const found = await findProjectRoot(nested);
196
+ await assertEqual(found, root, 'Bazel WORKSPACE should be detected');
197
+ return { name: 'bazel-workspace', ok: true };
198
+ }
199
+
200
+ async function testNx() {
201
+ const root = await mkTmpDir('nx');
202
+ const nested = path.join(root, 'apps', 'web');
203
+ await fs.ensureDir(nested);
204
+ await fs.writeJson(path.join(root, 'nx.json'), { npmScope: 'tmp' }, { spaces: 2 });
205
+ const found = await findProjectRoot(nested);
206
+ await assertEqual(found, root, 'nx.json should be detected');
207
+ return { name: 'nx', ok: true };
208
+ }
209
+
210
+ async function testTurbo() {
211
+ const root = await mkTmpDir('turbo');
212
+ const nested = path.join(root, 'packages', 'x');
213
+ await fs.ensureDir(nested);
214
+ await fs.writeJson(path.join(root, 'turbo.json'), { pipeline: {} }, { spaces: 2 });
215
+ const found = await findProjectRoot(nested);
216
+ await assertEqual(found, root, 'turbo.json should be detected');
217
+ return { name: 'turbo', ok: true };
218
+ }
219
+
220
+ async function testRush() {
221
+ const root = await mkTmpDir('rush');
222
+ const nested = path.join(root, 'apps', 'a');
223
+ await fs.ensureDir(nested);
224
+ await fs.writeJson(path.join(root, 'rush.json'), { projectFolderMinDepth: 1 }, { spaces: 2 });
225
+ const found = await findProjectRoot(nested);
226
+ await assertEqual(found, root, 'rush.json should be detected');
227
+ return { name: 'rush', ok: true };
228
+ }
229
+
230
+ async function testGoWorkAndMod() {
231
+ const root = await mkTmpDir('gowork');
232
+ const mod = path.join(root, 'modA');
233
+ const nested = path.join(mod, 'pkg');
234
+ await fs.ensureDir(nested);
235
+ await fs.writeFile(path.join(root, 'go.work'), 'go 1.22\nuse ./modA\n');
236
+ await fs.writeFile(path.join(mod, 'go.mod'), 'module example.com/a\ngo 1.22\n');
237
+ const found = await findProjectRoot(nested);
238
+ await assertEqual(found, root, 'go.work should define the workspace root');
239
+ return { name: 'go-work', ok: true };
240
+ }
241
+
242
+ async function testDenoJson() {
243
+ const root = await mkTmpDir('deno');
244
+ const nested = path.join(root, 'src');
245
+ await fs.ensureDir(nested);
246
+ await fs.writeJson(path.join(root, 'deno.json'), { tasks: {} }, { spaces: 2 });
247
+ const found = await findProjectRoot(nested);
248
+ await assertEqual(found, root, 'deno.json should be detected');
249
+ return { name: 'deno-json', ok: true };
250
+ }
251
+
252
+ async function testGradleSettings() {
253
+ const root = await mkTmpDir('gradle');
254
+ const nested = path.join(root, 'app');
255
+ await fs.ensureDir(nested);
256
+ await fs.writeFile(path.join(root, 'settings.gradle'), "rootProject.name='tmp'\n");
257
+ const found = await findProjectRoot(nested);
258
+ await assertEqual(found, root, 'settings.gradle should be detected');
259
+ return { name: 'gradle-settings', ok: true };
260
+ }
261
+
262
+ async function testMavenPom() {
263
+ const root = await mkTmpDir('maven');
264
+ const nested = path.join(root, 'module');
265
+ await fs.ensureDir(nested);
266
+ await fs.writeFile(path.join(root, 'pom.xml'), '<project></project>\n');
267
+ const found = await findProjectRoot(nested);
268
+ await assertEqual(found, root, 'pom.xml should be detected');
269
+ return { name: 'maven-pom', ok: true };
270
+ }
271
+
272
+ async function testSbtBuild() {
273
+ const root = await mkTmpDir('sbt');
274
+ const nested = path.join(root, 'sub');
275
+ await fs.ensureDir(nested);
276
+ await fs.writeFile(path.join(root, 'build.sbt'), 'name := "tmp"\n');
277
+ const found = await findProjectRoot(nested);
278
+ await assertEqual(found, root, 'build.sbt should be detected');
279
+ return { name: 'sbt-build', ok: true };
280
+ }
281
+
282
+ async function testComposer() {
283
+ const root = await mkTmpDir('composer');
284
+ const nested = path.join(root, 'src');
285
+ await fs.ensureDir(nested);
286
+ await fs.writeJson(path.join(root, 'composer.json'), { name: 'tmp/pkg' }, { spaces: 2 });
287
+ await fs.writeFile(path.join(root, 'composer.lock'), '{}\n');
288
+ const found = await findProjectRoot(nested);
289
+ await assertEqual(found, root, 'composer.{json,lock} should be detected');
290
+ return { name: 'composer', ok: true };
291
+ }
292
+
293
+ async function testCargo() {
294
+ const root = await mkTmpDir('cargo');
295
+ const nested = path.join(root, 'src');
296
+ await fs.ensureDir(nested);
297
+ await fs.writeFile(path.join(root, 'Cargo.toml'), "[package]\nname='tmp'\nversion='0.0.0'\n");
298
+ const found = await findProjectRoot(nested);
299
+ await assertEqual(found, root, 'Cargo.toml should be detected');
300
+ return { name: 'cargo', ok: true };
301
+ }
302
+
303
+ async function testNixFlake() {
304
+ const root = await mkTmpDir('nix');
305
+ const nested = path.join(root, 'work');
306
+ await fs.ensureDir(nested);
307
+ await fs.writeFile(path.join(root, 'flake.nix'), '{ }\n');
308
+ const found = await findProjectRoot(nested);
309
+ await assertEqual(found, root, 'flake.nix should be detected');
310
+ return { name: 'nix-flake', ok: true };
311
+ }
312
+
313
+ async function testChangesetConfig() {
314
+ const root = await mkTmpDir('changeset');
315
+ const nested = path.join(root, 'pkg');
316
+ await fs.ensureDir(nested);
317
+ await fs.ensureDir(path.join(root, '.changeset'));
318
+ await fs.writeJson(
319
+ path.join(root, '.changeset', 'config.json'),
320
+ { $schema: 'https://unpkg.com/@changesets/config@2.3.1/schema.json' },
321
+ { spaces: 2 },
322
+ );
323
+ const found = await findProjectRoot(nested);
324
+ await assertEqual(found, root, '.changeset/config.json should be detected');
325
+ return { name: 'changesets', ok: true };
326
+ }
327
+
328
+ async function testEnvCustomMarker() {
329
+ const root = await mkTmpDir('env-marker');
330
+ const nested = path.join(root, 'dir');
331
+ await fs.ensureDir(nested);
332
+ await fs.writeFile(path.join(root, 'MY_ROOT'), '\n');
333
+ const prev = process.env.PROJECT_ROOT_MARKERS;
334
+ process.env.PROJECT_ROOT_MARKERS = 'MY_ROOT';
335
+ try {
336
+ const found = await findProjectRoot(nested);
337
+ await assertEqual(found, root, 'custom env marker should be honored');
338
+ } finally {
339
+ if (prev === undefined) delete process.env.PROJECT_ROOT_MARKERS;
340
+ else process.env.PROJECT_ROOT_MARKERS = prev;
341
+ }
342
+ return { name: 'env-custom-marker', ok: true };
343
+ }
344
+
345
+ async function testPackageLowPriorityVsLock() {
346
+ const root = await mkTmpDir('pkg-vs-lock');
347
+ const nested = path.join(root, 'nested');
348
+ await fs.ensureDir(path.join(nested, 'deep'));
349
+ await fs.writeJson(path.join(nested, 'package.json'), { name: 'nested' }, { spaces: 2 });
350
+ await fs.writeFile(path.join(root, 'yarn.lock'), '\n');
351
+ const found = await findProjectRoot(path.join(nested, 'deep'));
352
+ await assertEqual(found, root, 'lockfile at root should outrank nested package.json');
353
+ return { name: 'package-vs-lock-priority', ok: true };
354
+ }
355
+
356
+ async function run() {
357
+ const tests = [
358
+ testSentinel,
359
+ testOtherSentinels,
360
+ testGitCliAndMarker,
361
+ testHgMarkerOrCli,
362
+ testWorkspacePnpm,
363
+ testPackageJsonWorkspaces,
364
+ testLockfiles,
365
+ testLanguageConfigs,
366
+ testPreferOuterOnTie,
367
+ testBazelWorkspace,
368
+ testNx,
369
+ testTurbo,
370
+ testRush,
371
+ testGoWorkAndMod,
372
+ testDenoJson,
373
+ testGradleSettings,
374
+ testMavenPom,
375
+ testSbtBuild,
376
+ testComposer,
377
+ testCargo,
378
+ testNixFlake,
379
+ testChangesetConfig,
380
+ testEnvCustomMarker,
381
+ testPackageLowPriorityVsLock,
382
+ testSvnMarker,
383
+ testSymlinkStart,
384
+ testSubmoduleLikeInnerGitFile,
385
+ ];
386
+
387
+ const results = [];
388
+ for (const t of tests) {
389
+ try {
390
+ const r = await t();
391
+ results.push({ ...r, ok: true });
392
+ console.log(`✔ ${r.name}${r.skipped ? ' (skipped)' : ''}`);
393
+ } catch (error) {
394
+ console.error(`✖ ${t.name}:`, error && error.message ? error.message : error);
395
+ results.push({ name: t.name, ok: false, error: String(error) });
396
+ }
397
+ }
398
+
399
+ const failed = results.filter((r) => !r.ok);
400
+ console.log('\nSummary:');
401
+ for (const r of results) {
402
+ console.log(`- ${r.name}: ${r.ok ? 'ok' : 'FAIL'}${r.skipped ? ' (skipped)' : ''}`);
403
+ }
404
+
405
+ if (failed.length > 0) {
406
+ process.exitCode = 1;
407
+ }
408
+ }
409
+
410
+ run().catch((error) => {
411
+ console.error('Fatal error:', error);
412
+ process.exit(1);
413
+ });
@@ -0,0 +1,88 @@
1
+ const fs = require('fs-extra');
2
+
3
+ function escapeXml(string_) {
4
+ if (typeof string_ !== 'string') {
5
+ return String(string_);
6
+ }
7
+ return string_.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll("'", '&apos;');
8
+ }
9
+
10
+ function indentFileContent(content) {
11
+ if (typeof content !== 'string') {
12
+ return String(content);
13
+ }
14
+ return content.split('\n').map((line) => ` ${line}`);
15
+ }
16
+
17
+ function generateXMLOutput(aggregatedContent, outputPath) {
18
+ const { textFiles } = aggregatedContent;
19
+ const writeStream = fs.createWriteStream(outputPath, { encoding: 'utf8' });
20
+
21
+ return new Promise((resolve, reject) => {
22
+ writeStream.on('error', reject);
23
+ writeStream.on('finish', resolve);
24
+
25
+ writeStream.write('<?xml version="1.0" encoding="UTF-8"?>\n');
26
+ writeStream.write('<files>\n');
27
+
28
+ // Sort files by path for deterministic order
29
+ const filesSorted = [...textFiles].sort((a, b) => a.path.localeCompare(b.path));
30
+ let index = 0;
31
+
32
+ const writeNext = () => {
33
+ if (index >= filesSorted.length) {
34
+ writeStream.write('</files>\n');
35
+ writeStream.end();
36
+ return;
37
+ }
38
+
39
+ const file = filesSorted[index++];
40
+ const p = escapeXml(file.path);
41
+ const content = typeof file.content === 'string' ? file.content : '';
42
+
43
+ if (content.length === 0) {
44
+ writeStream.write(`\t<file path='${p}'/>\n`);
45
+ setTimeout(writeNext, 0);
46
+ return;
47
+ }
48
+
49
+ const needsCdata = content.includes('<') || content.includes('&') || content.includes(']]>');
50
+ if (needsCdata) {
51
+ // Open tag and CDATA on their own line with tab indent; content lines indented with two tabs
52
+ writeStream.write(`\t<file path='${p}'><![CDATA[\n`);
53
+ // Safely split any occurrences of "]]>" inside content, trim trailing newlines, indent each line with two tabs
54
+ const safe = content.replaceAll(']]>', ']]]]><![CDATA[>');
55
+ const trimmed = safe.replace(/[\r\n]+$/, '');
56
+ const indented =
57
+ trimmed.length > 0
58
+ ? trimmed
59
+ .split('\n')
60
+ .map((line) => `\t\t${line}`)
61
+ .join('\n')
62
+ : '';
63
+ writeStream.write(indented);
64
+ // Close CDATA and attach closing tag directly after the last content line
65
+ writeStream.write(']]></file>\n');
66
+ } else {
67
+ // Write opening tag then newline; indent content with two tabs; attach closing tag directly after last content char
68
+ writeStream.write(`\t<file path='${p}'>\n`);
69
+ const trimmed = content.replace(/[\r\n]+$/, '');
70
+ const indented =
71
+ trimmed.length > 0
72
+ ? trimmed
73
+ .split('\n')
74
+ .map((line) => `\t\t${line}`)
75
+ .join('\n')
76
+ : '';
77
+ writeStream.write(indented);
78
+ writeStream.write(`</file>\n`);
79
+ }
80
+
81
+ setTimeout(writeNext, 0);
82
+ };
83
+
84
+ writeNext();
85
+ });
86
+ }
87
+
88
+ module.exports = { generateXMLOutput };
@@ -1,58 +1,8 @@
1
- # BMAD Method Installer
2
-
3
- This directory contains the BMAD Method installer implementation.
4
-
5
- ## Structure
6
-
7
- ```text
8
- installer/
9
- ├── bin/ # CLI entry points
10
- │ └── bmad.js # Main CLI executable
11
- ├── lib/ # Core implementation
12
- │ ├── installer.js # Main installation logic
13
- │ ├── updater.js # Update management
14
- │ ├── config-loader.js # YAML config parsing
15
- │ ├── file-manager.js # File operations
16
- │ ├── ide-setup.js # IDE-specific setup
17
- │ └── prompts.js # Interactive CLI prompts
18
- ├── config/ # Configuration files
19
- │ └── install.config.yml # Installation profiles
20
- ├── templates/ # IDE template files
21
- │ ├── cursor-rules.md # Cursor template
22
- │ ├── claude-commands.md # Claude Code template
23
- │ └── windsurf-rules.md # Windsurf template
24
- └── package.json # NPM package configuration
25
- ```
26
-
27
- ## Installation Profiles
28
-
29
- - **minimal**: IDE agents only (best for beginners)
30
- - **core**: IDE + Web agents
31
- - **teams**: Full team workflows
32
- - **developer**: Everything including creation tools
1
+ # BMad Method Installer
33
2
 
34
3
  ## Usage
35
4
 
36
- ````bash
5
+ ```bash
37
6
  # Interactive installation
38
7
  npx bmad-method install
39
-
40
- # Direct profile installation
41
- npx bmad-method install --profile=minimal
42
-
43
- # Update existing installation
44
- npx bmad-method update
45
- ```text
46
-
47
- ## Development
48
-
49
- ```bash
50
- # Install dependencies
51
- npm install
52
-
53
- # Run tests
54
- npm test
55
-
56
- # Lint code
57
- npm run lint
58
- ````
8
+ ```