mustflow 1.18.16 → 1.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. package/README.md +16 -6
  2. package/dist/cli/commands/adapters.js +90 -0
  3. package/dist/cli/commands/classify.js +3 -4
  4. package/dist/cli/commands/contract-lint.js +26 -6
  5. package/dist/cli/commands/dashboard.js +103 -4
  6. package/dist/cli/commands/explain-verify.js +213 -0
  7. package/dist/cli/commands/explain.js +48 -4
  8. package/dist/cli/commands/handoff.js +136 -0
  9. package/dist/cli/commands/run.js +97 -136
  10. package/dist/cli/commands/update.js +91 -61
  11. package/dist/cli/commands/verify.js +230 -137
  12. package/dist/cli/i18n/en.js +65 -4
  13. package/dist/cli/i18n/es.js +65 -4
  14. package/dist/cli/i18n/fr.js +65 -4
  15. package/dist/cli/i18n/hi.js +65 -4
  16. package/dist/cli/i18n/ko.js +65 -4
  17. package/dist/cli/i18n/zh.js +65 -4
  18. package/dist/cli/index.js +11 -0
  19. package/dist/cli/lib/command-registry.js +10 -0
  20. package/dist/cli/lib/dashboard-export.js +775 -0
  21. package/dist/cli/lib/local-index.js +22 -6
  22. package/dist/cli/lib/run-plan.js +222 -0
  23. package/dist/cli/lib/templates.js +18 -3
  24. package/dist/cli/lib/update-diff-preview.js +163 -0
  25. package/dist/cli/lib/validation.js +22 -0
  26. package/dist/core/adapter-compatibility.js +235 -0
  27. package/dist/core/change-classification.js +9 -0
  28. package/dist/core/change-verification.js +10 -3
  29. package/dist/core/check-issues.js +4 -0
  30. package/dist/core/command-contract-validation.js +14 -0
  31. package/dist/core/command-cwd.js +18 -6
  32. package/dist/core/command-env.js +91 -0
  33. package/dist/core/contract-lint.js +165 -3
  34. package/dist/core/contract-models.js +172 -0
  35. package/dist/core/dashboard-verification.js +2 -0
  36. package/dist/core/doc-review-triage.js +1 -0
  37. package/dist/core/handoff-record.js +376 -0
  38. package/dist/core/public-json-contracts.js +16 -0
  39. package/dist/core/run-receipt.js +46 -7
  40. package/dist/core/run-write-drift.js +180 -0
  41. package/dist/core/secret-redaction.js +39 -0
  42. package/dist/core/source-anchors.js +3 -5
  43. package/dist/core/verification-decision-graph.js +223 -0
  44. package/package.json +3 -1
  45. package/schemas/README.md +11 -4
  46. package/schemas/adapter-compatibility-report.schema.json +184 -0
  47. package/schemas/change-verification-report.schema.json +133 -1
  48. package/schemas/commands.schema.json +8 -1
  49. package/schemas/contract-lint-report.schema.json +48 -0
  50. package/schemas/explain-report.schema.json +265 -2
  51. package/schemas/handoff-validation-report.schema.json +68 -0
  52. package/schemas/run-receipt.schema.json +74 -1
  53. package/templates/default/common/.mustflow/config/commands.toml +2 -0
  54. package/templates/default/i18n.toml +78 -234
  55. package/templates/default/locales/en/.mustflow/skills/INDEX.md +7 -3
  56. package/templates/default/locales/en/.mustflow/skills/architecture-deepening-review/SKILL.md +154 -0
  57. package/templates/default/locales/en/.mustflow/skills/behavior-preserving-refactor/SKILL.md +8 -3
  58. package/templates/default/locales/en/.mustflow/skills/code-review/SKILL.md +9 -4
  59. package/templates/default/locales/en/.mustflow/skills/date-number-audit/SKILL.md +19 -4
  60. package/templates/default/locales/en/.mustflow/skills/diff-risk-review/SKILL.md +4 -2
  61. package/templates/default/locales/en/.mustflow/skills/external-skill-intake/SKILL.md +141 -0
  62. package/templates/default/locales/en/.mustflow/skills/release-notes-authoring/SKILL.md +143 -0
  63. package/templates/default/locales/en/.mustflow/skills/repro-first-debug/SKILL.md +22 -8
  64. package/templates/default/locales/en/.mustflow/skills/skill-authoring/SKILL.md +3 -3
  65. package/templates/default/locales/en/.mustflow/skills/source-freshness-check/SKILL.md +22 -9
  66. package/templates/default/locales/en/.mustflow/skills/ui-quality-gate/SKILL.md +21 -13
  67. package/templates/default/locales/en/.mustflow/skills/vertical-slice-tdd/SKILL.md +167 -0
  68. package/templates/default/manifest.toml +16 -1
  69. package/templates/default/locales/es/.mustflow/skills/INDEX.md +0 -75
  70. package/templates/default/locales/es/.mustflow/skills/adapter-boundary/SKILL.md +0 -193
  71. package/templates/default/locales/es/.mustflow/skills/artifact-integrity-check/SKILL.md +0 -114
  72. package/templates/default/locales/es/.mustflow/skills/behavior-preserving-refactor/SKILL.md +0 -182
  73. package/templates/default/locales/es/.mustflow/skills/code-review/SKILL.md +0 -115
  74. package/templates/default/locales/es/.mustflow/skills/codebase-orientation/SKILL.md +0 -115
  75. package/templates/default/locales/es/.mustflow/skills/command-pattern/SKILL.md +0 -247
  76. package/templates/default/locales/es/.mustflow/skills/composition-over-inheritance/SKILL.md +0 -176
  77. package/templates/default/locales/es/.mustflow/skills/contract-sync-check/SKILL.md +0 -116
  78. package/templates/default/locales/es/.mustflow/skills/database-change-safety/SKILL.md +0 -155
  79. package/templates/default/locales/es/.mustflow/skills/date-number-audit/SKILL.md +0 -116
  80. package/templates/default/locales/es/.mustflow/skills/dependency-injection/SKILL.md +0 -161
  81. package/templates/default/locales/es/.mustflow/skills/dependency-reality-check/SKILL.md +0 -115
  82. package/templates/default/locales/es/.mustflow/skills/diff-risk-review/SKILL.md +0 -136
  83. package/templates/default/locales/es/.mustflow/skills/docs-prose-review/SKILL.md +0 -119
  84. package/templates/default/locales/es/.mustflow/skills/docs-update/SKILL.md +0 -97
  85. package/templates/default/locales/es/.mustflow/skills/external-prompt-injection-defense/SKILL.md +0 -116
  86. package/templates/default/locales/es/.mustflow/skills/facade-pattern/SKILL.md +0 -210
  87. package/templates/default/locales/es/.mustflow/skills/failure-triage/SKILL.md +0 -97
  88. package/templates/default/locales/es/.mustflow/skills/instruction-conflict-scope-check/SKILL.md +0 -118
  89. package/templates/default/locales/es/.mustflow/skills/line-ending-hygiene/SKILL.md +0 -111
  90. package/templates/default/locales/es/.mustflow/skills/migration-safety-check/SKILL.md +0 -117
  91. package/templates/default/locales/es/.mustflow/skills/multi-agent-work-coordination/SKILL.md +0 -260
  92. package/templates/default/locales/es/.mustflow/skills/null-object-pattern/SKILL.md +0 -196
  93. package/templates/default/locales/es/.mustflow/skills/pattern-scout/SKILL.md +0 -110
  94. package/templates/default/locales/es/.mustflow/skills/performance-budget-check/SKILL.md +0 -121
  95. package/templates/default/locales/es/.mustflow/skills/project-context-authoring/SKILL.md +0 -107
  96. package/templates/default/locales/es/.mustflow/skills/pure-core-imperative-shell/SKILL.md +0 -212
  97. package/templates/default/locales/es/.mustflow/skills/readme-authoring/SKILL.md +0 -115
  98. package/templates/default/locales/es/.mustflow/skills/repo-improvement-loop/SKILL.md +0 -150
  99. package/templates/default/locales/es/.mustflow/skills/repro-first-debug/SKILL.md +0 -112
  100. package/templates/default/locales/es/.mustflow/skills/requirement-regression-guard/SKILL.md +0 -152
  101. package/templates/default/locales/es/.mustflow/skills/result-option/SKILL.md +0 -186
  102. package/templates/default/locales/es/.mustflow/skills/security-privacy-review/SKILL.md +0 -116
  103. package/templates/default/locales/es/.mustflow/skills/security-regression-tests/SKILL.md +0 -131
  104. package/templates/default/locales/es/.mustflow/skills/skill-authoring/SKILL.md +0 -110
  105. package/templates/default/locales/es/.mustflow/skills/source-freshness-check/SKILL.md +0 -111
  106. package/templates/default/locales/es/.mustflow/skills/state-machine-pattern/SKILL.md +0 -214
  107. package/templates/default/locales/es/.mustflow/skills/strategy-pattern/SKILL.md +0 -215
  108. package/templates/default/locales/es/.mustflow/skills/structure-discovery-gate/SKILL.md +0 -159
  109. package/templates/default/locales/es/.mustflow/skills/test-design-guard/SKILL.md +0 -162
  110. package/templates/default/locales/es/.mustflow/skills/test-maintenance/SKILL.md +0 -122
  111. package/templates/default/locales/es/.mustflow/skills/ui-quality-gate/SKILL.md +0 -117
  112. package/templates/default/locales/es/.mustflow/skills/visual-review-artifact/SKILL.md +0 -127
  113. package/templates/default/locales/es/.mustflow/skills/visual-review-artifact/assets/review-template.html +0 -286
  114. package/templates/default/locales/es/.mustflow/skills/visual-review-artifact/resources.toml +0 -7
  115. package/templates/default/locales/es/.mustflow/skills/web-asset-optimization/SKILL.md +0 -108
  116. package/templates/default/locales/fr/.mustflow/skills/INDEX.md +0 -75
  117. package/templates/default/locales/fr/.mustflow/skills/adapter-boundary/SKILL.md +0 -193
  118. package/templates/default/locales/fr/.mustflow/skills/artifact-integrity-check/SKILL.md +0 -114
  119. package/templates/default/locales/fr/.mustflow/skills/behavior-preserving-refactor/SKILL.md +0 -182
  120. package/templates/default/locales/fr/.mustflow/skills/code-review/SKILL.md +0 -115
  121. package/templates/default/locales/fr/.mustflow/skills/codebase-orientation/SKILL.md +0 -115
  122. package/templates/default/locales/fr/.mustflow/skills/command-pattern/SKILL.md +0 -247
  123. package/templates/default/locales/fr/.mustflow/skills/composition-over-inheritance/SKILL.md +0 -176
  124. package/templates/default/locales/fr/.mustflow/skills/contract-sync-check/SKILL.md +0 -116
  125. package/templates/default/locales/fr/.mustflow/skills/database-change-safety/SKILL.md +0 -155
  126. package/templates/default/locales/fr/.mustflow/skills/date-number-audit/SKILL.md +0 -116
  127. package/templates/default/locales/fr/.mustflow/skills/dependency-injection/SKILL.md +0 -161
  128. package/templates/default/locales/fr/.mustflow/skills/dependency-reality-check/SKILL.md +0 -115
  129. package/templates/default/locales/fr/.mustflow/skills/diff-risk-review/SKILL.md +0 -136
  130. package/templates/default/locales/fr/.mustflow/skills/docs-prose-review/SKILL.md +0 -119
  131. package/templates/default/locales/fr/.mustflow/skills/docs-update/SKILL.md +0 -97
  132. package/templates/default/locales/fr/.mustflow/skills/external-prompt-injection-defense/SKILL.md +0 -116
  133. package/templates/default/locales/fr/.mustflow/skills/facade-pattern/SKILL.md +0 -210
  134. package/templates/default/locales/fr/.mustflow/skills/failure-triage/SKILL.md +0 -97
  135. package/templates/default/locales/fr/.mustflow/skills/instruction-conflict-scope-check/SKILL.md +0 -118
  136. package/templates/default/locales/fr/.mustflow/skills/line-ending-hygiene/SKILL.md +0 -111
  137. package/templates/default/locales/fr/.mustflow/skills/migration-safety-check/SKILL.md +0 -117
  138. package/templates/default/locales/fr/.mustflow/skills/multi-agent-work-coordination/SKILL.md +0 -260
  139. package/templates/default/locales/fr/.mustflow/skills/null-object-pattern/SKILL.md +0 -196
  140. package/templates/default/locales/fr/.mustflow/skills/pattern-scout/SKILL.md +0 -110
  141. package/templates/default/locales/fr/.mustflow/skills/performance-budget-check/SKILL.md +0 -121
  142. package/templates/default/locales/fr/.mustflow/skills/project-context-authoring/SKILL.md +0 -107
  143. package/templates/default/locales/fr/.mustflow/skills/pure-core-imperative-shell/SKILL.md +0 -212
  144. package/templates/default/locales/fr/.mustflow/skills/readme-authoring/SKILL.md +0 -115
  145. package/templates/default/locales/fr/.mustflow/skills/repo-improvement-loop/SKILL.md +0 -150
  146. package/templates/default/locales/fr/.mustflow/skills/repro-first-debug/SKILL.md +0 -112
  147. package/templates/default/locales/fr/.mustflow/skills/requirement-regression-guard/SKILL.md +0 -152
  148. package/templates/default/locales/fr/.mustflow/skills/result-option/SKILL.md +0 -186
  149. package/templates/default/locales/fr/.mustflow/skills/security-privacy-review/SKILL.md +0 -116
  150. package/templates/default/locales/fr/.mustflow/skills/security-regression-tests/SKILL.md +0 -131
  151. package/templates/default/locales/fr/.mustflow/skills/skill-authoring/SKILL.md +0 -110
  152. package/templates/default/locales/fr/.mustflow/skills/source-freshness-check/SKILL.md +0 -111
  153. package/templates/default/locales/fr/.mustflow/skills/state-machine-pattern/SKILL.md +0 -214
  154. package/templates/default/locales/fr/.mustflow/skills/strategy-pattern/SKILL.md +0 -215
  155. package/templates/default/locales/fr/.mustflow/skills/structure-discovery-gate/SKILL.md +0 -159
  156. package/templates/default/locales/fr/.mustflow/skills/test-design-guard/SKILL.md +0 -162
  157. package/templates/default/locales/fr/.mustflow/skills/test-maintenance/SKILL.md +0 -122
  158. package/templates/default/locales/fr/.mustflow/skills/ui-quality-gate/SKILL.md +0 -117
  159. package/templates/default/locales/fr/.mustflow/skills/visual-review-artifact/SKILL.md +0 -127
  160. package/templates/default/locales/fr/.mustflow/skills/visual-review-artifact/assets/review-template.html +0 -286
  161. package/templates/default/locales/fr/.mustflow/skills/visual-review-artifact/resources.toml +0 -7
  162. package/templates/default/locales/fr/.mustflow/skills/web-asset-optimization/SKILL.md +0 -108
  163. package/templates/default/locales/hi/.mustflow/skills/INDEX.md +0 -75
  164. package/templates/default/locales/hi/.mustflow/skills/adapter-boundary/SKILL.md +0 -193
  165. package/templates/default/locales/hi/.mustflow/skills/artifact-integrity-check/SKILL.md +0 -114
  166. package/templates/default/locales/hi/.mustflow/skills/behavior-preserving-refactor/SKILL.md +0 -182
  167. package/templates/default/locales/hi/.mustflow/skills/code-review/SKILL.md +0 -115
  168. package/templates/default/locales/hi/.mustflow/skills/codebase-orientation/SKILL.md +0 -115
  169. package/templates/default/locales/hi/.mustflow/skills/command-pattern/SKILL.md +0 -247
  170. package/templates/default/locales/hi/.mustflow/skills/composition-over-inheritance/SKILL.md +0 -176
  171. package/templates/default/locales/hi/.mustflow/skills/contract-sync-check/SKILL.md +0 -116
  172. package/templates/default/locales/hi/.mustflow/skills/database-change-safety/SKILL.md +0 -155
  173. package/templates/default/locales/hi/.mustflow/skills/date-number-audit/SKILL.md +0 -116
  174. package/templates/default/locales/hi/.mustflow/skills/dependency-injection/SKILL.md +0 -161
  175. package/templates/default/locales/hi/.mustflow/skills/dependency-reality-check/SKILL.md +0 -115
  176. package/templates/default/locales/hi/.mustflow/skills/diff-risk-review/SKILL.md +0 -136
  177. package/templates/default/locales/hi/.mustflow/skills/docs-prose-review/SKILL.md +0 -119
  178. package/templates/default/locales/hi/.mustflow/skills/docs-update/SKILL.md +0 -97
  179. package/templates/default/locales/hi/.mustflow/skills/external-prompt-injection-defense/SKILL.md +0 -116
  180. package/templates/default/locales/hi/.mustflow/skills/facade-pattern/SKILL.md +0 -210
  181. package/templates/default/locales/hi/.mustflow/skills/failure-triage/SKILL.md +0 -97
  182. package/templates/default/locales/hi/.mustflow/skills/instruction-conflict-scope-check/SKILL.md +0 -118
  183. package/templates/default/locales/hi/.mustflow/skills/line-ending-hygiene/SKILL.md +0 -111
  184. package/templates/default/locales/hi/.mustflow/skills/migration-safety-check/SKILL.md +0 -117
  185. package/templates/default/locales/hi/.mustflow/skills/multi-agent-work-coordination/SKILL.md +0 -260
  186. package/templates/default/locales/hi/.mustflow/skills/null-object-pattern/SKILL.md +0 -196
  187. package/templates/default/locales/hi/.mustflow/skills/pattern-scout/SKILL.md +0 -110
  188. package/templates/default/locales/hi/.mustflow/skills/performance-budget-check/SKILL.md +0 -121
  189. package/templates/default/locales/hi/.mustflow/skills/project-context-authoring/SKILL.md +0 -107
  190. package/templates/default/locales/hi/.mustflow/skills/pure-core-imperative-shell/SKILL.md +0 -212
  191. package/templates/default/locales/hi/.mustflow/skills/readme-authoring/SKILL.md +0 -115
  192. package/templates/default/locales/hi/.mustflow/skills/repo-improvement-loop/SKILL.md +0 -150
  193. package/templates/default/locales/hi/.mustflow/skills/repro-first-debug/SKILL.md +0 -112
  194. package/templates/default/locales/hi/.mustflow/skills/requirement-regression-guard/SKILL.md +0 -152
  195. package/templates/default/locales/hi/.mustflow/skills/result-option/SKILL.md +0 -186
  196. package/templates/default/locales/hi/.mustflow/skills/security-privacy-review/SKILL.md +0 -116
  197. package/templates/default/locales/hi/.mustflow/skills/security-regression-tests/SKILL.md +0 -131
  198. package/templates/default/locales/hi/.mustflow/skills/skill-authoring/SKILL.md +0 -110
  199. package/templates/default/locales/hi/.mustflow/skills/source-freshness-check/SKILL.md +0 -111
  200. package/templates/default/locales/hi/.mustflow/skills/state-machine-pattern/SKILL.md +0 -214
  201. package/templates/default/locales/hi/.mustflow/skills/strategy-pattern/SKILL.md +0 -215
  202. package/templates/default/locales/hi/.mustflow/skills/structure-discovery-gate/SKILL.md +0 -159
  203. package/templates/default/locales/hi/.mustflow/skills/test-design-guard/SKILL.md +0 -162
  204. package/templates/default/locales/hi/.mustflow/skills/test-maintenance/SKILL.md +0 -122
  205. package/templates/default/locales/hi/.mustflow/skills/ui-quality-gate/SKILL.md +0 -117
  206. package/templates/default/locales/hi/.mustflow/skills/visual-review-artifact/SKILL.md +0 -127
  207. package/templates/default/locales/hi/.mustflow/skills/visual-review-artifact/assets/review-template.html +0 -286
  208. package/templates/default/locales/hi/.mustflow/skills/visual-review-artifact/resources.toml +0 -7
  209. package/templates/default/locales/hi/.mustflow/skills/web-asset-optimization/SKILL.md +0 -108
  210. package/templates/default/locales/ko/.mustflow/skills/INDEX.md +0 -80
  211. package/templates/default/locales/ko/.mustflow/skills/adapter-boundary/SKILL.md +0 -193
  212. package/templates/default/locales/ko/.mustflow/skills/artifact-integrity-check/SKILL.md +0 -114
  213. package/templates/default/locales/ko/.mustflow/skills/behavior-preserving-refactor/SKILL.md +0 -182
  214. package/templates/default/locales/ko/.mustflow/skills/code-review/SKILL.md +0 -118
  215. package/templates/default/locales/ko/.mustflow/skills/codebase-orientation/SKILL.md +0 -115
  216. package/templates/default/locales/ko/.mustflow/skills/command-pattern/SKILL.md +0 -247
  217. package/templates/default/locales/ko/.mustflow/skills/composition-over-inheritance/SKILL.md +0 -176
  218. package/templates/default/locales/ko/.mustflow/skills/contract-sync-check/SKILL.md +0 -116
  219. package/templates/default/locales/ko/.mustflow/skills/database-change-safety/SKILL.md +0 -155
  220. package/templates/default/locales/ko/.mustflow/skills/date-number-audit/SKILL.md +0 -116
  221. package/templates/default/locales/ko/.mustflow/skills/dependency-injection/SKILL.md +0 -161
  222. package/templates/default/locales/ko/.mustflow/skills/dependency-reality-check/SKILL.md +0 -115
  223. package/templates/default/locales/ko/.mustflow/skills/diff-risk-review/SKILL.md +0 -136
  224. package/templates/default/locales/ko/.mustflow/skills/docs-prose-review/SKILL.md +0 -119
  225. package/templates/default/locales/ko/.mustflow/skills/docs-update/SKILL.md +0 -107
  226. package/templates/default/locales/ko/.mustflow/skills/external-prompt-injection-defense/SKILL.md +0 -116
  227. package/templates/default/locales/ko/.mustflow/skills/facade-pattern/SKILL.md +0 -210
  228. package/templates/default/locales/ko/.mustflow/skills/failure-triage/SKILL.md +0 -119
  229. package/templates/default/locales/ko/.mustflow/skills/instruction-conflict-scope-check/SKILL.md +0 -118
  230. package/templates/default/locales/ko/.mustflow/skills/line-ending-hygiene/SKILL.md +0 -111
  231. package/templates/default/locales/ko/.mustflow/skills/migration-safety-check/SKILL.md +0 -117
  232. package/templates/default/locales/ko/.mustflow/skills/multi-agent-work-coordination/SKILL.md +0 -259
  233. package/templates/default/locales/ko/.mustflow/skills/null-object-pattern/SKILL.md +0 -196
  234. package/templates/default/locales/ko/.mustflow/skills/pattern-scout/SKILL.md +0 -110
  235. package/templates/default/locales/ko/.mustflow/skills/performance-budget-check/SKILL.md +0 -121
  236. package/templates/default/locales/ko/.mustflow/skills/project-context-authoring/SKILL.md +0 -107
  237. package/templates/default/locales/ko/.mustflow/skills/pure-core-imperative-shell/SKILL.md +0 -212
  238. package/templates/default/locales/ko/.mustflow/skills/readme-authoring/SKILL.md +0 -115
  239. package/templates/default/locales/ko/.mustflow/skills/repo-improvement-loop/SKILL.md +0 -150
  240. package/templates/default/locales/ko/.mustflow/skills/repro-first-debug/SKILL.md +0 -112
  241. package/templates/default/locales/ko/.mustflow/skills/requirement-regression-guard/SKILL.md +0 -152
  242. package/templates/default/locales/ko/.mustflow/skills/result-option/SKILL.md +0 -186
  243. package/templates/default/locales/ko/.mustflow/skills/security-privacy-review/SKILL.md +0 -116
  244. package/templates/default/locales/ko/.mustflow/skills/security-regression-tests/SKILL.md +0 -131
  245. package/templates/default/locales/ko/.mustflow/skills/skill-authoring/SKILL.md +0 -110
  246. package/templates/default/locales/ko/.mustflow/skills/source-freshness-check/SKILL.md +0 -111
  247. package/templates/default/locales/ko/.mustflow/skills/state-machine-pattern/SKILL.md +0 -214
  248. package/templates/default/locales/ko/.mustflow/skills/strategy-pattern/SKILL.md +0 -215
  249. package/templates/default/locales/ko/.mustflow/skills/structure-discovery-gate/SKILL.md +0 -159
  250. package/templates/default/locales/ko/.mustflow/skills/test-design-guard/SKILL.md +0 -162
  251. package/templates/default/locales/ko/.mustflow/skills/test-maintenance/SKILL.md +0 -130
  252. package/templates/default/locales/ko/.mustflow/skills/ui-quality-gate/SKILL.md +0 -117
  253. package/templates/default/locales/ko/.mustflow/skills/visual-review-artifact/SKILL.md +0 -127
  254. package/templates/default/locales/ko/.mustflow/skills/visual-review-artifact/assets/review-template.html +0 -286
  255. package/templates/default/locales/ko/.mustflow/skills/visual-review-artifact/resources.toml +0 -7
  256. package/templates/default/locales/ko/.mustflow/skills/web-asset-optimization/SKILL.md +0 -108
  257. package/templates/default/locales/zh/.mustflow/skills/INDEX.md +0 -74
  258. package/templates/default/locales/zh/.mustflow/skills/adapter-boundary/SKILL.md +0 -193
  259. package/templates/default/locales/zh/.mustflow/skills/artifact-integrity-check/SKILL.md +0 -114
  260. package/templates/default/locales/zh/.mustflow/skills/behavior-preserving-refactor/SKILL.md +0 -182
  261. package/templates/default/locales/zh/.mustflow/skills/code-review/SKILL.md +0 -115
  262. package/templates/default/locales/zh/.mustflow/skills/codebase-orientation/SKILL.md +0 -115
  263. package/templates/default/locales/zh/.mustflow/skills/command-pattern/SKILL.md +0 -247
  264. package/templates/default/locales/zh/.mustflow/skills/composition-over-inheritance/SKILL.md +0 -176
  265. package/templates/default/locales/zh/.mustflow/skills/contract-sync-check/SKILL.md +0 -116
  266. package/templates/default/locales/zh/.mustflow/skills/database-change-safety/SKILL.md +0 -155
  267. package/templates/default/locales/zh/.mustflow/skills/date-number-audit/SKILL.md +0 -116
  268. package/templates/default/locales/zh/.mustflow/skills/dependency-injection/SKILL.md +0 -161
  269. package/templates/default/locales/zh/.mustflow/skills/dependency-reality-check/SKILL.md +0 -115
  270. package/templates/default/locales/zh/.mustflow/skills/diff-risk-review/SKILL.md +0 -136
  271. package/templates/default/locales/zh/.mustflow/skills/docs-prose-review/SKILL.md +0 -119
  272. package/templates/default/locales/zh/.mustflow/skills/docs-update/SKILL.md +0 -97
  273. package/templates/default/locales/zh/.mustflow/skills/external-prompt-injection-defense/SKILL.md +0 -116
  274. package/templates/default/locales/zh/.mustflow/skills/facade-pattern/SKILL.md +0 -210
  275. package/templates/default/locales/zh/.mustflow/skills/failure-triage/SKILL.md +0 -96
  276. package/templates/default/locales/zh/.mustflow/skills/instruction-conflict-scope-check/SKILL.md +0 -118
  277. package/templates/default/locales/zh/.mustflow/skills/line-ending-hygiene/SKILL.md +0 -111
  278. package/templates/default/locales/zh/.mustflow/skills/migration-safety-check/SKILL.md +0 -117
  279. package/templates/default/locales/zh/.mustflow/skills/multi-agent-work-coordination/SKILL.md +0 -260
  280. package/templates/default/locales/zh/.mustflow/skills/null-object-pattern/SKILL.md +0 -196
  281. package/templates/default/locales/zh/.mustflow/skills/pattern-scout/SKILL.md +0 -110
  282. package/templates/default/locales/zh/.mustflow/skills/performance-budget-check/SKILL.md +0 -121
  283. package/templates/default/locales/zh/.mustflow/skills/project-context-authoring/SKILL.md +0 -107
  284. package/templates/default/locales/zh/.mustflow/skills/pure-core-imperative-shell/SKILL.md +0 -212
  285. package/templates/default/locales/zh/.mustflow/skills/readme-authoring/SKILL.md +0 -115
  286. package/templates/default/locales/zh/.mustflow/skills/repo-improvement-loop/SKILL.md +0 -150
  287. package/templates/default/locales/zh/.mustflow/skills/repro-first-debug/SKILL.md +0 -112
  288. package/templates/default/locales/zh/.mustflow/skills/requirement-regression-guard/SKILL.md +0 -152
  289. package/templates/default/locales/zh/.mustflow/skills/result-option/SKILL.md +0 -186
  290. package/templates/default/locales/zh/.mustflow/skills/security-privacy-review/SKILL.md +0 -116
  291. package/templates/default/locales/zh/.mustflow/skills/security-regression-tests/SKILL.md +0 -131
  292. package/templates/default/locales/zh/.mustflow/skills/skill-authoring/SKILL.md +0 -110
  293. package/templates/default/locales/zh/.mustflow/skills/source-freshness-check/SKILL.md +0 -111
  294. package/templates/default/locales/zh/.mustflow/skills/state-machine-pattern/SKILL.md +0 -214
  295. package/templates/default/locales/zh/.mustflow/skills/strategy-pattern/SKILL.md +0 -215
  296. package/templates/default/locales/zh/.mustflow/skills/structure-discovery-gate/SKILL.md +0 -159
  297. package/templates/default/locales/zh/.mustflow/skills/test-design-guard/SKILL.md +0 -162
  298. package/templates/default/locales/zh/.mustflow/skills/test-maintenance/SKILL.md +0 -122
  299. package/templates/default/locales/zh/.mustflow/skills/ui-quality-gate/SKILL.md +0 -117
  300. package/templates/default/locales/zh/.mustflow/skills/visual-review-artifact/SKILL.md +0 -127
  301. package/templates/default/locales/zh/.mustflow/skills/visual-review-artifact/assets/review-template.html +0 -286
  302. package/templates/default/locales/zh/.mustflow/skills/visual-review-artifact/resources.toml +0 -7
  303. package/templates/default/locales/zh/.mustflow/skills/web-asset-optimization/SKILL.md +0 -108
