ma-agents 3.12.3 → 3.13.1

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 (257) hide show
  1. package/bin/cli.js +67 -13
  2. package/docs/architecture.md +18 -0
  3. package/lib/bmad-cache/bmb/.claude-plugin/marketplace.json +1 -1
  4. package/lib/bmad-cache/bmb/_git_preserved/hooks/commit-msg.sample +52 -2
  5. package/lib/bmad-cache/bmb/_git_preserved/hooks/fsmonitor-watchman.sample +2 -8
  6. package/lib/bmad-cache/bmb/_git_preserved/index +0 -0
  7. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-8f8b045fef5af6911495cf3b2a89f1ed75e120f7.idx +0 -0
  8. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-8f8b045fef5af6911495cf3b2a89f1ed75e120f7.pack +0 -0
  9. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-8f8b045fef5af6911495cf3b2a89f1ed75e120f7.rev +0 -0
  10. package/lib/bmad-cache/bmb/_git_preserved/packed-refs +1 -1
  11. package/lib/bmad-cache/bmb/_git_preserved/refs/heads/main +1 -1
  12. package/lib/bmad-cache/bmb/_git_preserved/shallow +1 -1
  13. package/lib/bmad-cache/bmb/package-lock.json +2 -2
  14. package/lib/bmad-cache/bmb/package.json +1 -1
  15. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/assets/module-help.csv +1 -1
  16. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/scripts/merge-config.py +33 -0
  17. package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/scripts/merge-help-csv.py +28 -0
  18. package/lib/bmad-cache/bmb/samples/sample-module-setup/assets/module-help.csv +1 -1
  19. package/lib/bmad-cache/bmb/samples/sample-module-setup/scripts/cleanup-legacy.py +28 -0
  20. package/lib/bmad-cache/bmb/samples/sample-module-setup/scripts/merge-config.py +33 -0
  21. package/lib/bmad-cache/bmb/samples/sample-module-setup/scripts/merge-help-csv.py +28 -0
  22. package/lib/bmad-cache/bmb/skills/bmad-bmb-setup/assets/module-help.csv +1 -1
  23. package/lib/bmad-cache/bmb/skills/bmad-bmb-setup/scripts/cleanup-legacy.py +28 -0
  24. package/lib/bmad-cache/bmb/skills/bmad-bmb-setup/scripts/merge-config.py +33 -0
  25. package/lib/bmad-cache/bmb/skills/bmad-bmb-setup/scripts/merge-help-csv.py +28 -0
  26. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/assets/Dockerfile +29 -0
  27. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/docker_setup.py +115 -0
  28. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/generate_report.py +184 -0
  29. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/pty_runner.py +171 -0
  30. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/run_evals.py +492 -0
  31. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/run_triggers.py +366 -0
  32. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/utils.py +260 -0
  33. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/setup-skill-template/assets/module-help.csv +1 -1
  34. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/setup-skill-template/scripts/cleanup-legacy.py +28 -0
  35. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/setup-skill-template/scripts/merge-config.py +33 -0
  36. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/setup-skill-template/scripts/merge-help-csv.py +28 -0
  37. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/standalone-module-template/merge-config.py +33 -0
  38. package/lib/bmad-cache/bmb/skills/bmad-module-builder/assets/standalone-module-template/merge-help-csv.py +28 -0
  39. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/tests/test-validate-module.py +74 -1
  40. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/validate-module.py +24 -13
  41. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/assets/sample-customize-product-brief.toml +48 -33
  42. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/extract-report-json.py +287 -0
  43. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/generate-html-report.py +57 -8
  44. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/prepass-prompt-metrics.py +7 -7
  45. package/lib/bmad-cache/bmb/skills/module-help.csv +1 -1
  46. package/lib/bmad-cache/bmb/website/public/img/eval-test-types.png +0 -0
  47. package/lib/bmad-cache/cache-manifest.json +17 -18
  48. package/lib/bmad-cache/cis/_git_preserved/hooks/commit-msg.sample +52 -2
  49. package/lib/bmad-cache/cis/_git_preserved/hooks/fsmonitor-watchman.sample +2 -8
  50. package/lib/bmad-cache/cis/_git_preserved/index +0 -0
  51. package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-18c8290560a98bcb7bf0676e6cc9b2ac5ca2823e.idx +0 -0
  52. package/lib/bmad-cache/cis/_git_preserved/objects/pack/{pack-42ffc048f54e58ce94c6331bc6be97ebbb7936f2.pack → pack-18c8290560a98bcb7bf0676e6cc9b2ac5ca2823e.pack} +0 -0
  53. package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-18c8290560a98bcb7bf0676e6cc9b2ac5ca2823e.rev +0 -0
  54. package/lib/bmad-cache/cis/_git_preserved/packed-refs +1 -1
  55. package/lib/bmad-cache/cis/_git_preserved/refs/heads/main +1 -1
  56. package/lib/bmad-cache/cis/_git_preserved/refs/tags/v0.2.1 +1 -0
  57. package/lib/bmad-cache/cis/_git_preserved/shallow +1 -1
  58. package/lib/bmad-cache/cis/package-lock.json +2 -2
  59. package/lib/bmad-cache/cis/package.json +1 -1
  60. package/lib/bmad-cache/cis/src/module-help.csv +1 -1
  61. package/lib/bmad-cache/gds/.claude-plugin/marketplace.json +4 -7
  62. package/lib/bmad-cache/gds/README.md +3 -1
  63. package/lib/bmad-cache/gds/_git_preserved/hooks/commit-msg.sample +52 -2
  64. package/lib/bmad-cache/gds/_git_preserved/hooks/fsmonitor-watchman.sample +2 -8
  65. package/lib/bmad-cache/gds/_git_preserved/index +0 -0
  66. package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-dcb7c556d9bb6b6b70d2301e094eaac6d7300552.idx +0 -0
  67. package/lib/bmad-cache/gds/_git_preserved/objects/pack/{pack-9427a146a90c00bb542cba038874bf9671ba4dc0.pack → pack-dcb7c556d9bb6b6b70d2301e094eaac6d7300552.pack} +0 -0
  68. package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-dcb7c556d9bb6b6b70d2301e094eaac6d7300552.rev +0 -0
  69. package/lib/bmad-cache/gds/_git_preserved/packed-refs +1 -1
  70. package/lib/bmad-cache/gds/_git_preserved/refs/heads/main +1 -1
  71. package/lib/bmad-cache/gds/_git_preserved/shallow +1 -1
  72. package/lib/bmad-cache/gds/package.json +1 -1
  73. package/lib/bmad-cache/gds/src/agents/gds-agent-game-designer/customize.toml +5 -5
  74. package/lib/bmad-cache/gds/src/agents/gds-agent-game-dev/customize.toml +5 -5
  75. package/lib/bmad-cache/gds/src/agents/gds-agent-game-solo-dev/customize.toml +0 -5
  76. package/lib/bmad-cache/gds/src/module-help.csv +6 -12
  77. package/lib/bmad-cache/gds/src/module.yaml +1 -1
  78. package/lib/bmad-cache/gds/src/workflows/1-preproduction/gds-create-game-brief/customize.toml +97 -22
  79. package/lib/bmad-cache/gds/src/workflows/2-design/gds-gdd/assets/validation-report-template.html +190 -0
  80. package/lib/bmad-cache/gds/src/workflows/2-design/gds-gdd/customize.toml +99 -0
  81. package/lib/bmad-cache/gds/src/workflows/2-design/gds-gdd/scripts/render-validation-html.py +290 -0
  82. package/lib/bmad-cache/gds/src/workflows/2-design/gds-prd/assets/validation-report-template.html +190 -0
  83. package/lib/bmad-cache/gds/src/workflows/2-design/gds-prd/customize.toml +84 -0
  84. package/lib/bmad-cache/gds/src/workflows/2-design/gds-ux/assets/validation-report-template.html +319 -0
  85. package/lib/bmad-cache/gds/src/workflows/2-design/gds-ux/customize.toml +101 -0
  86. package/lib/bmad-cache/gds/src/workflows/3-technical/gds-game-architecture/architecture-patterns.yaml +1 -0
  87. package/lib/bmad-cache/gds/src/workflows/3-technical/gds-game-architecture/decision-catalog.yaml +88 -0
  88. package/lib/bmad-cache/gds/src/workflows/3-technical/gds-game-architecture/engine-mcps.yaml +124 -2
  89. package/lib/bmad-cache/gds/src/workflows/4-production/gds-investigate/customize.toml +62 -0
  90. package/lib/bmad-cache/tea/.claude-plugin/marketplace.json +1 -1
  91. package/lib/bmad-cache/tea/.github/workflows/docs.yaml +3 -3
  92. package/lib/bmad-cache/tea/.github/workflows/quality.yaml +10 -10
  93. package/lib/bmad-cache/tea/AGENTS.md +31 -0
  94. package/lib/bmad-cache/tea/CHANGELOG.md +42 -1
  95. package/lib/bmad-cache/tea/README.md +8 -5
  96. package/lib/bmad-cache/tea/_git_preserved/hooks/commit-msg.sample +52 -2
  97. package/lib/bmad-cache/tea/_git_preserved/hooks/fsmonitor-watchman.sample +2 -8
  98. package/lib/bmad-cache/tea/_git_preserved/index +0 -0
  99. package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-9e4197e37df7763dd7a05c2965ee921dfd2eb617.idx +0 -0
  100. package/lib/bmad-cache/tea/_git_preserved/objects/pack/{pack-f0df537f2649464ff6c5aee241165eb9c8664227.pack → pack-9e4197e37df7763dd7a05c2965ee921dfd2eb617.pack} +0 -0
  101. package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-9e4197e37df7763dd7a05c2965ee921dfd2eb617.rev +0 -0
  102. package/lib/bmad-cache/tea/_git_preserved/packed-refs +1 -1
  103. package/lib/bmad-cache/tea/_git_preserved/refs/heads/main +1 -1
  104. package/lib/bmad-cache/tea/_git_preserved/refs/tags/v1.19.0 +1 -0
  105. package/lib/bmad-cache/tea/_git_preserved/shallow +1 -1
  106. package/lib/bmad-cache/tea/docs/explanation/engagement-models.md +15 -16
  107. package/lib/bmad-cache/tea/docs/explanation/knowledge-base-system.md +2 -0
  108. package/lib/bmad-cache/tea/docs/explanation/risk-based-testing.md +1 -1
  109. package/lib/bmad-cache/tea/docs/explanation/tea-overview.md +88 -52
  110. package/lib/bmad-cache/tea/docs/explanation/testing-as-engineering.md +13 -12
  111. package/lib/bmad-cache/tea/docs/glossary/index.md +2 -2
  112. package/lib/bmad-cache/tea/docs/how-to/brownfield/use-tea-for-enterprise.md +19 -18
  113. package/lib/bmad-cache/tea/docs/how-to/brownfield/use-tea-with-existing-tests.md +1 -1
  114. package/lib/bmad-cache/tea/docs/how-to/workflows/run-nfr-assess.md +32 -26
  115. package/lib/bmad-cache/tea/docs/how-to/workflows/run-test-design.md +20 -14
  116. package/lib/bmad-cache/tea/docs/how-to/workflows/run-trace.md +3 -3
  117. package/lib/bmad-cache/tea/docs/index.md +13 -11
  118. package/lib/bmad-cache/tea/docs/reference/commands.md +37 -13
  119. package/lib/bmad-cache/tea/docs/reference/knowledge-base.md +2 -2
  120. package/lib/bmad-cache/tea/package-lock.json +2 -2
  121. package/lib/bmad-cache/tea/package.json +1 -1
  122. package/lib/bmad-cache/tea/src/agents/bmad-tea/customize.toml +20 -15
  123. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/confidence-gate.md +73 -0
  124. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/test-quality.md +1 -0
  125. package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/tea-index.csv +2 -1
  126. package/lib/bmad-cache/tea/src/module-help.csv +2 -2
  127. package/lib/bmad-cache/tea/src/workflows/testarch/README.md +5 -4
  128. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/data/role-paths.yaml +1 -1
  129. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/data/tea-resources-index.yaml +1 -1
  130. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-01.md +2 -2
  131. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-07.md +1 -1
  132. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/templates/certificate-template.md +1 -1
  133. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/resources/tea-index.csv +1 -1
  134. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/resources/tea-index.csv +1 -1
  135. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/resources/tea-index.csv +1 -1
  136. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/resources/tea-index.csv +1 -1
  137. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/SKILL.md +3 -3
  138. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/checklist.md +11 -11
  139. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/instructions.md +4 -2
  140. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/nfr-report-template.md +5 -5
  141. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/resources/tea-index.csv +1 -1
  142. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-01-load-context.md +1 -1
  143. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-01b-resume.md +1 -1
  144. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-02-define-thresholds.md +14 -3
  145. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04-evaluate-and-score.md +7 -7
  146. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04a-subagent-security.md +4 -4
  147. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04b-subagent-performance.md +4 -4
  148. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04c-subagent-reliability.md +4 -4
  149. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04d-subagent-scalability.md +4 -4
  150. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-04e-aggregate-nfr.md +4 -4
  151. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-05-generate-report.md +1 -1
  152. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/workflow-plan.md +1 -1
  153. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/workflow.yaml +3 -3
  154. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/checklist.md +23 -3
  155. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/resources/tea-index.csv +1 -1
  156. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-02-load-context.md +7 -0
  157. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-03-risk-and-testability.md +16 -2
  158. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-04-coverage-plan.md +20 -4
  159. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-05-generate-output.md +2 -0
  160. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/test-design-architecture-template.md +17 -0
  161. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/test-design-qa-template.md +15 -0
  162. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/test-design-template.md +16 -0
  163. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/resources/tea-index.csv +1 -1
  164. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/checklist.md +1 -1
  165. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/resources/tea-index.csv +1 -1
  166. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/trace-template.md +1 -1
  167. package/lib/bmad-cache/tea/test/test-installation-components.js +49 -0
  168. package/lib/bmad-cache/tea/website/astro.config.mjs +2 -2
  169. package/lib/bmad-cache/wds/README.md +1 -1
  170. package/lib/bmad-cache/wds/_git_preserved/hooks/commit-msg.sample +52 -2
  171. package/lib/bmad-cache/wds/_git_preserved/hooks/fsmonitor-watchman.sample +2 -8
  172. package/lib/bmad-cache/wds/_git_preserved/index +0 -0
  173. package/lib/bmad-cache/wds/_git_preserved/objects/pack/pack-656c3d8d5426e73043b6a7f45eedaab74e3c419e.idx +0 -0
  174. package/lib/bmad-cache/wds/_git_preserved/objects/pack/{pack-96877c1c09123cccb1f91c1412184b11d2b492ad.pack → pack-656c3d8d5426e73043b6a7f45eedaab74e3c419e.pack} +0 -0
  175. package/lib/bmad-cache/wds/_git_preserved/objects/pack/pack-656c3d8d5426e73043b6a7f45eedaab74e3c419e.rev +0 -0
  176. package/lib/bmad-cache/wds/_git_preserved/packed-refs +1 -1
  177. package/lib/bmad-cache/wds/_git_preserved/refs/heads/main +1 -1
  178. package/lib/bmad-cache/wds/_git_preserved/refs/tags/v0.4.3 +1 -0
  179. package/lib/bmad-cache/wds/_git_preserved/shallow +1 -1
  180. package/lib/bmad-cache/wds/eslint.config.mjs +1 -1
  181. package/lib/bmad-cache/wds/package.json +1 -1
  182. package/lib/bmad-cache/wds/src/agents/wds-agent-freya-ux/customize.toml +80 -0
  183. package/lib/bmad-cache/wds/src/agents/wds-agent-mimir-builder/customize.toml +52 -0
  184. package/lib/bmad-cache/wds/src/agents/wds-agent-saga-analyst/customize.toml +70 -0
  185. package/lib/bmad-cache/wds/src/module-help.csv +19 -19
  186. package/lib/bmad-cache/wds/src/module.yaml +28 -0
  187. package/lib/bmad-cache/wds/src/scripts/README.md +155 -0
  188. package/lib/bmad-cache/wds/src/scripts/wds-add-object.js +202 -0
  189. package/lib/bmad-cache/wds/src/scripts/wds-add-spacing.js +158 -0
  190. package/lib/bmad-cache/wds/src/scripts/wds-init-page.js +229 -0
  191. package/lib/bmad-cache/wds/src/scripts/wds-init-scenario.js +120 -0
  192. package/lib/bmad-cache/wds/src/scripts/wds-nav.js +201 -0
  193. package/lib/bmad-cache/wds/src/scripts/wds-validate.js +301 -0
  194. package/lib/bmad-cache/wds/src/workflows/wds-3-scenarios/workflow.xml +450 -0
  195. package/lib/bmad-cache/wds/src/workflows/wds-4-ux-design/workflow-specify.xml +387 -0
  196. package/lib/bmad-extension/.claude-plugin/marketplace.json.template +1 -1
  197. package/lib/bmad-extension-plugin/.claude-plugin/marketplace.json +2 -2
  198. package/lib/bmad.js +361 -18
  199. package/lib/installer.js +296 -26
  200. package/lib/mil498-templates/OCD.md +169 -169
  201. package/lib/mil498-templates/README.md +4 -4
  202. package/lib/mil498-templates/SDD.md +163 -163
  203. package/lib/mil498-templates/SDP.md +307 -307
  204. package/lib/mil498-templates/SRS.md +219 -219
  205. package/lib/mil498-templates/SSDD.md +154 -154
  206. package/lib/mil498-templates/SSS.md +225 -225
  207. package/lib/mil498-templates/STD.md +188 -188
  208. package/lib/profile.js +96 -5
  209. package/lib/templates/instruction-block-git.template.md +25 -0
  210. package/lib/templates/instruction-block-onprem.template.md +86 -86
  211. package/lib/templates/instruction-block-universal.template.md +29 -29
  212. package/package.json +5 -4
  213. package/scripts/build-bmad-cache.js +143 -42
  214. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-6ecd9fc6445b1281449c5ec49a6c5794708e662e.idx +0 -0
  215. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-6ecd9fc6445b1281449c5ec49a6c5794708e662e.pack +0 -0
  216. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-6ecd9fc6445b1281449c5ec49a6c5794708e662e.rev +0 -0
  217. package/lib/bmad-cache/bmb/_git_preserved/refs/remotes/origin/HEAD +0 -1
  218. package/lib/bmad-cache/bmb/_git_preserved/refs/tags/v1.7.0 +0 -1
  219. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/generate-convert-report.py +0 -406
  220. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/tests/test_generate_convert_report.py +0 -243
  221. package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-42ffc048f54e58ce94c6331bc6be97ebbb7936f2.idx +0 -0
  222. package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-42ffc048f54e58ce94c6331bc6be97ebbb7936f2.rev +0 -0
  223. package/lib/bmad-cache/cis/_git_preserved/refs/remotes/origin/HEAD +0 -1
  224. package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-9427a146a90c00bb542cba038874bf9671ba4dc0.idx +0 -0
  225. package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-9427a146a90c00bb542cba038874bf9671ba4dc0.rev +0 -0
  226. package/lib/bmad-cache/gds/_git_preserved/refs/remotes/origin/HEAD +0 -1
  227. package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-gdd/customize.toml +0 -41
  228. package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-prd/customize.toml +0 -41
  229. package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-prd/data/domain-complexity.csv +0 -15
  230. package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-prd/data/project-types.csv +0 -11
  231. package/lib/bmad-cache/gds/src/workflows/2-design/gds-create-ux-design/customize.toml +0 -41
  232. package/lib/bmad-cache/gds/src/workflows/2-design/gds-edit-gdd/customize.toml +0 -41
  233. package/lib/bmad-cache/gds/src/workflows/2-design/gds-edit-prd/customize.toml +0 -41
  234. package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-gdd/customize.toml +0 -41
  235. package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-prd/customize.toml +0 -41
  236. package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-prd/data/domain-complexity.csv +0 -15
  237. package/lib/bmad-cache/gds/src/workflows/2-design/gds-validate-prd/data/project-types.csv +0 -11
  238. package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-f0df537f2649464ff6c5aee241165eb9c8664227.idx +0 -0
  239. package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-f0df537f2649464ff6c5aee241165eb9c8664227.rev +0 -0
  240. package/lib/bmad-cache/tea/_git_preserved/refs/remotes/origin/HEAD +0 -1
  241. package/lib/bmad-cache/wds/_git_preserved/objects/pack/pack-96877c1c09123cccb1f91c1412184b11d2b492ad.idx +0 -0
  242. package/lib/bmad-cache/wds/_git_preserved/objects/pack/pack-96877c1c09123cccb1f91c1412184b11d2b492ad.rev +0 -0
  243. package/lib/bmad-cache/wds/_git_preserved/refs/remotes/origin/HEAD +0 -1
  244. package/lib/bmad-cache/wds/src/agents/wds-agent-freya-ux/bmad-skill-manifest.yaml +0 -12
  245. package/lib/bmad-cache/wds/src/agents/wds-agent-saga-analyst/bmad-skill-manifest.yaml +0 -12
  246. package/lib/bmad-cache/wds/src/workflows/wds-0-alignment-signoff/bmad-skill-manifest.yaml +0 -1
  247. package/lib/bmad-cache/wds/src/workflows/wds-0-project-setup/bmad-skill-manifest.yaml +0 -1
  248. package/lib/bmad-cache/wds/src/workflows/wds-1-project-brief/bmad-skill-manifest.yaml +0 -1
  249. package/lib/bmad-cache/wds/src/workflows/wds-2-trigger-mapping/bmad-skill-manifest.yaml +0 -1
  250. package/lib/bmad-cache/wds/src/workflows/wds-3-scenarios/bmad-skill-manifest.yaml +0 -1
  251. package/lib/bmad-cache/wds/src/workflows/wds-4-ux-design/bmad-skill-manifest.yaml +0 -1
  252. package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/bmad-skill-manifest.yaml +0 -1
  253. package/lib/bmad-cache/wds/src/workflows/wds-6-asset-generation/bmad-skill-manifest.yaml +0 -1
  254. package/lib/bmad-cache/wds/src/workflows/wds-7-design-system/bmad-skill-manifest.yaml +0 -1
  255. package/lib/bmad-cache/wds/src/workflows/wds-8-product-evolution/bmad-skill-manifest.yaml +0 -1
  256. /package/lib/bmad-cache/gds/src/workflows/2-design/{gds-create-gdd → gds-gdd/assets}/game-types.csv +0 -0
  257. /package/lib/bmad-cache/gds/src/workflows/2-design/{gds-validate-gdd/data → gds-gdd/assets}/genre-complexity.csv +0 -0
