convoke-agents 2.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 (244) hide show
  1. package/CHANGELOG.md +920 -0
  2. package/INSTALLATION.md +230 -0
  3. package/LICENSE +21 -0
  4. package/README.md +330 -0
  5. package/UPDATE-GUIDE.md +220 -0
  6. package/_bmad/bme/_vortex/README.md +150 -0
  7. package/_bmad/bme/_vortex/agents/contextualization-expert.md +100 -0
  8. package/_bmad/bme/_vortex/agents/discovery-empathy-expert.md +117 -0
  9. package/_bmad/bme/_vortex/agents/hypothesis-engineer.md +117 -0
  10. package/_bmad/bme/_vortex/agents/lean-experiments-specialist.md +118 -0
  11. package/_bmad/bme/_vortex/agents/learning-decision-expert.md +117 -0
  12. package/_bmad/bme/_vortex/agents/production-intelligence-specialist.md +117 -0
  13. package/_bmad/bme/_vortex/agents/research-convergence-specialist.md +117 -0
  14. package/_bmad/bme/_vortex/compass-routing-reference.md +312 -0
  15. package/_bmad/bme/_vortex/config.yaml +46 -0
  16. package/_bmad/bme/_vortex/contracts/hc1-empathy-artifacts.md +152 -0
  17. package/_bmad/bme/_vortex/contracts/hc2-problem-definition.md +125 -0
  18. package/_bmad/bme/_vortex/contracts/hc3-hypothesis-contract.md +112 -0
  19. package/_bmad/bme/_vortex/contracts/hc4-experiment-context.md +140 -0
  20. package/_bmad/bme/_vortex/contracts/hc5-signal-report.md +130 -0
  21. package/_bmad/bme/_vortex/examples/hc2-example-problem-definition.md +85 -0
  22. package/_bmad/bme/_vortex/examples/hc3-example-hypothesis-contract.md +103 -0
  23. package/_bmad/bme/_vortex/examples/hc5-example-signal-report.md +76 -0
  24. package/_bmad/bme/_vortex/guides/EMMA-USER-GUIDE.md +232 -0
  25. package/_bmad/bme/_vortex/guides/ISLA-USER-GUIDE.md +208 -0
  26. package/_bmad/bme/_vortex/guides/LIAM-USER-GUIDE.md +255 -0
  27. package/_bmad/bme/_vortex/guides/MAX-USER-GUIDE.md +213 -0
  28. package/_bmad/bme/_vortex/guides/MILA-USER-GUIDE.md +235 -0
  29. package/_bmad/bme/_vortex/guides/NOAH-USER-GUIDE.md +258 -0
  30. package/_bmad/bme/_vortex/guides/WADE-USER-GUIDE.md +245 -0
  31. package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/empathy-map.template.md +143 -0
  32. package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/steps/step-01-define-user.md +60 -0
  33. package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/steps/step-02-says-thinks.md +67 -0
  34. package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/steps/step-03-does-feels.md +79 -0
  35. package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/steps/step-04-pain-points.md +87 -0
  36. package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/steps/step-05-gains.md +103 -0
  37. package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/steps/step-06-synthesize.md +104 -0
  38. package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/validate.md +117 -0
  39. package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/workflow.md +44 -0
  40. package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/steps/step-01-define-requirements.md +85 -0
  41. package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/steps/step-02-user-flows.md +59 -0
  42. package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/steps/step-03-information-architecture.md +68 -0
  43. package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/steps/step-04-wireframe-sketch.md +97 -0
  44. package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/steps/step-05-components.md +128 -0
  45. package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/steps/step-06-synthesize.md +83 -0
  46. package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/wireframe.template.md +287 -0
  47. package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/workflow.md +44 -0
  48. package/_bmad/bme/_vortex/workflows/assumption-mapping/steps/step-01-setup.md +66 -0
  49. package/_bmad/bme/_vortex/workflows/assumption-mapping/steps/step-02-context.md +93 -0
  50. package/_bmad/bme/_vortex/workflows/assumption-mapping/steps/step-03-risk-mapping.md +103 -0
  51. package/_bmad/bme/_vortex/workflows/assumption-mapping/steps/step-04-synthesize.md +101 -0
  52. package/_bmad/bme/_vortex/workflows/assumption-mapping/workflow.md +49 -0
  53. package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-01-setup.md +81 -0
  54. package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-02-context.md +67 -0
  55. package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-03-classification.md +98 -0
  56. package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-04-evidence.md +100 -0
  57. package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-05-synthesize.md +174 -0
  58. package/_bmad/bme/_vortex/workflows/behavior-analysis/workflow.md +52 -0
  59. package/_bmad/bme/_vortex/workflows/contextualize-scope/contextualize-scope.template.md +67 -0
  60. package/_bmad/bme/_vortex/workflows/contextualize-scope/steps/step-01-list-opportunities.md +47 -0
  61. package/_bmad/bme/_vortex/workflows/contextualize-scope/steps/step-02-define-criteria.md +36 -0
  62. package/_bmad/bme/_vortex/workflows/contextualize-scope/steps/step-03-evaluate-opportunities.md +30 -0
  63. package/_bmad/bme/_vortex/workflows/contextualize-scope/steps/step-04-define-boundaries.md +32 -0
  64. package/_bmad/bme/_vortex/workflows/contextualize-scope/steps/step-05-validate-fit.md +28 -0
  65. package/_bmad/bme/_vortex/workflows/contextualize-scope/steps/step-06-synthesize.md +36 -0
  66. package/_bmad/bme/_vortex/workflows/contextualize-scope/validate.md +30 -0
  67. package/_bmad/bme/_vortex/workflows/contextualize-scope/workflow.md +59 -0
  68. package/_bmad/bme/_vortex/workflows/empathy-map/empathy-map.template.md +143 -0
  69. package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-01-define-user.md +60 -0
  70. package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-02-says-thinks.md +67 -0
  71. package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-03-does-feels.md +79 -0
  72. package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-04-pain-points.md +87 -0
  73. package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-05-gains.md +103 -0
  74. package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-06-synthesize.md +107 -0
  75. package/_bmad/bme/_vortex/workflows/empathy-map/validate.md +117 -0
  76. package/_bmad/bme/_vortex/workflows/empathy-map/workflow.md +45 -0
  77. package/_bmad/bme/_vortex/workflows/experiment-design/steps/step-01-setup.md +66 -0
  78. package/_bmad/bme/_vortex/workflows/experiment-design/steps/step-02-context.md +77 -0
  79. package/_bmad/bme/_vortex/workflows/experiment-design/steps/step-03-design.md +114 -0
  80. package/_bmad/bme/_vortex/workflows/experiment-design/steps/step-04-synthesize.md +128 -0
  81. package/_bmad/bme/_vortex/workflows/experiment-design/workflow.md +51 -0
  82. package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-01-setup.md +66 -0
  83. package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-02-context.md +80 -0
  84. package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-03-brainwriting.md +79 -0
  85. package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-04-assumption-mapping.md +102 -0
  86. package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-05-synthesize.md +130 -0
  87. package/_bmad/bme/_vortex/workflows/hypothesis-engineering/workflow.md +52 -0
  88. package/_bmad/bme/_vortex/workflows/lean-experiment/lean-experiment.template.md +29 -0
  89. package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-01-hypothesis.md +58 -0
  90. package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-02-design.md +68 -0
  91. package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-03-metrics.md +73 -0
  92. package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-04-run.md +75 -0
  93. package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-05-analyze.md +84 -0
  94. package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-06-decide.md +111 -0
  95. package/_bmad/bme/_vortex/workflows/lean-experiment/validate.md +30 -0
  96. package/_bmad/bme/_vortex/workflows/lean-experiment/workflow.md +26 -0
  97. package/_bmad/bme/_vortex/workflows/lean-persona/lean-persona.template.md +163 -0
  98. package/_bmad/bme/_vortex/workflows/lean-persona/steps/step-01-define-job.md +72 -0
  99. package/_bmad/bme/_vortex/workflows/lean-persona/steps/step-02-current-solution.md +83 -0
  100. package/_bmad/bme/_vortex/workflows/lean-persona/steps/step-03-problem-contexts.md +90 -0
  101. package/_bmad/bme/_vortex/workflows/lean-persona/steps/step-04-forces-anxieties.md +98 -0
  102. package/_bmad/bme/_vortex/workflows/lean-persona/steps/step-05-success-criteria.md +103 -0
  103. package/_bmad/bme/_vortex/workflows/lean-persona/steps/step-06-synthesize.md +129 -0
  104. package/_bmad/bme/_vortex/workflows/lean-persona/validate.md +30 -0
  105. package/_bmad/bme/_vortex/workflows/lean-persona/workflow.md +50 -0
  106. package/_bmad/bme/_vortex/workflows/learning-card/learning-card.template.md +179 -0
  107. package/_bmad/bme/_vortex/workflows/learning-card/steps/step-01-experiment-context.md +100 -0
  108. package/_bmad/bme/_vortex/workflows/learning-card/steps/step-02-raw-results.md +125 -0
  109. package/_bmad/bme/_vortex/workflows/learning-card/steps/step-03-analysis.md +125 -0
  110. package/_bmad/bme/_vortex/workflows/learning-card/steps/step-04-validated-learning.md +139 -0
  111. package/_bmad/bme/_vortex/workflows/learning-card/steps/step-05-implications.md +134 -0
  112. package/_bmad/bme/_vortex/workflows/learning-card/steps/step-06-synthesize.md +121 -0
  113. package/_bmad/bme/_vortex/workflows/learning-card/validate.md +134 -0
  114. package/_bmad/bme/_vortex/workflows/learning-card/workflow.md +51 -0
  115. package/_bmad/bme/_vortex/workflows/mvp/mvp.template.md +40 -0
  116. package/_bmad/bme/_vortex/workflows/mvp/steps/step-01-riskiest-assumption.md +17 -0
  117. package/_bmad/bme/_vortex/workflows/mvp/steps/step-02-success-criteria.md +13 -0
  118. package/_bmad/bme/_vortex/workflows/mvp/steps/step-03-smallest-test.md +13 -0
  119. package/_bmad/bme/_vortex/workflows/mvp/steps/step-04-scope-features.md +13 -0
  120. package/_bmad/bme/_vortex/workflows/mvp/steps/step-05-build-measure-learn.md +13 -0
  121. package/_bmad/bme/_vortex/workflows/mvp/steps/step-06-synthesize.md +28 -0
  122. package/_bmad/bme/_vortex/workflows/mvp/validate.md +30 -0
  123. package/_bmad/bme/_vortex/workflows/mvp/workflow.md +36 -0
  124. package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-01-setup.md +102 -0
  125. package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-02-context.md +81 -0
  126. package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-03-pattern-identification.md +88 -0
  127. package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-04-theme-clustering.md +100 -0
  128. package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-05-synthesize.md +135 -0
  129. package/_bmad/bme/_vortex/workflows/pattern-mapping/workflow.md +58 -0
  130. package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/pivot-patch-persevere.template.md +201 -0
  131. package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-01-evidence-review.md +125 -0
  132. package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-02-hypothesis-assessment.md +132 -0
  133. package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-03-option-analysis.md +167 -0
  134. package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-04-stakeholder-input.md +141 -0
  135. package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-05-decision.md +161 -0
  136. package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-06-action-plan.md +188 -0
  137. package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/validate.md +159 -0
  138. package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/workflow.md +51 -0
  139. package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-01-setup.md +97 -0
  140. package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-02-context.md +86 -0
  141. package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-03-jtbd-reframing.md +88 -0
  142. package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-04-pains-gains-revision.md +76 -0
  143. package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-05-synthesize.md +158 -0
  144. package/_bmad/bme/_vortex/workflows/pivot-resynthesis/workflow.md +52 -0
  145. package/_bmad/bme/_vortex/workflows/product-vision/product-vision.template.md +147 -0
  146. package/_bmad/bme/_vortex/workflows/product-vision/steps/step-01-define-problem.md +89 -0
  147. package/_bmad/bme/_vortex/workflows/product-vision/steps/step-02-target-market.md +91 -0
  148. package/_bmad/bme/_vortex/workflows/product-vision/steps/step-03-unique-approach.md +87 -0
  149. package/_bmad/bme/_vortex/workflows/product-vision/steps/step-04-future-state.md +100 -0
  150. package/_bmad/bme/_vortex/workflows/product-vision/steps/step-05-principles.md +92 -0
  151. package/_bmad/bme/_vortex/workflows/product-vision/steps/step-06-synthesize.md +170 -0
  152. package/_bmad/bme/_vortex/workflows/product-vision/validate.md +30 -0
  153. package/_bmad/bme/_vortex/workflows/product-vision/workflow.md +55 -0
  154. package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-01-setup.md +84 -0
  155. package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-02-context.md +66 -0
  156. package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-03-monitoring.md +74 -0
  157. package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-04-prioritization.md +97 -0
  158. package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-05-synthesize.md +183 -0
  159. package/_bmad/bme/_vortex/workflows/production-monitoring/workflow.md +52 -0
  160. package/_bmad/bme/_vortex/workflows/proof-of-concept/proof-of-concept.template.md +25 -0
  161. package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-01-risk.md +79 -0
  162. package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-02-scope.md +105 -0
  163. package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-03-build.md +92 -0
  164. package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-04-test.md +103 -0
  165. package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-05-evaluate.md +114 -0
  166. package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-06-document.md +125 -0
  167. package/_bmad/bme/_vortex/workflows/proof-of-concept/validate.md +30 -0
  168. package/_bmad/bme/_vortex/workflows/proof-of-concept/workflow.md +26 -0
  169. package/_bmad/bme/_vortex/workflows/proof-of-value/proof-of-value.template.md +29 -0
  170. package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-01-value-hypothesis.md +75 -0
  171. package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-02-validation-design.md +94 -0
  172. package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-03-willingness.md +96 -0
  173. package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-04-test.md +107 -0
  174. package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-05-analyze.md +116 -0
  175. package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-06-document.md +147 -0
  176. package/_bmad/bme/_vortex/workflows/proof-of-value/validate.md +30 -0
  177. package/_bmad/bme/_vortex/workflows/proof-of-value/workflow.md +26 -0
  178. package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-01-setup.md +69 -0
  179. package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-02-context.md +70 -0
  180. package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-03-jtbd-framing.md +81 -0
  181. package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-04-pains-gains.md +77 -0
  182. package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-05-synthesize.md +147 -0
  183. package/_bmad/bme/_vortex/workflows/research-convergence/workflow.md +50 -0
  184. package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-01-setup.md +68 -0
  185. package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-02-context.md +67 -0
  186. package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-03-signal-analysis.md +85 -0
  187. package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-04-anomaly-detection.md +93 -0
  188. package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-05-synthesize.md +163 -0
  189. package/_bmad/bme/_vortex/workflows/signal-interpretation/workflow.md +52 -0
  190. package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-01-discovery-scope.md +77 -0
  191. package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-02-research-methods.md +152 -0
  192. package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-03-research-plan.md +159 -0
  193. package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-04-execute.md +169 -0
  194. package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-05-organize-data.md +149 -0
  195. package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-06-synthesize.md +159 -0
  196. package/_bmad/bme/_vortex/workflows/user-discovery/user-discovery.template.md +231 -0
  197. package/_bmad/bme/_vortex/workflows/user-discovery/validate.md +153 -0
  198. package/_bmad/bme/_vortex/workflows/user-discovery/workflow.md +45 -0
  199. package/_bmad/bme/_vortex/workflows/user-interview/steps/step-01-research-goals.md +100 -0
  200. package/_bmad/bme/_vortex/workflows/user-interview/steps/step-02-interview-script.md +123 -0
  201. package/_bmad/bme/_vortex/workflows/user-interview/steps/step-03-recruitment.md +144 -0
  202. package/_bmad/bme/_vortex/workflows/user-interview/steps/step-04-conduct.md +154 -0
  203. package/_bmad/bme/_vortex/workflows/user-interview/steps/step-05-findings.md +163 -0
  204. package/_bmad/bme/_vortex/workflows/user-interview/steps/step-06-synthesize.md +171 -0
  205. package/_bmad/bme/_vortex/workflows/user-interview/user-interview.template.md +250 -0
  206. package/_bmad/bme/_vortex/workflows/user-interview/validate.md +142 -0
  207. package/_bmad/bme/_vortex/workflows/user-interview/workflow.md +51 -0
  208. package/_bmad/bme/_vortex/workflows/vortex-navigation/steps/step-01-current-state.md +56 -0
  209. package/_bmad/bme/_vortex/workflows/vortex-navigation/steps/step-02-evidence-inventory.md +70 -0
  210. package/_bmad/bme/_vortex/workflows/vortex-navigation/steps/step-03-gap-analysis.md +76 -0
  211. package/_bmad/bme/_vortex/workflows/vortex-navigation/steps/step-04-stream-evaluation.md +57 -0
  212. package/_bmad/bme/_vortex/workflows/vortex-navigation/steps/step-05-recommendation.md +65 -0
  213. package/_bmad/bme/_vortex/workflows/vortex-navigation/steps/step-06-navigation-plan.md +72 -0
  214. package/_bmad/bme/_vortex/workflows/vortex-navigation/validate.md +75 -0
  215. package/_bmad/bme/_vortex/workflows/vortex-navigation/vortex-navigation.template.md +105 -0
  216. package/_bmad/bme/_vortex/workflows/vortex-navigation/workflow.md +54 -0
  217. package/index.js +56 -0
  218. package/package.json +77 -0
  219. package/scripts/README.md +226 -0
  220. package/scripts/convoke-doctor.js +322 -0
  221. package/scripts/docs-audit.js +584 -0
  222. package/scripts/install-all-agents.js +9 -0
  223. package/scripts/install-vortex-agents.js +208 -0
  224. package/scripts/postinstall.js +104 -0
  225. package/scripts/update/convoke-migrate.js +169 -0
  226. package/scripts/update/convoke-update.js +272 -0
  227. package/scripts/update/convoke-version.js +134 -0
  228. package/scripts/update/lib/agent-registry.js +144 -0
  229. package/scripts/update/lib/backup-manager.js +243 -0
  230. package/scripts/update/lib/config-merger.js +242 -0
  231. package/scripts/update/lib/migration-runner.js +367 -0
  232. package/scripts/update/lib/refresh-installation.js +171 -0
  233. package/scripts/update/lib/utils.js +96 -0
  234. package/scripts/update/lib/validator.js +360 -0
  235. package/scripts/update/lib/version-detector.js +241 -0
  236. package/scripts/update/migrations/1.0.x-to-1.3.0.js +128 -0
  237. package/scripts/update/migrations/1.1.x-to-1.3.0.js +29 -0
  238. package/scripts/update/migrations/1.2.x-to-1.3.0.js +29 -0
  239. package/scripts/update/migrations/1.3.x-to-1.5.0.js +29 -0
  240. package/scripts/update/migrations/1.4.x-to-1.5.0.js +29 -0
  241. package/scripts/update/migrations/1.5.x-to-1.6.0.js +95 -0
  242. package/scripts/update/migrations/1.6.x-to-1.7.0.js +29 -0
  243. package/scripts/update/migrations/1.7.x-to-2.0.0.js +31 -0
  244. package/scripts/update/migrations/registry.js +194 -0
