bmad-stella 1.0.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 (398) hide show
  1. package/.github/FORK_GUIDE.md +106 -0
  2. package/.github/FUNDING.yaml +15 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
  5. package/.github/workflows/discord.yaml +26 -0
  6. package/.github/workflows/format-check.yaml +44 -0
  7. package/.github/workflows/manual-release.yaml +174 -0
  8. package/.github/workflows/pr-validation.yaml +55 -0
  9. package/.husky/pre-commit +3 -0
  10. package/.vscode/settings.json +69 -0
  11. package/CHANGELOG.md +686 -0
  12. package/CONTRIBUTING.md +243 -0
  13. package/LICENSE +26 -0
  14. package/PR-opencode-agents-generator.md +40 -0
  15. package/README.md +159 -0
  16. package/REVIEWER-AGENT-SIMPLE.md +66 -0
  17. package/bmad-core/agent-teams/team-all.yaml +15 -0
  18. package/bmad-core/agent-teams/team-fullstack.yaml +19 -0
  19. package/bmad-core/agent-teams/team-ide-minimal.yaml +11 -0
  20. package/bmad-core/agent-teams/team-no-ui.yaml +14 -0
  21. package/bmad-core/agents/analyst.md +84 -0
  22. package/bmad-core/agents/architect.md +85 -0
  23. package/bmad-core/agents/bmad-master.md +110 -0
  24. package/bmad-core/agents/bmad-orchestrator.md +147 -0
  25. package/bmad-core/agents/dev.md +96 -0
  26. package/bmad-core/agents/planner.md +86 -0
  27. package/bmad-core/agents/pm.md +84 -0
  28. package/bmad-core/agents/po.md +79 -0
  29. package/bmad-core/agents/qa.md +80 -0
  30. package/bmad-core/agents/reviewer.md +61 -0
  31. package/bmad-core/agents/sm.md +65 -0
  32. package/bmad-core/agents/ux-expert.md +69 -0
  33. package/bmad-core/checklists/architect-checklist.md +440 -0
  34. package/bmad-core/checklists/change-checklist.md +184 -0
  35. package/bmad-core/checklists/planner-validation-checklist.md +167 -0
  36. package/bmad-core/checklists/pm-checklist.md +372 -0
  37. package/bmad-core/checklists/po-master-checklist.md +434 -0
  38. package/bmad-core/checklists/story-dod-checklist.md +96 -0
  39. package/bmad-core/checklists/story-draft-checklist.md +155 -0
  40. package/bmad-core/checklists/task-dod-checklist.md +110 -0
  41. package/bmad-core/core-config.yaml +26 -0
  42. package/bmad-core/data/bmad-kb.md +809 -0
  43. package/bmad-core/data/brainstorming-techniques.md +38 -0
  44. package/bmad-core/data/elicitation-methods.md +156 -0
  45. package/bmad-core/data/technical-preferences.md +5 -0
  46. package/bmad-core/data/test-levels-framework.md +148 -0
  47. package/bmad-core/data/test-priorities-matrix.md +174 -0
  48. package/bmad-core/tasks/advanced-elicitation.md +119 -0
  49. package/bmad-core/tasks/apply-qa-fixes.md +150 -0
  50. package/bmad-core/tasks/brownfield-create-epic.md +162 -0
  51. package/bmad-core/tasks/brownfield-create-story.md +149 -0
  52. package/bmad-core/tasks/correct-course.md +72 -0
  53. package/bmad-core/tasks/create-brownfield-story.md +314 -0
  54. package/bmad-core/tasks/create-deep-research-prompt.md +280 -0
  55. package/bmad-core/tasks/create-implementation-plan.md +298 -0
  56. package/bmad-core/tasks/create-next-story.md +114 -0
  57. package/bmad-core/tasks/decompose-task.md +162 -0
  58. package/bmad-core/tasks/document-project.md +345 -0
  59. package/bmad-core/tasks/facilitate-brainstorming-session.md +138 -0
  60. package/bmad-core/tasks/generate-ai-frontend-prompt.md +53 -0
  61. package/bmad-core/tasks/identify-dependencies.md +347 -0
  62. package/bmad-core/tasks/implement-test.md +188 -0
  63. package/bmad-core/tasks/index-docs.md +175 -0
  64. package/bmad-core/tasks/kb-mode-interaction.md +77 -0
  65. package/bmad-core/tasks/nfr-assess.md +345 -0
  66. package/bmad-core/tasks/qa-gate.md +163 -0
  67. package/bmad-core/tasks/review-and-improve.md +95 -0
  68. package/bmad-core/tasks/review-story.md +316 -0
  69. package/bmad-core/tasks/risk-profile.md +355 -0
  70. package/bmad-core/tasks/shard-doc.md +187 -0
  71. package/bmad-core/tasks/test-design.md +176 -0
  72. package/bmad-core/tasks/trace-requirements.md +266 -0
  73. package/bmad-core/tasks/validate-next-story.md +136 -0
  74. package/bmad-core/templates/architecture-tmpl.yaml +651 -0
  75. package/bmad-core/templates/brainstorming-output-tmpl.yaml +156 -0
  76. package/bmad-core/templates/brownfield-architecture-tmpl.yaml +477 -0
  77. package/bmad-core/templates/brownfield-prd-tmpl.yaml +281 -0
  78. package/bmad-core/templates/competitor-analysis-tmpl.yaml +307 -0
  79. package/bmad-core/templates/front-end-architecture-tmpl.yaml +219 -0
  80. package/bmad-core/templates/front-end-spec-tmpl.yaml +350 -0
  81. package/bmad-core/templates/fullstack-architecture-tmpl.yaml +824 -0
  82. package/bmad-core/templates/implementation-plan-tmpl.yaml +224 -0
  83. package/bmad-core/templates/market-research-tmpl.yaml +253 -0
  84. package/bmad-core/templates/prd-tmpl.yaml +203 -0
  85. package/bmad-core/templates/project-brief-tmpl.yaml +222 -0
  86. package/bmad-core/templates/qa-gate-tmpl.yaml +103 -0
  87. package/bmad-core/templates/story-tmpl.yaml +138 -0
  88. package/bmad-core/workflows/brownfield-fullstack.yaml +298 -0
  89. package/bmad-core/workflows/brownfield-service.yaml +188 -0
  90. package/bmad-core/workflows/brownfield-ui.yaml +198 -0
  91. package/bmad-core/workflows/greenfield-fullstack.yaml +241 -0
  92. package/bmad-core/workflows/greenfield-service.yaml +207 -0
  93. package/bmad-core/workflows/greenfield-ui.yaml +236 -0
  94. package/common/tasks/create-doc.md +103 -0
  95. package/common/tasks/execute-checklist.md +88 -0
  96. package/common/utils/bmad-doc-template.md +327 -0
  97. package/common/utils/workflow-management.md +71 -0
  98. package/dist/agents/analyst.txt +2907 -0
  99. package/dist/agents/architect.txt +3567 -0
  100. package/dist/agents/bmad-master.txt +8828 -0
  101. package/dist/agents/bmad-orchestrator.txt +1520 -0
  102. package/dist/agents/dev.txt +576 -0
  103. package/dist/agents/pm.txt +2226 -0
  104. package/dist/agents/po.txt +1359 -0
  105. package/dist/agents/qa.txt +2001 -0
  106. package/dist/agents/sm.txt +667 -0
  107. package/dist/agents/ux-expert.txt +703 -0
  108. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +2386 -0
  109. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +1627 -0
  110. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +822 -0
  111. package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +11008 -0
  112. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.txt +4031 -0
  113. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.txt +3717 -0
  114. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.txt +456 -0
  115. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.txt +982 -0
  116. package/dist/expansion-packs/bmad-2d-unity-game-dev/teams/unity-2d-game-team.txt +15450 -0
  117. package/dist/expansion-packs/bmad-creative-writing/agents/beta-reader.txt +921 -0
  118. package/dist/expansion-packs/bmad-creative-writing/agents/book-critic.txt +81 -0
  119. package/dist/expansion-packs/bmad-creative-writing/agents/character-psychologist.txt +886 -0
  120. package/dist/expansion-packs/bmad-creative-writing/agents/cover-designer.txt +85 -0
  121. package/dist/expansion-packs/bmad-creative-writing/agents/dialog-specialist.txt +903 -0
  122. package/dist/expansion-packs/bmad-creative-writing/agents/editor.txt +837 -0
  123. package/dist/expansion-packs/bmad-creative-writing/agents/genre-specialist.txt +989 -0
  124. package/dist/expansion-packs/bmad-creative-writing/agents/narrative-designer.txt +888 -0
  125. package/dist/expansion-packs/bmad-creative-writing/agents/plot-architect.txt +1173 -0
  126. package/dist/expansion-packs/bmad-creative-writing/agents/world-builder.txt +914 -0
  127. package/dist/expansion-packs/bmad-creative-writing/teams/agent-team.txt +6511 -0
  128. package/dist/expansion-packs/bmad-godot-game-dev/agents/bmad-orchestrator.txt +1513 -0
  129. package/dist/expansion-packs/bmad-godot-game-dev/agents/game-analyst.txt +3190 -0
  130. package/dist/expansion-packs/bmad-godot-game-dev/agents/game-architect.txt +4499 -0
  131. package/dist/expansion-packs/bmad-godot-game-dev/agents/game-designer.txt +3925 -0
  132. package/dist/expansion-packs/bmad-godot-game-dev/agents/game-developer.txt +666 -0
  133. package/dist/expansion-packs/bmad-godot-game-dev/agents/game-pm.txt +2381 -0
  134. package/dist/expansion-packs/bmad-godot-game-dev/agents/game-po.txt +1612 -0
  135. package/dist/expansion-packs/bmad-godot-game-dev/agents/game-qa.txt +1741 -0
  136. package/dist/expansion-packs/bmad-godot-game-dev/agents/game-sm.txt +1208 -0
  137. package/dist/expansion-packs/bmad-godot-game-dev/agents/game-ux-expert.txt +958 -0
  138. package/dist/expansion-packs/bmad-godot-game-dev/teams/godot-game-team.txt +27717 -0
  139. package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +2087 -0
  140. package/dist/teams/team-all.txt +12911 -0
  141. package/dist/teams/team-fullstack.txt +10477 -0
  142. package/dist/teams/team-ide-minimal.txt +5299 -0
  143. package/dist/teams/team-no-ui.txt +9029 -0
  144. package/docs/GUIDING-PRINCIPLES.md +91 -0
  145. package/docs/core-architecture.md +219 -0
  146. package/docs/enhanced-ide-development-workflow.md +248 -0
  147. package/docs/expansion-packs.md +200 -0
  148. package/docs/flattener.md +91 -0
  149. package/docs/how-to-contribute-with-pull-requests.md +158 -0
  150. package/docs/stella-user-guide.md +637 -0
  151. package/docs/user-guide.md +577 -0
  152. package/docs/versioning-and-releases.md +155 -0
  153. package/docs/versions.md +48 -0
  154. package/docs/working-in-the-brownfield.md +606 -0
  155. package/eslint.config.mjs +119 -0
  156. package/expansion-packs/README.md +3 -0
  157. package/expansion-packs/bmad-2d-phaser-game-dev/agent-teams/phaser-2d-nodejs-game-team.yaml +14 -0
  158. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.md +73 -0
  159. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.md +80 -0
  160. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.md +66 -0
  161. package/expansion-packs/bmad-2d-phaser-game-dev/checklists/game-design-checklist.md +203 -0
  162. package/expansion-packs/bmad-2d-phaser-game-dev/checklists/game-story-dod-checklist.md +162 -0
  163. package/expansion-packs/bmad-2d-phaser-game-dev/config.yaml +9 -0
  164. package/expansion-packs/bmad-2d-phaser-game-dev/data/bmad-kb.md +252 -0
  165. package/expansion-packs/bmad-2d-phaser-game-dev/data/development-guidelines.md +649 -0
  166. package/expansion-packs/bmad-2d-phaser-game-dev/tasks/advanced-elicitation.md +112 -0
  167. package/expansion-packs/bmad-2d-phaser-game-dev/tasks/create-game-story.md +218 -0
  168. package/expansion-packs/bmad-2d-phaser-game-dev/tasks/game-design-brainstorming.md +292 -0
  169. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-architecture-tmpl.yaml +614 -0
  170. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-brief-tmpl.yaml +357 -0
  171. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-design-doc-tmpl.yaml +344 -0
  172. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-story-tmpl.yaml +254 -0
  173. package/expansion-packs/bmad-2d-phaser-game-dev/templates/level-design-doc-tmpl.yaml +485 -0
  174. package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-dev-greenfield.yaml +184 -0
  175. package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-prototype.yaml +176 -0
  176. package/expansion-packs/bmad-2d-unity-game-dev/agent-teams/unity-2d-game-team.yaml +15 -0
  177. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.md +82 -0
  178. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.md +79 -0
  179. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.md +80 -0
  180. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.md +67 -0
  181. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-architect-checklist.md +393 -0
  182. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-change-checklist.md +205 -0
  183. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-design-checklist.md +203 -0
  184. package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-story-dod-checklist.md +126 -0
  185. package/expansion-packs/bmad-2d-unity-game-dev/config.yaml +7 -0
  186. package/expansion-packs/bmad-2d-unity-game-dev/data/bmad-kb.md +771 -0
  187. package/expansion-packs/bmad-2d-unity-game-dev/data/development-guidelines.md +588 -0
  188. package/expansion-packs/bmad-2d-unity-game-dev/tasks/advanced-elicitation.md +112 -0
  189. package/expansion-packs/bmad-2d-unity-game-dev/tasks/correct-course-game.md +143 -0
  190. package/expansion-packs/bmad-2d-unity-game-dev/tasks/create-game-story.md +186 -0
  191. package/expansion-packs/bmad-2d-unity-game-dev/tasks/game-design-brainstorming.md +292 -0
  192. package/expansion-packs/bmad-2d-unity-game-dev/tasks/validate-game-story.md +202 -0
  193. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-architecture-tmpl.yaml +1031 -0
  194. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-brief-tmpl.yaml +357 -0
  195. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-design-doc-tmpl.yaml +706 -0
  196. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-story-tmpl.yaml +257 -0
  197. package/expansion-packs/bmad-2d-unity-game-dev/templates/level-design-doc-tmpl.yaml +485 -0
  198. package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-dev-greenfield.yaml +184 -0
  199. package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-prototype.yaml +176 -0
  200. package/expansion-packs/bmad-creative-writing/README.md +146 -0
  201. package/expansion-packs/bmad-creative-writing/agent-teams/agent-team.yaml +20 -0
  202. package/expansion-packs/bmad-creative-writing/agents/beta-reader.md +94 -0
  203. package/expansion-packs/bmad-creative-writing/agents/book-critic.md +40 -0
  204. package/expansion-packs/bmad-creative-writing/agents/character-psychologist.md +93 -0
  205. package/expansion-packs/bmad-creative-writing/agents/cover-designer.md +46 -0
  206. package/expansion-packs/bmad-creative-writing/agents/dialog-specialist.md +92 -0
  207. package/expansion-packs/bmad-creative-writing/agents/editor.md +93 -0
  208. package/expansion-packs/bmad-creative-writing/agents/genre-specialist.md +95 -0
  209. package/expansion-packs/bmad-creative-writing/agents/narrative-designer.md +93 -0
  210. package/expansion-packs/bmad-creative-writing/agents/plot-architect.md +95 -0
  211. package/expansion-packs/bmad-creative-writing/agents/world-builder.md +94 -0
  212. package/expansion-packs/bmad-creative-writing/checklists/beta-feedback-closure-checklist.md +23 -0
  213. package/expansion-packs/bmad-creative-writing/checklists/character-consistency-checklist.md +23 -0
  214. package/expansion-packs/bmad-creative-writing/checklists/comedic-timing-checklist.md +23 -0
  215. package/expansion-packs/bmad-creative-writing/checklists/cyberpunk-aesthetic-checklist.md +23 -0
  216. package/expansion-packs/bmad-creative-writing/checklists/ebook-formatting-checklist.md +21 -0
  217. package/expansion-packs/bmad-creative-writing/checklists/epic-poetry-meter-checklist.md +23 -0
  218. package/expansion-packs/bmad-creative-writing/checklists/fantasy-magic-system-checklist.md +23 -0
  219. package/expansion-packs/bmad-creative-writing/checklists/foreshadowing-payoff-checklist.md +22 -0
  220. package/expansion-packs/bmad-creative-writing/checklists/genre-tropes-checklist.md +22 -0
  221. package/expansion-packs/bmad-creative-writing/checklists/historical-accuracy-checklist.md +23 -0
  222. package/expansion-packs/bmad-creative-writing/checklists/horror-suspense-checklist.md +23 -0
  223. package/expansion-packs/bmad-creative-writing/checklists/kdp-cover-ready-checklist.md +25 -0
  224. package/expansion-packs/bmad-creative-writing/checklists/line-edit-quality-checklist.md +23 -0
  225. package/expansion-packs/bmad-creative-writing/checklists/marketing-copy-checklist.md +23 -0
  226. package/expansion-packs/bmad-creative-writing/checklists/mystery-clue-trail-checklist.md +23 -0
  227. package/expansion-packs/bmad-creative-writing/checklists/orbital-mechanics-checklist.md +23 -0
  228. package/expansion-packs/bmad-creative-writing/checklists/plot-structure-checklist.md +59 -0
  229. package/expansion-packs/bmad-creative-writing/checklists/publication-readiness-checklist.md +23 -0
  230. package/expansion-packs/bmad-creative-writing/checklists/romance-emotional-beats-checklist.md +23 -0
  231. package/expansion-packs/bmad-creative-writing/checklists/scene-quality-checklist.md +23 -0
  232. package/expansion-packs/bmad-creative-writing/checklists/scifi-technology-plausibility-checklist.md +22 -0
  233. package/expansion-packs/bmad-creative-writing/checklists/sensitivity-representation-checklist.md +23 -0
  234. package/expansion-packs/bmad-creative-writing/checklists/steampunk-gadget-checklist.md +23 -0
  235. package/expansion-packs/bmad-creative-writing/checklists/thriller-pacing-stakes-checklist.md +23 -0
  236. package/expansion-packs/bmad-creative-writing/checklists/timeline-continuity-checklist.md +23 -0
  237. package/expansion-packs/bmad-creative-writing/checklists/world-building-continuity-checklist.md +23 -0
  238. package/expansion-packs/bmad-creative-writing/checklists/ya-appropriateness-checklist.md +23 -0
  239. package/expansion-packs/bmad-creative-writing/config.yaml +12 -0
  240. package/expansion-packs/bmad-creative-writing/data/bmad-kb.md +209 -0
  241. package/expansion-packs/bmad-creative-writing/data/story-structures.md +67 -0
  242. package/expansion-packs/bmad-creative-writing/docs/brief.md +212 -0
  243. package/expansion-packs/bmad-creative-writing/tasks/advanced-elicitation.md +119 -0
  244. package/expansion-packs/bmad-creative-writing/tasks/analyze-reader-feedback.md +23 -0
  245. package/expansion-packs/bmad-creative-writing/tasks/analyze-story-structure.md +67 -0
  246. package/expansion-packs/bmad-creative-writing/tasks/assemble-kdp-package.md +29 -0
  247. package/expansion-packs/bmad-creative-writing/tasks/brainstorm-premise.md +23 -0
  248. package/expansion-packs/bmad-creative-writing/tasks/build-world.md +24 -0
  249. package/expansion-packs/bmad-creative-writing/tasks/character-depth-pass.md +22 -0
  250. package/expansion-packs/bmad-creative-writing/tasks/create-doc.md +103 -0
  251. package/expansion-packs/bmad-creative-writing/tasks/create-draft-section.md +26 -0
  252. package/expansion-packs/bmad-creative-writing/tasks/critical-review.md +26 -0
  253. package/expansion-packs/bmad-creative-writing/tasks/develop-character.md +24 -0
  254. package/expansion-packs/bmad-creative-writing/tasks/execute-checklist.md +88 -0
  255. package/expansion-packs/bmad-creative-writing/tasks/expand-premise.md +23 -0
  256. package/expansion-packs/bmad-creative-writing/tasks/expand-synopsis.md +23 -0
  257. package/expansion-packs/bmad-creative-writing/tasks/final-polish.md +23 -0
  258. package/expansion-packs/bmad-creative-writing/tasks/generate-cover-brief.md +25 -0
  259. package/expansion-packs/bmad-creative-writing/tasks/generate-cover-prompts.md +26 -0
  260. package/expansion-packs/bmad-creative-writing/tasks/generate-scene-list.md +23 -0
  261. package/expansion-packs/bmad-creative-writing/tasks/incorporate-feedback.md +25 -0
  262. package/expansion-packs/bmad-creative-writing/tasks/outline-scenes.md +23 -0
  263. package/expansion-packs/bmad-creative-writing/tasks/provide-feedback.md +24 -0
  264. package/expansion-packs/bmad-creative-writing/tasks/publish-chapter.md +23 -0
  265. package/expansion-packs/bmad-creative-writing/tasks/quick-feedback.md +22 -0
  266. package/expansion-packs/bmad-creative-writing/tasks/select-next-arc.md +23 -0
  267. package/expansion-packs/bmad-creative-writing/tasks/workshop-dialog.md +64 -0
  268. package/expansion-packs/bmad-creative-writing/templates/beta-feedback-form.yaml +97 -0
  269. package/expansion-packs/bmad-creative-writing/templates/chapter-draft-tmpl.yaml +82 -0
  270. package/expansion-packs/bmad-creative-writing/templates/character-profile-tmpl.yaml +92 -0
  271. package/expansion-packs/bmad-creative-writing/templates/cover-design-brief-tmpl.yaml +98 -0
  272. package/expansion-packs/bmad-creative-writing/templates/premise-brief-tmpl.yaml +78 -0
  273. package/expansion-packs/bmad-creative-writing/templates/scene-list-tmpl.yaml +55 -0
  274. package/expansion-packs/bmad-creative-writing/templates/story-outline-tmpl.yaml +96 -0
  275. package/expansion-packs/bmad-creative-writing/templates/world-guide-tmpl.yaml +89 -0
  276. package/expansion-packs/bmad-creative-writing/workflows/book-cover-design-workflow.md +218 -0
  277. package/expansion-packs/bmad-creative-writing/workflows/novel-greenfield-workflow.yaml +56 -0
  278. package/expansion-packs/bmad-creative-writing/workflows/novel-serial-workflow.yaml +50 -0
  279. package/expansion-packs/bmad-creative-writing/workflows/novel-snowflake-workflow.yaml +69 -0
  280. package/expansion-packs/bmad-creative-writing/workflows/novel-writing.yaml +91 -0
  281. package/expansion-packs/bmad-creative-writing/workflows/screenplay-development.yaml +85 -0
  282. package/expansion-packs/bmad-creative-writing/workflows/series-planning.yaml +78 -0
  283. package/expansion-packs/bmad-creative-writing/workflows/short-story-creation.yaml +64 -0
  284. package/expansion-packs/bmad-godot-game-dev/README.md +244 -0
  285. package/expansion-packs/bmad-godot-game-dev/agent-teams/godot-game-team.yaml +18 -0
  286. package/expansion-packs/bmad-godot-game-dev/agents/bmad-orchestrator.md +147 -0
  287. package/expansion-packs/bmad-godot-game-dev/agents/game-analyst.md +84 -0
  288. package/expansion-packs/bmad-godot-game-dev/agents/game-architect.md +146 -0
  289. package/expansion-packs/bmad-godot-game-dev/agents/game-designer.md +78 -0
  290. package/expansion-packs/bmad-godot-game-dev/agents/game-developer.md +124 -0
  291. package/expansion-packs/bmad-godot-game-dev/agents/game-pm.md +82 -0
  292. package/expansion-packs/bmad-godot-game-dev/agents/game-po.md +115 -0
  293. package/expansion-packs/bmad-godot-game-dev/agents/game-qa.md +159 -0
  294. package/expansion-packs/bmad-godot-game-dev/agents/game-sm.md +66 -0
  295. package/expansion-packs/bmad-godot-game-dev/agents/game-ux-expert.md +75 -0
  296. package/expansion-packs/bmad-godot-game-dev/checklists/game-architect-checklist.md +377 -0
  297. package/expansion-packs/bmad-godot-game-dev/checklists/game-change-checklist.md +250 -0
  298. package/expansion-packs/bmad-godot-game-dev/checklists/game-design-checklist.md +225 -0
  299. package/expansion-packs/bmad-godot-game-dev/checklists/game-po-checklist.md +448 -0
  300. package/expansion-packs/bmad-godot-game-dev/checklists/game-story-dod-checklist.md +202 -0
  301. package/expansion-packs/bmad-godot-game-dev/config.yaml +30 -0
  302. package/expansion-packs/bmad-godot-game-dev/data/bmad-kb.md +811 -0
  303. package/expansion-packs/bmad-godot-game-dev/data/brainstorming-techniques.md +36 -0
  304. package/expansion-packs/bmad-godot-game-dev/data/development-guidelines.md +893 -0
  305. package/expansion-packs/bmad-godot-game-dev/data/elicitation-methods.md +156 -0
  306. package/expansion-packs/bmad-godot-game-dev/data/technical-preferences.md +3 -0
  307. package/expansion-packs/bmad-godot-game-dev/tasks/advanced-elicitation.md +110 -0
  308. package/expansion-packs/bmad-godot-game-dev/tasks/apply-qa-fixes.md +224 -0
  309. package/expansion-packs/bmad-godot-game-dev/tasks/brownfield-create-epic.md +162 -0
  310. package/expansion-packs/bmad-godot-game-dev/tasks/brownfield-create-story.md +149 -0
  311. package/expansion-packs/bmad-godot-game-dev/tasks/correct-course-game.md +159 -0
  312. package/expansion-packs/bmad-godot-game-dev/tasks/create-deep-research-prompt.md +278 -0
  313. package/expansion-packs/bmad-godot-game-dev/tasks/create-doc.md +103 -0
  314. package/expansion-packs/bmad-godot-game-dev/tasks/create-game-story.md +202 -0
  315. package/expansion-packs/bmad-godot-game-dev/tasks/document-project.md +343 -0
  316. package/expansion-packs/bmad-godot-game-dev/tasks/execute-checklist.md +88 -0
  317. package/expansion-packs/bmad-godot-game-dev/tasks/facilitate-brainstorming-session.md +136 -0
  318. package/expansion-packs/bmad-godot-game-dev/tasks/game-brownfield-create-epic.md +160 -0
  319. package/expansion-packs/bmad-godot-game-dev/tasks/game-brownfield-create-story.md +147 -0
  320. package/expansion-packs/bmad-godot-game-dev/tasks/game-design-brainstorming.md +290 -0
  321. package/expansion-packs/bmad-godot-game-dev/tasks/game-risk-profile.md +368 -0
  322. package/expansion-packs/bmad-godot-game-dev/tasks/game-test-design.md +219 -0
  323. package/expansion-packs/bmad-godot-game-dev/tasks/generate-ai-frontend-prompt.md +51 -0
  324. package/expansion-packs/bmad-godot-game-dev/tasks/kb-mode-interaction.md +77 -0
  325. package/expansion-packs/bmad-godot-game-dev/tasks/review-game-story.md +364 -0
  326. package/expansion-packs/bmad-godot-game-dev/tasks/shard-doc.md +187 -0
  327. package/expansion-packs/bmad-godot-game-dev/tasks/validate-game-story.md +208 -0
  328. package/expansion-packs/bmad-godot-game-dev/templates/brainstorming-output-tmpl.yaml +156 -0
  329. package/expansion-packs/bmad-godot-game-dev/templates/brownfield-prd-tmpl.yaml +281 -0
  330. package/expansion-packs/bmad-godot-game-dev/templates/competitor-analysis-tmpl.yaml +306 -0
  331. package/expansion-packs/bmad-godot-game-dev/templates/game-architecture-tmpl.yaml +1111 -0
  332. package/expansion-packs/bmad-godot-game-dev/templates/game-brief-tmpl.yaml +356 -0
  333. package/expansion-packs/bmad-godot-game-dev/templates/game-design-doc-tmpl.yaml +724 -0
  334. package/expansion-packs/bmad-godot-game-dev/templates/game-prd-tmpl.yaml +209 -0
  335. package/expansion-packs/bmad-godot-game-dev/templates/game-qa-gate-tmpl.yaml +186 -0
  336. package/expansion-packs/bmad-godot-game-dev/templates/game-story-tmpl.yaml +406 -0
  337. package/expansion-packs/bmad-godot-game-dev/templates/game-ui-spec-tmpl.yaml +601 -0
  338. package/expansion-packs/bmad-godot-game-dev/templates/level-design-doc-tmpl.yaml +620 -0
  339. package/expansion-packs/bmad-godot-game-dev/templates/market-research-tmpl.yaml +418 -0
  340. package/expansion-packs/bmad-godot-game-dev/utils/bmad-doc-template.md +327 -0
  341. package/expansion-packs/bmad-godot-game-dev/utils/workflow-management.md +71 -0
  342. package/expansion-packs/bmad-godot-game-dev/workflows/game-dev-greenfield.yaml +245 -0
  343. package/expansion-packs/bmad-godot-game-dev/workflows/game-prototype.yaml +213 -0
  344. package/expansion-packs/bmad-infrastructure-devops/README.md +147 -0
  345. package/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.md +73 -0
  346. package/expansion-packs/bmad-infrastructure-devops/checklists/infrastructure-checklist.md +486 -0
  347. package/expansion-packs/bmad-infrastructure-devops/config.yaml +10 -0
  348. package/expansion-packs/bmad-infrastructure-devops/data/bmad-kb.md +307 -0
  349. package/expansion-packs/bmad-infrastructure-devops/tasks/review-infrastructure.md +161 -0
  350. package/expansion-packs/bmad-infrastructure-devops/tasks/validate-infrastructure.md +155 -0
  351. package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-architecture-tmpl.yaml +425 -0
  352. package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.yaml +630 -0
  353. package/package.json +116 -0
  354. package/prettier.config.mjs +32 -0
  355. package/tools/bmad-npx-wrapper.js +39 -0
  356. package/tools/builders/web-builder.js +675 -0
  357. package/tools/bump-all-versions.js +115 -0
  358. package/tools/bump-expansion-version.js +90 -0
  359. package/tools/cli.js +152 -0
  360. package/tools/flattener/aggregate.js +76 -0
  361. package/tools/flattener/binary.js +80 -0
  362. package/tools/flattener/discovery.js +71 -0
  363. package/tools/flattener/files.js +35 -0
  364. package/tools/flattener/ignoreRules.js +178 -0
  365. package/tools/flattener/main.js +568 -0
  366. package/tools/flattener/projectRoot.js +206 -0
  367. package/tools/flattener/prompts.js +44 -0
  368. package/tools/flattener/stats.helpers.js +395 -0
  369. package/tools/flattener/stats.js +80 -0
  370. package/tools/flattener/test-matrix.js +413 -0
  371. package/tools/flattener/xml.js +88 -0
  372. package/tools/implement-fork-friendly-ci.sh +229 -0
  373. package/tools/installer/README.md +8 -0
  374. package/tools/installer/bin/bmad.js +633 -0
  375. package/tools/installer/config/ide-agent-config.yaml +58 -0
  376. package/tools/installer/config/install.config.yaml +184 -0
  377. package/tools/installer/lib/config-loader.js +257 -0
  378. package/tools/installer/lib/dependency-manager.js +383 -0
  379. package/tools/installer/lib/file-manager.js +394 -0
  380. package/tools/installer/lib/ide-base-setup.js +228 -0
  381. package/tools/installer/lib/ide-setup.js +2461 -0
  382. package/tools/installer/lib/installer.js +2094 -0
  383. package/tools/installer/lib/memory-profiler.js +225 -0
  384. package/tools/installer/lib/module-manager.js +114 -0
  385. package/tools/installer/lib/resource-locator.js +308 -0
  386. package/tools/installer/package.json +47 -0
  387. package/tools/lib/dependency-resolver.js +175 -0
  388. package/tools/lib/yaml-utils.js +29 -0
  389. package/tools/md-assets/web-agent-startup-instructions.md +39 -0
  390. package/tools/preview-release-notes.js +66 -0
  391. package/tools/setup-hooks.sh +37 -0
  392. package/tools/shared/bannerArt.js +105 -0
  393. package/tools/sync-installer-version.js +32 -0
  394. package/tools/sync-version.sh +23 -0
  395. package/tools/update-expansion-version.js +53 -0
  396. package/tools/upgraders/v3-to-v4-upgrader.js +673 -0
  397. package/tools/version-bump.js +94 -0
  398. package/tools/yaml-format.js +253 -0
