bmad-method-quarkus 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/.claude-plugin/marketplace.json +53 -0
  2. package/AGENTS.md +12 -0
  3. package/LICENSE +30 -0
  4. package/README.md +94 -0
  5. package/README_CN.md +108 -0
  6. package/README_VN.md +109 -0
  7. package/bmad-modules.yaml +133 -0
  8. package/package.json +123 -0
  9. package/removals.txt +87 -0
  10. package/src/bmm-skills/agents/bmad-agent-analyst/SKILL.md +76 -0
  11. package/src/bmm-skills/agents/bmad-agent-analyst/customize.toml +105 -0
  12. package/src/bmm-skills/agents/bmad-agent-architect/SKILL.md +76 -0
  13. package/src/bmm-skills/agents/bmad-agent-architect/customize.toml +65 -0
  14. package/src/bmm-skills/agents/bmad-agent-dev/SKILL.md +76 -0
  15. package/src/bmm-skills/agents/bmad-agent-dev/customize.toml +83 -0
  16. package/src/bmm-skills/agents/bmad-agent-pm/SKILL.md +76 -0
  17. package/src/bmm-skills/agents/bmad-agent-pm/customize.toml +75 -0
  18. package/src/bmm-skills/agents/bmad-agent-ux-designer/SKILL.md +76 -0
  19. package/src/bmm-skills/agents/bmad-agent-ux-designer/customize.toml +60 -0
  20. package/src/bmm-skills/agents/bmad-quarkus-architect/.memlog.md +12 -0
  21. package/src/bmm-skills/agents/bmad-quarkus-architect/.memlog.md:Zone.Identifier +0 -0
  22. package/src/bmm-skills/agents/bmad-quarkus-architect/SKILL.md +86 -0
  23. package/src/bmm-skills/agents/bmad-quarkus-architect/SKILL.md:Zone.Identifier +0 -0
  24. package/src/bmm-skills/agents/bmad-quarkus-architect/customize.toml +37 -0
  25. package/src/bmm-skills/agents/bmad-quarkus-architect/customize.toml:Zone.Identifier +0 -0
  26. package/src/bmm-skills/agents/bmad-quarkus-architect/references/enrich-stories.md +19 -0
  27. package/src/bmm-skills/agents/bmad-quarkus-architect/references/enrich-stories.md:Zone.Identifier +0 -0
  28. package/src/bmm-skills/agents/bmad-quarkus-architect/references/prompt-quality-canon.md +79 -0
  29. package/src/bmm-skills/agents/bmad-quarkus-architect/references/prompt-quality-canon.md:Zone.Identifier +0 -0
  30. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/bqa-setup/SKILL.md +80 -0
  31. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/bqa-setup/SKILL.md:Zone.Identifier +0 -0
  32. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/bqa-setup/assets/module-help.csv +9 -0
  33. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/bqa-setup/assets/module-help.csv:Zone.Identifier +0 -0
  34. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/bqa-setup/assets/module.yaml +16 -0
  35. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/bqa-setup/assets/module.yaml:Zone.Identifier +0 -0
  36. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/bqa-setup/scripts/cleanup-legacy.py +287 -0
  37. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/bqa-setup/scripts/cleanup-legacy.py:Zone.Identifier +0 -0
  38. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/bqa-setup/scripts/merge-config.py +441 -0
  39. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/bqa-setup/scripts/merge-config.py:Zone.Identifier +0 -0
  40. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/bqa-setup/scripts/merge-help-csv.py +246 -0
  41. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/bqa-setup/scripts/merge-help-csv.py:Zone.Identifier +0 -0
  42. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-error-handling-i18n/SKILL.md +181 -0
  43. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-error-handling-i18n/SKILL.md:Zone.Identifier +0 -0
  44. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-grpc-services/SKILL.md +141 -0
  45. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-grpc-services/SKILL.md:Zone.Identifier +0 -0
  46. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-hexagonal-core/SKILL.md +392 -0
  47. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-hexagonal-core/SKILL.md:Zone.Identifier +0 -0
  48. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-kafka-messaging/SKILL.md +148 -0
  49. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-kafka-messaging/SKILL.md:Zone.Identifier +0 -0
  50. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-observability-otel/SKILL.md +180 -0
  51. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-observability-otel/SKILL.md:Zone.Identifier +0 -0
  52. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-openapi-tmforum/SKILL.md +128 -0
  53. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-openapi-tmforum/SKILL.md:Zone.Identifier +0 -0
  54. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-sql-jdbc-agroal/SKILL.md +245 -0
  55. package/src/bmm-skills/agents/bmad-quarkus-architect/skills/quarkus-sql-jdbc-agroal/SKILL.md:Zone.Identifier +0 -0
  56. package/src/bmm-skills/module-help.csv +19 -0
  57. package/src/bmm-skills/module.yaml +92 -0
  58. package/src/bmm-skills/plan/bmad-architecture/SKILL.md +85 -0
  59. package/src/bmm-skills/plan/bmad-architecture/assets/spine-template.md +79 -0
  60. package/src/bmm-skills/plan/bmad-architecture/customize.toml +102 -0
  61. package/src/bmm-skills/plan/bmad-architecture/references/headless.md +26 -0
  62. package/src/bmm-skills/plan/bmad-architecture/references/reviewer-gate.md +13 -0
  63. package/src/bmm-skills/plan/bmad-architecture/scripts/lint_spine.py +257 -0
  64. package/src/bmm-skills/plan/bmad-architecture/scripts/tests/test_lint_spine.py +270 -0
  65. package/src/bmm-skills/plan/bmad-create-epics-and-stories/SKILL.md +93 -0
  66. package/src/bmm-skills/plan/bmad-create-epics-and-stories/customize.toml +41 -0
  67. package/src/bmm-skills/plan/bmad-create-epics-and-stories/steps/step-01-validate-prerequisites.md +263 -0
  68. package/src/bmm-skills/plan/bmad-create-epics-and-stories/steps/step-02-design-epics.md +242 -0
  69. package/src/bmm-skills/plan/bmad-create-epics-and-stories/steps/step-03-create-stories.md +255 -0
  70. package/src/bmm-skills/plan/bmad-create-epics-and-stories/steps/step-04-final-validation.md +143 -0
  71. package/src/bmm-skills/plan/bmad-create-epics-and-stories/templates/epics-template.md +61 -0
  72. package/src/bmm-skills/plan/bmad-generate-project-context/SKILL.md +10 -0
  73. package/src/bmm-skills/plan/bmad-prd/SKILL.md +94 -0
  74. package/src/bmm-skills/plan/bmad-prd/assets/headless-schemas.md +76 -0
  75. package/src/bmm-skills/plan/bmad-prd/assets/prd-template.md +165 -0
  76. package/src/bmm-skills/plan/bmad-prd/assets/prd-validation-checklist.md +135 -0
  77. package/src/bmm-skills/plan/bmad-prd/assets/validation-report-template.html +325 -0
  78. package/src/bmm-skills/plan/bmad-prd/customize.toml +149 -0
  79. package/src/bmm-skills/plan/bmad-prd/references/headless.md +39 -0
  80. package/src/bmm-skills/plan/bmad-prd/references/validate.md +97 -0
  81. package/src/bmm-skills/plan/bmad-prfaq/SKILL.md +135 -0
  82. package/src/bmm-skills/plan/bmad-prfaq/agents/artifact-analyzer.md +60 -0
  83. package/src/bmm-skills/plan/bmad-prfaq/agents/web-researcher.md +49 -0
  84. package/src/bmm-skills/plan/bmad-prfaq/assets/prfaq-template.md +62 -0
  85. package/src/bmm-skills/plan/bmad-prfaq/bmad-manifest.json +16 -0
  86. package/src/bmm-skills/plan/bmad-prfaq/customize.toml +41 -0
  87. package/src/bmm-skills/plan/bmad-prfaq/references/customer-faq.md +55 -0
  88. package/src/bmm-skills/plan/bmad-prfaq/references/internal-faq.md +51 -0
  89. package/src/bmm-skills/plan/bmad-prfaq/references/press-release.md +60 -0
  90. package/src/bmm-skills/plan/bmad-prfaq/references/verdict.md +83 -0
  91. package/src/bmm-skills/plan/bmad-product-brief/SKILL.md +91 -0
  92. package/src/bmm-skills/plan/bmad-product-brief/assets/brief-template.md +41 -0
  93. package/src/bmm-skills/plan/bmad-product-brief/customize.toml +101 -0
  94. package/src/bmm-skills/plan/bmad-project-context/SKILL.md +110 -0
  95. package/src/bmm-skills/plan/bmad-project-context/customize.toml +24 -0
  96. package/src/bmm-skills/plan/bmad-project-context/references/best-practices.md +65 -0
  97. package/src/bmm-skills/plan/bmad-project-context/references/template.md +55 -0
  98. package/src/bmm-skills/plan/bmad-spec/SKILL.md +160 -0
  99. package/src/bmm-skills/plan/bmad-spec/assets/headless-schemas.md +33 -0
  100. package/src/bmm-skills/plan/bmad-spec/assets/spec-template.md +49 -0
  101. package/src/bmm-skills/plan/bmad-spec/assets/stories-schema.md +44 -0
  102. package/src/bmm-skills/plan/bmad-spec/customize.toml +52 -0
  103. package/src/bmm-skills/plan/bmad-sprint-planning/SKILL.md +62 -0
  104. package/src/bmm-skills/plan/bmad-sprint-planning/customize.toml +41 -0
  105. package/src/bmm-skills/plan/bmad-sprint-planning/references/fix-sprint-status.md +30 -0
  106. package/src/bmm-skills/plan/bmad-sprint-planning/references/generate-tracking.md +25 -0
  107. package/src/bmm-skills/plan/bmad-sprint-planning/references/readiness-gate.md +20 -0
  108. package/src/bmm-skills/plan/bmad-sprint-planning/references/status-view.md +14 -0
  109. package/src/bmm-skills/plan/bmad-sprint-planning/references/validate.md +10 -0
  110. package/src/bmm-skills/plan/bmad-sprint-planning/scripts/__pycache__/sprint_plan.cpython-311.pyc +0 -0
  111. package/src/bmm-skills/plan/bmad-sprint-planning/scripts/sprint_plan.py +697 -0
  112. package/src/bmm-skills/plan/bmad-sprint-planning/scripts/tests/__pycache__/test_sprint_plan.cpython-311-pytest-9.1.1.pyc +0 -0
  113. package/src/bmm-skills/plan/bmad-sprint-planning/scripts/tests/test_sprint_plan.py +524 -0
  114. package/src/bmm-skills/plan/bmad-sprint-planning/sprint-status-template.yaml +71 -0
  115. package/src/bmm-skills/plan/bmad-ux/SKILL.md +90 -0
  116. package/src/bmm-skills/plan/bmad-ux/assets/color-themes.md +9 -0
  117. package/src/bmm-skills/plan/bmad-ux/assets/design-directions.md +9 -0
  118. package/src/bmm-skills/plan/bmad-ux/assets/design-example-editorial.md +158 -0
  119. package/src/bmm-skills/plan/bmad-ux/assets/design-example-mobile.md +93 -0
  120. package/src/bmm-skills/plan/bmad-ux/assets/design-example-shadcn.md +109 -0
  121. package/src/bmm-skills/plan/bmad-ux/assets/excalidraw-wireframe.md +19 -0
  122. package/src/bmm-skills/plan/bmad-ux/assets/experience-example-mobile.md +112 -0
  123. package/src/bmm-skills/plan/bmad-ux/assets/experience-example-shadcn.md +133 -0
  124. package/src/bmm-skills/plan/bmad-ux/assets/headless-schemas.md +84 -0
  125. package/src/bmm-skills/plan/bmad-ux/assets/key-screens.md +29 -0
  126. package/src/bmm-skills/plan/bmad-ux/assets/validation-report-template.html +319 -0
  127. package/src/bmm-skills/plan/bmad-ux/customize.toml +102 -0
  128. package/src/bmm-skills/plan/bmad-ux/references/creative-tools.md +19 -0
  129. package/src/bmm-skills/plan/bmad-ux/references/design-md-spec.md +50 -0
  130. package/src/bmm-skills/plan/bmad-ux/references/headless.md +37 -0
  131. package/src/bmm-skills/plan/bmad-ux/references/validate.md +115 -0
  132. package/src/bmm-skills/ship/bmad-build/SKILL.md +13 -0
  133. package/src/bmm-skills/ship/bmad-build/compile-epic-context.md +62 -0
  134. package/src/bmm-skills/ship/bmad-build/customize.toml +164 -0
  135. package/src/bmm-skills/ship/bmad-build/references/deletion-check.md +14 -0
  136. package/src/bmm-skills/ship/bmad-build/review-prompts/edge-case-hunter.md +88 -0
  137. package/src/bmm-skills/ship/bmad-build/review-prompts/verification-gap.md +113 -0
  138. package/src/bmm-skills/ship/bmad-build/spec-template.md +89 -0
  139. package/src/bmm-skills/ship/bmad-build/step-01-clarify-and-route.md +105 -0
  140. package/src/bmm-skills/ship/bmad-build/step-02-plan.md +47 -0
  141. package/src/bmm-skills/ship/bmad-build/step-03-implement.md +49 -0
  142. package/src/bmm-skills/ship/bmad-build/step-04-review.md +55 -0
  143. package/src/bmm-skills/ship/bmad-build/step-05-present.md +75 -0
  144. package/src/bmm-skills/ship/bmad-build/step-oneshot.md +77 -0
  145. package/src/bmm-skills/ship/bmad-build/sync-sprint-status.md +19 -0
  146. package/src/bmm-skills/ship/bmad-build/workflow.md +84 -0
  147. package/src/bmm-skills/ship/bmad-build-auto/SKILL.md +13 -0
  148. package/src/bmm-skills/ship/bmad-build-auto/compile-epic-context.md +62 -0
  149. package/src/bmm-skills/ship/bmad-build-auto/customize.toml +121 -0
  150. package/src/bmm-skills/ship/bmad-build-auto/references/deletion-check.md +14 -0
  151. package/src/bmm-skills/ship/bmad-build-auto/review-prompts/edge-case-hunter.md +88 -0
  152. package/src/bmm-skills/ship/bmad-build-auto/review-prompts/verification-gap.md +113 -0
  153. package/src/bmm-skills/ship/bmad-build-auto/spec-template.md +99 -0
  154. package/src/bmm-skills/ship/bmad-build-auto/step-01-clarify-and-route.md +83 -0
  155. package/src/bmm-skills/ship/bmad-build-auto/step-02-plan.md +27 -0
  156. package/src/bmm-skills/ship/bmad-build-auto/step-03-implement.md +44 -0
  157. package/src/bmm-skills/ship/bmad-build-auto/step-04-review.md +96 -0
  158. package/src/bmm-skills/ship/bmad-build-auto/workflow.md +104 -0
  159. package/src/bmm-skills/ship/bmad-checkpoint-preview/SKILL.md +68 -0
  160. package/src/bmm-skills/ship/bmad-checkpoint-preview/customize.toml +41 -0
  161. package/src/bmm-skills/ship/bmad-checkpoint-preview/generate-trail.md +38 -0
  162. package/src/bmm-skills/ship/bmad-checkpoint-preview/step-01-orientation.md +105 -0
  163. package/src/bmm-skills/ship/bmad-checkpoint-preview/step-02-walkthrough.md +89 -0
  164. package/src/bmm-skills/ship/bmad-checkpoint-preview/step-03-detail-pass.md +106 -0
  165. package/src/bmm-skills/ship/bmad-checkpoint-preview/step-04-testing.md +74 -0
  166. package/src/bmm-skills/ship/bmad-checkpoint-preview/step-05-wrapup.md +30 -0
  167. package/src/bmm-skills/ship/bmad-code-review/SKILL.md +90 -0
  168. package/src/bmm-skills/ship/bmad-code-review/customize.toml +113 -0
  169. package/src/bmm-skills/ship/bmad-code-review/references/deletion-check.md +14 -0
  170. package/src/bmm-skills/ship/bmad-code-review/review-prompts/edge-case-hunter.md +88 -0
  171. package/src/bmm-skills/ship/bmad-code-review/review-prompts/verification-gap.md +113 -0
  172. package/src/bmm-skills/ship/bmad-code-review/steps/step-01-gather-context.md +87 -0
  173. package/src/bmm-skills/ship/bmad-code-review/steps/step-02-review.md +32 -0
  174. package/src/bmm-skills/ship/bmad-code-review/steps/step-03-triage.md +50 -0
  175. package/src/bmm-skills/ship/bmad-code-review/steps/step-04-present.md +132 -0
  176. package/src/bmm-skills/ship/bmad-correct-course/SKILL.md +300 -0
  177. package/src/bmm-skills/ship/bmad-correct-course/checklist.md +288 -0
  178. package/src/bmm-skills/ship/bmad-correct-course/customize.toml +41 -0
  179. package/src/bmm-skills/ship/bmad-qa-generate-e2e-tests/SKILL.md +176 -0
  180. package/src/bmm-skills/ship/bmad-qa-generate-e2e-tests/checklist.md +33 -0
  181. package/src/bmm-skills/ship/bmad-qa-generate-e2e-tests/customize.toml +41 -0
  182. package/src/bmm-skills/ship/bmad-retrospective/SKILL.md +94 -0
  183. package/src/bmm-skills/ship/bmad-retrospective/customize.toml +41 -0
  184. package/src/bmm-skills/ship/bmad-retrospective/references/acceptance-verdict.md +55 -0
  185. package/src/bmm-skills/ship/bmad-retrospective/references/aggregate-views.md +17 -0
  186. package/src/bmm-skills/ship/bmad-retrospective/references/evidence-gathering.md +30 -0
  187. package/src/bmm-skills/ship/bmad-retrospective/references/retro-document.md +84 -0
  188. package/src/bmm-skills/ship/bmad-retrospective/references/team-discussion.md +22 -0
  189. package/src/bmm-skills/ship/bmad-retrospective/scripts/__pycache__/sprint_status.cpython-311.pyc +0 -0
  190. package/src/bmm-skills/ship/bmad-retrospective/scripts/git_evidence.py +304 -0
  191. package/src/bmm-skills/ship/bmad-retrospective/scripts/sprint_status.py +746 -0
  192. package/src/bmm-skills/ship/bmad-retrospective/scripts/tests/__pycache__/test_git_evidence.cpython-311-pytest-9.1.1.pyc +0 -0
  193. package/src/bmm-skills/ship/bmad-retrospective/scripts/tests/__pycache__/test_sprint_status.cpython-311-pytest-9.1.1.pyc +0 -0
  194. package/src/bmm-skills/ship/bmad-retrospective/scripts/tests/fixtures/sprint-status-template.yaml +71 -0
  195. package/src/bmm-skills/ship/bmad-retrospective/scripts/tests/test_git_evidence.py +750 -0
  196. package/src/bmm-skills/ship/bmad-retrospective/scripts/tests/test_sprint_status.py +1579 -0
  197. package/src/bmm-skills/v6-shims/README.md +28 -0
  198. package/src/bmm-skills/v6-shims/bmad-create-architecture/SKILL.md +30 -0
  199. package/src/bmm-skills/v6-shims/bmad-create-architecture/customize.toml +41 -0
  200. package/src/bmm-skills/v6-shims/bmad-create-prd/SKILL.md +30 -0
  201. package/src/bmm-skills/v6-shims/bmad-create-prd/customize.toml +41 -0
  202. package/src/bmm-skills/v6-shims/bmad-create-story/SKILL.md +434 -0
  203. package/src/bmm-skills/v6-shims/bmad-create-story/checklist.md +357 -0
  204. package/src/bmm-skills/v6-shims/bmad-create-story/customize.toml +41 -0
  205. package/src/bmm-skills/v6-shims/bmad-create-story/discover-inputs.md +88 -0
  206. package/src/bmm-skills/v6-shims/bmad-create-story/template.md +49 -0
  207. package/src/bmm-skills/v6-shims/bmad-dev-auto/SKILL.md +19 -0
  208. package/src/bmm-skills/v6-shims/bmad-dev-story/SKILL.md +502 -0
  209. package/src/bmm-skills/v6-shims/bmad-dev-story/checklist.md +80 -0
  210. package/src/bmm-skills/v6-shims/bmad-dev-story/customize.toml +44 -0
  211. package/src/bmm-skills/v6-shims/bmad-document-project/SKILL.md +14 -0
  212. package/src/bmm-skills/v6-shims/bmad-domain-research/SKILL.md +14 -0
  213. package/src/bmm-skills/v6-shims/bmad-edit-prd/SKILL.md +30 -0
  214. package/src/bmm-skills/v6-shims/bmad-edit-prd/customize.toml +42 -0
  215. package/src/bmm-skills/v6-shims/bmad-market-research/SKILL.md +14 -0
  216. package/src/bmm-skills/v6-shims/bmad-quick-dev/SKILL.md +19 -0
  217. package/src/bmm-skills/v6-shims/bmad-sprint-status/SKILL.md +26 -0
  218. package/src/bmm-skills/v6-shims/bmad-sprint-status/customize.toml +41 -0
  219. package/src/bmm-skills/v6-shims/bmad-technical-research/SKILL.md +14 -0
  220. package/src/bmm-skills/v6-shims/bmad-validate-prd/SKILL.md +30 -0
  221. package/src/bmm-skills/v6-shims/bmad-validate-prd/customize.toml +42 -0
  222. package/src/core-skills/bmad-advanced-elicitation/SKILL.md +65 -0
  223. package/src/core-skills/bmad-advanced-elicitation/assets/methods.csv +72 -0
  224. package/src/core-skills/bmad-advanced-elicitation/customize.toml +54 -0
  225. package/src/core-skills/bmad-advanced-elicitation/scripts/pick_methods.py +233 -0
  226. package/src/core-skills/bmad-advanced-elicitation/scripts/tests/test_pick_methods.py +228 -0
  227. package/src/core-skills/bmad-brainstorming/SKILL.md +80 -0
  228. package/src/core-skills/bmad-brainstorming/assets/brain-icons.json +166 -0
  229. package/src/core-skills/bmad-brainstorming/assets/brain-methods.csv +109 -0
  230. package/src/core-skills/bmad-brainstorming/assets/brain-selector.html +328 -0
  231. package/src/core-skills/bmad-brainstorming/customize.toml +84 -0
  232. package/src/core-skills/bmad-brainstorming/references/converge.md +24 -0
  233. package/src/core-skills/bmad-brainstorming/references/finalize.md +26 -0
  234. package/src/core-skills/bmad-brainstorming/references/headless.md +54 -0
  235. package/src/core-skills/bmad-brainstorming/references/in-chat-techniques.md +18 -0
  236. package/src/core-skills/bmad-brainstorming/references/mode-autonomous.md +10 -0
  237. package/src/core-skills/bmad-brainstorming/references/mode-facilitator.md +11 -0
  238. package/src/core-skills/bmad-brainstorming/references/mode-partner.md +16 -0
  239. package/src/core-skills/bmad-brainstorming/references/resume.md +5 -0
  240. package/src/core-skills/bmad-brainstorming/scripts/brain.py +770 -0
  241. package/src/core-skills/bmad-brainstorming/scripts/tests/test_brain.py +239 -0
  242. package/src/core-skills/bmad-customize/SKILL.md +111 -0
  243. package/src/core-skills/bmad-customize/scripts/list_customizable_skills.py +231 -0
  244. package/src/core-skills/bmad-customize/scripts/tests/test_list_customizable_skills.py +249 -0
  245. package/src/core-skills/bmad-deep-recon/SKILL.md +82 -0
  246. package/src/core-skills/bmad-deep-recon/assets/research.template.md +18 -0
  247. package/src/core-skills/bmad-deep-recon/customize.toml +212 -0
  248. package/src/core-skills/bmad-deep-recon/references/draft.md +8 -0
  249. package/src/core-skills/bmad-deep-recon/references/finalize.md +11 -0
  250. package/src/core-skills/bmad-deep-recon/references/html-briefing.md +16 -0
  251. package/src/core-skills/bmad-deep-recon/references/lifecycle.md +11 -0
  252. package/src/core-skills/bmad-deep-recon/references/process.md +10 -0
  253. package/src/core-skills/bmad-deep-recon/references/run.md +73 -0
  254. package/src/core-skills/bmad-deep-recon/references/selection.md +13 -0
  255. package/src/core-skills/bmad-deep-recon/references/synthesis.md +16 -0
  256. package/src/core-skills/bmad-deep-recon/references/verification.md +29 -0
  257. package/src/core-skills/bmad-deep-recon/scripts/recon_kit.py +322 -0
  258. package/src/core-skills/bmad-deep-recon/scripts/tests/test_recon_kit.py +144 -0
  259. package/src/core-skills/bmad-deep-recon/types/academic-lit.md +19 -0
  260. package/src/core-skills/bmad-deep-recon/types/competitive.md +19 -0
  261. package/src/core-skills/bmad-deep-recon/types/domain.md +19 -0
  262. package/src/core-skills/bmad-deep-recon/types/market.md +19 -0
  263. package/src/core-skills/bmad-deep-recon/types/technical.md +19 -0
  264. package/src/core-skills/bmad-deep-recon/types/user-voice.md +19 -0
  265. package/src/core-skills/bmad-forge-idea/SKILL.md +107 -0
  266. package/src/core-skills/bmad-forge-idea/customize.toml +42 -0
  267. package/src/core-skills/bmad-forge-idea/scripts/resolve_personas.py +275 -0
  268. package/src/core-skills/bmad-forge-idea/scripts/tests/test_resolve_personas.py +138 -0
  269. package/src/core-skills/bmad-help/SKILL.md +75 -0
  270. package/src/core-skills/bmad-party-mode/SKILL.md +60 -0
  271. package/src/core-skills/bmad-party-mode/customize.toml +211 -0
  272. package/src/core-skills/bmad-party-mode/references/create-party.md +70 -0
  273. package/src/core-skills/bmad-party-mode/references/mode-agent-team.md +13 -0
  274. package/src/core-skills/bmad-party-mode/references/mode-auto.md +13 -0
  275. package/src/core-skills/bmad-party-mode/references/mode-subagent.md +31 -0
  276. package/src/core-skills/bmad-party-mode/references/party-memory.md +51 -0
  277. package/src/core-skills/bmad-party-mode/scripts/resolve_party.py +282 -0
  278. package/src/core-skills/bmad-party-mode/scripts/tests/test_resolve_party.py +146 -0
  279. package/src/core-skills/bmad-review/SKILL.md +49 -0
  280. package/src/core-skills/bmad-review/customize.toml +141 -0
  281. package/src/core-skills/bmad-review/references/editorial-common.md +56 -0
  282. package/src/core-skills/bmad-review/references/lens-adversarial.md +19 -0
  283. package/src/core-skills/bmad-review/references/lens-edge-case-hunter.md +54 -0
  284. package/src/core-skills/bmad-review/references/lens-prose.md +7 -0
  285. package/src/core-skills/bmad-review/references/lens-structure.md +9 -0
  286. package/src/core-skills/bmad-review/references/lens-verification-gap.md +92 -0
  287. package/src/core-skills/bmad-review/references/structure-models.md +44 -0
  288. package/src/core-skills/bmad-review/scripts/tests/test_word_metrics.py +62 -0
  289. package/src/core-skills/bmad-review/scripts/word_metrics.py +102 -0
  290. package/src/core-skills/module-help.csv +10 -0
  291. package/src/core-skills/module.yaml +38 -0
  292. package/src/core-skills/v6-shims/README.md +25 -0
  293. package/src/core-skills/v6-shims/bmad-editorial-review/SKILL.md +6 -0
  294. package/src/core-skills/v6-shims/bmad-editorial-review/customize.toml +31 -0
  295. package/src/core-skills/v6-shims/bmad-editorial-review-prose/SKILL.md +6 -0
  296. package/src/core-skills/v6-shims/bmad-editorial-review-structure/SKILL.md +6 -0
  297. package/src/core-skills/v6-shims/bmad-review-adversarial-general/SKILL.md +6 -0
  298. package/src/core-skills/v6-shims/bmad-review-edge-case-hunter/SKILL.md +6 -0
  299. package/src/core-skills/v6-shims/bmad-review-verification-gap/SKILL.md +6 -0
  300. package/src/scripts/__pycache__/config_utils.cpython-311.pyc +0 -0
  301. package/src/scripts/config_utils.py +119 -0
  302. package/src/scripts/memlog.py +224 -0
  303. package/src/scripts/render_skill.py +401 -0
  304. package/src/scripts/resolve_config.py +74 -0
  305. package/src/scripts/resolve_customization.py +99 -0
  306. package/src/scripts/tests/__pycache__/test_config_utils.cpython-311.pyc +0 -0
  307. package/src/scripts/tests/__pycache__/test_resolve_config.cpython-311.pyc +0 -0
  308. package/src/scripts/tests/__pycache__/test_resolve_customization.cpython-311.pyc +0 -0
  309. package/src/scripts/tests/test_config_utils.py +85 -0
  310. package/src/scripts/tests/test_memlog.py +306 -0
  311. package/src/scripts/tests/test_resolve_config.py +89 -0
  312. package/src/scripts/tests/test_resolve_customization.py +77 -0
  313. package/tools/bundle-web-bundles.js +117 -0
  314. package/tools/format-workflow-md.js +263 -0
  315. package/tools/installer/README.md +60 -0
  316. package/tools/installer/bmad-cli.js +105 -0
  317. package/tools/installer/cli-utils.js +57 -0
  318. package/tools/installer/commands/install.js +149 -0
  319. package/tools/installer/commands/status.js +65 -0
  320. package/tools/installer/commands/uninstall.js +167 -0
  321. package/tools/installer/core/config.js +73 -0
  322. package/tools/installer/core/existing-install.js +121 -0
  323. package/tools/installer/core/install-paths.js +132 -0
  324. package/tools/installer/core/installer.js +1767 -0
  325. package/tools/installer/core/legacy-warnings.js +151 -0
  326. package/tools/installer/core/manifest-generator.js +859 -0
  327. package/tools/installer/core/manifest.js +433 -0
  328. package/tools/installer/core/uv-check.js +195 -0
  329. package/tools/installer/core/wsl-node-check.js +109 -0
  330. package/tools/installer/file-ops.js +204 -0
  331. package/tools/installer/fs-native.js +116 -0
  332. package/tools/installer/ide/_config-driven.js +972 -0
  333. package/tools/installer/ide/manager.js +324 -0
  334. package/tools/installer/ide/platform-codes.js +80 -0
  335. package/tools/installer/ide/platform-codes.yaml +343 -0
  336. package/tools/installer/ide/shared/installed-skills.js +50 -0
  337. package/tools/installer/ide/shared/path-utils.js +219 -0
  338. package/tools/installer/ide/shared/skill-manifest.js +57 -0
  339. package/tools/installer/install-messages.yaml +37 -0
  340. package/tools/installer/list-options.js +210 -0
  341. package/tools/installer/message-loader.js +83 -0
  342. package/tools/installer/modules/channel-plan.js +203 -0
  343. package/tools/installer/modules/channel-resolver.js +241 -0
  344. package/tools/installer/modules/custom-module-manager.js +924 -0
  345. package/tools/installer/modules/external-manager.js +671 -0
  346. package/tools/installer/modules/git-env.js +47 -0
  347. package/tools/installer/modules/module-help-schema.js +13 -0
  348. package/tools/installer/modules/official-modules.js +2257 -0
  349. package/tools/installer/modules/plugin-resolver.js +398 -0
  350. package/tools/installer/modules/version-resolver.js +336 -0
  351. package/tools/installer/project-root.js +224 -0
  352. package/tools/installer/prompts.js +791 -0
  353. package/tools/installer/set-overrides.js +330 -0
  354. package/tools/installer/ui.js +2167 -0
  355. package/tools/installer/yaml-format.js +245 -0
  356. package/tools/javascript-conventions.md +5 -0
  357. package/tools/migrate-custom-module-paths.js +124 -0
  358. package/tools/skill-validator.md +378 -0
  359. package/tools/validate-published-implementation-model.mjs +68 -0
  360. package/tools/validate-sidebar-order.js +388 -0
  361. package/tools/validate-skills.js +735 -0
  362. package/tools/validate-svg-changes.sh +356 -0
  363. package/web-bundles/README.md +46 -0
  364. package/web-bundles/brainstorming-coach/INSTRUCTIONS.md +86 -0
  365. package/web-bundles/brainstorming-coach/SKILL.md +83 -0
  366. package/web-bundles/brainstorming-coach/brain-methods.csv +62 -0
  367. package/web-bundles/bundles.json +139 -0
  368. package/web-bundles/market-and-industry-research/INSTRUCTIONS.md +88 -0
  369. package/web-bundles/market-and-industry-research/SKILL.md +59 -0
  370. package/web-bundles/prd-coach/INSTRUCTIONS.md +86 -0
  371. package/web-bundles/prd-coach/SKILL.md +101 -0
  372. package/web-bundles/prd-coach/prd-template.md +165 -0
  373. package/web-bundles/prd-coach/prd-validation-checklist.md +135 -0
  374. package/web-bundles/prfaq-coach/INSTRUCTIONS.md +86 -0
  375. package/web-bundles/prfaq-coach/SKILL.md +139 -0
  376. package/web-bundles/product-brief-coach/INSTRUCTIONS.md +86 -0
  377. package/web-bundles/product-brief-coach/SKILL.md +113 -0
  378. package/web-bundles/ux-coach/INSTRUCTIONS.md +92 -0
  379. package/web-bundles/ux-coach/SKILL.md +187 -0
  380. package/web-bundles/ux-coach/ux-validation.md +100 -0
