bmad-method 6.0.3 → 6.0.5-next.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 (271) hide show
  1. package/.augment/code_review_guidelines.yaml +2 -42
  2. package/.claude/skills/bmad-os-findings-triage/SKILL.md +6 -0
  3. package/.claude/skills/bmad-os-findings-triage/prompts/agent-prompt.md +104 -0
  4. package/.claude/skills/bmad-os-findings-triage/prompts/instructions.md +286 -0
  5. package/.claude/skills/bmad-os-review-pr/SKILL.md +1 -1
  6. package/.claude/skills/bmad-os-review-pr/prompts/instructions.md +63 -6
  7. package/.claude/skills/bmad-os-review-prompt/SKILL.md +177 -0
  8. package/.claude/skills/bmad-os-root-cause-analysis/SKILL.md +12 -0
  9. package/.claude/skills/bmad-os-root-cause-analysis/prompts/instructions.md +74 -0
  10. package/.github/ISSUE_TEMPLATE/config.yaml +1 -1
  11. package/.github/ISSUE_TEMPLATE/documentation.yaml +1 -1
  12. package/.github/workflows/publish.yaml +243 -0
  13. package/CHANGELOG.md +32 -0
  14. package/CONTRIBUTING.md +1 -1
  15. package/README.md +8 -8
  16. package/README_CN.md +121 -0
  17. package/docs/_STYLE_GUIDE.md +10 -10
  18. package/docs/explanation/brainstorming.md +1 -1
  19. package/docs/explanation/party-mode.md +1 -1
  20. package/docs/explanation/preventing-agent-conflicts.md +1 -1
  21. package/docs/explanation/project-context.md +15 -15
  22. package/docs/explanation/quick-flow.md +9 -9
  23. package/docs/how-to/established-projects.md +7 -7
  24. package/docs/how-to/get-answers-about-bmad.md +2 -2
  25. package/docs/how-to/install-bmad.md +16 -6
  26. package/docs/how-to/project-context.md +2 -2
  27. package/docs/how-to/quick-fixes.md +5 -5
  28. package/docs/how-to/shard-large-documents.md +1 -1
  29. package/docs/how-to/upgrade-to-v6.md +8 -5
  30. package/docs/index.md +2 -2
  31. package/docs/reference/agents.md +14 -14
  32. package/docs/reference/commands.md +64 -70
  33. package/docs/reference/testing.md +1 -1
  34. package/docs/reference/workflow-map.md +19 -19
  35. package/docs/tutorials/getting-started.md +34 -34
  36. package/docs/zh-cn/404.md +9 -0
  37. package/docs/zh-cn/_STYLE_GUIDE.md +370 -0
  38. package/docs/zh-cn/explanation/advanced-elicitation.md +62 -0
  39. package/docs/zh-cn/explanation/adversarial-review.md +71 -0
  40. package/docs/zh-cn/explanation/brainstorming.md +43 -0
  41. package/docs/zh-cn/explanation/established-projects-faq.md +60 -0
  42. package/docs/zh-cn/explanation/party-mode.md +79 -0
  43. package/docs/zh-cn/explanation/preventing-agent-conflicts.md +137 -0
  44. package/docs/zh-cn/explanation/project-context.md +176 -0
  45. package/docs/zh-cn/explanation/quick-flow.md +93 -0
  46. package/docs/zh-cn/explanation/why-solutioning-matters.md +90 -0
  47. package/docs/zh-cn/how-to/customize-bmad.md +182 -0
  48. package/docs/zh-cn/how-to/established-projects.md +134 -0
  49. package/docs/zh-cn/how-to/get-answers-about-bmad.md +144 -0
  50. package/docs/zh-cn/how-to/install-bmad.md +105 -0
  51. package/docs/zh-cn/how-to/non-interactive-installation.md +181 -0
  52. package/docs/zh-cn/how-to/project-context.md +152 -0
  53. package/docs/zh-cn/how-to/quick-fixes.md +140 -0
  54. package/docs/zh-cn/how-to/shard-large-documents.md +86 -0
  55. package/docs/zh-cn/how-to/upgrade-to-v6.md +120 -0
  56. package/docs/zh-cn/index.md +69 -0
  57. package/docs/zh-cn/reference/agents.md +41 -0
  58. package/docs/zh-cn/reference/commands.md +166 -0
  59. package/docs/zh-cn/reference/modules.md +94 -0
  60. package/docs/zh-cn/reference/testing.md +122 -0
  61. package/docs/zh-cn/reference/workflow-map.md +104 -0
  62. package/docs/zh-cn/roadmap.mdx +152 -0
  63. package/docs/zh-cn/tutorials/getting-started.md +300 -0
  64. package/package.json +1 -1
  65. package/src/bmm/agents/analyst.agent.yaml +1 -1
  66. package/src/bmm/agents/bmad-skill-manifest.yaml +39 -0
  67. package/src/bmm/agents/dev.agent.yaml +2 -2
  68. package/src/bmm/agents/pm.agent.yaml +1 -1
  69. package/src/bmm/agents/qa.agent.yaml +1 -1
  70. package/src/bmm/agents/quick-flow-solo-dev.agent.yaml +6 -2
  71. package/src/bmm/agents/sm.agent.yaml +4 -4
  72. package/src/bmm/agents/tech-writer/bmad-skill-manifest.yaml +3 -0
  73. package/src/bmm/agents/tech-writer/tech-writer.agent.yaml +1 -1
  74. package/src/bmm/module-help.csv +11 -10
  75. package/src/bmm/workflows/1-analysis/create-product-brief/bmad-skill-manifest.yaml +3 -0
  76. package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +1 -1
  77. package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +1 -1
  78. package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +1 -1
  79. package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +1 -1
  80. package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +1 -1
  81. package/src/bmm/workflows/1-analysis/research/bmad-skill-manifest.yaml +14 -0
  82. package/src/bmm/workflows/2-plan-workflows/create-prd/bmad-skill-manifest.yaml +14 -0
  83. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +1 -1
  84. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md +1 -1
  85. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md +1 -1
  86. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +1 -1
  87. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +1 -1
  88. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +1 -1
  89. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +1 -1
  90. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +1 -1
  91. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +1 -1
  92. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +1 -1
  93. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +1 -1
  94. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +1 -1
  95. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md +1 -1
  96. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md +1 -1
  97. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-02-review.md +1 -1
  98. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +1 -1
  99. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +1 -1
  100. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +1 -1
  101. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +1 -1
  102. package/src/bmm/workflows/2-plan-workflows/create-ux-design/bmad-skill-manifest.yaml +3 -0
  103. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +1 -1
  104. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +2 -2
  105. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +2 -2
  106. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +2 -2
  107. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +2 -2
  108. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +2 -2
  109. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +2 -2
  110. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +2 -2
  111. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +2 -2
  112. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +2 -2
  113. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +2 -2
  114. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +2 -2
  115. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +1 -1
  116. package/src/bmm/workflows/3-solutioning/check-implementation-readiness/bmad-skill-manifest.yaml +3 -0
  117. package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +1 -1
  118. package/src/bmm/workflows/3-solutioning/create-architecture/bmad-skill-manifest.yaml +3 -0
  119. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +2 -2
  120. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +2 -2
  121. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +2 -2
  122. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +2 -2
  123. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +2 -2
  124. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +2 -2
  125. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +1 -1
  126. package/src/bmm/workflows/3-solutioning/create-epics-and-stories/bmad-skill-manifest.yaml +3 -0
  127. package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md +1 -1
  128. package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +1 -1
  129. package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +1 -1
  130. package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +2 -2
  131. package/src/bmm/workflows/4-implementation/code-review/bmad-skill-manifest.yaml +3 -0
  132. package/src/bmm/workflows/4-implementation/code-review/discover-inputs.md +88 -0
  133. package/src/bmm/workflows/4-implementation/code-review/workflow.md +271 -0
  134. package/src/bmm/workflows/4-implementation/correct-course/bmad-skill-manifest.yaml +3 -0
  135. package/src/bmm/workflows/4-implementation/correct-course/checklist.md +1 -1
  136. package/src/bmm/workflows/4-implementation/correct-course/{instructions.md → workflow.md} +79 -12
  137. package/src/bmm/workflows/4-implementation/create-story/bmad-skill-manifest.yaml +3 -0
  138. package/src/bmm/workflows/4-implementation/create-story/checklist.md +9 -10
  139. package/src/bmm/workflows/4-implementation/create-story/discover-inputs.md +88 -0
  140. package/src/bmm/workflows/4-implementation/create-story/workflow.md +388 -0
  141. package/src/bmm/workflows/4-implementation/dev-story/bmad-skill-manifest.yaml +3 -0
  142. package/src/bmm/workflows/4-implementation/dev-story/{instructions.xml → workflow.md} +49 -2
  143. package/src/bmm/workflows/4-implementation/retrospective/bmad-skill-manifest.yaml +3 -0
  144. package/src/bmm/workflows/4-implementation/retrospective/{instructions.md → workflow.md} +64 -23
  145. package/src/bmm/workflows/4-implementation/sprint-planning/bmad-skill-manifest.yaml +3 -0
  146. package/src/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +1 -0
  147. package/src/bmm/workflows/4-implementation/sprint-planning/{instructions.md → workflow.md} +55 -10
  148. package/src/bmm/workflows/4-implementation/sprint-status/bmad-skill-manifest.yaml +3 -0
  149. package/src/bmm/workflows/4-implementation/sprint-status/{instructions.md → workflow.md} +45 -8
  150. package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/SKILL.md +6 -0
  151. package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/bmad-skill-manifest.yaml +1 -0
  152. package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-01-clarify-and-route.md +54 -0
  153. package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-02-plan.md +39 -0
  154. package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-03-implement.md +35 -0
  155. package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-04-review.md +55 -0
  156. package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-05-present.md +19 -0
  157. package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/tech-spec-template.md +90 -0
  158. package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/workflow.md +84 -0
  159. package/src/bmm/workflows/bmad-quick-flow/quick-dev/bmad-skill-manifest.yaml +3 -0
  160. package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +8 -14
  161. package/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +1 -1
  162. package/src/bmm/workflows/bmad-quick-flow/quick-spec/bmad-skill-manifest.yaml +3 -0
  163. package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +4 -6
  164. package/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +1 -1
  165. package/src/bmm/workflows/document-project/bmad-skill-manifest.yaml +3 -0
  166. package/src/bmm/workflows/document-project/instructions.md +5 -7
  167. package/src/bmm/workflows/document-project/workflow.md +39 -0
  168. package/src/bmm/workflows/document-project/workflows/deep-dive-instructions.md +0 -1
  169. package/src/bmm/workflows/document-project/workflows/deep-dive-workflow.md +42 -0
  170. package/src/bmm/workflows/document-project/workflows/full-scan-instructions.md +0 -1
  171. package/src/bmm/workflows/document-project/workflows/full-scan-workflow.md +42 -0
  172. package/src/bmm/workflows/generate-project-context/bmad-skill-manifest.yaml +3 -0
  173. package/src/bmm/workflows/generate-project-context/steps/step-02-generate.md +2 -2
  174. package/src/bmm/workflows/qa-generate-e2e-tests/bmad-skill-manifest.yaml +3 -0
  175. package/src/bmm/workflows/qa-generate-e2e-tests/checklist.md +1 -1
  176. package/src/bmm/workflows/qa-generate-e2e-tests/{instructions.md → workflow.md} +40 -7
  177. package/src/core/agents/bmad-master.agent.yaml +1 -1
  178. package/src/core/agents/bmad-skill-manifest.yaml +3 -0
  179. package/src/core/module-help.csv +3 -2
  180. package/src/core/module.yaml +1 -1
  181. package/src/core/tasks/bmad-help/SKILL.md +6 -0
  182. package/src/core/tasks/bmad-help/bmad-skill-manifest.yaml +1 -0
  183. package/src/core/tasks/{help.md → bmad-help/workflow.md} +6 -4
  184. package/src/core/tasks/bmad-review-adversarial-general/SKILL.md +6 -0
  185. package/src/core/tasks/bmad-review-adversarial-general/bmad-skill-manifest.yaml +1 -0
  186. package/src/core/tasks/bmad-review-adversarial-general/workflow.md +32 -0
  187. package/src/core/tasks/bmad-review-edge-case-hunter/SKILL.md +6 -0
  188. package/src/core/tasks/bmad-review-edge-case-hunter/bmad-skill-manifest.yaml +1 -0
  189. package/src/core/tasks/bmad-review-edge-case-hunter/workflow.md +62 -0
  190. package/src/core/tasks/bmad-skill-manifest.yaml +19 -0
  191. package/src/core/workflows/advanced-elicitation/bmad-skill-manifest.yaml +3 -0
  192. package/src/core/workflows/advanced-elicitation/workflow.md +138 -0
  193. package/src/core/workflows/brainstorming/bmad-skill-manifest.yaml +3 -0
  194. package/src/core/workflows/brainstorming/steps/step-01-session-setup.md +31 -18
  195. package/src/core/workflows/brainstorming/steps/step-01b-continue.md +1 -1
  196. package/src/core/workflows/brainstorming/steps/step-03-technique-execution.md +3 -3
  197. package/src/core/workflows/brainstorming/steps/step-04-idea-organization.md +2 -2
  198. package/src/core/workflows/brainstorming/workflow.md +5 -3
  199. package/src/core/workflows/party-mode/bmad-skill-manifest.yaml +3 -0
  200. package/src/core/workflows/party-mode/workflow.md +1 -1
  201. package/src/utility/agent-components/activation-steps.txt +2 -2
  202. package/src/utility/agent-components/handler-multi.txt +1 -2
  203. package/test/adversarial-review-tests/README.md +3 -3
  204. package/test/adversarial-review-tests/test-cases.yaml +2 -2
  205. package/test/fixtures/agent-schema/valid/menu/multiple-menu-items.agent.yaml +1 -1
  206. package/test/fixtures/agent-schema/valid/menu-commands/all-command-types.agent.yaml +1 -1
  207. package/test/fixtures/agent-schema/valid/menu-commands/multiple-commands.agent.yaml +1 -2
  208. package/test/fixtures/file-refs-csv/valid/bmm-style.csv +1 -1
  209. package/test/test-file-refs-csv.js +1 -1
  210. package/test/test-install-to-bmad.js +154 -0
  211. package/test/test-installation-components.js +1586 -2
  212. package/test/test-workflow-path-regex.js +88 -0
  213. package/tools/cli/installers/install-messages.yaml +1 -1
  214. package/tools/cli/installers/lib/core/installer.js +34 -1
  215. package/tools/cli/installers/lib/core/manifest-generator.js +332 -41
  216. package/tools/cli/installers/lib/ide/_base-ide.js +24 -15
  217. package/tools/cli/installers/lib/ide/_config-driven.js +547 -53
  218. package/tools/cli/installers/lib/ide/manager.js +26 -62
  219. package/tools/cli/installers/lib/ide/platform-codes.yaml +116 -29
  220. package/tools/cli/installers/lib/ide/shared/agent-command-generator.js +1 -0
  221. package/tools/cli/installers/lib/ide/shared/bmad-artifacts.js +7 -0
  222. package/tools/cli/installers/lib/ide/shared/path-utils.js +68 -3
  223. package/tools/cli/installers/lib/ide/shared/skill-manifest.js +90 -0
  224. package/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +2 -0
  225. package/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +6 -145
  226. package/tools/cli/installers/lib/ide/templates/agent-command-template.md +1 -1
  227. package/tools/cli/installers/lib/ide/templates/combined/default-workflow.md +1 -1
  228. package/tools/cli/installers/lib/ide/templates/combined/gemini-workflow-yaml.toml +1 -1
  229. package/tools/cli/installers/lib/ide/templates/combined/gemini-workflow.toml +1 -1
  230. package/tools/cli/installers/lib/ide/templates/combined/opencode-agent.md +1 -1
  231. package/tools/cli/installers/lib/ide/templates/combined/opencode-task.md +0 -1
  232. package/tools/cli/installers/lib/ide/templates/combined/opencode-tool.md +0 -1
  233. package/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md +0 -1
  234. package/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md +0 -1
  235. package/tools/cli/installers/lib/modules/manager.js +9 -132
  236. package/tools/cli/lib/agent/compiler.js +1 -10
  237. package/tools/cli/lib/agent-analyzer.js +2 -14
  238. package/tools/cli/lib/yaml-xml-builder.js +1 -18
  239. package/tools/docs/native-skills-migration-checklist.md +281 -0
  240. package/tools/platform-codes.yaml +1 -1
  241. package/tools/schema/agent.js +1 -3
  242. package/tools/validate-file-refs.js +2 -0
  243. package/website/astro.config.mjs +24 -3
  244. package/website/src/content/config.ts +2 -1
  245. package/website/src/content/i18n/zh-CN.json +28 -0
  246. package/src/bmm/workflows/4-implementation/code-review/instructions.xml +0 -227
  247. package/src/bmm/workflows/4-implementation/code-review/workflow.yaml +0 -43
  248. package/src/bmm/workflows/4-implementation/correct-course/workflow.yaml +0 -53
  249. package/src/bmm/workflows/4-implementation/create-story/instructions.xml +0 -346
  250. package/src/bmm/workflows/4-implementation/create-story/workflow.yaml +0 -52
  251. package/src/bmm/workflows/4-implementation/dev-story/workflow.yaml +0 -20
  252. package/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +0 -52
  253. package/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +0 -47
  254. package/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml +0 -25
  255. package/src/bmm/workflows/document-project/workflow.yaml +0 -22
  256. package/src/bmm/workflows/document-project/workflows/deep-dive.yaml +0 -31
  257. package/src/bmm/workflows/document-project/workflows/full-scan.yaml +0 -31
  258. package/src/bmm/workflows/qa-generate-e2e-tests/workflow.yaml +0 -42
  259. package/src/core/tasks/review-adversarial-general.xml +0 -49
  260. package/src/core/tasks/workflow.xml +0 -235
  261. package/src/core/workflows/advanced-elicitation/workflow.xml +0 -118
  262. package/src/utility/agent-components/handler-validate-workflow.txt +0 -7
  263. package/src/utility/agent-components/handler-workflow.txt +0 -10
  264. package/tools/cli/installers/lib/ide/codex.js +0 -440
  265. package/tools/cli/installers/lib/ide/github-copilot.js +0 -699
  266. package/tools/cli/installers/lib/ide/kilo.js +0 -269
  267. package/tools/cli/installers/lib/ide/rovodev.js +0 -257
  268. package/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md +0 -14
  269. package/tools/cli/installers/lib/ide/templates/combined/kiro-workflow-yaml.md +0 -15
  270. package/tools/cli/installers/lib/ide/templates/workflow-command-template.md +0 -13
  271. package/tools/cli/installers/lib/ide/templates/workflow-commander.md +0 -5
