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,713 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
5
+ import { resolveContainedPath as containedRef } from "./artifact-files.mjs";
6
+ import { atomicWrite, filesUnder } from "./fs-utils.mjs";
7
+ import { parsePrototypeCatalogCsv } from "./prototype-revision.mjs";
8
+ import { stableValue } from "./stable-value.mjs";
9
+
10
+ const TARGET_PROTOTYPE_ID = "PROTOTYPE";
11
+ const SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
12
+
13
+ function toPosix(value) {
14
+ return value.replaceAll("\\", "/");
15
+ }
16
+
17
+ function sha256(value) {
18
+ return crypto.createHash("sha256").update(value).digest("hex");
19
+ }
20
+
21
+ function stableJson(value) {
22
+ return JSON.stringify(stableValue(value));
23
+ }
24
+
25
+ function readYaml(file, label) {
26
+ try {
27
+ const document = parseYaml(fs.readFileSync(file, "utf8"));
28
+ if (!document || typeof document !== "object" || Array.isArray(document)) {
29
+ throw new Error("expected a mapping");
30
+ }
31
+ return document;
32
+ } catch (error) {
33
+ throw new Error(`Cannot read ${label} (${toPosix(file)}): ${error.message}`);
34
+ }
35
+ }
36
+
37
+ function currentIterationId(root) {
38
+ for (const deliveryRoot of [".workflow/delivery", "delivery"]) {
39
+ const stateFile = path.join(root, ...deliveryRoot.split("/"), "workflow-state.yaml");
40
+ if (fs.existsSync(stateFile)) {
41
+ const state = readYaml(stateFile, "workflow state");
42
+ const active = String(state.development_state?.scope_id || "").trim();
43
+ if (active) {
44
+ if (!SAFE_ID.test(active)) throw new Error(`Active iteration ID is unsafe: ${active}.`);
45
+ return active;
46
+ }
47
+ }
48
+ const projectFile = path.join(root, ...deliveryRoot.split("/"), "project.yaml");
49
+ if (fs.existsSync(projectFile)) {
50
+ const project = readYaml(projectFile, "project descriptor");
51
+ const active = String(project.current_iteration_id || "").trim();
52
+ if (active) {
53
+ if (!SAFE_ID.test(active)) throw new Error(`Active iteration ID is unsafe: ${active}.`);
54
+ return active;
55
+ }
56
+ }
57
+ }
58
+ return null;
59
+ }
60
+
61
+ function discoverLegacySets(root, activeIterationId) {
62
+ const iterationPrefixes = [".workflow/iterations", "iterations"];
63
+ const experiencePrefixes = [".workflow/experience", "experience"];
64
+ const archivePrefixes = [".workflow/control/archives/versions", "control/archives/versions"];
65
+ const designNodes = ["02-solution-design", "04-experience-design"];
66
+ const sets = [];
67
+ const addIterationSets = (prefix, scopeForIteration) => {
68
+ const iterationsRoot = path.join(root, ...prefix.split("/"));
69
+ if (!fs.existsSync(iterationsRoot)) return;
70
+ for (const entry of fs.readdirSync(iterationsRoot, { withFileTypes: true })) {
71
+ if (!entry.isDirectory()) continue;
72
+ const iterationId = entry.name;
73
+ for (const node of designNodes) {
74
+ const file = path.join(iterationsRoot, iterationId, node, "prototype-set.yaml");
75
+ if (!fs.existsSync(file) || !fs.statSync(file).isFile()) continue;
76
+ sets.push({ file, iteration_id: iterationId, scope: scopeForIteration(iterationId) });
77
+ }
78
+ }
79
+ };
80
+ for (const prefix of iterationPrefixes) {
81
+ addIterationSets(prefix, (iterationId) =>
82
+ iterationId === activeIterationId ? "open" : "closed");
83
+ }
84
+ for (const prefix of experiencePrefixes) {
85
+ const experienceRoot = path.join(root, ...prefix.split("/"));
86
+ if (fs.existsSync(experienceRoot)) {
87
+ for (const entry of fs.readdirSync(experienceRoot, { withFileTypes: true })) {
88
+ if (!entry.isDirectory()) continue;
89
+ const file = path.join(experienceRoot, entry.name, "prototype-set.yaml");
90
+ if (!fs.existsSync(file) || !fs.statSync(file).isFile()) continue;
91
+ sets.push({
92
+ file,
93
+ iteration_id: entry.name,
94
+ scope: entry.name === activeIterationId ? "open" : "closed",
95
+ });
96
+ }
97
+ }
98
+ const directFile = path.join(experienceRoot, "prototype-set.yaml");
99
+ if (fs.existsSync(directFile) && fs.statSync(directFile).isFile()) {
100
+ sets.push({
101
+ file: directFile,
102
+ iteration_id: activeIterationId,
103
+ scope: activeIterationId ? "open" : "closed",
104
+ });
105
+ }
106
+ }
107
+ for (const prefix of archivePrefixes) {
108
+ addIterationSets(prefix, () => "archived");
109
+ }
110
+ return sets.sort((left, right) => left.file.localeCompare(right.file));
111
+ }
112
+
113
+ function setMembers(document) {
114
+ if (Array.isArray(document.members)) return document.members;
115
+ if (Array.isArray(document.ordered_members)) return document.ordered_members;
116
+ return [];
117
+ }
118
+
119
+ function memberIdentity(value) {
120
+ return String(value?.prototype_member_id || value?.prototype_artifact_id || value?.artifact_id || "").trim();
121
+ }
122
+
123
+ function manifestRef(setDirectory, member, memberId) {
124
+ const explicit = String(member.manifest_ref || "").trim();
125
+ if (explicit) return explicit;
126
+ for (const candidate of [`prototype-manifest-${memberId}.yaml`, "prototype-manifest.yaml"]) {
127
+ if (fs.existsSync(path.join(setDirectory, candidate))) return candidate;
128
+ }
129
+ return "";
130
+ }
131
+
132
+ function catalogBinding(manifest, kind) {
133
+ const keys = kind === "routes"
134
+ ? ["prototype_routes", "routes"]
135
+ : kind === "pages" ? ["page_catalog"] : ["prototype_files"];
136
+ for (const key of keys) {
137
+ const ref = manifest[`${key}_ref`];
138
+ if (!ref) continue;
139
+ return {
140
+ ref: String(ref),
141
+ algorithm: String(manifest[`${key}_algorithm`] || "sha256"),
142
+ checksum: String(manifest[`${key}_checksum`] || ""),
143
+ };
144
+ }
145
+ return null;
146
+ }
147
+
148
+ function sourceBinding(manifest) {
149
+ const ref = manifest.source_path || manifest.prototype?.source_ref;
150
+ const checksum = manifest.source_checksum || manifest.prototype?.source_checksum;
151
+ return {
152
+ ref: String(ref || ""),
153
+ algorithm: String(manifest.source_algorithm || manifest.prototype?.source_algorithm || "sha256"),
154
+ checksum: String(checksum || ""),
155
+ };
156
+ }
157
+
158
+ function exactSourceFiles(source) {
159
+ if (!fs.existsSync(source)) return [];
160
+ if (fs.statSync(source).isFile()) return [source];
161
+ if (fs.statSync(source).isDirectory()) return filesUnder(source);
162
+ return [];
163
+ }
164
+
165
+ function sourceDigest(source) {
166
+ if (fs.statSync(source).isFile()) return sha256(fs.readFileSync(source));
167
+ const hash = crypto.createHash("sha256");
168
+ for (const file of filesUnder(source)) {
169
+ hash.update(toPosix(path.relative(source, file)));
170
+ hash.update("\0");
171
+ hash.update(fs.readFileSync(file));
172
+ hash.update("\0");
173
+ }
174
+ return hash.digest("hex");
175
+ }
176
+
177
+ function conflict(kind, id, records, reason = "member-definitions-differ") {
178
+ const memberIds = [...new Set(records.map((record) => record.member_id))].sort();
179
+ const recordChecksums = records.map((record) => record.record_checksum).sort();
180
+ const conflictId = `PROTO-CONFLICT-${sha256(stableJson({ kind, id, memberIds, recordChecksums, reason })).slice(0, 16).toUpperCase()}`;
181
+ return {
182
+ conflict_id: conflictId,
183
+ target_kind: kind,
184
+ target_id: id,
185
+ member_ids: memberIds,
186
+ reason,
187
+ decision_required: reason === "member-definitions-differ",
188
+ };
189
+ }
190
+
191
+ function mergeRecords(kind, identityField, records) {
192
+ const grouped = new Map();
193
+ const conflicts = [];
194
+ for (const [index, record] of records.entries()) {
195
+ const id = String(record[identityField] || "").trim();
196
+ if (!id) {
197
+ conflicts.push(conflict(
198
+ kind,
199
+ `${record.member_id}:${identityField}:row-${index + 1}`,
200
+ [record],
201
+ "missing-stable-identity",
202
+ ));
203
+ continue;
204
+ }
205
+ if (!grouped.has(id)) grouped.set(id, []);
206
+ grouped.get(id).push(record);
207
+ }
208
+ const merged = [];
209
+ for (const [id, candidates] of grouped) {
210
+ const unique = new Set(candidates.map((record) => record.record_checksum));
211
+ const duplicateMembers = new Set(candidates
212
+ .map((record) => record.member_id)
213
+ .filter((memberId, index, memberIds) => memberIds.indexOf(memberId) !== index));
214
+ if (duplicateMembers.size) {
215
+ conflicts.push(conflict(
216
+ kind,
217
+ id,
218
+ candidates.filter((record) => duplicateMembers.has(record.member_id)),
219
+ "duplicate-member-record-id",
220
+ ));
221
+ } else if (unique.size > 1) conflicts.push(conflict(kind, id, candidates));
222
+ const canonical = [...candidates].sort((left, right) =>
223
+ left.member_id.localeCompare(right.member_id))[0];
224
+ merged.push({
225
+ [`${kind === "file" ? "file" : kind}_id`]: id,
226
+ member_ids: [...new Set(candidates.map((record) => record.member_id))].sort(),
227
+ record_checksum: canonical.record_checksum,
228
+ conflict: unique.size > 1,
229
+ });
230
+ }
231
+ return {
232
+ records: merged.sort((left, right) => String(left[`${kind === "file" ? "file" : kind}_id`])
233
+ .localeCompare(String(right[`${kind === "file" ? "file" : kind}_id`]))),
234
+ conflicts,
235
+ };
236
+ }
237
+
238
+ function readCatalog(member, kind, conflicts, sourceFiles, required) {
239
+ const binding = catalogBinding(member.manifest, kind);
240
+ if (!binding) {
241
+ if (required) conflicts.push(conflict("catalog", `${member.member_id}:${kind}`, [{
242
+ member_id: member.member_id,
243
+ record_checksum: sha256("missing"),
244
+ }], "catalog-binding-missing"));
245
+ return [];
246
+ }
247
+ let file;
248
+ try {
249
+ file = containedRef(member.directory, binding.ref, `Legacy Prototype ${kind} catalog`);
250
+ } catch (error) {
251
+ conflicts.push(conflict("catalog", `${member.member_id}:${kind}`, [{
252
+ member_id: member.member_id,
253
+ record_checksum: sha256(error.message),
254
+ }], "invalid-catalog-ref"));
255
+ return [];
256
+ }
257
+ if (binding.algorithm !== "sha256" || !/^[a-f0-9]{64}$/.test(binding.checksum)
258
+ || !fs.existsSync(file) || sha256(fs.readFileSync(file)) !== binding.checksum) {
259
+ conflicts.push(conflict("catalog", `${member.member_id}:${kind}`, [{
260
+ member_id: member.member_id,
261
+ record_checksum: fs.existsSync(file) ? sha256(fs.readFileSync(file)) : sha256("missing"),
262
+ }], "catalog-checksum-mismatch"));
263
+ return [];
264
+ }
265
+ sourceFiles.add(file);
266
+ return parsePrototypeCatalogCsv(
267
+ fs.readFileSync(file, "utf8"),
268
+ `Legacy Prototype ${kind} catalog`,
269
+ ).rows
270
+ .map((row) => ({
271
+ ...row,
272
+ member_id: member.member_id,
273
+ record_checksum: sha256(stableJson(row)),
274
+ }));
275
+ }
276
+
277
+ function loadOpenMembers(root, openSets) {
278
+ const members = [];
279
+ const conflicts = [];
280
+ const sourceFiles = new Set();
281
+ let declaredMemberCount = 0;
282
+ for (const set of openSets) {
283
+ sourceFiles.add(set.file);
284
+ const document = readYaml(set.file, "legacy Prototype set");
285
+ const directory = path.dirname(set.file);
286
+ for (const item of setMembers(document)) {
287
+ declaredMemberCount += 1;
288
+ const expectedId = memberIdentity(item);
289
+ if (!SAFE_ID.test(expectedId)) {
290
+ conflicts.push(conflict("member", expectedId || "missing", [{
291
+ member_id: expectedId || "missing",
292
+ record_checksum: sha256(stableJson(item)),
293
+ }], "invalid-member-id"));
294
+ continue;
295
+ }
296
+ const ref = manifestRef(directory, item, expectedId);
297
+ let manifestFile;
298
+ try {
299
+ manifestFile = containedRef(directory, ref, "Legacy Prototype member manifest");
300
+ } catch (error) {
301
+ conflicts.push(conflict("member", expectedId || "missing", [{
302
+ member_id: expectedId || "missing",
303
+ record_checksum: sha256(error.message),
304
+ }], "invalid-manifest-ref"));
305
+ continue;
306
+ }
307
+ const expectedChecksum = String(item.manifest_checksum || "");
308
+ if (!expectedId || !fs.existsSync(manifestFile) || !/^[a-f0-9]{64}$/.test(expectedChecksum)
309
+ || sha256(fs.readFileSync(manifestFile)) !== expectedChecksum) {
310
+ conflicts.push(conflict("member", expectedId || "missing", [{
311
+ member_id: expectedId || "missing",
312
+ record_checksum: fs.existsSync(manifestFile)
313
+ ? sha256(fs.readFileSync(manifestFile)) : sha256("missing"),
314
+ }], "manifest-checksum-mismatch"));
315
+ continue;
316
+ }
317
+ sourceFiles.add(manifestFile);
318
+ const manifest = readYaml(manifestFile, "legacy Prototype member manifest");
319
+ const actualId = memberIdentity(manifest);
320
+ if (actualId !== expectedId) {
321
+ conflicts.push(conflict("member", expectedId, [{
322
+ member_id: expectedId,
323
+ record_checksum: sha256(stableJson({ expectedId, actualId })),
324
+ }], "member-identity-mismatch"));
325
+ continue;
326
+ }
327
+ const binding = sourceBinding(manifest);
328
+ let source;
329
+ try {
330
+ source = containedRef(directory, binding.ref, "Legacy Prototype source");
331
+ } catch (error) {
332
+ conflicts.push(conflict("source", expectedId, [{
333
+ member_id: expectedId,
334
+ record_checksum: sha256(error.message),
335
+ }], "invalid-source-ref"));
336
+ continue;
337
+ }
338
+ if (!fs.existsSync(source) || !new Set(["sha256", "sha256-tree-v1"]).has(binding.algorithm)
339
+ || !/^[a-f0-9]{64}$/.test(binding.checksum)
340
+ || sourceDigest(source) !== binding.checksum) {
341
+ conflicts.push(conflict("source", expectedId, [{
342
+ member_id: expectedId,
343
+ record_checksum: fs.existsSync(source) ? sourceDigest(source) : sha256("missing"),
344
+ }], "source-checksum-mismatch"));
345
+ continue;
346
+ }
347
+ for (const file of exactSourceFiles(source)) sourceFiles.add(file);
348
+ members.push({
349
+ member_id: expectedId,
350
+ manifest_ref: toPosix(path.relative(root, manifestFile)),
351
+ manifest_checksum: expectedChecksum,
352
+ directory,
353
+ manifest,
354
+ source,
355
+ source_ref: toPosix(path.relative(root, source)),
356
+ source_checksum: binding.checksum,
357
+ terminal_ids: [...new Set([
358
+ ...(Array.isArray(item.terminal_ids) ? item.terminal_ids : []),
359
+ ...(Array.isArray(manifest.terminal_ids) ? manifest.terminal_ids : []),
360
+ ...(Array.isArray(manifest.coverage?.terminal_ids) ? manifest.coverage.terminal_ids : []),
361
+ ].map(String))].sort(),
362
+ });
363
+ }
364
+ }
365
+ members.sort((left, right) => left.member_id.localeCompare(right.member_id));
366
+ const duplicateIds = [...new Set(members.map((member) => member.member_id))]
367
+ .filter((id) => members.filter((member) => member.member_id === id).length > 1);
368
+ for (const id of duplicateIds) {
369
+ conflicts.push(conflict("member", id, members.filter((member) => member.member_id === id)
370
+ .map((member) => ({ member_id: id, record_checksum: member.manifest_checksum })), "duplicate-member-id"));
371
+ }
372
+ return { members, conflicts, sourceFiles, declaredMemberCount };
373
+ }
374
+
375
+ function mergeReport(loaded) {
376
+ const conflicts = [...loaded.conflicts];
377
+ const sourceFiles = loaded.sourceFiles;
378
+ const terminals = loaded.members.flatMap((member) => member.terminal_ids.map((terminalId) => ({
379
+ terminal_id: terminalId,
380
+ member_id: member.member_id,
381
+ record_checksum: sha256(stableJson({ terminal_id: terminalId })),
382
+ })));
383
+ const requireCatalogs = loaded.members.length > 0;
384
+ const pages = loaded.members.flatMap((member) =>
385
+ readCatalog(member, "pages", conflicts, sourceFiles, requireCatalogs));
386
+ const routes = loaded.members.flatMap((member) =>
387
+ readCatalog(member, "routes", conflicts, sourceFiles, requireCatalogs));
388
+ const files = loaded.members.flatMap((member) =>
389
+ readCatalog(member, "files", conflicts, sourceFiles, requireCatalogs));
390
+ const terminalMerge = mergeRecords("terminal", "terminal_id", terminals);
391
+ const pageMerge = mergeRecords("page", "page_id", pages);
392
+ const routeMerge = mergeRecords("route", "route_id", routes);
393
+ const fileMerge = mergeRecords("file", "file_ref", files);
394
+ conflicts.push(...terminalMerge.conflicts, ...pageMerge.conflicts, ...routeMerge.conflicts, ...fileMerge.conflicts);
395
+ return {
396
+ terminals: terminalMerge.records,
397
+ pages: pageMerge.records,
398
+ routes: routeMerge.records,
399
+ files: fileMerge.records,
400
+ conflicts: conflicts.sort((left, right) => left.conflict_id.localeCompare(right.conflict_id)),
401
+ };
402
+ }
403
+
404
+ function applyDecisions(report, decisionsFile, sourceChecksum) {
405
+ report.decisions = [];
406
+ report.unresolved_conflicts = report.merge_report.conflicts.map((item) => ({ ...item }));
407
+ report.decision_template = {
408
+ schema_version: 1,
409
+ source_checksum: sourceChecksum || "REPLACE_WITH_MIGRATION_SOURCE_CHECKSUM",
410
+ actor: "human:<identity>",
411
+ decisions: [],
412
+ prototype_decisions: report.merge_report.conflicts.filter((item) => item.decision_required).map((item) => ({
413
+ conflict_id: item.conflict_id,
414
+ action: "choose-member",
415
+ member_id: item.member_ids[0] || "<member-id>",
416
+ rationale: "<why this member is canonical for the merged identity>",
417
+ })),
418
+ };
419
+ if (!decisionsFile) return;
420
+ if (!sourceChecksum) throw new Error("Prototype migration decisions require the migration source checksum.");
421
+ const document = readYaml(path.resolve(decisionsFile), "migration decisions");
422
+ if (document.schema_version !== 1 || document.source_checksum !== sourceChecksum) {
423
+ throw new Error("Prototype migration decisions do not match the current source checksum.");
424
+ }
425
+ const actor = String(document.actor || "").trim();
426
+ if (!actor.startsWith("human:")) {
427
+ throw new Error("Prototype migration decisions require actor human:<identity>.");
428
+ }
429
+ if (!Array.isArray(document.prototype_decisions)) {
430
+ throw new Error("Prototype migration decisions must contain a prototype_decisions list.");
431
+ }
432
+ const byId = new Map();
433
+ for (const decision of document.prototype_decisions) {
434
+ const id = String(decision?.conflict_id || "");
435
+ if (!id || byId.has(id)) throw new Error(`Prototype migration conflict decision is missing or duplicated: ${id || "missing"}.`);
436
+ byId.set(id, decision);
437
+ }
438
+ const unresolved = [];
439
+ for (const item of report.merge_report.conflicts) {
440
+ const decision = byId.get(item.conflict_id);
441
+ if (!decision) {
442
+ unresolved.push(item);
443
+ continue;
444
+ }
445
+ if (!item.decision_required) {
446
+ throw new Error(
447
+ `Prototype migration conflict ${item.conflict_id} (${item.reason}) is not human-resolvable; decisions cannot override integrity or structural evidence.`,
448
+ );
449
+ }
450
+ const memberId = String(decision.member_id || "");
451
+ const rationale = String(decision.rationale || "").trim();
452
+ if (decision.action !== "choose-member" || !item.member_ids.includes(memberId) || !rationale) {
453
+ throw new Error(`Prototype migration decision is invalid for ${item.conflict_id}.`);
454
+ }
455
+ const normalized = {
456
+ conflict_id: item.conflict_id,
457
+ action: "choose-member",
458
+ member_id: memberId,
459
+ actor,
460
+ rationale,
461
+ };
462
+ report.decisions.push(normalized);
463
+ item.decision_required = false;
464
+ item.resolution = normalized;
465
+ }
466
+ for (const id of byId.keys()) {
467
+ if (!report.merge_report.conflicts.some((item) => item.conflict_id === id)) {
468
+ throw new Error(`Prototype migration decision does not match a conflict: ${id}.`);
469
+ }
470
+ }
471
+ report.decisions.sort((left, right) => left.conflict_id.localeCompare(right.conflict_id));
472
+ report.unresolved_conflicts = unresolved;
473
+ }
474
+
475
+ function generatedContent(report) {
476
+ const migrationId = `PROTOTYPE-MIGRATION-${report.source_checksum.slice(0, 16).toUpperCase()}`;
477
+ const migrationRecord = stableValue({
478
+ schema_version: 1,
479
+ artifact_id: migrationId,
480
+ artifact_type: "legacy-prototype-migration",
481
+ iteration_id: report.iteration_id,
482
+ status: "applied-pending-ux-ui",
483
+ source_checksum: report.source_checksum,
484
+ target_prototype_id: TARGET_PROTOTYPE_ID,
485
+ legacy_sets: report.legacy_sets,
486
+ members: report.members,
487
+ merge_report: report.merge_report,
488
+ decisions: report.decisions,
489
+ preserved_history: report.preserved_history,
490
+ approval: report.approval,
491
+ });
492
+ const descriptor = stableValue({
493
+ schema_version: 1,
494
+ artifact_type: "prototype-current",
495
+ prototype_id: TARGET_PROTOTYPE_ID,
496
+ iteration_id: report.iteration_id,
497
+ status: "migration-pending-ux-ui",
498
+ current_source_ref: "prototype/source",
499
+ current_review_shell_ref: "prototype/review-shell",
500
+ current_revision_ref: null,
501
+ migration: {
502
+ artifact_id: migrationId,
503
+ ref: "prototype-migration.yaml",
504
+ algorithm: "sha256",
505
+ checksum: sha256(stringifyYaml(migrationRecord, { lineWidth: 0 })),
506
+ },
507
+ });
508
+ const links = report.members.map((member) =>
509
+ `<li><a href="../source/${encodeURIComponent(member.member_id)}/">${member.member_id}</a></li>`).join("");
510
+ const shell = `<!doctype html>\n<html lang="en"><head><meta charset="utf-8"><title>Legacy Prototype migration</title></head><body><main><h1>Prototype migration pending UX-UI</h1><ul>${links}</ul></main></body></html>\n`;
511
+ return {
512
+ descriptor: stringifyYaml(descriptor, { lineWidth: 0 }),
513
+ migration: stringifyYaml(migrationRecord, { lineWidth: 0 }),
514
+ shell,
515
+ };
516
+ }
517
+
518
+ function buildOperations(root, report) {
519
+ const generated = generatedContent(report);
520
+ const writes = [
521
+ { path: ".workflow/experience/" + report.iteration_id + "/prototype.yaml", kind: "prototype-current", content: Buffer.from(generated.descriptor) },
522
+ { path: ".workflow/experience/" + report.iteration_id + "/prototype-migration.yaml", kind: "prototype-migration-record", content: Buffer.from(generated.migration) },
523
+ { path: ".workflow/experience/" + report.iteration_id + "/prototype/review-shell/index.html", kind: "prototype-review-shell", content: Buffer.from(generated.shell) },
524
+ ];
525
+ const copies = [];
526
+ for (const member of report.members) {
527
+ const source = path.join(root, ...member.source_ref.split("/"));
528
+ const sourceRoot = fs.statSync(source).isDirectory() ? source : path.dirname(source);
529
+ for (const file of exactSourceFiles(source)) {
530
+ const sourceTail = fs.statSync(source).isDirectory()
531
+ ? toPosix(path.relative(sourceRoot, file)) : path.basename(file);
532
+ copies.push({
533
+ source_path: toPosix(path.relative(root, file)),
534
+ target_path: `.workflow/experience/${report.iteration_id}/prototype/source/${member.member_id}/${sourceTail}`,
535
+ source_sha256: sha256(fs.readFileSync(file)),
536
+ target_sha256: sha256(fs.readFileSync(file)),
537
+ transformation: "byte-for-byte",
538
+ });
539
+ }
540
+ }
541
+ const targetConflicts = [];
542
+ for (const operation of [...writes.map((item) => ({ ...item, target_path: item.path, target_sha256: sha256(item.content) })), ...copies]) {
543
+ const target = path.join(root, ...operation.target_path.split("/"));
544
+ if (fs.existsSync(target)) {
545
+ const actual = sha256(fs.readFileSync(target));
546
+ const reason = actual === operation.target_sha256
547
+ ? "migration-target-already-exists" : "migration-target-conflict";
548
+ targetConflicts.push(conflict("target", operation.target_path, [{
549
+ member_id: "existing-project",
550
+ record_checksum: actual,
551
+ }], reason));
552
+ }
553
+ }
554
+ Object.defineProperty(report, "_operations", {
555
+ enumerable: false,
556
+ value: { writes, copies },
557
+ });
558
+ report.file_changes = {
559
+ additions: writes.map((item) => ({ path: item.path, kind: item.kind, sha256: sha256(item.content) })),
560
+ copies,
561
+ };
562
+ report.merge_report.conflicts.push(...targetConflicts);
563
+ report.merge_report.conflicts.sort((left, right) => left.conflict_id.localeCompare(right.conflict_id));
564
+ report.unresolved_conflicts.push(...targetConflicts);
565
+ }
566
+
567
+ export function planPrototypeMigration(project, options = {}) {
568
+ const root = path.resolve(project);
569
+ const iterationId = currentIterationId(root);
570
+ const sets = discoverLegacySets(root, iterationId);
571
+ const openSets = sets.filter((item) => item.scope === "open");
572
+ const preservedHistory = sets.filter((item) => item.scope !== "open").map((item) => ({
573
+ iteration_id: item.iteration_id,
574
+ scope: item.scope,
575
+ set_ref: toPosix(path.relative(root, item.file)),
576
+ set_checksum: sha256(fs.readFileSync(item.file)),
577
+ policy: "byte-for-byte-preserved",
578
+ }));
579
+ const targetRelative = iterationId ? `.workflow/experience/${iterationId}/prototype.yaml` : null;
580
+ const targetFile = targetRelative ? path.join(root, ...targetRelative.split("/")) : null;
581
+ const existingCurrent = targetFile && fs.existsSync(targetFile) ? readYaml(targetFile, "current Prototype") : null;
582
+ const loaded = loadOpenMembers(root, openSets);
583
+ const merged = mergeReport(loaded);
584
+ const sourceFiles = [...loaded.sourceFiles].sort((left, right) => left.localeCompare(right));
585
+ const legacySourceChecksum = sha256(stableJson(sourceFiles.map((file) => ({
586
+ path: toPosix(path.relative(root, file)),
587
+ sha256: sha256(fs.readFileSync(file)),
588
+ }))));
589
+ const report = {
590
+ schema_version: 1,
591
+ status: "not-required",
592
+ applied: false,
593
+ iteration_id: iterationId,
594
+ source_checksum: legacySourceChecksum,
595
+ member_count: loaded.declaredMemberCount,
596
+ valid_member_count: loaded.members.length,
597
+ invalid_member_count: loaded.declaredMemberCount - loaded.members.length,
598
+ legacy_sets: openSets.map((item) => ({
599
+ iteration_id: item.iteration_id,
600
+ ref: toPosix(path.relative(root, item.file)),
601
+ checksum: sha256(fs.readFileSync(item.file)),
602
+ })),
603
+ members: loaded.members.map((member) => ({
604
+ member_id: member.member_id,
605
+ manifest_ref: member.manifest_ref,
606
+ manifest_checksum: member.manifest_checksum,
607
+ source_ref: member.source_ref,
608
+ source_checksum: member.source_checksum,
609
+ terminal_ids: member.terminal_ids,
610
+ })),
611
+ target: {
612
+ prototype_id: TARGET_PROTOTYPE_ID,
613
+ descriptor_ref: targetRelative,
614
+ experience_ref: iterationId ? `.workflow/experience/${iterationId}` : null,
615
+ },
616
+ merge_report: merged,
617
+ preserved_history: preservedHistory,
618
+ preserved_sources: sourceFiles.map((file) => ({
619
+ path: toPosix(path.relative(root, file)),
620
+ sha256: sha256(fs.readFileSync(file)),
621
+ })),
622
+ approval: {
623
+ required_gate: loaded.declaredMemberCount ? "UX-UI" : null,
624
+ existing_approval_reused: false,
625
+ policy: loaded.declaredMemberCount ? "fresh-approval-required" : "not-applicable",
626
+ },
627
+ required_follow_up: {
628
+ command: "ai-delivery migrate",
629
+ write_planned: false,
630
+ },
631
+ };
632
+ applyDecisions(report, options.decisionsFile, options.sourceChecksum);
633
+ report.can_apply = report.unresolved_conflicts.length === 0;
634
+ if (!iterationId || !openSets.length || !loaded.members.length) {
635
+ report.status = report.unresolved_conflicts.length ? "blocked" : "not-required";
636
+ report.file_changes = { additions: [], copies: [] };
637
+ report.can_apply = report.unresolved_conflicts.length === 0;
638
+ return report;
639
+ }
640
+ if (existingCurrent) {
641
+ if (existingCurrent.artifact_type !== "prototype-current"
642
+ || existingCurrent.prototype_id !== TARGET_PROTOTYPE_ID) {
643
+ report.unresolved_conflicts.push(conflict("target", targetRelative, [{
644
+ member_id: "existing-project",
645
+ record_checksum: sha256(stableJson(existingCurrent)),
646
+ }], "incompatible-current-prototype"));
647
+ report.can_apply = false;
648
+ report.status = "blocked";
649
+ } else {
650
+ report.status = "already-current";
651
+ report.can_apply = true;
652
+ }
653
+ report.file_changes = { additions: [], copies: [] };
654
+ return report;
655
+ }
656
+ if (report.can_apply) buildOperations(root, report);
657
+ report.can_apply = report.unresolved_conflicts.length === 0;
658
+ report.status = report.can_apply ? "ready" : "blocked";
659
+ return report;
660
+ }
661
+
662
+ export function applyPrototypeMigration(project, report) {
663
+ const root = path.resolve(project);
664
+ if (report.status === "not-required" || report.status === "already-current") return report;
665
+ if (!report.can_apply || !report._operations) {
666
+ throw new Error("Prototype migration requires checksum-bound human decisions before apply.");
667
+ }
668
+ for (const source of report.preserved_sources) {
669
+ const file = path.join(root, ...source.path.split("/"));
670
+ if (!fs.existsSync(file) || sha256(fs.readFileSync(file)) !== source.sha256) {
671
+ throw new Error(`Legacy Prototype source changed during apply: ${source.path}.`);
672
+ }
673
+ }
674
+ const created = [];
675
+ try {
676
+ for (const write of report._operations.writes) {
677
+ const target = path.join(root, ...write.path.split("/"));
678
+ if (fs.existsSync(target)) throw new Error(`Prototype migration target already exists: ${write.path}.`);
679
+ atomicWrite(target, write.content);
680
+ created.push(target);
681
+ }
682
+ for (const copy of report._operations.copies) {
683
+ const source = path.join(root, ...copy.source_path.split("/"));
684
+ const target = path.join(root, ...copy.target_path.split("/"));
685
+ if (fs.existsSync(target) || sha256(fs.readFileSync(source)) !== copy.source_sha256) {
686
+ throw new Error(`Prototype migration copy changed during apply: ${copy.source_path}.`);
687
+ }
688
+ atomicWrite(target, fs.readFileSync(source));
689
+ created.push(target);
690
+ }
691
+ } catch (error) {
692
+ for (const file of created.reverse()) fs.rmSync(file, { force: true });
693
+ throw error;
694
+ }
695
+ report.applied = true;
696
+ return report;
697
+ }
698
+
699
+ export function rollbackPrototypeMigration(project, report) {
700
+ if (!report?.file_changes) return;
701
+ const root = path.resolve(project);
702
+ const files = [
703
+ ...(report.file_changes.copies || []).map((item) => ({ path: item.target_path, sha256: item.target_sha256 })),
704
+ ...(report.file_changes.additions || []).map((item) => ({ path: item.path, sha256: item.sha256 })),
705
+ ].reverse();
706
+ for (const item of files) {
707
+ const file = path.join(root, ...item.path.split("/"));
708
+ if (!fs.existsSync(file) || sha256(fs.readFileSync(file)) !== item.sha256) {
709
+ throw new Error(`Migrated Prototype bytes changed; rollback is blocked: ${item.path}.`);
710
+ }
711
+ }
712
+ for (const item of files) fs.rmSync(path.join(root, ...item.path.split("/")), { force: true });
713
+ }