mustflow 1.18.16 → 1.31.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 (314) hide show
  1. package/README.md +28 -8
  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 +302 -168
  10. package/dist/cli/commands/update.js +91 -61
  11. package/dist/cli/commands/upgrade.js +65 -0
  12. package/dist/cli/commands/verify.js +304 -139
  13. package/dist/cli/i18n/en.js +77 -4
  14. package/dist/cli/i18n/es.js +77 -4
  15. package/dist/cli/i18n/fr.js +77 -4
  16. package/dist/cli/i18n/hi.js +77 -4
  17. package/dist/cli/i18n/ko.js +77 -4
  18. package/dist/cli/i18n/zh.js +77 -4
  19. package/dist/cli/index.js +34 -42
  20. package/dist/cli/lib/command-registry.js +15 -0
  21. package/dist/cli/lib/dashboard-export.js +775 -0
  22. package/dist/cli/lib/dashboard-html.js +1 -1
  23. package/dist/cli/lib/local-index.js +33 -14
  24. package/dist/cli/lib/reporter.js +6 -0
  25. package/dist/cli/lib/run-plan.js +239 -0
  26. package/dist/cli/lib/templates.js +18 -3
  27. package/dist/cli/lib/update-diff-preview.js +163 -0
  28. package/dist/cli/lib/validation.js +132 -1
  29. package/dist/core/adapter-compatibility.js +235 -0
  30. package/dist/core/bounded-output.js +38 -0
  31. package/dist/core/change-classification.js +14 -1
  32. package/dist/core/change-verification.js +246 -5
  33. package/dist/core/check-issues.js +10 -0
  34. package/dist/core/command-contract-validation.js +34 -0
  35. package/dist/core/command-cwd.js +18 -6
  36. package/dist/core/command-effects.js +13 -0
  37. package/dist/core/command-env.js +91 -0
  38. package/dist/core/contract-lint.js +260 -4
  39. package/dist/core/contract-models.js +172 -0
  40. package/dist/core/dashboard-verification.js +10 -0
  41. package/dist/core/doc-review-triage.js +1 -0
  42. package/dist/core/handoff-record.js +376 -0
  43. package/dist/core/public-json-contracts.js +23 -0
  44. package/dist/core/run-performance-history.js +307 -0
  45. package/dist/core/run-profile.js +87 -0
  46. package/dist/core/run-receipt.js +217 -11
  47. package/dist/core/run-write-drift.js +196 -0
  48. package/dist/core/secret-redaction.js +39 -0
  49. package/dist/core/skill-route-alignment.js +90 -0
  50. package/dist/core/source-anchors.js +3 -5
  51. package/dist/core/test-selection.js +224 -0
  52. package/dist/core/verification-decision-graph.js +290 -0
  53. package/dist/core/verification-scheduler.js +96 -2
  54. package/package.json +3 -1
  55. package/schemas/README.md +15 -4
  56. package/schemas/adapter-compatibility-report.schema.json +184 -0
  57. package/schemas/change-verification-report.schema.json +286 -4
  58. package/schemas/commands.schema.json +55 -2
  59. package/schemas/contract-lint-report.schema.json +99 -0
  60. package/schemas/dashboard-export.schema.json +273 -0
  61. package/schemas/explain-report.schema.json +267 -2
  62. package/schemas/handoff-validation-report.schema.json +68 -0
  63. package/schemas/run-receipt.schema.json +183 -1
  64. package/templates/default/common/.mustflow/config/commands.toml +3 -1
  65. package/templates/default/i18n.toml +78 -234
  66. package/templates/default/locales/en/.mustflow/skills/INDEX.md +7 -3
  67. package/templates/default/locales/en/.mustflow/skills/architecture-deepening-review/SKILL.md +154 -0
  68. package/templates/default/locales/en/.mustflow/skills/behavior-preserving-refactor/SKILL.md +8 -3
  69. package/templates/default/locales/en/.mustflow/skills/code-review/SKILL.md +9 -4
  70. package/templates/default/locales/en/.mustflow/skills/date-number-audit/SKILL.md +19 -4
  71. package/templates/default/locales/en/.mustflow/skills/diff-risk-review/SKILL.md +4 -2
  72. package/templates/default/locales/en/.mustflow/skills/external-skill-intake/SKILL.md +141 -0
  73. package/templates/default/locales/en/.mustflow/skills/release-notes-authoring/SKILL.md +143 -0
  74. package/templates/default/locales/en/.mustflow/skills/repro-first-debug/SKILL.md +22 -8
  75. package/templates/default/locales/en/.mustflow/skills/skill-authoring/SKILL.md +3 -3
  76. package/templates/default/locales/en/.mustflow/skills/source-freshness-check/SKILL.md +22 -9
  77. package/templates/default/locales/en/.mustflow/skills/ui-quality-gate/SKILL.md +21 -13
  78. package/templates/default/locales/en/.mustflow/skills/vertical-slice-tdd/SKILL.md +167 -0
  79. package/templates/default/manifest.toml +16 -1
  80. package/templates/default/locales/es/.mustflow/skills/INDEX.md +0 -75
  81. package/templates/default/locales/es/.mustflow/skills/adapter-boundary/SKILL.md +0 -193
  82. package/templates/default/locales/es/.mustflow/skills/artifact-integrity-check/SKILL.md +0 -114
  83. package/templates/default/locales/es/.mustflow/skills/behavior-preserving-refactor/SKILL.md +0 -182
  84. package/templates/default/locales/es/.mustflow/skills/code-review/SKILL.md +0 -115
  85. package/templates/default/locales/es/.mustflow/skills/codebase-orientation/SKILL.md +0 -115
  86. package/templates/default/locales/es/.mustflow/skills/command-pattern/SKILL.md +0 -247
  87. package/templates/default/locales/es/.mustflow/skills/composition-over-inheritance/SKILL.md +0 -176
  88. package/templates/default/locales/es/.mustflow/skills/contract-sync-check/SKILL.md +0 -116
  89. package/templates/default/locales/es/.mustflow/skills/database-change-safety/SKILL.md +0 -155
  90. package/templates/default/locales/es/.mustflow/skills/date-number-audit/SKILL.md +0 -116
  91. package/templates/default/locales/es/.mustflow/skills/dependency-injection/SKILL.md +0 -161
  92. package/templates/default/locales/es/.mustflow/skills/dependency-reality-check/SKILL.md +0 -115
  93. package/templates/default/locales/es/.mustflow/skills/diff-risk-review/SKILL.md +0 -136
  94. package/templates/default/locales/es/.mustflow/skills/docs-prose-review/SKILL.md +0 -119
  95. package/templates/default/locales/es/.mustflow/skills/docs-update/SKILL.md +0 -97
  96. package/templates/default/locales/es/.mustflow/skills/external-prompt-injection-defense/SKILL.md +0 -116
  97. package/templates/default/locales/es/.mustflow/skills/facade-pattern/SKILL.md +0 -210
  98. package/templates/default/locales/es/.mustflow/skills/failure-triage/SKILL.md +0 -97
  99. package/templates/default/locales/es/.mustflow/skills/instruction-conflict-scope-check/SKILL.md +0 -118
  100. package/templates/default/locales/es/.mustflow/skills/line-ending-hygiene/SKILL.md +0 -111
  101. package/templates/default/locales/es/.mustflow/skills/migration-safety-check/SKILL.md +0 -117
  102. package/templates/default/locales/es/.mustflow/skills/multi-agent-work-coordination/SKILL.md +0 -260
  103. package/templates/default/locales/es/.mustflow/skills/null-object-pattern/SKILL.md +0 -196
  104. package/templates/default/locales/es/.mustflow/skills/pattern-scout/SKILL.md +0 -110
  105. package/templates/default/locales/es/.mustflow/skills/performance-budget-check/SKILL.md +0 -121
  106. package/templates/default/locales/es/.mustflow/skills/project-context-authoring/SKILL.md +0 -107
  107. package/templates/default/locales/es/.mustflow/skills/pure-core-imperative-shell/SKILL.md +0 -212
  108. package/templates/default/locales/es/.mustflow/skills/readme-authoring/SKILL.md +0 -115
  109. package/templates/default/locales/es/.mustflow/skills/repo-improvement-loop/SKILL.md +0 -150
  110. package/templates/default/locales/es/.mustflow/skills/repro-first-debug/SKILL.md +0 -112
  111. package/templates/default/locales/es/.mustflow/skills/requirement-regression-guard/SKILL.md +0 -152
  112. package/templates/default/locales/es/.mustflow/skills/result-option/SKILL.md +0 -186
  113. package/templates/default/locales/es/.mustflow/skills/security-privacy-review/SKILL.md +0 -116
  114. package/templates/default/locales/es/.mustflow/skills/security-regression-tests/SKILL.md +0 -131
  115. package/templates/default/locales/es/.mustflow/skills/skill-authoring/SKILL.md +0 -110
  116. package/templates/default/locales/es/.mustflow/skills/source-freshness-check/SKILL.md +0 -111
  117. package/templates/default/locales/es/.mustflow/skills/state-machine-pattern/SKILL.md +0 -214
  118. package/templates/default/locales/es/.mustflow/skills/strategy-pattern/SKILL.md +0 -215
  119. package/templates/default/locales/es/.mustflow/skills/structure-discovery-gate/SKILL.md +0 -159
  120. package/templates/default/locales/es/.mustflow/skills/test-design-guard/SKILL.md +0 -162
  121. package/templates/default/locales/es/.mustflow/skills/test-maintenance/SKILL.md +0 -122
  122. package/templates/default/locales/es/.mustflow/skills/ui-quality-gate/SKILL.md +0 -117
  123. package/templates/default/locales/es/.mustflow/skills/visual-review-artifact/SKILL.md +0 -127
  124. package/templates/default/locales/es/.mustflow/skills/visual-review-artifact/assets/review-template.html +0 -286
  125. package/templates/default/locales/es/.mustflow/skills/visual-review-artifact/resources.toml +0 -7
  126. package/templates/default/locales/es/.mustflow/skills/web-asset-optimization/SKILL.md +0 -108
  127. package/templates/default/locales/fr/.mustflow/skills/INDEX.md +0 -75
  128. package/templates/default/locales/fr/.mustflow/skills/adapter-boundary/SKILL.md +0 -193
  129. package/templates/default/locales/fr/.mustflow/skills/artifact-integrity-check/SKILL.md +0 -114
  130. package/templates/default/locales/fr/.mustflow/skills/behavior-preserving-refactor/SKILL.md +0 -182
  131. package/templates/default/locales/fr/.mustflow/skills/code-review/SKILL.md +0 -115
  132. package/templates/default/locales/fr/.mustflow/skills/codebase-orientation/SKILL.md +0 -115
  133. package/templates/default/locales/fr/.mustflow/skills/command-pattern/SKILL.md +0 -247
  134. package/templates/default/locales/fr/.mustflow/skills/composition-over-inheritance/SKILL.md +0 -176
  135. package/templates/default/locales/fr/.mustflow/skills/contract-sync-check/SKILL.md +0 -116
  136. package/templates/default/locales/fr/.mustflow/skills/database-change-safety/SKILL.md +0 -155
  137. package/templates/default/locales/fr/.mustflow/skills/date-number-audit/SKILL.md +0 -116
  138. package/templates/default/locales/fr/.mustflow/skills/dependency-injection/SKILL.md +0 -161
  139. package/templates/default/locales/fr/.mustflow/skills/dependency-reality-check/SKILL.md +0 -115
  140. package/templates/default/locales/fr/.mustflow/skills/diff-risk-review/SKILL.md +0 -136
  141. package/templates/default/locales/fr/.mustflow/skills/docs-prose-review/SKILL.md +0 -119
  142. package/templates/default/locales/fr/.mustflow/skills/docs-update/SKILL.md +0 -97
  143. package/templates/default/locales/fr/.mustflow/skills/external-prompt-injection-defense/SKILL.md +0 -116
  144. package/templates/default/locales/fr/.mustflow/skills/facade-pattern/SKILL.md +0 -210
  145. package/templates/default/locales/fr/.mustflow/skills/failure-triage/SKILL.md +0 -97
  146. package/templates/default/locales/fr/.mustflow/skills/instruction-conflict-scope-check/SKILL.md +0 -118
  147. package/templates/default/locales/fr/.mustflow/skills/line-ending-hygiene/SKILL.md +0 -111
  148. package/templates/default/locales/fr/.mustflow/skills/migration-safety-check/SKILL.md +0 -117
  149. package/templates/default/locales/fr/.mustflow/skills/multi-agent-work-coordination/SKILL.md +0 -260
  150. package/templates/default/locales/fr/.mustflow/skills/null-object-pattern/SKILL.md +0 -196
  151. package/templates/default/locales/fr/.mustflow/skills/pattern-scout/SKILL.md +0 -110
  152. package/templates/default/locales/fr/.mustflow/skills/performance-budget-check/SKILL.md +0 -121
  153. package/templates/default/locales/fr/.mustflow/skills/project-context-authoring/SKILL.md +0 -107
  154. package/templates/default/locales/fr/.mustflow/skills/pure-core-imperative-shell/SKILL.md +0 -212
  155. package/templates/default/locales/fr/.mustflow/skills/readme-authoring/SKILL.md +0 -115
  156. package/templates/default/locales/fr/.mustflow/skills/repo-improvement-loop/SKILL.md +0 -150
  157. package/templates/default/locales/fr/.mustflow/skills/repro-first-debug/SKILL.md +0 -112
  158. package/templates/default/locales/fr/.mustflow/skills/requirement-regression-guard/SKILL.md +0 -152
  159. package/templates/default/locales/fr/.mustflow/skills/result-option/SKILL.md +0 -186
  160. package/templates/default/locales/fr/.mustflow/skills/security-privacy-review/SKILL.md +0 -116
  161. package/templates/default/locales/fr/.mustflow/skills/security-regression-tests/SKILL.md +0 -131
  162. package/templates/default/locales/fr/.mustflow/skills/skill-authoring/SKILL.md +0 -110
  163. package/templates/default/locales/fr/.mustflow/skills/source-freshness-check/SKILL.md +0 -111
  164. package/templates/default/locales/fr/.mustflow/skills/state-machine-pattern/SKILL.md +0 -214
  165. package/templates/default/locales/fr/.mustflow/skills/strategy-pattern/SKILL.md +0 -215
  166. package/templates/default/locales/fr/.mustflow/skills/structure-discovery-gate/SKILL.md +0 -159
  167. package/templates/default/locales/fr/.mustflow/skills/test-design-guard/SKILL.md +0 -162
  168. package/templates/default/locales/fr/.mustflow/skills/test-maintenance/SKILL.md +0 -122
  169. package/templates/default/locales/fr/.mustflow/skills/ui-quality-gate/SKILL.md +0 -117
  170. package/templates/default/locales/fr/.mustflow/skills/visual-review-artifact/SKILL.md +0 -127
  171. package/templates/default/locales/fr/.mustflow/skills/visual-review-artifact/assets/review-template.html +0 -286
  172. package/templates/default/locales/fr/.mustflow/skills/visual-review-artifact/resources.toml +0 -7
  173. package/templates/default/locales/fr/.mustflow/skills/web-asset-optimization/SKILL.md +0 -108
  174. package/templates/default/locales/hi/.mustflow/skills/INDEX.md +0 -75
  175. package/templates/default/locales/hi/.mustflow/skills/adapter-boundary/SKILL.md +0 -193
  176. package/templates/default/locales/hi/.mustflow/skills/artifact-integrity-check/SKILL.md +0 -114
  177. package/templates/default/locales/hi/.mustflow/skills/behavior-preserving-refactor/SKILL.md +0 -182
  178. package/templates/default/locales/hi/.mustflow/skills/code-review/SKILL.md +0 -115
  179. package/templates/default/locales/hi/.mustflow/skills/codebase-orientation/SKILL.md +0 -115
  180. package/templates/default/locales/hi/.mustflow/skills/command-pattern/SKILL.md +0 -247
  181. package/templates/default/locales/hi/.mustflow/skills/composition-over-inheritance/SKILL.md +0 -176
  182. package/templates/default/locales/hi/.mustflow/skills/contract-sync-check/SKILL.md +0 -116
  183. package/templates/default/locales/hi/.mustflow/skills/database-change-safety/SKILL.md +0 -155
  184. package/templates/default/locales/hi/.mustflow/skills/date-number-audit/SKILL.md +0 -116
  185. package/templates/default/locales/hi/.mustflow/skills/dependency-injection/SKILL.md +0 -161
  186. package/templates/default/locales/hi/.mustflow/skills/dependency-reality-check/SKILL.md +0 -115
  187. package/templates/default/locales/hi/.mustflow/skills/diff-risk-review/SKILL.md +0 -136
  188. package/templates/default/locales/hi/.mustflow/skills/docs-prose-review/SKILL.md +0 -119
  189. package/templates/default/locales/hi/.mustflow/skills/docs-update/SKILL.md +0 -97
  190. package/templates/default/locales/hi/.mustflow/skills/external-prompt-injection-defense/SKILL.md +0 -116
  191. package/templates/default/locales/hi/.mustflow/skills/facade-pattern/SKILL.md +0 -210
  192. package/templates/default/locales/hi/.mustflow/skills/failure-triage/SKILL.md +0 -97
  193. package/templates/default/locales/hi/.mustflow/skills/instruction-conflict-scope-check/SKILL.md +0 -118
  194. package/templates/default/locales/hi/.mustflow/skills/line-ending-hygiene/SKILL.md +0 -111
  195. package/templates/default/locales/hi/.mustflow/skills/migration-safety-check/SKILL.md +0 -117
  196. package/templates/default/locales/hi/.mustflow/skills/multi-agent-work-coordination/SKILL.md +0 -260
  197. package/templates/default/locales/hi/.mustflow/skills/null-object-pattern/SKILL.md +0 -196
  198. package/templates/default/locales/hi/.mustflow/skills/pattern-scout/SKILL.md +0 -110
  199. package/templates/default/locales/hi/.mustflow/skills/performance-budget-check/SKILL.md +0 -121
  200. package/templates/default/locales/hi/.mustflow/skills/project-context-authoring/SKILL.md +0 -107
  201. package/templates/default/locales/hi/.mustflow/skills/pure-core-imperative-shell/SKILL.md +0 -212
  202. package/templates/default/locales/hi/.mustflow/skills/readme-authoring/SKILL.md +0 -115
  203. package/templates/default/locales/hi/.mustflow/skills/repo-improvement-loop/SKILL.md +0 -150
  204. package/templates/default/locales/hi/.mustflow/skills/repro-first-debug/SKILL.md +0 -112
  205. package/templates/default/locales/hi/.mustflow/skills/requirement-regression-guard/SKILL.md +0 -152
  206. package/templates/default/locales/hi/.mustflow/skills/result-option/SKILL.md +0 -186
  207. package/templates/default/locales/hi/.mustflow/skills/security-privacy-review/SKILL.md +0 -116
  208. package/templates/default/locales/hi/.mustflow/skills/security-regression-tests/SKILL.md +0 -131
  209. package/templates/default/locales/hi/.mustflow/skills/skill-authoring/SKILL.md +0 -110
  210. package/templates/default/locales/hi/.mustflow/skills/source-freshness-check/SKILL.md +0 -111
  211. package/templates/default/locales/hi/.mustflow/skills/state-machine-pattern/SKILL.md +0 -214
  212. package/templates/default/locales/hi/.mustflow/skills/strategy-pattern/SKILL.md +0 -215
  213. package/templates/default/locales/hi/.mustflow/skills/structure-discovery-gate/SKILL.md +0 -159
  214. package/templates/default/locales/hi/.mustflow/skills/test-design-guard/SKILL.md +0 -162
  215. package/templates/default/locales/hi/.mustflow/skills/test-maintenance/SKILL.md +0 -122
  216. package/templates/default/locales/hi/.mustflow/skills/ui-quality-gate/SKILL.md +0 -117
  217. package/templates/default/locales/hi/.mustflow/skills/visual-review-artifact/SKILL.md +0 -127
  218. package/templates/default/locales/hi/.mustflow/skills/visual-review-artifact/assets/review-template.html +0 -286
  219. package/templates/default/locales/hi/.mustflow/skills/visual-review-artifact/resources.toml +0 -7
  220. package/templates/default/locales/hi/.mustflow/skills/web-asset-optimization/SKILL.md +0 -108
  221. package/templates/default/locales/ko/.mustflow/skills/INDEX.md +0 -80
  222. package/templates/default/locales/ko/.mustflow/skills/adapter-boundary/SKILL.md +0 -193
  223. package/templates/default/locales/ko/.mustflow/skills/artifact-integrity-check/SKILL.md +0 -114
  224. package/templates/default/locales/ko/.mustflow/skills/behavior-preserving-refactor/SKILL.md +0 -182
  225. package/templates/default/locales/ko/.mustflow/skills/code-review/SKILL.md +0 -118
  226. package/templates/default/locales/ko/.mustflow/skills/codebase-orientation/SKILL.md +0 -115
  227. package/templates/default/locales/ko/.mustflow/skills/command-pattern/SKILL.md +0 -247
  228. package/templates/default/locales/ko/.mustflow/skills/composition-over-inheritance/SKILL.md +0 -176
  229. package/templates/default/locales/ko/.mustflow/skills/contract-sync-check/SKILL.md +0 -116
  230. package/templates/default/locales/ko/.mustflow/skills/database-change-safety/SKILL.md +0 -155
  231. package/templates/default/locales/ko/.mustflow/skills/date-number-audit/SKILL.md +0 -116
  232. package/templates/default/locales/ko/.mustflow/skills/dependency-injection/SKILL.md +0 -161
  233. package/templates/default/locales/ko/.mustflow/skills/dependency-reality-check/SKILL.md +0 -115
  234. package/templates/default/locales/ko/.mustflow/skills/diff-risk-review/SKILL.md +0 -136
  235. package/templates/default/locales/ko/.mustflow/skills/docs-prose-review/SKILL.md +0 -119
  236. package/templates/default/locales/ko/.mustflow/skills/docs-update/SKILL.md +0 -107
  237. package/templates/default/locales/ko/.mustflow/skills/external-prompt-injection-defense/SKILL.md +0 -116
  238. package/templates/default/locales/ko/.mustflow/skills/facade-pattern/SKILL.md +0 -210
  239. package/templates/default/locales/ko/.mustflow/skills/failure-triage/SKILL.md +0 -119
  240. package/templates/default/locales/ko/.mustflow/skills/instruction-conflict-scope-check/SKILL.md +0 -118
  241. package/templates/default/locales/ko/.mustflow/skills/line-ending-hygiene/SKILL.md +0 -111
  242. package/templates/default/locales/ko/.mustflow/skills/migration-safety-check/SKILL.md +0 -117
  243. package/templates/default/locales/ko/.mustflow/skills/multi-agent-work-coordination/SKILL.md +0 -259
  244. package/templates/default/locales/ko/.mustflow/skills/null-object-pattern/SKILL.md +0 -196
  245. package/templates/default/locales/ko/.mustflow/skills/pattern-scout/SKILL.md +0 -110
  246. package/templates/default/locales/ko/.mustflow/skills/performance-budget-check/SKILL.md +0 -121
  247. package/templates/default/locales/ko/.mustflow/skills/project-context-authoring/SKILL.md +0 -107
  248. package/templates/default/locales/ko/.mustflow/skills/pure-core-imperative-shell/SKILL.md +0 -212
  249. package/templates/default/locales/ko/.mustflow/skills/readme-authoring/SKILL.md +0 -115
  250. package/templates/default/locales/ko/.mustflow/skills/repo-improvement-loop/SKILL.md +0 -150
  251. package/templates/default/locales/ko/.mustflow/skills/repro-first-debug/SKILL.md +0 -112
  252. package/templates/default/locales/ko/.mustflow/skills/requirement-regression-guard/SKILL.md +0 -152
  253. package/templates/default/locales/ko/.mustflow/skills/result-option/SKILL.md +0 -186
  254. package/templates/default/locales/ko/.mustflow/skills/security-privacy-review/SKILL.md +0 -116
  255. package/templates/default/locales/ko/.mustflow/skills/security-regression-tests/SKILL.md +0 -131
  256. package/templates/default/locales/ko/.mustflow/skills/skill-authoring/SKILL.md +0 -110
  257. package/templates/default/locales/ko/.mustflow/skills/source-freshness-check/SKILL.md +0 -111
  258. package/templates/default/locales/ko/.mustflow/skills/state-machine-pattern/SKILL.md +0 -214
  259. package/templates/default/locales/ko/.mustflow/skills/strategy-pattern/SKILL.md +0 -215
  260. package/templates/default/locales/ko/.mustflow/skills/structure-discovery-gate/SKILL.md +0 -159
  261. package/templates/default/locales/ko/.mustflow/skills/test-design-guard/SKILL.md +0 -162
  262. package/templates/default/locales/ko/.mustflow/skills/test-maintenance/SKILL.md +0 -130
  263. package/templates/default/locales/ko/.mustflow/skills/ui-quality-gate/SKILL.md +0 -117
  264. package/templates/default/locales/ko/.mustflow/skills/visual-review-artifact/SKILL.md +0 -127
  265. package/templates/default/locales/ko/.mustflow/skills/visual-review-artifact/assets/review-template.html +0 -286
  266. package/templates/default/locales/ko/.mustflow/skills/visual-review-artifact/resources.toml +0 -7
  267. package/templates/default/locales/ko/.mustflow/skills/web-asset-optimization/SKILL.md +0 -108
  268. package/templates/default/locales/zh/.mustflow/skills/INDEX.md +0 -74
  269. package/templates/default/locales/zh/.mustflow/skills/adapter-boundary/SKILL.md +0 -193
  270. package/templates/default/locales/zh/.mustflow/skills/artifact-integrity-check/SKILL.md +0 -114
  271. package/templates/default/locales/zh/.mustflow/skills/behavior-preserving-refactor/SKILL.md +0 -182
  272. package/templates/default/locales/zh/.mustflow/skills/code-review/SKILL.md +0 -115
  273. package/templates/default/locales/zh/.mustflow/skills/codebase-orientation/SKILL.md +0 -115
  274. package/templates/default/locales/zh/.mustflow/skills/command-pattern/SKILL.md +0 -247
  275. package/templates/default/locales/zh/.mustflow/skills/composition-over-inheritance/SKILL.md +0 -176
  276. package/templates/default/locales/zh/.mustflow/skills/contract-sync-check/SKILL.md +0 -116
  277. package/templates/default/locales/zh/.mustflow/skills/database-change-safety/SKILL.md +0 -155
  278. package/templates/default/locales/zh/.mustflow/skills/date-number-audit/SKILL.md +0 -116
  279. package/templates/default/locales/zh/.mustflow/skills/dependency-injection/SKILL.md +0 -161
  280. package/templates/default/locales/zh/.mustflow/skills/dependency-reality-check/SKILL.md +0 -115
  281. package/templates/default/locales/zh/.mustflow/skills/diff-risk-review/SKILL.md +0 -136
  282. package/templates/default/locales/zh/.mustflow/skills/docs-prose-review/SKILL.md +0 -119
  283. package/templates/default/locales/zh/.mustflow/skills/docs-update/SKILL.md +0 -97
  284. package/templates/default/locales/zh/.mustflow/skills/external-prompt-injection-defense/SKILL.md +0 -116
  285. package/templates/default/locales/zh/.mustflow/skills/facade-pattern/SKILL.md +0 -210
  286. package/templates/default/locales/zh/.mustflow/skills/failure-triage/SKILL.md +0 -96
  287. package/templates/default/locales/zh/.mustflow/skills/instruction-conflict-scope-check/SKILL.md +0 -118
  288. package/templates/default/locales/zh/.mustflow/skills/line-ending-hygiene/SKILL.md +0 -111
  289. package/templates/default/locales/zh/.mustflow/skills/migration-safety-check/SKILL.md +0 -117
  290. package/templates/default/locales/zh/.mustflow/skills/multi-agent-work-coordination/SKILL.md +0 -260
  291. package/templates/default/locales/zh/.mustflow/skills/null-object-pattern/SKILL.md +0 -196
  292. package/templates/default/locales/zh/.mustflow/skills/pattern-scout/SKILL.md +0 -110
  293. package/templates/default/locales/zh/.mustflow/skills/performance-budget-check/SKILL.md +0 -121
  294. package/templates/default/locales/zh/.mustflow/skills/project-context-authoring/SKILL.md +0 -107
  295. package/templates/default/locales/zh/.mustflow/skills/pure-core-imperative-shell/SKILL.md +0 -212
  296. package/templates/default/locales/zh/.mustflow/skills/readme-authoring/SKILL.md +0 -115
  297. package/templates/default/locales/zh/.mustflow/skills/repo-improvement-loop/SKILL.md +0 -150
  298. package/templates/default/locales/zh/.mustflow/skills/repro-first-debug/SKILL.md +0 -112
  299. package/templates/default/locales/zh/.mustflow/skills/requirement-regression-guard/SKILL.md +0 -152
  300. package/templates/default/locales/zh/.mustflow/skills/result-option/SKILL.md +0 -186
  301. package/templates/default/locales/zh/.mustflow/skills/security-privacy-review/SKILL.md +0 -116
  302. package/templates/default/locales/zh/.mustflow/skills/security-regression-tests/SKILL.md +0 -131
  303. package/templates/default/locales/zh/.mustflow/skills/skill-authoring/SKILL.md +0 -110
  304. package/templates/default/locales/zh/.mustflow/skills/source-freshness-check/SKILL.md +0 -111
  305. package/templates/default/locales/zh/.mustflow/skills/state-machine-pattern/SKILL.md +0 -214
  306. package/templates/default/locales/zh/.mustflow/skills/strategy-pattern/SKILL.md +0 -215
  307. package/templates/default/locales/zh/.mustflow/skills/structure-discovery-gate/SKILL.md +0 -159
  308. package/templates/default/locales/zh/.mustflow/skills/test-design-guard/SKILL.md +0 -162
  309. package/templates/default/locales/zh/.mustflow/skills/test-maintenance/SKILL.md +0 -122
  310. package/templates/default/locales/zh/.mustflow/skills/ui-quality-gate/SKILL.md +0 -117
  311. package/templates/default/locales/zh/.mustflow/skills/visual-review-artifact/SKILL.md +0 -127
  312. package/templates/default/locales/zh/.mustflow/skills/visual-review-artifact/assets/review-template.html +0 -286
  313. package/templates/default/locales/zh/.mustflow/skills/visual-review-artifact/resources.toml +0 -7
  314. 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
+ }