@@ -0,0 +1,433 @@
1
+ const path = require('node:path');
2
+ const https = require('node:https');
3
+ const { execFile } = require('node:child_process');
4
+ const { promisify } = require('node:util');
5
+ const fs = require('../fs-native');
6
+ const crypto = require('node:crypto');
7
+ const { resolveModuleVersion } = require('../modules/version-resolver');
8
+ const prompts = require('../prompts');
9
+
10
+ const execFileAsync = promisify(execFile);
11
+ const NPM_LOOKUP_TIMEOUT_MS = 10_000;
12
+ const NPM_PACKAGE_NAME_PATTERN = /^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/;
13
+
14
+ function isValidNpmPackageName(packageName) {
15
+ return typeof packageName === 'string' && NPM_PACKAGE_NAME_PATTERN.test(packageName);
16
+ }
17
+
18
+ class Manifest {
19
+ /**
20
+ * Create a new manifest
21
+ * @param {string} bmadDir - Path to bmad directory
22
+ * @param {Object} data - Manifest data
23
+ * @param {Array} installedFiles - List of installed files (no longer used, files tracked in files-manifest.csv)
24
+ */
25
+ async create(bmadDir, data, installedFiles = []) {
26
+ const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml');
27
+ const yaml = require('yaml');
28
+
29
+ // Ensure _config directory exists
30
+ await fs.ensureDir(path.dirname(manifestPath));
31
+
32
+ // Get the BMad version from package.json
33
+ const bmadVersion = data.version || require(path.join(process.cwd(), 'package.json')).version;
34
+
35
+ // Convert module list to new detailed format
36
+ const moduleDetails = [];
37
+ if (data.modules && Array.isArray(data.modules)) {
38
+ for (const moduleName of data.modules) {
39
+ // Core and BMM modules use the BMad version
40
+ const moduleVersion = moduleName === 'core' || moduleName === 'bmm' ? bmadVersion : null;
41
+ const now = data.installDate || new Date().toISOString();
42
+
43
+ moduleDetails.push({
44
+ name: moduleName,
45
+ version: moduleVersion,
46
+ installDate: now,
47
+ lastUpdated: now,
48
+ source: moduleName === 'core' || moduleName === 'bmm' ? 'built-in' : 'unknown',
49
+ });
50
+ }
51
+ }
52
+
53
+ // Structure the manifest data
54
+ const manifestData = {
55
+ installation: {
56
+ version: bmadVersion,
57
+ installDate: data.installDate || new Date().toISOString(),
58
+ lastUpdated: data.lastUpdated || new Date().toISOString(),
59
+ },
60
+ modules: moduleDetails,
61
+ ides: data.ides || [],
62
+ };
63
+
64
+ // Write YAML manifest
65
+ // Clean the manifest data to remove any non-serializable values
66
+ const cleanManifestData = structuredClone(manifestData);
67
+
68
+ const yamlContent = yaml.stringify(cleanManifestData, {
69
+ indent: 2,
70
+ lineWidth: 0,
71
+ sortKeys: false,
72
+ });
73
+
74
+ // Ensure POSIX-compliant final newline
75
+ const content = yamlContent.endsWith('\n') ? yamlContent : yamlContent + '\n';
76
+ await fs.writeFile(manifestPath, content, 'utf8');
77
+ return { success: true, path: manifestPath, filesTracked: 0 };
78
+ }
79
+
80
+ /**
81
+ * Read existing manifest
82
+ * @param {string} bmadDir - Path to bmad directory
83
+ * @returns {Object|null} Manifest data or null if not found
84
+ */
85
+ async read(bmadDir) {
86
+ const yamlPath = path.join(bmadDir, '_config', 'manifest.yaml');
87
+ const yaml = require('yaml');
88
+
89
+ if (await fs.pathExists(yamlPath)) {
90
+ try {
91
+ const content = await fs.readFile(yamlPath, 'utf8');
92
+ const manifestData = yaml.parse(content);
93
+
94
+ // Handle new detailed module format
95
+ const modules = manifestData.modules || [];
96
+
97
+ // For backward compatibility: if modules is an array of strings (old format),
98
+ // the calling code may need the array of names
99
+ const moduleNames = modules.map((m) => (typeof m === 'string' ? m : m.name));
100
+
101
+ // Check if we have the new detailed format
102
+ const hasDetailedModules = modules.length > 0 && typeof modules[0] === 'object';
103
+
104
+ // Flatten the structure for compatibility with existing code
105
+ return {
106
+ version: manifestData.installation?.version,
107
+ installDate: manifestData.installation?.installDate,
108
+ lastUpdated: manifestData.installation?.lastUpdated,
109
+ modules: moduleNames, // Simple array of module names for backward compatibility
110
+ modulesDetailed: hasDetailedModules ? modules : null, // New detailed format
111
+ ides: manifestData.ides || [],
112
+ };
113
+ } catch (error) {
114
+ await prompts.log.error(`Failed to read YAML manifest: ${error.message}`);
115
+ }
116
+ }
117
+
118
+ return null;
119
+ }
120
+
121
+ /**
122
+ * Read raw manifest data without flattening
123
+ * @param {string} bmadDir - Path to bmad directory
124
+ * @returns {Object|null} Raw manifest data or null if not found
125
+ */
126
+ async _readRaw(bmadDir) {
127
+ const yamlPath = path.join(bmadDir, '_config', 'manifest.yaml');
128
+ const yaml = require('yaml');
129
+
130
+ if (await fs.pathExists(yamlPath)) {
131
+ try {
132
+ const content = await fs.readFile(yamlPath, 'utf8');
133
+ return yaml.parse(content);
134
+ } catch (error) {
135
+ await prompts.log.error(`Failed to read YAML manifest: ${error.message}`);
136
+ }
137
+ }
138
+
139
+ return null;
140
+ }
141
+
142
+ /**
143
+ * Flatten manifest for backward compatibility
144
+ * @param {Object} manifest - Raw manifest data
145
+ * @returns {Object} Flattened manifest
146
+ */
147
+ _flattenManifest(manifest) {
148
+ const modules = manifest.modules || [];
149
+ const moduleNames = modules.map((m) => (typeof m === 'string' ? m : m.name));
150
+ const hasDetailedModules = modules.length > 0 && typeof modules[0] === 'object';
151
+
152
+ return {
153
+ version: manifest.installation?.version,
154
+ installDate: manifest.installation?.installDate,
155
+ lastUpdated: manifest.installation?.lastUpdated,
156
+ modules: moduleNames,
157
+ modulesDetailed: hasDetailedModules ? modules : null,
158
+ ides: manifest.ides || [],
159
+ };
160
+ }
161
+
162
+ /**
163
+ * Add a module to the manifest with optional version info
164
+ * If module already exists, update its version info
165
+ * @param {string} bmadDir - Path to bmad directory
166
+ * @param {string} moduleName - Module name to add
167
+ * @param {Object} options - Optional version info
168
+ */
169
+ async addModule(bmadDir, moduleName, options = {}) {
170
+ let manifest = await this._readRaw(bmadDir);
171
+ if (!manifest) {
172
+ // Bootstrap a minimal manifest if it doesn't exist yet
173
+ // (e.g., skill-only modules with no agents to compile)
174
+ manifest = { modules: [] };
175
+ }
176
+
177
+ if (!manifest.modules) {
178
+ manifest.modules = [];
179
+ }
180
+
181
+ const existingIndex = manifest.modules.findIndex((m) => m.name === moduleName);
182
+
183
+ if (existingIndex === -1) {
184
+ // Module doesn't exist, add it
185
+ const entry = {
186
+ name: moduleName,
187
+ version: options.version || null,
188
+ installDate: new Date().toISOString(),
189
+ lastUpdated: new Date().toISOString(),
190
+ source: options.source || 'unknown',
191
+ npmPackage: options.npmPackage || null,
192
+ repoUrl: options.repoUrl || null,
193
+ };
194
+ if (options.channel) entry.channel = options.channel;
195
+ if (options.sha) entry.sha = options.sha;
196
+ if (options.localPath) entry.localPath = options.localPath;
197
+ if (options.rawSource) entry.rawSource = options.rawSource;
198
+ if (options.registryApprovedTag) entry.registryApprovedTag = options.registryApprovedTag;
199
+ if (options.registryApprovedSha) entry.registryApprovedSha = options.registryApprovedSha;
200
+ manifest.modules.push(entry);
201
+ } else {
202
+ // Module exists, update its version info
203
+ const existing = manifest.modules[existingIndex];
204
+ manifest.modules[existingIndex] = {
205
+ ...existing,
206
+ version: options.version === undefined ? existing.version : options.version,
207
+ source: options.source || existing.source,
208
+ npmPackage: options.npmPackage === undefined ? existing.npmPackage : options.npmPackage,
209
+ repoUrl: options.repoUrl === undefined ? existing.repoUrl : options.repoUrl,
210
+ localPath: options.localPath === undefined ? existing.localPath : options.localPath,
211
+ channel: options.channel === undefined ? existing.channel : options.channel,
212
+ sha: options.sha === undefined ? existing.sha : options.sha,
213
+ rawSource: options.rawSource === undefined ? existing.rawSource : options.rawSource,
214
+ registryApprovedTag: options.registryApprovedTag === undefined ? existing.registryApprovedTag : options.registryApprovedTag,
215
+ registryApprovedSha: options.registryApprovedSha === undefined ? existing.registryApprovedSha : options.registryApprovedSha,
216
+ lastUpdated: new Date().toISOString(),
217
+ };
218
+ }
219
+
220
+ await this._writeRaw(bmadDir, manifest);
221
+ }
222
+
223
+ /**
224
+ * Get all modules with their version info
225
+ * @param {string} bmadDir - Path to bmad directory
226
+ * @returns {Array} Array of module info objects
227
+ */
228
+ async getAllModuleVersions(bmadDir) {
229
+ const manifest = await this._readRaw(bmadDir);
230
+ if (!manifest || !manifest.modules) {
231
+ return [];
232
+ }
233
+
234
+ return manifest.modules;
235
+ }
236
+
237
+ /**
238
+ * Write raw manifest data to file
239
+ * @param {string} bmadDir - Path to bmad directory
240
+ * @param {Object} manifestData - Raw manifest data to write
241
+ */
242
+ async _writeRaw(bmadDir, manifestData) {
243
+ const yaml = require('yaml');
244
+ const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml');
245
+
246
+ await fs.ensureDir(path.dirname(manifestPath));
247
+
248
+ const cleanManifestData = structuredClone(manifestData);
249
+
250
+ const yamlContent = yaml.stringify(cleanManifestData, {
251
+ indent: 2,
252
+ lineWidth: 0,
253
+ sortKeys: false,
254
+ });
255
+
256
+ const content = yamlContent.endsWith('\n') ? yamlContent : yamlContent + '\n';
257
+ await fs.writeFile(manifestPath, content, 'utf8');
258
+ }
259
+
260
+ /**
261
+ * Calculate SHA256 hash of a file
262
+ * @param {string} filePath - Path to file
263
+ * @returns {string} SHA256 hash
264
+ */
265
+ async calculateFileHash(filePath) {
266
+ try {
267
+ const content = await fs.readFile(filePath);
268
+ return crypto.createHash('sha256').update(content).digest('hex');
269
+ } catch {
270
+ return null;
271
+ }
272
+ }
273
+
274
+ /**
275
+ * Get module version info from source
276
+ * @param {string} moduleName - Module name/code
277
+ * @param {string} bmadDir - Path to bmad directory
278
+ * @param {string} moduleSourcePath - Optional source path for custom modules
279
+ * @returns {Object} Version info object with version, source, npmPackage, repoUrl
280
+ */
281
+ async getModuleVersionInfo(moduleName, bmadDir, moduleSourcePath = null) {
282
+ // Resolve source type first, then read version with the correct path context
283
+ if (['core', 'bmm'].includes(moduleName)) {
284
+ const versionInfo = await resolveModuleVersion(moduleName, { moduleSourcePath });
285
+ return {
286
+ version: versionInfo.version,
287
+ source: 'built-in',
288
+ npmPackage: null,
289
+ repoUrl: null,
290
+ };
291
+ }
292
+
293
+ // Check if this is an external official module
294
+ const { ExternalModuleManager } = require('../modules/external-manager');
295
+ const extMgr = new ExternalModuleManager();
296
+ const moduleInfo = await extMgr.getModuleByCode(moduleName);
297
+
298
+ if (moduleInfo) {
299
+ const externalResolution = extMgr.getResolution(moduleName);
300
+ const versionInfo = await resolveModuleVersion(moduleName, { moduleSourcePath });
301
+ return {
302
+ // Git tag recorded during install trumps the on-disk package.json
303
+ // version, so the manifest carries "v1.7.0" instead of "1.7.0".
304
+ version: externalResolution?.version || versionInfo.version,
305
+ source: 'external',
306
+ npmPackage: moduleInfo.npmPackage || null,
307
+ repoUrl: moduleInfo.url || null,
308
+ channel: externalResolution?.channel || null,
309
+ sha: externalResolution?.sha || null,
310
+ };
311
+ }
312
+
313
+ // Check if this is a custom module (from user-provided URL or local path)
314
+ const { CustomModuleManager } = require('../modules/custom-module-manager');
315
+ const customMgr = new CustomModuleManager();
316
+ const resolved = customMgr.getResolution(moduleName);
317
+ const customSource = await customMgr.findModuleSourceByCode(moduleName, { bmadDir });
318
+ if (customSource || resolved) {
319
+ const versionInfo = await resolveModuleVersion(moduleName, {
320
+ moduleSourcePath: moduleSourcePath || customSource,
321
+ fallbackVersion: resolved?.version,
322
+ marketplacePluginNames: resolved?.pluginName ? [resolved.pluginName] : [],
323
+ });
324
+ const hasGitClone = !!resolved?.repoUrl;
325
+ return {
326
+ // Prefer the git ref we actually cloned over the package.json version.
327
+ version: resolved?.cloneRef || (hasGitClone ? 'main' : versionInfo.version),
328
+ source: 'custom',
329
+ npmPackage: null,
330
+ repoUrl: resolved?.repoUrl || null,
331
+ localPath: resolved?.localPath || null,
332
+ channel: hasGitClone ? (resolved?.cloneRef ? 'pinned' : 'next') : null,
333
+ sha: resolved?.cloneSha || null,
334
+ rawSource: resolved?.rawInput || null,
335
+ };
336
+ }
337
+
338
+ // Unknown module
339
+ const versionInfo = await resolveModuleVersion(moduleName, { moduleSourcePath });
340
+ return {
341
+ version: versionInfo.version,
342
+ source: 'unknown',
343
+ npmPackage: null,
344
+ repoUrl: null,
345
+ };
346
+ }
347
+
348
+ /**
349
+ * Fetch latest version from npm for a package
350
+ * @param {string} packageName - npm package name
351
+ * @returns {string|null} Latest version or null
352
+ */
353
+ async fetchNpmVersion(packageName) {
354
+ if (!isValidNpmPackageName(packageName)) {
355
+ return null;
356
+ }
357
+
358
+ try {
359
+ // Try using npm view first (more reliable)
360
+ try {
361
+ const { stdout } = await execFileAsync('npm', ['view', packageName, 'version'], {
362
+ encoding: 'utf8',
363
+ timeout: NPM_LOOKUP_TIMEOUT_MS,
364
+ });
365
+ return stdout.trim();
366
+ } catch {
367
+ // Fallback to npm registry API
368
+ return new Promise((resolve) => {
369
+ const request = https.get(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`, (res) => {
370
+ let data = '';
371
+ res.on('data', (chunk) => (data += chunk));
372
+ res.on('end', () => {
373
+ try {
374
+ const pkg = JSON.parse(data);
375
+ resolve(pkg['dist-tags']?.latest || pkg.version || null);
376
+ } catch {
377
+ resolve(null);
378
+ }
379
+ });
380
+ });
381
+
382
+ request.setTimeout(NPM_LOOKUP_TIMEOUT_MS, () => {
383
+ request.destroy();
384
+ resolve(null);
385
+ });
386
+
387
+ request.on('error', () => resolve(null));
388
+ });
389
+ }
390
+ } catch {
391
+ return null;
392
+ }
393
+ }
394
+
395
+ /**
396
+ * Check for available updates for installed modules
397
+ * @param {string} bmadDir - Path to bmad directory
398
+ * @returns {Array} Array of update info objects
399
+ */
400
+ async checkForUpdates(bmadDir) {
401
+ const semver = require('semver');
402
+ const modules = await this.getAllModuleVersions(bmadDir);
403
+ const updates = [];
404
+
405
+ for (const module of modules) {
406
+ if (!module.npmPackage) {
407
+ continue; // Skip modules without npm package (built-in)
408
+ }
409
+
410
+ const latestVersion = await this.fetchNpmVersion(module.npmPackage);
411
+ if (!latestVersion) {
412
+ continue;
413
+ }
414
+
415
+ const installedVersion = semver.valid(module.version) || semver.valid(semver.coerce(module.version || ''));
416
+ const availableVersion = semver.valid(latestVersion) || semver.valid(semver.coerce(latestVersion));
417
+
418
+ if (installedVersion && availableVersion && semver.gt(availableVersion, installedVersion)) {
419
+ updates.push({
420
+ name: module.name,
421
+ installedVersion: module.version,
422
+ latestVersion: latestVersion,
423
+ npmPackage: module.npmPackage,
424
+ updateAvailable: true,
425
+ });
426
+ }
427
+ }
428
+
429
+ return updates;
430
+ }
431
+ }
432
+
433
+ module.exports = { Manifest };
@@ -0,0 +1,195 @@
1
+ const { spawnSync } = require('node:child_process');
2
+ const prompts = require('../prompts');
3
+
4
+ // `uv` (https://docs.astral.sh/uv/) is how BMAD runs the Python scripts its
5
+ // skills shell out to: `uv run <script>` resolves the interpreter and any
6
+ // dependencies on demand from the script's own `requires-python` metadata, so
7
+ // skills don't have to assume a particular `python3` is on PATH.
8
+ //
9
+ // As of v6.11.0 this is a requirement, not a preference: the rendered skills
10
+ // (`bmad-build`, `bmad-build-auto`) render through `render_skill.py` and HALT
11
+ // on activation if `uv` is unavailable — there is no interpreter fallback.
12
+ //
13
+ // The check still never blocks the install. Core-only, docs-only, and CI
14
+ // installs are legitimate and never touch a rendered skill, so a missing `uv`
15
+ // must not fail the run. What it does is tell the truth about what will and
16
+ // will not work afterwards, here and again in the post-install summary.
17
+ const RUNTIME_COMMAND = 'uv';
18
+
19
+ // Probed only when `uv` is absent. Some skills still invoke the interpreter
20
+ // directly (`python3 .../resolve_customization.py`), and those scripts declare
21
+ // `requires-python = ">=3.11"` — `resolve_config.py` hard-exits below it
22
+ // because `tomllib` is a 3.11 stdlib addition. When `uv` is present it
23
+ // provisions its own interpreter and whatever `python3` resolves to on PATH is
24
+ // irrelevant, so probing it then would report a problem that doesn't exist.
25
+ const PYTHON_COMMAND = 'python3';
26
+ const MIN_PYTHON = { major: 3, minor: 11 };
27
+
28
+ /**
29
+ * Parse `uv --version` output into version parts.
30
+ * Example outputs: "uv 0.5.31", "uv 0.5.31 (Homebrew 2025-02-12)".
31
+ * @param {string} output - stdout/stderr from `uv --version`
32
+ * @returns {{major: number, minor: number, patch: number, raw: string}|null}
33
+ */
34
+ function parseUvVersion(output) {
35
+ if (!output) return null;
36
+ const match = output.match(/uv\s+(\d+)\.(\d+)(?:\.(\d+))?/i);
37
+ if (!match) return null;
38
+ return {
39
+ major: Number(match[1]),
40
+ minor: Number(match[2]),
41
+ patch: Number(match[3] || 0),
42
+ raw: `${match[1]}.${match[2]}.${match[3] || 0}`,
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Parse `python3 --version` output into version parts.
48
+ * Example outputs: "Python 3.11.7", "Python 3.13.0rc1".
49
+ * @param {string} output - stdout/stderr from `python3 --version`
50
+ * @returns {{major: number, minor: number, patch: number, raw: string}|null}
51
+ */
52
+ function parsePythonVersion(output) {
53
+ if (!output) return null;
54
+ const match = output.match(/Python\s+(\d+)\.(\d+)(?:\.(\d+))?/i);
55
+ if (!match) return null;
56
+ return {
57
+ major: Number(match[1]),
58
+ minor: Number(match[2]),
59
+ patch: Number(match[3] || 0),
60
+ raw: `${match[1]}.${match[2]}.${match[3] || 0}`,
61
+ };
62
+ }
63
+
64
+ /**
65
+ * Whether a parsed Python version satisfies the 3.11+ floor the scripts declare.
66
+ * @param {{major: number, minor: number}|null} version
67
+ * @returns {boolean}
68
+ */
69
+ function pythonMeetsMinimum(version) {
70
+ if (!version) return false;
71
+ if (version.major !== MIN_PYTHON.major) return version.major > MIN_PYTHON.major;
72
+ return version.minor >= MIN_PYTHON.minor;
73
+ }
74
+
75
+ /**
76
+ * Run `<command> --version` and hand the combined output to a parser.
77
+ * @param {string} command
78
+ * @param {(output: string) => Object|null} parse
79
+ * @returns {{version: Object}|null}
80
+ */
81
+ function probeVersion(command, parse) {
82
+ let result;
83
+ try {
84
+ result = spawnSync(command, ['--version'], {
85
+ encoding: 'utf8',
86
+ timeout: 5000,
87
+ windowsHide: true,
88
+ });
89
+ } catch {
90
+ return null;
91
+ }
92
+ if (!result || result.error) return null;
93
+ const version = parse(`${result.stdout || ''}\n${result.stderr || ''}`);
94
+ return version ? { version } : null;
95
+ }
96
+
97
+ /**
98
+ * Probe the local environment for `uv`.
99
+ * @returns {{version: {major: number, minor: number, patch: number, raw: string}}|null}
100
+ */
101
+ function detectUv() {
102
+ return probeVersion(RUNTIME_COMMAND, parseUvVersion);
103
+ }
104
+
105
+ /**
106
+ * Probe the local environment for `python3`.
107
+ * @returns {{version: {major: number, minor: number, patch: number, raw: string}}|null}
108
+ */
109
+ function detectPython3() {
110
+ return probeVersion(PYTHON_COMMAND, parsePythonVersion);
111
+ }
112
+
113
+ function setupHints() {
114
+ return [
115
+ '`uv run` provisions the interpreter and dependencies for you — no manual',
116
+ 'venv or pip, and no need for a particular python3 on PATH.',
117
+ '',
118
+ 'Easiest path: ask your AI agent to "install and set up uv for me".',
119
+ '',
120
+ 'Or install it yourself:',
121
+ ' macOS/Linux: curl -LsSf https://astral.sh/uv/install.sh | sh',
122
+ ' Windows: powershell -c "irm https://astral.sh/uv/install.ps1 | iex"',
123
+ ' Homebrew: brew install uv',
124
+ ' Docs: https://docs.astral.sh/uv/getting-started/installation/',
125
+ ].join('\n');
126
+ }
127
+
128
+ /**
129
+ * Describe what a missing `uv` leaves working, based on the `python3` fallback.
130
+ *
131
+ * With `uv` gone the rendered skills are lost either way; the only question is
132
+ * whether the skills that invoke the interpreter directly still run, and that
133
+ * turns on `python3` being 3.11+.
134
+ *
135
+ * @param {{version: Object}|null} python - result of detectPython3()
136
+ * @returns {string}
137
+ */
138
+ function pythonFallbackNote(python) {
139
+ if (!python) {
140
+ return 'No python3 on PATH either, so no Python-backed skill will run.';
141
+ }
142
+ if (pythonMeetsMinimum(python.version)) {
143
+ return (
144
+ `python3 ${python.version.raw} is present, so skills that call the interpreter ` +
145
+ 'directly still work — but the rendered skills above stay unavailable.'
146
+ );
147
+ }
148
+ return (
149
+ `python3 ${python.version.raw} is present but below the required ` +
150
+ `${MIN_PYTHON.major}.${MIN_PYTHON.minor}, so no Python-backed skill will run.`
151
+ );
152
+ }
153
+
154
+ /**
155
+ * Check whether `uv` is available and inform the user.
156
+ *
157
+ * Warn-don't-block: a missing `uv` never stops or fails the install, because
158
+ * core-only and CI installs are legitimate and never render a skill. But the
159
+ * warning names the concrete consequence — `bmad-build` and `bmad-build-auto`
160
+ * halt — rather than describing `uv` as a nice-to-have, and `installer.js`
161
+ * repeats it in the post-install summary so it isn't lost in the scrollback.
162
+ *
163
+ * @returns {Promise<{status: 'found'|'missing', detected: Object|null, python: Object|null}>}
164
+ */
165
+ async function checkUvEnvironment() {
166
+ // Called via module.exports so tests can stub detection.
167
+ const detected = module.exports.detectUv();
168
+
169
+ if (detected) {
170
+ await prompts.log.success(`✅ Python UV check pass (uv ${detected.version.raw} detected).`);
171
+ return { status: 'found', detected, python: null };
172
+ }
173
+
174
+ const python = module.exports.detectPython3();
175
+
176
+ await prompts.log.warn(
177
+ 'uv not found on PATH. BMAD requires it to run the Python scripts its skills\n' +
178
+ 'shell out to: bmad-build and bmad-build-auto render through `uv run` and will\n' +
179
+ 'HALT on activation without it — there is no interpreter fallback.\n' +
180
+ `${pythonFallbackNote(python)}\n` +
181
+ 'The install itself completes either way.',
182
+ );
183
+ await prompts.note(setupHints(), 'uv required');
184
+ return { status: 'missing', detected: null, python };
185
+ }
186
+
187
+ module.exports = {
188
+ checkUvEnvironment,
189
+ detectUv,
190
+ detectPython3,
191
+ parseUvVersion,
192
+ parsePythonVersion,
193
+ pythonMeetsMinimum,
194
+ MIN_PYTHON,
195
+ };