agentvibes 2.17.2 → 2.17.4

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 (339) hide show
  1. package/.bmad/_cfg/agent-manifest.csv +11 -0
  2. package/.bmad/_cfg/agent-voice-map.csv +11 -0
  3. package/.bmad/_cfg/agents/bmm-analyst.customize.yaml +42 -0
  4. package/.bmad/_cfg/agents/bmm-architect.customize.yaml +42 -0
  5. package/.bmad/_cfg/agents/bmm-dev.customize.yaml +42 -0
  6. package/.bmad/_cfg/agents/bmm-frame-expert.customize.yaml +42 -0
  7. package/.bmad/_cfg/agents/bmm-pm.customize.yaml +42 -0
  8. package/.bmad/_cfg/agents/bmm-sm.customize.yaml +42 -0
  9. package/.bmad/_cfg/agents/bmm-tea.customize.yaml +42 -0
  10. package/.bmad/_cfg/agents/bmm-tech-writer.customize.yaml +42 -0
  11. package/.bmad/_cfg/agents/bmm-ux-designer.customize.yaml +42 -0
  12. package/.bmad/_cfg/agents/core-bmad-master.customize.yaml +42 -0
  13. package/.bmad/_cfg/files-manifest.csv +243 -0
  14. package/.bmad/_cfg/ides/claude-code.yaml +6 -0
  15. package/.bmad/_cfg/manifest.yaml +9 -0
  16. package/.bmad/_cfg/task-manifest.csv +5 -0
  17. package/.bmad/_cfg/tool-manifest.csv +2 -0
  18. package/.bmad/_cfg/workflow-manifest.csv +38 -0
  19. package/.bmad/bmm/README.md +128 -0
  20. package/.bmad/bmm/agents/analyst.md +79 -0
  21. package/.bmad/bmm/agents/analyst.md.backup-pre-tts +75 -0
  22. package/.bmad/bmm/agents/architect.md +80 -0
  23. package/.bmad/bmm/agents/dev.md +70 -0
  24. package/.bmad/bmm/agents/frame-expert.md +72 -0
  25. package/.bmad/bmm/agents/pm.md +84 -0
  26. package/.bmad/bmm/agents/sm.md +93 -0
  27. package/.bmad/bmm/agents/tea.md +80 -0
  28. package/.bmad/bmm/agents/tech-writer.md +84 -0
  29. package/.bmad/bmm/agents/ux-designer.md +79 -0
  30. package/.bmad/bmm/config.yaml +17 -0
  31. package/.bmad/bmm/docs/README.md +236 -0
  32. package/.bmad/bmm/docs/agents-guide.md +1058 -0
  33. package/.bmad/bmm/docs/brownfield-guide.md +762 -0
  34. package/.bmad/bmm/docs/enterprise-agentic-development.md +686 -0
  35. package/.bmad/bmm/docs/faq.md +588 -0
  36. package/.bmad/bmm/docs/glossary.md +320 -0
  37. package/.bmad/bmm/docs/party-mode.md +224 -0
  38. package/.bmad/bmm/docs/quick-spec-flow.md +652 -0
  39. package/.bmad/bmm/docs/quick-start.md +376 -0
  40. package/.bmad/bmm/docs/scale-adaptive-system.md +612 -0
  41. package/.bmad/bmm/docs/test-architecture.md +396 -0
  42. package/.bmad/bmm/docs/workflow-architecture-reference.md +366 -0
  43. package/.bmad/bmm/docs/workflow-document-project-reference.md +489 -0
  44. package/.bmad/bmm/docs/workflows-analysis.md +370 -0
  45. package/.bmad/bmm/docs/workflows-implementation.md +286 -0
  46. package/.bmad/bmm/docs/workflows-planning.md +612 -0
  47. package/.bmad/bmm/docs/workflows-solutioning.md +554 -0
  48. package/.bmad/bmm/teams/default-party.csv +20 -0
  49. package/.bmad/bmm/teams/team-fullstack.yaml +13 -0
  50. package/.bmad/bmm/testarch/knowledge/ci-burn-in.md +675 -0
  51. package/.bmad/bmm/testarch/knowledge/component-tdd.md +486 -0
  52. package/.bmad/bmm/testarch/knowledge/contract-testing.md +957 -0
  53. package/.bmad/bmm/testarch/knowledge/data-factories.md +500 -0
  54. package/.bmad/bmm/testarch/knowledge/email-auth.md +721 -0
  55. package/.bmad/bmm/testarch/knowledge/error-handling.md +725 -0
  56. package/.bmad/bmm/testarch/knowledge/feature-flags.md +750 -0
  57. package/.bmad/bmm/testarch/knowledge/fixture-architecture.md +401 -0
  58. package/.bmad/bmm/testarch/knowledge/network-first.md +486 -0
  59. package/.bmad/bmm/testarch/knowledge/nfr-criteria.md +670 -0
  60. package/.bmad/bmm/testarch/knowledge/playwright-config.md +730 -0
  61. package/.bmad/bmm/testarch/knowledge/probability-impact.md +601 -0
  62. package/.bmad/bmm/testarch/knowledge/risk-governance.md +615 -0
  63. package/.bmad/bmm/testarch/knowledge/selective-testing.md +732 -0
  64. package/.bmad/bmm/testarch/knowledge/selector-resilience.md +527 -0
  65. package/.bmad/bmm/testarch/knowledge/test-healing-patterns.md +644 -0
  66. package/.bmad/bmm/testarch/knowledge/test-levels-framework.md +473 -0
  67. package/.bmad/bmm/testarch/knowledge/test-priorities-matrix.md +373 -0
  68. package/.bmad/bmm/testarch/knowledge/test-quality.md +664 -0
  69. package/.bmad/bmm/testarch/knowledge/timing-debugging.md +372 -0
  70. package/.bmad/bmm/testarch/knowledge/visual-debugging.md +524 -0
  71. package/.bmad/bmm/testarch/tea-index.csv +22 -0
  72. package/.bmad/bmm/workflows/1-analysis/brainstorm-project/instructions.md +112 -0
  73. package/.bmad/bmm/workflows/1-analysis/brainstorm-project/project-context.md +25 -0
  74. package/.bmad/bmm/workflows/1-analysis/brainstorm-project/workflow.yaml +26 -0
  75. package/.bmad/bmm/workflows/1-analysis/domain-research/instructions.md +425 -0
  76. package/.bmad/bmm/workflows/1-analysis/domain-research/template.md +180 -0
  77. package/.bmad/bmm/workflows/1-analysis/domain-research/workflow.yaml +28 -0
  78. package/.bmad/bmm/workflows/1-analysis/product-brief/checklist.md +115 -0
  79. package/.bmad/bmm/workflows/1-analysis/product-brief/instructions.md +524 -0
  80. package/.bmad/bmm/workflows/1-analysis/product-brief/template.md +181 -0
  81. package/.bmad/bmm/workflows/1-analysis/product-brief/workflow.yaml +45 -0
  82. package/.bmad/bmm/workflows/1-analysis/research/checklist-deep-prompt.md +144 -0
  83. package/.bmad/bmm/workflows/1-analysis/research/checklist-technical.md +249 -0
  84. package/.bmad/bmm/workflows/1-analysis/research/checklist.md +299 -0
  85. package/.bmad/bmm/workflows/1-analysis/research/claude-code/injections.yaml +114 -0
  86. package/.bmad/bmm/workflows/1-analysis/research/instructions-deep-prompt.md +438 -0
  87. package/.bmad/bmm/workflows/1-analysis/research/instructions-market.md +675 -0
  88. package/.bmad/bmm/workflows/1-analysis/research/instructions-router.md +134 -0
  89. package/.bmad/bmm/workflows/1-analysis/research/instructions-technical.md +534 -0
  90. package/.bmad/bmm/workflows/1-analysis/research/template-deep-prompt.md +94 -0
  91. package/.bmad/bmm/workflows/1-analysis/research/template-market.md +347 -0
  92. package/.bmad/bmm/workflows/1-analysis/research/template-technical.md +245 -0
  93. package/.bmad/bmm/workflows/1-analysis/research/workflow.yaml +44 -0
  94. package/.bmad/bmm/workflows/2-plan-workflows/create-epics-and-stories/epics-template.md +80 -0
  95. package/.bmad/bmm/workflows/2-plan-workflows/create-epics-and-stories/instructions.md +616 -0
  96. package/.bmad/bmm/workflows/2-plan-workflows/create-epics-and-stories/workflow.yaml +53 -0
  97. package/.bmad/bmm/workflows/2-plan-workflows/create-ux-design/checklist.md +310 -0
  98. package/.bmad/bmm/workflows/2-plan-workflows/create-ux-design/instructions.md +1308 -0
  99. package/.bmad/bmm/workflows/2-plan-workflows/create-ux-design/ux-design-template.md +145 -0
  100. package/.bmad/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml +61 -0
  101. package/.bmad/bmm/workflows/2-plan-workflows/prd/checklist.md +346 -0
  102. package/.bmad/bmm/workflows/2-plan-workflows/prd/domain-complexity.csv +13 -0
  103. package/.bmad/bmm/workflows/2-plan-workflows/prd/instructions.md +703 -0
  104. package/.bmad/bmm/workflows/2-plan-workflows/prd/prd-template.md +204 -0
  105. package/.bmad/bmm/workflows/2-plan-workflows/prd/project-types.csv +11 -0
  106. package/.bmad/bmm/workflows/2-plan-workflows/prd/workflow.yaml +52 -0
  107. package/.bmad/bmm/workflows/2-plan-workflows/tech-spec/checklist.md +217 -0
  108. package/.bmad/bmm/workflows/2-plan-workflows/tech-spec/epics-template.md +74 -0
  109. package/.bmad/bmm/workflows/2-plan-workflows/tech-spec/instructions-generate-stories.md +436 -0
  110. package/.bmad/bmm/workflows/2-plan-workflows/tech-spec/instructions.md +980 -0
  111. package/.bmad/bmm/workflows/2-plan-workflows/tech-spec/tech-spec-template.md +181 -0
  112. package/.bmad/bmm/workflows/2-plan-workflows/tech-spec/user-story-template.md +90 -0
  113. package/.bmad/bmm/workflows/2-plan-workflows/tech-spec/workflow.yaml +58 -0
  114. package/.bmad/bmm/workflows/3-solutioning/architecture/architecture-patterns.yaml +321 -0
  115. package/.bmad/bmm/workflows/3-solutioning/architecture/architecture-template.md +103 -0
  116. package/.bmad/bmm/workflows/3-solutioning/architecture/checklist.md +240 -0
  117. package/.bmad/bmm/workflows/3-solutioning/architecture/decision-catalog.yaml +222 -0
  118. package/.bmad/bmm/workflows/3-solutioning/architecture/instructions.md +768 -0
  119. package/.bmad/bmm/workflows/3-solutioning/architecture/pattern-categories.csv +13 -0
  120. package/.bmad/bmm/workflows/3-solutioning/architecture/workflow.yaml +55 -0
  121. package/.bmad/bmm/workflows/3-solutioning/implementation-readiness/checklist.md +169 -0
  122. package/.bmad/bmm/workflows/3-solutioning/implementation-readiness/instructions.md +332 -0
  123. package/.bmad/bmm/workflows/3-solutioning/implementation-readiness/template.md +146 -0
  124. package/.bmad/bmm/workflows/3-solutioning/implementation-readiness/workflow.yaml +62 -0
  125. package/.bmad/bmm/workflows/4-implementation/code-review/backlog_template.md +12 -0
  126. package/.bmad/bmm/workflows/4-implementation/code-review/checklist.md +22 -0
  127. package/.bmad/bmm/workflows/4-implementation/code-review/instructions.md +398 -0
  128. package/.bmad/bmm/workflows/4-implementation/code-review/workflow.yaml +60 -0
  129. package/.bmad/bmm/workflows/4-implementation/correct-course/checklist.md +279 -0
  130. package/.bmad/bmm/workflows/4-implementation/correct-course/instructions.md +206 -0
  131. package/.bmad/bmm/workflows/4-implementation/correct-course/workflow.yaml +56 -0
  132. package/.bmad/bmm/workflows/4-implementation/create-story/checklist.md +240 -0
  133. package/.bmad/bmm/workflows/4-implementation/create-story/instructions.md +256 -0
  134. package/.bmad/bmm/workflows/4-implementation/create-story/template.md +51 -0
  135. package/.bmad/bmm/workflows/4-implementation/create-story/workflow.yaml +71 -0
  136. package/.bmad/bmm/workflows/4-implementation/dev-story/checklist.md +38 -0
  137. package/.bmad/bmm/workflows/4-implementation/dev-story/instructions.md +267 -0
  138. package/.bmad/bmm/workflows/4-implementation/dev-story/workflow.yaml +56 -0
  139. package/.bmad/bmm/workflows/4-implementation/epic-tech-context/checklist.md +17 -0
  140. package/.bmad/bmm/workflows/4-implementation/epic-tech-context/instructions.md +164 -0
  141. package/.bmad/bmm/workflows/4-implementation/epic-tech-context/template.md +76 -0
  142. package/.bmad/bmm/workflows/4-implementation/epic-tech-context/workflow.yaml +57 -0
  143. package/.bmad/bmm/workflows/4-implementation/retrospective/instructions.md +1443 -0
  144. package/.bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml +56 -0
  145. package/.bmad/bmm/workflows/4-implementation/sprint-planning/checklist.md +33 -0
  146. package/.bmad/bmm/workflows/4-implementation/sprint-planning/instructions.md +234 -0
  147. package/.bmad/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +55 -0
  148. package/.bmad/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +49 -0
  149. package/.bmad/bmm/workflows/4-implementation/story-context/checklist.md +16 -0
  150. package/.bmad/bmm/workflows/4-implementation/story-context/context-template.xml +34 -0
  151. package/.bmad/bmm/workflows/4-implementation/story-context/instructions.md +209 -0
  152. package/.bmad/bmm/workflows/4-implementation/story-context/workflow.yaml +61 -0
  153. package/.bmad/bmm/workflows/4-implementation/story-done/instructions.md +111 -0
  154. package/.bmad/bmm/workflows/4-implementation/story-done/workflow.yaml +26 -0
  155. package/.bmad/bmm/workflows/4-implementation/story-ready/instructions.md +117 -0
  156. package/.bmad/bmm/workflows/4-implementation/story-ready/workflow.yaml +23 -0
  157. package/.bmad/bmm/workflows/document-project/checklist.md +245 -0
  158. package/.bmad/bmm/workflows/document-project/documentation-requirements.csv +12 -0
  159. package/.bmad/bmm/workflows/document-project/instructions.md +222 -0
  160. package/.bmad/bmm/workflows/document-project/templates/deep-dive-template.md +345 -0
  161. package/.bmad/bmm/workflows/document-project/templates/index-template.md +169 -0
  162. package/.bmad/bmm/workflows/document-project/templates/project-overview-template.md +103 -0
  163. package/.bmad/bmm/workflows/document-project/templates/project-scan-report-schema.json +160 -0
  164. package/.bmad/bmm/workflows/document-project/templates/source-tree-template.md +135 -0
  165. package/.bmad/bmm/workflows/document-project/workflow.yaml +29 -0
  166. package/.bmad/bmm/workflows/document-project/workflows/deep-dive-instructions.md +298 -0
  167. package/.bmad/bmm/workflows/document-project/workflows/deep-dive.yaml +31 -0
  168. package/.bmad/bmm/workflows/document-project/workflows/full-scan-instructions.md +1106 -0
  169. package/.bmad/bmm/workflows/document-project/workflows/full-scan.yaml +31 -0
  170. package/.bmad/bmm/workflows/frame-expert/_shared/excalidraw-helpers.md +127 -0
  171. package/.bmad/bmm/workflows/frame-expert/_shared/excalidraw-library.json +90 -0
  172. package/.bmad/bmm/workflows/frame-expert/_shared/excalidraw-templates.yaml +127 -0
  173. package/.bmad/bmm/workflows/frame-expert/_shared/validate-json-instructions.md +79 -0
  174. package/.bmad/bmm/workflows/frame-expert/create-dataflow/checklist.md +39 -0
  175. package/.bmad/bmm/workflows/frame-expert/create-dataflow/instructions.md +131 -0
  176. package/.bmad/bmm/workflows/frame-expert/create-dataflow/workflow.yaml +23 -0
  177. package/.bmad/bmm/workflows/frame-expert/create-diagram/checklist.md +43 -0
  178. package/.bmad/bmm/workflows/frame-expert/create-diagram/instructions.md +142 -0
  179. package/.bmad/bmm/workflows/frame-expert/create-diagram/workflow.yaml +24 -0
  180. package/.bmad/bmm/workflows/frame-expert/create-flowchart/checklist.md +49 -0
  181. package/.bmad/bmm/workflows/frame-expert/create-flowchart/instructions.md +242 -0
  182. package/.bmad/bmm/workflows/frame-expert/create-flowchart/workflow.yaml +27 -0
  183. package/.bmad/bmm/workflows/frame-expert/create-wireframe/checklist.md +38 -0
  184. package/.bmad/bmm/workflows/frame-expert/create-wireframe/instructions.md +133 -0
  185. package/.bmad/bmm/workflows/frame-expert/create-wireframe/workflow.yaml +23 -0
  186. package/.bmad/bmm/workflows/techdoc/documentation-standards.md +262 -0
  187. package/.bmad/bmm/workflows/testarch/atdd/atdd-checklist-template.md +363 -0
  188. package/.bmad/bmm/workflows/testarch/atdd/checklist.md +373 -0
  189. package/.bmad/bmm/workflows/testarch/atdd/instructions.md +785 -0
  190. package/.bmad/bmm/workflows/testarch/atdd/workflow.yaml +45 -0
  191. package/.bmad/bmm/workflows/testarch/automate/checklist.md +580 -0
  192. package/.bmad/bmm/workflows/testarch/automate/instructions.md +1303 -0
  193. package/.bmad/bmm/workflows/testarch/automate/workflow.yaml +52 -0
  194. package/.bmad/bmm/workflows/testarch/ci/checklist.md +246 -0
  195. package/.bmad/bmm/workflows/testarch/ci/github-actions-template.yaml +165 -0
  196. package/.bmad/bmm/workflows/testarch/ci/gitlab-ci-template.yaml +128 -0
  197. package/.bmad/bmm/workflows/testarch/ci/instructions.md +517 -0
  198. package/.bmad/bmm/workflows/testarch/ci/workflow.yaml +45 -0
  199. package/.bmad/bmm/workflows/testarch/framework/checklist.md +321 -0
  200. package/.bmad/bmm/workflows/testarch/framework/instructions.md +455 -0
  201. package/.bmad/bmm/workflows/testarch/framework/workflow.yaml +47 -0
  202. package/.bmad/bmm/workflows/testarch/nfr-assess/checklist.md +405 -0
  203. package/.bmad/bmm/workflows/testarch/nfr-assess/instructions.md +722 -0
  204. package/.bmad/bmm/workflows/testarch/nfr-assess/nfr-report-template.md +443 -0
  205. package/.bmad/bmm/workflows/testarch/nfr-assess/workflow.yaml +47 -0
  206. package/.bmad/bmm/workflows/testarch/test-design/checklist.md +234 -0
  207. package/.bmad/bmm/workflows/testarch/test-design/instructions.md +782 -0
  208. package/.bmad/bmm/workflows/testarch/test-design/test-design-template.md +285 -0
  209. package/.bmad/bmm/workflows/testarch/test-design/workflow.yaml +48 -0
  210. package/.bmad/bmm/workflows/testarch/test-review/checklist.md +470 -0
  211. package/.bmad/bmm/workflows/testarch/test-review/instructions.md +608 -0
  212. package/.bmad/bmm/workflows/testarch/test-review/test-review-template.md +388 -0
  213. package/.bmad/bmm/workflows/testarch/test-review/workflow.yaml +46 -0
  214. package/.bmad/bmm/workflows/testarch/trace/checklist.md +654 -0
  215. package/.bmad/bmm/workflows/testarch/trace/instructions.md +1045 -0
  216. package/.bmad/bmm/workflows/testarch/trace/trace-template.md +673 -0
  217. package/.bmad/bmm/workflows/testarch/trace/workflow.yaml +55 -0
  218. package/.bmad/bmm/workflows/workflow-status/init/instructions.md +334 -0
  219. package/.bmad/bmm/workflows/workflow-status/init/workflow.yaml +28 -0
  220. package/.bmad/bmm/workflows/workflow-status/instructions.md +388 -0
  221. package/.bmad/bmm/workflows/workflow-status/paths/enterprise-brownfield.yaml +138 -0
  222. package/.bmad/bmm/workflows/workflow-status/paths/enterprise-greenfield.yaml +126 -0
  223. package/.bmad/bmm/workflows/workflow-status/paths/game-design.yaml +52 -0
  224. package/.bmad/bmm/workflows/workflow-status/paths/method-brownfield.yaml +122 -0
  225. package/.bmad/bmm/workflows/workflow-status/paths/method-greenfield.yaml +113 -0
  226. package/.bmad/bmm/workflows/workflow-status/paths/quick-flow-brownfield.yaml +58 -0
  227. package/.bmad/bmm/workflows/workflow-status/paths/quick-flow-greenfield.yaml +47 -0
  228. package/.bmad/bmm/workflows/workflow-status/project-levels.yaml +59 -0
  229. package/.bmad/bmm/workflows/workflow-status/workflow-status-template.yaml +24 -0
  230. package/.bmad/bmm/workflows/workflow-status/workflow.yaml +28 -0
  231. package/.bmad/core/agents/bmad-master.md +72 -0
  232. package/.bmad/core/agents/bmad-web-orchestrator.agent.xml +113 -0
  233. package/.bmad/core/config.yaml +1 -0
  234. package/.bmad/core/tasks/adv-elicit-methods.csv +39 -0
  235. package/.bmad/core/tasks/advanced-elicitation-methods.csv +21 -0
  236. package/.bmad/core/tasks/advanced-elicitation.xml +106 -0
  237. package/.bmad/core/tasks/index-docs.xml +65 -0
  238. package/.bmad/core/tasks/validate-workflow.xml +89 -0
  239. package/.bmad/core/tasks/workflow.xml +270 -0
  240. package/.bmad/core/tools/shard-doc.xml +109 -0
  241. package/.bmad/core/workflows/brainstorming/README.md +261 -0
  242. package/.bmad/core/workflows/brainstorming/brain-methods.csv +36 -0
  243. package/.bmad/core/workflows/brainstorming/instructions.md +315 -0
  244. package/.bmad/core/workflows/brainstorming/template.md +106 -0
  245. package/.bmad/core/workflows/brainstorming/workflow.yaml +38 -0
  246. package/.bmad/core/workflows/party-mode/instructions.md +203 -0
  247. package/.bmad/core/workflows/party-mode/workflow.yaml +28 -0
  248. package/.bmad/docs/claude-code-instructions.md +25 -0
  249. package/.claude/commands/BMad/analyst.md +88 -0
  250. package/.claude/commands/BMad/architect.md +89 -0
  251. package/.claude/commands/BMad/bmad-master.md +114 -0
  252. package/.claude/commands/BMad/bmad-orchestrator.md +151 -0
  253. package/.claude/commands/BMad/dev.md +85 -0
  254. package/.claude/commands/BMad/pm.md +88 -0
  255. package/.claude/commands/BMad/po.md +83 -0
  256. package/.claude/commands/BMad/qa.md +91 -0
  257. package/.claude/commands/BMad/sm.md +69 -0
  258. package/.claude/commands/BMad/tasks/advanced-elicitation.md +123 -0
  259. package/.claude/commands/BMad/tasks/apply-qa-fixes.md +154 -0
  260. package/.claude/commands/BMad/tasks/brownfield-create-epic.md +166 -0
  261. package/.claude/commands/BMad/tasks/brownfield-create-story.md +153 -0
  262. package/.claude/commands/BMad/tasks/correct-course.md +76 -0
  263. package/.claude/commands/BMad/tasks/create-brownfield-story.md +318 -0
  264. package/.claude/commands/BMad/tasks/create-deep-research-prompt.md +284 -0
  265. package/.claude/commands/BMad/tasks/create-doc.md +107 -0
  266. package/.claude/commands/BMad/tasks/create-next-story.md +118 -0
  267. package/.claude/commands/BMad/tasks/document-project.md +349 -0
  268. package/.claude/commands/BMad/tasks/execute-checklist.md +92 -0
  269. package/.claude/commands/BMad/tasks/facilitate-brainstorming-session.md +142 -0
  270. package/.claude/commands/BMad/tasks/generate-ai-frontend-prompt.md +57 -0
  271. package/.claude/commands/BMad/tasks/index-docs.md +179 -0
  272. package/.claude/commands/BMad/tasks/kb-mode-interaction.md +81 -0
  273. package/.claude/commands/BMad/tasks/nfr-assess.md +349 -0
  274. package/.claude/commands/BMad/tasks/qa-gate.md +167 -0
  275. package/.claude/commands/BMad/tasks/review-story.md +320 -0
  276. package/.claude/commands/BMad/tasks/risk-profile.md +359 -0
  277. package/.claude/commands/BMad/tasks/shard-doc.md +191 -0
  278. package/.claude/commands/BMad/tasks/test-design.md +180 -0
  279. package/.claude/commands/BMad/tasks/trace-requirements.md +270 -0
  280. package/.claude/commands/BMad/tasks/validate-next-story.md +140 -0
  281. package/.claude/commands/BMad/ux-expert.md +73 -0
  282. package/.claude/commands/bmad/bmm/agents/analyst.md +14 -0
  283. package/.claude/commands/bmad/bmm/agents/architect.md +14 -0
  284. package/.claude/commands/bmad/bmm/agents/dev.md +14 -0
  285. package/.claude/commands/bmad/bmm/agents/frame-expert.md +14 -0
  286. package/.claude/commands/bmad/bmm/agents/pm.md +14 -0
  287. package/.claude/commands/bmad/bmm/agents/sm.md +14 -0
  288. package/.claude/commands/bmad/bmm/agents/tea.md +14 -0
  289. package/.claude/commands/bmad/bmm/agents/tech-writer.md +14 -0
  290. package/.claude/commands/bmad/bmm/agents/ux-designer.md +14 -0
  291. package/.claude/commands/bmad/bmm/workflows/architecture.md +13 -0
  292. package/.claude/commands/bmad/bmm/workflows/brainstorm-project.md +13 -0
  293. package/.claude/commands/bmad/bmm/workflows/code-review.md +13 -0
  294. package/.claude/commands/bmad/bmm/workflows/correct-course.md +13 -0
  295. package/.claude/commands/bmad/bmm/workflows/create-dataflow.md +13 -0
  296. package/.claude/commands/bmad/bmm/workflows/create-diagram.md +13 -0
  297. package/.claude/commands/bmad/bmm/workflows/create-epics-and-stories.md +13 -0
  298. package/.claude/commands/bmad/bmm/workflows/create-flowchart.md +13 -0
  299. package/.claude/commands/bmad/bmm/workflows/create-story.md +13 -0
  300. package/.claude/commands/bmad/bmm/workflows/create-ux-design.md +13 -0
  301. package/.claude/commands/bmad/bmm/workflows/create-wireframe.md +13 -0
  302. package/.claude/commands/bmad/bmm/workflows/dev-story.md +13 -0
  303. package/.claude/commands/bmad/bmm/workflows/document-project.md +13 -0
  304. package/.claude/commands/bmad/bmm/workflows/domain-research.md +13 -0
  305. package/.claude/commands/bmad/bmm/workflows/epic-tech-context.md +13 -0
  306. package/.claude/commands/bmad/bmm/workflows/implementation-readiness.md +13 -0
  307. package/.claude/commands/bmad/bmm/workflows/prd.md +13 -0
  308. package/.claude/commands/bmad/bmm/workflows/product-brief.md +13 -0
  309. package/.claude/commands/bmad/bmm/workflows/research.md +13 -0
  310. package/.claude/commands/bmad/bmm/workflows/retrospective.md +13 -0
  311. package/.claude/commands/bmad/bmm/workflows/sprint-planning.md +13 -0
  312. package/.claude/commands/bmad/bmm/workflows/story-context.md +13 -0
  313. package/.claude/commands/bmad/bmm/workflows/story-done.md +13 -0
  314. package/.claude/commands/bmad/bmm/workflows/story-ready.md +13 -0
  315. package/.claude/commands/bmad/bmm/workflows/tech-spec.md +13 -0
  316. package/.claude/commands/bmad/bmm/workflows/workflow-init.md +13 -0
  317. package/.claude/commands/bmad/bmm/workflows/workflow-status.md +13 -0
  318. package/.claude/commands/bmad/core/agents/bmad-master.md +14 -0
  319. package/.claude/commands/bmad/core/tasks/advanced-elicitation.md +9 -0
  320. package/.claude/commands/bmad/core/tasks/index-docs.md +9 -0
  321. package/.claude/commands/bmad/core/tools/shard-doc.md +9 -0
  322. package/.claude/commands/bmad/core/workflows/brainstorming.md +13 -0
  323. package/.claude/commands/bmad/core/workflows/party-mode.md +13 -0
  324. package/.claude/config/background-music-position.txt +26 -0
  325. package/.claude/config/background-music-volume.txt +1 -0
  326. package/.claude/config/background-music.cfg +1 -0
  327. package/.claude/config/tts-verbosity.txt +1 -0
  328. package/.claude/github-star-reminder.txt +1 -0
  329. package/.claude/hooks/background-music-manager.sh +1 -1
  330. package/.claude/hooks/bmad-party-manager.sh +225 -0
  331. package/.claude/hooks/bmad-voice-manager.sh +116 -4
  332. package/.claude/piper-voices-dir.txt +1 -0
  333. package/.mcp.json +30 -0
  334. package/README.md +166 -13
  335. package/mcp-server/server.py +53 -41
  336. package/package.json +6 -2
  337. package/src/commands/install-mcp.js +151 -90
  338. package/src/installer.js +531 -298
  339. package/src/utils/dependency-checker.js +193 -132
