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,524 @@
1
+ # /// script
2
+ # requires-python = ">=3.10"
3
+ # dependencies = ["pytest>=8.0", "ruamel.yaml>=0.18"]
4
+ # ///
5
+ """Tests for sprint_plan.py — deterministic sprint-status generation.
6
+
7
+ Run: uv run scripts/tests/test_sprint_plan.py
8
+ or: uv run --with pytest --with ruamel.yaml -m pytest scripts/tests/test_sprint_plan.py
9
+ """
10
+
11
+ import importlib.util
12
+ import json
13
+ import sys
14
+ from pathlib import Path
15
+
16
+ import pytest
17
+ from ruamel.yaml import YAML
18
+
19
+ SCRIPT = Path(__file__).resolve().parents[1] / "sprint_plan.py"
20
+ TEMPLATE = Path(__file__).resolve().parents[2] / "sprint-status-template.yaml"
21
+
22
+ spec = importlib.util.spec_from_file_location("sprint_plan", SCRIPT)
23
+ mod = importlib.util.module_from_spec(spec)
24
+ spec.loader.exec_module(mod)
25
+
26
+ EPICS_FIXTURE = """\
27
+ # Project Epics
28
+
29
+ ## Epic 1: Foundation
30
+ Some prose.
31
+
32
+ ### Story 1.1: User Authentication
33
+ Acceptance criteria...
34
+
35
+ ### Story 1.2: Account Management
36
+
37
+ ## Epic 2: Chat
38
+ ### Story 2.1: Personality System
39
+ ### Story 2.6a: Split Story, With Punctuation!
40
+ """
41
+
42
+ DATE = "08-01-2026 14:30"
43
+
44
+
45
+ def run_generate(tmp_path, epics_text=EPICS_FIXTURE, existing=None, stories=(), extra=()):
46
+ epic_file = tmp_path / "epics.md"
47
+ epic_file.write_text(epics_text, encoding="utf-8")
48
+ status_file = tmp_path / "impl" / "sprint-status.yaml"
49
+ if existing is not None:
50
+ status_file.parent.mkdir(parents=True, exist_ok=True)
51
+ status_file.write_text(existing, encoding="utf-8")
52
+ stories_dir = tmp_path / "impl"
53
+ stories_dir.mkdir(parents=True, exist_ok=True)
54
+ for name in stories:
55
+ (stories_dir / f"{name}.md").write_text("story", encoding="utf-8")
56
+ argv = [
57
+ "generate", "--epic-file", str(epic_file), "--status-file", str(status_file),
58
+ "--stories-dir", str(stories_dir), "--project", "My Project", "--date", DATE,
59
+ *extra,
60
+ ]
61
+ mod.main(argv)
62
+ return status_file
63
+
64
+
65
+ def load(status_file):
66
+ yaml = YAML()
67
+ with open(status_file, encoding="utf-8") as fh:
68
+ return yaml.load(fh)
69
+
70
+
71
+ def out_json(capsys):
72
+ return json.loads(capsys.readouterr().out)
73
+
74
+
75
+ def test_fresh_generate_orders_and_defaults(tmp_path, capsys):
76
+ status_file = run_generate(tmp_path)
77
+ result = out_json(capsys)
78
+ data = load(status_file)
79
+ keys = list(data["development_status"].keys())
80
+ assert keys == [
81
+ "epic-1", "1-1-user-authentication", "1-2-account-management", "epic-1-retrospective",
82
+ "epic-2", "2-1-personality-system", "2-6a-split-story-with-punctuation", "epic-2-retrospective",
83
+ ]
84
+ assert data["development_status"]["epic-1"] == "backlog"
85
+ assert data["development_status"]["1-1-user-authentication"] == "backlog"
86
+ assert data["development_status"]["epic-1-retrospective"] == "optional"
87
+ assert data["project"] == "My Project"
88
+ assert data["generated"] == DATE and data["last_updated"] == DATE
89
+ assert result["ok"] and result["epics"] == 2 and result["stories"] == 4
90
+ text = status_file.read_text(encoding="utf-8")
91
+ assert "STATUS DEFINITIONS" in text
92
+ assert "\n\n epic-2:" in text # blank line between epic groups
93
+
94
+
95
+ def test_header_comment_matches_template():
96
+ """The template's STATUS DEFINITIONS block and the script's HEADER_COMMENT
97
+ are two copies of one contract; this pins them together."""
98
+ lines = TEMPLATE.read_text(encoding="utf-8").splitlines()
99
+ start = lines.index("# STATUS DEFINITIONS:")
100
+ block = []
101
+ for line in lines[start:]:
102
+ if not line.startswith("#"):
103
+ break
104
+ block.append(line[2:] if line.startswith("# ") else line[1:])
105
+ assert "\n".join(block) + "\n" == mod.HEADER_COMMENT
106
+
107
+
108
+ EXISTING = """\
109
+ generated: 01-01-2026 09:00
110
+ last_updated: 01-01-2026 09:00
111
+ project: My Project
112
+ project_key: NOKEY
113
+ tracking_system: file-system
114
+ story_location: impl
115
+
116
+ development_status:
117
+ epic-1: in-progress
118
+ 1-1-user-authentication: done
119
+ 1-2-account-management: backlog
120
+ epic-1-retrospective: optional
121
+ 9-9-ghost-story: done
122
+
123
+ action_items:
124
+ - epic: 1
125
+ action: "Add error-handling review; watch: quotes, commas"
126
+ owner: "Charlie"
127
+ status: open
128
+ """
129
+
130
+
131
+ def test_merge_preserves_and_never_downgrades(tmp_path, capsys):
132
+ status_file = run_generate(tmp_path, existing=EXISTING)
133
+ result = out_json(capsys)
134
+ data = load(status_file)
135
+ assert data["development_status"]["epic-1"] == "in-progress"
136
+ assert data["development_status"]["1-1-user-authentication"] == "done"
137
+ assert data["generated"] == "01-01-2026 09:00"
138
+ assert data["last_updated"] == DATE
139
+ assert result["dropped_orphans"] == [{"key": "9-9-ghost-story", "status": "done"}]
140
+ assert "9-9-ghost-story" not in data["development_status"]
141
+
142
+
143
+ def test_legacy_statuses_merge_by_meaning_not_reset(tmp_path, capsys):
144
+ existing = (EXISTING
145
+ .replace("1-2-account-management: backlog", "1-2-account-management: drafted")
146
+ .replace("epic-1: in-progress", "epic-1: contexted"))
147
+ status_file = run_generate(tmp_path, existing=existing)
148
+ result = out_json(capsys)
149
+ data = load(status_file)
150
+ assert data["development_status"]["1-2-account-management"] == "ready-for-dev"
151
+ assert data["development_status"]["epic-1"] == "in-progress"
152
+ assert {"key": "1-2-account-management", "from": "drafted", "to": "ready-for-dev"} in result["legacy_mapped"]
153
+ assert not any("illegal" in w for w in result["warnings"])
154
+ assert result["illegal"] == []
155
+
156
+
157
+ def test_metadata_preserved_when_flags_omitted(tmp_path, capsys):
158
+ existing = (EXISTING
159
+ .replace("project_key: NOKEY", "project_key: JIRA-PROJ")
160
+ .replace("tracking_system: file-system", "tracking_system: jira")
161
+ .replace("story_location: impl", "story_location: /custom/stories"))
162
+ status_file = run_generate(tmp_path, existing=existing)
163
+ out_json(capsys)
164
+ data = load(status_file)
165
+ assert data["project_key"] == "JIRA-PROJ"
166
+ assert data["tracking_system"] == "jira"
167
+ assert data["story_location"] == "/custom/stories"
168
+
169
+
170
+ def test_unknown_keys_and_comments_survive_regenerate(tmp_path, capsys):
171
+ existing = EXISTING + "\n# my own note\nsprint_goal: Ship the beta\n"
172
+ status_file = run_generate(tmp_path, existing=existing)
173
+ out_json(capsys)
174
+ data = load(status_file)
175
+ assert data["sprint_goal"] == "Ship the beta"
176
+ assert "# my own note" in status_file.read_text(encoding="utf-8")
177
+
178
+
179
+ def test_fresh_rebuild_ignores_existing_statuses(tmp_path, capsys):
180
+ status_file = run_generate(tmp_path, existing=EXISTING, extra=("--fresh",))
181
+ result = out_json(capsys)
182
+ data = load(status_file)
183
+ assert data["development_status"]["1-1-user-authentication"] == "backlog"
184
+ assert data["development_status"]["epic-1"] == "backlog"
185
+ assert result["fresh"] is True
186
+ # action_items are retro history, not tracking state — carried even on --fresh
187
+ assert data["action_items"][0]["status"] == "open"
188
+
189
+
190
+ def test_set_applies_explicit_statuses_even_downgrades(tmp_path, capsys):
191
+ status_file = run_generate(
192
+ tmp_path, existing=EXISTING,
193
+ extra=("--fresh", "--set", "1-1-user-authentication=in-progress", "--set", "epic-1=in-progress"),
194
+ )
195
+ result = out_json(capsys)
196
+ data = load(status_file)
197
+ assert data["development_status"]["1-1-user-authentication"] == "in-progress"
198
+ assert data["development_status"]["epic-1"] == "in-progress"
199
+ assert "1-1-user-authentication=in-progress" in result["explicit_set"]
200
+
201
+
202
+ def test_set_rejects_unknown_key_and_illegal_status(tmp_path, capsys):
203
+ with pytest.raises(SystemExit) as excinfo:
204
+ run_generate(tmp_path, extra=("--set", "9-9-nope=done"))
205
+ assert excinfo.value.code == 1
206
+ assert out_json(capsys)["ok"] is False
207
+ with pytest.raises(SystemExit):
208
+ run_generate(tmp_path, extra=("--set", "epic-1=review"))
209
+ assert out_json(capsys)["ok"] is False
210
+
211
+
212
+ def test_action_items_carried_verbatim(tmp_path):
213
+ status_file = run_generate(tmp_path, existing=EXISTING)
214
+ data = load(status_file)
215
+ assert data["action_items"][0]["action"] == "Add error-handling review; watch: quotes, commas"
216
+ assert data["action_items"][0]["status"] == "open"
217
+
218
+
219
+ def test_story_file_on_disk_floors_ready_for_dev(tmp_path, capsys):
220
+ status_file = run_generate(tmp_path, stories=["1-2-account-management"])
221
+ result = out_json(capsys)
222
+ data = load(status_file)
223
+ assert data["development_status"]["1-2-account-management"] == "ready-for-dev"
224
+ assert data["development_status"]["1-1-user-authentication"] == "backlog"
225
+ assert result["upgraded_from_disk"] == ["1-2-account-management"]
226
+
227
+
228
+ def test_story_file_never_downgrades_done(tmp_path):
229
+ status_file = run_generate(tmp_path, existing=EXISTING, stories=["1-1-user-authentication"])
230
+ data = load(status_file)
231
+ assert data["development_status"]["1-1-user-authentication"] == "done"
232
+
233
+
234
+ def test_illegal_existing_status_warns_and_resets(tmp_path, capsys):
235
+ existing = EXISTING.replace("1-2-account-management: backlog", "1-2-account-management: shipped")
236
+ status_file = run_generate(tmp_path, existing=existing)
237
+ result = out_json(capsys)
238
+ data = load(status_file)
239
+ assert data["development_status"]["1-2-account-management"] == "backlog"
240
+ assert any("illegal status 'shipped'" in w for w in result["warnings"])
241
+ assert {"key": "1-2-account-management", "status": "shipped"} in result["illegal"]
242
+
243
+
244
+ def test_fenced_code_blocks_are_not_parsed(tmp_path, capsys):
245
+ text = EPICS_FIXTURE + "\n```\n## Epic 9: Example Format\n### Story 9.1: Sample\n```\n"
246
+ status_file = run_generate(tmp_path, epics_text=text)
247
+ result = out_json(capsys)
248
+ data = load(status_file)
249
+ assert "epic-9" not in data["development_status"]
250
+ assert result["epics"] == 2
251
+ assert not any("Epic 9" in w for w in result["warnings"])
252
+
253
+
254
+ def test_non_ascii_titles_keep_distinct_keys(tmp_path, capsys):
255
+ text = "## Epic 1: 基础\n### Story 1.1: 用户认证\n### Story 1.2: 账户管理\n"
256
+ status_file = run_generate(tmp_path, epics_text=text)
257
+ out_json(capsys)
258
+ keys = list(load(status_file)["development_status"].keys())
259
+ assert "1-1-用户认证" in keys and "1-2-账户管理" in keys
260
+
261
+
262
+ def test_suspect_heading_is_reported(tmp_path, capsys):
263
+ text = EPICS_FIXTURE + "\n### Story Two point one: Bad Format\n"
264
+ run_generate(tmp_path, epics_text=text)
265
+ result = out_json(capsys)
266
+ assert any("unparsed Epic/Story-like heading" in w for w in result["warnings"])
267
+
268
+
269
+ def test_dry_run_writes_nothing_and_reports_drift(tmp_path, capsys):
270
+ epic_file = tmp_path / "epics.md"
271
+ epic_file.write_text(EPICS_FIXTURE, encoding="utf-8")
272
+ status_file = tmp_path / "sprint-status.yaml"
273
+ status_file.write_text(EXISTING, encoding="utf-8")
274
+ original = status_file.read_bytes()
275
+ mod.main([
276
+ "generate", "--epic-file", str(epic_file), "--status-file", str(status_file),
277
+ "--stories-dir", str(tmp_path), "--project", "P", "--date", DATE, "--dry-run",
278
+ ])
279
+ result = out_json(capsys)
280
+ assert result["dry_run"] is True and result["ok"] is True
281
+ assert result["in_sync"] is False
282
+ assert "epic-2" in result["new_entries"]
283
+ assert result["dropped_orphans"] == [{"key": "9-9-ghost-story", "status": "done"}]
284
+ assert status_file.read_bytes() == original
285
+
286
+
287
+ def test_dry_run_in_sync_after_generate(tmp_path, capsys):
288
+ status_file = run_generate(tmp_path)
289
+ capsys.readouterr()
290
+ mod.main([
291
+ "generate", "--epic-file", str(tmp_path / "epics.md"), "--status-file", str(status_file),
292
+ "--stories-dir", str(tmp_path / "impl"), "--project", "My Project", "--date", DATE,
293
+ "--dry-run",
294
+ ])
295
+ result = out_json(capsys)
296
+ assert result["in_sync"] is True
297
+ assert result["new_entries"] == [] and result["dropped_orphans"] == [] and result["illegal"] == []
298
+
299
+
300
+ def test_no_epics_fails_with_json(tmp_path, capsys):
301
+ epic_file = tmp_path / "notes.md"
302
+ epic_file.write_text("just prose, no epics", encoding="utf-8")
303
+ with pytest.raises(SystemExit) as excinfo:
304
+ mod.main([
305
+ "generate", "--epic-file", str(epic_file), "--status-file", str(tmp_path / "s.yaml"),
306
+ "--stories-dir", str(tmp_path), "--project", "P", "--date", DATE,
307
+ ])
308
+ assert excinfo.value.code == 1
309
+ assert out_json(capsys)["ok"] is False
310
+
311
+
312
+ def test_non_mapping_yaml_fails_with_json(tmp_path, capsys):
313
+ epic_file = tmp_path / "epics.md"
314
+ epic_file.write_text(EPICS_FIXTURE, encoding="utf-8")
315
+ status_file = tmp_path / "sprint-status.yaml"
316
+ status_file.write_text("- just\n- a\n- list\n", encoding="utf-8")
317
+ with pytest.raises(SystemExit) as excinfo:
318
+ mod.main([
319
+ "generate", "--epic-file", str(epic_file), "--status-file", str(status_file),
320
+ "--stories-dir", str(tmp_path), "--project", "P", "--date", DATE,
321
+ ])
322
+ assert excinfo.value.code == 1
323
+ assert "not a mapping" in out_json(capsys)["error"]
324
+ with pytest.raises(SystemExit):
325
+ mod.main(["status", "--status-file", str(status_file)])
326
+ assert "not a mapping" in out_json(capsys)["error"]
327
+
328
+
329
+ def test_argument_errors_emit_json(capsys):
330
+ with pytest.raises(SystemExit) as excinfo:
331
+ mod.main(["generate"])
332
+ assert excinfo.value.code == 2
333
+ assert out_json(capsys)["ok"] is False
334
+ with pytest.raises(SystemExit) as excinfo:
335
+ mod.main(["-h"])
336
+ assert excinfo.value.code == 2
337
+ assert out_json(capsys)["ok"] is False
338
+
339
+
340
+ STATUS_FIXTURE = """\
341
+ generated: 01-01-2026 09:00
342
+ last_updated: 07-30-2026 09:00
343
+ project: My Project
344
+ project_key: NOKEY
345
+ tracking_system: file-system
346
+ story_location: impl
347
+
348
+ development_status:
349
+ epic-1: in-progress
350
+ 1-1-user-authentication: done
351
+ 1-2-account-management: drafted
352
+ epic-1-retrospective: optional
353
+ epic-2: backlog
354
+ 2-1-personality-system: backlog
355
+ epic-2-retrospective: optional
356
+
357
+ action_items:
358
+ - epic: 1
359
+ action: "Tighten error handling"
360
+ owner: "Charlie"
361
+ status: open
362
+ - epic: 1
363
+ action: "Old item"
364
+ owner: "Charlie"
365
+ status: done
366
+ """
367
+
368
+
369
+ def run_status(tmp_path, capsys, fixture=STATUS_FIXTURE, extra=()):
370
+ status_file = tmp_path / "sprint-status.yaml"
371
+ status_file.write_text(fixture, encoding="utf-8")
372
+ mod.main(["status", "--status-file", str(status_file), "--date", DATE, *extra])
373
+ return json.loads(capsys.readouterr().out)
374
+
375
+
376
+ def test_status_counts_and_recommendation(tmp_path, capsys):
377
+ result = run_status(tmp_path, capsys)
378
+ assert result["stories"] == {"done": 1, "ready-for-dev": 1, "backlog": 1}
379
+ assert result["epics"] == {"in-progress": 1, "backlog": 1}
380
+ assert result["retrospectives"] == {"optional": 2}
381
+ assert result["recommendation"]["skill"] == "bmad-build"
382
+ assert result["recommendation"]["story_key"] == "1-2-account-management"
383
+ assert result["all_done"] is False
384
+
385
+
386
+ def test_status_maps_legacy_values(tmp_path, capsys):
387
+ result = run_status(tmp_path, capsys)
388
+ assert {"key": "1-2-account-management", "from": "drafted", "to": "ready-for-dev"} in result["legacy_mapped"]
389
+
390
+
391
+ def test_status_open_action_items(tmp_path, capsys):
392
+ result = run_status(tmp_path, capsys)
393
+ assert len(result["open_action_items"]) == 1
394
+ assert result["open_action_items"][0]["action"] == "Tighten error handling"
395
+
396
+
397
+ def test_status_malformed_action_items_are_flagged_not_dropped(tmp_path, capsys):
398
+ fixture = STATUS_FIXTURE + " - \"just a string\"\n - epic: 2\n action: \"No status\"\n"
399
+ result = run_status(tmp_path, capsys, fixture=fixture)
400
+ assert any("not a mapping" in w for w in result["warnings"])
401
+ assert any("missing or unknown status" in w for w in result["warnings"])
402
+ assert len(result["open_action_items"]) == 1
403
+
404
+
405
+ def test_status_review_beats_ready(tmp_path, capsys):
406
+ fixture = STATUS_FIXTURE.replace("2-1-personality-system: backlog", "2-1-personality-system: review")
407
+ result = run_status(tmp_path, capsys, fixture=fixture)
408
+ assert result["recommendation"]["skill"] == "bmad-code-review"
409
+ assert result["recommendation"]["story_key"] == "2-1-personality-system"
410
+ assert any("review" in r for r in result["risks"])
411
+
412
+
413
+ def test_status_in_progress_beats_all(tmp_path, capsys):
414
+ fixture = STATUS_FIXTURE.replace("2-1-personality-system: backlog", "2-1-personality-system: in-progress")
415
+ result = run_status(tmp_path, capsys, fixture=fixture)
416
+ assert result["recommendation"]["skill"] == "bmad-build"
417
+ assert result["recommendation"]["story_key"] == "2-1-personality-system"
418
+ assert result["recommendation"]["reason"] == "resume the in-progress story"
419
+
420
+
421
+ def test_status_staleness_and_orphan_risks(tmp_path, capsys):
422
+ fixture = (STATUS_FIXTURE
423
+ .replace("last_updated: 07-30-2026 09:00", "last_updated: 01-02-2026 09:00")
424
+ .replace(" epic-2-retrospective: optional",
425
+ " epic-2-retrospective: optional\n 5-1-ghost: backlog"))
426
+ result = run_status(tmp_path, capsys, fixture=fixture)
427
+ assert any("stale" in r for r in result["risks"])
428
+ assert any("orphaned story '5-1-ghost'" in r for r in result["risks"])
429
+
430
+
431
+ def test_status_unparseable_timestamp_warns_instead_of_silence(tmp_path, capsys):
432
+ fixture = STATUS_FIXTURE.replace("last_updated: 07-30-2026 09:00", "last_updated: whenever")
433
+ result = run_status(tmp_path, capsys, fixture=fixture)
434
+ assert any("staleness check skipped" in w for w in result["warnings"])
435
+
436
+
437
+ def test_status_iso_and_date_typed_stamps_do_not_crash(tmp_path, capsys):
438
+ fixture = (STATUS_FIXTURE
439
+ .replace("generated: 01-01-2026 09:00", "generated: 2026-01-01")
440
+ .replace("last_updated: 07-30-2026 09:00", "last_updated: 2026-01-02"))
441
+ result = run_status(tmp_path, capsys, fixture=fixture)
442
+ assert result["ok"] is True
443
+ assert result["generated"] == "2026-01-01"
444
+ assert any("stale" in r for r in result["risks"]) # ISO stamp still parses
445
+
446
+
447
+ def test_status_all_done_recommends_retro_then_nothing(tmp_path, capsys):
448
+ fixture = (STATUS_FIXTURE
449
+ .replace("1-2-account-management: drafted", "1-2-account-management: done")
450
+ .replace("2-1-personality-system: backlog", "2-1-personality-system: done"))
451
+ result = run_status(tmp_path, capsys, fixture=fixture)
452
+ assert result["recommendation"]["skill"] == "bmad-retrospective"
453
+ assert "epic-1-retrospective" in result["recommendation"]["reason"]
454
+ fixture_done = fixture.replace("epic-1-retrospective: optional", "epic-1-retrospective: done") \
455
+ .replace("epic-2-retrospective: optional", "epic-2-retrospective: done")
456
+ result = run_status(tmp_path, capsys, fixture=fixture_done)
457
+ assert result["all_done"] is True and result["recommendation"] is None
458
+
459
+
460
+ def test_status_odd_retro_key_reports_instead_of_crashing(tmp_path, capsys):
461
+ fixture = (STATUS_FIXTURE
462
+ .replace("1-2-account-management: drafted", "1-2-account-management: done")
463
+ .replace("2-1-personality-system: backlog", "2-1-personality-system: done")
464
+ .replace("epic-1-retrospective: optional", "epic-1-retrospective: done")
465
+ .replace("epic-2-retrospective: optional",
466
+ "epic-2-retrospective: done\n epic-abc-retrospective: optional"))
467
+ result = run_status(tmp_path, capsys, fixture=fixture)
468
+ assert result["ok"] is True
469
+ assert {"key": "epic-abc-retrospective", "status": "optional"} in result["unrecognized"]
470
+ assert any("unrecognized key" in r for r in result["risks"])
471
+
472
+
473
+ def test_status_illegal_status_reported(tmp_path, capsys):
474
+ fixture = STATUS_FIXTURE.replace("2-1-personality-system: backlog", "2-1-personality-system: shipped")
475
+ result = run_status(tmp_path, capsys, fixture=fixture)
476
+ assert {"key": "2-1-personality-system", "status": "shipped"} in result["illegal"]
477
+
478
+
479
+ def test_status_missing_file_fails_json(tmp_path, capsys):
480
+ with pytest.raises(SystemExit) as excinfo:
481
+ mod.main(["status", "--status-file", str(tmp_path / "nope.yaml")])
482
+ assert excinfo.value.code == 1
483
+ assert json.loads(capsys.readouterr().out)["ok"] is False
484
+
485
+
486
+ def run_validate(tmp_path, capsys, content):
487
+ status_file = tmp_path / "sprint-status.yaml"
488
+ if content is not None:
489
+ status_file.write_text(content, encoding="utf-8")
490
+ mod.main(["validate", "--status-file", str(status_file)])
491
+ return json.loads(capsys.readouterr().out)
492
+
493
+
494
+ def test_validate_clean_file(tmp_path, capsys):
495
+ clean = STATUS_FIXTURE.replace("1-2-account-management: drafted", "1-2-account-management: backlog")
496
+ result = run_validate(tmp_path, capsys, clean)
497
+ assert result["valid"] is True and result["problems"] == []
498
+
499
+
500
+ def test_validate_reports_problems_without_crashing(tmp_path, capsys):
501
+ broken = (STATUS_FIXTURE
502
+ .replace("2-1-personality-system: backlog", "2-1-personality-system: shipped")
503
+ .replace("epic-2-retrospective: optional",
504
+ "epic-2-retrospective: optional\n weird-key: done")
505
+ .replace("last_updated: 07-30-2026 09:00", "last_updated: whenever"))
506
+ result = run_validate(tmp_path, capsys, broken)
507
+ assert result["valid"] is False
508
+ assert any("illegal story status 'shipped'" in p for p in result["problems"])
509
+ assert any("unrecognized key 'weird-key'" in p for p in result["problems"])
510
+ assert any("'last_updated' timestamp" in p for p in result["problems"])
511
+ assert {"key": "1-2-account-management", "from": "drafted", "to": "ready-for-dev"} in result["legacy_mapped"]
512
+
513
+
514
+ def test_validate_missing_file_and_bad_yaml(tmp_path, capsys):
515
+ result = run_validate(tmp_path, capsys, None)
516
+ assert result["valid"] is False and "does not exist" in result["problems"][0]
517
+ result = run_validate(tmp_path, capsys, "development_status: [unclosed\n")
518
+ assert result["valid"] is False and "not valid YAML" in result["problems"][0]
519
+ result = run_validate(tmp_path, capsys, "- a\n- b\n")
520
+ assert result["valid"] is False and any("not a mapping" in p for p in result["problems"])
521
+
522
+
523
+ if __name__ == "__main__":
524
+ sys.exit(pytest.main([__file__, "-q"]))
@@ -0,0 +1,71 @@
1
+ # Sprint Status Template
2
+ # This is an EXAMPLE showing the expected format
3
+ # The actual file will be generated with all epics/stories from your epic files
4
+
5
+ # generated: {date}
6
+ # project: {project_name}
7
+ # project_key: {project_key}
8
+ # tracking_system: {tracking_system}
9
+ # story_location: {story_location}
10
+
11
+ # STATUS DEFINITIONS:
12
+ # ==================
13
+ # Epic Status:
14
+ # - backlog: Epic not yet started
15
+ # - in-progress: Epic actively being worked on
16
+ # - done: All stories in epic completed
17
+ #
18
+ # Story Status:
19
+ # - backlog: Story only exists in epic file
20
+ # - ready-for-dev: Story file created, ready for development
21
+ # - in-progress: Developer actively working on implementation
22
+ # - review: Implementation complete, ready for review
23
+ # - done: Story completed
24
+ #
25
+ # Retrospective Status:
26
+ # - optional: Can be completed but not required
27
+ # - done: Retrospective has been completed
28
+ #
29
+ # Action Item Status:
30
+ # - open: Committed during a retrospective, not yet addressed
31
+ # - in-progress: Actively being worked on
32
+ # - done: Completed
33
+ #
34
+ # WORKFLOW NOTES:
35
+ # ===============
36
+ # - Epic transitions to 'in-progress' automatically when its first story starts (via build's sprint sync)
37
+ # - Stories can be worked in parallel if team capacity allows
38
+ # - Developer typically creates the next story after the previous one is 'done' to incorporate learnings
39
+ # - Dev moves story to 'review', then runs code-review (fresh context, different LLM recommended)
40
+ # - Retrospective appends its action items to action_items; the status view surfaces open ones
41
+
42
+ # EXAMPLE STRUCTURE (your actual epics/stories will replace these):
43
+ # Timestamps use MM-DD-YYYY HH:MM.
44
+
45
+ generated: 05-06-2025 21:30
46
+ last_updated: 05-06-2025 21:30
47
+ project: My Awesome Project
48
+ project_key: NOKEY
49
+ tracking_system: file-system
50
+ story_location: "docs/stories"
51
+
52
+ development_status:
53
+ epic-1: backlog
54
+ 1-1-user-authentication: done
55
+ 1-2-account-management: ready-for-dev
56
+ 1-3-plant-data-model: backlog
57
+ 1-4-add-plant-manual: backlog
58
+ epic-1-retrospective: optional
59
+
60
+ epic-2: backlog
61
+ 2-1-personality-system: backlog
62
+ 2-2-chat-interface: backlog
63
+ 2-3-llm-integration: backlog
64
+ epic-2-retrospective: optional
65
+
66
+ # Action items committed during retrospectives (section created by the retrospective workflow)
67
+ action_items:
68
+ - epic: 1
69
+ action: "Add error-handling review to the code review checklist"
70
+ owner: "Charlie"
71
+ status: open