@@ -0,0 +1,775 @@
1
+ import { Buffer } from 'node:buffer';
2
+ import path from 'node:path';
3
+ import { redactSecretLikeText } from '../../core/secret-redaction.js';
4
+ import { ensureFileTargetInsideWithoutSymlinks, ensureInside, toPosixPath, writeUtf8FileInsideWithoutSymlinks, } from './filesystem.js';
5
+ export class DashboardExportPathError extends Error {
6
+ targetPath;
7
+ constructor(targetPath) {
8
+ super(`Dashboard export path escapes mustflow root: ${targetPath}`);
9
+ this.targetPath = targetPath;
10
+ }
11
+ }
12
+ const DASHBOARD_EXPORT_MAX_STRING_BYTES = 8192;
13
+ const DASHBOARD_EXPORT_MAX_ARRAY_ITEMS = 200;
14
+ const DASHBOARD_EXPORT_MAX_DEPTH = 16;
15
+ const DASHBOARD_HARNESS_MAX_ITEMS = 50;
16
+ const DASHBOARD_HARNESS_MAX_PATHS = 8;
17
+ const OMITTED_VALUE = '[omitted by mf dashboard export]';
18
+ const TRUNCATION_SUFFIX = '\n[truncated by mf dashboard export]';
19
+ const SENSITIVE_KEY_PATTERN = /(?:token|secret|password|credential|authorization|api[_-]?key)/iu;
20
+ function isRecord(value) {
21
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
22
+ }
23
+ function fieldPath(pathSegments) {
24
+ return pathSegments.length === 0 ? '<root>' : pathSegments.join('.');
25
+ }
26
+ function truncateUtf8(value, maxBytes) {
27
+ if (Buffer.byteLength(value, 'utf8') <= maxBytes) {
28
+ return value;
29
+ }
30
+ let end = value.length;
31
+ while (end > 0 && Buffer.byteLength(value.slice(0, end) + TRUNCATION_SUFFIX, 'utf8') > maxBytes) {
32
+ end -= 1;
33
+ }
34
+ return `${value.slice(0, end)}${TRUNCATION_SUFFIX}`;
35
+ }
36
+ function sanitizeRunOutput(value, state, pathSegments) {
37
+ state.omittedFields.push(`${fieldPath(pathSegments)}.tail`);
38
+ if (!isRecord(value)) {
39
+ return {
40
+ bytes: 0,
41
+ truncated: false,
42
+ tail_omitted: true,
43
+ redacted: false,
44
+ redaction_count: 0,
45
+ redaction_kinds: [],
46
+ };
47
+ }
48
+ return {
49
+ bytes: typeof value.bytes === 'number' ? value.bytes : 0,
50
+ truncated: value.truncated === true,
51
+ tail_omitted: true,
52
+ redacted: value.redacted === true,
53
+ redaction_count: typeof value.redaction_count === 'number' ? value.redaction_count : 0,
54
+ redaction_kinds: stringArray(value.redaction_kinds),
55
+ };
56
+ }
57
+ function sanitizeRunHistory(value, state) {
58
+ if (!isRecord(value) || value.exists !== true || value.valid !== true) {
59
+ return sanitizeValue(value, state, ['status', 'run_history']);
60
+ }
61
+ state.omittedFields.push('status.run_history.command_line');
62
+ const sanitized = {};
63
+ for (const [key, entry] of Object.entries(value)) {
64
+ if (key === 'command_line') {
65
+ sanitized.command_line_omitted = true;
66
+ continue;
67
+ }
68
+ if (key === 'stdout' || key === 'stderr') {
69
+ sanitized[key] = sanitizeRunOutput(entry, state, ['status', 'run_history', key]);
70
+ continue;
71
+ }
72
+ sanitized[key] = sanitizeValue(entry, state, ['status', 'run_history', key]);
73
+ }
74
+ return sanitized;
75
+ }
76
+ function sanitizeStatus(value, state) {
77
+ const sanitized = {};
78
+ for (const [key, entry] of Object.entries(value)) {
79
+ sanitized[key] =
80
+ key === 'run_history' ? sanitizeRunHistory(entry, state) : sanitizeValue(entry, state, ['status', key]);
81
+ }
82
+ return sanitized;
83
+ }
84
+ function sanitizeValue(value, state, pathSegments, depth = 0) {
85
+ if (value === null || typeof value === 'boolean' || typeof value === 'number') {
86
+ return value;
87
+ }
88
+ if (typeof value === 'string') {
89
+ const redaction = redactSecretLikeText(value);
90
+ if (redaction.redacted) {
91
+ state.redactedFields.push(fieldPath(pathSegments));
92
+ state.redactionCount += redaction.redactionCount;
93
+ for (const kind of redaction.redactionKinds) {
94
+ state.redactionKinds.add(kind);
95
+ }
96
+ }
97
+ const truncated = truncateUtf8(redaction.text, DASHBOARD_EXPORT_MAX_STRING_BYTES);
98
+ if (truncated !== redaction.text) {
99
+ state.truncatedFields.push(fieldPath(pathSegments));
100
+ }
101
+ return truncated;
102
+ }
103
+ if (Array.isArray(value)) {
104
+ const items = value.slice(0, DASHBOARD_EXPORT_MAX_ARRAY_ITEMS);
105
+ if (items.length !== value.length) {
106
+ state.truncatedFields.push(fieldPath(pathSegments));
107
+ }
108
+ return items.map((entry, index) => sanitizeValue(entry, state, [...pathSegments, String(index)], depth + 1));
109
+ }
110
+ if (isRecord(value)) {
111
+ if (depth >= DASHBOARD_EXPORT_MAX_DEPTH) {
112
+ state.truncatedFields.push(fieldPath(pathSegments));
113
+ return '[max depth reached by mf dashboard export]';
114
+ }
115
+ const sanitized = {};
116
+ for (const [key, entry] of Object.entries(value)) {
117
+ const childPath = [...pathSegments, key];
118
+ if (SENSITIVE_KEY_PATTERN.test(key)) {
119
+ state.omittedFields.push(fieldPath(childPath));
120
+ sanitized[key] = OMITTED_VALUE;
121
+ continue;
122
+ }
123
+ sanitized[key] = sanitizeValue(entry, state, childPath, depth + 1);
124
+ }
125
+ return sanitized;
126
+ }
127
+ return String(value);
128
+ }
129
+ function asRecord(value) {
130
+ return isRecord(value) ? value : {};
131
+ }
132
+ function asArray(value) {
133
+ return Array.isArray(value) ? value : [];
134
+ }
135
+ function text(value) {
136
+ if (value === null || value === undefined || value === '') {
137
+ return 'none';
138
+ }
139
+ return String(value);
140
+ }
141
+ function booleanText(value) {
142
+ return value === true ? 'yes' : value === false ? 'no' : text(value);
143
+ }
144
+ function stringOrNull(value) {
145
+ return typeof value === 'string' && value.length > 0 ? value : null;
146
+ }
147
+ function numberOrZero(value) {
148
+ return typeof value === 'number' && Number.isFinite(value) ? value : 0;
149
+ }
150
+ function numberOrNull(value) {
151
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
152
+ }
153
+ function stringArray(value, maxItems = DASHBOARD_HARNESS_MAX_ITEMS) {
154
+ return asArray(value)
155
+ .filter((item) => typeof item === 'string')
156
+ .slice(0, maxItems);
157
+ }
158
+ function createDecisionGraphSummary(value) {
159
+ const graph = asRecord(value);
160
+ if (graph.root !== 'verification_decision') {
161
+ return null;
162
+ }
163
+ const summary = asRecord(graph.summary);
164
+ return {
165
+ root: String(graph.root),
166
+ node_count: numberOrZero(summary.nodeCount),
167
+ edge_count: numberOrZero(summary.edgeCount),
168
+ runnable: numberOrZero(summary.runnable),
169
+ skipped: numberOrZero(summary.skipped),
170
+ blocked: numberOrZero(summary.blocked),
171
+ manual_only: numberOrZero(summary.manual_only),
172
+ unknown: numberOrZero(summary.unknown),
173
+ gap_count: numberOrZero(summary.gapCount),
174
+ };
175
+ }
176
+ function createVerificationGap(node) {
177
+ const kind = stringOrNull(node.kind);
178
+ const status = stringOrNull(node.status);
179
+ const data = asRecord(node.data);
180
+ const gapKind = kind === 'gap'
181
+ ? 'missing'
182
+ : kind === 'command_candidate' && status === 'manual_only'
183
+ ? 'manual_only'
184
+ : kind === 'command_candidate' && status === 'blocked'
185
+ ? 'blocked'
186
+ : kind === 'command_candidate' && status === 'unknown'
187
+ ? 'unknown'
188
+ : null;
189
+ if (!gapKind) {
190
+ return null;
191
+ }
192
+ return {
193
+ kind: gapKind,
194
+ intent: stringOrNull(node.intent),
195
+ reason: stringOrNull(node.reason),
196
+ detail: stringOrNull(data.detail) ?? stringOrNull(data.skipReason),
197
+ files: stringArray(data.files, DASHBOARD_HARNESS_MAX_PATHS),
198
+ surfaces: stringArray(data.surfaces, DASHBOARD_HARNESS_MAX_PATHS),
199
+ };
200
+ }
201
+ function createVerificationGaps(decisionGraph) {
202
+ const graph = asRecord(decisionGraph);
203
+ const gaps = [];
204
+ const seen = new Set();
205
+ for (const entry of asArray(graph.nodes)) {
206
+ const gap = createVerificationGap(asRecord(entry));
207
+ if (!gap) {
208
+ continue;
209
+ }
210
+ const key = [gap.kind, gap.intent ?? '', gap.reason ?? '', gap.detail ?? ''].join('\0');
211
+ if (!seen.has(key)) {
212
+ seen.add(key);
213
+ gaps.push(gap);
214
+ }
215
+ }
216
+ return gaps.slice(0, DASHBOARD_HARNESS_MAX_ITEMS);
217
+ }
218
+ function createRunHistorySummary(status) {
219
+ const runHistory = asRecord(status.run_history);
220
+ const exists = runHistory.exists === true;
221
+ const valid = exists && runHistory.valid === true;
222
+ return {
223
+ path: stringOrNull(runHistory.path) ?? '.mustflow/state/runs/latest.json',
224
+ exists,
225
+ valid,
226
+ intent: valid ? stringOrNull(runHistory.intent) : null,
227
+ status: valid ? stringOrNull(runHistory.status) : null,
228
+ exit_code: valid ? numberOrNull(runHistory.exit_code) : null,
229
+ timed_out: valid ? runHistory.timed_out === true : null,
230
+ finished_at: valid ? stringOrNull(runHistory.finished_at) : null,
231
+ duration_ms: valid ? numberOrNull(runHistory.duration_ms) : null,
232
+ receipt_path: valid ? stringOrNull(runHistory.receipt_path) : null,
233
+ };
234
+ }
235
+ function addHarnessRisk(risks, risk) {
236
+ if (risks.length < DASHBOARD_HARNESS_MAX_ITEMS) {
237
+ risks.push(risk);
238
+ }
239
+ }
240
+ function createRemainingRisks(status, docsReview, decisionGraphSummary) {
241
+ const release = asRecord(status.release);
242
+ const update = asRecord(status.update);
243
+ const verification = asRecord(status.verification);
244
+ const runHistory = createRunHistorySummary(status);
245
+ const risks = [];
246
+ const issues = stringArray(status.issues);
247
+ const changedFiles = stringArray(status.changed_files);
248
+ const missingFiles = stringArray(status.missing_files);
249
+ const releaseSensitiveFiles = stringArray(release.release_sensitive_changed_files);
250
+ const blockers = asArray(update.blockers);
251
+ const activeDocs = numberOrZero(docsReview.count);
252
+ const verificationChangedFiles = stringArray(verification.changed_files);
253
+ const runnableRecommendations = asArray(verification.recommendations).filter((entry) => asRecord(entry).runnable === true);
254
+ for (const issue of issues.slice(0, DASHBOARD_HARNESS_MAX_ITEMS)) {
255
+ addHarnessRisk(risks, { code: 'manifest_issue', severity: 'warning', detail: issue });
256
+ }
257
+ if (changedFiles.length > 0) {
258
+ addHarnessRisk(risks, {
259
+ code: 'tracked_file_changes',
260
+ severity: 'warning',
261
+ detail: 'Tracked mustflow files differ from the manifest lock.',
262
+ count: changedFiles.length,
263
+ paths: changedFiles.slice(0, DASHBOARD_HARNESS_MAX_PATHS),
264
+ });
265
+ }
266
+ if (missingFiles.length > 0) {
267
+ addHarnessRisk(risks, {
268
+ code: 'tracked_file_missing',
269
+ severity: 'error',
270
+ detail: 'Manifest-tracked mustflow files are missing.',
271
+ count: missingFiles.length,
272
+ paths: missingFiles.slice(0, DASHBOARD_HARNESS_MAX_PATHS),
273
+ });
274
+ }
275
+ if (releaseSensitiveFiles.length > 0) {
276
+ addHarnessRisk(risks, {
277
+ code: 'release_sensitive_changes',
278
+ severity: 'warning',
279
+ detail: 'Release-sensitive files changed and may need release verification.',
280
+ count: releaseSensitiveFiles.length,
281
+ paths: releaseSensitiveFiles.slice(0, DASHBOARD_HARNESS_MAX_PATHS),
282
+ });
283
+ }
284
+ if (update.ok === false) {
285
+ addHarnessRisk(risks, {
286
+ code: 'update_plan_unavailable',
287
+ severity: 'warning',
288
+ detail: stringOrNull(update.error) ?? 'Template update dry-run status is not available.',
289
+ });
290
+ }
291
+ if (blockers.length > 0) {
292
+ addHarnessRisk(risks, {
293
+ code: 'template_update_blockers',
294
+ severity: 'warning',
295
+ detail: 'The template update plan has blockers.',
296
+ count: blockers.length,
297
+ });
298
+ }
299
+ if (activeDocs > 0) {
300
+ addHarnessRisk(risks, {
301
+ code: 'docs_review_pending',
302
+ severity: 'warning',
303
+ detail: 'Documentation review entries are still active.',
304
+ count: activeDocs,
305
+ });
306
+ }
307
+ if (verificationChangedFiles.length > 0 && !decisionGraphSummary) {
308
+ addHarnessRisk(risks, {
309
+ code: 'verification_decision_graph_missing',
310
+ severity: 'warning',
311
+ detail: 'Changed files exist, but no verification decision graph is available.',
312
+ count: verificationChangedFiles.length,
313
+ paths: verificationChangedFiles.slice(0, DASHBOARD_HARNESS_MAX_PATHS),
314
+ });
315
+ }
316
+ if (verificationChangedFiles.length > 0 && runnableRecommendations.length === 0) {
317
+ addHarnessRisk(risks, {
318
+ code: 'no_runnable_verification_recommendation',
319
+ severity: 'warning',
320
+ detail: 'Changed files exist, but the dashboard report has no runnable verification recommendation.',
321
+ count: verificationChangedFiles.length,
322
+ });
323
+ }
324
+ if (decisionGraphSummary && decisionGraphSummary.manual_only > 0) {
325
+ addHarnessRisk(risks, {
326
+ code: 'manual_only_verification_gap',
327
+ severity: 'warning',
328
+ detail: 'Some matching verification intents require an explicit user request.',
329
+ count: decisionGraphSummary.manual_only,
330
+ });
331
+ }
332
+ if (decisionGraphSummary && decisionGraphSummary.blocked > 0) {
333
+ addHarnessRisk(risks, {
334
+ code: 'blocked_verification_gap',
335
+ severity: 'warning',
336
+ detail: 'Some matching verification intents are blocked by the command contract.',
337
+ count: decisionGraphSummary.blocked,
338
+ });
339
+ }
340
+ if (decisionGraphSummary && decisionGraphSummary.unknown > 0) {
341
+ addHarnessRisk(risks, {
342
+ code: 'unknown_verification_gap',
343
+ severity: 'warning',
344
+ detail: 'Some changed surfaces lack known runnable verification coverage.',
345
+ count: decisionGraphSummary.unknown,
346
+ });
347
+ }
348
+ if (decisionGraphSummary && decisionGraphSummary.gap_count > 0) {
349
+ addHarnessRisk(risks, {
350
+ code: 'missing_verification_gap',
351
+ severity: 'warning',
352
+ detail: 'The verification decision graph reports missing coverage gaps.',
353
+ count: decisionGraphSummary.gap_count,
354
+ });
355
+ }
356
+ if (!runHistory.exists) {
357
+ addHarnessRisk(risks, {
358
+ code: 'latest_run_missing',
359
+ severity: 'info',
360
+ detail: 'No latest mf run receipt is available.',
361
+ });
362
+ }
363
+ else if (!runHistory.valid) {
364
+ addHarnessRisk(risks, {
365
+ code: 'latest_run_invalid',
366
+ severity: 'warning',
367
+ detail: 'The latest mf run receipt could not be read as a valid receipt.',
368
+ });
369
+ }
370
+ return risks;
371
+ }
372
+ function createDashboardHarnessReport(statusValue, docsReviewValue) {
373
+ const status = asRecord(statusValue);
374
+ const docsReview = asRecord(docsReviewValue);
375
+ const verification = asRecord(status.verification);
376
+ const decisionGraphSummary = createDecisionGraphSummary(verification.decision_graph);
377
+ const runnableIntents = asArray(verification.recommendations)
378
+ .map(asRecord)
379
+ .filter((entry) => entry.runnable === true)
380
+ .map((entry) => stringOrNull(entry.intent))
381
+ .filter((entry) => entry !== null)
382
+ .slice(0, DASHBOARD_HARNESS_MAX_ITEMS);
383
+ return {
384
+ schema_version: '1',
385
+ generated_from: 'dashboard_status_snapshot',
386
+ install: {
387
+ installed: status.installed === true,
388
+ manifest_lock: text(status.manifest_lock),
389
+ tracked_files: numberOrZero(status.tracked_files),
390
+ changed_files: stringArray(status.changed_files).length,
391
+ missing_files: stringArray(status.missing_files).length,
392
+ issues: stringArray(status.issues).length,
393
+ },
394
+ verification: {
395
+ changed_file_count: stringArray(verification.changed_files).length,
396
+ changed_surfaces: stringArray(verification.surfaces),
397
+ decision_graph_summary: decisionGraphSummary,
398
+ runnable_intents: runnableIntents,
399
+ skipped_intents: asArray(verification.skipped)
400
+ .map(asRecord)
401
+ .map((entry) => ({
402
+ intent: text(entry.intent),
403
+ reason_key: text(entry.reason_key),
404
+ }))
405
+ .slice(0, DASHBOARD_HARNESS_MAX_ITEMS),
406
+ gaps: createVerificationGaps(verification.decision_graph),
407
+ },
408
+ run_history: createRunHistorySummary(status),
409
+ docs_review: {
410
+ ledger_path: text(docsReview.ledger_path),
411
+ active_documents: numberOrZero(docsReview.count),
412
+ },
413
+ remaining_risks: createRemainingRisks(status, docsReview, decisionGraphSummary),
414
+ };
415
+ }
416
+ export function resolveDashboardExportPath(projectRoot, outputPath) {
417
+ const targetPath = path.resolve(projectRoot, outputPath);
418
+ try {
419
+ ensureInside(projectRoot, targetPath);
420
+ ensureFileTargetInsideWithoutSymlinks(projectRoot, targetPath, { allowMissingLeaf: true });
421
+ }
422
+ catch {
423
+ throw new DashboardExportPathError(outputPath);
424
+ }
425
+ return targetPath;
426
+ }
427
+ export function createDashboardExportSnapshot(input) {
428
+ const state = {
429
+ truncatedFields: [],
430
+ omittedFields: [],
431
+ redactedFields: [],
432
+ redactionKinds: new Set(),
433
+ redactionCount: 0,
434
+ };
435
+ const preferences = sanitizeValue(input.preferences, state, ['preferences']);
436
+ const status = sanitizeStatus(input.status, state);
437
+ const docsReview = sanitizeValue(input.docsReview, state, ['docs_review']);
438
+ const snapshot = {
439
+ schema_version: '1',
440
+ command: 'dashboard export',
441
+ format: input.format,
442
+ generated_at: new Date().toISOString(),
443
+ mustflow_root: input.projectRoot,
444
+ output_policy: {
445
+ bounded_to_mustflow_root: true,
446
+ starts_server: false,
447
+ static_html: input.format === 'html',
448
+ contains_mutation_controls: false,
449
+ omits_dashboard_token: true,
450
+ omits_raw_run_output: true,
451
+ redacts_secret_like_values: true,
452
+ },
453
+ preferences,
454
+ status,
455
+ docs_review: docsReview,
456
+ harness_report: createDashboardHarnessReport(status, docsReview),
457
+ };
458
+ return {
459
+ ...snapshot,
460
+ limits: {
461
+ max_string_bytes: DASHBOARD_EXPORT_MAX_STRING_BYTES,
462
+ max_array_items: DASHBOARD_EXPORT_MAX_ARRAY_ITEMS,
463
+ max_depth: DASHBOARD_EXPORT_MAX_DEPTH,
464
+ truncated_fields: [...new Set(state.truncatedFields)].sort(),
465
+ omitted_fields: [...new Set(state.omittedFields)].sort(),
466
+ redacted_fields: [...new Set(state.redactedFields)].sort(),
467
+ redaction_count: state.redactionCount,
468
+ redaction_kinds: [...state.redactionKinds].sort(),
469
+ },
470
+ };
471
+ }
472
+ function escapeHtml(value) {
473
+ return value
474
+ .replace(/&/gu, '&amp;')
475
+ .replace(/</gu, '&lt;')
476
+ .replace(/>/gu, '&gt;')
477
+ .replace(/"/gu, '&quot;')
478
+ .replace(/'/gu, '&#39;');
479
+ }
480
+ function renderMetric(label, value) {
481
+ return `<dt>${escapeHtml(label)}</dt><dd>${escapeHtml(text(value))}</dd>`;
482
+ }
483
+ function renderList(items) {
484
+ if (items.length === 0) {
485
+ return '<p class="empty">none</p>';
486
+ }
487
+ return `<ul>${items.map((item) => `<li>${escapeHtml(text(item))}</li>`).join('')}</ul>`;
488
+ }
489
+ function renderRecommendations(recommendations) {
490
+ if (recommendations.length === 0) {
491
+ return '<p class="empty">none</p>';
492
+ }
493
+ const rows = recommendations
494
+ .map((entry) => {
495
+ const recommendation = asRecord(entry);
496
+ return `<tr><td>${escapeHtml(text(recommendation.intent))}</td><td>${escapeHtml(text(recommendation.command))}</td><td>${escapeHtml(booleanText(recommendation.runnable))}</td></tr>`;
497
+ })
498
+ .join('');
499
+ return `<table><thead><tr><th>Intent</th><th>Command</th><th>Runnable</th></tr></thead><tbody>${rows}</tbody></table>`;
500
+ }
501
+ function renderCommandIntents(intents) {
502
+ if (intents.length === 0) {
503
+ return '<p class="empty">none</p>';
504
+ }
505
+ const rows = intents
506
+ .map((entry) => {
507
+ const intent = asRecord(entry);
508
+ return `<tr><td>${escapeHtml(text(intent.name))}</td><td>${escapeHtml(text(intent.status))}</td><td>${escapeHtml(text(intent.run_policy))}</td><td>${escapeHtml(booleanText(intent.runnable))}</td></tr>`;
509
+ })
510
+ .join('');
511
+ return `<table><thead><tr><th>Name</th><th>Status</th><th>Run policy</th><th>Runnable</th></tr></thead><tbody>${rows}</tbody></table>`;
512
+ }
513
+ function renderSkippedIntents(intents) {
514
+ if (intents.length === 0) {
515
+ return '<p class="empty">none</p>';
516
+ }
517
+ const rows = intents
518
+ .map((entry) => {
519
+ const intent = asRecord(entry);
520
+ return `<tr><td>${escapeHtml(text(intent.intent))}</td><td>${escapeHtml(text(intent.reason_key))}</td></tr>`;
521
+ })
522
+ .join('');
523
+ return `<table><thead><tr><th>Intent</th><th>Reason</th></tr></thead><tbody>${rows}</tbody></table>`;
524
+ }
525
+ function renderVerificationGaps(gaps) {
526
+ if (gaps.length === 0) {
527
+ return '<p class="empty">none</p>';
528
+ }
529
+ const rows = gaps
530
+ .map((entry) => {
531
+ const gap = asRecord(entry);
532
+ return `<tr><td>${escapeHtml(text(gap.kind))}</td><td>${escapeHtml(text(gap.intent))}</td><td>${escapeHtml(text(gap.reason))}</td><td>${escapeHtml(text(gap.detail))}</td></tr>`;
533
+ })
534
+ .join('');
535
+ return `<table><thead><tr><th>Kind</th><th>Intent</th><th>Reason</th><th>Detail</th></tr></thead><tbody>${rows}</tbody></table>`;
536
+ }
537
+ function renderRemainingRisks(risks) {
538
+ if (risks.length === 0) {
539
+ return '<p class="empty">none</p>';
540
+ }
541
+ const rows = risks
542
+ .map((entry) => {
543
+ const risk = asRecord(entry);
544
+ const paths = asArray(risk.paths).map(text).join(', ');
545
+ return `<tr><td>${escapeHtml(text(risk.severity))}</td><td>${escapeHtml(text(risk.code))}</td><td>${escapeHtml(text(risk.count))}</td><td>${escapeHtml(text(risk.detail))}${paths ? `<br>${escapeHtml(paths)}` : ''}</td></tr>`;
546
+ })
547
+ .join('');
548
+ return `<table><thead><tr><th>Severity</th><th>Code</th><th>Count</th><th>Detail</th></tr></thead><tbody>${rows}</tbody></table>`;
549
+ }
550
+ function renderRunHistory(runHistory) {
551
+ if (runHistory.exists !== true) {
552
+ return '<p class="empty">none</p>';
553
+ }
554
+ if (runHistory.valid !== true) {
555
+ return `<p class="empty">${escapeHtml(text(runHistory.error))}</p>`;
556
+ }
557
+ return `<dl>${[
558
+ renderMetric('Intent', runHistory.intent),
559
+ renderMetric('Status', runHistory.status),
560
+ renderMetric('Exit code', runHistory.exit_code),
561
+ renderMetric('Finished', runHistory.finished_at),
562
+ renderMetric('Output tails', 'omitted'),
563
+ ].join('')}</dl>`;
564
+ }
565
+ function renderTruncation(snapshot) {
566
+ const truncated = snapshot.limits.truncated_fields;
567
+ const omitted = snapshot.limits.omitted_fields;
568
+ return `<dl>${[
569
+ renderMetric('Max string bytes', snapshot.limits.max_string_bytes),
570
+ renderMetric('Max array items', snapshot.limits.max_array_items),
571
+ renderMetric('Max depth', snapshot.limits.max_depth),
572
+ ].join('')}</dl><h3>Truncated fields</h3>${renderList(truncated)}<h3>Omitted fields</h3>${renderList(omitted)}`;
573
+ }
574
+ export function renderDashboardExportHtml(snapshot) {
575
+ const status = asRecord(snapshot.status);
576
+ const preferences = asRecord(snapshot.preferences);
577
+ const release = asRecord(status.release);
578
+ const update = asRecord(status.update);
579
+ const verification = asRecord(status.verification);
580
+ const commandContract = asRecord(status.command_contract);
581
+ const docsReview = asRecord(snapshot.docs_review);
582
+ const harnessReport = asRecord(snapshot.harness_report);
583
+ const harnessInstall = asRecord(harnessReport.install);
584
+ const harnessVerification = asRecord(harnessReport.verification);
585
+ const graphSummary = asRecord(harnessVerification.decision_graph_summary);
586
+ const harnessRunHistory = asRecord(harnessReport.run_history);
587
+ const harnessDocsReview = asRecord(harnessReport.docs_review);
588
+ const embeddedJson = JSON.stringify(snapshot).replace(/</gu, '\\u003c');
589
+ return `<!doctype html>
590
+ <html lang="en">
591
+ <head>
592
+ <meta charset="utf-8">
593
+ <meta name="viewport" content="width=device-width, initial-scale=1">
594
+ <title>mustflow dashboard export</title>
595
+ <style>
596
+ :root {
597
+ color-scheme: light dark;
598
+ --bg: #101216;
599
+ --panel: #181b21;
600
+ --line: #2a2f3a;
601
+ --text: #eef1f7;
602
+ --muted: #aeb6c5;
603
+ --accent: #8fb4ff;
604
+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
605
+ }
606
+ * { box-sizing: border-box; }
607
+ body {
608
+ background: var(--bg);
609
+ color: var(--text);
610
+ font-size: 16px;
611
+ line-height: 1.5;
612
+ margin: 0;
613
+ }
614
+ header, main {
615
+ margin: 0 auto;
616
+ max-width: 1100px;
617
+ padding: 18px;
618
+ }
619
+ header { border-bottom: 1px solid var(--line); }
620
+ h1 { font-size: 22px; margin: 0; }
621
+ h2 { font-size: 18px; margin: 0 0 12px; }
622
+ h3 { font-size: 15px; margin: 14px 0 8px; }
623
+ section {
624
+ border-bottom: 1px solid var(--line);
625
+ padding: 18px 0;
626
+ }
627
+ dl {
628
+ display: grid;
629
+ gap: 8px 16px;
630
+ grid-template-columns: minmax(150px, 240px) minmax(0, 1fr);
631
+ margin: 0;
632
+ }
633
+ dt { color: var(--muted); }
634
+ dd { margin: 0; overflow-wrap: anywhere; }
635
+ table {
636
+ border-collapse: collapse;
637
+ width: 100%;
638
+ }
639
+ th, td {
640
+ border-top: 1px solid var(--line);
641
+ padding: 8px;
642
+ text-align: left;
643
+ vertical-align: top;
644
+ }
645
+ th { color: var(--muted); font-weight: 600; }
646
+ ul { margin: 0; padding-left: 22px; }
647
+ .empty { color: var(--muted); margin: 0; }
648
+ .snapshot { color: var(--muted); font-size: 13px; overflow-wrap: anywhere; }
649
+ </style>
650
+ </head>
651
+ <body>
652
+ <header>
653
+ <h1>mustflow dashboard export</h1>
654
+ <p class="snapshot">${escapeHtml(snapshot.generated_at)}</p>
655
+ </header>
656
+ <main>
657
+ <section>
658
+ <h2>Dashboard status</h2>
659
+ <dl>${[
660
+ renderMetric('mustflow root', snapshot.mustflow_root),
661
+ renderMetric('Installed', status.installed),
662
+ renderMetric('Manifest lock', status.manifest_lock),
663
+ renderMetric('Template', text(asRecord(status.template).id) === 'none' ? 'none' : `${text(asRecord(status.template).id)} ${text(asRecord(status.template).version)}`),
664
+ renderMetric('Tracked files', status.tracked_files),
665
+ renderMetric('Changed files', asArray(status.changed_files).length),
666
+ renderMetric('Missing files', asArray(status.missing_files).length),
667
+ renderMetric('Runnable intents', asArray(status.runnable_intents).length),
668
+ renderMetric('Documents needing review', status.active_review_documents),
669
+ ].join('')}</dl>
670
+ </section>
671
+ <section>
672
+ <h2>Harness report</h2>
673
+ <dl>${[
674
+ renderMetric('Installed', harnessInstall.installed),
675
+ renderMetric('Manifest lock', harnessInstall.manifest_lock),
676
+ renderMetric('Tracked files', harnessInstall.tracked_files),
677
+ renderMetric('Changed files', harnessVerification.changed_file_count),
678
+ renderMetric('Changed surfaces', asArray(harnessVerification.changed_surfaces).join(', ') || 'none'),
679
+ renderMetric('Runnable verification intents', asArray(harnessVerification.runnable_intents).length),
680
+ renderMetric('Skipped verification intents', asArray(harnessVerification.skipped_intents).length),
681
+ renderMetric('Verification gaps', asArray(harnessVerification.gaps).length),
682
+ renderMetric('Decision graph nodes', graphSummary.node_count),
683
+ renderMetric('Decision graph edges', graphSummary.edge_count),
684
+ renderMetric('Latest run intent', harnessRunHistory.intent),
685
+ renderMetric('Latest run status', harnessRunHistory.status),
686
+ renderMetric('Docs review entries', harnessDocsReview.active_documents),
687
+ renderMetric('Remaining risks', asArray(harnessReport.remaining_risks).length),
688
+ ].join('')}</dl>
689
+ <h3>Runnable verification intents</h3>
690
+ ${renderList(asArray(harnessVerification.runnable_intents))}
691
+ <h3>Skipped verification intents</h3>
692
+ ${renderSkippedIntents(asArray(harnessVerification.skipped_intents))}
693
+ <h3>Verification gaps</h3>
694
+ ${renderVerificationGaps(asArray(harnessVerification.gaps))}
695
+ <h3>Remaining risks</h3>
696
+ ${renderRemainingRisks(asArray(harnessReport.remaining_risks))}
697
+ </section>
698
+ <section>
699
+ <h2>Release</h2>
700
+ <dl>${[
701
+ renderMetric('Package', release.package_name),
702
+ renderMetric('Version', release.package_version),
703
+ renderMetric('Template version', text(asRecord(status.template).version)),
704
+ renderMetric('Release-sensitive files', asArray(release.release_sensitive_changed_files).length),
705
+ ].join('')}</dl>
706
+ </section>
707
+ <section>
708
+ <h2>Verification</h2>
709
+ <dl>${[
710
+ renderMetric('Changed files', asArray(verification.changed_files).length),
711
+ renderMetric('Surfaces', asArray(verification.surfaces).join(', ') || 'none'),
712
+ ].join('')}</dl>
713
+ ${renderRecommendations(asArray(verification.recommendations))}
714
+ </section>
715
+ <section>
716
+ <h2>Commands</h2>
717
+ ${renderCommandIntents(asArray(commandContract.intents))}
718
+ </section>
719
+ <section>
720
+ <h2>Update plan</h2>
721
+ <dl>${[
722
+ renderMetric('Dry run ok', update.ok),
723
+ renderMetric('Apply ready', update.apply_ready),
724
+ renderMetric('Blockers', asArray(update.blockers).length),
725
+ renderMetric('Template changes', asArray(update.changes).length),
726
+ ].join('')}</dl>
727
+ </section>
728
+ <section>
729
+ <h2>Run history</h2>
730
+ ${renderRunHistory(asRecord(status.run_history))}
731
+ </section>
732
+ <section>
733
+ <h2>Skills</h2>
734
+ <dl>${[
735
+ renderMetric('Index path', text(asRecord(status.skills).index_path)),
736
+ renderMetric('Route count', text(asRecord(status.skills).count)),
737
+ ].join('')}</dl>
738
+ </section>
739
+ <section>
740
+ <h2>Documents</h2>
741
+ <dl>${[
742
+ renderMetric('Ledger path', docsReview.ledger_path),
743
+ renderMetric('Documents', docsReview.count),
744
+ ].join('')}</dl>
745
+ </section>
746
+ <section>
747
+ <h2>Preferences</h2>
748
+ <dl>${[
749
+ renderMetric('Path', preferences.preferencesPath),
750
+ renderMetric('Settings', asArray(preferences.settings).length),
751
+ ].join('')}</dl>
752
+ </section>
753
+ <section>
754
+ <h2>Export limits</h2>
755
+ ${renderTruncation(snapshot)}
756
+ </section>
757
+ </main>
758
+ <script id="dashboard-export-data" type="application/json">${embeddedJson}</script>
759
+ </body>
760
+ </html>
761
+ `;
762
+ }
763
+ export function writeDashboardExport(input) {
764
+ const absolutePath = resolveDashboardExportPath(input.projectRoot, input.outputPath);
765
+ const snapshot = createDashboardExportSnapshot(input);
766
+ const content = input.format === 'json' ? `${JSON.stringify(snapshot, null, 2)}\n` : renderDashboardExportHtml(snapshot);
767
+ writeUtf8FileInsideWithoutSymlinks(input.projectRoot, absolutePath, content);
768
+ return {
769
+ absolutePath,
770
+ relativePath: toPosixPath(path.relative(input.projectRoot, absolutePath)),
771
+ bytes: Buffer.byteLength(content, 'utf8'),
772
+ truncatedFields: snapshot.limits.truncated_fields,
773
+ omittedFields: snapshot.limits.omitted_fields,
774
+ };
775
+ }