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/lib/bmad.js CHANGED
@@ -1,7 +1,8 @@
1
1
  const fs = require('fs-extra');
2
2
  const path = require('path');
3
3
  const os = require('os');
4
- const { execSync } = require('child_process');
4
+ const { execSync, execFileSync } = require('child_process');
5
+ const { pathToFileURL } = require('url');
5
6
  const chalk = require('chalk');
6
7
  const yaml = require('yaml');
7
8
  const jsYaml = require('js-yaml');
@@ -277,17 +278,34 @@ function ensurePluginStageGitignoredForProject(projectRoot) {
277
278
  console.warn(chalk.yellow(` Warning: could not load installer for gitignore policy: ${err.message}`));
278
279
  return;
279
280
  }
280
- if (typeof installer.ensurePluginStageIgnored !== 'function') return;
281
- try {
282
- installer.ensurePluginStageIgnored(projectRoot);
283
- } catch (err) {
284
- // EACCES on read-only `.gitignore`, EROFS on read-only filesystem, etc.
285
- // Logged so the operator can fix it manually; never fatal to the install.
286
- console.warn(
287
- chalk.yellow(
288
- ` Warning: could not update ${path.join(projectRoot, '.gitignore')} with plugin-stage entry: ${err.message}`
289
- )
290
- );
281
+ if (typeof installer.ensurePluginStageIgnored === 'function') {
282
+ try {
283
+ installer.ensurePluginStageIgnored(projectRoot);
284
+ } catch (err) {
285
+ // EACCES on read-only `.gitignore`, EROFS on read-only filesystem, etc.
286
+ // Logged so the operator can fix it manually; never fatal to the install.
287
+ console.warn(
288
+ chalk.yellow(
289
+ ` Warning: could not update ${path.join(projectRoot, '.gitignore')} with plugin-stage entry: ${err.message}`
290
+ )
291
+ );
292
+ }
293
+ }
294
+
295
+ // Bug 27.11 — also ensure the regenerated, installer-managed `_bmad/` tree is
296
+ // gitignored. Same project-root contract and same non-fatal failure policy as
297
+ // the plugin-stage entry above. `_bmad-output/` is intentionally left tracked
298
+ // (see ensureBmadOutputTracked) and is not matched by these patterns.
299
+ if (typeof installer.ensureBmadDirIgnored === 'function') {
300
+ try {
301
+ installer.ensureBmadDirIgnored(projectRoot);
302
+ } catch (err) {
303
+ console.warn(
304
+ chalk.yellow(
305
+ ` Warning: could not update ${path.join(projectRoot, '.gitignore')} with _bmad/ entry: ${err.message}`
306
+ )
307
+ );
308
+ }
291
309
  }
292
310
  }
293
311
 
@@ -471,7 +489,7 @@ const BMAD_MODULE_DESCRIPTIONS = Object.freeze({
471
489
  cis: 'Creative Intelligence Suite — innovation and ideation toolkit',
472
490
  gds: 'Game Dev Studio — game development workflows',
473
491
  tea: 'Test Architecture Enterprise — Test Architect (Murat) + 9 testarch workflows',
474
- wds: 'Web Dev Studio — retired upstream',
492
+ wds: 'Whiteport Design Studio — strategic UX and design-first planning',
475
493
  });
476
494
 