package/src/installer.js CHANGED
@@ -117,9 +117,56 @@ function createPageHeaderFooter(pageTitle, currentPage, totalPages, pageOffset =
117
117
  * @param {Object} options - Options for pagination (yes, continueLabel, pageOffset, totalPages, showPreviousOnFirst)
118
118
  * @returns {Promise<void>}
119
119
  */
120
+ /**
121
+ * Build navigation choices for paginated content
122
+ * @param {number} currentPage - Current page index
123
+ * @param {number} totalPages - Total number of pages
124
+ * @param {string} continueLabel - Label for continue button
125
+ * @param {boolean} showPreviousOnFirst - Show previous on first page
126
+ * @returns {Array} Navigation choices
127
+ */
128
+ function buildNavigationChoices(currentPage, totalPages, continueLabel, showPreviousOnFirst) {
129
+ const choices = [];
130
+ const isLastPage = currentPage >= totalPages - 1;
131
+
132
+ if (!isLastPage) {
133
+ choices.push({ name: chalk.green('Next →'), value: 'next' });
134
+ } else {
135
+ choices.push({ name: chalk.cyan(`✓ ${continueLabel.replace('✓ ', '')}`), value: 'continue' });
136
+ }
137
+
138
+ if (currentPage > 0 || showPreviousOnFirst) {
139
+ choices.push({ name: chalk.magentaBright('← Previous'), value: 'prev' });
140
+ }
141
+
142
+ return choices;
143
+ }
144
+
145
+ /**
146
+ * Handle navigation action in paginated content
147
+ * @param {string} action - Navigation action (prev, next, continue)
148
+ * @param {number} currentPage - Current page index
149
+ * @param {boolean} showPreviousOnFirst - Show previous on first page
150
+ * @returns {Object} Navigation result {newPage, shouldExit, shouldReturn}
151
+ */
152
+ function handleNavigationAction(action, currentPage, showPreviousOnFirst) {
153
+ if (action === 'prev') {
154
+ if (currentPage > 0) {
155
+ return { newPage: currentPage - 1, shouldExit: false, shouldReturn: false };
156
+ }
157
+ if (showPreviousOnFirst) {
158
+ return { newPage: currentPage, shouldExit: false, shouldReturn: true };
159
+ }
160
+ } else if (action === 'next') {
161
+ return { newPage: currentPage + 1, shouldExit: false, shouldReturn: false };
162
+ }
163
+
164
+ // Continue action - exit loop
165
+ return { newPage: currentPage, shouldExit: true, shouldReturn: false };
166
+ }
167
+
120
168
  async function showPaginatedContent(pages, options = {}) {
121
169
  if (options.yes || pages.length === 0) {
122
- // In non-interactive mode or no pages, just display all content
123
170
  pages.forEach(page => console.log(page.content));
124
171
  return;
125
172
  }
@@ -131,7 +178,6 @@ async function showPaginatedContent(pages, options = {}) {
131
178
  let currentPage = 0;
132
179
 
133
180
  while (currentPage >= 0 && currentPage < pages.length) {
134
- // Clear screen and show current page with header/footer
135
181
  console.clear();
136
182
 
137
183
  const { header, footer } = createPageHeaderFooter(
@@ -145,35 +191,12 @@ async function showPaginatedContent(pages, options = {}) {
145
191
  console.log('');
146
192
  console.log(pages[currentPage].content);
147
193
 
148
- // Build navigation message with Previous/Next on same line
149
- let navMessage = '';
150
- if (currentPage > 0 && currentPage < pages.length - 1) {
151
- navMessage = `${chalk.cyan('←')} Previous | Next ${chalk.cyan('→')} | ${continueLabel}`;
152
- } else if (currentPage > 0) {
153
- navMessage = `${chalk.cyan('←')} Previous | ${continueLabel}`;
154
- } else if (currentPage < pages.length - 1) {
155
- navMessage = `Next ${chalk.cyan('→')} | ${continueLabel}`;
156
- } else {
157
- navMessage = continueLabel;
158
- }
159
-
160
- // Build navigation choices with colors
161
- const choices = [];
162
- if (currentPage < pages.length - 1) {
163
- choices.push({ name: chalk.green('Next →'), value: 'next' });
164
- } else {
165
- // Only show "Start Installation" on the last page
166
- choices.push({ name: chalk.cyan(`✓ ${continueLabel.replace('✓ ', '')}`), value: 'continue' });
167
- }
168
- if (currentPage > 0 || showPreviousOnFirst) {
169
- choices.push({ name: chalk.magentaBright('← Previous'), value: 'prev' });
170
- }
194
+ const choices = buildNavigationChoices(currentPage, pages.length, continueLabel, showPreviousOnFirst);
171
195
 
172
196
  console.log('');
173
197
  console.log(footer);
174
198
  console.log('');
175
199
 
176
- // Show navigation prompt
177
200
  const { action } = await inquirer.prompt([{
178
201
  type: 'list',
179
202
  name: 'action',
@@ -182,21 +205,121 @@ async function showPaginatedContent(pages, options = {}) {
182
205
  default: currentPage < pages.length - 1 ? 'next' : 'continue'
183
206
  }]);
184
207
 
185
- if (action === 'prev') {
186
- if (currentPage > 0) {
187
- currentPage--;
188
- } else if (showPreviousOnFirst) {
189
- // User clicked Previous on first page - signal to caller
190
- return 'prev';
191
- }
192
- } else if (action === 'next') {
193
- currentPage++;
194
- } else {
195
- // Continue - exit loop
208
+ const navResult = handleNavigationAction(action, currentPage, showPreviousOnFirst);
209
+
210
+ if (navResult.shouldReturn) {
211
+ return 'prev';
212
+ }
213
+
214
+ if (navResult.shouldExit) {
196
215
  console.clear();
197
216
  break;
198
217
  }
218
+
219
+ currentPage = navResult.newPage;
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Get page title by page number
225
+ * @param {number} pageNum - Page number (0-4)
226
+ * @returns {string} Page title
227
+ */
228
+ function getPageTitle(pageNum) {
229
+ const titles = {
230
+ 0: 'System Dependencies',
231
+ 1: 'TTS Provider Configuration',
232
+ 2: 'Voice Selection',
233
+ 3: 'Audio Settings',
234
+ 4: 'Verbosity Settings'
235
+ };
236
+ return titles[pageNum] || 'Configuration';
237
+ }
238
+
239
+ /**
240
+ * Handle Page 0: System Dependencies display
241
+ * @returns {Promise<void>}
242
+ */
243
+ async function handleSystemDependenciesPage() {
244
+ const { checkDependencies, getInstallCommands } = await import('./utils/dependency-checker.js');
245
+ const depResults = checkDependencies();
246
+
247
+ let depContent = chalk.gray('System dependencies are tools AgentVibes needs to function properly.\n');
248
+ depContent += chalk.gray('Required tools must be installed, optional tools enable extra features.\n\n');
249
+
250
+ // Satisfied dependencies
251
+ if (depResults.core.node?.isCompatible) {
252
+ depContent += chalk.green(`✓ Node.js ${depResults.core.node.version}\n`);
253
+ }
254
+ if (depResults.core.python?.isCompatible) {
255
+ depContent += chalk.green(`✓ Python ${depResults.core.python.version}\n`);
256
+ }
257
+ if (depResults.core.bash?.isModern) {
258
+ depContent += chalk.green(`✓ Bash ${depResults.core.bash.version}\n`);
259
+ }
260
+ if (depResults.optional.curl) {
261
+ depContent += chalk.green('✓ curl\n');
262
+ }
263
+ if (depResults.optional.sox) {
264
+ depContent += chalk.green('✓ sox\n');
265
+ }
266
+ if (depResults.optional.ffmpeg) {
267
+ depContent += chalk.green('✓ ffmpeg\n');
268
+ }
269
+ if (depResults.optional.bc) {
270
+ depContent += chalk.green('✓ bc\n');
271
+ }
272
+ if (depResults.optional.flock) {
273
+ depContent += chalk.green('✓ flock\n');
274
+ }
275
+ if (depResults.optional.pipx) {
276
+ depContent += chalk.green('✓ pipx\n');
277
+ }
278
+ if (depResults.optional.audioPlayer) {
279
+ depContent += chalk.green('✓ audio player (paplay/aplay/mpv)\n');
280
+ }
281
+
282
+ // Missing dependencies
283
+ if (Object.keys(depResults.missing).length > 0) {
284
+ depContent += '\n' + chalk.gray('─'.repeat(50)) + '\n\n';
285
+ depContent += chalk.yellow.bold('Missing (Optional):\n\n');
286
+
287
+ if (depResults.missing.curl) depContent += chalk.yellow('⚠ curl - needed for downloads\n');
288
+ if (depResults.missing.sox) depContent += chalk.yellow('⚠ sox - audio effects\n');
289
+ if (depResults.missing.ffmpeg) depContent += chalk.yellow('⚠ ffmpeg - background music\n');
290
+ if (depResults.missing.bc) depContent += chalk.yellow('⚠ bc - audio calculations\n');
291
+ if (depResults.missing.flock) depContent += chalk.yellow('⚠ flock - TTS queue locking\n');
292
+ if (depResults.missing.pipx) depContent += chalk.yellow('⚠ pipx - Piper TTS installation\n');
293
+ if (depResults.missing.audioPlayer) depContent += chalk.yellow('⚠ audio player - playback\n');
294
+
295
+ depContent += '\n' + chalk.gray('TTS will still work without optional tools');
296
+
297
+ // Add install commands
298
+ const os = await import('os');
299
+ const platform = os.platform();
300
+ const installCmds = getInstallCommands(depResults.missing, platform);
301
+
302
+ if (installCmds.length > 0) {
303
+ depContent += '\n\n' + chalk.gray('─'.repeat(50)) + '\n\n';
304
+ depContent += chalk.cyan.bold('To Install Missing Tools:\n\n');
305
+
306
+ installCmds.forEach(({ label, command }) => {
307
+ depContent += chalk.cyan(`${label}:\n`);
308
+ depContent += chalk.white(` ${command}\n\n`);
309
+ });
310
+ }
199
311
  }
312
+
313
+ const depsBoxen = boxen(depContent.trim(), {
314
+ padding: 1,
315
+ margin: 1,
316
+ borderStyle: 'round',
317
+ borderColor: Object.keys(depResults.missing).length > 0 ? 'yellow' : 'green',
318
+ title: chalk.bold('🔧 System Dependencies'),
319
+ titleAlignment: 'center'
320
+ });
321
+
322
+ console.log(depsBoxen);
200
323
  }
201
324
 
202
325
  /**
@@ -208,6 +331,7 @@ async function collectConfiguration(options = {}) {
208
331
  const config = {
209
332
  provider: null,
210
333
  piperPath: null,
334
+ defaultVoice: null,
211
335
  reverb: 'light',
212
336
  backgroundMusic: {
213
337
  enabled: true,
@@ -219,13 +343,14 @@ async function collectConfiguration(options = {}) {
219
343
  if (options.yes) {
220
344
  // Non-interactive mode - use defaults
221
345
  config.provider = process.platform === 'darwin' ? 'macos' : 'piper';
346
+ config.defaultVoice = process.platform === 'darwin' ? 'Samantha' : 'en_US-ryan-high';
222
347
  const homeDir = process.env.HOME || process.env.USERPROFILE;
223
348
  config.piperPath = path.join(homeDir, '.claude', 'piper-voices');
224
349
  return config;
225
350
  }
226
351
 
227
352
  let currentPage = 0;
228
- const sectionPages = 4; // System Dependencies, Provider, Audio Settings, Verbosity
353
+ const sectionPages = 5; // System Dependencies, Provider, Voice Selection, Audio Settings, Verbosity
229
354
  const pageOffset = options.pageOffset || 0;
230
355
  const totalPages = options.totalPages || sectionPages;
231
356
 
@@ -238,96 +363,13 @@ async function collectConfiguration(options = {}) {
238
363
  console.clear();
239
364
 
240
365
  // Show header
241
- const pageTitle = currentPage === 0 ? 'System Dependencies' :
242
- currentPage === 1 ? 'TTS Provider Configuration' :
243
- currentPage === 2 ? 'Audio Settings' :
244
- 'Verbosity Settings';
366
+ const pageTitle = getPageTitle(currentPage);
245
367
  const { header, footer } = createPageHeaderFooter(pageTitle, currentPage, totalPages, pageOffset);
246
368
  console.log(header);
247
369
  console.log('');
248
370
 
249
371
  if (currentPage === 0) {
250
- // Page 1: System Dependencies Check
251
- const { checkDependencies } = await import('./utils/dependency-checker.js');
252
- const depResults = checkDependencies();
253
-
254
- let depContent = chalk.gray('System dependencies are tools AgentVibes needs to function properly.\n');
255
- depContent += chalk.gray('Required tools must be installed, optional tools enable extra features.\n\n');
256
-
257
- // Satisfied dependencies
258
- if (depResults.core.node?.isCompatible) {
259
- depContent += chalk.green(`✓ Node.js ${depResults.core.node.version}\n`);
260
- }
261
- if (depResults.core.python?.isCompatible) {
262
- depContent += chalk.green(`✓ Python ${depResults.core.python.version}\n`);
263
- }
264
- if (depResults.core.bash?.isModern) {
265
- depContent += chalk.green(`✓ Bash ${depResults.core.bash.version}\n`);
266
- }
267
- if (depResults.optional.curl) {
268
- depContent += chalk.green('✓ curl\n');
269
- }
270
- if (depResults.optional.sox) {
271
- depContent += chalk.green('✓ sox\n');
272
- }
273
- if (depResults.optional.ffmpeg) {
274
- depContent += chalk.green('✓ ffmpeg\n');
275
- }
276
- if (depResults.optional.bc) {
277
- depContent += chalk.green('✓ bc\n');
278
- }
279
- if (depResults.optional.flock) {
280
- depContent += chalk.green('✓ flock\n');
281
- }
282
- if (depResults.optional.pipx) {
283
- depContent += chalk.green('✓ pipx\n');
284
- }
285
- if (depResults.optional.audioPlayer) {
286
- depContent += chalk.green('✓ audio player (paplay/aplay/mpv)\n');
287
- }
288
-
289
- // Missing dependencies
290
- if (Object.keys(depResults.missing).length > 0) {
291
- depContent += '\n' + chalk.gray('─'.repeat(50)) + '\n\n';
292
- depContent += chalk.yellow.bold('Missing (Optional):\n\n');
293
-
294
- if (depResults.missing.curl) depContent += chalk.yellow('⚠ curl - needed for downloads\n');
295
- if (depResults.missing.sox) depContent += chalk.yellow('⚠ sox - audio effects\n');
296
- if (depResults.missing.ffmpeg) depContent += chalk.yellow('⚠ ffmpeg - background music\n');
297
- if (depResults.missing.bc) depContent += chalk.yellow('⚠ bc - audio calculations\n');
298
- if (depResults.missing.flock) depContent += chalk.yellow('⚠ flock - TTS queue locking\n');
299
- if (depResults.missing.pipx) depContent += chalk.yellow('⚠ pipx - Piper TTS installation\n');
300
- if (depResults.missing.audioPlayer) depContent += chalk.yellow('⚠ audio player - playback\n');
301
-
302
- depContent += '\n' + chalk.gray('TTS will still work without optional tools');
303
-
304
- // Add install commands
305
- const os = await import('os');
306
- const { getInstallCommands } = await import('./utils/dependency-checker.js');
307
- const platform = os.platform();
308
- const installCmds = getInstallCommands(depResults.missing, platform);
309
-
310
- if (installCmds.length > 0) {
311
- depContent += '\n\n' + chalk.gray('─'.repeat(50)) + '\n\n';
312
- depContent += chalk.cyan.bold('To Install Missing Tools:\n\n');
313
-
314
- installCmds.forEach(({ label, command }) => {
315
- depContent += chalk.cyan(`${label}:\n`);
316
- depContent += chalk.white(` ${command}\n\n`);
317
- });
318
- }
319
- }
320
-
321
- const depsBoxen = boxen(depContent.trim(), {
322
- padding: 1,
323
- margin: 1,
324
- borderStyle: 'round',
325
- borderColor: Object.keys(depResults.missing).length > 0 ? 'yellow' : 'green',
326
- title: chalk.bold('🔧 System Dependencies'),
327
- titleAlignment: 'center'
328
- });
329
-
330
- console.log(depsBoxen);
372
+ await handleSystemDependenciesPage();
331
373
  } else if (currentPage === 1) {
332
374
  // Page 2: TTS Provider & Voice Storage
333
375
 
@@ -453,7 +495,86 @@ async function collectConfiguration(options = {}) {
453
495
  }
454
496
 
455
497
  } else if (currentPage === 2) {
456
- // Page 3: Audio Settings (Reverb + Background Music)
498
+ // Page 3: Voice Selection
499
+ console.log(boxen(
500
+ chalk.white('Choose a default voice for your AgentVibes.\n\n') +
501
+ chalk.gray('This will be used when no specific voice is configured.\n') +
502
+ chalk.gray('You can change this anytime with: ') + chalk.cyan('/agent-vibes:voice switch <name>'),
503
+ {
504
+ padding: 1,
505
+ margin: 1,
506
+ borderStyle: 'round',
507
+ borderColor: 'gray',
508
+ title: chalk.bold('🎤 Default Voice'),
509
+ titleAlignment: 'center'
510
+ }
511
+ ));
512
+
513
+ if (config.provider === 'piper') {
514
+ // Piper voices - popular selections
515
+ const piperVoices = [
516
+ { name: chalk.cyan('en_US-ryan-high') + chalk.gray(' (Male, American, High Quality)'), value: 'en_US-ryan-high' },
517
+ { name: chalk.magenta('en_US-amy-medium') + chalk.gray(' (Female, American, Clear)'), value: 'en_US-amy-medium' },
518
+ { name: chalk.cyan('en_US-joe-medium') + chalk.gray(' (Male, American, Warm)'), value: 'en_US-joe-medium' },
519
+ { name: chalk.magenta('en_US-lessac-medium') + chalk.gray(' (Female, American, Professional)'), value: 'en_US-lessac-medium' },
520
+ { name: chalk.cyan('en_GB-alan-medium') + chalk.gray(' (Male, British, Refined)'), value: 'en_GB-alan-medium' },
521
+ { name: chalk.magenta('en_GB-southern_english_female-medium') + chalk.gray(' (Female, British)'), value: 'en_GB-southern_english_female-medium' },
522
+ new inquirer.Separator(),
523
+ { name: chalk.yellow('Skip - I\'ll set this later'), value: '__skip__' },
524
+ { name: chalk.magentaBright('← Back to Provider Selection'), value: '__back__' }
525
+ ];
526
+
527
+ const { selectedVoice } = await inquirer.prompt([{
528
+ type: 'list',
529
+ name: 'selectedVoice',
530
+ message: chalk.yellow('Select your default Piper voice:'),
531
+ choices: piperVoices,
532
+ default: 'en_US-ryan-high',
533
+ pageSize: 12
534
+ }]);
535
+
536
+ if (selectedVoice === '__back__') {
537
+ return null;
538
+ }
539
+
540
+ if (selectedVoice !== '__skip__') {
541
+ config.defaultVoice = selectedVoice;
542
+ }
543
+
544
+ } else if (config.provider === 'macos') {
545
+ // macOS Say voices - popular selections
546
+ const macOSVoices = [
547
+ { name: chalk.cyan('Samantha') + chalk.gray(' (Female, American)'), value: 'Samantha' },
548
+ { name: chalk.cyan('Alex') + chalk.gray(' (Male, American)'), value: 'Alex' },
549
+ { name: chalk.magenta('Flo') + chalk.gray(' (Female, American, Expressive)'), value: 'Flo' },
550
+ { name: chalk.cyan('Tom') + chalk.gray(' (Male, American)'), value: 'Tom' },
551
+ { name: chalk.magenta('Karen') + chalk.gray(' (Female, Australian)'), value: 'Karen' },
552
+ { name: chalk.cyan('Daniel') + chalk.gray(' (Male, British)'), value: 'Daniel' },
553
+ new inquirer.Separator(),
554
+ { name: chalk.yellow('Skip - I\'ll set this later'), value: '__skip__' },
555
+ { name: chalk.magentaBright('← Back to Provider Selection'), value: '__back__' }
556
+ ];
557
+
558
+ const { selectedVoice } = await inquirer.prompt([{
559
+ type: 'list',
560
+ name: 'selectedVoice',
561
+ message: chalk.yellow('Select your default macOS voice:'),
562
+ choices: macOSVoices,
563
+ default: 'Samantha',
564
+ pageSize: 12
565
+ }]);
566
+
567
+ if (selectedVoice === '__back__') {
568
+ return null;
569
+ }
570
+
571
+ if (selectedVoice !== '__skip__') {
572
+ config.defaultVoice = selectedVoice;
573
+ }
574
+ }
575
+
576
+ } else if (currentPage === 3) {
577
+ // Page 4: Audio Settings (Reverb + Background Music)
457
578
  console.log(boxen(
458
579
  chalk.white('Configure audio effects and background music for your Agents.\n\n') +
459
580
  chalk.yellow('Reverb:\n') +
@@ -541,8 +662,8 @@ async function collectConfiguration(options = {}) {
541
662
  config.backgroundMusic.track = selectedTrack;
542
663
  }
543
664
 
544
- } else if (currentPage === 3) {
545
- // Page 4: Verbosity Settings
665
+ } else if (currentPage === 4) {
666
+ // Page 5: Verbosity Settings
546
667
  console.log(boxen(
547
668
  chalk.white('Choose how much Claude speaks during interactions.\n\n') +
548
669
  chalk.yellow('🔊 High:\n') +
@@ -685,19 +806,20 @@ function showWelcome() {
685
806
  * Shown during install and update commands
686
807
  */
687
808
  function getReleaseInfoBoxen() {
688
- return chalk.cyan.bold('📦 AgentVibes v2.17.0 - Installer UX Revolution\n\n') +
809
+ return chalk.cyan.bold('📦 AgentVibes v2.17.4 - Code Quality & Maintainability\n\n') +
689
810
  chalk.green.bold('🎙️ WHAT\'S NEW:\n\n') +
690
- chalk.cyan('AgentVibes v2.17.0 delivers a complete installer user experience transformation\n') +
691
- chalk.cyan('with intelligent system dependency checking, paginated configuration flow, and\n') +
692
- chalk.cyan('comprehensive inline help with command examples throughout.\n\n') +
811
+ chalk.cyan('AgentVibes v2.17.4 focuses on code quality and maintainability with extensive\n') +
812
+ chalk.cyan('SonarCloud-driven refactoring across the entire codebase. This release reduces\n') +
813
+ chalk.cyan('cognitive complexity in critical files by up to 90%, making the codebase more\n') +
814
+ chalk.cyan('maintainable and easier to understand.\n\n') +
693
815
  chalk.green.bold('✨ KEY HIGHLIGHTS:\n\n') +
694
- chalk.gray(' 🔧 System Dependency Checker - Validates Node, Python, bash, sox, ffmpeg, curl, etc.\n') +
695
- chalk.gray(' 📄 Paginated Configuration - Beautiful headers with Agent Vibes branding on every page\n') +
696
- chalk.gray(' 💡 Inline Help & Commands - TTS explanations and examples throughout installer\n') +
697
- chalk.gray(' 🎵 New Music Track - Salsa v2 background music now available\n') +
698
- chalk.gray(' 🎨 Professional UI - Consistent sunshine yellow styling and dynamic page numbering\n') +
699
- chalk.gray(' 📋 Enhanced Navigation - Previous button, accurate page counts, README links\n') +
700
- chalk.gray(' Quality Assurance - 140 tests passing, SonarCloud integration\n\n') +
816
+ chalk.gray(' ⚙️ Major Code Refactoring - Cognitive complexity reduced by up to 90% across critical files\n') +
817
+ chalk.gray(' 🧪 Comprehensive Testing - 377 new party mode tests added, 225 total tests passing\n') +
818
+ chalk.gray(' 📚 Improved Documentation - New Prerequisites and FAQ sections clarify installation\n') +
819
+ chalk.gray(' 🎭 Conversational Agent Intros - BMAD party mode now uses "Hi! I\'m John, your Product Manager"\n') +
820
+ chalk.gray(' 🔊 Better Audio Balance - Background music reduced 15% for clearer TTS voice\n') +
821
+ chalk.gray(' 🏗️ installer.js: 84 ~8 complexity (90% reduction)\n') +
822
+ chalk.gray(' 📦 dependency-checker.js: 43 ~5, 23 → ~8 (88% & 65% reductions)\n\n') +
701
823
  chalk.gray('📖 Full Release Notes: RELEASE_NOTES.md\n') +
702
824
  chalk.gray('🌐 Website: https://agentvibes.org\n') +
703
825
  chalk.gray('📦 Repository: https://github.com/paulpreibisch/AgentVibes\n\n') +
@@ -1218,6 +1340,103 @@ async function copyCommandFiles(targetDir, spinner) {
1218
1340
  }
1219
1341
  }
1220
1342
 
1343
+ /**
1344
+ * Check if a file should be included as a hook file
1345
+ * @param {string} file - Filename to check
1346
+ * @param {Object} stat - File stats object
1347
+ * @returns {boolean} True if file should be included
1348
+ */
1349
+ function shouldIncludeHookFile(file, stat) {
1350
+ return stat.isFile() &&
1351
+ (file.endsWith('.sh') || file === 'hooks.json') &&
1352
+ !file.includes('prepare-release') &&
1353
+ !file.startsWith('.');
1354
+ }
1355
+
1356
+ /**
1357
+ * Filter hook files from directory
1358
+ * @param {string} srcHooksDir - Source hooks directory
1359
+ * @param {Array} allFiles - All files in directory
1360
+ * @returns {Promise<Array>} Filtered hook files
1361
+ */
1362
+ async function filterHookFiles(srcHooksDir, allFiles) {
1363
+ const hookFiles = [];
1364
+
1365
+ for (const file of allFiles) {
1366
+ const srcPath = path.join(srcHooksDir, file);
1367
+ try {
1368
+ const stat = await fs.stat(srcPath);
1369
+ if (shouldIncludeHookFile(file, stat)) {
1370
+ hookFiles.push(file);
1371
+ }
1372
+ } catch (err) {
1373
+ console.log(chalk.yellow(` ⚠ Could not check ${file}: ${err.message}`));
1374
+ }
1375
+ }
1376
+
1377
+ return hookFiles;
1378
+ }
1379
+
1380
+ /**
1381
+ * Copy a single hook file and set permissions
1382
+ * @param {string} srcPath - Source file path
1383
+ * @param {string} destPath - Destination file path
1384
+ * @param {string} filename - Name of the file
1385
+ * @returns {Promise<Object>} Result object with success/error info
1386
+ */
1387
+ async function copyHookFile(srcPath, destPath, filename) {
1388
+ try {
1389
+ await fs.copyFile(srcPath, destPath);
1390
+
1391
+ if (filename.endsWith('.sh')) {
1392
+ await fs.chmod(destPath, 0o750);
1393
+ return { success: true, name: filename, executable: true };
1394
+ }
1395
+
1396
+ return { success: true, name: filename, executable: false };
1397
+ } catch (err) {
1398
+ return { success: false, name: filename, error: err.message };
1399
+ }
1400
+ }
1401
+
1402
+ /**
1403
+ * Build boxen content for hook installation results
1404
+ * @param {Array} installedFiles - Successfully installed files
1405
+ * @param {Array} failedFiles - Failed files
1406
+ * @returns {string} Boxen formatted content
1407
+ */
1408
+ function buildHookInstallationBoxen(installedFiles, failedFiles) {
1409
+ let content = chalk.bold(`${installedFiles.length} TTS Hook Scripts Installed\n\n`);
1410
+ content += chalk.gray('Hook scripts automatically run at key moments during your\n');
1411
+ content += chalk.gray('Claude Code sessions to provide TTS feedback and manage audio.\n\n');
1412
+
1413
+ installedFiles.forEach(file => {
1414
+ content += chalk.green(`✓ ${file.name}`);
1415
+ if (file.executable) {
1416
+ content += chalk.gray(' (executable)');
1417
+ }
1418
+ content += '\n';
1419
+ });
1420
+
1421
+ if (failedFiles.length > 0) {
1422
+ content += '\n' + chalk.gray('─'.repeat(60)) + '\n\n';
1423
+ content += chalk.bold.yellow(`${failedFiles.length} Failed\n\n`);
1424
+ failedFiles.forEach(file => {
1425
+ content += chalk.yellow(`⚠ ${file.name}\n`);
1426
+ content += chalk.dim(` ${file.error}\n`);
1427
+ });
1428
+ }
1429
+
1430
+ return boxen(content.trim(), {
1431
+ padding: 1,
1432
+ margin: 1,
1433
+ borderStyle: 'round',
1434
+ borderColor: 'green',
1435
+ title: chalk.bold('🔧 TTS Scripts'),
1436
+ titleAlignment: 'center'
1437
+ });
1438
+ }
1439
+
1221
1440
  /**
1222
1441
  * Copy hook files to target directory
1223
1442
  * @param {string} targetDir - Target installation directory
@@ -1233,87 +1452,36 @@ async function copyHookFiles(targetDir, spinner) {
1233
1452
  await fs.mkdir(hooksDir, { recursive: true });
1234
1453
 
1235
1454
  const allHookFiles = await fs.readdir(srcHooksDir);
1236
- const hookFiles = [];
1237
-
1238
- for (const file of allHookFiles) {
1239
- const srcPath = path.join(srcHooksDir, file);
1240
- try {
1241
- const stat = await fs.stat(srcPath);
1242
-
1243
- if (stat.isFile() &&
1244
- (file.endsWith('.sh') || file === 'hooks.json') &&
1245
- !file.includes('prepare-release') &&
1246
- !file.startsWith('.')) {
1247
- hookFiles.push(file);
1248
- }
1249
- } catch (err) {
1250
- console.log(chalk.yellow(` ⚠ Could not check ${file}: ${err.message}`));
1251
- // Continue with other files
1252
- }
1253
- }
1455
+ const hookFiles = await filterHookFiles(srcHooksDir, allHookFiles);
1254
1456
 
1255
1457
  spinner.start(`Installing ${hookFiles.length} TTS scripts...`);
1256
- let successCount = 0;
1257
- let installedFiles = [];
1258
- let failedFiles = [];
1458
+
1459
+ const installedFiles = [];
1460
+ const failedFiles = [];
1259
1461
 
1260
1462
  for (const file of hookFiles) {
1261
1463
  const srcPath = path.join(srcHooksDir, file);
1262
1464
  const destPath = path.join(hooksDir, file);
1263
- try {
1264
- await fs.copyFile(srcPath, destPath);
1465
+ const result = await copyHookFile(srcPath, destPath, file);
1265
1466
 
1266
- if (file.endsWith('.sh')) {
1267
- // Security: Use more restrictive permissions (owner: rwx, group: r-x, others: ---)
1268
- await fs.chmod(destPath, 0o750);
1269
- installedFiles.push({ name: file, executable: true });
1270
- } else {
1271
- installedFiles.push({ name: file, executable: false });
1272
- }
1273
- successCount++;
1274
- } catch (err) {
1275
- failedFiles.push({ name: file, error: err.message });
1467
+ if (result.success) {
1468
+ installedFiles.push({ name: result.name, executable: result.executable });
1469
+ } else {
1470
+ failedFiles.push({ name: result.name, error: result.error });
1276
1471
  }
1277
1472
  }
1278
1473
 
1474
+ const successCount = installedFiles.length;
1475
+
1279
1476
  if (successCount === hookFiles.length) {
1280
1477
  spinner.succeed(chalk.green('Installed TTS scripts!\n'));
1281
1478
  } else {
1282
1479
  spinner.warn(chalk.yellow(`Installed ${successCount}/${hookFiles.length} scripts (some failed)\n`));
1283
1480
  }
1284
1481
 
1285
- // Create boxen content (don't print yet - will be shown in pagination)
1286
- let boxenContent = null;
1287
- if (installedFiles.length > 0) {
1288
- let content = chalk.bold(`${installedFiles.length} TTS Hook Scripts Installed\n\n`);
1289
- content += chalk.gray('Hook scripts automatically run at key moments during your\n');
1290
- content += chalk.gray('Claude Code sessions to provide TTS feedback and manage audio.\n\n');
1291
- installedFiles.forEach(file => {
1292
- content += chalk.green(`✓ ${file.name}`);
1293
- if (file.executable) {
1294
- content += chalk.gray(' (executable)');
1295
- }
1296
- content += '\n';
1297
- });
1298
-
1299
- if (failedFiles.length > 0) {
1300
- content += '\n' + chalk.gray('─'.repeat(60)) + '\n\n';
1301
- content += chalk.bold.yellow(`${failedFiles.length} Failed\n\n`);
1302
- failedFiles.forEach(file => {
1303
- content += chalk.yellow(`⚠ ${file.name}\n`);
1304
- content += chalk.dim(` ${file.error}\n`);
1305
- });
1306
- }
1307
-
1308
- boxenContent = boxen(content.trim(), {
1309
- padding: 1,
1310
- margin: 1,
1311
- borderStyle: 'round',
1312
- borderColor: 'green',
1313
- title: chalk.bold('🔧 TTS Scripts'),
1314
- titleAlignment: 'center'
1315
- });
1316
- }
1482
+ const boxenContent = installedFiles.length > 0
1483
+ ? buildHookInstallationBoxen(installedFiles, failedFiles)
1484
+ : null;
1317
1485
 
1318
1486
  return { count: successCount, boxen: boxenContent };
1319
1487
  } catch (err) {
@@ -1697,7 +1865,7 @@ async function checkAndInstallPiper(targetDir, options) {
1697
1865
  const { execSync } = await import('node:child_process');
1698
1866
 
1699
1867
  try {
1700
- execSync('command -v piper', { stdio: 'ignore' });
1868
+ execSync('command -v piper', { stdio: 'ignore' }); // NOSONAR - Safe: fixed command, no user input
1701
1869
  console.log(chalk.green('✅ Piper TTS is already installed\n'));
1702
1870
  return;
1703
1871
  } catch {
@@ -2108,36 +2276,31 @@ frame-expert,en_GB-alan-medium
2108
2276
  * @param {Object} spinner - Ora spinner instance
2109
2277
  * @returns {Promise<boolean>} True if migration was performed
2110
2278
  */
2111
- async function detectAndMigrateOldConfig(targetDir, spinner) {
2112
- const oldConfigPaths = [
2113
- path.join(targetDir, '.claude', 'config', 'agentvibes.json'),
2114
- path.join(targetDir, '.claude', 'config', 'bmad-voices.md'),
2115
- path.join(targetDir, '.claude', 'config', 'bmad-voices-enabled.flag'),
2116
- path.join(targetDir, '.claude', 'plugins', 'bmad-voices-enabled.flag'),
2117
- path.join(targetDir, '.claude', 'plugins', 'bmad-party-mode-disabled.flag'),
2118
- ];
2119
-
2120
- // Check if any old config exists
2121
- let hasOldConfig = false;
2122
- for (const oldPath of oldConfigPaths) {
2279
+ /**
2280
+ * Check if any old config files exist
2281
+ * @param {string[]} paths - Array of paths to check
2282
+ * @returns {Promise<boolean>} True if any old config exists
2283
+ */
2284
+ async function hasOldConfigFiles(paths) {
2285
+ for (const oldPath of paths) {
2123
2286
  try {
2124
2287
  await fs.access(oldPath);
2125
- hasOldConfig = true;
2126
- break;
2288
+ return true;
2127
2289
  } catch {
2128
2290
  // File doesn't exist, continue
2129
2291
  }
2130
2292
  }
2293
+ return false;
2294
+ }
2131
2295
 
2132
- if (!hasOldConfig) {
2133
- return false; // No migration needed
2134
- }
2135
-
2136
- spinner.info(chalk.yellow('🔄 Old configuration detected - migrating to .agentvibes/'));
2137
-
2138
- // Run migration script
2139
- const migrationScript = path.join(targetDir, '.claude', 'hooks', 'migrate-to-agentvibes.sh');
2140
-
2296
+ /**
2297
+ * Execute migration script
2298
+ * @param {string} migrationScript - Path to migration script
2299
+ * @param {string} targetDir - Target directory
2300
+ * @param {Object} spinner - Ora spinner instance
2301
+ * @returns {Promise<boolean>} True if migration succeeded
2302
+ */
2303
+ async function executeMigrationScript(migrationScript, targetDir, spinner) {
2141
2304
  try {
2142
2305
  await fs.access(migrationScript);
2143
2306
 
@@ -2162,6 +2325,27 @@ async function detectAndMigrateOldConfig(targetDir, spinner) {
2162
2325
  }
2163
2326
  }
2164
2327
 
2328
+ async function detectAndMigrateOldConfig(targetDir, spinner) {
2329
+ const oldConfigPaths = [
2330
+ path.join(targetDir, '.claude', 'config', 'agentvibes.json'),
2331
+ path.join(targetDir, '.claude', 'config', 'bmad-voices.md'),
2332
+ path.join(targetDir, '.claude', 'config', 'bmad-voices-enabled.flag'),
2333
+ path.join(targetDir, '.claude', 'plugins', 'bmad-voices-enabled.flag'),
2334
+ path.join(targetDir, '.claude', 'plugins', 'bmad-party-mode-disabled.flag'),
2335
+ ];
2336
+
2337
+ // Check if any old config exists
2338
+ if (!await hasOldConfigFiles(oldConfigPaths)) {
2339
+ return false; // No migration needed
2340
+ }
2341
+
2342
+ spinner.info(chalk.yellow('🔄 Old configuration detected - migrating to .agentvibes/'));
2343
+
2344
+ // Run migration script
2345
+ const migrationScript = path.join(targetDir, '.claude', 'hooks', 'migrate-to-agentvibes.sh');
2346
+ return await executeMigrationScript(migrationScript, targetDir, spinner);
2347
+ }
2348
+
2165
2349
  /**
2166
2350
  * Handle BMAD integration (detection and TTS injection)
2167
2351
  * @param {string} targetDir - Target installation directory
@@ -2218,7 +2402,7 @@ async function handleBmadIntegration(targetDir) {
2218
2402
  async function showRecentChanges(sourceDir) {
2219
2403
  try {
2220
2404
  const { execSync } = await import('node:child_process');
2221
- const gitLog = execSync(
2405
+ const gitLog = execSync( // NOSONAR - Safe: fixed command with controlled cwd, no user input
2222
2406
  'git log --oneline --no-decorate -5',
2223
2407
  { cwd: sourceDir, encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }
2224
2408
  ).trim();
@@ -2305,84 +2489,129 @@ async function updatePersonalityFiles(targetDir, srcPersonalitiesDir) {
2305
2489
  }
2306
2490
 
2307
2491
  /**
2308
- * Update AgentVibes files in target directory
2492
+ * Create a silent spinner for update operations
2493
+ * @returns {Object} Mock spinner object
2494
+ */
2495
+ function createSilentSpinner() {
2496
+ return { start: () => {}, succeed: () => {}, info: () => {}, fail: () => {} };
2497
+ }
2498
+
2499
+ /**
2500
+ * Update command files
2309
2501
  * @param {string} targetDir - Target installation directory
2310
- * @param {Object} options - Update options
2502
+ * @param {Object} spinner - Ora spinner instance
2503
+ * @returns {Promise<number>} Number of commands updated
2311
2504
  */
2312
- async function updateAgentVibes(targetDir, options) {
2313
- const spinner = ora('Updating AgentVibes...').start();
2505
+ async function updateCommandFiles(targetDir, spinner) {
2506
+ spinner.text = 'Updating commands...';
2507
+ const commandsDir = path.join(targetDir, '.claude', 'commands', 'agent-vibes');
2508
+ const srcCommandsDir = path.join(__dirname, '..', '.claude', 'commands', 'agent-vibes');
2509
+ const commandFiles = await fs.readdir(srcCommandsDir);
2314
2510
 
2315
- try {
2316
- const claudeDir = path.join(targetDir, '.claude');
2317
- const commandsDir = path.join(targetDir, '.claude', 'commands', 'agent-vibes');
2511
+ for (const file of commandFiles) {
2512
+ const srcPath = path.join(srcCommandsDir, file);
2513
+ const destPath = path.join(commandsDir, file);
2514
+ await fs.copyFile(srcPath, destPath);
2515
+ }
2318
2516
 
2319
- // Update commands
2320
- spinner.text = 'Updating commands...';
2321
- const srcCommandsDir = path.join(__dirname, '..', '.claude', 'commands', 'agent-vibes');
2322
- const commandFiles = await fs.readdir(srcCommandsDir);
2517
+ return commandFiles.length;
2518
+ }
2323
2519
 
2324
- for (const file of commandFiles) {
2325
- const srcPath = path.join(srcCommandsDir, file);
2326
- const destPath = path.join(commandsDir, file);
2327
- await fs.copyFile(srcPath, destPath);
2328
- }
2329
- console.log(chalk.green(`\n✓ Updated ${commandFiles.length} commands`));
2520
+ /**
2521
+ * Perform all update operations
2522
+ * @param {string} targetDir - Target installation directory
2523
+ * @param {Object} spinner - Ora spinner instance
2524
+ * @returns {Promise<Object>} Update results
2525
+ */
2526
+ async function performUpdateOperations(targetDir, spinner) {
2527
+ const silentSpinner = createSilentSpinner();
2330
2528
 
2331
- // Update hooks
2332
- spinner.text = 'Updating TTS scripts...';
2333
- const hookResult = await copyHookFiles(targetDir, { start: () => {}, succeed: () => {}, info: () => {}, fail: () => {} });
2334
- console.log(chalk.green(`✓ Updated ${hookResult.count} TTS scripts`));
2529
+ // Update commands
2530
+ const commandCount = await updateCommandFiles(targetDir, spinner);
2531
+ console.log(chalk.green(`\n✓ Updated ${commandCount} commands`));
2335
2532
 
2336
- // Update personalities
2337
- spinner.text = 'Updating personality templates...';
2338
- const srcPersonalitiesDir = path.join(__dirname, '..', '.claude', 'personalities');
2339
- const personalityResult = await updatePersonalityFiles(targetDir, srcPersonalitiesDir);
2340
- console.log(chalk.green(`✓ Updated ${personalityResult.updated} personalities, added ${personalityResult.new} new`));
2533
+ // Update hooks
2534
+ spinner.text = 'Updating TTS scripts...';
2535
+ const hookResult = await copyHookFiles(targetDir, silentSpinner);
2536
+ console.log(chalk.green(`✓ Updated ${hookResult.count} TTS scripts`));
2341
2537
 
2342
- // Output styles removed - deprecated in favor of SessionStart hook system
2538
+ // Update personalities
2539
+ spinner.text = 'Updating personality templates...';
2540
+ const srcPersonalitiesDir = path.join(__dirname, '..', '.claude', 'personalities');
2541
+ const personalityResult = await updatePersonalityFiles(targetDir, srcPersonalitiesDir);
2542
+ console.log(chalk.green(`✓ Updated ${personalityResult.updated} personalities, added ${personalityResult.new} new`));
2343
2543
 
2344
- // Update plugin files
2345
- const pluginFileCount = await copyPluginFiles(targetDir, { start: () => {}, succeed: () => {}, info: () => {}, fail: () => {} });
2346
- if (pluginFileCount > 0) {
2347
- console.log(chalk.green(`✓ Updated ${pluginFileCount} BMAD plugin files`));
2348
- }
2544
+ // Update plugin files
2545
+ const pluginFileCount = await copyPluginFiles(targetDir, silentSpinner);
2546
+ if (pluginFileCount > 0) {
2547
+ console.log(chalk.green(`✓ Updated ${pluginFileCount} BMAD plugin files`));
2548
+ }
2349
2549
 
2350
- // Update BMAD config files
2351
- const bmadConfigFileCount = await copyBmadConfigFiles(targetDir, { start: () => {}, succeed: () => {}, info: () => {}, fail: () => {} });
2352
- if (bmadConfigFileCount > 0) {
2353
- console.log(chalk.green(`✓ Updated ${bmadConfigFileCount} BMAD config files`));
2354
- }
2550
+ // Update BMAD config files
2551
+ const bmadConfigFileCount = await copyBmadConfigFiles(targetDir, silentSpinner);
2552
+ if (bmadConfigFileCount > 0) {
2553
+ console.log(chalk.green(`✓ Updated ${bmadConfigFileCount} BMAD config files`));
2554
+ }
2355
2555
 
2356
- // Update background music files
2357
- const backgroundMusicUpdateResult = await copyBackgroundMusicFiles(targetDir, { start: () => {}, succeed: () => {}, info: () => {}, fail: () => {} });
2358
- if (backgroundMusicUpdateResult.count > 0) {
2359
- console.log(chalk.green(`✓ Installed ${backgroundMusicUpdateResult.count} background music track${backgroundMusicUpdateResult.count === 1 ? '' : 's'}`));
2360
- }
2556
+ // Update background music files
2557
+ const backgroundMusicUpdateResult = await copyBackgroundMusicFiles(targetDir, silentSpinner);
2558
+ if (backgroundMusicUpdateResult.count > 0) {
2559
+ console.log(chalk.green(`✓ Installed ${backgroundMusicUpdateResult.count} background music track${backgroundMusicUpdateResult.count === 1 ? '' : 's'}`));
2560
+ }
2361
2561
 
2362
- // Update config files
2363
- const configFileCount = await copyConfigFiles(targetDir, { start: () => {}, succeed: () => {}, info: () => {}, fail: () => {} });
2364
- if (configFileCount > 0) {
2365
- console.log(chalk.green(`✓ Installed ${configFileCount} config file${configFileCount === 1 ? '' : 's'}`));
2366
- }
2562
+ // Update config files
2563
+ const configFileCount = await copyConfigFiles(targetDir, silentSpinner);
2564
+ if (configFileCount > 0) {
2565
+ console.log(chalk.green(`✓ Installed ${configFileCount} config file${configFileCount === 1 ? '' : 's'}`));
2566
+ }
2367
2567
 
2368
- // Update settings.json
2369
- spinner.text = 'Updating AgentVibes hook configuration...';
2370
- await configureSessionStartHook(targetDir, { start: () => {}, succeed: () => {}, info: () => {}, fail: () => {} });
2568
+ // Update settings.json
2569
+ spinner.text = 'Updating AgentVibes hook configuration...';
2570
+ await configureSessionStartHook(targetDir, silentSpinner);
2371
2571
 
2372
- // Detect and migrate old configuration
2373
- spinner.text = 'Checking for old configuration...';
2374
- await detectAndMigrateOldConfig(targetDir, spinner);
2572
+ // Detect and migrate old configuration
2573
+ spinner.text = 'Checking for old configuration...';
2574
+ await detectAndMigrateOldConfig(targetDir, spinner);
2575
+
2576
+ return {
2577
+ commandCount,
2578
+ hookCount: hookResult.count,
2579
+ personalityResult,
2580
+ pluginFileCount
2581
+ };
2582
+ }
2583
+
2584
+ /**
2585
+ * Display update summary
2586
+ * @param {Object} results - Update results
2587
+ */
2588
+ function displayUpdateSummary(results) {
2589
+ console.log(chalk.cyan('📦 Update Summary:'));
2590
+ console.log(chalk.white(` • ${results.commandCount} commands updated`));
2591
+ console.log(chalk.white(` • ${results.hookCount} TTS scripts updated`));
2592
+ console.log(chalk.white(` • ${results.personalityResult.new + results.personalityResult.updated} personality templates (${results.personalityResult.new} new, ${results.personalityResult.updated} updated)`));
2593
+ if (results.pluginFileCount > 0) {
2594
+ console.log(chalk.white(` • ${results.pluginFileCount} BMAD plugin files updated`));
2595
+ }
2596
+ console.log('');
2597
+ }
2598
+
2599
+ /**
2600
+ * Update AgentVibes files in target directory
2601
+ * @param {string} targetDir - Target installation directory
2602
+ * @param {Object} options - Update options
2603
+ */
2604
+ async function updateAgentVibes(targetDir, options) {
2605
+ const spinner = ora('Updating AgentVibes...').start();
2606
+
2607
+ try {
2608
+ // Perform all update operations
2609
+ const updateResults = await performUpdateOperations(targetDir, spinner);
2375
2610
 
2376
2611
  spinner.succeed(chalk.green.bold('\n✨ Update complete!\n'));
2377
2612
 
2378
- console.log(chalk.cyan('📦 Update Summary:'));
2379
- console.log(chalk.white(` • ${commandFiles.length} commands updated`));
2380
- console.log(chalk.white(` • ${hookResult.count} TTS scripts updated`));
2381
- console.log(chalk.white(` • ${personalityResult.new + personalityResult.updated} personality templates (${personalityResult.new} new, ${personalityResult.updated} updated)`));
2382
- if (pluginFileCount > 0) {
2383
- console.log(chalk.white(` • ${pluginFileCount} BMAD plugin files updated`));
2384
- }
2385
- console.log('');
2613
+ // Display summary
2614
+ displayUpdateSummary(updateResults);
2386
2615
 
2387
2616
  // Show recent changes
2388
2617
  await showRecentChanges(path.join(__dirname, '..'));
@@ -2644,17 +2873,21 @@ async function install(options = {}) {
2644
2873
  await fs.writeFile(piperConfigPath, piperVoicesPath);
2645
2874
  }
2646
2875
 
2647
- // Set default voice based on provider to prevent fallback to mismatched global voice
2876
+ // Set default voice based on user selection or provider defaults
2648
2877
  const voiceConfigPath = path.join(claudeDir, 'tts-voice.txt');
2649
- let defaultVoice;
2650
- switch (selectedProvider) {
2651
- case 'piper':
2652
- defaultVoice = 'en_US-lessac-medium';
2653
- break;
2654
- case 'macos':
2655
- default:
2656
- defaultVoice = 'Samantha';
2657
- break;
2878
+ let defaultVoice = userConfig.defaultVoice;
2879
+
2880
+ // Fallback to defaults if voice wasn't selected
2881
+ if (!defaultVoice) {
2882
+ switch (selectedProvider) {
2883
+ case 'piper':
2884
+ defaultVoice = 'en_US-ryan-high';
2885
+ break;
2886
+ case 'macos':
2887
+ default:
2888
+ defaultVoice = 'Samantha';
2889
+ break;
2890
+ }
2658
2891
  }
2659
2892
  await fs.writeFile(voiceConfigPath, defaultVoice);
2660
2893