ai-delivery-workflow 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/README.md +7 -8
  2. package/bin/ai-delivery.mjs +2 -24
  3. package/bin/release-check.mjs +8 -2
  4. package/docs/CLI-PARAMETER-REFERENCE.zh-CN.md +6 -67
  5. package/docs/DUAL-REPOSITORY-WORKSPACE.zh-CN.md +14 -1
  6. package/docs/FILE-REFERENCE.zh-CN.md +17 -36
  7. package/docs/MAINTENANCE-VERIFICATION.zh-CN.md +2 -2
  8. package/docs/NPM-RELEASE-MANAGEMENT.zh-CN.md +2 -1
  9. package/docs/PROJECT-MANUAL.zh-CN.md +50 -43
  10. package/docs/STATE-CLI-MAINTENANCE.zh-CN.md +8 -10
  11. package/docs/STATE-CLI-USER-GUIDE.zh-CN.md +7 -17
  12. package/docs/adr/0006-product-line-candidate-inventory.md +20 -0
  13. package/docs/agents/domain.md +31 -6
  14. package/docs/agents/issue-tracker.md +17 -18
  15. package/docs/agents/triage-labels.md +7 -7
  16. package/docs/agents/workflow-manager-acceptance-matrix.md +9 -15
  17. package/docs/agents/workflow-manager-current-state.md +14 -17
  18. package/lib/delivery-state.mjs +59 -910
  19. package/lib/fs-utils.mjs +0 -16
  20. package/lib/npm-auth.mjs +16 -0
  21. package/lib/project-bootstrap.mjs +21 -58
  22. package/lib/project-installer.mjs +24 -180
  23. package/lib/project-repair.mjs +217 -0
  24. package/lib/toml-hooks.mjs +2 -4
  25. package/lib/workflow-manager-governance.mjs +3 -47
  26. package/lib/workspace.mjs +2 -3
  27. package/package.json +2 -2
  28. package/skills/ai-delivery-assemble-release/SKILL.md +10 -8
  29. package/skills/ai-delivery-assemble-release/agents/openai.yaml +3 -3
  30. package/skills/ai-delivery-assemble-release/assets/release-candidate-manifest.yaml +16 -4
  31. package/skills/ai-delivery-assemble-release/assets/release-git-plan.yaml +96 -6
  32. package/skills/ai-delivery-assemble-release/assets/version-inclusion.csv +2 -2
  33. package/skills/ai-delivery-assemble-release/references/release-assembly-contract.md +16 -2
  34. package/skills/ai-delivery-assemble-release/scripts/plan-release.mjs +127 -3
  35. package/skills/ai-delivery-bootstrap/SKILL.md +1 -1
  36. package/skills/ai-delivery-bootstrap/agents/openai.yaml +3 -3
  37. package/skills/ai-delivery-bootstrap/references/bootstrap-contract.md +1 -1
  38. package/skills/ai-delivery-checkpoint-task/SKILL.md +0 -4
  39. package/skills/ai-delivery-checkpoint-task/agents/openai.yaml +3 -3
  40. package/skills/ai-delivery-checkpoint-task/references/checkpoint-contract.md +2 -2
  41. package/skills/ai-delivery-checkpoint-task/scripts/hook-event.mjs +2 -8
  42. package/skills/ai-delivery-checkpoint-task/scripts/task-state.mjs +26 -46
  43. package/skills/ai-delivery-close-version/agents/openai.yaml +3 -3
  44. package/skills/ai-delivery-define-product/agents/openai.yaml +4 -4
  45. package/skills/ai-delivery-deploy-production/agents/openai.yaml +3 -3
  46. package/skills/ai-delivery-design-experience/SKILL.md +3 -3
  47. package/skills/ai-delivery-design-experience/agents/openai.yaml +4 -4
  48. package/skills/ai-delivery-design-experience/references/experience-contract.md +1 -11
  49. package/skills/ai-delivery-design-experience/references/prototype-management-contract.md +1 -1
  50. package/skills/ai-delivery-develop-iteration/agents/openai.yaml +3 -3
  51. package/skills/ai-delivery-evolve-workflow/agents/openai.yaml +3 -3
  52. package/skills/ai-delivery-execute-test/agents/openai.yaml +4 -4
  53. package/skills/ai-delivery-execute-work-package/agents/openai.yaml +4 -4
  54. package/skills/ai-delivery-manage-git/SKILL.md +9 -7
  55. package/skills/ai-delivery-manage-git/agents/openai.yaml +3 -3
  56. package/skills/ai-delivery-manage-git/references/git-policy.md +7 -3
  57. package/skills/ai-delivery-manage-git/scripts/release-git.mjs +995 -0
  58. package/skills/ai-delivery-manage-standards/agents/openai.yaml +4 -4
  59. package/skills/ai-delivery-orchestrate/SKILL.md +5 -7
  60. package/skills/ai-delivery-orchestrate/agents/openai.yaml +3 -3
  61. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/hooks/hook-event.mjs +2 -8
  62. package/skills/ai-delivery-orchestrate/assets/project-template/AGENTS.md +9 -8
  63. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/CONTRIBUTING.md +25 -25
  64. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/airbnb/DESIGN.md +545 -545
  65. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/airbnb/README.md +5 -5
  66. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/airtable/DESIGN.md +554 -554
  67. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/airtable/README.md +5 -5
  68. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/apple/DESIGN.md +562 -562
  69. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/apple/README.md +5 -5
  70. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/binance/DESIGN.md +634 -634
  71. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/binance/README.md +5 -5
  72. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bmw/DESIGN.md +544 -544
  73. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bmw/README.md +5 -5
  74. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bmw-m/DESIGN.md +503 -503
  75. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bmw-m/README.md +5 -5
  76. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bugatti/DESIGN.md +454 -454
  77. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bugatti/README.md +5 -5
  78. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cal/DESIGN.md +542 -542
  79. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cal/README.md +5 -5
  80. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/claude/DESIGN.md +589 -589
  81. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/claude/README.md +5 -5
  82. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/clay/DESIGN.md +541 -541
  83. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/clay/README.md +5 -5
  84. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/clickhouse/DESIGN.md +544 -544
  85. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/clickhouse/README.md +5 -5
  86. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cohere/DESIGN.md +451 -451
  87. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cohere/README.md +5 -5
  88. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/coinbase/DESIGN.md +570 -570
  89. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/coinbase/README.md +5 -5
  90. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/composio/DESIGN.md +506 -506
  91. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/composio/README.md +5 -5
  92. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cursor/DESIGN.md +537 -537
  93. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cursor/README.md +5 -5
  94. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/dell-1996/DESIGN.md +632 -632
  95. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/dell-1996/README.md +5 -5
  96. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/elevenlabs/DESIGN.md +504 -504
  97. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/elevenlabs/README.md +5 -5
  98. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/expo/DESIGN.md +526 -526
  99. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/expo/README.md +5 -5
  100. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ferrari/DESIGN.md +531 -531
  101. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ferrari/README.md +5 -5
  102. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/figma/DESIGN.md +578 -578
  103. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/figma/README.md +5 -5
  104. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/framer/DESIGN.md +544 -544
  105. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/framer/README.md +5 -5
  106. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/hashicorp/DESIGN.md +575 -575
  107. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/hashicorp/README.md +5 -5
  108. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/hp/DESIGN.md +670 -670
  109. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/hp/README.md +5 -5
  110. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ibm/DESIGN.md +550 -550
  111. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ibm/README.md +5 -5
  112. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/intercom/DESIGN.md +546 -546
  113. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/intercom/README.md +5 -5
  114. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/kraken/DESIGN.md +125 -125
  115. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/kraken/README.md +5 -5
  116. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/lamborghini/DESIGN.md +288 -288
  117. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/lamborghini/README.md +5 -5
  118. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/linear.app/DESIGN.md +548 -548
  119. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/linear.app/README.md +5 -5
  120. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/lovable/DESIGN.md +298 -298
  121. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/lovable/README.md +5 -5
  122. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mastercard/DESIGN.md +365 -365
  123. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mastercard/README.md +5 -5
  124. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/meta/DESIGN.md +683 -683
  125. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/meta/README.md +5 -5
  126. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/minimax/DESIGN.md +746 -746
  127. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/minimax/README.md +5 -5
  128. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mintlify/DESIGN.md +852 -852
  129. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mintlify/README.md +5 -5
  130. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/miro/DESIGN.md +825 -825
  131. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/miro/README.md +5 -5
  132. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mistral.ai/DESIGN.md +773 -773
  133. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mistral.ai/README.md +5 -5
  134. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mongodb/DESIGN.md +767 -767
  135. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mongodb/README.md +5 -5
  136. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nike/DESIGN.md +575 -575
  137. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nike/README.md +5 -5
  138. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nintendo-2001/DESIGN.md +649 -649
  139. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nintendo-2001/README.md +5 -5
  140. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/notion/DESIGN.md +821 -821
  141. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/notion/README.md +5 -5
  142. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nvidia/DESIGN.md +640 -640
  143. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nvidia/README.md +5 -5
  144. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ollama/DESIGN.md +539 -539
  145. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ollama/README.md +5 -5
  146. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/opencode.ai/DESIGN.md +521 -521
  147. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/opencode.ai/README.md +5 -5
  148. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/pinterest/DESIGN.md +597 -597
  149. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/pinterest/README.md +5 -5
  150. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/playstation/DESIGN.md +661 -661
  151. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/playstation/README.md +5 -5
  152. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/posthog/DESIGN.md +690 -690
  153. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/posthog/README.md +5 -5
  154. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/raycast/DESIGN.md +669 -669
  155. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/raycast/README.md +5 -5
  156. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/renault/DESIGN.md +589 -589
  157. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/renault/README.md +5 -5
  158. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/replicate/DESIGN.md +616 -616
  159. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/replicate/README.md +5 -5
  160. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/resend/DESIGN.md +585 -585
  161. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/resend/README.md +5 -5
  162. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/revolut/DESIGN.md +636 -636
  163. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/revolut/README.md +5 -5
  164. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/runwayml/DESIGN.md +244 -244
  165. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/runwayml/README.md +5 -5
  166. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/sanity/DESIGN.md +357 -357
  167. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/sanity/README.md +5 -5
  168. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/sentry/DESIGN.md +551 -551
  169. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/sentry/README.md +5 -5
  170. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/shopify/DESIGN.md +516 -516
  171. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/shopify/README.md +5 -5
  172. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/slack/DESIGN.md +482 -482
  173. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/spacex/DESIGN.md +363 -363
  174. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/spacex/README.md +5 -5
  175. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/spotify/DESIGN.md +246 -246
  176. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/spotify/README.md +5 -5
  177. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/starbucks/DESIGN.md +580 -580
  178. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/starbucks/README.md +5 -5
  179. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/stripe/DESIGN.md +487 -487
  180. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/stripe/README.md +5 -5
  181. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/supabase/DESIGN.md +462 -462
  182. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/supabase/README.md +5 -5
  183. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/superhuman/DESIGN.md +448 -448
  184. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/superhuman/README.md +5 -5
  185. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/tesla/DESIGN.md +286 -286
  186. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/tesla/README.md +5 -5
  187. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/theverge/DESIGN.md +339 -339
  188. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/theverge/README.md +5 -5
  189. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/together.ai/DESIGN.md +633 -633
  190. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/together.ai/README.md +5 -5
  191. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/uber/DESIGN.md +636 -636
  192. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/uber/README.md +5 -5
  193. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/vercel/DESIGN.md +736 -736
  194. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/vercel/README.md +5 -5
  195. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/vodafone/DESIGN.md +538 -538
  196. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/vodafone/README.md +5 -5
  197. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/voltagent/DESIGN.md +521 -521
  198. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/voltagent/README.md +5 -5
  199. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/warp/DESIGN.md +526 -526
  200. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/warp/README.md +5 -5
  201. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/webflow/DESIGN.md +588 -588
  202. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/webflow/README.md +5 -5
  203. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/wired/DESIGN.md +497 -497
  204. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/wired/README.md +5 -5
  205. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/wise/DESIGN.md +544 -544
  206. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/wise/README.md +5 -5
  207. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/x.ai/DESIGN.md +465 -465
  208. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/x.ai/README.md +5 -5
  209. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/zapier/DESIGN.md +537 -537
  210. package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/zapier/README.md +5 -5
  211. package/skills/ai-delivery-orchestrate/references/formal-state-contract.md +11 -20
  212. package/skills/ai-delivery-orchestrate/references/workflow-model.md +2 -4
  213. package/skills/ai-delivery-orchestrate-release/SKILL.md +10 -10
  214. package/skills/ai-delivery-orchestrate-release/agents/openai.yaml +4 -4
  215. package/skills/ai-delivery-orchestrate-release/assets/release-request.yaml +4 -1
  216. package/skills/ai-delivery-orchestrate-release/assets/version-selection.yaml +13 -1
  217. package/skills/ai-delivery-orchestrate-release/references/release-workflow-contract.md +14 -0
  218. package/skills/ai-delivery-plan-iteration/agents/openai.yaml +4 -4
  219. package/skills/ai-delivery-prepare-platform/agents/openai.yaml +4 -4
  220. package/skills/ai-delivery-prepare-release/SKILL.md +6 -5
  221. package/skills/ai-delivery-prepare-release/agents/openai.yaml +4 -4
  222. package/skills/ai-delivery-prepare-release/assets/release-template/release-manifest.yaml +21 -2
  223. package/skills/ai-delivery-prepare-release/references/release-contract.md +5 -1
  224. package/skills/ai-delivery-review-change/agents/openai.yaml +4 -4
  225. package/skills/ai-delivery-triage-failure/agents/openai.yaml +4 -4
  226. package/skills/ai-delivery-validate-artifacts/agents/openai.yaml +4 -4
  227. package/skills/ai-delivery-verify-candidate/agents/openai.yaml +3 -3
  228. package/skills/ai-delivery-verify-production/SKILL.md +7 -4
  229. package/skills/ai-delivery-verify-production/agents/openai.yaml +3 -3
  230. package/skills/ai-delivery-verify-production/assets/production-verification-template/production-verification.json +9 -0
  231. package/skills/ai-delivery-verify-production/assets/production-verification-template/production-verification.md +20 -0
  232. package/skills/ai-delivery-verify-production/references/production-verification-contract.md +19 -3
  233. package/docs/PROTOTYPE-MIGRATION.zh-CN.md +0 -164
  234. package/docs/VIEWER-MAINTENANCE.zh-CN.md +0 -150
  235. package/docs/VIEWER-USER-GUIDE.zh-CN.md +0 -113
  236. package/lib/project-migration.mjs +0 -1193
  237. package/lib/prototype-migration.mjs +0 -713
  238. package/skills/ai-delivery-design-experience/assets/experience-template/LEGACY-COMPATIBILITY.md +0 -16
  239. package/skills/ai-delivery-design-experience/assets/experience-template/canvas-catalog.csv +0 -1
  240. package/skills/ai-delivery-design-experience/assets/experience-template/canvas-pages.csv +0 -1
  241. package/skills/ai-delivery-design-experience/assets/experience-template/page-catalog.csv +0 -1
  242. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-file-terminals.csv +0 -1
  243. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-files.csv +0 -1
  244. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-manifest.yaml +0 -76
  245. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-set.yaml +0 -24
@@ -1,713 +0,0 @@
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
- }