477
495
  /**
@@ -481,7 +499,9 @@ const BMAD_MODULE_DESCRIPTIONS = Object.freeze({
481
499
  * the optional external modules (bmb, cis, gds, tea, wds, ...).
482
500
  *
483
501
  * Each entry carries a `retired` flag so the caller can hide modules that
484
- * have been retired upstream (e.g. wds).
502
+ * have been retired upstream (driven by the manifest's `retiredUpstream`
503
+ * marker; at v6.8.0 the bundled set — tea, bmb, cis, gds, wds — are all
504
+ * active `type: bmad-org` clones, so none are flagged).
485
505
  *
486
506
  * If the cache manifest is missing or unreadable, falls back to a list
487
507
  * containing only `bmm` — that's the minimum a successful install needs.
@@ -844,6 +864,11 @@ async function installBmad(modules = ['bmm', 'bmb'], tools = [], projectRoot = p
844
864
  try {
845
865
  runCommand(command, { cwd: projectRoot, env: buildChildSpawnEnv() });
846
866
  bmadInvokeSucceeded = true;
867
+ // Bug 27.14 — repair any module artifact path that upstream's
868
+ // suffix-match output-folder resolution contaminated (e.g. gds paths
869
+ // pinned to bmb's "skills" instead of the chosen output folder). Runs
870
+ // after bmad-method writes the config and before downstream consumers.
871
+ normalizeModuleOutputFolders(projectRoot);
847
872
  // F1a — on-prem persona phase-prefix pass. Runs BEFORE
848
873
  // deployMethodology so a methodology-deploy failure doesn't prevent
849
874
  // the prefix from being applied (they are independent concerns).
@@ -950,6 +975,10 @@ async function runMigration(modules, tools, projectRoot, force, { userName, comm
950
975
  return false;
951
976
  }
952
977
 
978
+ // Bug 27.14 — repair contaminated module artifact paths on the migration
979
+ // path too (same upstream suffix-match resolution applies to updates).
980
+ normalizeModuleOutputFolders(projectRoot);
981
+
953
982
  // Step 3: Merge user customizations
954
983
  if (backedUpFiles.length > 0) {
955
984
  console.log(chalk.cyan(' Step 3/4: Merging user customizations...'));
@@ -1472,10 +1501,42 @@ async function deployMethodology(projectRoot = process.cwd(), force = false) {
1472
1501
  console.log(chalk.gray(' Tip: Use /open-presentation to open the slides (install via npx ma-agents install open-presentation)'));
1473
1502
  }
1474
1503
 
1504
+ /**
1505
+ * Detect whether a `.clinerules/workflows/*.md` file is a ma-agents-generated
1506
+ * Cline workflow wrapper (as opposed to a user-authored file that happens to
1507
+ * live in the same directory).
1508
+ *
1509
+ * Reconciliation (Story 27.4) deletes stale wrappers, so the matcher must be
1510
+ * conservative: it returns `true` ONLY for the exact shape this function emits.
1511
+ * Every generated wrapper contains a line that points the reader back into the
1512
+ * backing skill via a `.cline/skills/<name>/` reference (either `SKILL.md` or
1513
+ * `workflow.md`). User files under `.clinerules/` will not carry that marker,
1514
+ * so they are never mistaken for wrappers and never deleted.
1515
+ *
1516
+ * @param {string} content - Raw UTF-8 contents of the candidate `.md` file.
1517
+ * @returns {boolean} `true` if the content matches the generated-wrapper shape.
1518
+ */
1519
+ function isGeneratedClineWrapper(content) {
1520
+ if (typeof content !== 'string' || content.length === 0) return false;
1521
+ // The generated-wrapper fingerprint: a body line that instructs the reader
1522
+ // to read a file under `.cline/skills/<name>/` (SKILL.md or workflow.md).
1523
+ // Matches forward-slashed paths only — that is exactly what we emit.
1524
+ return /\.cline\/skills\/[^/\s`]+\/(?:SKILL|workflow)\.md/.test(content);
1525
+ }
1526
+
1475
1527
  /**
1476
1528
  * Generate Cline workflow wrappers for all BMAD skills installed to .cline/skills/.
1477
1529
  * Creates .clinerules/workflows/<skill-name>.md for each installed skill so they
1478
1530
  * can be invoked via / commands in Cline chat.
1531
+ *
1532
+ * Reconciliation (Story 27.4): after (re)generating wrappers for all current
1533
+ * skills, any stale wrapper under `.clinerules/workflows/` whose backing
1534
+ * `.cline/skills/<name>/` directory no longer exists is removed. This keeps
1535
+ * `/`-invocation in Cline from offering workflows for skills BMAD renamed away
1536
+ * or retired. Deletion is scoped strictly to ma-agents-generated wrapper files
1537
+ * (see {@link isGeneratedClineWrapper}); user-authored files elsewhere under
1538
+ * `.clinerules/` are never touched, and the operation is idempotent.
1539
+ *
1479
1540
  * No-op when 'cline' is not in the selected tools list.
1480
1541
  */
1481
1542
  async function deployClineWorkflows(projectRoot, tools = []) {
@@ -1502,6 +1563,10 @@ async function deployClineWorkflows(projectRoot, tools = []) {
1502
1563
  const entries = await fs.readdir(clineSkillsDir, { withFileTypes: true });
1503
1564
  const skillDirs = entries.filter(e => e.isDirectory());
1504
1565
 
1566
+ // Live skill-name set: every `.cline/skills/<name>/` that backs a wrapper
1567
+ // (i.e. contains a SKILL.md). Used below to reconcile stale wrappers.
1568
+ const liveSkillNames = new Set();
1569
+
1505
1570
  let generated = 0;
1506
1571
  for (const entry of skillDirs) {
1507
1572
  const skillName = entry.name;
@@ -1510,6 +1575,7 @@ async function deployClineWorkflows(projectRoot, tools = []) {
1510
1575
  const workflowMdPath = path.join(skillDir, 'workflow.md');
1511
1576
 
1512
1577
  if (!(await fs.pathExists(skillMdPath))) continue;
1578
+ liveSkillNames.add(skillName);
1513
1579
 
1514
1580
  const skillMdContent = await fs.readFile(skillMdPath, 'utf8');
1515
1581
  let displayName = skillName.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
@@ -1546,10 +1612,47 @@ async function deployClineWorkflows(projectRoot, tools = []) {
1546
1612
  generated++;
1547
1613
  }
1548
1614
 
1615
+ // Reconciliation (Story 27.4): remove stale wrappers whose backing skill
1616
+ // dir no longer exists. Scope is strictly the generated-wrapper `.md` files
1617
+ // directly inside `workflows/` — subdirectories and non-wrapper user files
1618
+ // are left untouched.
1619
+ let removed = 0;
1620
+ const workflowEntries = await fs.readdir(workflowsDir, { withFileTypes: true });
1621
+ for (const wf of workflowEntries) {
1622
+ // Only top-level `.md` files are candidate wrappers. Skip directories
1623
+ // and any non-markdown file outright.
1624
+ if (!wf.isFile()) continue;
1625
+ if (!wf.name.endsWith('.md')) continue;
1626
+
1627
+ const wrapperName = wf.name.slice(0, -'.md'.length);
1628
+ // A wrapper whose name is still in the live set is current — keep it.
1629
+ // (It was just (re)written above.)
1630
+ if (liveSkillNames.has(wrapperName)) continue;
1631
+
1632
+ // Name is not backed by a live skill. Before deleting, confirm the file
1633
+ // actually matches the ma-agents generated-wrapper shape so we never
1634
+ // remove a user-authored `.md` that happens to share a stale name.
1635
+ const wrapperPath = path.join(workflowsDir, wf.name);
1636
+ let wrapperContent;
1637
+ try {
1638
+ wrapperContent = await fs.readFile(wrapperPath, 'utf8');
1639
+ } catch {
1640
+ // Unreadable (e.g. vanished mid-run) — nothing to reconcile.
1641
+ continue;
1642
+ }
1643
+ if (!isGeneratedClineWrapper(wrapperContent)) continue;
1644
+
1645
+ await fs.remove(wrapperPath);
1646
+ removed++;
1647
+ }
1648
+
1549
1649
  if (generated > 0) {
1550
1650
  console.log(chalk.green(` ✓ Generated ${generated} Cline workflow wrappers in .clinerules/workflows/`));
1551
1651
  console.log(chalk.gray(' Tip: In Cline, type / to browse and invoke BMAD skills'));
1552
1652
  }
1653
+ if (removed > 0) {
1654
+ console.log(chalk.green(` ✓ Removed ${removed} stale Cline workflow wrapper${removed === 1 ? '' : 's'} (backing skill no longer present)`));
1655
+ }
1553
1656
  }
1554
1657
 
1555
1658
  /**
@@ -1731,6 +1834,237 @@ function readCanonicalBmadConfig(projectRoot) {
1731
1834
  }
1732
1835
  }
1733
1836
 
1837
+ // ── Bug 27.14 — output-folder propagation normalization ──────────────────────
1838
+ //
1839
+ // Upstream bmad-method's resolveConfigValue (official-modules.js) resolves the
1840
+ // `{output_folder}` token via a `endsWith('_output_folder')` suffix match over
1841
+ // all collected answers. When bmb (answer key `bmb_..._output_folder` = "skills")
1842
+ // and gds are co-installed, gds's `{output_folder}` resolves alphabetically to
1843
+ // bmb's "skills" value, so gds artifact paths become `{project-root}/skills/...`
1844
+ // instead of `{project-root}/_bmad-output/...`.
1845
+ //
1846
+ // ma-agents owns no part of that resolution (it lives in vendored node_modules),
1847
+ // so this is a post-install WORK-AROUND: after bmad-method writes the config,
1848
+ // re-read `[core] output_folder` and rewrite any contaminated module artifact
1849
+ // path back onto the canonical output folder. We deliberately scope the rewrite
1850
+ // to the well-known core artifact keys so we never touch a module's INTENTIONAL
1851
+ // own-folder values (e.g. bmb's `bmad_builder_output_folder = ".../skills"` or
1852
+ // wds's `design_artifacts = ".../design-artifacts"`).
1853
+ //
1854
+ // Upstream follow-up (do NOT edit node_modules here): patch resolveConfigValue
1855
+ // to require an exact `output_folder` / `core_output_folder` key instead of the
1856
+ // `endsWith` suffix match. Tracked as an upstream follow-up.
1857
+
1858
+ // Artifact keys that must always live under `[core] output_folder`. These are
1859
+ // the canonical bmm/gds planning+implementation+architecture artifact keys plus
1860
+ // tea's test_artifacts. Module-specific own-folder keys (bmb_*_output_folder,
1861
+ // design_artifacts, project_knowledge, *_output sub-paths) are intentionally
1862
+ // excluded.
1863
+ const OUTPUT_FOLDER_ARTIFACT_KEYS = [
1864
+ 'planning_artifacts',
1865
+ 'architecture_artifacts',
1866
+ 'implementation_artifacts',
1867
+ 'test_artifacts',
1868
+ ];
1869
+
1870
+ /**
1871
+ * Given an artifact path value and the canonical output folder, return a
1872
+ * corrected value if the path's output-folder segment differs from the
1873
+ * canonical one, or `null` if no change is needed.
1874
+ *
1875
+ * Handles both conventions:
1876
+ * - `{project-root}/<seg>/<suffix...>` (config.toml style)
1877
+ * - `<seg>/<suffix...>` (config.yaml stripped style)
1878
+ *
1879
+ * The leading `<seg>` (the first path segment after an optional `{project-root}/`
1880
+ * prefix) is the resolved output folder; if it !== `outputFolder` it is rewritten.
1881
+ * Only single-segment output folders are handled (the bmad default), which covers
1882
+ * the observed `skills` vs `_bmad-output` contamination.
1883
+ */
1884
+ function correctArtifactPath(value, outputFolder) {
1885
+ if (typeof value !== 'string' || !value) return null;
1886
+ const ROOT = '{project-root}/';
1887
+ let prefix = '';
1888
+ let rest = value;
1889
+ if (rest.startsWith(ROOT)) {
1890
+ prefix = ROOT;
1891
+ rest = rest.slice(ROOT.length);
1892
+ }
1893
+ const slash = rest.indexOf('/');
1894
+ if (slash === -1) return null; // no segment/suffix split — leave as-is
1895
+ const seg = rest.slice(0, slash);
1896
+ const suffix = rest.slice(slash); // includes leading '/'
1897
+ if (seg === outputFolder) return null; // already canonical
1898
+ return `${prefix}${outputFolder}${suffix}`;
1899
+ }
1900
+
1901
+ /**
1902
+ * Rewrite contaminated artifact paths inside `_bmad/config.toml`. Returns the
1903
+ * number of lines changed. Uses line-based editing (no TOML dependency) so we
1904
+ * preserve comments, ordering, and formatting exactly.
1905
+ */
1906
+ function normalizeTomlOutputFolders(tomlPath, outputFolder) {
1907
+ if (!fs.existsSync(tomlPath)) return 0;
1908
+ let raw;
1909
+ try {
1910
+ raw = fs.readFileSync(tomlPath, 'utf-8');
1911
+ } catch {
1912
+ return 0;
1913
+ }
1914
+ const usesCrlf = /\r\n/.test(raw);
1915
+ const eol = usesCrlf ? '\r\n' : '\n';
1916
+ const lines = raw.split(/\r?\n/);
1917
+ let changed = 0;
1918
+ let inModuleSection = false;
1919
+
1920
+ for (let i = 0; i < lines.length; i++) {
1921
+ const line = lines[i];
1922
+ const sectionMatch = line.match(/^\s*\[([^\]]+)\]\s*$/);
1923
+ if (sectionMatch) {
1924
+ const section = sectionMatch[1].trim();
1925
+ inModuleSection = section.startsWith('modules.');
1926
+ continue;
1927
+ }
1928
+ if (!inModuleSection) continue;
1929
+
1930
+ // key = "value" (only quoted string values are artifact paths)
1931
+ const kvMatch = line.match(/^(\s*)([A-Za-z0-9_]+)(\s*=\s*)"([^"]*)"(\s*(?:#.*)?)$/);
1932
+ if (!kvMatch) continue;
1933
+ const [, indent, key, eq, val, trailer] = kvMatch;
1934
+ if (!OUTPUT_FOLDER_ARTIFACT_KEYS.includes(key)) continue;
1935
+ const corrected = correctArtifactPath(val, outputFolder);
1936
+ if (corrected === null) continue;
1937
+ lines[i] = `${indent}${key}${eq}"${corrected}"${trailer}`;
1938
+ changed++;
1939
+ }
1940
+
1941
+ if (changed > 0) {
1942
+ fs.writeFileSync(tomlPath, lines.join(eol), 'utf-8');
1943
+ }
1944
+ return changed;
1945
+ }
1946
+
1947
+ /**
1948
+ * Rewrite contaminated artifact paths inside a per-module `_bmad/<mod>/config.yaml`.
1949
+ * Returns the number of keys changed. Uses js-yaml so we keep schema fidelity.
1950
+ */
1951
+ function normalizeYamlOutputFolders(yamlPath, outputFolder) {
1952
+ if (!fs.existsSync(yamlPath)) return 0;
1953
+ let raw;
1954
+ try {
1955
+ raw = fs.readFileSync(yamlPath, 'utf-8');
1956
+ } catch {
1957
+ return 0;
1958
+ }
1959
+ let doc;
1960
+ try {
1961
+ doc = yaml.parse(raw);
1962
+ } catch {
1963
+ return 0;
1964
+ }
1965
+ if (!doc || typeof doc !== 'object') return 0;
1966
+
1967
+ let changed = 0;
1968
+ for (const key of OUTPUT_FOLDER_ARTIFACT_KEYS) {
1969
+ if (typeof doc[key] !== 'string') continue;
1970
+ const corrected = correctArtifactPath(doc[key], outputFolder);
1971
+ if (corrected === null) continue;
1972
+ doc[key] = corrected;
1973
+ changed++;
1974
+ }
1975
+
1976
+ if (changed > 0) {
1977
+ // Preserve the leading comment header (everything up to the first
1978
+ // non-comment, non-blank line) so the "Generated by BMAD installer"
1979
+ // banner survives the rewrite.
1980
+ const headerLines = [];
1981
+ for (const l of raw.split(/\r?\n/)) {
1982
+ if (l.trim() === '' || l.trimStart().startsWith('#')) {
1983
+ headerLines.push(l);
1984
+ } else {
1985
+ break;
1986
+ }
1987
+ }
1988
+ const header = headerLines.length > 0 ? headerLines.join('\n') + '\n' : '';
1989
+ fs.writeFileSync(yamlPath, header + yaml.stringify(doc), 'utf-8');
1990
+ }
1991
+ return changed;
1992
+ }
1993
+
1994
+ /**
1995
+ * Bug 27.14 — post-install pass that re-points any contaminated module artifact
1996
+ * path at the canonical `[core] output_folder`. Reads the output folder from
1997
+ * `_bmad/config.toml` (the install-owned source of truth), then normalizes both
1998
+ * `_bmad/config.toml` and every `_bmad/<mod>/config.yaml`.
1999
+ *
2000
+ * Idempotent and non-fatal: a second run finds nothing to change, and any I/O
2001
+ * error is logged and swallowed (config normalization must never abort an
2002
+ * otherwise-green install).
2003
+ *
2004
+ * @param {string} projectRoot - Absolute path to the project root.
2005
+ * @returns {number} Total number of artifact paths rewritten (for tests/logging).
2006
+ */
2007
+ function normalizeModuleOutputFolders(projectRoot) {
2008
+ if (typeof projectRoot !== 'string' || !projectRoot) return 0;
2009
+ const tomlPath = path.join(projectRoot, BMAD_DIR, 'config.toml');
2010
+ if (!fs.existsSync(tomlPath)) return 0;
2011
+
2012
+ let tomlRaw;
2013
+ try {
2014
+ tomlRaw = fs.readFileSync(tomlPath, 'utf-8');
2015
+ } catch {
2016
+ return 0;
2017
+ }
2018
+
2019
+ // Extract `[core] output_folder = "..."`. Only the value inside the [core]
2020
+ // section counts; module sections may carry their own output_folder-like keys.
2021
+ let outputFolder = null;
2022
+ let inCore = false;
2023
+ for (const line of tomlRaw.split(/\r?\n/)) {
2024
+ const section = line.match(/^\s*\[([^\]]+)\]\s*$/);
2025
+ if (section) {
2026
+ inCore = section[1].trim() === 'core';
2027
+ continue;
2028
+ }
2029
+ if (!inCore) continue;
2030
+ const kv = line.match(/^\s*output_folder\s*=\s*"([^"]*)"/);
2031
+ if (kv) {
2032
+ outputFolder = kv[1].trim();
2033
+ break;
2034
+ }
2035
+ }
2036
+ if (!outputFolder) return 0; // nothing canonical to normalize against
2037
+
2038
+ let total = 0;
2039
+ try {
2040
+ total += normalizeTomlOutputFolders(tomlPath, outputFolder);
2041
+
2042
+ // Walk each `_bmad/<mod>/config.yaml`.
2043
+ const bmadDir = path.join(projectRoot, BMAD_DIR);
2044
+ let entries = [];
2045
+ try {
2046
+ entries = fs.readdirSync(bmadDir, { withFileTypes: true });
2047
+ } catch {
2048
+ entries = [];
2049
+ }
2050
+ for (const entry of entries) {
2051
+ if (!entry.isDirectory()) continue;
2052
+ const cfg = path.join(bmadDir, entry.name, 'config.yaml');
2053
+ total += normalizeYamlOutputFolders(cfg, outputFolder);
2054
+ }
2055
+ } catch (err) {
2056
+ console.warn(chalk.yellow(` Warning: output-folder normalization skipped: ${err.message}`));
2057
+ return total;
2058
+ }
2059
+
2060
+ if (total > 0) {
2061
+ console.log(chalk.green(
2062
+ ` Normalized ${total} module artifact path(s) to output folder "${outputFolder}/" (bug 27.14 work-around)`
2063
+ ));
2064
+ }
2065
+ return total;
2066
+ }
2067
+
1734
2068
  /**
1735
2069
  * Migration shim: normalize the project layout so that canonical config lives
1736
2070
  * at `_bmad/bmm/config.yaml` (v6.3.0) instead of `_bmad/_config/manifest.yaml`
@@ -1793,7 +2127,7 @@ function ensureCanonicalConfigLocation(projectRoot) {
1793
2127
 
1794
2128
  // ── Migration constants ─────────────────────────────────────────────────────
1795
2129
 
1796
- const BMAD_TARGET_VERSION = '6.6.0';
2130
+ const BMAD_TARGET_VERSION = '6.8.0';
1797
2131
  const BMAD_MIGRATION_THRESHOLD = '6.2.0'; // versions below this need migration
1798
2132
  const BACKUP_DIR_NAME = '.backup-pre-migration';
1799
2133
 
@@ -2733,10 +3067,15 @@ function restoreGitDir(moduleDir) {
2733
3067
  }
2734
3068
  fs.renameSync(preserved, gitDir);
2735
3069
 
2736
- // Point origin at the local directory so `git fetch origin` succeeds offline
3070
+ // Point origin at the local directory so `git fetch origin` succeeds offline.
3071
+ // Use pathToFileURL so a Windows absolute path becomes a well-formed
3072
+ // `file:///C:/...` URL (three slashes) rather than `file://C:/...`, and so
3073
+ // paths containing spaces or other reserved characters are percent-encoded.
3074
+ // execFileSync (arg array) avoids shell interpolation — matching the rest of
3075
+ // the codebase's git calls (see scripts/build-bmad-cache.js).
2737
3076
  try {
2738
- const localUrl = 'file://' + moduleDir.replace(/\\/g, '/');
2739
- execSync(`git remote set-url origin "${localUrl}"`, {
3077
+ const localUrl = pathToFileURL(moduleDir).href;
3078
+ execFileSync('git', ['remote', 'set-url', 'origin', localUrl], {
2740
3079
  cwd: moduleDir,
2741
3080
  stdio: 'pipe'
2742
3081
  });
@@ -2754,8 +3093,12 @@ module.exports = {
2754
3093
  prePopulateBmadCache,
2755
3094
  deployMethodology,
2756
3095
  deployClineWorkflows,
3096
+ // Story 27.4 — exported for unit tests of stale-wrapper reconciliation
3097
+ isGeneratedClineWrapper,
2757
3098
  // Story 22.7 — canonical config (_bmad/bmm/config.yaml) helpers
2758
3099
  readCanonicalBmadConfig,
3100
+ normalizeModuleOutputFolders,
3101
+ correctArtifactPath,
2759
3102
  ensureCanonicalConfigLocation,
2760
3103
  CANONICAL_CONFIG_REL,
2761
3104
  LEGACY_MANIFEST_REL,