@@ -5,6 +5,12 @@ const crypto = require('node:crypto');
5
5
  const csv = require('csv-parse/sync');
6
6
  const { getSourcePath, getModulePath } = require('../../../lib/project-root');
7
7
  const prompts = require('../../../lib/prompts');
8
+ const {
9
+ loadSkillManifest: loadSkillManifestShared,
10
+ getCanonicalId: getCanonicalIdShared,
11
+ getArtifactType: getArtifactTypeShared,
12
+ getInstallToBmad: getInstallToBmadShared,
13
+ } = require('../ide/shared/skill-manifest');
8
14
 
9
15
  // Load package.json for version info
10
16
  const packageJson = require('../../../../../package.json');
@@ -15,6 +21,7 @@ const packageJson = require('../../../../../package.json');
15
21
  class ManifestGenerator {
16
22
  constructor() {
17
23
  this.workflows = [];
24
+ this.skills = [];
18
25
  this.agents = [];
19
26
  this.tasks = [];
20
27
  this.tools = [];
@@ -23,17 +30,35 @@ class ManifestGenerator {
23
30
  this.selectedIdes = [];
24
31
  }
25
32
 
33
+ /** Delegate to shared skill-manifest module */
34
+ async loadSkillManifest(dirPath) {
35
+ return loadSkillManifestShared(dirPath);
36
+ }
37
+
38
+ /** Delegate to shared skill-manifest module */
39
+ getCanonicalId(manifest, filename) {
40
+ return getCanonicalIdShared(manifest, filename);
41
+ }
42
+
43
+ /** Delegate to shared skill-manifest module */
44
+ getArtifactType(manifest, filename) {
45
+ return getArtifactTypeShared(manifest, filename);
46
+ }
47
+
48
+ /** Delegate to shared skill-manifest module */
49
+ getInstallToBmad(manifest, filename) {
50
+ return getInstallToBmadShared(manifest, filename);
51
+ }
52
+
26
53
  /**
27
- * Clean text for CSV output by normalizing whitespace and escaping quotes
54
+ * Clean text for CSV output by normalizing whitespace.
55
+ * Note: Quote escaping is handled by escapeCsv() at write time.
28
56
  * @param {string} text - Text to clean
29
- * @returns {string} Cleaned text safe for CSV
57
+ * @returns {string} Cleaned text
30
58
  */
31
59
  cleanForCSV(text) {
32
60
  if (!text) return '';
33
- return text
34
- .trim()
35
- .replaceAll(/\s+/g, ' ') // Normalize all whitespace (including newlines) to single space
36
- .replaceAll('"', '""'); // Escape quotes for CSV
61
+ return text.trim().replaceAll(/\s+/g, ' '); // Normalize all whitespace (including newlines) to single space
37
62
  }
38
63
 
39
64
  /**
@@ -80,6 +105,12 @@ class ManifestGenerator {
80
105
  // Filter out any undefined/null values from IDE list
81
106
  this.selectedIdes = resolvedIdes.filter((ide) => ide && typeof ide === 'string');
82
107
 
108
+ // Reset files list (defensive: prevent stale data if instance is reused)
109
+ this.files = [];
110
+
111
+ // Collect skills first (populates skillClaimedDirs before legacy collectors run)
112
+ await this.collectSkills();
113
+
83
114
  // Collect workflow data
84
115
  await this.collectWorkflows(selectedModules);
85
116
 
@@ -96,6 +127,7 @@ class ManifestGenerator {
96
127
  const manifestFiles = [
97
128
  await this.writeMainManifest(cfgDir),
98
129
  await this.writeWorkflowManifest(cfgDir),
130
+ await this.writeSkillManifest(cfgDir),
99
131
  await this.writeAgentManifest(cfgDir),
100
132
  await this.writeTaskManifest(cfgDir),
101
133
  await this.writeToolManifest(cfgDir),
@@ -103,6 +135,7 @@ class ManifestGenerator {
103
135
  ];
104
136
 
105
137
  return {
138
+ skills: this.skills.length,
106
139
  workflows: this.workflows.length,
107
140
  agents: this.agents.length,
108
141
  tasks: this.tasks.length,
@@ -112,6 +145,169 @@ class ManifestGenerator {
112
145
  };
113
146
  }
114
147
 
148
+ /**
149
+ * Recursively walk a module directory tree, collecting skill directories.
150
+ * A skill directory is one that contains both a bmad-skill-manifest.yaml with
151
+ * type: skill AND a SKILL.md file with name/description frontmatter.
152
+ * Populates this.skills[] and this.skillClaimedDirs (Set of absolute paths).
153
+ */
154
+ async collectSkills() {
155
+ this.skills = [];
156
+ this.skillClaimedDirs = new Set();
157
+ const debug = process.env.BMAD_DEBUG_MANIFEST === 'true';
158
+
159
+ for (const moduleName of this.updatedModules) {
160
+ const modulePath = path.join(this.bmadDir, moduleName);
161
+ if (!(await fs.pathExists(modulePath))) continue;
162
+
163
+ // Recursive walk skipping . and _ prefixed dirs
164
+ const walk = async (dir) => {
165
+ let entries;
166
+ try {
167
+ entries = await fs.readdir(dir, { withFileTypes: true });
168
+ } catch {
169
+ return;
170
+ }
171
+
172
+ // Check this directory for skill manifest
173
+ const manifest = await this.loadSkillManifest(dir);
174
+
175
+ // Determine if this directory is a skill (type: skill in manifest)
176
+ const skillFile = 'SKILL.md';
177
+ const artifactType = this.getArtifactType(manifest, skillFile);
178
+
179
+ if (artifactType === 'skill') {
180
+ const skillMdPath = path.join(dir, 'SKILL.md');
181
+ const dirName = path.basename(dir);
182
+
183
+ // Validate and parse SKILL.md
184
+ const skillMeta = await this.parseSkillMd(skillMdPath, dir, dirName, debug);
185
+
186
+ if (skillMeta) {
187
+ // Build path relative from module root (points to SKILL.md — the permanent entrypoint)
188
+ const relativePath = path.relative(modulePath, dir).split(path.sep).join('/');
189
+ const installPath = relativePath
190
+ ? `${this.bmadFolderName}/${moduleName}/${relativePath}/${skillFile}`
191
+ : `${this.bmadFolderName}/${moduleName}/${skillFile}`;
192
+
193
+ // Skills derive canonicalId from directory name — never from manifest
194
+ if (manifest && manifest.__single && manifest.__single.canonicalId) {
195
+ console.warn(
196
+ `Warning: Skill manifest at ${dir}/bmad-skill-manifest.yaml contains canonicalId — this field is ignored for skills (directory name is the canonical ID)`,
197
+ );
198
+ }
199
+ const canonicalId = dirName;
200
+
201
+ this.skills.push({
202
+ name: skillMeta.name,
203
+ description: this.cleanForCSV(skillMeta.description),
204
+ module: moduleName,
205
+ path: installPath,
206
+ canonicalId,
207
+ install_to_bmad: this.getInstallToBmad(manifest, skillFile),
208
+ });
209
+
210
+ // Add to files list
211
+ this.files.push({
212
+ type: 'skill',
213
+ name: skillMeta.name,
214
+ module: moduleName,
215
+ path: installPath,
216
+ });
217
+
218
+ this.skillClaimedDirs.add(dir);
219
+
220
+ if (debug) {
221
+ console.log(`[DEBUG] collectSkills: claimed skill "${skillMeta.name}" as ${canonicalId} at ${dir}`);
222
+ }
223
+ }
224
+ }
225
+
226
+ // Warn if manifest says type:skill but directory was not claimed
227
+ if (manifest && !this.skillClaimedDirs.has(dir)) {
228
+ let hasSkillType = false;
229
+ if (manifest.__single) {
230
+ hasSkillType = manifest.__single.type === 'skill';
231
+ } else {
232
+ for (const key of Object.keys(manifest)) {
233
+ if (manifest[key]?.type === 'skill') {
234
+ hasSkillType = true;
235
+ break;
236
+ }
237
+ }
238
+ }
239
+ if (hasSkillType && debug) {
240
+ console.log(`[DEBUG] collectSkills: dir has type:skill manifest but failed validation: ${dir}`);
241
+ }
242
+ }
243
+
244
+ // Recurse into subdirectories
245
+ for (const entry of entries) {
246
+ if (!entry.isDirectory()) continue;
247
+ if (entry.name.startsWith('.') || entry.name.startsWith('_')) continue;
248
+ await walk(path.join(dir, entry.name));
249
+ }
250
+ };
251
+
252
+ await walk(modulePath);
253
+ }
254
+
255
+ if (debug) {
256
+ console.log(`[DEBUG] collectSkills: total skills found: ${this.skills.length}, claimed dirs: ${this.skillClaimedDirs.size}`);
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Parse and validate SKILL.md for a skill directory.
262
+ * Returns parsed frontmatter object with name/description, or null if invalid.
263
+ * @param {string} skillMdPath - Absolute path to SKILL.md
264
+ * @param {string} dir - Skill directory path (for error messages)
265
+ * @param {string} dirName - Expected name (must match frontmatter name)
266
+ * @param {boolean} debug - Whether to emit debug-level messages
267
+ * @returns {Promise<Object|null>} Parsed frontmatter or null
268
+ */
269
+ async parseSkillMd(skillMdPath, dir, dirName, debug = false) {
270
+ if (!(await fs.pathExists(skillMdPath))) {
271
+ if (debug) console.log(`[DEBUG] parseSkillMd: "${dir}" is missing SKILL.md — skipping`);
272
+ return null;
273
+ }
274
+
275
+ try {
276
+ const rawContent = await fs.readFile(skillMdPath, 'utf8');
277
+ const content = rawContent.replaceAll('\r\n', '\n').replaceAll('\r', '\n');
278
+
279
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
280
+ if (frontmatterMatch) {
281
+ const skillMeta = yaml.parse(frontmatterMatch[1]);
282
+
283
+ if (
284
+ !skillMeta ||
285
+ typeof skillMeta !== 'object' ||
286
+ typeof skillMeta.name !== 'string' ||
287
+ typeof skillMeta.description !== 'string' ||
288
+ !skillMeta.name ||
289
+ !skillMeta.description
290
+ ) {
291
+ if (debug) console.log(`[DEBUG] parseSkillMd: SKILL.md in "${dir}" is missing name or description (or wrong type) — skipping`);
292
+ return null;
293
+ }
294
+
295
+ if (skillMeta.name !== dirName) {
296
+ console.error(`Error: SKILL.md name "${skillMeta.name}" does not match directory name "${dirName}" — skipping`);
297
+ return null;
298
+ }
299
+
300
+ return skillMeta;
301
+ }
302
+
303
+ if (debug) console.log(`[DEBUG] parseSkillMd: SKILL.md in "${dir}" has no frontmatter — skipping`);
304
+ return null;
305
+ } catch (error) {
306
+ if (debug) console.log(`[DEBUG] parseSkillMd: failed to parse SKILL.md in "${dir}": ${error.message} — skipping`);
307
+ return null;
308
+ }
309
+ }
310
+
115
311
  /**
116
312
  * Collect all workflows from core and selected modules
117
313
  * Scans the INSTALLED bmad directory, not the source
@@ -126,16 +322,20 @@ class ManifestGenerator {
126
322
  if (await fs.pathExists(modulePath)) {
127
323
  const moduleWorkflows = await this.getWorkflowsFromPath(modulePath, moduleName);
128
324
  this.workflows.push(...moduleWorkflows);
325
+
326
+ // Also scan tasks/ for type:skill entries (skills can live anywhere)
327
+ const tasksSkills = await this.getWorkflowsFromPath(modulePath, moduleName, 'tasks');
328
+ this.workflows.push(...tasksSkills);
129
329
  }
130
330
  }
131
331
  }
132
332
 
133
333
  /**
134
- * Recursively find and parse workflow.yaml and workflow.md files
334
+ * Recursively find and parse workflow.md files
135
335
  */
136
- async getWorkflowsFromPath(basePath, moduleName) {
336
+ async getWorkflowsFromPath(basePath, moduleName, subDir = 'workflows') {
137
337
  const workflows = [];
138
- const workflowsPath = path.join(basePath, 'workflows');
338
+ const workflowsPath = path.join(basePath, subDir);
139
339
  const debug = process.env.BMAD_DEBUG_MANIFEST === 'true';
140
340
 
141
341
  if (debug) {
@@ -149,22 +349,25 @@ class ManifestGenerator {
149
349
  return workflows;
150
350
  }
151
351
 
152
- // Recursively find workflow.yaml files
352
+ // Recursively find workflow.md files
153
353
  const findWorkflows = async (dir, relativePath = '') => {
354
+ // Skip directories already claimed as skills
355
+ if (this.skillClaimedDirs && this.skillClaimedDirs.has(dir)) return;
356
+
154
357
  const entries = await fs.readdir(dir, { withFileTypes: true });
358
+ // Load skill manifest for this directory (if present)
359
+ const skillManifest = await this.loadSkillManifest(dir);
155
360
 
156
361
  for (const entry of entries) {
157
362
  const fullPath = path.join(dir, entry.name);
158
363
 
159
364
  if (entry.isDirectory()) {
365
+ // Skip directories claimed by collectSkills
366
+ if (this.skillClaimedDirs && this.skillClaimedDirs.has(fullPath)) continue;
160
367
  // Recurse into subdirectories
161
368
  const newRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
162
369
  await findWorkflows(fullPath, newRelativePath);
163
- } else if (
164
- entry.name === 'workflow.yaml' ||
165
- entry.name === 'workflow.md' ||
166
- (entry.name.startsWith('workflow-') && entry.name.endsWith('.md'))
167
- ) {
370
+ } else if (entry.name === 'workflow.md' || (entry.name.startsWith('workflow-') && entry.name.endsWith('.md'))) {
168
371
  // Parse workflow file (both YAML and MD formats)
169
372
  if (debug) {
170
373
  console.log(`[DEBUG] Found workflow file: ${fullPath}`);
@@ -174,21 +377,15 @@ class ManifestGenerator {
174
377
  const rawContent = await fs.readFile(fullPath, 'utf8');
175
378
  const content = rawContent.replaceAll('\r\n', '\n').replaceAll('\r', '\n');
176
379
 
177
- let workflow;
178
- if (entry.name === 'workflow.yaml') {
179
- // Parse YAML workflow
180
- workflow = yaml.parse(content);
181
- } else {
182
- // Parse MD workflow with YAML frontmatter
183
- const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
184
- if (!frontmatterMatch) {
185
- if (debug) {
186
- console.log(`[DEBUG] Skipped (no frontmatter): ${fullPath}`);
187
- }
188
- continue; // Skip MD files without frontmatter
380
+ // Parse MD workflow with YAML frontmatter
381
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
382
+ if (!frontmatterMatch) {
383
+ if (debug) {
384
+ console.log(`[DEBUG] Skipped (no frontmatter): ${fullPath}`);
189
385
  }
190
- workflow = yaml.parse(frontmatterMatch[1]);
386
+ continue; // Skip MD files without frontmatter
191
387
  }
388
+ const workflow = yaml.parse(frontmatterMatch[1]);
192
389
 
193
390
  if (debug) {
194
391
  console.log(`[DEBUG] Parsed: name="${workflow.name}", description=${workflow.description ? 'OK' : 'MISSING'}`);
@@ -214,8 +411,8 @@ class ManifestGenerator {
214
411
  // Build relative path for installation
215
412
  const installPath =
216
413
  moduleName === 'core'
217
- ? `${this.bmadFolderName}/core/workflows/${relativePath}/${entry.name}`
218
- : `${this.bmadFolderName}/${moduleName}/workflows/${relativePath}/${entry.name}`;
414
+ ? `${this.bmadFolderName}/core/${subDir}/${relativePath}/${entry.name}`
415
+ : `${this.bmadFolderName}/${moduleName}/${subDir}/${relativePath}/${entry.name}`;
219
416
 
220
417
  // Workflows with standalone: false are filtered out above
221
418
  workflows.push({
@@ -223,6 +420,7 @@ class ManifestGenerator {
223
420
  description: this.cleanForCSV(workflow.description),
224
421
  module: moduleName,
225
422
  path: installPath,
423
+ canonicalId: this.getCanonicalId(skillManifest, entry.name),
226
424
  });
227
425
 
228
426
  // Add to files list
@@ -294,13 +492,19 @@ class ManifestGenerator {
294
492
  * Only includes compiled .md files (not .agent.yaml source files)
295
493
  */
296
494
  async getAgentsFromDir(dirPath, moduleName, relativePath = '') {
495
+ // Skip directories claimed by collectSkills
496
+ if (this.skillClaimedDirs && this.skillClaimedDirs.has(dirPath)) return [];
297
497
  const agents = [];
298
498
  const entries = await fs.readdir(dirPath, { withFileTypes: true });
499
+ // Load skill manifest for this directory (if present)
500
+ const skillManifest = await this.loadSkillManifest(dirPath);
299
501
 
300
502
  for (const entry of entries) {
301
503
  const fullPath = path.join(dirPath, entry.name);
302
504
 
303
505
  if (entry.isDirectory()) {
506
+ // Skip directories claimed by collectSkills
507
+ if (this.skillClaimedDirs && this.skillClaimedDirs.has(fullPath)) continue;
304
508
  // Recurse into subdirectories
305
509
  const newRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
306
510
  const subDirAgents = await this.getAgentsFromDir(fullPath, moduleName, newRelativePath);
@@ -351,6 +555,7 @@ class ManifestGenerator {
351
555
  principles: principlesMatch ? this.cleanForCSV(principlesMatch[1]) : '',
352
556
  module: moduleName,
353
557
  path: installPath,
558
+ canonicalId: this.getCanonicalId(skillManifest, entry.name),
354
559
  });
355
560
 
356
561
  // Add to files list
@@ -388,8 +593,12 @@ class ManifestGenerator {
388
593
  * Get tasks from a directory
389
594
  */
390
595
  async getTasksFromDir(dirPath, moduleName) {
596
+ // Skip directories claimed by collectSkills
597
+ if (this.skillClaimedDirs && this.skillClaimedDirs.has(dirPath)) return [];
391
598
  const tasks = [];
392
599
  const files = await fs.readdir(dirPath);
600
+ // Load skill manifest for this directory (if present)
601
+ const skillManifest = await this.loadSkillManifest(dirPath);
393
602
 
394
603
  for (const file of files) {
395
604
  // Check for both .xml and .md files
@@ -449,6 +658,7 @@ class ManifestGenerator {
449
658
  module: moduleName,
450
659
  path: installPath,
451
660
  standalone: standalone,
661
+ canonicalId: this.getCanonicalId(skillManifest, file),
452
662
  });
453
663
 
454
664
  // Add to files list
@@ -486,8 +696,12 @@ class ManifestGenerator {
486
696
  * Get tools from a directory
487
697
  */
488
698
  async getToolsFromDir(dirPath, moduleName) {
699
+ // Skip directories claimed by collectSkills
700
+ if (this.skillClaimedDirs && this.skillClaimedDirs.has(dirPath)) return [];
489
701
  const tools = [];
490
702
  const files = await fs.readdir(dirPath);
703
+ // Load skill manifest for this directory (if present)
704
+ const skillManifest = await this.loadSkillManifest(dirPath);
491
705
 
492
706
  for (const file of files) {
493
707
  // Check for both .xml and .md files
@@ -547,6 +761,7 @@ class ManifestGenerator {
547
761
  module: moduleName,
548
762
  path: installPath,
549
763
  standalone: standalone,
764
+ canonicalId: this.getCanonicalId(skillManifest, file),
550
765
  });
551
766
 
552
767
  // Add to files list
@@ -737,8 +952,8 @@ class ManifestGenerator {
737
952
  const csvPath = path.join(cfgDir, 'workflow-manifest.csv');
738
953
  const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`;
739
954
 
740
- // Create CSV header - standalone column removed, everything is canonicalized to 4 columns
741
- let csv = 'name,description,module,path\n';
955
+ // Create CSV header - standalone column removed, canonicalId added as optional column
956
+ let csv = 'name,description,module,path,canonicalId\n';
742
957
 
743
958
  // Build workflows map from discovered workflows only
744
959
  // Old entries are NOT preserved - the manifest reflects what actually exists on disk
@@ -752,12 +967,19 @@ class ManifestGenerator {
752
967
  description: workflow.description,
753
968
  module: workflow.module,
754
969
  path: workflow.path,
970
+ canonicalId: workflow.canonicalId || '',
755
971
  });
756
972
  }
757
973
 
758
974
  // Write all workflows
759
975
  for (const [, value] of allWorkflows) {
760
- const row = [escapeCsv(value.name), escapeCsv(value.description), escapeCsv(value.module), escapeCsv(value.path)].join(',');
976
+ const row = [
977
+ escapeCsv(value.name),
978
+ escapeCsv(value.description),
979
+ escapeCsv(value.module),
980
+ escapeCsv(value.path),
981
+ escapeCsv(value.canonicalId),
982
+ ].join(',');
761
983
  csv += row + '\n';
762
984
  }
763
985
 
@@ -765,6 +987,32 @@ class ManifestGenerator {
765
987
  return csvPath;
766
988
  }
767
989
 
990
+ /**
991
+ * Write skill manifest CSV
992
+ * @returns {string} Path to the manifest file
993
+ */
994
+ async writeSkillManifest(cfgDir) {
995
+ const csvPath = path.join(cfgDir, 'skill-manifest.csv');
996
+ const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`;
997
+
998
+ let csvContent = 'canonicalId,name,description,module,path,install_to_bmad\n';
999
+
1000
+ for (const skill of this.skills) {
1001
+ const row = [
1002
+ escapeCsv(skill.canonicalId),
1003
+ escapeCsv(skill.name),
1004
+ escapeCsv(skill.description),
1005
+ escapeCsv(skill.module),
1006
+ escapeCsv(skill.path),
1007
+ escapeCsv(skill.install_to_bmad),
1008
+ ].join(',');
1009
+ csvContent += row + '\n';
1010
+ }
1011
+
1012
+ await fs.writeFile(csvPath, csvContent);
1013
+ return csvPath;
1014
+ }
1015
+
768
1016
  /**
769
1017
  * Write agent manifest CSV
770
1018
  * @returns {string} Path to the manifest file
@@ -786,8 +1034,8 @@ class ManifestGenerator {
786
1034
  }
787
1035
  }
788
1036
 
789
- // Create CSV header with persona fields
790
- let csvContent = 'name,displayName,title,icon,capabilities,role,identity,communicationStyle,principles,module,path\n';
1037
+ // Create CSV header with persona fields and canonicalId
1038
+ let csvContent = 'name,displayName,title,icon,capabilities,role,identity,communicationStyle,principles,module,path,canonicalId\n';
791
1039
 
792
1040
  // Combine existing and new agents, preferring new data for duplicates
793
1041
  const allAgents = new Map();
@@ -812,6 +1060,7 @@ class ManifestGenerator {
812
1060
  principles: agent.principles,
813
1061
  module: agent.module,
814
1062
  path: agent.path,
1063
+ canonicalId: agent.canonicalId || '',
815
1064
  });
816
1065
  }
817
1066
 
@@ -829,6 +1078,7 @@ class ManifestGenerator {
829
1078
  escapeCsv(record.principles),
830
1079
  escapeCsv(record.module),
831
1080
  escapeCsv(record.path),
1081
+ escapeCsv(record.canonicalId),
832
1082
  ].join(',');
833
1083
  csvContent += row + '\n';
834
1084
  }
@@ -858,8 +1108,8 @@ class ManifestGenerator {
858
1108
  }
859
1109
  }
860
1110
 
861
- // Create CSV header with standalone column
862
- let csvContent = 'name,displayName,description,module,path,standalone\n';
1111
+ // Create CSV header with standalone and canonicalId columns
1112
+ let csvContent = 'name,displayName,description,module,path,standalone,canonicalId\n';
863
1113
 
864
1114
  // Combine existing and new tasks
865
1115
  const allTasks = new Map();
@@ -879,6 +1129,7 @@ class ManifestGenerator {
879
1129
  module: task.module,
880
1130
  path: task.path,
881
1131
  standalone: task.standalone,
1132
+ canonicalId: task.canonicalId || '',
882
1133
  });
883
1134
  }
884
1135
 
@@ -891,6 +1142,7 @@ class ManifestGenerator {
891
1142
  escapeCsv(record.module),
892
1143
  escapeCsv(record.path),
893
1144
  escapeCsv(record.standalone),
1145
+ escapeCsv(record.canonicalId),
894
1146
  ].join(',');
895
1147
  csvContent += row + '\n';
896
1148
  }
@@ -920,8 +1172,8 @@ class ManifestGenerator {
920
1172
  }
921
1173
  }
922
1174
 
923
- // Create CSV header with standalone column
924
- let csvContent = 'name,displayName,description,module,path,standalone\n';
1175
+ // Create CSV header with standalone and canonicalId columns
1176
+ let csvContent = 'name,displayName,description,module,path,standalone,canonicalId\n';
925
1177
 
926
1178
  // Combine existing and new tools
927
1179
  const allTools = new Map();
@@ -941,6 +1193,7 @@ class ManifestGenerator {
941
1193
  module: tool.module,
942
1194
  path: tool.path,
943
1195
  standalone: tool.standalone,
1196
+ canonicalId: tool.canonicalId || '',
944
1197
  });
945
1198
  }
946
1199
 
@@ -953,6 +1206,7 @@ class ManifestGenerator {
953
1206
  escapeCsv(record.module),
954
1207
  escapeCsv(record.path),
955
1208
  escapeCsv(record.standalone),
1209
+ escapeCsv(record.canonicalId),
956
1210
  ].join(',');
957
1211
  csvContent += row + '\n';
958
1212
  }
@@ -1067,8 +1321,14 @@ class ManifestGenerator {
1067
1321
  const hasTasks = await fs.pathExists(path.join(modulePath, 'tasks'));
1068
1322
  const hasTools = await fs.pathExists(path.join(modulePath, 'tools'));
1069
1323
 
1070
- // If it has any of these directories, it's likely a module
1071
- if (hasAgents || hasWorkflows || hasTasks || hasTools) {
1324
+ // Check for skill-only modules: recursive scan for bmad-skill-manifest.yaml with type: skill
1325
+ let hasSkills = false;
1326
+ if (!hasAgents && !hasWorkflows && !hasTasks && !hasTools) {
1327
+ hasSkills = await this._hasSkillManifestRecursive(modulePath);
1328
+ }
1329
+
1330
+ // If it has any of these directories or skill manifests, it's likely a module
1331
+ if (hasAgents || hasWorkflows || hasTasks || hasTools || hasSkills) {
1072
1332
  modules.push(entry.name);
1073
1333
  }
1074
1334
  }
@@ -1078,6 +1338,37 @@ class ManifestGenerator {
1078
1338
 
1079
1339
  return modules;
1080
1340
  }
1341
+
1342
+ /**
1343
+ * Recursively check if a directory tree contains a bmad-skill-manifest.yaml with type: skill.
1344
+ * Skips directories starting with . or _.
1345
+ * @param {string} dir - Directory to search
1346
+ * @returns {boolean} True if a skill manifest is found
1347
+ */
1348
+ async _hasSkillManifestRecursive(dir) {
1349
+ let entries;
1350
+ try {
1351
+ entries = await fs.readdir(dir, { withFileTypes: true });
1352
+ } catch {
1353
+ return false;
1354
+ }
1355
+
1356
+ // Check for manifest in this directory
1357
+ const manifest = await this.loadSkillManifest(dir);
1358
+ if (manifest) {
1359
+ const type = this.getArtifactType(manifest, 'workflow.md');
1360
+ if (type === 'skill') return true;
1361
+ }
1362
+
1363
+ // Recurse into subdirectories
1364
+ for (const entry of entries) {
1365
+ if (!entry.isDirectory()) continue;
1366
+ if (entry.name.startsWith('.') || entry.name.startsWith('_')) continue;
1367
+ if (await this._hasSkillManifestRecursive(path.join(dir, entry.name))) return true;
1368
+ }
1369
+
1370
+ return false;
1371
+ }
1081
1372
  }
1082
1373
 
1083
1374
  module.exports = { ManifestGenerator };