ai-delivery-workflow 0.2.2 → 0.4.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 (361) hide show
  1. package/README.md +45 -14
  2. package/bin/ai-delivery.mjs +181 -6
  3. package/bin/benchmark-autonomy.mjs +217 -0
  4. package/bin/release-check.mjs +382 -0
  5. package/docs/CLI-PARAMETER-REFERENCE.zh-CN.md +346 -0
  6. package/docs/CODEGRAPH-INTEGRATION.zh-CN.md +89 -0
  7. package/docs/DUAL-REPOSITORY-WORKSPACE.zh-CN.md +2 -2
  8. package/docs/EVOLUTION-MAINTENANCE.zh-CN.md +7 -7
  9. package/docs/EVOLUTION-USER-GUIDE.zh-CN.md +2 -2
  10. package/docs/FILE-REFERENCE.zh-CN.md +120 -39
  11. package/docs/MAINTENANCE-VERIFICATION.zh-CN.md +51 -0
  12. package/docs/MOCK-SYSTEM.zh-CN.md +141 -0
  13. package/docs/NPM-RELEASE-MANAGEMENT.zh-CN.md +106 -0
  14. package/docs/PROJECT-MANUAL.zh-CN.md +154 -95
  15. package/docs/PROTOTYPE-MIGRATION.zh-CN.md +164 -0
  16. package/docs/STATE-CLI-MAINTENANCE.zh-CN.md +35 -17
  17. package/docs/STATE-CLI-USER-GUIDE.zh-CN.md +115 -39
  18. package/docs/VIEWER-MAINTENANCE.zh-CN.md +101 -324
  19. package/docs/VIEWER-USER-GUIDE.zh-CN.md +68 -190
  20. package/docs/adr/0001-prototype-first-ui-governance.md +3 -0
  21. package/docs/adr/0002-microcks-as-default-mock-system.md +3 -0
  22. package/docs/adr/0003-workflow-manager-governed-control-surface.md +46 -0
  23. package/docs/adr/0004-operational-carbon-visual-standard.md +9 -0
  24. package/docs/adr/0005-prototype-management-as-routed-pages.md +7 -0
  25. package/docs/agents/domain.md +12 -0
  26. package/docs/agents/issue-tracker.md +27 -0
  27. package/docs/agents/triage-labels.md +11 -0
  28. package/docs/agents/workflow-manager-acceptance-matrix.md +93 -0
  29. package/docs/agents/workflow-manager-agent-interface.md +145 -0
  30. package/docs/agents/workflow-manager-current-state.md +205 -0
  31. package/lib/artifact-files.mjs +47 -0
  32. package/lib/codegraph.mjs +405 -0
  33. package/lib/delivery-state.mjs +3079 -198
  34. package/lib/frontend-guard.mjs +288 -0
  35. package/lib/fs-utils.mjs +53 -0
  36. package/lib/history-anchor.mjs +98 -0
  37. package/lib/mock-scenario-pack.mjs +687 -0
  38. package/lib/mock-system.mjs +897 -0
  39. package/lib/npm-package-result.mjs +11 -0
  40. package/lib/png-evidence.mjs +149 -0
  41. package/lib/project-bootstrap.mjs +96 -55
  42. package/lib/project-installer.mjs +1484 -164
  43. package/lib/project-migration.mjs +1193 -0
  44. package/lib/prototype-migration.mjs +713 -0
  45. package/lib/prototype-page-review.mjs +384 -0
  46. package/lib/prototype-review-target.mjs +334 -0
  47. package/lib/prototype-revision.mjs +812 -0
  48. package/lib/stable-value.mjs +15 -0
  49. package/lib/toml-hooks.mjs +69 -0
  50. package/lib/ui-acceptance.mjs +565 -0
  51. package/lib/visual-standard.mjs +232 -0
  52. package/lib/workflow-manager-contracts.mjs +367 -0
  53. package/lib/workflow-manager-facts.mjs +778 -0
  54. package/lib/workflow-manager-governance.mjs +514 -0
  55. package/lib/workflow-manager-mock.mjs +183 -0
  56. package/lib/workflow-manager-prototypes.mjs +1847 -0
  57. package/lib/workflow-manager-public/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  58. package/lib/workflow-manager-public/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  59. package/lib/workflow-manager-public/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  60. package/lib/workflow-manager-public/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  61. package/lib/workflow-manager-public/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  62. package/lib/workflow-manager-public/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  63. package/lib/workflow-manager-public/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  64. package/lib/workflow-manager-public/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  65. package/lib/workflow-manager-public/assets/index-Chlg6r8f.css +1 -0
  66. package/lib/workflow-manager-public/assets/index-E-hGB5ZD.js +13 -0
  67. package/lib/workflow-manager-public/fonts/OFL-1.1.txt +90 -0
  68. package/lib/workflow-manager-public/index.html +14 -0
  69. package/lib/workflow-manager-systems.mjs +519 -0
  70. package/lib/workflow-manager-transaction.mjs +397 -0
  71. package/lib/workflow-manager.mjs +745 -0
  72. package/package.json +8 -2
  73. package/skills/ai-delivery-assemble-release/agents/openai.yaml +3 -3
  74. package/skills/ai-delivery-assemble-release/assets/release-material-index.csv +1 -1
  75. package/skills/ai-delivery-assemble-release/assets/version-inclusion.csv +1 -1
  76. package/skills/ai-delivery-bootstrap/SKILL.md +4 -4
  77. package/skills/ai-delivery-bootstrap/agents/openai.yaml +3 -3
  78. package/skills/ai-delivery-bootstrap/references/bootstrap-contract.md +4 -2
  79. package/skills/ai-delivery-checkpoint-task/SKILL.md +17 -3
  80. package/skills/ai-delivery-checkpoint-task/agents/openai.yaml +3 -3
  81. package/skills/ai-delivery-checkpoint-task/assets/runtime-template/task.json +7 -1
  82. package/skills/ai-delivery-checkpoint-task/references/checkpoint-contract.md +22 -8
  83. package/skills/ai-delivery-checkpoint-task/scripts/hook-event.mjs +91 -0
  84. package/skills/ai-delivery-checkpoint-task/scripts/task-state.mjs +1086 -51
  85. package/skills/ai-delivery-close-version/SKILL.md +9 -8
  86. package/skills/ai-delivery-close-version/agents/openai.yaml +3 -3
  87. package/skills/ai-delivery-close-version/assets/version-lineage.yaml +1 -1
  88. package/skills/ai-delivery-close-version/references/version-closeout-contract.md +2 -2
  89. package/skills/ai-delivery-define-product/SKILL.md +8 -4
  90. package/skills/ai-delivery-define-product/agents/openai.yaml +4 -4
  91. package/skills/ai-delivery-define-product/references/product-contract.md +2 -2
  92. package/skills/ai-delivery-deploy-production/agents/openai.yaml +3 -3
  93. package/skills/ai-delivery-design-architecture/SKILL.md +9 -5
  94. package/skills/ai-delivery-design-architecture/assets/architecture-template/prototype-architecture-validation.yaml +16 -16
  95. package/skills/ai-delivery-design-architecture/references/architecture-contract.md +1 -1
  96. package/skills/ai-delivery-design-experience/SKILL.md +36 -30
  97. package/skills/ai-delivery-design-experience/agents/openai.yaml +4 -4
  98. package/skills/ai-delivery-design-experience/assets/experience-template/LEGACY-COMPATIBILITY.md +16 -0
  99. package/skills/ai-delivery-design-experience/assets/experience-template/design-reference-selection.yaml +32 -0
  100. package/skills/ai-delivery-design-experience/assets/experience-template/experience-baseline.yaml +2 -2
  101. package/skills/ai-delivery-design-experience/assets/experience-template/formal-ui-confirmation.yaml +16 -3
  102. package/skills/ai-delivery-design-experience/assets/experience-template/frontend-change-scope.yaml +30 -0
  103. package/skills/ai-delivery-design-experience/assets/experience-template/interaction-contract.csv +1 -1
  104. package/skills/ai-delivery-design-experience/assets/experience-template/mock-admin-export.yaml +8 -0
  105. package/skills/ai-delivery-design-experience/assets/experience-template/mock-scenario-mappings.csv +1 -0
  106. package/skills/ai-delivery-design-experience/assets/experience-template/mock-scenario-pack-request.yaml +24 -0
  107. package/skills/ai-delivery-design-experience/assets/experience-template/product-prototype-reconciliation.yaml +2 -1
  108. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-adjustment-log.csv +1 -1
  109. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-component-bindings.csv +1 -0
  110. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-component-candidates.csv +1 -0
  111. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-components.csv +1 -0
  112. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-confirmation.yaml +18 -18
  113. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-data-contracts.csv +1 -0
  114. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-impact-assessment.yaml +5 -5
  115. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-implementation-bindings.csv +1 -0
  116. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-manifest.yaml +2 -0
  117. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-pages.csv +1 -0
  118. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-product-coverage.csv +1 -1
  119. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-review-comments.csv +1 -1
  120. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-review-decision.yaml +13 -12
  121. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-review-scenes.csv +1 -0
  122. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-review-sessions.csv +1 -1
  123. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-review-unit-pages.csv +1 -0
  124. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-review-units.csv +1 -0
  125. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-revision.yaml +88 -0
  126. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-routes.csv +1 -0
  127. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-set.yaml +2 -0
  128. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-source-inspection-snapshots.csv +1 -0
  129. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-terminals.csv +1 -0
  130. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-tool-candidates.csv +1 -1
  131. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-tool-selection.yaml +2 -3
  132. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-traceability.csv +1 -1
  133. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-trigger-conditions.csv +1 -0
  134. package/skills/ai-delivery-design-experience/assets/experience-template/prototype.yaml +6 -0
  135. package/skills/ai-delivery-design-experience/assets/experience-template/ui-framework-selection.yaml +17 -1
  136. package/skills/ai-delivery-design-experience/assets/experience-template/ui-handoff.yaml +6 -5
  137. package/skills/ai-delivery-design-experience/assets/experience-template/ui-mapping.csv +1 -0
  138. package/skills/ai-delivery-design-experience/assets/experience-template/visual-direction.yaml +4 -0
  139. package/skills/ai-delivery-design-experience/assets/experience-template/visual-reference-manifest.yaml +23 -0
  140. package/skills/ai-delivery-design-experience/assets/experience-template/visual-reference.html +163 -0
  141. package/skills/ai-delivery-design-experience/assets/experience-template/visual-system-confirmation.yaml +11 -0
  142. package/skills/ai-delivery-design-experience/references/experience-contract.md +26 -27
  143. package/skills/ai-delivery-design-experience/references/prototype-management-contract.md +42 -21
  144. package/skills/ai-delivery-design-tests/SKILL.md +13 -7
  145. package/skills/ai-delivery-design-tests/assets/test-design-template/prototype-test-scope.csv +1 -1
  146. package/skills/ai-delivery-design-tests/assets/test-design-template/prototype-test-validation.yaml +17 -16
  147. package/skills/ai-delivery-design-tests/references/test-design-contract.md +7 -5
  148. package/skills/ai-delivery-develop-iteration/SKILL.md +18 -11
  149. package/skills/ai-delivery-develop-iteration/agents/openai.yaml +3 -3
  150. package/skills/ai-delivery-develop-iteration/assets/development-template/candidate-manifest.yaml +36 -0
  151. package/skills/ai-delivery-develop-iteration/assets/development-template/task-prototype-traceability.csv +1 -1
  152. package/skills/ai-delivery-develop-iteration/references/development-contract.md +5 -3
  153. package/skills/ai-delivery-evolve-workflow/agents/openai.yaml +3 -3
  154. package/skills/ai-delivery-execute-test/SKILL.md +6 -2
  155. package/skills/ai-delivery-execute-test/agents/openai.yaml +4 -4
  156. package/skills/ai-delivery-execute-work-package/SKILL.md +10 -3
  157. package/skills/ai-delivery-execute-work-package/agents/openai.yaml +4 -4
  158. package/skills/ai-delivery-execute-work-package/references/work-package-contract.md +1 -1
  159. package/skills/ai-delivery-manage-git/agents/openai.yaml +3 -3
  160. package/skills/ai-delivery-manage-standards/agents/openai.yaml +4 -4
  161. package/skills/ai-delivery-orchestrate/SKILL.md +47 -29
  162. package/skills/ai-delivery-orchestrate/agents/openai.yaml +3 -3
  163. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/control/migrations/.gitkeep +0 -0
  164. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/control/repairs/.gitkeep +0 -0
  165. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/delivery/project.yaml +1 -0
  166. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/delivery/workflow-state.yaml +2 -0
  167. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/frontend-guard/frontend-guard.mjs +50 -0
  168. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/hooks/hook-event.mjs +91 -0
  169. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/manager/manager.mjs +64 -0
  170. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/manager/start.cmd +4 -0
  171. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/manager/start.ps1 +2 -0
  172. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/{viewer → manager}/start.sh +1 -1
  173. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/mock/mock.mjs +50 -0
  174. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/ui-acceptance/ui-acceptance.mjs +37 -0
  175. package/skills/ai-delivery-orchestrate/assets/project-template/AGENTS.md +32 -6
  176. package/skills/ai-delivery-orchestrate/assets/project-template/gitignore.template +1 -0
  177. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/CONTRIBUTING.md +25 -0
  178. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/LICENSE +21 -0
  179. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/README.md +250 -0
  180. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/UPSTREAM.yaml +19 -0
  181. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/airbnb/DESIGN.md +545 -0
  182. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/airbnb/README.md +5 -0
  183. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/airtable/DESIGN.md +554 -0
  184. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/airtable/README.md +5 -0
  185. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/apple/DESIGN.md +562 -0
  186. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/apple/README.md +5 -0
  187. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/binance/DESIGN.md +634 -0
  188. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/binance/README.md +5 -0
  189. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bmw/DESIGN.md +544 -0
  190. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bmw/README.md +5 -0
  191. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bmw-m/DESIGN.md +503 -0
  192. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bmw-m/README.md +5 -0
  193. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bugatti/DESIGN.md +454 -0
  194. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bugatti/README.md +5 -0
  195. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cal/DESIGN.md +542 -0
  196. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cal/README.md +5 -0
  197. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/claude/DESIGN.md +589 -0
  198. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/claude/README.md +5 -0
  199. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/clay/DESIGN.md +541 -0
  200. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/clay/README.md +5 -0
  201. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/clickhouse/DESIGN.md +544 -0
  202. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/clickhouse/README.md +5 -0
  203. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cohere/DESIGN.md +451 -0
  204. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cohere/README.md +5 -0
  205. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/coinbase/DESIGN.md +570 -0
  206. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/coinbase/README.md +5 -0
  207. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/composio/DESIGN.md +506 -0
  208. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/composio/README.md +5 -0
  209. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cursor/DESIGN.md +537 -0
  210. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cursor/README.md +5 -0
  211. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/dell-1996/DESIGN.md +632 -0
  212. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/dell-1996/README.md +5 -0
  213. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/elevenlabs/DESIGN.md +504 -0
  214. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/elevenlabs/README.md +5 -0
  215. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/expo/DESIGN.md +526 -0
  216. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/expo/README.md +5 -0
  217. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ferrari/DESIGN.md +531 -0
  218. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ferrari/README.md +5 -0
  219. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/figma/DESIGN.md +578 -0
  220. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/figma/README.md +5 -0
  221. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/framer/DESIGN.md +544 -0
  222. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/framer/README.md +5 -0
  223. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/hashicorp/DESIGN.md +575 -0
  224. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/hashicorp/README.md +5 -0
  225. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/hp/DESIGN.md +670 -0
  226. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/hp/README.md +5 -0
  227. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ibm/DESIGN.md +550 -0
  228. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ibm/README.md +5 -0
  229. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/intercom/DESIGN.md +546 -0
  230. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/intercom/README.md +5 -0
  231. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/kraken/DESIGN.md +125 -0
  232. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/kraken/README.md +5 -0
  233. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/lamborghini/DESIGN.md +288 -0
  234. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/lamborghini/README.md +5 -0
  235. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/linear.app/DESIGN.md +548 -0
  236. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/linear.app/README.md +5 -0
  237. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/lovable/DESIGN.md +298 -0
  238. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/lovable/README.md +5 -0
  239. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mastercard/DESIGN.md +365 -0
  240. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mastercard/README.md +5 -0
  241. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/meta/DESIGN.md +683 -0
  242. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/meta/README.md +5 -0
  243. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/minimax/DESIGN.md +746 -0
  244. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/minimax/README.md +5 -0
  245. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mintlify/DESIGN.md +852 -0
  246. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mintlify/README.md +5 -0
  247. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/miro/DESIGN.md +825 -0
  248. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/miro/README.md +5 -0
  249. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mistral.ai/DESIGN.md +773 -0
  250. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mistral.ai/README.md +5 -0
  251. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mongodb/DESIGN.md +767 -0
  252. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mongodb/README.md +5 -0
  253. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nike/DESIGN.md +575 -0
  254. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nike/README.md +5 -0
  255. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nintendo-2001/DESIGN.md +649 -0
  256. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nintendo-2001/README.md +5 -0
  257. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/notion/DESIGN.md +821 -0
  258. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/notion/README.md +5 -0
  259. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nvidia/DESIGN.md +640 -0
  260. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nvidia/README.md +5 -0
  261. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ollama/DESIGN.md +539 -0
  262. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ollama/README.md +5 -0
  263. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/opencode.ai/DESIGN.md +521 -0
  264. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/opencode.ai/README.md +5 -0
  265. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/pinterest/DESIGN.md +597 -0
  266. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/pinterest/README.md +5 -0
  267. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/playstation/DESIGN.md +661 -0
  268. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/playstation/README.md +5 -0
  269. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/posthog/DESIGN.md +690 -0
  270. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/posthog/README.md +5 -0
  271. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/raycast/DESIGN.md +669 -0
  272. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/raycast/README.md +5 -0
  273. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/renault/DESIGN.md +589 -0
  274. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/renault/README.md +5 -0
  275. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/replicate/DESIGN.md +616 -0
  276. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/replicate/README.md +5 -0
  277. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/resend/DESIGN.md +585 -0
  278. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/resend/README.md +5 -0
  279. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/revolut/DESIGN.md +636 -0
  280. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/revolut/README.md +5 -0
  281. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/runwayml/DESIGN.md +244 -0
  282. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/runwayml/README.md +5 -0
  283. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/sanity/DESIGN.md +357 -0
  284. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/sanity/README.md +5 -0
  285. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/sentry/DESIGN.md +551 -0
  286. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/sentry/README.md +5 -0
  287. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/shopify/DESIGN.md +516 -0
  288. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/shopify/README.md +5 -0
  289. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/slack/DESIGN.md +482 -0
  290. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/spacex/DESIGN.md +363 -0
  291. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/spacex/README.md +5 -0
  292. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/spotify/DESIGN.md +246 -0
  293. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/spotify/README.md +5 -0
  294. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/starbucks/DESIGN.md +580 -0
  295. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/starbucks/README.md +5 -0
  296. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/stripe/DESIGN.md +487 -0
  297. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/stripe/README.md +5 -0
  298. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/supabase/DESIGN.md +462 -0
  299. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/supabase/README.md +5 -0
  300. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/superhuman/DESIGN.md +448 -0
  301. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/superhuman/README.md +5 -0
  302. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/tesla/DESIGN.md +286 -0
  303. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/tesla/README.md +5 -0
  304. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/theverge/DESIGN.md +339 -0
  305. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/theverge/README.md +5 -0
  306. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/together.ai/DESIGN.md +633 -0
  307. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/together.ai/README.md +5 -0
  308. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/uber/DESIGN.md +636 -0
  309. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/uber/README.md +5 -0
  310. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/vercel/DESIGN.md +736 -0
  311. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/vercel/README.md +5 -0
  312. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/vodafone/DESIGN.md +538 -0
  313. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/vodafone/README.md +5 -0
  314. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/voltagent/DESIGN.md +521 -0
  315. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/voltagent/README.md +5 -0
  316. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/warp/DESIGN.md +526 -0
  317. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/warp/README.md +5 -0
  318. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/webflow/DESIGN.md +588 -0
  319. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/webflow/README.md +5 -0
  320. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/wired/DESIGN.md +497 -0
  321. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/wired/README.md +5 -0
  322. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/wise/DESIGN.md +544 -0
  323. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/wise/README.md +5 -0
  324. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/x.ai/DESIGN.md +465 -0
  325. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/x.ai/README.md +5 -0
  326. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/zapier/DESIGN.md +537 -0
  327. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/zapier/README.md +5 -0
  328. package/skills/ai-delivery-orchestrate/references/formal-state-contract.md +65 -20
  329. package/skills/ai-delivery-orchestrate/references/workflow-model.md +7 -5
  330. package/skills/ai-delivery-orchestrate-release/SKILL.md +2 -2
  331. package/skills/ai-delivery-orchestrate-release/agents/openai.yaml +4 -4
  332. package/skills/ai-delivery-orchestrate-release/references/release-workflow-contract.md +1 -1
  333. package/skills/ai-delivery-plan-iteration/SKILL.md +11 -4
  334. package/skills/ai-delivery-plan-iteration/agents/openai.yaml +4 -4
  335. package/skills/ai-delivery-plan-iteration/assets/planning-template/scope-manifest.yaml +17 -0
  336. package/skills/ai-delivery-plan-iteration/assets/planning-template/slice-prototype-traceability.csv +1 -1
  337. package/skills/ai-delivery-plan-iteration/references/planning-contract.md +8 -2
  338. package/skills/ai-delivery-prepare-platform/SKILL.md +5 -1
  339. package/skills/ai-delivery-prepare-platform/agents/openai.yaml +4 -4
  340. package/skills/ai-delivery-prepare-release/agents/openai.yaml +4 -4
  341. package/skills/ai-delivery-review-change/SKILL.md +14 -4
  342. package/skills/ai-delivery-review-change/agents/openai.yaml +4 -4
  343. package/skills/ai-delivery-review-change/references/review-contract.md +6 -0
  344. package/skills/ai-delivery-triage-failure/SKILL.md +5 -1
  345. package/skills/ai-delivery-triage-failure/agents/openai.yaml +4 -4
  346. package/skills/ai-delivery-validate-artifacts/SKILL.md +6 -3
  347. package/skills/ai-delivery-validate-artifacts/agents/openai.yaml +4 -4
  348. package/skills/ai-delivery-validate-artifacts/references/artifact-contract.md +13 -13
  349. package/skills/ai-delivery-verify-candidate/SKILL.md +13 -6
  350. package/skills/ai-delivery-verify-candidate/agents/openai.yaml +3 -3
  351. package/skills/ai-delivery-verify-candidate/assets/verification-template/ui-acceptance-request.yaml +19 -0
  352. package/skills/ai-delivery-verify-candidate/assets/verification-template/ui-acceptance-results.yaml +53 -0
  353. package/skills/ai-delivery-verify-candidate/references/candidate-verification-contract.md +10 -2
  354. package/skills/ai-delivery-verify-production/agents/openai.yaml +3 -3
  355. package/skills/ai-delivery-design-experience/assets/experience-template/low-fidelity-confirmation.yaml +0 -32
  356. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/viewer/public/app.js +0 -546
  357. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/viewer/public/index.html +0 -199
  358. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/viewer/public/styles.css +0 -529
  359. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/viewer/server.mjs +0 -780
  360. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/viewer/start.cmd +0 -4
  361. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/viewer/start.ps1 +0 -2