@@ -0,0 +1,568 @@
1
+ const { Command } = require('commander');
2
+ const fs = require('fs-extra');
3
+ const path = require('node:path');
4
+ const process = require('node:process');
5
+
6
+ // Modularized components
7
+ const { findProjectRoot } = require('./projectRoot.js');
8
+ const { promptYesNo, promptPath } = require('./prompts.js');
9
+ const { discoverFiles, filterFiles, aggregateFileContents } = require('./files.js');
10
+ const { generateXMLOutput } = require('./xml.js');
11
+ const { calculateStatistics } = require('./stats.js');
12
+
13
+ /**
14
+ * Recursively discover all files in a directory
15
+ * @param {string} rootDir - The root directory to scan
16
+ * @returns {Promise<string[]>} Array of file paths
17
+ */
18
+
19
+ /**
20
+ * Parse .gitignore file and return ignore patterns
21
+ * @param {string} gitignorePath - Path to .gitignore file
22
+ * @returns {Promise<string[]>} Array of ignore patterns
23
+ */
24
+
25
+ /**
26
+ * Check if a file is binary using file command and heuristics
27
+ * @param {string} filePath - Path to the file
28
+ * @returns {Promise<boolean>} True if file is binary
29
+ */
30
+
31
+ /**
32
+ * Read and aggregate content from text files
33
+ * @param {string[]} files - Array of file paths
34
+ * @param {string} rootDir - The root directory
35
+ * @param {Object} spinner - Optional spinner instance for progress display
36
+ * @returns {Promise<Object>} Object containing file contents and metadata
37
+ */
38
+
39
+ /**
40
+ * Generate XML output with aggregated file contents using streaming
41
+ * @param {Object} aggregatedContent - The aggregated content object
42
+ * @param {string} outputPath - The output file path
43
+ * @returns {Promise<void>} Promise that resolves when writing is complete
44
+ */
45
+
46
+ /**
47
+ * Calculate statistics for the processed files
48
+ * @param {Object} aggregatedContent - The aggregated content object
49
+ * @param {number} xmlFileSize - The size of the generated XML file in bytes
50
+ * @returns {Object} Statistics object
51
+ */
52
+
53
+ /**
54
+ * Filter files based on .gitignore patterns
55
+ * @param {string[]} files - Array of file paths
56
+ * @param {string} rootDir - The root directory
57
+ * @returns {Promise<string[]>} Filtered array of file paths
58
+ */
59
+
60
+ /**
61
+ * Attempt to find the project root by walking up from startDir
62
+ * Looks for common project markers like .git, package.json, pyproject.toml, etc.
63
+ * @param {string} startDir
64
+ * @returns {Promise<string|null>} project root directory or null if not found
65
+ */
66
+
67
+ const program = new Command();
68
+
69
+ program
70
+ .name('bmad-flatten')
71
+ .description('BMAD-METHODā„¢ codebase flattener tool')
72
+ .version('1.0.0')
73
+ .option('-i, --input <path>', 'Input directory to flatten', process.cwd())
74
+ .option('-o, --output <path>', 'Output file path', 'flattened-codebase.xml')
75
+ .action(async (options) => {
76
+ let inputDir = path.resolve(options.input);
77
+ let outputPath = path.resolve(options.output);
78
+
79
+ // Detect if user explicitly provided -i/--input or -o/--output
80
+ const argv = process.argv.slice(2);
81
+ const userSpecifiedInput = argv.some(
82
+ (a) => a === '-i' || a === '--input' || a.startsWith('--input='),
83
+ );
84
+ const userSpecifiedOutput = argv.some(
85
+ (a) => a === '-o' || a === '--output' || a.startsWith('--output='),
86
+ );
87
+ const noPathArguments = !userSpecifiedInput && !userSpecifiedOutput;
88
+
89
+ if (noPathArguments) {
90
+ const detectedRoot = await findProjectRoot(process.cwd());
91
+ const suggestedOutput = detectedRoot
92
+ ? path.join(detectedRoot, 'flattened-codebase.xml')
93
+ : path.resolve('flattened-codebase.xml');
94
+
95
+ if (detectedRoot) {
96
+ const useDefaults = await promptYesNo(
97
+ `Detected project root at "${detectedRoot}". Use it as input and write output to "${suggestedOutput}"?`,
98
+ true,
99
+ );
100
+ if (useDefaults) {
101
+ inputDir = detectedRoot;
102
+ outputPath = suggestedOutput;
103
+ } else {
104
+ inputDir = await promptPath('Enter input directory path', process.cwd());
105
+ outputPath = await promptPath(
106
+ 'Enter output file path',
107
+ path.join(inputDir, 'flattened-codebase.xml'),
108
+ );
109
+ }
110
+ } else {
111
+ console.log('Could not auto-detect a project root.');
112
+ inputDir = await promptPath('Enter input directory path', process.cwd());
113
+ outputPath = await promptPath(
114
+ 'Enter output file path',
115
+ path.join(inputDir, 'flattened-codebase.xml'),
116
+ );
117
+ }
118
+ }
119
+
120
+ // Ensure output directory exists
121
+ await fs.ensureDir(path.dirname(outputPath));
122
+
123
+ try {
124
+ // Verify input directory exists
125
+ if (!(await fs.pathExists(inputDir))) {
126
+ console.error(`āŒ Error: Input directory does not exist: ${inputDir}`);
127
+ process.exit(1);
128
+ }
129
+
130
+ // Import ora dynamically
131
+ const { default: ora } = await import('ora');
132
+
133
+ // Start file discovery with spinner
134
+ const discoverySpinner = ora('šŸ” Discovering files...').start();
135
+ const files = await discoverFiles(inputDir);
136
+ const filteredFiles = await filterFiles(files, inputDir);
137
+ discoverySpinner.succeed(`šŸ“ Found ${filteredFiles.length} files to include`);
138
+
139
+ // Process files with progress tracking
140
+ console.log('Reading file contents');
141
+ const processingSpinner = ora('šŸ“„ Processing files...').start();
142
+ const aggregatedContent = await aggregateFileContents(
143
+ filteredFiles,
144
+ inputDir,
145
+ processingSpinner,
146
+ );
147
+ processingSpinner.succeed(
148
+ `āœ… Processed ${aggregatedContent.processedFiles}/${filteredFiles.length} files`,
149
+ );
150
+ if (aggregatedContent.errors.length > 0) {
151
+ console.log(`Errors: ${aggregatedContent.errors.length}`);
152
+ }
153
+
154
+ // Generate XML output using streaming
155
+ const xmlSpinner = ora('šŸ”§ Generating XML output...').start();
156
+ await generateXMLOutput(aggregatedContent, outputPath);
157
+ xmlSpinner.succeed('šŸ“ XML generation completed');
158
+
159
+ // Calculate and display statistics
160
+ const outputStats = await fs.stat(outputPath);
161
+ const stats = await calculateStatistics(aggregatedContent, outputStats.size, inputDir);
162
+
163
+ // Display completion summary
164
+ console.log('\nšŸ“Š Completion Summary:');
165
+ console.log(
166
+ `āœ… Successfully processed ${filteredFiles.length} files into ${path.basename(outputPath)}`,
167
+ );
168
+ console.log(`šŸ“ Output file: ${outputPath}`);
169
+ console.log(`šŸ“ Total source size: ${stats.totalSize}`);
170
+ console.log(`šŸ“„ Generated XML size: ${stats.xmlSize}`);
171
+ console.log(`šŸ“ Total lines of code: ${stats.totalLines.toLocaleString()}`);
172
+ console.log(`šŸ”¢ Estimated tokens: ${stats.estimatedTokens}`);
173
+ console.log(
174
+ `šŸ“Š File breakdown: ${stats.textFiles} text, ${stats.binaryFiles} binary, ${stats.errorFiles} errors\n`,
175
+ );
176
+
177
+ // Ask user if they want detailed stats + markdown report
178
+ const generateDetailed = await promptYesNo(
179
+ 'Generate detailed stats (console + markdown) now?',
180
+ true,
181
+ );
182
+
183
+ if (generateDetailed) {
184
+ // Additional detailed stats
185
+ console.log('\nšŸ“ˆ Size Percentiles:');
186
+ console.log(
187
+ ` Avg: ${Math.round(stats.avgFileSize).toLocaleString()} B, Median: ${Math.round(
188
+ stats.medianFileSize,
189
+ ).toLocaleString()} B, p90: ${stats.p90.toLocaleString()} B, p95: ${stats.p95.toLocaleString()} B, p99: ${stats.p99.toLocaleString()} B`,
190
+ );
191
+
192
+ if (Array.isArray(stats.histogram) && stats.histogram.length > 0) {
193
+ console.log('\n🧮 Size Histogram:');
194
+ for (const b of stats.histogram.slice(0, 2)) {
195
+ console.log(` ${b.label}: ${b.count} files, ${b.bytes.toLocaleString()} bytes`);
196
+ }
197
+ if (stats.histogram.length > 2) {
198
+ console.log(` … and ${stats.histogram.length - 2} more buckets`);
199
+ }
200
+ }
201
+
202
+ if (Array.isArray(stats.byExtension) && stats.byExtension.length > 0) {
203
+ const topExt = stats.byExtension.slice(0, 2);
204
+ console.log('\nšŸ“¦ Top Extensions:');
205
+ for (const e of topExt) {
206
+ const pct = stats.totalBytes ? (e.bytes / stats.totalBytes) * 100 : 0;
207
+ console.log(
208
+ ` ${e.ext}: ${e.count} files, ${e.bytes.toLocaleString()} bytes (${pct.toFixed(
209
+ 2,
210
+ )}%)`,
211
+ );
212
+ }
213
+ if (stats.byExtension.length > 2) {
214
+ console.log(` … and ${stats.byExtension.length - 2} more extensions`);
215
+ }
216
+ }
217
+
218
+ if (Array.isArray(stats.byDirectory) && stats.byDirectory.length > 0) {
219
+ const topDir = stats.byDirectory.slice(0, 2);
220
+ console.log('\nšŸ“‚ Top Directories:');
221
+ for (const d of topDir) {
222
+ const pct = stats.totalBytes ? (d.bytes / stats.totalBytes) * 100 : 0;
223
+ console.log(
224
+ ` ${d.dir}: ${d.count} files, ${d.bytes.toLocaleString()} bytes (${pct.toFixed(
225
+ 2,
226
+ )}%)`,
227
+ );
228
+ }
229
+ if (stats.byDirectory.length > 2) {
230
+ console.log(` … and ${stats.byDirectory.length - 2} more directories`);
231
+ }
232
+ }
233
+
234
+ if (Array.isArray(stats.depthDistribution) && stats.depthDistribution.length > 0) {
235
+ console.log('\n🌳 Depth Distribution:');
236
+ const dd = stats.depthDistribution.slice(0, 2);
237
+ let line = ' ' + dd.map((d) => `${d.depth}:${d.count}`).join(' ');
238
+ if (stats.depthDistribution.length > 2) {
239
+ line += ` … +${stats.depthDistribution.length - 2} more`;
240
+ }
241
+ console.log(line);
242
+ }
243
+
244
+ if (Array.isArray(stats.longestPaths) && stats.longestPaths.length > 0) {
245
+ console.log('\n🧵 Longest Paths:');
246
+ for (const p of stats.longestPaths.slice(0, 2)) {
247
+ console.log(` ${p.path} (${p.length} chars, ${p.size.toLocaleString()} bytes)`);
248
+ }
249
+ if (stats.longestPaths.length > 2) {
250
+ console.log(` … and ${stats.longestPaths.length - 2} more paths`);
251
+ }
252
+ }
253
+
254
+ if (stats.temporal) {
255
+ console.log('\nā±ļø Temporal:');
256
+ if (stats.temporal.oldest) {
257
+ console.log(
258
+ ` Oldest: ${stats.temporal.oldest.path} (${stats.temporal.oldest.mtime})`,
259
+ );
260
+ }
261
+ if (stats.temporal.newest) {
262
+ console.log(
263
+ ` Newest: ${stats.temporal.newest.path} (${stats.temporal.newest.mtime})`,
264
+ );
265
+ }
266
+ if (Array.isArray(stats.temporal.ageBuckets)) {
267
+ console.log(' Age buckets:');
268
+ for (const b of stats.temporal.ageBuckets.slice(0, 2)) {
269
+ console.log(` ${b.label}: ${b.count} files, ${b.bytes.toLocaleString()} bytes`);
270
+ }
271
+ if (stats.temporal.ageBuckets.length > 2) {
272
+ console.log(` … and ${stats.temporal.ageBuckets.length - 2} more buckets`);
273
+ }
274
+ }
275
+ }
276
+
277
+ if (stats.quality) {
278
+ console.log('\nāœ… Quality Signals:');
279
+ console.log(` Zero-byte files: ${stats.quality.zeroByteFiles}`);
280
+ console.log(` Empty text files: ${stats.quality.emptyTextFiles}`);
281
+ console.log(` Hidden files: ${stats.quality.hiddenFiles}`);
282
+ console.log(` Symlinks: ${stats.quality.symlinks}`);
283
+ console.log(
284
+ ` Large files (>= ${(stats.quality.largeThreshold / (1024 * 1024)).toFixed(
285
+ 0,
286
+ )} MB): ${stats.quality.largeFilesCount}`,
287
+ );
288
+ console.log(
289
+ ` Suspiciously large files (>= 100 MB): ${stats.quality.suspiciousLargeFilesCount}`,
290
+ );
291
+ }
292
+
293
+ if (Array.isArray(stats.duplicateCandidates) && stats.duplicateCandidates.length > 0) {
294
+ console.log('\n🧬 Duplicate Candidates:');
295
+ for (const d of stats.duplicateCandidates.slice(0, 2)) {
296
+ console.log(` ${d.reason}: ${d.count} files @ ${d.size.toLocaleString()} bytes`);
297
+ }
298
+ if (stats.duplicateCandidates.length > 2) {
299
+ console.log(` … and ${stats.duplicateCandidates.length - 2} more groups`);
300
+ }
301
+ }
302
+
303
+ if (typeof stats.compressibilityRatio === 'number') {
304
+ console.log(
305
+ `\nšŸ—œļø Compressibility ratio (sampled): ${(stats.compressibilityRatio * 100).toFixed(
306
+ 2,
307
+ )}%`,
308
+ );
309
+ }
310
+
311
+ if (stats.git && stats.git.isRepo) {
312
+ console.log('\nšŸ”§ Git:');
313
+ console.log(
314
+ ` Tracked: ${stats.git.trackedCount} files, ${stats.git.trackedBytes.toLocaleString()} bytes`,
315
+ );
316
+ console.log(
317
+ ` Untracked: ${stats.git.untrackedCount} files, ${stats.git.untrackedBytes.toLocaleString()} bytes`,
318
+ );
319
+ if (Array.isArray(stats.git.lfsCandidates) && stats.git.lfsCandidates.length > 0) {
320
+ console.log(' LFS candidates (top 2):');
321
+ for (const f of stats.git.lfsCandidates.slice(0, 2)) {
322
+ console.log(` ${f.path} (${f.size.toLocaleString()} bytes)`);
323
+ }
324
+ if (stats.git.lfsCandidates.length > 2) {
325
+ console.log(` … and ${stats.git.lfsCandidates.length - 2} more`);
326
+ }
327
+ }
328
+ }
329
+
330
+ if (Array.isArray(stats.largestFiles) && stats.largestFiles.length > 0) {
331
+ console.log('\nšŸ“š Largest Files (top 2):');
332
+ for (const f of stats.largestFiles.slice(0, 2)) {
333
+ // Show LOC for text files when available; omit ext and mtime
334
+ let locStr = '';
335
+ if (!f.isBinary && Array.isArray(aggregatedContent?.textFiles)) {
336
+ const tf = aggregatedContent.textFiles.find((t) => t.path === f.path);
337
+ if (tf && typeof tf.lines === 'number') {
338
+ locStr = `, LOC: ${tf.lines.toLocaleString()}`;
339
+ }
340
+ }
341
+ console.log(
342
+ ` ${f.path} – ${f.sizeFormatted} (${f.percentOfTotal.toFixed(2)}%)${locStr}`,
343
+ );
344
+ }
345
+ if (stats.largestFiles.length > 2) {
346
+ console.log(` … and ${stats.largestFiles.length - 2} more files`);
347
+ }
348
+ }
349
+
350
+ // Write a comprehensive markdown report next to the XML
351
+ {
352
+ const mdPath = outputPath.endsWith('.xml')
353
+ ? outputPath.replace(/\.xml$/i, '.stats.md')
354
+ : outputPath + '.stats.md';
355
+ try {
356
+ const pct = (num, den) => (den ? (num / den) * 100 : 0);
357
+ const md = [];
358
+ md.push(
359
+ `# 🧾 Flatten Stats for ${path.basename(outputPath)}`,
360
+ '',
361
+ '## šŸ“Š Summary',
362
+ `- Total source size: ${stats.totalSize}`,
363
+ `- Generated XML size: ${stats.xmlSize}`,
364
+ `- Total lines of code: ${stats.totalLines.toLocaleString()}`,
365
+ `- Estimated tokens: ${stats.estimatedTokens}`,
366
+ `- File breakdown: ${stats.textFiles} text, ${stats.binaryFiles} binary, ${stats.errorFiles} errors`,
367
+ '',
368
+ '## šŸ“ˆ Size Percentiles',
369
+ `Avg: ${Math.round(stats.avgFileSize).toLocaleString()} B, Median: ${Math.round(
370
+ stats.medianFileSize,
371
+ ).toLocaleString()} B, p90: ${stats.p90.toLocaleString()} B, p95: ${stats.p95.toLocaleString()} B, p99: ${stats.p99.toLocaleString()} B`,
372
+ '',
373
+ );
374
+
375
+ // Histogram
376
+ if (Array.isArray(stats.histogram) && stats.histogram.length > 0) {
377
+ md.push(
378
+ '## 🧮 Size Histogram',
379
+ '| Bucket | Files | Bytes |',
380
+ '| --- | ---: | ---: |',
381
+ );
382
+ for (const b of stats.histogram) {
383
+ md.push(`| ${b.label} | ${b.count} | ${b.bytes.toLocaleString()} |`);
384
+ }
385
+ md.push('');
386
+ }
387
+
388
+ // Top Extensions
389
+ if (Array.isArray(stats.byExtension) && stats.byExtension.length > 0) {
390
+ md.push(
391
+ '## šŸ“¦ Top Extensions by Bytes (Top 20)',
392
+ '| Ext | Files | Bytes | % of total |',
393
+ '| --- | ---: | ---: | ---: |',
394
+ );
395
+ for (const e of stats.byExtension.slice(0, 20)) {
396
+ const p = pct(e.bytes, stats.totalBytes);
397
+ md.push(
398
+ `| ${e.ext} | ${e.count} | ${e.bytes.toLocaleString()} | ${p.toFixed(2)}% |`,
399
+ );
400
+ }
401
+ md.push('');
402
+ }
403
+
404
+ // Top Directories
405
+ if (Array.isArray(stats.byDirectory) && stats.byDirectory.length > 0) {
406
+ md.push(
407
+ '## šŸ“‚ Top Directories by Bytes (Top 20)',
408
+ '| Directory | Files | Bytes | % of total |',
409
+ '| --- | ---: | ---: | ---: |',
410
+ );
411
+ for (const d of stats.byDirectory.slice(0, 20)) {
412
+ const p = pct(d.bytes, stats.totalBytes);
413
+ md.push(
414
+ `| ${d.dir} | ${d.count} | ${d.bytes.toLocaleString()} | ${p.toFixed(2)}% |`,
415
+ );
416
+ }
417
+ md.push('');
418
+ }
419
+
420
+ // Depth distribution
421
+ if (Array.isArray(stats.depthDistribution) && stats.depthDistribution.length > 0) {
422
+ md.push('## 🌳 Depth Distribution', '| Depth | Count |', '| ---: | ---: |');
423
+ for (const d of stats.depthDistribution) {
424
+ md.push(`| ${d.depth} | ${d.count} |`);
425
+ }
426
+ md.push('');
427
+ }
428
+
429
+ // Longest paths
430
+ if (Array.isArray(stats.longestPaths) && stats.longestPaths.length > 0) {
431
+ md.push(
432
+ '## 🧵 Longest Paths (Top 25)',
433
+ '| Path | Length | Bytes |',
434
+ '| --- | ---: | ---: |',
435
+ );
436
+ for (const pth of stats.longestPaths) {
437
+ md.push(`| ${pth.path} | ${pth.length} | ${pth.size.toLocaleString()} |`);
438
+ }
439
+ md.push('');
440
+ }
441
+
442
+ // Temporal
443
+ if (stats.temporal) {
444
+ md.push('## ā±ļø Temporal');
445
+ if (stats.temporal.oldest) {
446
+ md.push(`- Oldest: ${stats.temporal.oldest.path} (${stats.temporal.oldest.mtime})`);
447
+ }
448
+ if (stats.temporal.newest) {
449
+ md.push(`- Newest: ${stats.temporal.newest.path} (${stats.temporal.newest.mtime})`);
450
+ }
451
+ if (Array.isArray(stats.temporal.ageBuckets)) {
452
+ md.push('', '| Age | Files | Bytes |', '| --- | ---: | ---: |');
453
+ for (const b of stats.temporal.ageBuckets) {
454
+ md.push(`| ${b.label} | ${b.count} | ${b.bytes.toLocaleString()} |`);
455
+ }
456
+ }
457
+ md.push('');
458
+ }
459
+
460
+ // Quality signals
461
+ if (stats.quality) {
462
+ md.push(
463
+ '## āœ… Quality Signals',
464
+ `- Zero-byte files: ${stats.quality.zeroByteFiles}`,
465
+ `- Empty text files: ${stats.quality.emptyTextFiles}`,
466
+ `- Hidden files: ${stats.quality.hiddenFiles}`,
467
+ `- Symlinks: ${stats.quality.symlinks}`,
468
+ `- Large files (>= ${(stats.quality.largeThreshold / (1024 * 1024)).toFixed(0)} MB): ${stats.quality.largeFilesCount}`,
469
+ `- Suspiciously large files (>= 100 MB): ${stats.quality.suspiciousLargeFilesCount}`,
470
+ '',
471
+ );
472
+ }
473
+
474
+ // Duplicates
475
+ if (Array.isArray(stats.duplicateCandidates) && stats.duplicateCandidates.length > 0) {
476
+ md.push(
477
+ '## 🧬 Duplicate Candidates',
478
+ '| Reason | Files | Size (bytes) |',
479
+ '| --- | ---: | ---: |',
480
+ );
481
+ for (const d of stats.duplicateCandidates) {
482
+ md.push(`| ${d.reason} | ${d.count} | ${d.size.toLocaleString()} |`);
483
+ }
484
+ md.push('', '### 🧬 Duplicate Groups Details');
485
+ let dupIndex = 1;
486
+ for (const d of stats.duplicateCandidates) {
487
+ md.push(
488
+ `#### Group ${dupIndex}: ${d.count} files @ ${d.size.toLocaleString()} bytes (${d.reason})`,
489
+ );
490
+ if (Array.isArray(d.files) && d.files.length > 0) {
491
+ for (const fp of d.files) {
492
+ md.push(`- ${fp}`);
493
+ }
494
+ } else {
495
+ md.push('- (file list unavailable)');
496
+ }
497
+ md.push('');
498
+ dupIndex++;
499
+ }
500
+ md.push('');
501
+ }
502
+
503
+ // Compressibility
504
+ if (typeof stats.compressibilityRatio === 'number') {
505
+ md.push(
506
+ '## šŸ—œļø Compressibility',
507
+ `Sampled compressibility ratio: ${(stats.compressibilityRatio * 100).toFixed(2)}%`,
508
+ '',
509
+ );
510
+ }
511
+
512
+ // Git
513
+ if (stats.git && stats.git.isRepo) {
514
+ md.push(
515
+ '## šŸ”§ Git',
516
+ `- Tracked: ${stats.git.trackedCount} files, ${stats.git.trackedBytes.toLocaleString()} bytes`,
517
+ `- Untracked: ${stats.git.untrackedCount} files, ${stats.git.untrackedBytes.toLocaleString()} bytes`,
518
+ );
519
+ if (Array.isArray(stats.git.lfsCandidates) && stats.git.lfsCandidates.length > 0) {
520
+ md.push('', '### šŸ“¦ LFS Candidates (Top 20)', '| Path | Bytes |', '| --- | ---: |');
521
+ for (const f of stats.git.lfsCandidates.slice(0, 20)) {
522
+ md.push(`| ${f.path} | ${f.size.toLocaleString()} |`);
523
+ }
524
+ }
525
+ md.push('');
526
+ }
527
+
528
+ // Largest Files
529
+ if (Array.isArray(stats.largestFiles) && stats.largestFiles.length > 0) {
530
+ md.push(
531
+ '## šŸ“š Largest Files (Top 50)',
532
+ '| Path | Size | % of total | LOC |',
533
+ '| --- | ---: | ---: | ---: |',
534
+ );
535
+ for (const f of stats.largestFiles) {
536
+ let loc = '';
537
+ if (!f.isBinary && Array.isArray(aggregatedContent?.textFiles)) {
538
+ const tf = aggregatedContent.textFiles.find((t) => t.path === f.path);
539
+ if (tf && typeof tf.lines === 'number') {
540
+ loc = tf.lines.toLocaleString();
541
+ }
542
+ }
543
+ md.push(
544
+ `| ${f.path} | ${f.sizeFormatted} | ${f.percentOfTotal.toFixed(2)}% | ${loc} |`,
545
+ );
546
+ }
547
+ md.push('');
548
+ }
549
+
550
+ await fs.writeFile(mdPath, md.join('\n'));
551
+ console.log(`\n🧾 Detailed stats report written to: ${mdPath}`);
552
+ } catch (error) {
553
+ console.warn(`āš ļø Failed to write stats markdown: ${error.message}`);
554
+ }
555
+ }
556
+ }
557
+ } catch (error) {
558
+ console.error('āŒ Critical error:', error.message);
559
+ console.error('An unexpected error occurred.');
560
+ process.exit(1);
561
+ }
562
+ });
563
+
564
+ if (require.main === module) {
565
+ program.parse();
566
+ }
567
+
568
+ module.exports = program;