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,778 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import crypto from "node:crypto";
4
+ import { spawnSync } from "node:child_process";
5
+ import { createRequire } from "node:module";
6
+ import { fileURLToPath, pathToFileURL } from "node:url";
7
+ import {
8
+ commitWorkflowManagerAction,
9
+ prepareWorkflowManagerFormalTransaction,
10
+ preflightWorkflowManagerAction,
11
+ workflowManagerChecksum,
12
+ } from "./workflow-manager-transaction.mjs";
13
+
14
+ const runtimeRoot = path.dirname(fileURLToPath(import.meta.url));
15
+ const installedYaml = path.join(runtimeRoot, "..", "state", "vendor", "yaml", "dist", "index.js");
16
+ const require = createRequire(import.meta.url);
17
+ const YAML = require(fs.existsSync(installedYaml) ? installedYaml : "yaml");
18
+ const installedStateRuntime = path.join(runtimeRoot, "..", "state", "delivery-state.mjs");
19
+ const packageStateRuntime = path.join(runtimeRoot, "delivery-state.mjs");
20
+ const stateRuntime = fs.existsSync(installedStateRuntime) ? installedStateRuntime : packageStateRuntime;
21
+ const { executeDeliveryStateCommand } = await import(pathToFileURL(stateRuntime).href);
22
+
23
+ export const WORKFLOW_MANAGER_FACTS_SCHEMA_VERSION = "workflow-manager-facts.v1";
24
+
25
+ const COLLECTIONS = Object.freeze({
26
+ requirements: [".workflow/product/requirements.yaml", ".workflow/product/requirements.yml"],
27
+ test_cases: [".workflow/quality/test-cases.yaml", ".workflow/quality/test-cases.yml"],
28
+ test_runs: [".workflow/quality/test-runs.yaml", ".workflow/quality/test-runs.yml"],
29
+ relations: [".workflow/control/relations.yaml", ".workflow/control/relations.yml"],
30
+ });
31
+
32
+ const COLLECTION_DEFINITIONS = Object.freeze({
33
+ requirements: {
34
+ relative: ".workflow/product/requirements.yaml",
35
+ arrayKey: "requirements",
36
+ identity: "requirement_id",
37
+ entityType: "requirement",
38
+ },
39
+ test_cases: {
40
+ relative: ".workflow/quality/test-cases.yaml",
41
+ arrayKey: "test_cases",
42
+ identity: "test_case_id",
43
+ entityType: "test-case",
44
+ },
45
+ test_runs: {
46
+ relative: ".workflow/quality/test-runs.yaml",
47
+ arrayKey: "test_runs",
48
+ identity: "test_run_id",
49
+ entityType: "test-run",
50
+ },
51
+ });
52
+
53
+ const REQUIREMENT_STATUSES = new Set(["draft", "accepted", "implemented", "verified", "retired", "superseded"]);
54
+ const TEST_CASE_KINDS = new Set(["ui", "api", "integration", "unit", "security", "performance"]);
55
+ const TEST_CASE_STATUSES = new Set(["draft", "ready", "retired"]);
56
+ const TEST_RUN_OUTCOMES = new Set(["passed", "failed", "blocked", "skipped"]);
57
+
58
+ function sha256(bytes) {
59
+ return crypto.createHash("sha256").update(bytes).digest("hex");
60
+ }
61
+
62
+ function readYamlFile(root, candidates) {
63
+ for (const relative of candidates) {
64
+ const file = path.resolve(root, relative);
65
+ if (!isInside(file, root)) throw new Error(`Fact path escapes project root: ${relative}`);
66
+ if (fs.existsSync(file) && fs.statSync(file).isFile()) {
67
+ const bytes = fs.readFileSync(file);
68
+ return { file, relative, checksum: sha256(bytes), value: YAML.parse(bytes.toString("utf8")) || {} };
69
+ }
70
+ }
71
+ return null;
72
+ }
73
+
74
+ function isInside(candidate, root) {
75
+ const relative = path.relative(root, candidate);
76
+ return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
77
+ }
78
+
79
+ function arrayValue(value, keys) {
80
+ for (const key of keys) if (Array.isArray(value?.[key])) return value[key];
81
+ return [];
82
+ }
83
+
84
+ function collection(root, key, keys, identity) {
85
+ const source = readYamlFile(root, COLLECTIONS[key]);
86
+ const items = arrayValue(source?.value, keys).filter((item) => item && typeof item === "object").map((item) => ({
87
+ ...item,
88
+ entity_type: key === "requirements" ? "requirement" : key === "test_cases" ? "test-case" : key === "test_runs" ? "test-run" : item.entity_type || "relation",
89
+ entity_id: item[identity] || item.id || item.entity_id || null,
90
+ mutability: item.mutability || (key === "test_runs" ? "immutable" : key === "test_cases" ? "versioned" : key === "requirements" ? "governed" : "governed-relation"),
91
+ }));
92
+ return {
93
+ registration_status: source ? "registered" : "not-registered",
94
+ mutability: key === "test_runs" ? "append-only" : key === "relations" ? "governed" : "governed",
95
+ source: source ? { path: source.relative, revision: source.value.revision ?? 0, checksum: source.checksum } : null,
96
+ items,
97
+ };
98
+ }
99
+
100
+ function artifactCollection(root) {
101
+ const relative = ".workflow/delivery/artifact-registry.yaml";
102
+ const file = path.resolve(root, relative);
103
+ if (!isInside(file, root) || !fs.existsSync(file)) return { registration_status: "not-registered", source: null, items: [] };
104
+ const bytes = fs.readFileSync(file);
105
+ const value = YAML.parse(bytes.toString("utf8")) || {};
106
+ const items = arrayValue(value, ["artifacts"]).map((item) => ({
107
+ ...item,
108
+ entity_type: "artifact",
109
+ entity_id: item.artifact_id || item.id || item.entity_id || null,
110
+ mutability: "formal-state-governed",
111
+ }));
112
+ return { registration_status: "registered", mutability: "formal-state-governed", source: { path: relative, revision: value.revision ?? 0, checksum: sha256(bytes) }, items };
113
+ }
114
+
115
+ function eventCollection(root) {
116
+ const relatives = [
117
+ ".workflow/delivery/state-events.jsonl",
118
+ ".workflow/control/events/workflow-manager-events.jsonl",
119
+ ];
120
+ const sources = [];
121
+ const items = [];
122
+ const identities = new Set();
123
+ for (const relative of relatives) {
124
+ const file = path.resolve(root, relative);
125
+ if (!isInside(file, root) || !fs.existsSync(file)) continue;
126
+ const bytes = fs.readFileSync(file);
127
+ const sourceItems = bytes.toString("utf8").split(/\r?\n/).filter(Boolean).map((line, index) => {
128
+ let item;
129
+ try {
130
+ item = JSON.parse(line);
131
+ } catch {
132
+ return {
133
+ entity_type: "event",
134
+ entity_id: `${relative}:${index + 1}`,
135
+ source_path: relative,
136
+ source_line: index + 1,
137
+ mutability: "immutable",
138
+ parse_error: true,
139
+ };
140
+ }
141
+ const identity = item.event_id || item.id || `${relative}:${index + 1}`;
142
+ if (identities.has(identity)) throw new Error(`Duplicate event identity across Workflow Manager streams: ${identity}`);
143
+ identities.add(identity);
144
+ return {
145
+ ...item,
146
+ entity_type: "event",
147
+ entity_id: identity,
148
+ source_path: relative,
149
+ source_line: index + 1,
150
+ mutability: "immutable",
151
+ };
152
+ });
153
+ items.push(...sourceItems);
154
+ sources.push({ path: relative, revision: sourceItems.length, checksum: sha256(bytes) });
155
+ }
156
+ items.sort((left, right) => String(right.occurred_at || "").localeCompare(String(left.occurred_at || ""))
157
+ || String(left.entity_id).localeCompare(String(right.entity_id)));
158
+ return {
159
+ registration_status: sources.length ? "registered" : "not-registered",
160
+ mutability: "immutable",
161
+ source: sources.length ? {
162
+ path: sources.map((source) => source.path).join(" + "),
163
+ paths: sources,
164
+ revision: sources.reduce((total, source) => total + source.revision, 0),
165
+ checksum: workflowManagerChecksum(sources.map((source) => source.checksum)),
166
+ } : null,
167
+ items,
168
+ };
169
+ }
170
+
171
+ function decisionCollection(root) {
172
+ const file = path.resolve(root, ".workflow/delivery/workflow-state.yaml");
173
+ if (!isInside(file, root) || !fs.existsSync(file)) return { pending: [], history: [], source: null };
174
+ const bytes = fs.readFileSync(file);
175
+ const value = YAML.parse(bytes.toString("utf8")) || {};
176
+ const scope = value.development_state || value;
177
+ const pending = Array.isArray(scope.pending_gates) ? scope.pending_gates : [];
178
+ const history = Array.isArray(scope.gate_decisions) ? scope.gate_decisions.map((item) => ({
179
+ ...item,
180
+ comment: item.comment || (/^Workflow Manager (approved|rejected) decision for /.test(item.rationale || "")
181
+ ? null
182
+ : item.rationale || null),
183
+ entity_type: "decision",
184
+ entity_id: item.decision_id || item.gate_id || null,
185
+ })) : [];
186
+ return { pending, history, source: { path: ".workflow/delivery/workflow-state.yaml", revision: scope.revision ?? value.revision ?? 0, checksum: sha256(bytes) } };
187
+ }
188
+
189
+ function normalizeRelation(item, index) {
190
+ return {
191
+ ...item,
192
+ relation_id: item.relation_id || item.id || `REL-${String(index + 1).padStart(4, "0")}`,
193
+ from: item.from || item.source || item.from_id || null,
194
+ to: item.to || item.target || item.to_id || null,
195
+ from_entity_type: item.from_entity_type || item.source_entity_type || null,
196
+ to_entity_type: item.to_entity_type || item.target_entity_type || null,
197
+ relation_type: item.relation_type || item.type || "related-to",
198
+ relation_state: item.relation_state || item.status || "suggested",
199
+ };
200
+ }
201
+
202
+ function attachRelations(collections, relations) {
203
+ const byTypedId = new Map();
204
+ const byId = new Map();
205
+ for (const bucket of Object.values(collections)) {
206
+ for (const item of bucket.items || []) {
207
+ if (!item.entity_id) continue;
208
+ byTypedId.set(`${item.entity_type}:${item.entity_id}`, item);
209
+ byId.set(item.entity_id, [...(byId.get(item.entity_id) || []), item]);
210
+ }
211
+ }
212
+ const resolve = (identity, declaredType) => declaredType
213
+ ? byTypedId.get(`${declaredType}:${identity}`)
214
+ : byId.get(identity)?.length === 1 ? byId.get(identity)[0] : null;
215
+ for (const relation of relations.items) {
216
+ const related = (left, direction) => {
217
+ const targetId = direction === "out" ? left.to : left.from;
218
+ const declaredType = direction === "out" ? left.to_entity_type : left.from_entity_type;
219
+ const target = resolve(targetId, declaredType);
220
+ return {
221
+ entity_id: targetId,
222
+ entity_type: target?.entity_type || declaredType || "unknown",
223
+ relation_id: left.relation_id,
224
+ relation_type: left.relation_type,
225
+ relation_state: left.relation_state,
226
+ };
227
+ };
228
+ const from = resolve(relation.from, relation.from_entity_type);
229
+ const to = resolve(relation.to, relation.to_entity_type);
230
+ if (from) (from.related_items ||= []).push(related(relation, "out"));
231
+ if (to) (to.related_items ||= []).push(related(relation, "in"));
232
+ }
233
+ for (const bucket of Object.values(collections)) {
234
+ for (const item of bucket.items || []) {
235
+ item.related_items = (item.related_items || []).sort((a, b) => String(a.entity_id).localeCompare(String(b.entity_id)));
236
+ item.related_requirements = item.related_items.filter((related) => related.entity_type === "requirement");
237
+ }
238
+ }
239
+ }
240
+
241
+ function tasksCollection(root, relations) {
242
+ const directory = path.resolve(root, ".workflow/control/tasks");
243
+ if (!isInside(directory, root) || !fs.existsSync(directory)) return { registration_status: "not-registered", mutability: "task-writer-governed", source: null, items: [] };
244
+ const files = fs.readdirSync(directory).filter((name) => /\.(yaml|yml|json)$/i.test(name)).sort();
245
+ const items = [];
246
+ for (const name of files) {
247
+ const file = path.join(directory, name);
248
+ const bytes = fs.readFileSync(file);
249
+ const item = name.endsWith(".json") ? JSON.parse(bytes.toString("utf8")) : YAML.parse(bytes.toString("utf8"));
250
+ if (!item || typeof item !== "object") continue;
251
+ items.push({ ...item, entity_type: "task", entity_id: item.task_id || item.id || null, mutability: "task-writer-governed" });
252
+ }
253
+ return { registration_status: "registered", mutability: "task-writer-governed", source: { path: ".workflow/control/tasks", revision: files.length, checksum: sha256(files.map((name) => fs.readFileSync(path.join(directory, name))).reduce((all, bytes) => Buffer.concat([all, bytes]), Buffer.alloc(0))) }, items };
254
+ }
255
+
256
+ export function inspectWorkflowManagerFacts(projectRoot) {
257
+ const root = path.resolve(projectRoot);
258
+ const collections = {
259
+ requirements: collection(root, "requirements", ["requirements", "items"], "requirement_id"),
260
+ tasks: tasksCollection(root),
261
+ test_cases: collection(root, "test_cases", ["test_cases", "items"], "test_case_id"),
262
+ test_runs: collection(root, "test_runs", ["test_runs", "items"], "test_run_id"),
263
+ artifacts: artifactCollection(root),
264
+ events: eventCollection(root),
265
+ };
266
+ const relationBucket = collection(root, "relations", ["relations", "items"], "relation_id");
267
+ relationBucket.items = relationBucket.items.map(normalizeRelation);
268
+ attachRelations(collections, relationBucket);
269
+ return {
270
+ schema_version: WORKFLOW_MANAGER_FACTS_SCHEMA_VERSION,
271
+ mutability: "mixed-governed",
272
+ requirements: collections.requirements,
273
+ tasks: collections.tasks,
274
+ test_cases: collections.test_cases,
275
+ test_runs: collections.test_runs,
276
+ artifacts: collections.artifacts,
277
+ events: collections.events,
278
+ decisions: decisionCollection(root),
279
+ relations: relationBucket,
280
+ };
281
+ }
282
+
283
+ function requiredText(value, label) {
284
+ const normalized = typeof value === "string" ? value.trim() : "";
285
+ if (!normalized) throw new Error(`${label} is required`);
286
+ return normalized;
287
+ }
288
+
289
+ function requiredActor(value) {
290
+ const actor = requiredText(value, "actor");
291
+ if (!/^(human|agent):[A-Za-z0-9._@/-]+$/.test(actor)) {
292
+ throw new Error("actor must identify a human or agent");
293
+ }
294
+ return actor;
295
+ }
296
+
297
+ function allowedValue(value, allowed, label) {
298
+ const normalized = requiredText(value, label);
299
+ if (!allowed.has(normalized)) throw new Error(`${label} is not supported: ${normalized}`);
300
+ return normalized;
301
+ }
302
+
303
+ function safeIdentity(value, label) {
304
+ const normalized = requiredText(value, label);
305
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(normalized)) {
306
+ throw new Error(`${label} is invalid`);
307
+ }
308
+ return normalized;
309
+ }
310
+
311
+ function stringList(value, label) {
312
+ if (!Array.isArray(value) || value.length === 0) throw new Error(`${label} must be a non-empty array`);
313
+ const normalized = [...new Set(value.map((item) => requiredText(item, label)))];
314
+ return normalized;
315
+ }
316
+
317
+ function readWritableCollection(root, definition) {
318
+ const file = path.resolve(root, definition.relative);
319
+ if (!isInside(file, root)) throw new Error(`Fact path escapes project root: ${definition.relative}`);
320
+ if (!fs.existsSync(file)) {
321
+ return { file, revision: 0, checksum: null, value: { schema_version: 1, revision: 0, [definition.arrayKey]: [] } };
322
+ }
323
+ const bytes = fs.readFileSync(file);
324
+ const value = YAML.parse(bytes.toString("utf8")) || {};
325
+ if (value.schema_version !== 1 || !Number.isInteger(value.revision) || value.revision < 0
326
+ || !Array.isArray(value[definition.arrayKey] ?? value.items)) {
327
+ throw new Error(`${definition.arrayKey} collection must declare schema_version 1, a non-negative revision, and an item array`);
328
+ }
329
+ return {
330
+ file,
331
+ revision: Number(value.revision || 0),
332
+ checksum: sha256(bytes),
333
+ value: { ...value, [definition.arrayKey]: arrayValue(value, [definition.arrayKey, "items"]) },
334
+ };
335
+ }
336
+
337
+ function assertCollectionVersion(collection, input) {
338
+ if (!Number.isInteger(input.expected_revision) || input.expected_revision < 0) {
339
+ throw new Error("expected_revision must be a non-negative integer");
340
+ }
341
+ if (input.expected_revision !== collection.revision) {
342
+ throw new Error(`Collection revision conflict: expected ${input.expected_revision}, found ${collection.revision}`);
343
+ }
344
+ const expectedChecksum = input.expected_checksum ?? null;
345
+ if (expectedChecksum !== collection.checksum) {
346
+ throw new Error("Collection checksum conflict");
347
+ }
348
+ }
349
+
350
+ export function applyWorkflowManagerRequirement(projectRoot, input = {}) {
351
+ const root = path.resolve(projectRoot);
352
+ const definition = COLLECTION_DEFINITIONS.requirements;
353
+ const requirementId = safeIdentity(input.requirement_id, "requirement_id");
354
+ const operation = input.operation;
355
+ if (!new Set(["create", "update"]).has(operation)) throw new Error("operation must be create or update");
356
+ requiredActor(input.actor);
357
+ requiredText(input.idempotency_key, "idempotency_key");
358
+ const replay = preflightWorkflowManagerAction(root, {
359
+ action: "requirement-apply",
360
+ subject: requirementId,
361
+ input,
362
+ });
363
+ if (replay) return { outcome: "idempotent-replay", receipt: replay, result: replay.result };
364
+
365
+ const collection = readWritableCollection(root, definition);
366
+ assertCollectionVersion(collection, input);
367
+ const existingIndex = collection.value[definition.arrayKey]
368
+ .findIndex((item) => item?.[definition.identity] === requirementId);
369
+ if (operation === "create" && existingIndex >= 0) throw new Error(`Requirement already exists: ${requirementId}`);
370
+ if (operation === "update" && existingIndex < 0) throw new Error(`Requirement not found: ${requirementId}`);
371
+
372
+ const current = existingIndex >= 0 ? collection.value[definition.arrayKey][existingIndex] : null;
373
+ if (operation === "update") {
374
+ if (!Number.isInteger(input.expected_entity_revision) || input.expected_entity_revision !== Number(current.revision || 0)) {
375
+ throw new Error(`Requirement entity revision conflict for ${requirementId}`);
376
+ }
377
+ }
378
+ const requirement = {
379
+ requirement_id: requirementId,
380
+ iteration_id: operation === "create"
381
+ ? safeIdentity(input.iteration_id, "iteration_id")
382
+ : current.iteration_id,
383
+ title: requiredText(input.title, "title"),
384
+ summary: requiredText(input.summary, "summary"),
385
+ status: allowedValue(input.status, REQUIREMENT_STATUSES, "status"),
386
+ acceptance: stringList(input.acceptance, "acceptance"),
387
+ revision: Number(current?.revision || 0) + 1,
388
+ };
389
+ const items = [...collection.value[definition.arrayKey]];
390
+ if (existingIndex < 0) items.push(requirement);
391
+ else items[existingIndex] = requirement;
392
+ items.sort((left, right) => String(left.requirement_id).localeCompare(String(right.requirement_id)));
393
+ const next = {
394
+ ...collection.value,
395
+ schema_version: 1,
396
+ revision: collection.revision + 1,
397
+ [definition.arrayKey]: items,
398
+ };
399
+ const content = YAML.stringify(next, { lineWidth: 0 });
400
+ const outputChecksum = sha256(content);
401
+ const result = { requirement, collection_revision: next.revision, collection_checksum: outputChecksum };
402
+ return commitWorkflowManagerAction(root, {
403
+ action: "requirement-apply",
404
+ subject: requirementId,
405
+ input,
406
+ result,
407
+ detail: {
408
+ input_revision: collection.revision,
409
+ input_checksum: collection.checksum,
410
+ output_revision: next.revision,
411
+ output_checksum: outputChecksum,
412
+ affected_identities: [requirementId],
413
+ },
414
+ writes: [{ file: collection.file, content }],
415
+ receiptPrefix: "WM-REQ",
416
+ });
417
+ }
418
+
419
+ export function applyWorkflowManagerTestCase(projectRoot, input = {}) {
420
+ const root = path.resolve(projectRoot);
421
+ const definition = COLLECTION_DEFINITIONS.test_cases;
422
+ const testCaseId = safeIdentity(input.test_case_id, "test_case_id");
423
+ const operation = input.operation;
424
+ if (!new Set(["create", "update"]).has(operation)) throw new Error("operation must be create or update");
425
+ requiredActor(input.actor);
426
+ requiredText(input.idempotency_key, "idempotency_key");
427
+ const replay = preflightWorkflowManagerAction(root, {
428
+ action: "test-case-apply",
429
+ subject: testCaseId,
430
+ input,
431
+ });
432
+ if (replay) return { outcome: "idempotent-replay", receipt: replay, result: replay.result };
433
+
434
+ const collection = readWritableCollection(root, definition);
435
+ assertCollectionVersion(collection, input);
436
+ const existingIndex = collection.value[definition.arrayKey]
437
+ .findIndex((item) => item?.[definition.identity] === testCaseId);
438
+ if (operation === "create" && existingIndex >= 0) throw new Error(`Test case already exists: ${testCaseId}`);
439
+ if (operation === "update" && existingIndex < 0) throw new Error(`Test case not found: ${testCaseId}`);
440
+ const current = existingIndex >= 0 ? collection.value[definition.arrayKey][existingIndex] : null;
441
+ if (operation === "update") {
442
+ const currentRevision = Number(current.version || current.revision || 0);
443
+ if (!Number.isInteger(input.expected_entity_revision) || input.expected_entity_revision !== currentRevision) {
444
+ throw new Error(`Test case entity revision conflict for ${testCaseId}`);
445
+ }
446
+ }
447
+ const version = Number(current?.version || current?.revision || 0) + 1;
448
+ const timestamp = new Date().toISOString();
449
+ const versionDefinition = {
450
+ version,
451
+ title: requiredText(input.title, "title"),
452
+ kind: allowedValue(input.kind, TEST_CASE_KINDS, "kind"),
453
+ status: allowedValue(input.status, TEST_CASE_STATUSES, "status"),
454
+ steps: stringList(input.steps, "steps"),
455
+ expected_result: requiredText(input.expected_result, "expected_result"),
456
+ recorded_at: timestamp,
457
+ };
458
+ versionDefinition.checksum = workflowManagerChecksum(versionDefinition);
459
+ const previousVersions = Array.isArray(current?.versions)
460
+ ? current.versions
461
+ : current
462
+ ? [{
463
+ version: Number(current.version || current.revision || 1),
464
+ title: current.title,
465
+ kind: current.kind,
466
+ status: current.status,
467
+ steps: current.steps,
468
+ expected_result: current.expected_result,
469
+ recorded_at: current.updated_at || current.created_at || null,
470
+ checksum: current.definition_checksum || null,
471
+ }]
472
+ : [];
473
+ const testCase = {
474
+ test_case_id: testCaseId,
475
+ iteration_id: operation === "create"
476
+ ? safeIdentity(input.iteration_id, "iteration_id")
477
+ : safeIdentity(current.iteration_id, "iteration_id"),
478
+ title: versionDefinition.title,
479
+ kind: versionDefinition.kind,
480
+ status: versionDefinition.status,
481
+ steps: versionDefinition.steps,
482
+ expected_result: versionDefinition.expected_result,
483
+ version,
484
+ revision: version,
485
+ definition_checksum: versionDefinition.checksum,
486
+ created_at: current?.created_at || timestamp,
487
+ updated_at: timestamp,
488
+ versions: [...previousVersions, versionDefinition],
489
+ };
490
+ const items = [...collection.value[definition.arrayKey]];
491
+ if (existingIndex < 0) items.push(testCase);
492
+ else items[existingIndex] = testCase;
493
+ items.sort((left, right) => String(left.test_case_id).localeCompare(String(right.test_case_id)));
494
+ const next = {
495
+ ...collection.value,
496
+ schema_version: 1,
497
+ revision: collection.revision + 1,
498
+ [definition.arrayKey]: items,
499
+ };
500
+ const content = YAML.stringify(next, { lineWidth: 0 });
501
+ const outputChecksum = sha256(content);
502
+ const result = { test_case: testCase, collection_revision: next.revision, collection_checksum: outputChecksum };
503
+ return commitWorkflowManagerAction(root, {
504
+ action: "test-case-apply",
505
+ subject: testCaseId,
506
+ input,
507
+ result,
508
+ detail: {
509
+ input_revision: collection.revision,
510
+ input_checksum: collection.checksum,
511
+ output_revision: next.revision,
512
+ output_checksum: outputChecksum,
513
+ affected_identities: [testCaseId],
514
+ },
515
+ writes: [{ file: collection.file, content }],
516
+ receiptPrefix: "WM-TC",
517
+ });
518
+ }
519
+
520
+ export function recordWorkflowManagerTestRun(projectRoot, input = {}) {
521
+ const root = path.resolve(projectRoot);
522
+ const definition = COLLECTION_DEFINITIONS.test_runs;
523
+ const testRunId = safeIdentity(input.test_run_id, "test_run_id");
524
+ requiredActor(input.actor);
525
+ requiredText(input.idempotency_key, "idempotency_key");
526
+ const replay = preflightWorkflowManagerAction(root, {
527
+ action: "test-run-record",
528
+ subject: testRunId,
529
+ input,
530
+ });
531
+ if (replay) return { outcome: "idempotent-replay", receipt: replay, result: replay.result };
532
+
533
+ const collection = readWritableCollection(root, definition);
534
+ assertCollectionVersion(collection, input);
535
+ if (collection.value[definition.arrayKey].some((item) => item?.[definition.identity] === testRunId)) {
536
+ throw new Error(`Test run already exists: ${testRunId}`);
537
+ }
538
+ const testCaseId = safeIdentity(input.test_case_id, "test_case_id");
539
+ const testCaseSource = readWritableCollection(root, COLLECTION_DEFINITIONS.test_cases);
540
+ const testCase = testCaseSource.value.test_cases.find((item) => item?.test_case_id === testCaseId);
541
+ if (!testCase) throw new Error(`Test case not found: ${testCaseId}`);
542
+ if (!Number.isInteger(input.test_case_version)
543
+ || input.test_case_version !== Number(testCase.version || testCase.revision || 0)) {
544
+ throw new Error(`Test case version conflict for ${testCaseId}`);
545
+ }
546
+ const testRun = {
547
+ test_run_id: testRunId,
548
+ test_case_id: testCaseId,
549
+ test_case_version: input.test_case_version,
550
+ iteration_id: safeIdentity(input.iteration_id, "iteration_id"),
551
+ candidate_id: safeIdentity(input.candidate_id, "candidate_id"),
552
+ outcome: allowedValue(input.outcome, TEST_RUN_OUTCOMES, "outcome"),
553
+ evidence: stringList(input.evidence, "evidence"),
554
+ recorded_at: new Date().toISOString(),
555
+ };
556
+ const items = [...collection.value[definition.arrayKey], testRun]
557
+ .sort((left, right) => String(left.test_run_id).localeCompare(String(right.test_run_id)));
558
+ const next = {
559
+ ...collection.value,
560
+ schema_version: 1,
561
+ revision: collection.revision + 1,
562
+ [definition.arrayKey]: items,
563
+ };
564
+ const content = YAML.stringify(next, { lineWidth: 0 });
565
+ const outputChecksum = sha256(content);
566
+ const result = { test_run: testRun, collection_revision: next.revision, collection_checksum: outputChecksum };
567
+ return commitWorkflowManagerAction(root, {
568
+ action: "test-run-record",
569
+ subject: testRunId,
570
+ input,
571
+ result,
572
+ detail: {
573
+ input_revision: collection.revision,
574
+ input_checksum: collection.checksum,
575
+ output_revision: next.revision,
576
+ output_checksum: outputChecksum,
577
+ affected_identities: [testRunId, testCaseId, testRun.candidate_id],
578
+ },
579
+ writes: [{ file: collection.file, content }],
580
+ receiptPrefix: "WM-TR",
581
+ });
582
+ }
583
+
584
+ function appendArg(argv, flag, value) {
585
+ if (value === undefined || value === null || value === "") return;
586
+ argv.push(flag, String(value));
587
+ }
588
+
589
+ function appendArgs(argv, flag, values) {
590
+ for (const value of Array.isArray(values) ? values : []) appendArg(argv, flag, value);
591
+ }
592
+
593
+ function defaultTaskWriter(projectRoot, argv, descriptor, options = {}) {
594
+ const script = path.join(
595
+ projectRoot,
596
+ ".agents", "skills", "ai-delivery-checkpoint-task", "scripts", "task-state.mjs",
597
+ );
598
+ if (!fs.existsSync(script)) throw new Error(`Installed task writer is missing: ${script}`);
599
+ const written = spawnSync(process.execPath, [script, ...argv, "--manager-transaction"], {
600
+ cwd: projectRoot,
601
+ encoding: "utf8",
602
+ input: JSON.stringify(descriptor),
603
+ env: {
604
+ ...process.env,
605
+ ...(options.taskTransactionFailureSuffix
606
+ ? { AI_DELIVERY_TEST_TASK_TRANSACTION_FAILURE_SUFFIX: options.taskTransactionFailureSuffix }
607
+ : {}),
608
+ },
609
+ windowsHide: true,
610
+ });
611
+ if (written.error || written.status !== 0) {
612
+ throw new Error(written.error?.message || written.stderr.trim() || "Task writer failed");
613
+ }
614
+ return JSON.parse(written.stdout);
615
+ }
616
+
617
+ function taskWriterArgs(root, input) {
618
+ const operation = input.operation;
619
+ if (!new Set(["create", "activate", "checkpoint", "finish"]).has(operation)) {
620
+ throw new Error("operation must be create, activate, checkpoint, or finish");
621
+ }
622
+ const taskId = safeIdentity(input.task_id, "task_id");
623
+ const command = operation === "create" ? "init" : operation;
624
+ const argv = [command, "--root", root, "--state-root", root, "--task-id", taskId];
625
+ if (operation === "create") {
626
+ appendArg(argv, "--iteration-id", safeIdentity(input.iteration_id, "iteration_id"));
627
+ appendArg(argv, "--node", safeIdentity(input.node, "node"));
628
+ appendArg(argv, "--skill", safeIdentity(input.skill, "skill"));
629
+ appendArg(argv, "--goal", requiredText(input.goal, "goal"));
630
+ appendArg(argv, "--responsibility", requiredText(input.responsibility, "responsibility"));
631
+ appendArgs(argv, "--scope", input.scope);
632
+ appendArgs(argv, "--acceptance", input.acceptance);
633
+ appendArgs(argv, "--depends-on", input.depends_on);
634
+ appendArg(argv, "--next-action", requiredText(input.next_action, "next_action"));
635
+ appendArg(argv, "--next-action-owner", requiredText(input.next_action_owner, "next_action_owner"));
636
+ appendArg(argv, "--status", "queued");
637
+ appendArg(argv, "--sequence", input.sequence);
638
+ appendArg(argv, "--derived-from", input.derived_from);
639
+ appendArg(argv, "--supersedes", input.supersedes);
640
+ return { argv, taskId };
641
+ }
642
+ if (operation === "activate") {
643
+ appendArg(argv, "--status", input.status || "running");
644
+ appendArg(argv, "--phase", input.phase);
645
+ if (input.new_attempt === true) argv.push("--new-attempt");
646
+ } else {
647
+ appendArg(argv, "--status", requiredText(input.status, "status"));
648
+ appendArg(argv, "--phase", input.phase);
649
+ appendArgs(argv, "--completed-step", input.completed_steps);
650
+ appendArgs(argv, "--blocker", input.blockers);
651
+ appendArgs(argv, "--evidence", input.evidence);
652
+ appendArgs(argv, "--actual-output", input.actual_outputs);
653
+ }
654
+ appendArg(argv, "--next-action", requiredText(input.next_action, "next_action"));
655
+ appendArg(argv, "--next-action-owner", input.next_action_owner);
656
+ return { argv, taskId };
657
+ }
658
+
659
+ export function applyWorkflowManagerTask(projectRoot, input = {}, options = {}) {
660
+ const root = path.resolve(projectRoot);
661
+ requiredActor(input.actor);
662
+ requiredText(input.idempotency_key, "idempotency_key");
663
+ if (!Number.isInteger(input.expected_shared_revision) || input.expected_shared_revision < 0) {
664
+ throw new Error("expected_shared_revision must be a non-negative integer");
665
+ }
666
+ const { argv, taskId } = taskWriterArgs(root, input);
667
+ const replay = preflightWorkflowManagerAction(root, {
668
+ action: "task-apply",
669
+ subject: taskId,
670
+ input,
671
+ });
672
+ if (replay) return { outcome: "idempotent-replay", receipt: replay, result: replay.result };
673
+ const descriptor = { schema_version: 1, action: "task-apply", subject: taskId, input };
674
+ const taskWriter = options.taskWriter
675
+ || ((writerArgv) => defaultTaskWriter(root, writerArgv, descriptor, options));
676
+ const written = taskWriter(argv);
677
+ const task = written && typeof written === "object" ? { ...written } : written;
678
+ const managerTransaction = task?.manager_transaction || null;
679
+ if (task) delete task.manager_transaction;
680
+ if (!task || task.task_id !== taskId) throw new Error("Task writer returned an unexpected identity");
681
+ const result = { task };
682
+ if (!options.taskWriter) {
683
+ if (!managerTransaction?.receipt || managerTransaction.receipt.result?.task?.task_id !== taskId) {
684
+ throw new Error("Task writer did not return its governed Manager transaction evidence");
685
+ }
686
+ return {
687
+ outcome: managerTransaction.outcome,
688
+ result,
689
+ receipt: managerTransaction.receipt,
690
+ event: managerTransaction.event,
691
+ };
692
+ }
693
+ return commitWorkflowManagerAction(root, {
694
+ action: "task-apply",
695
+ subject: taskId,
696
+ input,
697
+ result,
698
+ detail: {
699
+ output_revision: Number(task.shared_revision || 0),
700
+ affected_identities: [taskId],
701
+ delegated_writer: "task-state.mjs",
702
+ },
703
+ receiptPrefix: "WM-TASK",
704
+ });
705
+ }
706
+
707
+ export function applyWorkflowManagerArtifact(projectRoot, input = {}, options = {}) {
708
+ const root = path.resolve(projectRoot);
709
+ const artifactId = safeIdentity(input.artifact_id, "artifact_id");
710
+ requiredActor(input.actor);
711
+ requiredText(input.idempotency_key, "idempotency_key");
712
+ if (!Number.isInteger(input.expected_revision) || input.expected_revision < 0) {
713
+ throw new Error("expected_revision must be a non-negative integer");
714
+ }
715
+ const replay = preflightWorkflowManagerAction(root, {
716
+ action: "artifact-register",
717
+ subject: artifactId,
718
+ input,
719
+ });
720
+ if (replay) return { outcome: "idempotent-replay", receipt: replay, result: replay.result };
721
+ const argv = [
722
+ "artifact", "register", "--project", root,
723
+ "--expected-revision", String(input.expected_revision),
724
+ "--id", artifactId,
725
+ "--artifact-type", requiredText(input.artifact_type, "artifact_type"),
726
+ "--path", requiredText(input.path, "path"),
727
+ "--node", safeIdentity(input.node, "node"),
728
+ "--status", requiredText(input.status, "status"),
729
+ ];
730
+ appendArg(argv, "--version", input.version);
731
+ appendArg(argv, "--producer-skill", input.producer_skill);
732
+ appendArg(argv, "--candidate-id", input.candidate_id);
733
+ appendArg(argv, "--supersedes", input.supersedes);
734
+ const stateWriter = options.stateWriter
735
+ || ((writerArgv, writerOptions) => executeDeliveryStateCommand(writerArgv, { yaml: YAML, ...writerOptions }));
736
+ if (options.stateWriter) {
737
+ const formal = stateWriter(argv, options.stateOptions || {});
738
+ if (formal?.artifact?.artifact_id !== artifactId) throw new Error("Formal state writer returned an unexpected artifact identity");
739
+ const result = { artifact: formal.artifact, artifact_registry_revision: formal.revision };
740
+ return commitWorkflowManagerAction(root, {
741
+ action: "artifact-register",
742
+ subject: artifactId,
743
+ input,
744
+ result,
745
+ detail: {
746
+ input_revision: input.expected_revision,
747
+ output_revision: formal.revision,
748
+ affected_identities: [artifactId],
749
+ delegated_writer: "delivery-state.artifact-register",
750
+ },
751
+ receiptPrefix: "WM-ART",
752
+ });
753
+ }
754
+ const transaction = prepareWorkflowManagerFormalTransaction(root, {
755
+ action: "artifact-register",
756
+ subject: artifactId,
757
+ input,
758
+ resultFactory: ({ mutations }) => {
759
+ const mutation = mutations.find((item) => item.stream === "artifact-registry");
760
+ const artifact = mutation?.value?.artifacts?.find((item) => item.artifact_id === artifactId);
761
+ if (!artifact) throw new Error("Formal state transaction did not register the expected artifact");
762
+ return { artifact, artifact_registry_revision: mutation.value.revision };
763
+ },
764
+ detailFactory: (_formal, result) => ({
765
+ input_revision: input.expected_revision,
766
+ output_revision: result.artifact_registry_revision,
767
+ affected_identities: [artifactId],
768
+ delegated_writer: "delivery-state.artifact-register",
769
+ }),
770
+ receiptPrefix: "WM-ART",
771
+ });
772
+ const formal = stateWriter(argv, {
773
+ ...(options.stateOptions || {}),
774
+ managerTransactionWriteFactory: transaction.factory,
775
+ });
776
+ if (formal?.artifact?.artifact_id !== artifactId) throw new Error("Formal state writer returned an unexpected artifact identity");
777
+ return transaction.result();
778
+ }