@@ -0,0 +1,367 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs-extra');
4
+ const path = require('path');
5
+ const chalk = require('chalk');
6
+ const yaml = require('js-yaml');
7
+ const { findProjectRoot, getPackageVersion } = require('./utils');
8
+ const backupManager = require('./backup-manager');
9
+ const configMerger = require('./config-merger');
10
+ const validator = require('./validator');
11
+ const { refreshInstallation } = require('./refresh-installation');
12
+ const registry = require('../migrations/registry');
13
+ const { WORKFLOW_NAMES } = require('./agent-registry');
14
+
15
+ /**
16
+ * Migration Runner for Convoke
17
+ * Core orchestration: executes migration deltas, refreshes installation, handles backups and rollback.
18
+ */
19
+
20
+ /**
21
+ * Run migrations from current version to the current package version.
22
+ * @param {string} fromVersion - Current installed version
23
+ * @param {object} options - Options { dryRun, verbose }
24
+ * @returns {Promise<object>} Migration result
25
+ */
26
+ async function runMigrations(fromVersion, options = {}) {
27
+ const { dryRun = false, verbose = false } = options;
28
+ const toVersion = getPackageVersion();
29
+
30
+ // Resolve project root
31
+ const projectRoot = findProjectRoot();
32
+ if (!projectRoot) {
33
+ throw new Error('Not in a Convoke project. Could not find _bmad/ directory.');
34
+ }
35
+
36
+ console.log('');
37
+ if (dryRun) {
38
+ console.log(chalk.yellow.bold('═══ DRY RUN MODE ═══'));
39
+ console.log(chalk.yellow('No changes will be made to your installation'));
40
+ console.log('');
41
+ }
42
+
43
+ // 1. Get applicable migration deltas
44
+ const migrations = registry.getMigrationsFor(fromVersion);
45
+
46
+ if (migrations.length === 0) {
47
+ console.log(chalk.yellow('No migrations needed'));
48
+ return { success: true, migrations: [], skipped: true };
49
+ }
50
+
51
+ console.log(chalk.cyan(`Found ${migrations.length} migration(s) to apply:`));
52
+ migrations.forEach((m, i) => {
53
+ const icon = m.breaking ? chalk.red('⚠') : chalk.green('✓');
54
+ console.log(` ${i + 1}. ${icon} ${m.name} - ${m.description}`);
55
+ });
56
+ console.log('');
57
+
58
+ // If dry run, just preview
59
+ if (dryRun) {
60
+ return await previewMigrations(migrations);
61
+ }
62
+
63
+ // 2. Acquire migration lock
64
+ await acquireMigrationLock(projectRoot);
65
+
66
+ let backupMetadata = null;
67
+ const results = [];
68
+
69
+ try {
70
+ // 3. Create backup
71
+ console.log(chalk.cyan('[1/5] Creating backup...'));
72
+ backupMetadata = await backupManager.createBackup(fromVersion, projectRoot);
73
+ console.log(chalk.green(`✓ Backup created: ${path.basename(backupMetadata.backup_dir)}`));
74
+ console.log('');
75
+
76
+ // 4. Execute migration deltas sequentially
77
+ console.log(chalk.cyan('[2/5] Running migration deltas...'));
78
+ for (let i = 0; i < migrations.length; i++) {
79
+ const migration = migrations[i];
80
+ console.log(chalk.cyan(`\nMigration ${i + 1}/${migrations.length}: ${migration.name}`));
81
+
82
+ try {
83
+ const changes = await executeMigration(migration, projectRoot, { verbose });
84
+ results.push({
85
+ name: migration.name,
86
+ success: true,
87
+ changes
88
+ });
89
+
90
+ console.log(chalk.green(`✓ ${migration.name} completed`));
91
+ } catch (error) {
92
+ console.error(chalk.red(`✗ ${migration.name} failed: ${error.message}`));
93
+ throw new MigrationError(migration.name, error);
94
+ }
95
+ }
96
+ console.log('');
97
+ console.log(chalk.green('✓ All migration deltas completed'));
98
+ console.log('');
99
+
100
+ // 5. Refresh installation (copy latest files from package)
101
+ console.log(chalk.cyan('[3/5] Refreshing installation files...'));
102
+ const refreshChanges = await refreshInstallation(projectRoot);
103
+ results.push({
104
+ name: 'refresh-installation',
105
+ success: true,
106
+ changes: refreshChanges
107
+ });
108
+ console.log(chalk.green('✓ Installation refreshed'));
109
+ console.log('');
110
+
111
+ // 6. Update migration history in config.yaml
112
+ console.log(chalk.cyan('[4/5] Updating configuration...'));
113
+ await updateMigrationHistory(projectRoot, fromVersion, toVersion, results);
114
+ console.log(chalk.green('✓ Migration history updated'));
115
+ console.log('');
116
+
117
+ // 7. Validate installation
118
+ console.log(chalk.cyan('[5/5] Validating installation...'));
119
+ const validationResult = await validator.validateInstallation(backupMetadata, projectRoot);
120
+
121
+ validationResult.checks.forEach(check => {
122
+ if (check.passed) {
123
+ console.log(chalk.green(` ✓ ${check.name}`));
124
+ if (check.info || check.warning) {
125
+ console.log(chalk.gray(` ${check.info || check.warning}`));
126
+ }
127
+ } else {
128
+ console.log(chalk.red(` ✗ ${check.name}`));
129
+ if (check.error) {
130
+ console.log(chalk.red(` Error: ${check.error}`));
131
+ }
132
+ }
133
+ });
134
+ console.log('');
135
+
136
+ if (!validationResult.valid) {
137
+ throw new Error('Installation validation failed');
138
+ }
139
+
140
+ console.log(chalk.green('✓ Installation validated'));
141
+ console.log('');
142
+
143
+ // 8. Cleanup old backups
144
+ const deletedCount = await backupManager.cleanupOldBackups(5, projectRoot);
145
+ if (deletedCount > 0) {
146
+ console.log(chalk.green(`✓ Cleaned up ${deletedCount} old backup(s)`));
147
+ }
148
+
149
+ // Release lock
150
+ await releaseMigrationLock(projectRoot);
151
+
152
+ // Create migration log
153
+ await createMigrationLog(projectRoot, fromVersion, toVersion, results, backupMetadata);
154
+
155
+ return {
156
+ success: true,
157
+ fromVersion,
158
+ toVersion,
159
+ results,
160
+ backupMetadata
161
+ };
162
+
163
+ } catch (error) {
164
+ console.error('');
165
+ console.error(chalk.red.bold('✗ Migration failed!'));
166
+ console.error('');
167
+ console.error(chalk.red(error.message));
168
+ console.error('');
169
+
170
+ // Rollback if we have a backup
171
+ if (backupMetadata) {
172
+ console.log(chalk.yellow('Restoring from backup...'));
173
+ try {
174
+ await backupManager.restoreBackup(backupMetadata, projectRoot);
175
+ console.log(chalk.green('✓ Installation restored from backup'));
176
+ console.log('');
177
+ } catch (restoreError) {
178
+ console.error(chalk.red('✗ Restore failed!'));
179
+ console.error(chalk.red(restoreError.message));
180
+ console.error('');
181
+ console.error(chalk.yellow(`Manual restore may be needed from: ${backupMetadata.backup_dir}`));
182
+ console.error('');
183
+ }
184
+ }
185
+
186
+ // Release lock
187
+ await releaseMigrationLock(projectRoot);
188
+
189
+ // Create error log
190
+ await createErrorLog(projectRoot, fromVersion, toVersion, error, backupMetadata);
191
+
192
+ throw error;
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Preview migrations without applying
198
+ */
199
+ async function previewMigrations(migrations) {
200
+ const previews = [];
201
+
202
+ for (const migration of migrations) {
203
+ console.log(chalk.cyan(`\n${migration.name}:`));
204
+ console.log(chalk.gray(migration.description));
205
+
206
+ if (migration.module && migration.module.preview) {
207
+ const preview = await migration.module.preview();
208
+ console.log('');
209
+ console.log(chalk.white('Actions:'));
210
+ preview.actions.forEach(action => {
211
+ console.log(chalk.gray(` - ${action}`));
212
+ });
213
+ previews.push({ name: migration.name, preview });
214
+ }
215
+ }
216
+
217
+ console.log('');
218
+ console.log(chalk.white('After deltas, installation will be refreshed:'));
219
+ console.log(chalk.gray(' - Refresh agent files'));
220
+ console.log(chalk.gray(` - Refresh ${WORKFLOW_NAMES.length} workflow directories`));
221
+ console.log(chalk.gray(' - Update config.yaml (preserving user preferences)'));
222
+ console.log(chalk.gray(' - Update user guides (with .bak backup)'));
223
+ console.log('');
224
+ console.log(chalk.green('To apply these changes, run:'));
225
+ console.log(chalk.cyan(' npx convoke-update'));
226
+ console.log('');
227
+
228
+ return { success: true, dryRun: true, previews };
229
+ }
230
+
231
+ /**
232
+ * Execute a single migration delta
233
+ */
234
+ async function executeMigration(migration, projectRoot, options = {}) {
235
+ const { verbose = false } = options;
236
+
237
+ if (!migration.module || !migration.module.apply) {
238
+ throw new Error(`Migration ${migration.name} has no apply function`);
239
+ }
240
+
241
+ const changes = await migration.module.apply(projectRoot);
242
+
243
+ if (verbose) {
244
+ changes.forEach(change => {
245
+ console.log(chalk.gray(` - ${change}`));
246
+ });
247
+ }
248
+
249
+ return changes;
250
+ }
251
+
252
+ /**
253
+ * Update migration history in config.yaml
254
+ */
255
+ async function updateMigrationHistory(projectRoot, fromVersion, toVersion, results) {
256
+ const configPath = path.join(projectRoot, '_bmad/bme/_vortex/config.yaml');
257
+
258
+ if (!fs.existsSync(configPath)) {
259
+ throw new Error('config.yaml not found after refresh');
260
+ }
261
+
262
+ const configContent = fs.readFileSync(configPath, 'utf8');
263
+ const config = yaml.load(configContent);
264
+
265
+ const migrationsApplied = results
266
+ .filter(r => r.name !== 'refresh-installation')
267
+ .map(r => r.name);
268
+
269
+ const updatedConfig = configMerger.addMigrationHistory(
270
+ config, fromVersion, toVersion, migrationsApplied
271
+ );
272
+
273
+ await configMerger.writeConfig(configPath, updatedConfig);
274
+ }
275
+
276
+ async function acquireMigrationLock(projectRoot) {
277
+ const lockFile = path.join(projectRoot, '_bmad-output/.migration-lock');
278
+
279
+ if (fs.existsSync(lockFile)) {
280
+ const lock = await fs.readJson(lockFile);
281
+ const age = Date.now() - lock.timestamp;
282
+
283
+ if (age > 5 * 60 * 1000) {
284
+ console.log(chalk.yellow('Removing stale migration lock'));
285
+ await fs.remove(lockFile);
286
+ } else {
287
+ throw new Error('Migration already in progress. Please wait and try again.');
288
+ }
289
+ }
290
+
291
+ await fs.ensureDir(path.join(projectRoot, '_bmad-output'));
292
+ await fs.writeJson(lockFile, { timestamp: Date.now(), pid: process.pid });
293
+ }
294
+
295
+ async function releaseMigrationLock(projectRoot) {
296
+ const lockFile = path.join(projectRoot, '_bmad-output/.migration-lock');
297
+ if (fs.existsSync(lockFile)) {
298
+ await fs.remove(lockFile);
299
+ }
300
+ }
301
+
302
+ async function createMigrationLog(projectRoot, fromVersion, toVersion, results, backupMetadata) {
303
+ const logsDir = path.join(projectRoot, '_bmad-output/.logs');
304
+ await fs.ensureDir(logsDir);
305
+
306
+ const logFile = path.join(logsDir, `migration-${Date.now()}.log`);
307
+ const logContent = [
308
+ `Convoke Migration Log`,
309
+ `Date: ${new Date().toISOString()}`,
310
+ `From Version: ${fromVersion}`,
311
+ `To Version: ${toVersion}`,
312
+ '',
313
+ 'Migrations Applied:',
314
+ ...results.map(r => ` - ${r.name}`),
315
+ '',
316
+ 'Changes:',
317
+ ...results.flatMap(r => r.changes.map(c => ` - ${c}`)),
318
+ '',
319
+ `Backup: ${backupMetadata.backup_dir}`,
320
+ '',
321
+ 'Status: SUCCESS'
322
+ ].join('\n');
323
+
324
+ await fs.writeFile(logFile, logContent, 'utf8');
325
+ }
326
+
327
+ async function createErrorLog(projectRoot, fromVersion, toVersion, error, backupMetadata) {
328
+ const logsDir = path.join(projectRoot, '_bmad-output/.logs');
329
+ await fs.ensureDir(logsDir);
330
+
331
+ const logFile = path.join(logsDir, `migration-error-${Date.now()}.log`);
332
+ const logContent = [
333
+ `Convoke Migration Error Log`,
334
+ `Date: ${new Date().toISOString()}`,
335
+ `From Version: ${fromVersion}`,
336
+ `To Version: ${toVersion}`,
337
+ '',
338
+ `Error: ${error.message}`,
339
+ '',
340
+ 'Stack Trace:',
341
+ error.stack,
342
+ '',
343
+ backupMetadata ? `Backup: ${backupMetadata.backup_dir}` : 'No backup created',
344
+ backupMetadata ? 'Status: ROLLED BACK' : 'Status: FAILED (no backup)',
345
+ '',
346
+ 'Please report this issue at: https://github.com/amalik/convoke-agents/issues'
347
+ ].join('\n');
348
+
349
+ await fs.writeFile(logFile, logContent, 'utf8');
350
+ console.log(chalk.gray(`Migration log: ${logFile}`));
351
+ }
352
+
353
+ class MigrationError extends Error {
354
+ constructor(migrationName, originalError) {
355
+ super(`Migration ${migrationName} failed: ${originalError.message}`);
356
+ this.name = 'MigrationError';
357
+ this.migrationName = migrationName;
358
+ this.originalError = originalError;
359
+ }
360
+ }
361
+
362
+ module.exports = {
363
+ runMigrations,
364
+ previewMigrations,
365
+ executeMigration,
366
+ MigrationError
367
+ };
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs-extra');
4
+ const path = require('path');
5
+ const { getPackageVersion } = require('./utils');
6
+ const configMerger = require('./config-merger');
7
+ const { AGENTS, AGENT_FILES, AGENT_IDS, WORKFLOW_NAMES, USER_GUIDES } = require('./agent-registry');
8
+
9
+ /**
10
+ * Refresh Installation for Convoke
11
+ *
12
+ * Copies latest agent files, workflows, config, and user guides from the
13
+ * package to the project. Called ONCE after all migration deltas have run,
14
+ * or directly by the install script.
15
+ */
16
+
17
+ /**
18
+ * Refresh all installation files from the package to the project.
19
+ *
20
+ * @param {string} projectRoot - Absolute path to project root
21
+ * @param {object} options
22
+ * @param {boolean} options.backupGuides - Create .bak of user guides before overwriting (default: true)
23
+ * @param {boolean} options.verbose - Log each action (default: true)
24
+ * @returns {Promise<Array<string>>} List of changes made
25
+ */
26
+ async function refreshInstallation(projectRoot, options = {}) {
27
+ const { backupGuides = true, verbose = true } = options;
28
+ const changes = [];
29
+ const packageRoot = path.join(__dirname, '..', '..', '..');
30
+ const packageVortex = path.join(packageRoot, '_bmad', 'bme', '_vortex');
31
+ const targetVortex = path.join(projectRoot, '_bmad', 'bme', '_vortex');
32
+ const version = getPackageVersion();
33
+
34
+ // When running from the package's own directory (dev environment),
35
+ // source and destination are identical — skip file copies.
36
+ const isSameRoot = path.resolve(packageRoot) === path.resolve(projectRoot);
37
+
38
+ // 1. Copy agent files
39
+ const agentsSource = path.join(packageVortex, 'agents');
40
+ const agentsTarget = path.join(targetVortex, 'agents');
41
+ await fs.ensureDir(agentsTarget);
42
+
43
+ if (!isSameRoot) {
44
+ for (const file of AGENT_FILES) {
45
+ const src = path.join(agentsSource, file);
46
+ if (fs.existsSync(src)) {
47
+ await fs.copy(src, path.join(agentsTarget, file), { overwrite: true });
48
+ changes.push(`Refreshed agent: ${file}`);
49
+ if (verbose) console.log(` Refreshed agent: ${file}`);
50
+ }
51
+ }
52
+ } else {
53
+ changes.push('Skipped agent copy (dev environment — files already in place)');
54
+ if (verbose) console.log(' Skipped agent copy (dev environment)');
55
+ }
56
+
57
+ // Remove deprecated agent files if still present
58
+ const deprecatedAgents = ['empathy-mapper.md', 'wireframe-designer.md'];
59
+ for (const file of deprecatedAgents) {
60
+ const agentPath = path.join(agentsTarget, file);
61
+ if (fs.existsSync(agentPath)) {
62
+ await fs.remove(agentPath);
63
+ changes.push(`Removed deprecated agent: ${file}`);
64
+ if (verbose) console.log(` Removed deprecated agent: ${file}`);
65
+ }
66
+ }
67
+
68
+ // 2. Copy workflow directories
69
+ const workflowsSource = path.join(packageVortex, 'workflows');
70
+ const workflowsTarget = path.join(targetVortex, 'workflows');
71
+ await fs.ensureDir(workflowsTarget);
72
+
73
+ if (!isSameRoot) {
74
+ for (const wf of WORKFLOW_NAMES) {
75
+ const src = path.join(workflowsSource, wf);
76
+ if (fs.existsSync(src)) {
77
+ await fs.copy(src, path.join(workflowsTarget, wf), { overwrite: true });
78
+ changes.push(`Refreshed workflow: ${wf}`);
79
+ if (verbose) console.log(` Refreshed workflow: ${wf}`);
80
+ }
81
+ }
82
+ } else {
83
+ changes.push('Skipped workflow copy (dev environment — files already in place)');
84
+ if (verbose) console.log(' Skipped workflow copy (dev environment)');
85
+ }
86
+
87
+ // 3. Update config.yaml (merge, preserving user prefs)
88
+ const configPath = path.join(targetVortex, 'config.yaml');
89
+ await fs.ensureDir(path.dirname(configPath));
90
+
91
+ const updates = {
92
+ agents: AGENT_IDS,
93
+ workflows: WORKFLOW_NAMES
94
+ };
95
+
96
+ const merged = await configMerger.mergeConfig(configPath, version, updates);
97
+ await configMerger.writeConfig(configPath, merged);
98
+ changes.push(`Updated config.yaml to v${version}`);
99
+ if (verbose) console.log(` Updated config.yaml to v${version}`);
100
+
101
+ // 4. Regenerate agent manifest — replace only bme rows, preserve other modules
102
+ const manifestPath = path.join(projectRoot, '_bmad', '_config', 'agent-manifest.csv');
103
+ await fs.ensureDir(path.dirname(manifestPath));
104
+
105
+ function csvEscape(value) {
106
+ return `"${String(value).replace(/"/g, '""')}"`;
107
+ }
108
+
109
+ const header = '"agent_id","name","title","icon","role","identity","communication_style","expertise","submodule","path"';
110
+
111
+ // Read existing non-bme rows to preserve them
112
+ let preservedRows = [];
113
+ if (fs.existsSync(manifestPath)) {
114
+ const existing = (await fs.readFile(manifestPath, 'utf8')).trim().split('\n');
115
+ // Skip header, keep rows where submodule is NOT bme
116
+ preservedRows = existing.slice(1).filter(row => {
117
+ // submodule is the 9th field (index 8) in the CSV
118
+ const fields = row.match(/"([^"]*(?:""[^"]*)*)"/g);
119
+ if (!fields || fields.length < 9) return true; // keep unrecognised rows
120
+ const submodule = fields[8].replace(/^"|"$/g, '');
121
+ return submodule !== 'bme';
122
+ });
123
+ }
124
+
125
+ // Build fresh bme rows from registry
126
+ const bmeRows = AGENTS.map(a => {
127
+ const p = a.persona;
128
+ return [
129
+ a.id, a.name, a.title, a.icon,
130
+ p.role, p.identity, p.communication_style, p.expertise,
131
+ 'bme', `_bmad/bme/_vortex/agents/${a.id}.md`,
132
+ ].map(csvEscape).join(',');
133
+ });
134
+
135
+ const allRows = [...preservedRows, ...bmeRows].join('\n') + '\n';
136
+ await fs.writeFile(manifestPath, header + '\n' + allRows, 'utf8');
137
+ changes.push('Regenerated agent-manifest.csv (bme rows updated, other modules preserved)');
138
+ if (verbose) console.log(' Regenerated agent-manifest.csv (bme rows updated, other modules preserved)');
139
+
140
+ // 5. Copy user guides (with optional backup)
141
+ const guidesSource = path.join(packageRoot, '_bmad', 'bme', '_vortex', 'guides');
142
+ const guidesTarget = path.join(projectRoot, '_bmad', 'bme', '_vortex', 'guides');
143
+ await fs.ensureDir(guidesTarget);
144
+
145
+ if (!isSameRoot) {
146
+ for (const guide of USER_GUIDES) {
147
+ const src = path.join(guidesSource, guide);
148
+ const dest = path.join(guidesTarget, guide);
149
+
150
+ if (fs.existsSync(src)) {
151
+ // Backup existing guide before overwriting
152
+ if (backupGuides && fs.existsSync(dest)) {
153
+ await fs.copy(dest, dest + '.bak', { overwrite: true });
154
+ changes.push(`Backed up ${guide} → ${guide}.bak`);
155
+ if (verbose) console.log(` Backed up ${guide} → ${guide}.bak`);
156
+ }
157
+
158
+ await fs.copy(src, dest, { overwrite: true });
159
+ changes.push(`Refreshed guide: ${guide}`);
160
+ if (verbose) console.log(` Refreshed guide: ${guide}`);
161
+ }
162
+ }
163
+ } else {
164
+ changes.push('Skipped guide copy (dev environment — files already in place)');
165
+ if (verbose) console.log(' Skipped guide copy (dev environment)');
166
+ }
167
+
168
+ return changes;
169
+ }
170
+
171
+ module.exports = { refreshInstallation };
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs-extra');
4
+ const path = require('path');
5
+
6
+ /**
7
+ * Shared utilities for the Convoke update system.
8
+ * Single source of truth for version, comparison, project detection.
9
+ */
10
+
11
+ /**
12
+ * Get the package version at runtime from package.json.
13
+ * This is the SINGLE SOURCE OF TRUTH for version - never hardcode versions elsewhere.
14
+ * @returns {string} e.g. "1.3.8"
15
+ */
16
+ function getPackageVersion() {
17
+ const pkg = require('../../../package.json');
18
+ return pkg.version;
19
+ }
20
+
21
+ /**
22
+ * Compare two semantic version strings.
23
+ * @param {string} v1
24
+ * @param {string} v2
25
+ * @returns {number} -1 if v1 < v2, 0 if equal, 1 if v1 > v2
26
+ */
27
+ function compareVersions(v1, v2) {
28
+ const parts1 = v1.split('.').map(Number);
29
+ const parts2 = v2.split('.').map(Number);
30
+
31
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
32
+ const p1 = parts1[i] || 0;
33
+ const p2 = parts2[i] || 0;
34
+ if (p1 < p2) return -1;
35
+ if (p1 > p2) return 1;
36
+ }
37
+
38
+ return 0;
39
+ }
40
+
41
+ /**
42
+ * Count user data files in _bmad-output/ (excluding .backups, .logs).
43
+ * @param {string} projectRoot - Absolute path to project root
44
+ * @returns {Promise<number>}
45
+ */
46
+ async function countUserDataFiles(projectRoot) {
47
+ const outputDir = path.join(projectRoot, '_bmad-output');
48
+
49
+ if (!fs.existsSync(outputDir)) {
50
+ return 0;
51
+ }
52
+
53
+ let count = 0;
54
+
55
+ async function walk(dir) {
56
+ const entries = await fs.readdir(dir, { withFileTypes: true });
57
+ for (const entry of entries) {
58
+ if (entry.name === '.backups' || entry.name === '.logs') continue;
59
+ const full = path.join(dir, entry.name);
60
+ if (entry.isDirectory()) {
61
+ await walk(full);
62
+ } else if (entry.isFile()) {
63
+ count++;
64
+ }
65
+ }
66
+ }
67
+
68
+ await walk(outputDir);
69
+ return count;
70
+ }
71
+
72
+ /**
73
+ * Find the project root by walking up from cwd looking for _bmad/ directory.
74
+ * @returns {string|null} Absolute path to project root, or null if not found
75
+ */
76
+ function findProjectRoot() {
77
+ let dir = process.cwd();
78
+ const root = path.parse(dir).root;
79
+
80
+ while (true) {
81
+ if (fs.existsSync(path.join(dir, '_bmad'))) {
82
+ return dir;
83
+ }
84
+ if (dir === root) break;
85
+ dir = path.dirname(dir);
86
+ }
87
+
88
+ return null;
89
+ }
90
+
91
+ module.exports = {
92
+ getPackageVersion,
93
+ compareVersions,
94
+ countUserDataFiles,
95
+ findProjectRoot
96
+ };