@@ -0,0 +1,288 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import crypto from "node:crypto";
4
+ import { spawnSync } from "node:child_process";
5
+ import {
6
+ readYamlMapping,
7
+ requireSha256,
8
+ resolveContainedPath,
9
+ sha256File,
10
+ } from "./artifact-files.mjs";
11
+ import {
12
+ parsePrototypeCatalogCsv,
13
+ prototypeRevisionCatalogContracts,
14
+ } from "./prototype-revision.mjs";
15
+ import { buildPrototypeReviewTarget } from "./prototype-review-target.mjs";
16
+
17
+ function normalizedRelative(value, label) {
18
+ const normalized = String(value || "").replaceAll("\\", "/").replace(/^\.\//, "");
19
+ if (!normalized || path.posix.isAbsolute(normalized)
20
+ || normalized.split("/").some((part) => part === ".." || !part)) {
21
+ throw new Error(`${label} must be a normalized relative path.`);
22
+ }
23
+ return normalized;
24
+ }
25
+
26
+ function insidePath(candidate, root) {
27
+ return candidate === root || candidate.startsWith(`${root}/`);
28
+ }
29
+
30
+ function requireGovernedSource(sourceRef, sourceKind, frontendRoots, extensions) {
31
+ const covered = frontendRoots.some((root) => insidePath(sourceRef, root))
32
+ && (sourceKind === "directory"
33
+ || extensions.includes(path.posix.extname(sourceRef).toLowerCase()));
34
+ if (!covered) {
35
+ throw new Error(`Declared UI source is outside the governed frontend scope: ${sourceRef}`);
36
+ }
37
+ }
38
+
39
+ function ownershipRules(value, label, options = {}) {
40
+ if (value === undefined) return [];
41
+ if (!Array.isArray(value)) throw new Error(`${label} must be a list.`);
42
+ return value.map((entry) => {
43
+ const sourceRef = normalizedRelative(entry?.source_ref, `${label} source_ref`);
44
+ if (!new Set(["file", "directory"]).has(entry?.source_kind)) {
45
+ throw new Error(`${label} source_kind must be file or directory.`);
46
+ }
47
+ const pageIds = Array.isArray(entry.page_ids)
48
+ ? [...new Set(entry.page_ids.map((item) => String(item || "")))].sort()
49
+ : [];
50
+ if (!pageIds.length || pageIds.some((item) => !/^P[0-9]{2,}(?:-[0-9]{2,})?$/.test(item))) {
51
+ throw new Error(`${label} page_ids are invalid.`);
52
+ }
53
+ if (options.requireFile && entry.source_kind !== "file") {
54
+ throw new Error(`${label} source_kind must be file.`);
55
+ }
56
+ const approvedChecksum = options.requireChecksum
57
+ ? requireSha256(entry.approved_checksum, `${label} approved_checksum`)
58
+ : null;
59
+ return {
60
+ sourceRef,
61
+ sourceKind: entry.source_kind,
62
+ pageIds,
63
+ approvedChecksum,
64
+ };
65
+ });
66
+ }
67
+
68
+ function readFrontendScope(target) {
69
+ const revision = readYamlMapping(target.revisionFile, "Prototype revision");
70
+ const binding = revision.frontend_scope;
71
+ if (binding?.algorithm !== "sha256") {
72
+ throw new Error("Prototype revision must bind a sha256 Frontend Change Scope.");
73
+ }
74
+ const scopeFile = resolveContainedPath(
75
+ target.contentRoot,
76
+ binding.ref,
77
+ "Frontend Change Scope",
78
+ );
79
+ if (sha256File(scopeFile) !== requireSha256(binding.checksum, "Frontend Change Scope")) {
80
+ throw new Error("Frontend Change Scope checksum mismatch.");
81
+ }
82
+ const scope = readYamlMapping(scopeFile, "Frontend Change Scope");
83
+ if (scope.schema_version !== 1 || scope.artifact_type !== "frontend-change-scope") {
84
+ throw new Error("Frontend Change Scope identity is invalid.");
85
+ }
86
+ const codeRoot = normalizedRelative(scope.code_root, "Frontend Change Scope code_root");
87
+ const frontendRoots = Array.isArray(scope.frontend_roots)
88
+ ? scope.frontend_roots.map((item) => normalizedRelative(item, "Frontend root"))
89
+ : [];
90
+ const extensions = Array.isArray(scope.ui_file_extensions)
91
+ ? scope.ui_file_extensions.map((item) => String(item || "").toLowerCase())
92
+ : [];
93
+ if (!frontendRoots.length || !extensions.length
94
+ || extensions.some((item) => !/^\.[a-z0-9]+$/.test(item))) {
95
+ throw new Error("Frontend Change Scope roots or UI file extensions are invalid.");
96
+ }
97
+ return {
98
+ revision,
99
+ scope,
100
+ codeRoot,
101
+ frontendRoots,
102
+ extensions,
103
+ sharedComponents: ownershipRules(scope.shared_components, "Shared component ownership"),
104
+ routeRegistries: ownershipRules(scope.route_registries, "Route registry ownership", {
105
+ requireFile: true,
106
+ requireChecksum: true,
107
+ }),
108
+ };
109
+ }
110
+
111
+ function readUiMappings(target, revision) {
112
+ const binding = revision.catalogs?.ui_mapping;
113
+ const mappingFile = resolveContainedPath(
114
+ target.contentRoot,
115
+ binding?.ref,
116
+ "Prototype UI Mapping catalog",
117
+ );
118
+ if (binding?.algorithm !== "sha256"
119
+ || sha256File(mappingFile) !== requireSha256(binding?.checksum, "Prototype UI Mapping catalog")) {
120
+ throw new Error("Prototype UI Mapping catalog checksum mismatch.");
121
+ }
122
+ const parsed = parsePrototypeCatalogCsv(
123
+ fs.readFileSync(mappingFile, "utf8"),
124
+ "Prototype UI Mapping catalog",
125
+ );
126
+ if (parsed.header !== prototypeRevisionCatalogContracts.ui_mapping) {
127
+ throw new Error("Prototype UI Mapping catalog header is invalid.");
128
+ }
129
+ return parsed.rows.filter((row) => row.lifecycle_status === "active");
130
+ }
131
+
132
+ function changedCodePath(projectRoot, codeRoot, changedPath) {
133
+ const root = path.resolve(projectRoot);
134
+ const codeDirectory = resolveContainedPath(root, codeRoot, "Frontend code root");
135
+ const absolute = path.isAbsolute(changedPath)
136
+ ? path.resolve(changedPath)
137
+ : path.resolve(root, changedPath);
138
+ const projectRelation = path.relative(root, absolute);
139
+ if (projectRelation === ".." || projectRelation.startsWith(`..${path.sep}`)) {
140
+ throw new Error(`Changed path resolves outside the project: ${changedPath}`);
141
+ }
142
+ const codeRelation = path.relative(codeDirectory, absolute);
143
+ if (codeRelation === ".." || codeRelation.startsWith(`..${path.sep}`) || path.isAbsolute(codeRelation)) {
144
+ return null;
145
+ }
146
+ return codeRelation.replaceAll("\\", "/");
147
+ }
148
+
149
+ export function verifyFrontendChangePaths(projectRoot, changedPaths, options = {}) {
150
+ const target = buildPrototypeReviewTarget(projectRoot, {
151
+ experience: options.experience || ".workflow/experience",
152
+ revision: options.revision,
153
+ now: options.now,
154
+ });
155
+ if (target.mode !== "prototype-revision") {
156
+ throw new Error("Frontend changes require an approved, unexpired Visual Standard and frozen Prototype revision.");
157
+ }
158
+ const {
159
+ revision, codeRoot, frontendRoots, extensions, sharedComponents, routeRegistries,
160
+ } = readFrontendScope(target);
161
+ const mappings = readUiMappings(target, revision);
162
+ for (const mapping of mappings) {
163
+ requireGovernedSource(
164
+ normalizedRelative(mapping.frontend_source_ref, "UI Mapping frontend_source_ref"),
165
+ "file",
166
+ frontendRoots,
167
+ extensions,
168
+ );
169
+ }
170
+ for (const ownership of [...sharedComponents, ...routeRegistries]) {
171
+ requireGovernedSource(
172
+ ownership.sourceRef,
173
+ ownership.sourceKind,
174
+ frontendRoots,
175
+ extensions,
176
+ );
177
+ }
178
+ const guardedFiles = [];
179
+ const affectedPageIds = new Set();
180
+ for (const changedPath of changedPaths) {
181
+ const relative = changedCodePath(projectRoot, codeRoot, changedPath);
182
+ if (relative === null
183
+ || !frontendRoots.some((root) => insidePath(relative, root))
184
+ || !extensions.includes(path.posix.extname(relative).toLowerCase())) continue;
185
+ guardedFiles.push(relative);
186
+ const matching = mappings.filter((mapping) =>
187
+ normalizedRelative(mapping.frontend_source_ref, "UI Mapping frontend_source_ref") === relative);
188
+ const sharedOwnership = sharedComponents.filter((entry) =>
189
+ entry.sourceKind === "file"
190
+ ? relative === entry.sourceRef
191
+ : insidePath(relative, entry.sourceRef));
192
+ const routeOwnership = routeRegistries.filter((entry) =>
193
+ entry.sourceKind === "file"
194
+ ? relative === entry.sourceRef
195
+ : insidePath(relative, entry.sourceRef));
196
+ if (!matching.length && !sharedOwnership.length && !routeOwnership.length) {
197
+ throw new Error(`Frontend UI file is not covered by the approved UI Mapping: ${relative}`);
198
+ }
199
+ for (const mapping of matching) affectedPageIds.add(mapping.page_id);
200
+ for (const ownership of routeOwnership) {
201
+ const actualChecksum = options.routeRegistryChecksums?.get(relative);
202
+ if (actualChecksum && actualChecksum !== ownership.approvedChecksum) {
203
+ throw new Error(`Approved route registry checksum mismatch: ${relative}`);
204
+ }
205
+ }
206
+ for (const ownership of [...sharedOwnership, ...routeOwnership]) {
207
+ for (const pageId of ownership.pageIds) affectedPageIds.add(pageId);
208
+ }
209
+ }
210
+ const pageById = new Map(target.pages.map((page) => [page.page_id, page]));
211
+ for (const pageId of affectedPageIds) {
212
+ const page = pageById.get(pageId);
213
+ if (!page || page.review_status !== "approved") {
214
+ throw new Error(`Frontend change requires a current approved Prototype Page receipt: ${pageId}.`);
215
+ }
216
+ }
217
+ return {
218
+ valid: true,
219
+ prototype_revision_id: target.targetId,
220
+ prototype_revision_checksum: target.targetChecksum,
221
+ guarded_files: [...new Set(guardedFiles)].sort(),
222
+ affected_page_ids: [...affectedPageIds].sort(),
223
+ };
224
+ }
225
+
226
+ function requireGitRef(value, label) {
227
+ const ref = String(value || "");
228
+ if (!ref || ref.startsWith("-") || /[\0\r\n]/.test(ref)) {
229
+ throw new Error(`${label} Git ref is invalid.`);
230
+ }
231
+ return ref;
232
+ }
233
+
234
+ export function verifyFrontendDiff(projectRoot, options = {}) {
235
+ const target = buildPrototypeReviewTarget(projectRoot, {
236
+ experience: options.experience || ".workflow/experience",
237
+ revision: options.revision,
238
+ now: options.now,
239
+ });
240
+ if (target.mode !== "prototype-revision") {
241
+ throw new Error("Frontend changes require an approved, unexpired Visual Standard and frozen Prototype revision.");
242
+ }
243
+ const { codeRoot, routeRegistries } = readFrontendScope(target);
244
+ const codeDirectory = resolveContainedPath(projectRoot, codeRoot, "Frontend code root");
245
+ const base = requireGitRef(options.base, "Base");
246
+ const head = requireGitRef(options.head || "HEAD", "Head");
247
+ const diff = spawnSync("git", [
248
+ "-C", codeDirectory, "diff", "--name-only", "-z", `${base}...${head}`, "--",
249
+ ], { encoding: "utf8", windowsHide: true, maxBuffer: 8 * 1024 * 1024 });
250
+ if (diff.error || diff.status !== 0) {
251
+ throw new Error(`Cannot independently read frontend Git diff: ${diff.error?.message || diff.stderr.trim() || `git exited ${diff.status}`}`);
252
+ }
253
+ const changed = diff.stdout.split("\0").filter(Boolean);
254
+ const changedSet = new Set(changed.map((item) => item.replaceAll("\\", "/")));
255
+ const routeRegistryChecksums = new Map();
256
+ for (const registry of routeRegistries.filter((entry) => changedSet.has(entry.sourceRef))) {
257
+ const blob = spawnSync("git", [
258
+ "-C", codeDirectory, "show", `${head}:${registry.sourceRef}`,
259
+ ], { encoding: null, windowsHide: true, maxBuffer: 8 * 1024 * 1024 });
260
+ if (blob.error || blob.status !== 0) {
261
+ throw new Error(
262
+ `Cannot independently read route registry from Head: ${registry.sourceRef}.`,
263
+ );
264
+ }
265
+ routeRegistryChecksums.set(
266
+ registry.sourceRef,
267
+ crypto.createHash("sha256").update(blob.stdout).digest("hex"),
268
+ );
269
+ }
270
+ const report = verifyFrontendChangePaths(
271
+ projectRoot,
272
+ changed.map((item) => `${codeRoot}/${item.replaceAll("\\", "/")}`),
273
+ { ...options, routeRegistryChecksums },
274
+ );
275
+ return {
276
+ ...report,
277
+ git_diff: { base, head, changed_file_count: changed.length },
278
+ };
279
+ }
280
+
281
+ export function runFrontendGuardCommand(projectRoot, action, options = {}) {
282
+ if (action === "check-file") {
283
+ if (!options.path) throw new Error("frontend-guard check-file requires --path.");
284
+ return verifyFrontendChangePaths(projectRoot, [options.path], options);
285
+ }
286
+ if (action === "verify-diff") return verifyFrontendDiff(projectRoot, options);
287
+ throw new Error(`Unknown frontend-guard action: ${action}`);
288
+ }
@@ -0,0 +1,53 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ export function atomicWrite(file, content) {
5
+ fs.mkdirSync(path.dirname(file), { recursive: true });
6
+ const temporary = `${file}.${process.pid}.${Date.now()}.tmp`;
7
+ fs.writeFileSync(temporary, content, "utf8");
8
+ fs.renameSync(temporary, file);
9
+ }
10
+
11
+ export function filesUnder(root) {
12
+ if (!fs.existsSync(root)) return [];
13
+ const files = [];
14
+ const visit = (directory) => {
15
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
16
+ const absolute = path.join(directory, entry.name);
17
+ if (entry.isDirectory()) visit(absolute);
18
+ else if (entry.isFile()) files.push(absolute);
19
+ }
20
+ };
21
+ visit(root);
22
+ return files.sort((left, right) => left.localeCompare(right));
23
+ }
24
+
25
+ export function assertPathInside(root, target) {
26
+ const realRoot = fs.realpathSync(root);
27
+ let existingAncestor = path.resolve(target);
28
+ while (!fs.existsSync(existingAncestor)) {
29
+ const parent = path.dirname(existingAncestor);
30
+ if (parent === existingAncestor) break;
31
+ existingAncestor = parent;
32
+ }
33
+ const realAncestor = fs.realpathSync(existingAncestor);
34
+ const relative = path.relative(realRoot, realAncestor);
35
+ if (relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative))) return target;
36
+ throw new Error(`Path resolves outside the project: ${target} -> ${realAncestor}`);
37
+ }
38
+
39
+ export function resolveContainedRelativePath(root, relative, allowedPrefixes = []) {
40
+ const value = String(relative || "");
41
+ if (!value || value.includes("\\") || value.includes("\0")
42
+ || path.posix.isAbsolute(value) || path.posix.normalize(value) !== value
43
+ || value === ".." || value.startsWith("../")) {
44
+ throw new Error(`Invalid migration path: ${value || "missing"}.`);
45
+ }
46
+ if (allowedPrefixes.length && !allowedPrefixes.some((prefix) =>
47
+ value === prefix || value.startsWith(`${prefix}/`))) {
48
+ throw new Error(`Migration path is outside its allowed area: ${value}.`);
49
+ }
50
+ const target = path.resolve(root, ...value.split("/"));
51
+ assertPathInside(root, target);
52
+ return target;
53
+ }
@@ -0,0 +1,98 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+
5
+ function sha256(value) {
6
+ return crypto.createHash("sha256").update(value).digest("hex");
7
+ }
8
+
9
+ function stableValue(value) {
10
+ if (Array.isArray(value)) return value.map(stableValue);
11
+ if (!value || typeof value !== "object") return value;
12
+ return Object.fromEntries(Object.keys(value).sort().map((key) => [key, stableValue(value[key])]));
13
+ }
14
+
15
+ export function structuredDocumentChecksum(value, checksumField, stringify) {
16
+ const unsigned = { ...value };
17
+ delete unsigned[checksumField];
18
+ return sha256(stringify(stableValue(unsigned)));
19
+ }
20
+
21
+ export function historyAnchorId(value) {
22
+ const anchorId = String(value || "");
23
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(anchorId)) {
24
+ throw new Error(`History anchor ID is invalid: ${anchorId || "missing"}.`);
25
+ }
26
+ return anchorId;
27
+ }
28
+
29
+ export function readVerifiedHistoryAnchor({
30
+ historySnapshots,
31
+ events,
32
+ streams,
33
+ readStructured,
34
+ stringify,
35
+ }) {
36
+ const pointerFile = path.join(historySnapshots, "latest.yaml");
37
+ if (!fs.existsSync(pointerFile)) return null;
38
+ const pointer = readStructured(pointerFile, "latest history anchor pointer");
39
+ if (pointer.schema_version !== 1 || !pointer.anchor_id || !pointer.anchor_checksum
40
+ || structuredDocumentChecksum(pointer, "pointer_checksum", stringify)
41
+ !== pointer.pointer_checksum) {
42
+ throw new Error("Latest history anchor pointer is invalid.");
43
+ }
44
+ const anchorId = historyAnchorId(pointer.anchor_id);
45
+ const directory = path.join(historySnapshots, anchorId);
46
+ const anchorFile = path.join(directory, "anchor.yaml");
47
+ const anchor = readStructured(anchorFile, `history anchor ${anchorId}`);
48
+ if (anchor.schema_version !== 1 || anchor.anchor_id !== anchorId
49
+ || anchor.anchor_checksum !== pointer.anchor_checksum
50
+ || structuredDocumentChecksum(anchor, "anchor_checksum", stringify) !== anchor.anchor_checksum) {
51
+ throw new Error(`History anchor checksum is invalid: ${anchorId}.`);
52
+ }
53
+ const snapshots = {};
54
+ const snapshotFiles = {};
55
+ for (const [stream, descriptor] of streams) {
56
+ const metadata = anchor.streams?.[stream];
57
+ if (!metadata || !Number.isInteger(metadata.revision) || metadata.revision < 0
58
+ || !/^[a-f0-9]{64}$/.test(metadata.view_checksum || "")
59
+ || (metadata.record_checksum !== null && !/^[a-f0-9]{64}$/.test(metadata.record_checksum || ""))) {
60
+ throw new Error(`History anchor stream metadata is invalid: ${anchorId}/${stream}.`);
61
+ }
62
+ const snapshotFile = path.join(directory, descriptor.snapshotFile);
63
+ if (!fs.existsSync(snapshotFile)
64
+ || sha256(fs.readFileSync(snapshotFile)) !== metadata.view_checksum) {
65
+ throw new Error(`History anchor snapshot checksum is invalid: ${anchorId}/${stream}.`);
66
+ }
67
+ snapshots[stream] = descriptor.normalize(readStructured(
68
+ snapshotFile,
69
+ `history anchor snapshot ${anchorId}/${stream}`,
70
+ ));
71
+ if (snapshots[stream].revision !== metadata.revision) {
72
+ throw new Error(`History anchor snapshot revision is invalid: ${anchorId}/${stream}.`);
73
+ }
74
+ snapshotFiles[stream] = snapshotFile;
75
+ }
76
+ const eventOffset = anchor.event_index?.offset_bytes;
77
+ const eventCount = anchor.event_index?.event_count;
78
+ const currentEventBytes = fs.existsSync(events) ? fs.statSync(events).size : 0;
79
+ if (!Number.isInteger(eventOffset) || eventOffset < 0 || eventOffset > currentEventBytes
80
+ || !Number.isInteger(eventCount) || eventCount < 0
81
+ || eventCount !== Object.values(anchor.streams)
82
+ .reduce((total, stream) => total + stream.revision, 0)) {
83
+ throw new Error(`History anchor event index metadata is invalid: ${anchorId}.`);
84
+ }
85
+ if (eventOffset > 0) {
86
+ const descriptor = fs.openSync(events, "r");
87
+ try {
88
+ const boundary = Buffer.alloc(1);
89
+ fs.readSync(descriptor, boundary, 0, 1, eventOffset - 1);
90
+ if (boundary[0] !== 0x0a) {
91
+ throw new Error(`History anchor event index boundary is invalid: ${anchorId}.`);
92
+ }
93
+ } finally {
94
+ fs.closeSync(descriptor);
95
+ }
96
+ }
97
+ return { pointer, pointerFile, anchor, anchorFile, snapshots, snapshotFiles };
98
+ }