package/bin/cli.js CHANGED
@@ -33,8 +33,8 @@ const chalk = require('chalk');
33
33
  const path = require('path');
34
34
  const fs = require('fs');
35
35
  const { execFileSync } = require('child_process');
36
- const { installSkill, uninstallSkill, getStatus, listSkills, listAgents, updateProjectContextRepoLayout, migrateRetiredSkills } = require('../lib/installer');
37
- const { getProfile, setProfile, resolveProfile } = require('../lib/profile');
36
+ const { installSkill, uninstallSkill, getStatus, listSkills, listAgents, updateProjectContextRepoLayout, migrateRetiredSkills, reconcileAgentsSharedSkills } = require('../lib/installer');
37
+ const { getProfile, setProfile, resolveProfile, getBmadModules, setBmadModules } = require('../lib/profile');
38
38
  const { reconfigure: runReconfigure, ReconfigureYesRejectedError, ManifestNotFoundError, RoomodesSlugDivergenceError } = require('../lib/reconfigure');
39
39
  const { uninstallProfileArtifacts } = require('../lib/uninstall');
40
40
  const bmad = require('../lib/bmad');
@@ -495,6 +495,19 @@ function writeConfigField(content, fieldName, value) {
495
495
  return content.trimEnd() + '\n' + newLine + '\n';
496
496
  }
497
497
 
498
+ // Bug 27.15 — unify the path convention. config.toml (written by upstream
499
+ // manifest-generator) declares artifact paths with a `{project-root}/` prefix;
500
+ // previously writeRepoLayoutConfig emitted a THIRD variant: bare relative
501
+ // `_bmad-output/...`. Emit the same `{project-root}/`-prefixed form here so
502
+ // ma-agents stops adding a divergent third convention. config.toml is the
503
+ // install-owned source of truth; the per-module config.yaml is the
504
+ // upstream-stripped read copy. Fully aligning the upstream stripper
505
+ // (official-modules.js) is a separate upstream follow-up; vendored node_modules
506
+ // is not edited here.
507
+ function canonicalArtifactPath(suffix) {
508
+ return `{project-root}/_bmad-output/${suffix}`;
509
+ }
510
+
498
511
  function writeRepoLayoutConfig(layout) {
499
512
  const configPath = path.join(process.cwd(), '_bmad', 'bmm', 'config.yaml');
500
513
  try {
@@ -522,8 +535,8 @@ function writeRepoLayoutConfig(layout) {
522
535
  content = writeConfigField(content, 'sprint_backend', 'jira');
523
536
  content = writeConfigField(content, 'jira_url', layout.sprintManagement.jiraUrl);
524
537
  content = writeConfigField(content, 'jira_project_key', layout.sprintManagement.jiraProjectKey);
525
- const planningArtifacts = kbPath === '.' ? '_bmad-output/planning-artifacts' : kbPath;
526
- const implArtifacts = '_bmad-output/implementation-artifacts';
538
+ const planningArtifacts = kbPath === '.' ? canonicalArtifactPath('planning-artifacts') : kbPath;
539
+ const implArtifacts = canonicalArtifactPath('implementation-artifacts');
527
540
  content = writeConfigField(content, 'planning_artifacts', planningArtifacts);
528
541
  content = writeConfigField(content, 'implementation_artifacts', implArtifacts);
529
542
  fs.writeFileSync(configPath, content, 'utf-8');
@@ -534,8 +547,8 @@ function writeRepoLayoutConfig(layout) {
534
547
  const spPath = spPortable.portable;
535
548
  content = writeConfigField(content, 'sprint_backend', 'file-system');
536
549
  content = writeConfigField(content, 'sprint_management_path', spPath);
537
- const planningArtifacts = kbPath === '.' ? '_bmad-output/planning-artifacts' : kbPath;
538
- const implArtifacts = spPath === '.' ? '_bmad-output/implementation-artifacts' : spPath;
550
+ const planningArtifacts = kbPath === '.' ? canonicalArtifactPath('planning-artifacts') : kbPath;
551
+ const implArtifacts = spPath === '.' ? canonicalArtifactPath('implementation-artifacts') : spPath;
539
552
  content = writeConfigField(content, 'planning_artifacts', planningArtifacts);
540
553
  content = writeConfigField(content, 'implementation_artifacts', implArtifacts);
541
554
  fs.writeFileSync(configPath, content, 'utf-8');
@@ -831,14 +844,26 @@ async function collectRepoLayout(flags, existingLayout = null) {
831
844
  * break without them. Retired modules (currently only `wds`) are filtered
832
845
  * out unconditionally.
833
846
  */
834
- async function selectBmadModules({ bmadModulesFlag, bmadModulesPrompt }) {
847
+ async function selectBmadModules({ bmadModulesFlag, bmadModulesPrompt, projectRoot } = {}) {
835
848
  const installable = bmad.getInstallableBmadModules().filter(m => !m.retired);
849
+ const root = projectRoot || process.cwd();
850
+
851
+ // Bug 27.13 — persist the resolved selection so a deselection sticks across
852
+ // future installs/reconfigures that do not re-pass --bmad-modules.
853
+ const persist = (modules) => {
854
+ try {
855
+ setBmadModules(root, modules);
856
+ } catch (err) {
857
+ console.warn(chalk.yellow(` Warning: could not persist BMAD module selection: ${err.message}`));
858
+ }
859
+ return modules;
860
+ };
836
861
 
837
862
  // Branch 1: explicit CSV — validate + use as-is.
838
863
  if (bmadModulesFlag) {
839
864
  const requested = bmadModulesFlag.split(',').map(s => s.trim()).filter(Boolean);
840
865
  try {
841
- return bmad.resolveBmadModules({ requested, available: installable });
866
+ return persist(bmad.resolveBmadModules({ requested, available: installable }));
842
867
  } catch (err) {
843
868
  console.error(chalk.red(`Error: ${err.message}`));
844
869
  process.exit(1);
@@ -872,11 +897,25 @@ async function selectBmadModules({ bmadModulesFlag, bmadModulesPrompt }) {
872
897
 
873
898
  // Belt-and-suspenders: force bmm back in if the user managed to uncheck
874
899
  // it despite the (required) tag.
875
- return bmad.resolveBmadModules({ requested: chosenModules, available: installable });
900
+ return persist(bmad.resolveBmadModules({ requested: chosenModules, available: installable }));
901
+ }
902
+
903
+ // Branch 3: no flag → use the persisted selection from a prior run if present
904
+ // (bug 27.13 — a previous deselection must survive); otherwise fall back to
905
+ // the original "install every available module" default. The persisted set is
906
+ // intersected with the currently-installable set so a since-retired module
907
+ // does not resurface, and bmm is force-included via resolveBmadModules.
908
+ const persisted = getBmadModules(root);
909
+ if (persisted && persisted.length > 0) {
910
+ const availableIds = new Set(installable.map(m => m.id));
911
+ const stillInstallable = persisted.filter(id => availableIds.has(id));
912
+ try {
913
+ return persist(bmad.resolveBmadModules({ requested: stillInstallable, available: installable }));
914
+ } catch {
915
+ // If the persisted set somehow fails validation, fall through to default.
916
+ }
876
917
  }
877
-
878
- // Branch 3: no flag → install everything available.
879
- return installable.map(m => m.id);
918
+ return persist(installable.map(m => m.id));
880
919
  }
881
920
 
882
921
  // --- Install wizard ---
@@ -1167,6 +1206,7 @@ async function installWizard(preselectedSkill, preselectedAgents, customPath, fo
1167
1206
  const bmadModules = await selectBmadModules({
1168
1207
  bmadModulesFlag,
1169
1208
  bmadModulesPrompt,
1209
+ projectRoot: process.cwd(),
1170
1210
  });
1171
1211
 
1172
1212
  if (!bmadInstalled) {
@@ -1314,6 +1354,20 @@ async function installWizard(preselectedSkill, preselectedAgents, customPath, fo
1314
1354
  }
1315
1355
  }
1316
1356
 
1357
+ // Bug 27.16 — if BMAD populated the shared `.agents/skills` dir but no
1358
+ // .agents-targeting agent (copilot/kilocode/roo-code) was selected, the
1359
+ // standalone catalog + MANIFEST.yaml were never written there. Backfill them
1360
+ // so the dir is never BMAD-only without the MANIFEST.yaml the instruction
1361
+ // block points agents at. No-op when an .agents agent was selected or no
1362
+ // shared dir exists.
1363
+ if (installScope === 'project') {
1364
+ try {
1365
+ await reconcileAgentsSharedSkills(process.cwd(), selectedAgentIds, installScope);
1366
+ } catch (err) {
1367
+ console.log(chalk.yellow(` .agents/skills reconciliation skipped: ${err.message}`));
1368
+ }
1369
+ }
1370
+
1317
1371
  // Step 6: Update project-context.md with repo layout section (after skills installed project-context.md)
1318
1372
  if (installScope === 'project') {
1319
1373
  const outputPath = path.join(process.cwd(), '_bmad-output', 'project-context.md');
@@ -1683,4 +1737,4 @@ if (require.main === module) {
1683
1737
  });
1684
1738
  }
1685
1739
 
1686
- module.exports = { parseFlags, collectRepoLayout, readExistingLayout, writeRepoLayoutConfig, writeProjectLayoutYaml, writeConfigField, normalizePath, toPortablePath, resolveStoredPath, ciCloneIfNeeded, showCurrentLayout, handleConfigLayout, yamlEscapeValue };
1740
+ module.exports = { parseFlags, selectBmadModules, collectRepoLayout, readExistingLayout, writeRepoLayoutConfig, writeProjectLayoutYaml, writeConfigField, normalizePath, toPortablePath, resolveStoredPath, ciCloneIfNeeded, showCurrentLayout, handleConfigLayout, yamlEscapeValue };
@@ -195,6 +195,24 @@ skills/<skill-name>/
195
195
  - **Modern C++** (6): cpp-memory-handling, cpp-robust-interfaces, cpp-modern-composition, cpp-const-correctness, cpp-concurrency-safety, cmake-best-practices
196
196
  - **Architecture** (5): logging-best-practices, opentelemetry-best-practices, vercel-react-best-practices, git-workflow-skill, self-signed-cert
197
197
 
198
+ ### 3.6 BMAD Cache & Offline Self-Containment (build-time)
199
+
200
+ **Responsibility**: Pre-vendor BMAD's external modules so installs never touch the network.
201
+
202
+ ma-agents bundles bmad-method as an npm dependency **and** pre-clones BMAD's external modules (`tea`, `bmb`, `cis`, `gds`) into `lib/bmad-cache/` at build time via `npm run build:bmad-cache` ([scripts/build-bmad-cache.js](../scripts/build-bmad-cache.js)). This is what lets `npx ma-agents install` run fully offline in air-gapped environments (NFR2/NFR50/NFR54) — the npm tarball already contains every module bmad-method would otherwise `git clone` from GitHub at install time.
203
+
204
+ **Module discovery**: the builder reads BMAD's bundled module registry to learn which external modules to clone. **The registry source has moved across BMAD versions** and the reader must track it:
205
+
206
+ | BMAD version | Module registry source | Format |
207
+ |--------------|------------------------|--------|
208
+ | ≤ 6.2.x | `tools/cli/external-official-modules.yaml` | YAML |
209
+ | 6.3.0 – 6.6.x | `tools/installer/modules/registry-fallback.yaml` | YAML |
210
+ | 6.8.0+ | `bmad-modules.yaml` (bmad-method **package root**) | YAML (`modules:` map; the in-package `registry-fallback.yaml` was retired in 6.7.0) |
211
+
212
+ The registry has stayed **YAML** throughout — only its path has moved. (`tools/installer/modules/official-modules.js` is unchanged loader code that reads this YAML; it does not contain the module list.) Modules are classified by a `type` field: `type: bmad-org` modules are bundled (**tea, bmb, cis, gds, wds**) and `type: experimental` modules are excluded (currently `automator`). `bmm`/`core` are built-in (loaded from bmad-method's local `module.yaml`, absent from the registry) and are never cloned. The reader for the current pin and its fail-loud contract are defined by Architecture Decision **P5-5** (Epic 27) in `_bmad-output/planning-artifacts/architecture.md`. A companion build step, `npm run build:plugin` ([scripts/build-plugin.js](../scripts/build-plugin.js)), assembles the ma-agents extension plugin bundle (`lib/bmad-extension-plugin/`) deterministically; a CI Bundle Drift Guard enforces that the committed bundle matches a fresh build.
213
+
214
+ > **Maintenance note:** because the registry path has now moved twice (YAML→YAML→YAML at three locations), the cache builder fails loud — if the resolved `type: bmad-org` set is smaller than the known bundled set, or no module source is found, it exits non-zero rather than producing a thin/empty cache, so a future BMAD registry move surfaces at build time, not as a broken air-gapped install.
215
+
198
216
  ## 4. Data Flow
199
217
 
200
218
  ### 4.1 Install Flow
@@ -12,7 +12,7 @@
12
12
  "name": "bmad-builder",
13
13
  "source": "./",
14
14
  "description": "Build AI agents, workflows, and modules from a conversation. Four skills — Agent Builder, Workflow Builder, Module Builder, and Setup — guide you from idea to production-ready skill structure with built-in quality optimization. Part of the BMad Method ecosystem.",
15
- "version": "1.6.0",
15
+ "version": "1.8.0",
16
16
  "author": {
17
17
  "name": "Brian (BMad) Madison"
18
18
  },
@@ -15,10 +15,60 @@
15
15
  # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
16
16
  # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
17
17
 
18
- # This example catches duplicate Signed-off-by lines.
18
+ # This example catches duplicate Signed-off-by lines and messages that
19
+ # would confuse 'git am'.
20
+
21
+ ret=0
19
22
 
20
23
  test "" = "$(grep '^Signed-off-by: ' "$1" |
21
24
  sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
22
25
  echo >&2 Duplicate Signed-off-by lines.
23
- exit 1
26
+ ret=1
24
27
  }
28
+
29
+ comment_re="$(
30
+ {
31
+ git config --get-regexp "^core\.comment(char|string)\$" ||
32
+ echo '#'
33
+ } | sed -n -e '
34
+ ${
35
+ s/^[^ ]* //
36
+ s|[][*./\]|\\&|g
37
+ s/^auto$/[#;@!$%^&|:]/
38
+ p
39
+ }'
40
+ )"
41
+ scissors_line="^${comment_re} -\{8,\} >8 -\{8,\}\$"
42
+ comment_line="^${comment_re}.*"
43
+ blank_line='^[ ]*$'
44
+ # Disallow lines starting with "diff -" or "Index: " in the body of the
45
+ # message. Stop looking if we see a scissors line.
46
+ line="$(sed -n -e "
47
+ # Skip comments and blank lines at the start of the file.
48
+ /${scissors_line}/q
49
+ /${comment_line}/d
50
+ /${blank_line}/d
51
+ # The first paragraph will become the subject header so
52
+ # does not need to be checked.
53
+ : subject
54
+ n
55
+ /${scissors_line}/q
56
+ /${blank_line}/!b subject
57
+ # Check the body of the message for problematic
58
+ # prefixes.
59
+ : body
60
+ n
61
+ /${scissors_line}/q
62
+ /${comment_line}/b body
63
+ /^diff -/{p;q;}
64
+ /^Index: /{p;q;}
65
+ b body
66
+ " "$1")"
67
+ if test -n "$line"
68
+ then
69
+ echo >&2 "Message contains a diff that will confuse 'git am'."
70
+ echo >&2 "To fix this indent the diff."
71
+ ret=1
72
+ fi
73
+
74
+ exit $ret
@@ -29,8 +29,6 @@ if ($version ne 2) {
29
29
 
30
30
  my $git_work_tree = get_working_dir();
31
31
 
32
- my $retry = 1;
33
-
34
32
  my $json_pkg;
35
33
  eval {
36
34
  require JSON::XS;
@@ -123,8 +121,7 @@ sub watchman_query {
123
121
  sub is_work_tree_watched {
124
122
  my ($output) = @_;
125
123
  my $error = $output->{error};
126
- if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
127
- $retry--;
124
+ if ($error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
128
125
  my $response = qx/watchman watch "$git_work_tree"/;
129
126
  die "Failed to make watchman watch '$git_work_tree'.\n" .
130
127
  "Falling back to scanning...\n" if $? != 0;
@@ -142,15 +139,12 @@ sub is_work_tree_watched {
142
139
  # Watchman query just to get it over with now so we won't pay
143
140
  # the cost in git to look up each individual file.
144
141
  my $o = watchman_clock();
145
- $error = $output->{error};
142
+ $error = $o->{error};
146
143
 
147
144
  die "Watchman: $error.\n" .
148
145
  "Falling back to scanning...\n" if $error;
149
146
 
150
147
  output_result($o->{clock}, ("/"));
151
- $last_update_token = $o->{clock};
152
-
153
- eval { launch_watchman() };
154
148
  return 0;
155
149
  }
156
150
 
@@ -1,2 +1,2 @@
1
1
  # pack-refs with: peeled fully-peeled sorted
2
- 86033fc9aeae2ca6d52c7cdb675c1f4bf17fc1c1 refs/remotes/origin/main
2
+ 7cfa7711778f04c5df56f7ae895fabc942fd920c refs/remotes/origin/main
@@ -1 +1 @@
1
- 86033fc9aeae2ca6d52c7cdb675c1f4bf17fc1c1
1
+ 7cfa7711778f04c5df56f7ae895fabc942fd920c
@@ -1 +1 @@
1
- 86033fc9aeae2ca6d52c7cdb675c1f4bf17fc1c1
1
+ 7cfa7711778f04c5df56f7ae895fabc942fd920c
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "bmad-builder",
3
- "version": "1.7.0",
3
+ "version": "1.8.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "bmad-builder",
9
- "version": "1.7.0",
9
+ "version": "1.8.1",
10
10
  "license": "MIT",
11
11
  "devDependencies": {
12
12
  "@astrojs/sitemap": "^3.6.0",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "bmad-builder",
4
- "version": "1.7.0",
4
+ "version": "1.8.1",
5
5
  "private": true,
6
6
  "description": "A BMad Core expansion module that guides users through the creation of Modules Workflow and Agents",
7
7
  "keywords": [
@@ -1,4 +1,4 @@
1
- module,skill,display-name,menu-code,description,action,args,phase,after,before,required,output-location,outputs
1
+ module,skill,display-name,menu-code,description,action,args,phase,preceded-by,followed-by,required,output-location,outputs
2
2
  Dream Weaver,bmad-agent-dream-weaver,Dream Capture,DL,"Capture and log a dream through guided conversation.",dream-log,,anytime,,,false,,journal entry
3
3
  Dream Weaver,bmad-agent-dream-weaver,Dream Interpretation,DI,"Analyze a dream for symbolism, meaning, and personal connections.",dream-interpret,,anytime,dw:dream-log,,false,,interpretation
4
4
  Dream Weaver,bmad-agent-dream-weaver,Recall Training,RT,"Dream recall exercises and progress tracking.",recall-training,,anytime,,,false,,coaching updates
@@ -339,9 +339,42 @@ def write_config(config: dict, config_path: str, verbose: bool = False) -> None:
339
339
  )
340
340
 
341
341
 
342
+ def reject_unresolved_paths(named_paths: list[tuple[str, str]]) -> None:
343
+ """Exit with a clear error if any path argument still contains the literal
344
+ ``{project-root}`` token. That token is meaningful only inside config
345
+ values; filesystem path arguments must be resolved by the caller. Failing
346
+ loudly here prevents silently creating a junk ``{project-root}/`` directory.
347
+ """
348
+ for name, value in named_paths:
349
+ if value and "{project-root}" in value:
350
+ print(
351
+ json.dumps(
352
+ {
353
+ "status": "error",
354
+ "error": (
355
+ f"Unresolved '{{project-root}}' token in {name} path: {value!r}. "
356
+ "Resolve '{project-root}' to the actual project root before running "
357
+ "this script — it is a filesystem path, not a config value."
358
+ ),
359
+ },
360
+ indent=2,
361
+ ),
362
+ file=sys.stderr,
363
+ )
364
+ sys.exit(1)
365
+
366
+
342
367
  def main():
343
368
  args = parse_args()
344
369
 
370
+ reject_unresolved_paths(
371
+ [
372
+ ("--config-path", args.config_path),
373
+ ("--user-config-path", args.user_config_path),
374
+ ("--legacy-dir", args.legacy_dir),
375
+ ]
376
+ )
377
+
345
378
  # Load inputs
346
379
  module_yaml = load_yaml_file(args.module_yaml)
347
380
  if not module_yaml:
@@ -139,9 +139,37 @@ def cleanup_legacy_csvs(
139
139
  return deleted
140
140
 
141
141
 
142
+ def reject_unresolved_paths(named_paths: list[tuple[str, str]]) -> None:
143
+ """Exit with a clear error if any path argument still contains the literal
144
+ ``{project-root}`` token. That token is meaningful only inside config
145
+ values; filesystem path arguments must be resolved by the caller. Failing
146
+ loudly here prevents silently creating a junk ``{project-root}/`` directory.
147
+ """
148
+ for name, value in named_paths:
149
+ if value and "{project-root}" in value:
150
+ print(
151
+ json.dumps(
152
+ {
153
+ "status": "error",
154
+ "error": (
155
+ f"Unresolved '{{project-root}}' token in {name} path: {value!r}. "
156
+ "Resolve '{project-root}' to the actual project root before running "
157
+ "this script — it is a filesystem path, not a config value."
158
+ ),
159
+ },
160
+ indent=2,
161
+ )
162
+ )
163
+ sys.exit(1)
164
+
165
+
142
166
  def main():
143
167
  args = parse_args()
144
168
 
169
+ reject_unresolved_paths(
170
+ [("--target", args.target), ("--legacy-dir", args.legacy_dir)]
171
+ )
172
+
145
173
  # Read source entries
146
174
  source_header, source_rows = read_csv_rows(args.source)
147
175
  if not source_rows:
@@ -1,4 +1,4 @@
1
- module,skill,display-name,menu-code,description,action,args,phase,after,before,required,output-location,outputs
1
+ module,skill,display-name,menu-code,description,action,args,phase,preceded-by,followed-by,required,output-location,outputs
2
2
  BMad Samples,sample-module-setup,Setup Samples Module,SS,"Install or update BMad Samples module config and help entries.",configure,"{-H: headless mode}|{inline values: skip prompts with provided values}",anytime,,,false,{project-root}/_bmad,config.yaml and config.user.yaml
3
3
  BMad Samples,bmad-agent-code-coach,Code Coaching,TC,"Personal coding coaching and mentoring — code review, pair programming, and learning paths.",activate,,anytime,,,false,,coaching session
4
4
  BMad Samples,bmad-agent-creative-muse,Creative Muse,TM,"Creative brainstorming, problem-solving, and storytelling companion.",activate,,anytime,,,false,,creative session
@@ -197,9 +197,37 @@ def cleanup_directories(
197
197
  return removed, not_found, total_files
198
198
 
199
199
 
200
+ def reject_unresolved_paths(named_paths: list[tuple[str, str]]) -> None:
201
+ """Exit with a clear error if any path argument still contains the literal
202
+ ``{project-root}`` token. That token is meaningful only inside config
203
+ values; filesystem path arguments must be resolved by the caller. Failing
204
+ loudly here prevents silently operating on a junk ``{project-root}/`` directory.
205
+ """
206
+ for name, value in named_paths:
207
+ if value and "{project-root}" in value:
208
+ print(
209
+ json.dumps(
210
+ {
211
+ "status": "error",
212
+ "error": (
213
+ f"Unresolved '{{project-root}}' token in {name} path: {value!r}. "
214
+ "Resolve '{project-root}' to the actual project root before running "
215
+ "this script — it is a filesystem path, not a config value."
216
+ ),
217
+ },
218
+ indent=2,
219
+ )
220
+ )
221
+ sys.exit(1)
222
+
223
+
200
224
  def main():
201
225
  args = parse_args()
202
226
 
227
+ reject_unresolved_paths(
228
+ [("--bmad-dir", args.bmad_dir), ("--skills-dir", args.skills_dir)]
229
+ )
230
+
203
231
  bmad_dir = args.bmad_dir
204
232
  module_code = args.module_code
205
233
 
@@ -339,9 +339,42 @@ def write_config(config: dict, config_path: str, verbose: bool = False) -> None:
339
339
  )
340
340
 
341
341
 
342
+ def reject_unresolved_paths(named_paths: list[tuple[str, str]]) -> None:
343
+ """Exit with a clear error if any path argument still contains the literal
344
+ ``{project-root}`` token. That token is meaningful only inside config
345
+ values; filesystem path arguments must be resolved by the caller. Failing
346
+ loudly here prevents silently creating a junk ``{project-root}/`` directory.
347
+ """
348
+ for name, value in named_paths:
349
+ if value and "{project-root}" in value:
350
+ print(
351
+ json.dumps(
352
+ {
353
+ "status": "error",
354
+ "error": (
355
+ f"Unresolved '{{project-root}}' token in {name} path: {value!r}. "
356
+ "Resolve '{project-root}' to the actual project root before running "
357
+ "this script — it is a filesystem path, not a config value."
358
+ ),
359
+ },
360
+ indent=2,
361
+ ),
362
+ file=sys.stderr,
363
+ )
364
+ sys.exit(1)
365
+
366
+
342
367
  def main():
343
368
  args = parse_args()
344
369
 
370
+ reject_unresolved_paths(
371
+ [
372
+ ("--config-path", args.config_path),
373
+ ("--user-config-path", args.user_config_path),
374
+ ("--legacy-dir", args.legacy_dir),
375
+ ]
376
+ )
377
+
345
378
  # Load inputs
346
379
  module_yaml = load_yaml_file(args.module_yaml)
347
380
  if not module_yaml:
@@ -139,9 +139,37 @@ def cleanup_legacy_csvs(
139
139
  return deleted
140
140
 
141
141
 
142
+ def reject_unresolved_paths(named_paths: list[tuple[str, str]]) -> None:
143
+ """Exit with a clear error if any path argument still contains the literal
144
+ ``{project-root}`` token. That token is meaningful only inside config
145
+ values; filesystem path arguments must be resolved by the caller. Failing
146
+ loudly here prevents silently creating a junk ``{project-root}/`` directory.
147
+ """
148
+ for name, value in named_paths:
149
+ if value and "{project-root}" in value:
150
+ print(
151
+ json.dumps(
152
+ {
153
+ "status": "error",
154
+ "error": (
155
+ f"Unresolved '{{project-root}}' token in {name} path: {value!r}. "
156
+ "Resolve '{project-root}' to the actual project root before running "
157
+ "this script — it is a filesystem path, not a config value."
158
+ ),
159
+ },
160
+ indent=2,
161
+ )
162
+ )
163
+ sys.exit(1)
164
+
165
+
142
166
  def main():
143
167
  args = parse_args()
144
168
 
169
+ reject_unresolved_paths(
170
+ [("--target", args.target), ("--legacy-dir", args.legacy_dir)]
171
+ )
172
+
145
173
  # Read source entries
146
174
  source_header, source_rows = read_csv_rows(args.source)
147
175
  if not source_rows:
@@ -1,4 +1,4 @@
1
- module,skill,display-name,menu-code,description,action,args,phase,after,before,required,output-location,outputs
1
+ module,skill,display-name,menu-code,description,action,args,phase,preceded-by,followed-by,required,output-location,outputs
2
2
  BMad Builder,bmad-bmb-setup,Setup Builder Module,SB,"Install or update BMad Builder module config and help entries.",configure,"{-H: headless mode}|{inline values: skip prompts with provided values}",anytime,,,false,{project-root}/_bmad,config.yaml and config.user.yaml
3
3
  BMad Builder,bmad-agent-builder,Build an Agent,BA,"Create, edit, or rebuild an agent skill through conversational discovery.",build-process,"{-H: headless mode}|{description: initial agent concept}|{path: existing agent to edit or rebuild}",anytime,,bmad-agent-builder:quality-analysis,false,bmad_builder_output_folder,agent skill
4
4
  BMad Builder,bmad-agent-builder,Analyze an Agent,AA,"Run quality analysis on an existing agent — structure, cohesion, prompt craft, and enhancement opportunities.",quality-analysis,"{-H: headless mode}|{path: agent to analyze}",anytime,bmad-agent-builder:build-process,,false,bmad_builder_reports,quality report
@@ -197,9 +197,37 @@ def cleanup_directories(
197
197
  return removed, not_found, total_files
198
198
 
199
199
 
200
+ def reject_unresolved_paths(named_paths: list[tuple[str, str]]) -> None:
201
+ """Exit with a clear error if any path argument still contains the literal
202
+ ``{project-root}`` token. That token is meaningful only inside config
203
+ values; filesystem path arguments must be resolved by the caller. Failing
204
+ loudly here prevents silently operating on a junk ``{project-root}/`` directory.
205
+ """
206
+ for name, value in named_paths:
207
+ if value and "{project-root}" in value:
208
+ print(
209
+ json.dumps(
210
+ {
211
+ "status": "error",
212
+ "error": (
213
+ f"Unresolved '{{project-root}}' token in {name} path: {value!r}. "
214
+ "Resolve '{project-root}' to the actual project root before running "
215
+ "this script — it is a filesystem path, not a config value."
216
+ ),
217
+ },
218
+ indent=2,
219
+ )
220
+ )
221
+ sys.exit(1)
222
+
223
+
200
224
  def main():
201
225
  args = parse_args()
202
226
 
227
+ reject_unresolved_paths(
228
+ [("--bmad-dir", args.bmad_dir), ("--skills-dir", args.skills_dir)]
229
+ )
230
+
203
231
  bmad_dir = args.bmad_dir
204
232
  module_code = args.module_code
205
233
 
@@ -339,9 +339,42 @@ def write_config(config: dict, config_path: str, verbose: bool = False) -> None:
339
339
  )
340
340
 
341
341
 
342
+ def reject_unresolved_paths(named_paths: list[tuple[str, str]]) -> None:
343
+ """Exit with a clear error if any path argument still contains the literal
344
+ ``{project-root}`` token. That token is meaningful only inside config
345
+ values; filesystem path arguments must be resolved by the caller. Failing
346
+ loudly here prevents silently creating a junk ``{project-root}/`` directory.
347
+ """
348
+ for name, value in named_paths:
349
+ if value and "{project-root}" in value:
350
+ print(
351
+ json.dumps(
352
+ {
353
+ "status": "error",
354
+ "error": (
355
+ f"Unresolved '{{project-root}}' token in {name} path: {value!r}. "
356
+ "Resolve '{project-root}' to the actual project root before running "
357
+ "this script — it is a filesystem path, not a config value."
358
+ ),
359
+ },
360
+ indent=2,
361
+ ),
362
+ file=sys.stderr,
363
+ )
364
+ sys.exit(1)
365
+
366
+
342
367
  def main():
343
368
  args = parse_args()
344
369
 
370
+ reject_unresolved_paths(
371
+ [
372
+ ("--config-path", args.config_path),
373
+ ("--user-config-path", args.user_config_path),
374
+ ("--legacy-dir", args.legacy_dir),
375
+ ]
376
+ )
377
+
345
378
  # Load inputs
346
379
  module_yaml = load_yaml_file(args.module_yaml)
347
380
  if not module_yaml: