@graphrefly/ts 0.0.0 → 0.0.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 (307) hide show
  1. package/README.md +135 -0
  2. package/dist/adapters/index.cjs +105 -66
  3. package/dist/adapters/index.cjs.map +1 -1
  4. package/dist/adapters/index.d.cts +11 -136
  5. package/dist/adapters/index.d.ts +11 -136
  6. package/dist/adapters/index.js +27 -225
  7. package/dist/adapters/index.js.map +1 -1
  8. package/dist/adapters/observe-storage.d.cts +4 -4
  9. package/dist/adapters/observe-storage.d.ts +4 -4
  10. package/dist/adapters/observe-storage.js +1 -0
  11. package/dist/adapters/observe-storage.js.map +1 -1
  12. package/dist/adapters/react.cjs +166 -0
  13. package/dist/adapters/react.cjs.map +1 -0
  14. package/dist/adapters/react.d.cts +31 -0
  15. package/dist/adapters/react.d.ts +31 -0
  16. package/dist/adapters/react.js +51 -0
  17. package/dist/adapters/react.js.map +1 -0
  18. package/dist/adapters/solid.cjs +157 -0
  19. package/dist/adapters/solid.cjs.map +1 -0
  20. package/dist/adapters/solid.d.cts +26 -0
  21. package/dist/adapters/solid.d.ts +26 -0
  22. package/dist/adapters/solid.js +48 -0
  23. package/dist/adapters/solid.js.map +1 -0
  24. package/dist/adapters/svelte.cjs +148 -0
  25. package/dist/adapters/svelte.cjs.map +1 -0
  26. package/dist/adapters/svelte.d.cts +31 -0
  27. package/dist/adapters/svelte.d.ts +31 -0
  28. package/dist/adapters/svelte.js +46 -0
  29. package/dist/adapters/svelte.js.map +1 -0
  30. package/dist/adapters/vue.cjs +155 -0
  31. package/dist/adapters/vue.cjs.map +1 -0
  32. package/dist/adapters/vue.d.cts +26 -0
  33. package/dist/adapters/vue.d.ts +26 -0
  34. package/dist/adapters/vue.js +46 -0
  35. package/dist/adapters/vue.js.map +1 -0
  36. package/dist/agent-runtime-BesGDZcB.d.ts +555 -0
  37. package/dist/agent-runtime-DZTJ3C-p.d.cts +555 -0
  38. package/dist/agentic-memory-BmRCvh0d.d.ts +517 -0
  39. package/dist/agentic-memory-DfuVZ-lY.d.cts +517 -0
  40. package/dist/capability-admission-B0BzqAm5.d.cts +102 -0
  41. package/dist/capability-admission-g0mn9hpq.d.ts +102 -0
  42. package/dist/{chunk-JR4IKCR2.js → chunk-2747WN4Y.js} +5 -5
  43. package/dist/{chunk-2ILL7HQI.js → chunk-3JR3EDB2.js} +17 -17
  44. package/dist/{chunk-2ILL7HQI.js.map → chunk-3JR3EDB2.js.map} +1 -1
  45. package/dist/{chunk-GDL26N2T.js → chunk-3KN7NJDR.js} +2 -2
  46. package/dist/{chunk-DJC4CHLQ.js → chunk-43BKLFZU.js} +9 -9
  47. package/dist/chunk-6XAIOL3X.js +2407 -0
  48. package/dist/chunk-6XAIOL3X.js.map +1 -0
  49. package/dist/{chunk-SCRFRCGR.js → chunk-BSQGE5PS.js} +1 -1
  50. package/dist/{chunk-Y3ZLRGHC.js → chunk-CZNV3VXM.js} +16 -16
  51. package/dist/chunk-DGUM43GV.js +11 -0
  52. package/dist/chunk-DGUM43GV.js.map +1 -0
  53. package/dist/{chunk-JIMUDQN3.js → chunk-FBUU43PM.js} +2 -2
  54. package/dist/chunk-H75VXTGT.js +219 -0
  55. package/dist/chunk-H75VXTGT.js.map +1 -0
  56. package/dist/{chunk-RIIOUTGM.js → chunk-HKK2JD7Z.js} +12 -9
  57. package/dist/chunk-HKK2JD7Z.js.map +1 -0
  58. package/dist/{chunk-D6BG7U6A.js → chunk-IXZBUWSP.js} +3 -3
  59. package/dist/chunk-PC3BTTBE.js +3217 -0
  60. package/dist/chunk-PC3BTTBE.js.map +1 -0
  61. package/dist/chunk-QFY4AFY4.js +879 -0
  62. package/dist/chunk-QFY4AFY4.js.map +1 -0
  63. package/dist/{chunk-DK554R7P.js → chunk-S6HXABGL.js} +2 -1
  64. package/dist/chunk-S6HXABGL.js.map +1 -0
  65. package/dist/{chunk-PKVBHGBM.js → chunk-SS2A464I.js} +7 -7
  66. package/dist/chunk-UT3MHJCW.js +49 -0
  67. package/dist/chunk-UT3MHJCW.js.map +1 -0
  68. package/dist/{chunk-G4M3NHRJ.js → chunk-V7CIJE4B.js} +3 -3
  69. package/dist/{chunk-TEW47IVR.js → chunk-VPEFSDME.js} +2 -2
  70. package/dist/chunk-VTHLCFN4.js +368 -0
  71. package/dist/chunk-VTHLCFN4.js.map +1 -0
  72. package/dist/{chunk-SWTLEQL6.js → chunk-WQIA3GFB.js} +2 -2
  73. package/dist/chunk-WQIA3GFB.js.map +1 -0
  74. package/dist/{chunk-I3IHOHCJ.js → chunk-XKXWK2KP.js} +108 -64
  75. package/dist/chunk-XKXWK2KP.js.map +1 -0
  76. package/dist/{chunk-COHO25CZ.js → chunk-YDSIVHRR.js} +553 -7
  77. package/dist/chunk-YDSIVHRR.js.map +1 -0
  78. package/dist/chunk-YXMZ2N6J.js +1884 -0
  79. package/dist/chunk-YXMZ2N6J.js.map +1 -0
  80. package/dist/composition/index.cjs +102 -57
  81. package/dist/composition/index.cjs.map +1 -1
  82. package/dist/composition/index.d.cts +4 -4
  83. package/dist/composition/index.d.ts +4 -4
  84. package/dist/composition/index.js +6 -5
  85. package/dist/core/index.cjs +102 -57
  86. package/dist/core/index.cjs.map +1 -1
  87. package/dist/core/index.d.cts +2 -2
  88. package/dist/core/index.d.ts +2 -2
  89. package/dist/core/index.js +5 -4
  90. package/dist/cqrs/index.cjs.map +1 -1
  91. package/dist/cqrs/index.d.cts +4 -4
  92. package/dist/cqrs/index.d.ts +4 -4
  93. package/dist/cqrs/index.js +3 -2
  94. package/dist/cqrs/index.js.map +1 -1
  95. package/dist/cqrs/messaging.cjs +312 -0
  96. package/dist/cqrs/messaging.cjs.map +1 -0
  97. package/dist/cqrs/messaging.d.cts +57 -0
  98. package/dist/cqrs/messaging.d.ts +57 -0
  99. package/dist/cqrs/messaging.js +274 -0
  100. package/dist/cqrs/messaging.js.map +1 -0
  101. package/dist/cqrs/work-queue.cjs +329 -0
  102. package/dist/cqrs/work-queue.cjs.map +1 -0
  103. package/dist/cqrs/work-queue.d.cts +90 -0
  104. package/dist/cqrs/work-queue.d.ts +90 -0
  105. package/dist/cqrs/work-queue.js +292 -0
  106. package/dist/cqrs/work-queue.js.map +1 -0
  107. package/dist/data/index.cjs +19 -0
  108. package/dist/data/index.cjs.map +1 -0
  109. package/dist/data/index.d.cts +36 -0
  110. package/dist/data/index.d.ts +36 -0
  111. package/dist/data/index.js +1 -0
  112. package/dist/data/index.js.map +1 -0
  113. package/dist/data-structures/index.cjs +105 -57
  114. package/dist/data-structures/index.cjs.map +1 -1
  115. package/dist/data-structures/index.d.cts +8 -8
  116. package/dist/data-structures/index.d.ts +8 -8
  117. package/dist/data-structures/index.js +7 -6
  118. package/dist/{describe-BZb7AS2y.d.ts → describe-BpyJuWkw.d.ts} +1 -1
  119. package/dist/{describe-Ciu8SUnN.d.cts → describe-DYMw_l1C.d.cts} +1 -1
  120. package/dist/executors/work-queue.cjs +342 -0
  121. package/dist/executors/work-queue.cjs.map +1 -0
  122. package/dist/executors/work-queue.d.cts +90 -0
  123. package/dist/executors/work-queue.d.ts +90 -0
  124. package/dist/executors/work-queue.js +306 -0
  125. package/dist/executors/work-queue.js.map +1 -0
  126. package/dist/graph/index.cjs +112 -58
  127. package/dist/graph/index.cjs.map +1 -1
  128. package/dist/graph/index.d.cts +9 -9
  129. package/dist/graph/index.d.ts +9 -9
  130. package/dist/graph/index.js +18 -17
  131. package/dist/{graph-DfdF9zy4.d.ts → graph-D-1-SQeC.d.ts} +3 -3
  132. package/dist/{graph-s23RbbFO.d.cts → graph-DCEWh4T2.d.cts} +3 -3
  133. package/dist/{index-CAEmLCYF.d.cts → index-72VZC0-E.d.cts} +2 -2
  134. package/dist/{index-SnzZu3x7.d.ts → index-Bmxeu0nK.d.ts} +2 -2
  135. package/dist/index.cjs +112 -58
  136. package/dist/index.cjs.map +1 -1
  137. package/dist/index.d.cts +11 -10
  138. package/dist/index.d.ts +11 -10
  139. package/dist/index.js +118 -113
  140. package/dist/inspection/boundary.cjs +98 -0
  141. package/dist/inspection/boundary.cjs.map +1 -0
  142. package/dist/inspection/boundary.d.cts +61 -0
  143. package/dist/inspection/boundary.d.ts +61 -0
  144. package/dist/inspection/boundary.js +75 -0
  145. package/dist/inspection/boundary.js.map +1 -0
  146. package/dist/{messages-BZqrGGm1.d.ts → messages-CAzUPPJM.d.cts} +10 -5
  147. package/dist/{messages-BZqrGGm1.d.cts → messages-CAzUPPJM.d.ts} +10 -5
  148. package/dist/messaging/index.cjs +744 -613
  149. package/dist/messaging/index.cjs.map +1 -1
  150. package/dist/messaging/index.d.cts +216 -160
  151. package/dist/messaging/index.d.ts +216 -160
  152. package/dist/messaging/index.js +19 -749
  153. package/dist/messaging/index.js.map +1 -1
  154. package/dist/operators/index.cjs +102 -57
  155. package/dist/operators/index.cjs.map +1 -1
  156. package/dist/operators/index.d.cts +6 -6
  157. package/dist/operators/index.d.ts +6 -6
  158. package/dist/operators/index.js +8 -7
  159. package/dist/orchestration/index.cjs +3333 -59
  160. package/dist/orchestration/index.cjs.map +1 -1
  161. package/dist/orchestration/index.d.cts +7 -4
  162. package/dist/orchestration/index.d.ts +7 -4
  163. package/dist/orchestration/index.js +49 -8
  164. package/dist/orchestration/index.js.map +1 -1
  165. package/dist/orchestration/messaging.cjs +314 -0
  166. package/dist/orchestration/messaging.cjs.map +1 -0
  167. package/dist/orchestration/messaging.d.cts +59 -0
  168. package/dist/orchestration/messaging.d.ts +59 -0
  169. package/dist/orchestration/messaging.js +276 -0
  170. package/dist/orchestration/messaging.js.map +1 -0
  171. package/dist/orchestration/work-queue.cjs +262 -0
  172. package/dist/orchestration/work-queue.cjs.map +1 -0
  173. package/dist/orchestration/work-queue.d.cts +85 -0
  174. package/dist/orchestration/work-queue.d.ts +85 -0
  175. package/dist/orchestration/work-queue.js +226 -0
  176. package/dist/orchestration/work-queue.js.map +1 -0
  177. package/dist/patterns/event-flow.cjs +447 -0
  178. package/dist/patterns/event-flow.cjs.map +1 -0
  179. package/dist/patterns/event-flow.d.cts +115 -0
  180. package/dist/patterns/event-flow.d.ts +115 -0
  181. package/dist/patterns/event-flow.js +14 -0
  182. package/dist/patterns/event-flow.js.map +1 -0
  183. package/dist/patterns/index.cjs +423 -18
  184. package/dist/patterns/index.cjs.map +1 -1
  185. package/dist/patterns/index.d.cts +8 -5
  186. package/dist/patterns/index.d.ts +8 -5
  187. package/dist/patterns/index.js +13 -4
  188. package/dist/{reactive-collection-Cb1II1Fi.d.ts → reactive-collection-BAmfrGjd.d.ts} +9 -9
  189. package/dist/{reactive-collection-BxBqtIOE.d.cts → reactive-collection-DNV0-gFi.d.cts} +9 -9
  190. package/dist/{reactive-collection-storage-D-KmjE0J.d.cts → reactive-collection-storage-BNEldDyi.d.cts} +5 -5
  191. package/dist/{reactive-collection-storage-BNiEc-Gd.d.ts → reactive-collection-storage-YZsAQsWK.d.ts} +5 -5
  192. package/dist/{reactive-map-D-g3dv8I.d.cts → reactive-map-DRD1LJ2H.d.cts} +6 -6
  193. package/dist/{reactive-map-BcB4KsQR.d.ts → reactive-map-EsDiCmJk.d.ts} +6 -6
  194. package/dist/render/index.d.cts +3 -3
  195. package/dist/render/index.d.ts +3 -3
  196. package/dist/render/index.js +1 -0
  197. package/dist/{semantic-memory-graph-BYoIlP35.d.cts → semantic-memory-graph-DKuNzuWw.d.cts} +2 -2
  198. package/dist/{semantic-memory-graph-CxyXLms3.d.ts → semantic-memory-graph-uwbwJdhe.d.ts} +2 -2
  199. package/dist/solutions/index.cjs +4478 -2
  200. package/dist/solutions/index.cjs.map +1 -1
  201. package/dist/solutions/index.d.cts +13 -519
  202. package/dist/solutions/index.d.ts +13 -519
  203. package/dist/solutions/index.js +90 -6
  204. package/dist/solutions/reactive-layout/browser/index.cjs +449 -0
  205. package/dist/solutions/reactive-layout/browser/index.cjs.map +1 -0
  206. package/dist/solutions/reactive-layout/browser/index.d.cts +44 -0
  207. package/dist/solutions/reactive-layout/browser/index.d.ts +44 -0
  208. package/dist/solutions/reactive-layout/browser/index.js +69 -0
  209. package/dist/solutions/reactive-layout/browser/index.js.map +1 -0
  210. package/dist/solutions/reactive-layout/index.cjs +4266 -0
  211. package/dist/solutions/reactive-layout/index.cjs.map +1 -0
  212. package/dist/solutions/reactive-layout/index.d.cts +581 -0
  213. package/dist/solutions/reactive-layout/index.d.ts +581 -0
  214. package/dist/solutions/reactive-layout/index.js +86 -0
  215. package/dist/solutions/reactive-layout/index.js.map +1 -0
  216. package/dist/solutions/reactive-layout/node-canvas/index.cjs +545 -0
  217. package/dist/solutions/reactive-layout/node-canvas/index.cjs.map +1 -0
  218. package/dist/solutions/reactive-layout/node-canvas/index.d.cts +54 -0
  219. package/dist/solutions/reactive-layout/node-canvas/index.d.ts +54 -0
  220. package/dist/solutions/reactive-layout/node-canvas/index.js +131 -0
  221. package/dist/solutions/reactive-layout/node-canvas/index.js.map +1 -0
  222. package/dist/solutions/reactive-layout/react-native/index.cjs +494 -0
  223. package/dist/solutions/reactive-layout/react-native/index.cjs.map +1 -0
  224. package/dist/solutions/reactive-layout/react-native/index.d.cts +51 -0
  225. package/dist/solutions/reactive-layout/react-native/index.d.ts +51 -0
  226. package/dist/solutions/reactive-layout/react-native/index.js +77 -0
  227. package/dist/solutions/reactive-layout/react-native/index.js.map +1 -0
  228. package/dist/solutions/reactive-layout/skia/index.cjs +547 -0
  229. package/dist/solutions/reactive-layout/skia/index.cjs.map +1 -0
  230. package/dist/solutions/reactive-layout/skia/index.d.cts +64 -0
  231. package/dist/solutions/reactive-layout/skia/index.d.ts +64 -0
  232. package/dist/solutions/reactive-layout/skia/index.js +70 -0
  233. package/dist/solutions/reactive-layout/skia/index.js.map +1 -0
  234. package/dist/solutions/work-item/actions.cjs +2164 -0
  235. package/dist/solutions/work-item/actions.cjs.map +1 -0
  236. package/dist/solutions/work-item/actions.d.cts +201 -0
  237. package/dist/solutions/work-item/actions.d.ts +201 -0
  238. package/dist/solutions/work-item/actions.js +1454 -0
  239. package/dist/solutions/work-item/actions.js.map +1 -0
  240. package/dist/solutions/work-item/scheduling.cjs +2454 -0
  241. package/dist/solutions/work-item/scheduling.cjs.map +1 -0
  242. package/dist/solutions/work-item/scheduling.d.cts +433 -0
  243. package/dist/solutions/work-item/scheduling.d.ts +433 -0
  244. package/dist/solutions/work-item/scheduling.js +32 -0
  245. package/dist/solutions/work-item/scheduling.js.map +1 -0
  246. package/dist/solutions/work-item/work-queue.cjs +306 -0
  247. package/dist/solutions/work-item/work-queue.cjs.map +1 -0
  248. package/dist/solutions/work-item/work-queue.d.cts +71 -0
  249. package/dist/solutions/work-item/work-queue.d.ts +71 -0
  250. package/dist/solutions/work-item/work-queue.js +270 -0
  251. package/dist/solutions/work-item/work-queue.js.map +1 -0
  252. package/dist/sources/browser.cjs +169 -57
  253. package/dist/sources/browser.cjs.map +1 -1
  254. package/dist/sources/browser.d.cts +33 -6
  255. package/dist/sources/browser.d.ts +33 -6
  256. package/dist/sources/browser.js +73 -6
  257. package/dist/sources/browser.js.map +1 -1
  258. package/dist/sources/index.cjs +102 -57
  259. package/dist/sources/index.cjs.map +1 -1
  260. package/dist/sources/index.d.cts +5 -5
  261. package/dist/sources/index.d.ts +5 -5
  262. package/dist/sources/index.js +6 -5
  263. package/dist/sources/node.cjs.map +1 -1
  264. package/dist/sources/node.d.cts +4 -4
  265. package/dist/sources/node.d.ts +4 -4
  266. package/dist/sources/node.js +2 -1
  267. package/dist/sources/node.js.map +1 -1
  268. package/dist/storage/browser.js +1 -0
  269. package/dist/storage/browser.js.map +1 -1
  270. package/dist/storage/index.d.cts +5 -5
  271. package/dist/storage/index.d.ts +5 -5
  272. package/dist/storage/index.js +5 -4
  273. package/dist/storage/node.js +1 -0
  274. package/dist/storage/node.js.map +1 -1
  275. package/dist/store-C-joM4gh.d.ts +123 -0
  276. package/dist/store-CNJwmT-h.d.cts +123 -0
  277. package/dist/testing/index.cjs +1 -0
  278. package/dist/testing/index.cjs.map +1 -1
  279. package/dist/testing/index.d.cts +1 -1
  280. package/dist/testing/index.d.ts +1 -1
  281. package/dist/testing/index.js +3 -2
  282. package/dist/{types-h12mNYbq.d.ts → types-BsJvElYZ.d.ts} +31 -31
  283. package/dist/{types-bNMSWKqF.d.cts → types-CcPIn7sy.d.cts} +31 -31
  284. package/dist/work-item-runtime-C3M79vE9.d.ts +228 -0
  285. package/dist/work-item-runtime-qaVgsL0T.d.cts +228 -0
  286. package/dist/work-queue/index.cjs +1132 -0
  287. package/dist/work-queue/index.cjs.map +1 -0
  288. package/dist/work-queue/index.d.cts +369 -0
  289. package/dist/work-queue/index.d.ts +369 -0
  290. package/dist/work-queue/index.js +1078 -0
  291. package/dist/work-queue/index.js.map +1 -0
  292. package/package.json +266 -2
  293. package/dist/chunk-COHO25CZ.js.map +0 -1
  294. package/dist/chunk-DK554R7P.js.map +0 -1
  295. package/dist/chunk-I3IHOHCJ.js.map +0 -1
  296. package/dist/chunk-RIIOUTGM.js.map +0 -1
  297. package/dist/chunk-SWTLEQL6.js.map +0 -1
  298. /package/dist/{chunk-JR4IKCR2.js.map → chunk-2747WN4Y.js.map} +0 -0
  299. /package/dist/{chunk-GDL26N2T.js.map → chunk-3KN7NJDR.js.map} +0 -0
  300. /package/dist/{chunk-DJC4CHLQ.js.map → chunk-43BKLFZU.js.map} +0 -0
  301. /package/dist/{chunk-SCRFRCGR.js.map → chunk-BSQGE5PS.js.map} +0 -0
  302. /package/dist/{chunk-Y3ZLRGHC.js.map → chunk-CZNV3VXM.js.map} +0 -0
  303. /package/dist/{chunk-JIMUDQN3.js.map → chunk-FBUU43PM.js.map} +0 -0
  304. /package/dist/{chunk-D6BG7U6A.js.map → chunk-IXZBUWSP.js.map} +0 -0
  305. /package/dist/{chunk-PKVBHGBM.js.map → chunk-SS2A464I.js.map} +0 -0
  306. /package/dist/{chunk-G4M3NHRJ.js.map → chunk-V7CIJE4B.js.map} +0 -0
  307. /package/dist/{chunk-TEW47IVR.js.map → chunk-VPEFSDME.js.map} +0 -0
@@ -0,0 +1,2454 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/solutions/work-item/scheduling.ts
21
+ var scheduling_exports = {};
22
+ __export(scheduling_exports, {
23
+ acceptanceCriteriaChanged: () => acceptanceCriteriaChanged,
24
+ validateAcceptanceCriteria: () => validateAcceptanceCriteria,
25
+ validateVerificationPlan: () => validateVerificationPlan,
26
+ validateWorkItemDraft: () => validateWorkItemDraft,
27
+ validateWorkItemEffectPlan: () => validateWorkItemEffectPlan,
28
+ verificationPlanChanged: () => verificationPlanChanged,
29
+ workItemAuthoringProjector: () => workItemAuthoringProjector,
30
+ workItemCreatedFromDraft: () => workItemCreatedFromDraft,
31
+ workItemEffectPlanProjector: () => workItemEffectPlanProjector,
32
+ workItemSpawnProposed: () => workItemSpawnProposed,
33
+ workItemVerificationRequestLowerer: () => workItemVerificationRequestLowerer,
34
+ workItemVerificationResultMapper: () => workItemVerificationResultMapper
35
+ });
36
+ module.exports = __toCommonJS(scheduling_exports);
37
+
38
+ // src/protocol/messages.ts
39
+ var SENTINEL = void 0;
40
+
41
+ // src/ctx/types.ts
42
+ function depWaves(ctx, depIndex) {
43
+ return ctx.waveData[depIndex] ?? [];
44
+ }
45
+ function depBatch(ctx, depIndex) {
46
+ const waves = depWaves(ctx, depIndex);
47
+ if (waves.length === 0) return null;
48
+ const flattened = waves.flat().filter((v) => v !== SENTINEL);
49
+ return flattened.length === 0 ? [] : flattened;
50
+ }
51
+
52
+ // src/solutions/work-item/scheduling.ts
53
+ var executionRelevantDefaults = /* @__PURE__ */ new Set([
54
+ "detail",
55
+ "detailRefs",
56
+ "acceptanceCriteria",
57
+ "verificationPlan",
58
+ "verificationSteps",
59
+ "dependencies"
60
+ ]);
61
+ var draftPatchKeys = /* @__PURE__ */ new Set([
62
+ "summary",
63
+ "detail",
64
+ "detailRefs",
65
+ "acceptanceCriteria",
66
+ "verificationPlan",
67
+ "verificationSteps",
68
+ "kind",
69
+ "priority",
70
+ "tags",
71
+ "owner",
72
+ "assignee",
73
+ "deadlineMs",
74
+ "customFields",
75
+ "sourceRefs",
76
+ "metadata"
77
+ ]);
78
+ function workItemCreatedFromDraft(workItemId, draft, opts = {}) {
79
+ return {
80
+ kind: "work-item-created",
81
+ eventId: opts.eventId ?? `${workItemId}:created`,
82
+ workItemId,
83
+ draft,
84
+ authorId: opts.authorId,
85
+ createdAtMs: opts.createdAtMs,
86
+ sourceRefs: opts.sourceRefs,
87
+ metadata: opts.metadata
88
+ };
89
+ }
90
+ function workItemSpawnProposed(proposalId, draft, opts = {}) {
91
+ return {
92
+ kind: "work-item-spawn-proposed",
93
+ proposalId,
94
+ draft,
95
+ parentWorkItemId: opts.parentWorkItemId,
96
+ proposedBy: opts.proposedBy,
97
+ sourceRefs: opts.sourceRefs,
98
+ metadata: opts.metadata
99
+ };
100
+ }
101
+ function acceptanceCriteriaChanged(workItemId, acceptanceCriteria, opts) {
102
+ return {
103
+ kind: "acceptance-criteria-changed",
104
+ eventId: opts.eventId,
105
+ workItemId,
106
+ acceptanceCriteria,
107
+ authorId: opts.authorId,
108
+ changedAtMs: opts.changedAtMs,
109
+ sourceRefs: opts.sourceRefs,
110
+ metadata: opts.metadata
111
+ };
112
+ }
113
+ function verificationPlanChanged(workItemId, verificationPlan, opts) {
114
+ return {
115
+ kind: "verification-plan-changed",
116
+ eventId: opts.eventId,
117
+ workItemId,
118
+ verificationPlan,
119
+ authorId: opts.authorId,
120
+ changedAtMs: opts.changedAtMs,
121
+ sourceRefs: opts.sourceRefs,
122
+ metadata: opts.metadata
123
+ };
124
+ }
125
+ function validateWorkItemDraft(draft, opts = {}) {
126
+ const out = [];
127
+ if (!isRecord(draft)) {
128
+ return [issue("malformed-draft", "WorkItemDraft must be an object", opts.workItemId)];
129
+ }
130
+ if (typeof draft.summary !== "string") {
131
+ out.push(issue("missing-required-field", "WorkItemDraft.summary is required", opts.workItemId));
132
+ } else if (draft.summary.trim() === "") {
133
+ out.push(issue("missing-required-field", "WorkItemDraft.summary is required", opts.workItemId));
134
+ }
135
+ const criteria = draft.acceptanceCriteria === void 0 || Array.isArray(draft.acceptanceCriteria) ? draft.acceptanceCriteria : void 0;
136
+ if (draft.acceptanceCriteria !== void 0 && criteria === void 0) {
137
+ out.push(
138
+ issue(
139
+ "malformed-draft",
140
+ "WorkItemDraft.acceptanceCriteria must be an array",
141
+ opts.workItemId
142
+ )
143
+ );
144
+ }
145
+ out.push(...validateAcceptanceCriteria(criteria ?? [], opts));
146
+ if (draft.verificationPlan !== void 0 && !isVerificationPlanShape(draft.verificationPlan)) {
147
+ out.push(
148
+ issue("malformed-draft", "WorkItemDraft.verificationPlan is malformed", opts.workItemId)
149
+ );
150
+ }
151
+ if (draft.verificationSteps !== void 0 && !Array.isArray(draft.verificationSteps)) {
152
+ out.push(
153
+ issue("malformed-draft", "WorkItemDraft.verificationSteps must be an array", opts.workItemId)
154
+ );
155
+ }
156
+ const plan = normalizePlanFromUnknown(draft);
157
+ if (plan !== void 0) {
158
+ out.push(...validateVerificationPlan(plan, criteria ?? [], opts));
159
+ }
160
+ return out;
161
+ }
162
+ function validateAcceptanceCriteria(criteria, opts = {}) {
163
+ const out = [];
164
+ const seen = /* @__PURE__ */ new Set();
165
+ for (const criterion of criteria) {
166
+ if (!isRecord(criterion)) {
167
+ out.push(issue("malformed-draft", "AcceptanceCriterion must be an object", opts.workItemId));
168
+ continue;
169
+ }
170
+ if (typeof criterion.criterionId !== "string" || criterion.criterionId === "") {
171
+ out.push(
172
+ issue(
173
+ "missing-required-field",
174
+ "AcceptanceCriterion.criterionId is required",
175
+ opts.workItemId
176
+ )
177
+ );
178
+ continue;
179
+ }
180
+ if (seen.has(criterion.criterionId)) {
181
+ out.push(
182
+ issue(
183
+ "duplicate-id",
184
+ `Duplicate acceptance criterion id '${criterion.criterionId}'`,
185
+ opts.workItemId,
186
+ { criterionId: criterion.criterionId }
187
+ )
188
+ );
189
+ }
190
+ seen.add(criterion.criterionId);
191
+ if (typeof criterion.statement !== "string" || criterion.statement.trim() === "") {
192
+ out.push(
193
+ issue(
194
+ "missing-required-field",
195
+ "AcceptanceCriterion.statement is required",
196
+ opts.workItemId,
197
+ { criterionId: criterion.criterionId }
198
+ )
199
+ );
200
+ }
201
+ }
202
+ return out;
203
+ }
204
+ function validateVerificationPlan(plan, criteria = [], opts = {}) {
205
+ const out = [];
206
+ if (!isRecord(plan) || !Array.isArray(plan.steps)) {
207
+ return [issue("malformed-draft", "VerificationPlan.steps must be an array", opts.workItemId)];
208
+ }
209
+ const criterionIds = new Set(criteria.map((criterion) => criterion.criterionId));
210
+ const stepIds = /* @__PURE__ */ new Set();
211
+ const modes = new Set(opts.allowedModes ?? ["auto", "manual", "hybrid"]);
212
+ const effectKinds = new Set(opts.allowedEffectKinds ?? ["verification"]);
213
+ for (const step of plan.steps) {
214
+ if (!isRecord(step)) {
215
+ out.push(issue("malformed-draft", "VerificationStep must be an object", opts.workItemId));
216
+ continue;
217
+ }
218
+ if (typeof step.stepId !== "string" || step.stepId === "") {
219
+ out.push(
220
+ issue("missing-required-field", "VerificationStep.stepId is required", opts.workItemId)
221
+ );
222
+ continue;
223
+ }
224
+ if (stepIds.has(step.stepId)) {
225
+ out.push(
226
+ issue("duplicate-id", `Duplicate verification step id '${step.stepId}'`, opts.workItemId, {
227
+ stepId: step.stepId
228
+ })
229
+ );
230
+ }
231
+ stepIds.add(step.stepId);
232
+ if (typeof step.mode !== "string" || !modes.has(step.mode)) {
233
+ out.push(
234
+ issue(
235
+ "unsupported-mode",
236
+ `Unsupported verification step mode '${step.mode}'`,
237
+ opts.workItemId,
238
+ { stepId: step.stepId }
239
+ )
240
+ );
241
+ }
242
+ if (step.effectKind !== void 0 && (typeof step.effectKind !== "string" || !effectKinds.has(step.effectKind))) {
243
+ out.push(
244
+ issue(
245
+ "unsupported-effect-kind",
246
+ `Unsupported verification effect kind '${step.effectKind}'`,
247
+ opts.workItemId,
248
+ { stepId: step.stepId }
249
+ )
250
+ );
251
+ }
252
+ const verifiesCriteriaIds = Array.isArray(step.verifiesCriteriaIds) ? step.verifiesCriteriaIds : [];
253
+ for (const criterionId of verifiesCriteriaIds) {
254
+ if (!criterionIds.has(criterionId)) {
255
+ out.push(
256
+ issue("dangling-ref", `Unknown acceptance criterion '${criterionId}'`, opts.workItemId, {
257
+ stepId: step.stepId,
258
+ criterionId
259
+ })
260
+ );
261
+ }
262
+ }
263
+ }
264
+ for (const step of plan.steps) {
265
+ if (!isRecord(step) || typeof step.stepId !== "string") continue;
266
+ const dependsOnStepIds = Array.isArray(step.dependsOnStepIds) ? step.dependsOnStepIds : [];
267
+ for (const depId of dependsOnStepIds) {
268
+ if (!stepIds.has(depId)) {
269
+ out.push(
270
+ issue("dangling-ref", `Unknown verification dependency '${depId}'`, opts.workItemId, {
271
+ stepId: step.stepId
272
+ })
273
+ );
274
+ }
275
+ }
276
+ }
277
+ const cycle = findCycle(
278
+ plan.steps.filter(
279
+ (step) => isRecord(step) && typeof step.stepId === "string" && Array.isArray(step.dependsOnStepIds)
280
+ )
281
+ );
282
+ if (cycle !== void 0) {
283
+ out.push(
284
+ issue(
285
+ "cyclic-dependency",
286
+ `Verification step cycle detected: ${cycle.join(" -> ")}`,
287
+ opts.workItemId,
288
+ { stepId: cycle[0] }
289
+ )
290
+ );
291
+ }
292
+ return out;
293
+ }
294
+ function workItemAuthoringProjector(graph, opts) {
295
+ const name = opts.name ?? "workItemAuthoring";
296
+ const runtime = graph.node(
297
+ [opts.facts],
298
+ (ctx) => {
299
+ const state = ctx.state.get() ?? {
300
+ workItems: /* @__PURE__ */ new Map(),
301
+ seenEvents: /* @__PURE__ */ new Set(),
302
+ statusSeq: 0,
303
+ auditSeq: 0
304
+ };
305
+ for (const raw of depBatch(ctx, 0) ?? [])
306
+ reduceAuthoring(ctx, state, raw, opts.policy);
307
+ ctx.state.set(state);
308
+ },
309
+ {
310
+ name: `${name}/runtime`,
311
+ factory: "workItemAuthoringProjector",
312
+ partial: true,
313
+ completeWhenDepsComplete: false,
314
+ errorWhenDepsError: false
315
+ }
316
+ );
317
+ return {
318
+ workItems: project(
319
+ graph,
320
+ runtime,
321
+ `${name}/workItems`,
322
+ "workItemAuthoringWorkItems",
323
+ (fact) => fact.kind === "work-item" ? fact.value : void 0
324
+ ),
325
+ status: project(
326
+ graph,
327
+ runtime,
328
+ `${name}/status`,
329
+ "workItemAuthoringStatus",
330
+ (fact) => fact.kind === "status" ? fact.value : void 0
331
+ ),
332
+ issues: project(
333
+ graph,
334
+ runtime,
335
+ `${name}/issues`,
336
+ "workItemAuthoringIssues",
337
+ (fact) => fact.kind === "issue" ? fact.value : void 0
338
+ ),
339
+ audit: project(
340
+ graph,
341
+ runtime,
342
+ `${name}/audit`,
343
+ "workItemAuthoringAudit",
344
+ (fact) => fact.kind === "audit" ? fact.value : void 0
345
+ )
346
+ };
347
+ }
348
+ function workItemVerificationRequestLowerer(graph, opts) {
349
+ const name = opts.name ?? "workItemVerificationRequests";
350
+ const deps = [opts.workItems];
351
+ const dispatchIntentIndex = opts.dispatchIntents === void 0 ? -1 : deps.push(opts.dispatchIntents) - 1;
352
+ const verificationResultIndex = opts.verificationResults === void 0 ? -1 : deps.push(opts.verificationResults) - 1;
353
+ const runtime = graph.node(
354
+ deps,
355
+ (ctx) => {
356
+ const state = ctx.state.get() ?? {
357
+ workItems: /* @__PURE__ */ new Map(),
358
+ emittedKeys: /* @__PURE__ */ new Set(),
359
+ passedSteps: /* @__PURE__ */ new Map(),
360
+ statusSeq: 0,
361
+ auditSeq: 0
362
+ };
363
+ for (const raw of depBatch(ctx, 0) ?? []) {
364
+ const workItem = raw;
365
+ state.workItems.set(workItem.workItemId, workItem);
366
+ lowerPlan(ctx, state, workItem, opts.policy);
367
+ }
368
+ if (dispatchIntentIndex >= 0) {
369
+ for (const raw of depBatch(ctx, dispatchIntentIndex) ?? [])
370
+ lowerIntent(ctx, state, raw, opts.policy);
371
+ }
372
+ if (verificationResultIndex >= 0) {
373
+ for (const raw of depBatch(ctx, verificationResultIndex) ?? [])
374
+ recordVerificationResult(ctx, state, raw, opts.policy);
375
+ }
376
+ ctx.state.set(state);
377
+ },
378
+ {
379
+ name: `${name}/runtime`,
380
+ factory: "workItemVerificationRequestLowerer",
381
+ partial: true,
382
+ completeWhenDepsComplete: false,
383
+ errorWhenDepsError: false
384
+ }
385
+ );
386
+ return {
387
+ effectRequests: project(
388
+ graph,
389
+ runtime,
390
+ `${name}/effectRequests`,
391
+ "workItemVerificationEffectRequests",
392
+ (fact) => fact.kind === "request" ? fact.value : void 0
393
+ ),
394
+ status: project(
395
+ graph,
396
+ runtime,
397
+ `${name}/status`,
398
+ "workItemVerificationRequestStatus",
399
+ (fact) => fact.kind === "status" ? fact.value : void 0
400
+ ),
401
+ issues: project(
402
+ graph,
403
+ runtime,
404
+ `${name}/issues`,
405
+ "workItemVerificationRequestIssues",
406
+ (fact) => fact.kind === "issue" ? fact.value : void 0
407
+ ),
408
+ audit: project(
409
+ graph,
410
+ runtime,
411
+ `${name}/audit`,
412
+ "workItemVerificationRequestAudit",
413
+ (fact) => fact.kind === "audit" ? fact.value : void 0
414
+ )
415
+ };
416
+ }
417
+ function workItemVerificationResultMapper(graph, opts) {
418
+ const name = opts.name ?? "workItemVerificationResults";
419
+ const deps = opts.policies === void 0 ? [opts.workItems, opts.evidence] : [opts.workItems, opts.evidence, opts.policies];
420
+ const runtime = graph.node(
421
+ deps,
422
+ (ctx) => {
423
+ const state = ctx.state.get() ?? {
424
+ workItems: /* @__PURE__ */ new Map(),
425
+ policies: /* @__PURE__ */ new Map(),
426
+ evidenceById: /* @__PURE__ */ new Map(),
427
+ resultEvidence: /* @__PURE__ */ new Set(),
428
+ proposalKeys: /* @__PURE__ */ new Set(),
429
+ statusSeq: 0,
430
+ auditSeq: 0
431
+ };
432
+ for (const raw of depBatch(ctx, 0) ?? []) {
433
+ const workItem = raw;
434
+ state.workItems.set(workItem.workItemId, workItem);
435
+ replayEvidence(ctx, state, workItem.workItemId);
436
+ }
437
+ if (opts.policies !== void 0) {
438
+ for (const raw of depBatch(ctx, 2) ?? []) {
439
+ const policy = raw;
440
+ const issues = validateMappingPolicy(policy);
441
+ if (issues.length > 0) {
442
+ for (const item of issues) emit(ctx, "issue", item);
443
+ emitResultStatus(ctx, state, {
444
+ state: "rejected",
445
+ code: "policy-mismatch",
446
+ metadata: { policyId: isRecord(policy) ? policy.policyId : void 0 }
447
+ });
448
+ continue;
449
+ }
450
+ state.policies.set(policy.policyId, policy);
451
+ }
452
+ for (const evidence of state.evidenceById.values()) {
453
+ mapEvidence(ctx, state, evidence, true);
454
+ }
455
+ }
456
+ for (const raw of depBatch(ctx, 1) ?? [])
457
+ mapEvidence(ctx, state, raw);
458
+ ctx.state.set(state);
459
+ },
460
+ {
461
+ name: `${name}/runtime`,
462
+ factory: "workItemVerificationResultMapper",
463
+ partial: true,
464
+ completeWhenDepsComplete: false,
465
+ errorWhenDepsError: false
466
+ }
467
+ );
468
+ return {
469
+ results: project(
470
+ graph,
471
+ runtime,
472
+ `${name}/results`,
473
+ "workItemVerificationResults",
474
+ (fact) => fact.kind === "result" ? fact.value : void 0
475
+ ),
476
+ proposals: project(
477
+ graph,
478
+ runtime,
479
+ `${name}/proposals`,
480
+ "workItemVerificationProposals",
481
+ (fact) => fact.kind === "proposal" ? fact.value : void 0
482
+ ),
483
+ status: project(
484
+ graph,
485
+ runtime,
486
+ `${name}/status`,
487
+ "workItemVerificationResultStatus",
488
+ (fact) => fact.kind === "status" ? fact.value : void 0
489
+ ),
490
+ issues: project(
491
+ graph,
492
+ runtime,
493
+ `${name}/issues`,
494
+ "workItemVerificationResultIssues",
495
+ (fact) => fact.kind === "issue" ? fact.value : void 0
496
+ ),
497
+ audit: project(
498
+ graph,
499
+ runtime,
500
+ `${name}/audit`,
501
+ "workItemVerificationResultAudit",
502
+ (fact) => fact.kind === "audit" ? fact.value : void 0
503
+ )
504
+ };
505
+ }
506
+ function validateWorkItemEffectPlan(proposal, workItem, policy = {}) {
507
+ const out = [];
508
+ if (!isRecord(proposal) || proposal.kind !== "work-item-effect-plan-proposed" || typeof proposal.planId !== "string" || proposal.planId.trim() === "" || typeof proposal.workItemId !== "string" || proposal.workItemId.trim() === "" || typeof proposal.executionInputRevision !== "number" || !Array.isArray(proposal.members)) {
509
+ return [
510
+ issue(
511
+ "malformed-draft",
512
+ "WorkItemEffectPlanProposed requires planId, workItemId, executionInputRevision, and members",
513
+ isRecord(proposal) && typeof proposal.workItemId === "string" ? proposal.workItemId : void 0
514
+ )
515
+ ];
516
+ }
517
+ if (proposal.joinPolicy !== void 0 && !isWorkItemEffectPlanJoinPolicy(proposal.joinPolicy)) {
518
+ out.push(
519
+ issue(
520
+ "policy-mismatch",
521
+ `Unsupported WorkItemEffectPlan join policy '${proposal.joinPolicy}'`,
522
+ proposal.workItemId,
523
+ { planId: proposal.planId, joinPolicy: proposal.joinPolicy }
524
+ )
525
+ );
526
+ }
527
+ if (workItem === void 0) {
528
+ out.push(
529
+ issue(
530
+ "dangling-ref",
531
+ `WorkItemEffectPlan '${proposal.planId}' references unknown WorkItem '${proposal.workItemId}'`,
532
+ proposal.workItemId,
533
+ { planId: proposal.planId }
534
+ )
535
+ );
536
+ } else if (proposal.executionInputRevision !== workItem.executionInputRevision) {
537
+ out.push(
538
+ issue(
539
+ "stale-execution-input",
540
+ `WorkItemEffectPlan '${proposal.planId}' targets stale execution input`,
541
+ proposal.workItemId,
542
+ {
543
+ planId: proposal.planId,
544
+ proposedRevision: proposal.executionInputRevision,
545
+ currentRevision: workItem.executionInputRevision
546
+ }
547
+ )
548
+ );
549
+ }
550
+ const memberIds = /* @__PURE__ */ new Set();
551
+ const allowedEffectKinds = policy.allowedEffectKinds === void 0 ? void 0 : new Set(policy.allowedEffectKinds);
552
+ for (const member of proposal.members) {
553
+ if (!isRecord(member)) {
554
+ out.push(
555
+ issue(
556
+ "malformed-draft",
557
+ "WorkItemEffectPlan member must be an object",
558
+ proposal.workItemId,
559
+ {
560
+ planId: proposal.planId
561
+ }
562
+ )
563
+ );
564
+ continue;
565
+ }
566
+ if (typeof member.memberId !== "string" || member.memberId.trim() === "") {
567
+ out.push(
568
+ issue(
569
+ "missing-required-field",
570
+ "WorkItemEffectPlan memberId is required",
571
+ proposal.workItemId,
572
+ { planId: proposal.planId }
573
+ )
574
+ );
575
+ continue;
576
+ }
577
+ if (memberIds.has(member.memberId)) {
578
+ out.push(
579
+ issue(
580
+ "duplicate-id",
581
+ `Duplicate WorkItemEffectPlan member id '${member.memberId}'`,
582
+ proposal.workItemId,
583
+ { planId: proposal.planId, planMemberId: member.memberId }
584
+ )
585
+ );
586
+ }
587
+ memberIds.add(member.memberId);
588
+ if (typeof member.effectKind !== "string" || member.effectKind.trim() === "") {
589
+ out.push(
590
+ issue(
591
+ "missing-required-field",
592
+ "WorkItemEffectPlan member effectKind is required",
593
+ proposal.workItemId,
594
+ { planId: proposal.planId, planMemberId: member.memberId }
595
+ )
596
+ );
597
+ } else if (allowedEffectKinds !== void 0 && !allowedEffectKinds.has(member.effectKind)) {
598
+ out.push(
599
+ issue(
600
+ "unsupported-effect-kind",
601
+ `Unsupported WorkItemEffectPlan effect kind '${member.effectKind}'`,
602
+ proposal.workItemId,
603
+ { planId: proposal.planId, planMemberId: member.memberId }
604
+ )
605
+ );
606
+ }
607
+ if (!isRecord(member.goal)) {
608
+ out.push(
609
+ issue(
610
+ "missing-required-field",
611
+ "WorkItemEffectPlan member goal is required",
612
+ proposal.workItemId,
613
+ { planId: proposal.planId, planMemberId: member.memberId }
614
+ )
615
+ );
616
+ }
617
+ for (const field of [
618
+ "dependsOnMemberIds",
619
+ "contextRefs",
620
+ "requirements",
621
+ "policyRefs",
622
+ "sourceRefs"
623
+ ]) {
624
+ if (member[field] !== void 0 && !Array.isArray(member[field])) {
625
+ out.push(
626
+ issue(
627
+ "malformed-draft",
628
+ `WorkItemEffectPlan member ${field} must be an array`,
629
+ proposal.workItemId,
630
+ { planId: proposal.planId, planMemberId: member.memberId, field }
631
+ )
632
+ );
633
+ }
634
+ }
635
+ }
636
+ for (const member of proposal.members) {
637
+ if (!isRecord(member) || typeof member.memberId !== "string") continue;
638
+ const deps = Array.isArray(member.dependsOnMemberIds) ? member.dependsOnMemberIds : [];
639
+ for (const depId of deps) {
640
+ if (!memberIds.has(depId)) {
641
+ out.push(
642
+ issue(
643
+ "dangling-ref",
644
+ `Unknown WorkItemEffectPlan dependency '${depId}'`,
645
+ proposal.workItemId,
646
+ { planId: proposal.planId, planMemberId: member.memberId, depId }
647
+ )
648
+ );
649
+ }
650
+ }
651
+ }
652
+ const cycle = findPlanCycle(
653
+ proposal.members.filter(
654
+ (member) => isRecord(member) && typeof member.memberId === "string" && Array.isArray(member.dependsOnMemberIds)
655
+ )
656
+ );
657
+ if (cycle !== void 0) {
658
+ out.push(
659
+ issue(
660
+ "cyclic-dependency",
661
+ `WorkItemEffectPlan member cycle detected: ${cycle.join(" -> ")}`,
662
+ proposal.workItemId,
663
+ { planId: proposal.planId, planMemberId: cycle[0] }
664
+ )
665
+ );
666
+ }
667
+ return out;
668
+ }
669
+ function workItemEffectPlanProjector(graph, opts) {
670
+ const name = opts.name ?? "workItemEffectPlans";
671
+ const deps = [opts.workItems, opts.proposals];
672
+ const evidenceIndex = opts.evidence === void 0 ? -1 : deps.push(opts.evidence) - 1;
673
+ const resultIndex = opts.effectRunResults === void 0 ? -1 : deps.push(opts.effectRunResults) - 1;
674
+ const now = opts.now ?? Date.now;
675
+ const runtime = graph.node(
676
+ deps,
677
+ (ctx) => {
678
+ const state = ctx.state.get() ?? emptyPlanState();
679
+ for (const raw of depBatch(ctx, 0) ?? []) {
680
+ const workItem = raw;
681
+ state.workItems.set(workItem.workItemId, workItem);
682
+ for (const proposal of state.proposals.values()) {
683
+ if (proposal.workItemId === workItem.workItemId)
684
+ admitPlan(ctx, state, proposal, opts.policy, now);
685
+ }
686
+ }
687
+ for (const raw of depBatch(ctx, 1) ?? []) {
688
+ const proposal = raw;
689
+ if (isRecord(proposal) && typeof proposal.planId === "string" && typeof proposal.workItemId === "string") {
690
+ const key = planKey(
691
+ proposal.workItemId,
692
+ proposal.planId,
693
+ proposal.executionInputRevision
694
+ );
695
+ if (key !== void 0) state.proposals.set(key, proposal);
696
+ }
697
+ admitPlan(ctx, state, proposal, opts.policy, now);
698
+ }
699
+ if (evidenceIndex >= 0) {
700
+ for (const raw of depBatch(ctx, evidenceIndex) ?? [])
701
+ recordPlanEvidence(ctx, state, raw);
702
+ }
703
+ if (resultIndex >= 0) {
704
+ for (const raw of depBatch(ctx, resultIndex) ?? [])
705
+ recordPlanResult(ctx, state, raw);
706
+ }
707
+ drainPlanWork(ctx, state, opts.policy);
708
+ ctx.state.set(state);
709
+ },
710
+ {
711
+ name: `${name}/runtime`,
712
+ factory: "workItemEffectPlanProjector",
713
+ partial: true,
714
+ completeWhenDepsComplete: false,
715
+ errorWhenDepsError: false
716
+ }
717
+ );
718
+ return {
719
+ admitted: project(
720
+ graph,
721
+ runtime,
722
+ `${name}/admitted`,
723
+ "workItemEffectPlansAdmitted",
724
+ (fact) => fact.kind === "admitted" ? fact.value : void 0
725
+ ),
726
+ rejected: project(
727
+ graph,
728
+ runtime,
729
+ `${name}/rejected`,
730
+ "workItemEffectPlansRejected",
731
+ (fact) => fact.kind === "rejected" ? fact.value : void 0
732
+ ),
733
+ effectRequests: project(
734
+ graph,
735
+ runtime,
736
+ `${name}/effectRequests`,
737
+ "workItemEffectPlanEffectRequests",
738
+ (fact) => fact.kind === "request" ? fact.value : void 0
739
+ ),
740
+ results: project(
741
+ graph,
742
+ runtime,
743
+ `${name}/results`,
744
+ "workItemEffectPlanResults",
745
+ (fact) => fact.kind === "result" ? fact.value : void 0
746
+ ),
747
+ status: project(
748
+ graph,
749
+ runtime,
750
+ `${name}/status`,
751
+ "workItemEffectPlanStatus",
752
+ (fact) => fact.kind === "status" ? fact.value : void 0
753
+ ),
754
+ issues: project(
755
+ graph,
756
+ runtime,
757
+ `${name}/issues`,
758
+ "workItemEffectPlanIssues",
759
+ (fact) => fact.kind === "issue" ? fact.value : void 0
760
+ ),
761
+ audit: project(
762
+ graph,
763
+ runtime,
764
+ `${name}/audit`,
765
+ "workItemEffectPlanAudit",
766
+ (fact) => fact.kind === "audit" ? fact.value : void 0
767
+ )
768
+ };
769
+ }
770
+ function emptyPlanState() {
771
+ return {
772
+ workItems: /* @__PURE__ */ new Map(),
773
+ proposals: /* @__PURE__ */ new Map(),
774
+ admitted: /* @__PURE__ */ new Map(),
775
+ rejected: /* @__PURE__ */ new Set(),
776
+ emittedMemberKeys: /* @__PURE__ */ new Set(),
777
+ statusKeys: /* @__PURE__ */ new Set(),
778
+ resultKeys: /* @__PURE__ */ new Set(),
779
+ requestByEffectRun: /* @__PURE__ */ new Map(),
780
+ requestByRequestId: /* @__PURE__ */ new Map(),
781
+ memberEvidence: /* @__PURE__ */ new Map(),
782
+ pendingEvidence: /* @__PURE__ */ new Map(),
783
+ pendingResults: /* @__PURE__ */ new Map(),
784
+ unmatchedEvidence: /* @__PURE__ */ new Set(),
785
+ unmatchedResults: /* @__PURE__ */ new Set(),
786
+ statusSeq: 0,
787
+ auditSeq: 0
788
+ };
789
+ }
790
+ function admitPlan(ctx, state, proposal, policy, now) {
791
+ if (!isRecord(proposal) || typeof proposal.planId !== "string") {
792
+ const issues2 = validateWorkItemEffectPlan(proposal, void 0, policy);
793
+ emitPlanIssues(ctx, state, issues2);
794
+ return;
795
+ }
796
+ const key = planKey(proposal.workItemId, proposal.planId, proposal.executionInputRevision);
797
+ if (key === void 0) {
798
+ const issues2 = validateWorkItemEffectPlan(proposal, void 0, policy);
799
+ emitPlanIssues(ctx, state, issues2);
800
+ return;
801
+ }
802
+ if (state.admitted.has(key) || state.rejected.has(key)) return;
803
+ const workItem = state.workItems.get(proposal.workItemId);
804
+ if (workItem === void 0) {
805
+ emitPlanStatusOnce(ctx, state, `${key}:deferred:missing-work-item`, {
806
+ workItemId: proposal.workItemId,
807
+ planId: proposal.planId,
808
+ executionInputRevision: proposal.executionInputRevision,
809
+ state: "deferred",
810
+ message: `WorkItemEffectPlan '${proposal.planId}' is waiting for WorkItem '${proposal.workItemId}'`,
811
+ sourceRefs: proposal.sourceRefs,
812
+ metadata: { reason: "missing-work-item" }
813
+ });
814
+ return;
815
+ }
816
+ const issues = validateWorkItemEffectPlan(proposal, workItem, policy);
817
+ if (issues.length > 0) {
818
+ state.rejected.add(key);
819
+ emitPlanIssues(ctx, state, issues);
820
+ const rejected = {
821
+ kind: "work-item-effect-plan-rejected",
822
+ planId: proposal.planId,
823
+ workItemId: proposal.workItemId,
824
+ executionInputRevision: proposal.executionInputRevision,
825
+ issues,
826
+ sourceRefs: proposal.sourceRefs,
827
+ rejectedAtMs: now(),
828
+ metadata: proposal.metadata
829
+ };
830
+ emitPlan(ctx, "rejected", rejected);
831
+ emitPlanStatus(ctx, state, {
832
+ workItemId: proposal.workItemId,
833
+ planId: proposal.planId,
834
+ executionInputRevision: proposal.executionInputRevision,
835
+ state: "rejected",
836
+ issues,
837
+ sourceRefs: proposal.sourceRefs,
838
+ metadata: { issueCodes: issues.map((item) => item.code) }
839
+ });
840
+ return;
841
+ }
842
+ const snapshot = normalizeEffectPlanSnapshot(proposal, policy);
843
+ const admitted = {
844
+ kind: "work-item-effect-plan-admitted",
845
+ planId: snapshot.planId,
846
+ workItemId: snapshot.workItemId,
847
+ executionInputRevision: snapshot.executionInputRevision,
848
+ plan: snapshot,
849
+ sourceRefs: immutableClone(proposal.sourceRefs),
850
+ admittedAtMs: now(),
851
+ metadata: immutableClone(proposal.metadata)
852
+ };
853
+ state.admitted.set(key, admitted);
854
+ emitPlan(ctx, "admitted", admitted);
855
+ emitPlanStatus(ctx, state, {
856
+ workItemId: admitted.workItemId,
857
+ planId: admitted.planId,
858
+ executionInputRevision: admitted.executionInputRevision,
859
+ state: "eligible",
860
+ sourceRefs: admitted.sourceRefs,
861
+ metadata: { memberCount: admitted.plan.members.length }
862
+ });
863
+ }
864
+ function drainPlanWork(ctx, state, policy) {
865
+ const maxPasses = state.admitted.size + state.pendingEvidence.size + state.pendingResults.size + state.emittedMemberKeys.size + 1;
866
+ for (let pass = 0; pass < maxPasses; pass += 1) {
867
+ let changed = false;
868
+ for (const admitted of state.admitted.values()) {
869
+ changed = lowerEligiblePlanMembers(ctx, state, admitted, policy) || changed;
870
+ derivePlanResult(ctx, state, admitted);
871
+ }
872
+ changed = replayPendingPlanFacts(ctx, state) || changed;
873
+ if (!changed) break;
874
+ }
875
+ for (const admitted of state.admitted.values()) derivePlanResult(ctx, state, admitted);
876
+ }
877
+ function lowerEligiblePlanMembers(ctx, state, admitted, policy) {
878
+ if (isAdmittedPlanStale(state, admitted)) {
879
+ emitStaleAdmittedPlanOnce(ctx, state, admitted);
880
+ return false;
881
+ }
882
+ let changed = false;
883
+ for (const member of admitted.plan.members) {
884
+ const coord = memberCoord(admitted, member.memberId);
885
+ if (state.memberEvidence.has(coord)) continue;
886
+ const missing = (member.dependsOnMemberIds ?? []).filter(
887
+ (memberId) => !memberSucceeded(state, admitted, memberId)
888
+ );
889
+ if (missing.length > 0) {
890
+ emitPlanStatusOnce(ctx, state, `${coord}:blocked:${missing.join(",")}`, {
891
+ workItemId: admitted.workItemId,
892
+ planId: admitted.planId,
893
+ executionInputRevision: admitted.executionInputRevision,
894
+ state: "blocked",
895
+ planMemberId: member.memberId,
896
+ issues: [
897
+ issue(
898
+ "blocked-prerequisite",
899
+ `WorkItemEffectPlan member '${member.memberId}' is blocked by prerequisites`,
900
+ admitted.workItemId,
901
+ { planId: admitted.planId, planMemberId: member.memberId, missingMemberIds: missing }
902
+ )
903
+ ],
904
+ sourceRefs: member.sourceRefs,
905
+ metadata: { missingMemberIds: missing }
906
+ });
907
+ continue;
908
+ }
909
+ if (state.emittedMemberKeys.has(coord)) continue;
910
+ state.emittedMemberKeys.add(coord);
911
+ changed = true;
912
+ const request = requestFromPlanMember(admitted, member, policy);
913
+ state.requestByEffectRun.set(request.effectRunId, request);
914
+ state.requestByRequestId.set(request.requestId, request);
915
+ emitPlan(ctx, "request", request);
916
+ emitPlanStatus(ctx, state, {
917
+ workItemId: admitted.workItemId,
918
+ planId: admitted.planId,
919
+ executionInputRevision: admitted.executionInputRevision,
920
+ state: "requested",
921
+ planMemberId: member.memberId,
922
+ requestId: request.requestId,
923
+ effectRunId: request.effectRunId,
924
+ sourceRefs: request.sourceRefs,
925
+ metadata: { effectKind: request.effectKind }
926
+ });
927
+ }
928
+ return changed;
929
+ }
930
+ function recordPlanEvidence(ctx, state, evidence) {
931
+ const coordinate = planCoordinateFromEvidence(state, evidence);
932
+ if (coordinate === void 0) {
933
+ state.pendingEvidence.set(evidence.evidenceId, evidence);
934
+ emitUnmatchedEvidence(ctx, state, `evidence:${evidence.evidenceId}`, evidence.workItemId, {
935
+ evidenceId: evidence.evidenceId,
936
+ effectRunId: evidence.effectRunId
937
+ });
938
+ return false;
939
+ }
940
+ if (emitConflictingPlanEvidenceCoordinate(ctx, state, evidence, coordinate)) return true;
941
+ const key = requiredPlanKey(
942
+ coordinate.workItemId,
943
+ coordinate.planId,
944
+ coordinate.executionInputRevision
945
+ );
946
+ const admitted = state.admitted.get(key);
947
+ if (admitted === void 0) {
948
+ state.pendingEvidence.set(evidence.evidenceId, evidence);
949
+ emitUnmatchedEvidence(ctx, state, `evidence:${evidence.evidenceId}`, coordinate.workItemId, {
950
+ evidenceId: evidence.evidenceId,
951
+ effectRunId: evidence.effectRunId,
952
+ planId: coordinate.planId,
953
+ planMemberId: coordinate.planMemberId,
954
+ executionInputRevision: coordinate.executionInputRevision
955
+ });
956
+ return false;
957
+ }
958
+ if (isAdmittedPlanStale(state, admitted)) {
959
+ emitStaleAdmittedPlanOnce(ctx, state, admitted);
960
+ return true;
961
+ }
962
+ if (!hasPlanMember(admitted, coordinate.planMemberId)) {
963
+ emitUnknownPlanMember(ctx, state, admitted, coordinate.planMemberId, {
964
+ evidenceId: evidence.evidenceId,
965
+ effectRunId: evidence.effectRunId
966
+ });
967
+ return true;
968
+ }
969
+ const recorded = recordMemberEvidence(ctx, state, admitted, coordinate.planMemberId, {
970
+ status: evidence.status,
971
+ requestId: coordinate.requestId ?? coordinate.request?.requestId,
972
+ effectRunId: evidence.effectRunId,
973
+ evidenceId: evidence.evidenceId,
974
+ effectRunResultId: evidence.effectRunResultId,
975
+ sourceRefs: evidence.sourceRefs
976
+ });
977
+ if (!recorded) return true;
978
+ emitPlanStatus(ctx, state, {
979
+ workItemId: coordinate.workItemId,
980
+ planId: coordinate.planId,
981
+ executionInputRevision: coordinate.executionInputRevision,
982
+ state: evidence.status === "completed" ? "completed" : "failed",
983
+ planMemberId: coordinate.planMemberId,
984
+ requestId: coordinate.requestId ?? coordinate.request?.requestId,
985
+ effectRunId: evidence.effectRunId,
986
+ evidenceId: evidence.evidenceId,
987
+ effectRunResultId: evidence.effectRunResultId,
988
+ sourceRefs: evidence.sourceRefs,
989
+ metadata: { evidenceStatus: evidence.status }
990
+ });
991
+ return true;
992
+ }
993
+ function emitConflictingPlanEvidenceCoordinate(ctx, state, evidence, coordinate) {
994
+ const expectedRequest = planRequestForCoordinate(state, coordinate);
995
+ const expectedRequestIdMismatch = expectedRequest !== void 0 && evidence.requestId !== void 0 && evidence.requestId !== expectedRequest.requestId;
996
+ if (expectedRequest !== void 0 && (expectedRequestIdMismatch || evidence.effectRunId !== expectedRequest.effectRunId)) {
997
+ emitPlanEvidenceCoordinateMismatch(ctx, state, evidence, coordinate, expectedRequest);
998
+ return true;
999
+ }
1000
+ const requestRefs = [
1001
+ evidence.requestId === void 0 ? void 0 : state.requestByRequestId.get(evidence.requestId),
1002
+ state.requestByEffectRun.get(evidence.effectRunId)
1003
+ ].filter((request) => request !== void 0);
1004
+ const conflicting = requestRefs.find(
1005
+ (request) => !requestMatchesPlanCoordinate(request, coordinate) || !requestMatchesEvidenceIdentity(request, evidence)
1006
+ );
1007
+ if (conflicting === void 0) return false;
1008
+ emitPlanEvidenceCoordinateMismatch(ctx, state, evidence, coordinate, conflicting);
1009
+ return true;
1010
+ }
1011
+ function emitPlanEvidenceCoordinateMismatch(ctx, state, evidence, coordinate, conflicting) {
1012
+ const item = issue(
1013
+ "dangling-ref",
1014
+ "WorkItemEffectPlan evidence request/effectRun coordinates do not match its plan member coordinates",
1015
+ evidence.workItemId,
1016
+ {
1017
+ evidenceId: evidence.evidenceId,
1018
+ requestId: evidence.requestId,
1019
+ effectRunId: evidence.effectRunId,
1020
+ planId: coordinate.planId,
1021
+ planMemberId: coordinate.planMemberId,
1022
+ executionInputRevision: coordinate.executionInputRevision,
1023
+ requestPlanId: conflicting.planId,
1024
+ requestPlanMemberId: conflicting.planMemberId,
1025
+ requestExecutionInputRevision: conflicting.executionInputRevision
1026
+ }
1027
+ );
1028
+ emitPlan(ctx, "issue", item);
1029
+ emitPlanStatus(ctx, state, {
1030
+ workItemId: coordinate.workItemId,
1031
+ planId: coordinate.planId,
1032
+ executionInputRevision: coordinate.executionInputRevision,
1033
+ state: "rejected",
1034
+ planMemberId: coordinate.planMemberId,
1035
+ requestId: evidence.requestId,
1036
+ effectRunId: evidence.effectRunId,
1037
+ evidenceId: evidence.evidenceId,
1038
+ issues: [item],
1039
+ sourceRefs: evidence.sourceRefs,
1040
+ metadata: item.metadata
1041
+ });
1042
+ }
1043
+ function requestMatchesPlanCoordinate(request, coordinate) {
1044
+ return request.workItemId === coordinate.workItemId && request.planId === coordinate.planId && request.planMemberId === coordinate.planMemberId && request.executionInputRevision === coordinate.executionInputRevision;
1045
+ }
1046
+ function requestMatchesEvidenceIdentity(request, evidence) {
1047
+ return (evidence.requestId === void 0 || evidence.requestId === request.requestId) && evidence.effectRunId === request.effectRunId;
1048
+ }
1049
+ function planRequestForCoordinate(state, coordinate) {
1050
+ for (const request of state.requestByRequestId.values()) {
1051
+ if (requestMatchesPlanCoordinate(request, coordinate)) return request;
1052
+ }
1053
+ return void 0;
1054
+ }
1055
+ function recordPlanResult(ctx, state, result) {
1056
+ const coordinate = planCoordinateFromResult(state, result);
1057
+ if (coordinate === void 0) {
1058
+ state.pendingResults.set(result.resultId, result);
1059
+ emitUnmatchedEvidence(ctx, state, `result:${result.resultId}`, void 0, {
1060
+ effectRunResultId: result.resultId,
1061
+ effectRunId: result.effectRunId
1062
+ });
1063
+ return false;
1064
+ }
1065
+ const key = requiredPlanKey(
1066
+ coordinate.workItemId,
1067
+ coordinate.planId,
1068
+ coordinate.executionInputRevision
1069
+ );
1070
+ const admitted = state.admitted.get(key);
1071
+ if (admitted === void 0) {
1072
+ state.pendingResults.set(result.resultId, result);
1073
+ emitUnmatchedEvidence(ctx, state, `result:${result.resultId}`, coordinate.workItemId, {
1074
+ effectRunResultId: result.resultId,
1075
+ effectRunId: result.effectRunId,
1076
+ planId: coordinate.planId,
1077
+ planMemberId: coordinate.planMemberId,
1078
+ executionInputRevision: coordinate.executionInputRevision
1079
+ });
1080
+ return false;
1081
+ }
1082
+ if (isAdmittedPlanStale(state, admitted)) {
1083
+ emitStaleAdmittedPlanOnce(ctx, state, admitted);
1084
+ return true;
1085
+ }
1086
+ if (!hasPlanMember(admitted, coordinate.planMemberId)) {
1087
+ emitUnknownPlanMember(ctx, state, admitted, coordinate.planMemberId, {
1088
+ effectRunResultId: result.resultId,
1089
+ effectRunId: result.effectRunId
1090
+ });
1091
+ return true;
1092
+ }
1093
+ const recorded = recordMemberEvidence(ctx, state, admitted, coordinate.planMemberId, {
1094
+ status: result.status,
1095
+ requestId: coordinate.request?.requestId,
1096
+ effectRunId: result.effectRunId,
1097
+ effectRunResultId: result.resultId,
1098
+ sourceRefs: result.sourceRefs
1099
+ });
1100
+ if (!recorded) return true;
1101
+ emitPlanStatus(ctx, state, {
1102
+ workItemId: coordinate.workItemId,
1103
+ planId: coordinate.planId,
1104
+ executionInputRevision: coordinate.executionInputRevision,
1105
+ state: result.status === "completed" ? "completed" : "failed",
1106
+ planMemberId: coordinate.planMemberId,
1107
+ requestId: coordinate.request?.requestId,
1108
+ effectRunId: result.effectRunId,
1109
+ effectRunResultId: result.resultId,
1110
+ sourceRefs: result.sourceRefs,
1111
+ metadata: { resultStatus: result.status }
1112
+ });
1113
+ return true;
1114
+ }
1115
+ function replayPendingPlanFacts(ctx, state) {
1116
+ let changed = false;
1117
+ for (const [evidenceId, evidence] of [...state.pendingEvidence]) {
1118
+ if (recordPlanEvidence(ctx, state, evidence)) {
1119
+ state.pendingEvidence.delete(evidenceId);
1120
+ changed = true;
1121
+ }
1122
+ }
1123
+ for (const [resultId, result] of [...state.pendingResults]) {
1124
+ if (recordPlanResult(ctx, state, result)) {
1125
+ state.pendingResults.delete(resultId);
1126
+ changed = true;
1127
+ }
1128
+ }
1129
+ return changed;
1130
+ }
1131
+ function planCoordinateFromEvidence(state, evidence) {
1132
+ const topLevelRequest = evidence.requestId === void 0 ? void 0 : state.requestByRequestId.get(evidence.requestId);
1133
+ const effectRunRequest = state.requestByEffectRun.get(evidence.effectRunId);
1134
+ if (evidence.planId !== void 0 && evidence.planMemberId !== void 0 && evidence.executionInputRevision !== void 0) {
1135
+ return {
1136
+ workItemId: evidence.workItemId,
1137
+ planId: evidence.planId,
1138
+ executionInputRevision: evidence.executionInputRevision,
1139
+ planMemberId: evidence.planMemberId,
1140
+ requestId: topLevelRequest?.requestId ?? effectRunRequest?.requestId ?? evidence.requestId,
1141
+ request: topLevelRequest ?? effectRunRequest
1142
+ };
1143
+ }
1144
+ const request = effectRunRequest;
1145
+ if (request?.planId !== void 0 && request.planMemberId !== void 0 && request.executionInputRevision !== void 0) {
1146
+ return {
1147
+ workItemId: request.workItemId,
1148
+ planId: request.planId,
1149
+ executionInputRevision: request.executionInputRevision,
1150
+ planMemberId: request.planMemberId,
1151
+ requestId: request.requestId,
1152
+ request
1153
+ };
1154
+ }
1155
+ const planId = stringMetadata(evidence.metadata, "planId");
1156
+ const planMemberId = stringMetadata(evidence.metadata, "planMemberId");
1157
+ const executionInputRevision = numberMetadata(evidence.metadata, "executionInputRevision");
1158
+ const requestId = stringMetadata(evidence.metadata, "requestId");
1159
+ if (planId === void 0 || planMemberId === void 0 || executionInputRevision === void 0)
1160
+ return void 0;
1161
+ return {
1162
+ workItemId: evidence.workItemId,
1163
+ planId,
1164
+ executionInputRevision,
1165
+ planMemberId,
1166
+ requestId
1167
+ };
1168
+ }
1169
+ function planCoordinateFromResult(state, result) {
1170
+ const request = state.requestByEffectRun.get(result.effectRunId);
1171
+ if (request?.planId !== void 0 && request.planMemberId !== void 0 && request.executionInputRevision !== void 0) {
1172
+ return {
1173
+ workItemId: request.workItemId,
1174
+ planId: request.planId,
1175
+ executionInputRevision: request.executionInputRevision,
1176
+ planMemberId: request.planMemberId,
1177
+ requestId: request.requestId,
1178
+ request
1179
+ };
1180
+ }
1181
+ const workItemId = sourceRefId(result.subjectRefs, "work-item") ?? sourceRefId(result.sourceRefs, "work-item");
1182
+ const planId = stringMetadata(result.metadata, "planId");
1183
+ const planMemberId = stringMetadata(result.metadata, "planMemberId");
1184
+ const executionInputRevision = numberMetadata(result.metadata, "executionInputRevision");
1185
+ if (workItemId === void 0 || planId === void 0 || planMemberId === void 0 || executionInputRevision === void 0)
1186
+ return void 0;
1187
+ return { workItemId, planId, executionInputRevision, planMemberId };
1188
+ }
1189
+ function recordMemberEvidence(ctx, state, admitted, planMemberId, evidence) {
1190
+ const coord = memberCoord(admitted, planMemberId);
1191
+ const existing = state.memberEvidence.get(coord);
1192
+ if (existing !== void 0) {
1193
+ const duplicateIssue = issue(
1194
+ "duplicate-suppressed",
1195
+ `WorkItemEffectPlan member '${planMemberId}' already has terminal evidence`,
1196
+ admitted.workItemId,
1197
+ {
1198
+ planId: admitted.planId,
1199
+ planMemberId,
1200
+ existingEvidenceId: existing.evidenceId,
1201
+ existingEffectRunResultId: existing.effectRunResultId,
1202
+ evidenceId: evidence.evidenceId,
1203
+ effectRunResultId: evidence.effectRunResultId
1204
+ }
1205
+ );
1206
+ emitPlan(ctx, "issue", duplicateIssue);
1207
+ emitPlanStatus(ctx, state, {
1208
+ workItemId: admitted.workItemId,
1209
+ planId: admitted.planId,
1210
+ executionInputRevision: admitted.executionInputRevision,
1211
+ state: "duplicate",
1212
+ planMemberId,
1213
+ requestId: evidence.requestId,
1214
+ effectRunId: evidence.effectRunId,
1215
+ evidenceId: evidence.evidenceId,
1216
+ effectRunResultId: evidence.effectRunResultId,
1217
+ issues: [duplicateIssue],
1218
+ sourceRefs: evidence.sourceRefs
1219
+ });
1220
+ return false;
1221
+ }
1222
+ state.memberEvidence.set(coord, evidence);
1223
+ return true;
1224
+ }
1225
+ function hasPlanMember(admitted, planMemberId) {
1226
+ return admitted.plan.members.some((member) => member.memberId === planMemberId);
1227
+ }
1228
+ function isAdmittedPlanStale(state, admitted) {
1229
+ const current = state.workItems.get(admitted.workItemId);
1230
+ return current !== void 0 && current.executionInputRevision !== admitted.executionInputRevision;
1231
+ }
1232
+ function emitStaleAdmittedPlanOnce(ctx, state, admitted) {
1233
+ const current = state.workItems.get(admitted.workItemId);
1234
+ emitPlanStatusOnce(ctx, state, `${memberCoord(admitted, "plan")}:stale`, {
1235
+ workItemId: admitted.workItemId,
1236
+ planId: admitted.planId,
1237
+ executionInputRevision: admitted.executionInputRevision,
1238
+ state: "stale",
1239
+ issues: [
1240
+ issue(
1241
+ "stale-execution-input",
1242
+ `WorkItemEffectPlan '${admitted.planId}' targets stale execution input`,
1243
+ admitted.workItemId,
1244
+ {
1245
+ planId: admitted.planId,
1246
+ proposedRevision: admitted.executionInputRevision,
1247
+ currentRevision: current?.executionInputRevision
1248
+ }
1249
+ )
1250
+ ],
1251
+ sourceRefs: admitted.sourceRefs,
1252
+ metadata: { currentRevision: current?.executionInputRevision }
1253
+ });
1254
+ }
1255
+ function emitUnknownPlanMember(ctx, state, admitted, planMemberId, metadata) {
1256
+ const item = issue(
1257
+ "dangling-ref",
1258
+ `WorkItemEffectPlan evidence/result references unknown member '${planMemberId}'`,
1259
+ admitted.workItemId,
1260
+ { planId: admitted.planId, planMemberId, ...metadata }
1261
+ );
1262
+ emitPlan(ctx, "issue", item);
1263
+ emitPlanStatus(ctx, state, {
1264
+ workItemId: admitted.workItemId,
1265
+ planId: admitted.planId,
1266
+ executionInputRevision: admitted.executionInputRevision,
1267
+ state: "rejected",
1268
+ planMemberId,
1269
+ issues: [item],
1270
+ sourceRefs: admitted.sourceRefs,
1271
+ metadata
1272
+ });
1273
+ }
1274
+ function emitUnmatchedEvidence(ctx, state, key, workItemId, metadata) {
1275
+ const seen = key.startsWith("evidence:") ? state.unmatchedEvidence : state.unmatchedResults;
1276
+ if (seen.has(key)) return;
1277
+ seen.add(key);
1278
+ const item = issue(
1279
+ "dangling-ref",
1280
+ "WorkItemEffectPlan evidence/result could not be joined to an admitted plan member",
1281
+ workItemId,
1282
+ metadata
1283
+ );
1284
+ emitPlan(ctx, "issue", item);
1285
+ emitPlanStatus(ctx, state, {
1286
+ workItemId: workItemId ?? "unknown",
1287
+ planId: typeof metadata.planId === "string" ? metadata.planId : "unknown",
1288
+ executionInputRevision: typeof metadata.executionInputRevision === "number" ? metadata.executionInputRevision : 0,
1289
+ state: "deferred",
1290
+ issues: [item],
1291
+ metadata
1292
+ });
1293
+ }
1294
+ function derivePlanResult(ctx, state, admitted) {
1295
+ const requiredMembers = admitted.plan.members.filter((member) => member.required !== false);
1296
+ if (requiredMembers.length === 0) return;
1297
+ const memberResults = [];
1298
+ for (const member of admitted.plan.members) {
1299
+ const evidence = state.memberEvidence.get(memberCoord(admitted, member.memberId));
1300
+ if (evidence === void 0) continue;
1301
+ memberResults.push({
1302
+ planMemberId: member.memberId,
1303
+ status: evidence.status,
1304
+ requestId: evidence.requestId,
1305
+ effectRunId: evidence.effectRunId,
1306
+ evidenceId: evidence.evidenceId,
1307
+ effectRunResultId: evidence.effectRunResultId
1308
+ });
1309
+ }
1310
+ const hasRequiredFailed = requiredMembers.some((member) => {
1311
+ const evidence = state.memberEvidence.get(memberCoord(admitted, member.memberId));
1312
+ return evidence !== void 0 && evidence.status !== "completed";
1313
+ });
1314
+ const settledRequiredCount = requiredMembers.filter(
1315
+ (member) => state.memberEvidence.has(memberCoord(admitted, member.memberId))
1316
+ ).length;
1317
+ const allRequiredSettled = settledRequiredCount === requiredMembers.length;
1318
+ const requiredBlockedByFailure = requiredMembers.some(
1319
+ (member) => memberBlockedByFailure(state, admitted, member.memberId, /* @__PURE__ */ new Set())
1320
+ );
1321
+ if (!hasRequiredFailed && !allRequiredSettled && !requiredBlockedByFailure) return;
1322
+ const status = admitted.plan.joinPolicy === "evidence-only" ? "evidence-only" : hasRequiredFailed || requiredBlockedByFailure ? "failed" : "succeeded";
1323
+ const key = memberCoord(admitted, "result");
1324
+ if (state.resultKeys.has(key)) return;
1325
+ state.resultKeys.add(key);
1326
+ const result = {
1327
+ kind: "work-item-effect-plan-result",
1328
+ resultId: `work-item-effect-plan-result:${admitted.workItemId}:${admitted.executionInputRevision}:${admitted.planId}`,
1329
+ workItemId: admitted.workItemId,
1330
+ planId: admitted.planId,
1331
+ executionInputRevision: admitted.executionInputRevision,
1332
+ status,
1333
+ memberResults,
1334
+ sourceRefs: admitted.sourceRefs
1335
+ };
1336
+ emitPlan(ctx, "result", result);
1337
+ emitPlanStatus(ctx, state, {
1338
+ workItemId: admitted.workItemId,
1339
+ planId: admitted.planId,
1340
+ executionInputRevision: admitted.executionInputRevision,
1341
+ state: status === "succeeded" || status === "evidence-only" ? "completed" : "failed",
1342
+ sourceRefs: admitted.sourceRefs,
1343
+ metadata: { resultId: result.resultId, resultStatus: status }
1344
+ });
1345
+ }
1346
+ function normalizeEffectPlanSnapshot(proposal, policy) {
1347
+ const joinPolicy = proposal.joinPolicy ?? policy?.joinPolicy ?? "all-required";
1348
+ const members = proposal.members.map(
1349
+ (member) => Object.freeze({
1350
+ ...member,
1351
+ goal: immutableClone(member.goal),
1352
+ dependsOnMemberIds: immutableClone(member.dependsOnMemberIds ?? []),
1353
+ contextRefs: immutableClone(member.contextRefs),
1354
+ requirements: immutableClone(member.requirements),
1355
+ capacityHints: immutableClone(member.capacityHints),
1356
+ limits: immutableClone(member.limits),
1357
+ policyRefs: immutableClone(member.policyRefs),
1358
+ sourceRefs: immutableClone(member.sourceRefs),
1359
+ metadata: immutableClone(member.metadata)
1360
+ })
1361
+ );
1362
+ return Object.freeze({
1363
+ planId: proposal.planId,
1364
+ workItemId: proposal.workItemId,
1365
+ executionInputRevision: proposal.executionInputRevision,
1366
+ members: Object.freeze(members),
1367
+ joinPolicy,
1368
+ limits: immutableClone(proposal.limits),
1369
+ policyRefs: immutableClone(proposal.policyRefs),
1370
+ sourceRefs: immutableClone(proposal.sourceRefs),
1371
+ metadata: immutableClone(proposal.metadata)
1372
+ });
1373
+ }
1374
+ function requestFromPlanMember(admitted, member, policy) {
1375
+ const requestId = `work-item:${admitted.workItemId}:effect-plan:${admitted.executionInputRevision}:${admitted.planId}:${member.memberId}`;
1376
+ const policyRefs = policy?.policyId === void 0 ? [...admitted.plan.policyRefs ?? [], ...member.policyRefs ?? []] : [
1377
+ ...admitted.plan.policyRefs ?? [],
1378
+ ...member.policyRefs ?? [],
1379
+ ref("work-item-effect-plan-policy", policy.policyId)
1380
+ ];
1381
+ return {
1382
+ kind: "work-item-effect-requested",
1383
+ requestId,
1384
+ workItemId: admitted.workItemId,
1385
+ effectRunId: `effect-run:${requestId}`,
1386
+ effectKind: member.effectKind,
1387
+ executionInputRevision: admitted.executionInputRevision,
1388
+ planId: admitted.planId,
1389
+ planMemberId: member.memberId,
1390
+ sourceRefs: [
1391
+ ref("work-item", admitted.workItemId),
1392
+ ref("work-item-revision", `${admitted.workItemId}:${admitted.executionInputRevision}`),
1393
+ ref("work-item-effect-plan", admitted.planId),
1394
+ ref("work-item-effect-plan-member", member.memberId),
1395
+ ...admitted.plan.sourceRefs ?? [],
1396
+ ...member.sourceRefs ?? []
1397
+ ],
1398
+ goal: member.goal,
1399
+ policyRefs: policyRefs.length === 0 ? void 0 : policyRefs,
1400
+ limits: member.limits ?? admitted.plan.limits,
1401
+ idempotencyKey: member.idempotencyKey ?? `${admitted.workItemId}:effect-plan:${admitted.executionInputRevision}:${admitted.planId}:${member.memberId}`,
1402
+ metadata: {
1403
+ ...member.metadata ?? {},
1404
+ executionInputRevision: admitted.executionInputRevision,
1405
+ planId: admitted.planId,
1406
+ planMemberId: member.memberId,
1407
+ ...member.contextRefs === void 0 ? {} : { contextRefs: member.contextRefs },
1408
+ ...member.requirements === void 0 ? {} : { requirements: member.requirements },
1409
+ ...member.capacityHints === void 0 ? {} : { capacityHints: member.capacityHints }
1410
+ }
1411
+ };
1412
+ }
1413
+ function immutableClone(value) {
1414
+ if (Array.isArray(value)) return Object.freeze(value.map((item) => immutableClone(item)));
1415
+ if (!isRecord(value)) return value;
1416
+ const out = {};
1417
+ for (const [key, child] of Object.entries(value)) out[key] = immutableClone(child);
1418
+ return Object.freeze(out);
1419
+ }
1420
+ function stringMetadata(metadata, key) {
1421
+ const value = metadata?.[key];
1422
+ return typeof value === "string" && value !== "" ? value : void 0;
1423
+ }
1424
+ function numberMetadata(metadata, key) {
1425
+ const value = metadata?.[key];
1426
+ return typeof value === "number" ? value : void 0;
1427
+ }
1428
+ function sourceRefId(refs2, kind) {
1429
+ return refs2?.find((sourceRef) => sourceRef.kind === kind)?.id;
1430
+ }
1431
+ function memberSucceeded(state, admitted, memberId) {
1432
+ return state.memberEvidence.get(memberCoord(admitted, memberId))?.status === "completed";
1433
+ }
1434
+ function memberBlockedByFailure(state, admitted, memberId, seen) {
1435
+ if (seen.has(memberId)) return false;
1436
+ seen.add(memberId);
1437
+ const evidence = state.memberEvidence.get(memberCoord(admitted, memberId));
1438
+ if (evidence !== void 0) return evidence.status !== "completed";
1439
+ const member = admitted.plan.members.find((item) => item.memberId === memberId);
1440
+ return (member?.dependsOnMemberIds ?? []).some(
1441
+ (depId) => memberBlockedByFailure(state, admitted, depId, seen)
1442
+ );
1443
+ }
1444
+ function memberCoord(admitted, memberId) {
1445
+ return `${admitted.workItemId}:${admitted.executionInputRevision}:${admitted.planId}:${memberId}`;
1446
+ }
1447
+ function planKey(workItemId, planId, executionInputRevision) {
1448
+ if (workItemId === void 0 || planId === void 0 || executionInputRevision === void 0)
1449
+ return void 0;
1450
+ return `${workItemId}:${executionInputRevision}:${planId}`;
1451
+ }
1452
+ function requiredPlanKey(workItemId, planId, executionInputRevision) {
1453
+ return `${workItemId}:${executionInputRevision}:${planId}`;
1454
+ }
1455
+ function emitPlanIssues(ctx, state, issues) {
1456
+ for (const item of issues) emitPlan(ctx, "issue", item);
1457
+ if (issues.length > 0) {
1458
+ state.auditSeq += 1;
1459
+ emitPlan(ctx, "audit", {
1460
+ id: `work-item-effect-plan-issue:${state.auditSeq}`,
1461
+ kind: "work-item-effect-plan-issue",
1462
+ subjectId: issues[0]?.subjectId,
1463
+ message: issues[0]?.message,
1464
+ issueCode: issues[0]?.code,
1465
+ metadata: { issueCodes: issues.map((item) => item.code) }
1466
+ });
1467
+ }
1468
+ }
1469
+ function emitPlanStatusOnce(ctx, state, key, status) {
1470
+ if (state.statusKeys.has(key)) return;
1471
+ state.statusKeys.add(key);
1472
+ emitPlanStatus(ctx, state, status);
1473
+ }
1474
+ function emitPlanStatus(ctx, state, status) {
1475
+ state.statusSeq += 1;
1476
+ const statusFact = {
1477
+ kind: "work-item-effect-plan-status",
1478
+ statusId: `work-item-effect-plan-status:${state.statusSeq}`,
1479
+ ...status
1480
+ };
1481
+ emitPlan(ctx, "status", statusFact);
1482
+ state.auditSeq += 1;
1483
+ emitPlan(ctx, "audit", {
1484
+ id: `work-item-effect-plan-status:${state.auditSeq}`,
1485
+ kind: "work-item-effect-plan-status",
1486
+ subjectId: status.workItemId,
1487
+ message: status.message,
1488
+ sourceRefs: status.sourceRefs,
1489
+ metadata: {
1490
+ statusId: statusFact.statusId,
1491
+ state: status.state,
1492
+ planId: status.planId,
1493
+ planMemberId: status.planMemberId,
1494
+ executionInputRevision: status.executionInputRevision,
1495
+ ...status.metadata ?? {}
1496
+ }
1497
+ });
1498
+ }
1499
+ function emitPlan(ctx, kind, value) {
1500
+ ctx.down([["DATA", { kind, value }]]);
1501
+ }
1502
+ function isWorkItemEffectPlanJoinPolicy(value) {
1503
+ return value === "all-required" || value === "evidence-only";
1504
+ }
1505
+ function findPlanCycle(members) {
1506
+ const byId = new Map(members.map((member) => [member.memberId, member.dependsOnMemberIds ?? []]));
1507
+ const visiting = /* @__PURE__ */ new Set();
1508
+ const visited = /* @__PURE__ */ new Set();
1509
+ const stack = [];
1510
+ const visit = (id) => {
1511
+ if (visiting.has(id)) return [...stack.slice(stack.indexOf(id)), id];
1512
+ if (visited.has(id)) return void 0;
1513
+ visiting.add(id);
1514
+ stack.push(id);
1515
+ for (const dep of byId.get(id) ?? []) {
1516
+ if (!byId.has(dep)) continue;
1517
+ const cycle = visit(dep);
1518
+ if (cycle !== void 0) return cycle;
1519
+ }
1520
+ stack.pop();
1521
+ visiting.delete(id);
1522
+ visited.add(id);
1523
+ return void 0;
1524
+ };
1525
+ for (const member of members) {
1526
+ const cycle = visit(member.memberId);
1527
+ if (cycle !== void 0) return cycle;
1528
+ }
1529
+ return void 0;
1530
+ }
1531
+ function reduceAuthoring(ctx, state, input, policy) {
1532
+ if (input.kind === "work-item-spawn-proposed") {
1533
+ const issues2 = validateWorkItemDraft(input.draft, { workItemId: input.parentWorkItemId });
1534
+ if (issues2.length > 0) {
1535
+ for (const item of issues2) emit(ctx, "issue", item);
1536
+ emitStatus(ctx, state, {
1537
+ state: "rejected",
1538
+ code: issues2[0]?.code,
1539
+ workItemId: input.parentWorkItemId,
1540
+ message: issues2[0]?.message,
1541
+ metadata: { proposalId: input.proposalId }
1542
+ });
1543
+ return;
1544
+ }
1545
+ emitStatus(ctx, state, {
1546
+ state: "deferred",
1547
+ workItemId: input.parentWorkItemId,
1548
+ message: `WorkItem spawn proposal '${input.proposalId}' carries draft data but is not applied`,
1549
+ metadata: { proposalId: input.proposalId }
1550
+ });
1551
+ return;
1552
+ }
1553
+ if (state.seenEvents.has(input.eventId)) {
1554
+ emit(
1555
+ ctx,
1556
+ "issue",
1557
+ issue("duplicate-id", `Duplicate WorkItem authoring id '${input.eventId}'`, input.workItemId)
1558
+ );
1559
+ return;
1560
+ }
1561
+ state.seenEvents.add(input.eventId);
1562
+ if (input.kind === "work-item-created") {
1563
+ if (state.workItems.has(input.workItemId)) {
1564
+ emit(
1565
+ ctx,
1566
+ "issue",
1567
+ issue("duplicate-id", `Duplicate WorkItem '${input.workItemId}'`, input.workItemId)
1568
+ );
1569
+ emitStatus(ctx, state, {
1570
+ state: "duplicate",
1571
+ code: "duplicate-id",
1572
+ workItemId: input.workItemId,
1573
+ metadata: { eventId: input.eventId }
1574
+ });
1575
+ return;
1576
+ }
1577
+ const issues2 = validateWorkItemDraft(input.draft, { workItemId: input.workItemId });
1578
+ if (issues2.length > 0) {
1579
+ reject(ctx, state, input.workItemId, issues2);
1580
+ return;
1581
+ }
1582
+ const projection = {
1583
+ ...input.draft,
1584
+ verificationPlan: normalizePlan(input.draft),
1585
+ workItemId: input.workItemId,
1586
+ authoringRevision: 1,
1587
+ executionInputRevision: 1,
1588
+ lastEventId: input.eventId,
1589
+ revisionSourceRefs: refs("work-item-authoring-fact", input.eventId, input.sourceRefs),
1590
+ createdAtMs: input.createdAtMs,
1591
+ updatedAtMs: input.createdAtMs
1592
+ };
1593
+ accept(ctx, state, projection);
1594
+ return;
1595
+ }
1596
+ const existing = state.workItems.get(input.workItemId);
1597
+ if (existing === void 0) {
1598
+ emit(
1599
+ ctx,
1600
+ "issue",
1601
+ issue(
1602
+ "dangling-ref",
1603
+ `Authoring fact '${input.eventId}' references unknown WorkItem '${input.workItemId}'`,
1604
+ input.workItemId
1605
+ )
1606
+ );
1607
+ return;
1608
+ }
1609
+ if (input.kind === "work-item-patched") {
1610
+ if (!isRecord(input.patch)) {
1611
+ reject(ctx, state, input.workItemId, [
1612
+ issue("invalid-patch", "WorkItemPatch must be an object", input.workItemId)
1613
+ ]);
1614
+ return;
1615
+ }
1616
+ const invalidKeys = Object.keys(input.patch).filter((key) => !draftPatchKeys.has(key));
1617
+ if (invalidKeys.length > 0) {
1618
+ reject(ctx, state, input.workItemId, [
1619
+ issue(
1620
+ "invalid-patch",
1621
+ `WorkItemPatch contains unsupported keys: ${invalidKeys.join(", ")}`,
1622
+ input.workItemId,
1623
+ {
1624
+ invalidKeys
1625
+ }
1626
+ )
1627
+ ]);
1628
+ return;
1629
+ }
1630
+ const draft = applyDraftPatch(existing, input.patch);
1631
+ const issues2 = validateWorkItemDraft(draft, { workItemId: input.workItemId });
1632
+ if (issues2.length > 0) {
1633
+ reject(ctx, state, input.workItemId, issues2);
1634
+ return;
1635
+ }
1636
+ const touched = touchesExecutionRelevant(
1637
+ input.patch,
1638
+ executionRelevant(policy, input.executionRelevantFields)
1639
+ );
1640
+ accept(ctx, state, {
1641
+ ...existing,
1642
+ ...draft,
1643
+ authoringRevision: existing.authoringRevision + 1,
1644
+ executionInputRevision: touched ? existing.executionInputRevision + 1 : existing.executionInputRevision,
1645
+ lastEventId: input.eventId,
1646
+ revisionSourceRefs: refs("work-item-authoring-fact", input.eventId, input.sourceRefs),
1647
+ updatedAtMs: input.patchedAtMs
1648
+ });
1649
+ return;
1650
+ }
1651
+ if (input.kind === "acceptance-criteria-changed") {
1652
+ const issues2 = validateAcceptanceCriteria(input.acceptanceCriteria, {
1653
+ workItemId: input.workItemId
1654
+ });
1655
+ if (issues2.length > 0) {
1656
+ reject(ctx, state, input.workItemId, issues2);
1657
+ return;
1658
+ }
1659
+ accept(ctx, state, {
1660
+ ...existing,
1661
+ acceptanceCriteria: input.acceptanceCriteria,
1662
+ authoringRevision: existing.authoringRevision + 1,
1663
+ executionInputRevision: existing.executionInputRevision + 1,
1664
+ lastEventId: input.eventId,
1665
+ revisionSourceRefs: refs("work-item-authoring-fact", input.eventId, input.sourceRefs),
1666
+ updatedAtMs: input.changedAtMs
1667
+ });
1668
+ return;
1669
+ }
1670
+ const issues = validateVerificationPlan(
1671
+ input.verificationPlan,
1672
+ existing.acceptanceCriteria ?? [],
1673
+ { workItemId: input.workItemId }
1674
+ );
1675
+ if (issues.length > 0) {
1676
+ reject(ctx, state, input.workItemId, issues);
1677
+ return;
1678
+ }
1679
+ accept(ctx, state, {
1680
+ ...existing,
1681
+ verificationPlan: input.verificationPlan,
1682
+ verificationSteps: input.verificationPlan.steps,
1683
+ authoringRevision: existing.authoringRevision + 1,
1684
+ executionInputRevision: existing.executionInputRevision + 1,
1685
+ lastEventId: input.eventId,
1686
+ revisionSourceRefs: refs("work-item-authoring-fact", input.eventId, input.sourceRefs),
1687
+ updatedAtMs: input.changedAtMs
1688
+ });
1689
+ }
1690
+ function lowerPlan(ctx, state, workItem, policy) {
1691
+ const plan = normalizePlan(workItem);
1692
+ if (plan === void 0) {
1693
+ emitRequestStatus(ctx, state, {
1694
+ state: "needs-human-review",
1695
+ code: "verification-unplanned",
1696
+ workItemId: workItem.workItemId
1697
+ });
1698
+ return;
1699
+ }
1700
+ const issues = validateVerificationPlan(plan, workItem.acceptanceCriteria ?? [], {
1701
+ workItemId: workItem.workItemId,
1702
+ allowedModes: policy?.allowedModes,
1703
+ allowedEffectKinds: policy?.allowedEffectKinds
1704
+ });
1705
+ if (issues.length > 0) {
1706
+ for (const item of issues) emit(ctx, "issue", item);
1707
+ return;
1708
+ }
1709
+ if (policy?.autoRun === false) {
1710
+ emitRequestStatus(ctx, state, {
1711
+ state: "deferred",
1712
+ code: "policy-mismatch",
1713
+ workItemId: workItem.workItemId,
1714
+ revision: workItem.authoringRevision,
1715
+ executionInputRevision: workItem.executionInputRevision,
1716
+ metadata: { policyId: policy.policyId, reason: "auto-run-disabled" }
1717
+ });
1718
+ return;
1719
+ }
1720
+ for (const step of plan.steps) {
1721
+ if (isStepSatisfied(state, workItem, step.stepId)) {
1722
+ emitRequestStatus(ctx, state, {
1723
+ state: "duplicate",
1724
+ code: "duplicate-suppressed",
1725
+ workItemId: workItem.workItemId,
1726
+ revision: workItem.authoringRevision,
1727
+ executionInputRevision: workItem.executionInputRevision,
1728
+ stepId: step.stepId,
1729
+ message: `Verification step '${step.stepId}' already has valid evidence`
1730
+ });
1731
+ continue;
1732
+ }
1733
+ if (step.mode === "manual") {
1734
+ emitRequestStatus(ctx, state, {
1735
+ state: "needs-human-review",
1736
+ code: "manual-review-required",
1737
+ workItemId: workItem.workItemId,
1738
+ stepId: step.stepId
1739
+ });
1740
+ continue;
1741
+ }
1742
+ const missingPrerequisites = (step.dependsOnStepIds ?? []).filter(
1743
+ (stepId) => !isStepSatisfied(state, workItem, stepId)
1744
+ );
1745
+ if (missingPrerequisites.length > 0) {
1746
+ emitRequestStatus(ctx, state, {
1747
+ state: "blocked",
1748
+ code: "blocked-prerequisite",
1749
+ workItemId: workItem.workItemId,
1750
+ stepId: step.stepId,
1751
+ metadata: { missingStepIds: missingPrerequisites }
1752
+ });
1753
+ continue;
1754
+ }
1755
+ emitRequest(ctx, state, requestFromStep(workItem, plan, step, policy));
1756
+ }
1757
+ }
1758
+ function lowerIntent(ctx, state, intent, policy) {
1759
+ const workItem = state.workItems.get(intent.workItemId);
1760
+ if (workItem === void 0) {
1761
+ emit(
1762
+ ctx,
1763
+ "issue",
1764
+ issue(
1765
+ "dangling-ref",
1766
+ `Dispatch intent '${intent.intentId}' references unknown WorkItem '${intent.workItemId}'`,
1767
+ intent.workItemId
1768
+ )
1769
+ );
1770
+ return;
1771
+ }
1772
+ if (intent.executionInputRevision !== workItem.executionInputRevision) {
1773
+ emit(
1774
+ ctx,
1775
+ "issue",
1776
+ issue(
1777
+ "stale-execution-input",
1778
+ `Dispatch intent '${intent.intentId}' targets stale execution input`,
1779
+ intent.workItemId,
1780
+ {
1781
+ intentRevision: intent.executionInputRevision,
1782
+ currentRevision: workItem.executionInputRevision,
1783
+ stalePolicy: policy?.stalePolicy ?? "review"
1784
+ }
1785
+ )
1786
+ );
1787
+ emitRequestStatus(ctx, state, {
1788
+ state: "stale",
1789
+ code: "stale-execution-input",
1790
+ workItemId: intent.workItemId,
1791
+ executionInputRevision: workItem.executionInputRevision,
1792
+ metadata: { intentId: intent.intentId }
1793
+ });
1794
+ return;
1795
+ }
1796
+ const effectKind = intent.effectKind ?? intent.targetKind;
1797
+ const allowedEffectKinds = new Set(policy?.allowedEffectKinds ?? ["verification"]);
1798
+ if (!allowedEffectKinds.has(effectKind)) {
1799
+ emit(
1800
+ ctx,
1801
+ "issue",
1802
+ issue(
1803
+ "unsupported-effect-kind",
1804
+ `Dispatch intent '${intent.intentId}' targets unsupported effect kind '${effectKind}'`,
1805
+ intent.workItemId,
1806
+ { intentId: intent.intentId, effectKind }
1807
+ )
1808
+ );
1809
+ emitRequestStatus(ctx, state, {
1810
+ state: "rejected",
1811
+ code: "unsupported-effect-kind",
1812
+ workItemId: intent.workItemId,
1813
+ executionInputRevision: workItem.executionInputRevision,
1814
+ metadata: { intentId: intent.intentId, effectKind }
1815
+ });
1816
+ return;
1817
+ }
1818
+ emitRequest(ctx, state, requestFromIntent(workItem, intent));
1819
+ }
1820
+ function recordVerificationResult(ctx, state, result, policy) {
1821
+ if (result.status !== "passed") return;
1822
+ const workItem = state.workItems.get(result.workItemId);
1823
+ if (workItem === void 0) {
1824
+ emit(
1825
+ ctx,
1826
+ "issue",
1827
+ issue(
1828
+ "dangling-ref",
1829
+ `Verification result '${result.resultId}' references unknown WorkItem '${result.workItemId}'`,
1830
+ result.workItemId
1831
+ )
1832
+ );
1833
+ return;
1834
+ }
1835
+ if (result.executionInputRevision !== workItem.executionInputRevision) {
1836
+ emit(
1837
+ ctx,
1838
+ "issue",
1839
+ issue(
1840
+ "stale-revision",
1841
+ `Verification result '${result.resultId}' targets stale execution input`,
1842
+ result.workItemId
1843
+ )
1844
+ );
1845
+ return;
1846
+ }
1847
+ const key = revisionKey(result.workItemId, result.executionInputRevision);
1848
+ const passedSteps = state.passedSteps.get(key) ?? /* @__PURE__ */ new Set();
1849
+ for (const stepId of result.verificationStepIds) passedSteps.add(stepId);
1850
+ state.passedSteps.set(key, passedSteps);
1851
+ lowerPlan(ctx, state, workItem, policy);
1852
+ }
1853
+ function mapEvidence(ctx, state, evidence, replay = false) {
1854
+ if (!replay && state.evidenceById.has(evidence.evidenceId)) {
1855
+ emit(
1856
+ ctx,
1857
+ "issue",
1858
+ issue(
1859
+ "duplicate-suppressed",
1860
+ `Duplicate evidence '${evidence.evidenceId}'`,
1861
+ evidence.workItemId
1862
+ )
1863
+ );
1864
+ return;
1865
+ }
1866
+ state.evidenceById.set(evidence.evidenceId, evidence);
1867
+ const workItem = state.workItems.get(evidence.workItemId);
1868
+ if (workItem === void 0) {
1869
+ emit(
1870
+ ctx,
1871
+ "issue",
1872
+ issue(
1873
+ "dangling-ref",
1874
+ `Evidence '${evidence.evidenceId}' references unknown WorkItem '${evidence.workItemId}'`,
1875
+ evidence.workItemId
1876
+ )
1877
+ );
1878
+ return;
1879
+ }
1880
+ const revision = typeof evidence.metadata?.executionInputRevision === "number" ? evidence.metadata.executionInputRevision : void 0;
1881
+ if (revision !== workItem.executionInputRevision) {
1882
+ emit(
1883
+ ctx,
1884
+ "issue",
1885
+ issue(
1886
+ "stale-revision",
1887
+ `Evidence '${evidence.evidenceId}' targets stale revision`,
1888
+ evidence.workItemId
1889
+ )
1890
+ );
1891
+ emitResultStatus(ctx, state, {
1892
+ state: "stale",
1893
+ code: "stale-revision",
1894
+ workItemId: evidence.workItemId,
1895
+ executionInputRevision: workItem.executionInputRevision
1896
+ });
1897
+ return;
1898
+ }
1899
+ const stepIds = stringArray(evidence.metadata?.verificationStepIds);
1900
+ const criterionIds = stringArray(evidence.metadata?.acceptanceCriterionIds);
1901
+ if (stepIds.length === 0 || criterionIds.length === 0) {
1902
+ emit(
1903
+ ctx,
1904
+ "issue",
1905
+ issue(
1906
+ "ambiguous-coverage",
1907
+ `Evidence '${evidence.evidenceId}' lacks coverage refs`,
1908
+ evidence.workItemId
1909
+ )
1910
+ );
1911
+ return;
1912
+ }
1913
+ const coverageIssue = validateEvidenceCoverage(workItem, stepIds, criterionIds);
1914
+ if (coverageIssue !== void 0) {
1915
+ emit(ctx, "issue", {
1916
+ ...coverageIssue,
1917
+ message: `Evidence '${evidence.evidenceId}' has invalid verification coverage: ${coverageIssue.message}`
1918
+ });
1919
+ emitResultStatus(ctx, state, {
1920
+ state: "rejected",
1921
+ code: coverageIssue.code,
1922
+ workItemId: evidence.workItemId,
1923
+ executionInputRevision: workItem.executionInputRevision,
1924
+ metadata: { evidenceId: evidence.evidenceId }
1925
+ });
1926
+ return;
1927
+ }
1928
+ const result = {
1929
+ kind: "verification-result-recorded",
1930
+ resultId: `verification-result:${evidence.evidenceId}`,
1931
+ workItemId: evidence.workItemId,
1932
+ evidenceId: evidence.evidenceId,
1933
+ effectRunId: evidence.effectRunId,
1934
+ effectRunResultId: evidence.effectRunResultId,
1935
+ executionInputRevision: revision,
1936
+ verificationStepIds: stepIds,
1937
+ acceptanceCriterionIds: criterionIds,
1938
+ status: resultStatus(evidence.status),
1939
+ output: evidence.output,
1940
+ error: evidence.error,
1941
+ reason: evidence.reason,
1942
+ sourceRefs: evidence.sourceRefs,
1943
+ recordedAtMs: evidence.recordedAtMs,
1944
+ metadata: evidence.metadata
1945
+ };
1946
+ if (!state.resultEvidence.has(evidence.evidenceId)) {
1947
+ state.resultEvidence.add(evidence.evidenceId);
1948
+ emit(ctx, "result", result);
1949
+ emitResultStatus(ctx, state, {
1950
+ state: "result-recorded",
1951
+ workItemId: evidence.workItemId,
1952
+ executionInputRevision: revision,
1953
+ metadata: { resultId: result.resultId }
1954
+ });
1955
+ }
1956
+ const policyIds = [
1957
+ ...new Set(
1958
+ (evidence.sourceRefs ?? []).filter((sourceRef) => sourceRef.kind === "work-item-verification-mapping-policy").map((sourceRef) => sourceRef.id)
1959
+ )
1960
+ ];
1961
+ if (policyIds.length === 0) return;
1962
+ for (const policyId of policyIds) {
1963
+ const policy = state.policies.get(policyId);
1964
+ if (policy === void 0) {
1965
+ if (!replay) {
1966
+ emit(
1967
+ ctx,
1968
+ "issue",
1969
+ issue(
1970
+ "missing-policy",
1971
+ `Missing verification mapping policy '${policyId}'`,
1972
+ evidence.workItemId,
1973
+ { policyId }
1974
+ )
1975
+ );
1976
+ emitResultStatus(ctx, state, {
1977
+ state: "deferred",
1978
+ code: "missing-policy",
1979
+ workItemId: evidence.workItemId,
1980
+ executionInputRevision: revision,
1981
+ metadata: { evidenceId: evidence.evidenceId, policyId }
1982
+ });
1983
+ }
1984
+ continue;
1985
+ }
1986
+ for (const [index, spec] of (policy.actionProposals ?? []).entries()) {
1987
+ if (spec.behavior !== void 0 && spec.behavior !== "propose") {
1988
+ emit(ctx, "issue", actionProposalIssue(policy, spec, evidence, "unsupported behavior"));
1989
+ continue;
1990
+ }
1991
+ if (spec.actionKind.length === 0) {
1992
+ emit(ctx, "issue", actionProposalIssue(policy, spec, evidence, "empty actionKind"));
1993
+ continue;
1994
+ }
1995
+ if (spec.statuses !== void 0 && !spec.statuses.includes(evidence.status)) continue;
1996
+ const outputKind = evidence.output?.kind;
1997
+ if (spec.outputKinds !== void 0 && (outputKind === void 0 || !spec.outputKinds.includes(outputKind)))
1998
+ continue;
1999
+ const proposalKey = `${evidence.evidenceId}:${policy.policyId}:${index}:${spec.actionKind}`;
2000
+ if (state.proposalKeys.has(proposalKey)) continue;
2001
+ state.proposalKeys.add(proposalKey);
2002
+ emit(ctx, "proposal", {
2003
+ kind: "work-item-domain-action-proposal",
2004
+ proposalId: `verification:${result.resultId}:${policy.policyId}:${index}:${spec.actionKind}`,
2005
+ workItemId: result.workItemId,
2006
+ actionKind: spec.actionKind,
2007
+ effectRunId: result.effectRunId,
2008
+ effectRunResultId: result.effectRunResultId,
2009
+ evidenceId: result.evidenceId,
2010
+ policyId: policy.policyId,
2011
+ payload: actionProposalPayload(spec, evidence, result),
2012
+ reason: spec.reason ?? evidence.reason,
2013
+ sourceRefs: [
2014
+ ref("work-item-evidence", evidence.evidenceId),
2015
+ ref("verification-result", result.resultId),
2016
+ ref("effect-run-result", result.effectRunResultId),
2017
+ ref("work-item-verification-mapping-policy", policy.policyId)
2018
+ ],
2019
+ metadata: {
2020
+ ...policy.metadata ?? {},
2021
+ ...spec.metadata ?? {},
2022
+ resultStatus: evidence.status
2023
+ }
2024
+ });
2025
+ emitResultStatus(ctx, state, {
2026
+ state: "domain-action-proposed",
2027
+ workItemId: evidence.workItemId,
2028
+ executionInputRevision: revision,
2029
+ metadata: { actionKind: spec.actionKind, policyId: policy.policyId }
2030
+ });
2031
+ }
2032
+ }
2033
+ }
2034
+ function requestFromStep(workItem, plan, step, policy) {
2035
+ const requestId = `work-item:${workItem.workItemId}:verification:${workItem.executionInputRevision}:${plan.planId}:${step.stepId}`;
2036
+ const effectKind = step.effectKind ?? "verification";
2037
+ const criterionIds = step.verifiesCriteriaIds ?? (workItem.acceptanceCriteria ?? []).map((criterion) => criterion.criterionId);
2038
+ const goal = goalWithInlineInput(
2039
+ step.goal ?? { kind: effectKind, summary: step.title ?? workItem.summary },
2040
+ step.input,
2041
+ `verification-step:${step.stepId}:input`,
2042
+ effectKind,
2043
+ step.contextRefs
2044
+ );
2045
+ return {
2046
+ kind: "work-item-effect-requested",
2047
+ requestId,
2048
+ workItemId: workItem.workItemId,
2049
+ effectRunId: `effect-run:${requestId}`,
2050
+ effectKind,
2051
+ executionInputRevision: workItem.executionInputRevision,
2052
+ sourceRefs: [
2053
+ ref("work-item", workItem.workItemId),
2054
+ ref("work-item-revision", `${workItem.workItemId}:${workItem.executionInputRevision}`),
2055
+ ref("verification-plan", plan.planId),
2056
+ ref("verification-step", step.stepId),
2057
+ ...plan.sourceRefs ?? [],
2058
+ ...step.sourceRefs ?? []
2059
+ ],
2060
+ goal,
2061
+ policyRefs: policy?.policyId === void 0 ? step.policyRefs : [
2062
+ ...step.policyRefs ?? [],
2063
+ ref("work-item-verification-lowerer-policy", policy.policyId)
2064
+ ],
2065
+ idempotencyKey: `${workItem.workItemId}:verification:${workItem.executionInputRevision}:${plan.planId}:${step.stepId}`,
2066
+ metadata: {
2067
+ ...step.metadata ?? {},
2068
+ executionInputRevision: workItem.executionInputRevision,
2069
+ verificationPlanId: plan.planId,
2070
+ verificationStepIds: [step.stepId],
2071
+ acceptanceCriterionIds: criterionIds,
2072
+ ...step.contextRefs === void 0 ? {} : { contextRefs: step.contextRefs },
2073
+ ...step.requirements === void 0 ? {} : { requirements: step.requirements },
2074
+ ...step.capacityHints === void 0 ? {} : { capacityHints: step.capacityHints }
2075
+ }
2076
+ };
2077
+ }
2078
+ function requestFromIntent(workItem, intent) {
2079
+ const requestId = `work-item:${workItem.workItemId}:dispatch:${workItem.executionInputRevision}:${intent.intentId}`;
2080
+ const effectKind = intent.effectKind ?? intent.targetKind;
2081
+ return {
2082
+ kind: "work-item-effect-requested",
2083
+ requestId,
2084
+ workItemId: workItem.workItemId,
2085
+ effectRunId: `effect-run:${requestId}`,
2086
+ effectKind,
2087
+ executionInputRevision: workItem.executionInputRevision,
2088
+ sourceRefs: [
2089
+ ref("work-item", workItem.workItemId),
2090
+ ref("work-item-dispatch-intent", intent.intentId),
2091
+ ...intent.sourceRefs ?? []
2092
+ ],
2093
+ goal: intent.goal ?? { kind: effectKind, summary: intent.reason ?? workItem.summary },
2094
+ policyRefs: intent.policyRefs,
2095
+ limits: intent.limits,
2096
+ idempotencyKey: intent.idempotencyKey ?? `${workItem.workItemId}:dispatch:${workItem.executionInputRevision}:${intent.intentId}`,
2097
+ metadata: {
2098
+ ...intent.metadata ?? {},
2099
+ executionInputRevision: workItem.executionInputRevision,
2100
+ verificationStepIds: intent.stepIds ?? [],
2101
+ acceptanceCriterionIds: intent.acceptanceCriterionIds ?? [],
2102
+ ...intent.contextRefs === void 0 ? {} : { contextRefs: intent.contextRefs },
2103
+ ...intent.requirements === void 0 ? {} : { requirements: intent.requirements },
2104
+ ...intent.capacityHints === void 0 ? {} : { capacityHints: intent.capacityHints }
2105
+ }
2106
+ };
2107
+ }
2108
+ function accept(ctx, state, projection) {
2109
+ state.workItems.set(projection.workItemId, projection);
2110
+ emit(ctx, "work-item", projection);
2111
+ emitStatus(ctx, state, {
2112
+ state: "projected",
2113
+ workItemId: projection.workItemId,
2114
+ revision: projection.authoringRevision,
2115
+ executionInputRevision: projection.executionInputRevision,
2116
+ metadata: { lastEventId: projection.lastEventId }
2117
+ });
2118
+ }
2119
+ function reject(ctx, state, workItemId, issues) {
2120
+ for (const item of issues) emit(ctx, "issue", item);
2121
+ emitStatus(ctx, state, {
2122
+ state: "rejected",
2123
+ code: issues[0]?.code,
2124
+ workItemId,
2125
+ message: issues[0]?.message
2126
+ });
2127
+ }
2128
+ function emitRequest(ctx, state, request) {
2129
+ const key = request.idempotencyKey ?? request.requestId;
2130
+ if (state.emittedKeys.has(key)) {
2131
+ emitRequestStatus(ctx, state, {
2132
+ state: "duplicate",
2133
+ code: "duplicate-suppressed",
2134
+ workItemId: request.workItemId,
2135
+ metadata: { requestId: request.requestId }
2136
+ });
2137
+ return;
2138
+ }
2139
+ state.emittedKeys.add(key);
2140
+ emit(ctx, "request", request);
2141
+ emitRequestStatus(ctx, state, {
2142
+ state: "request-emitted",
2143
+ workItemId: request.workItemId,
2144
+ executionInputRevision: request.executionInputRevision ?? request.metadata?.executionInputRevision,
2145
+ metadata: { requestId: request.requestId }
2146
+ });
2147
+ }
2148
+ function emitStatus(ctx, state, status) {
2149
+ state.statusSeq += 1;
2150
+ const statusFact = {
2151
+ kind: "work-item-validation-status",
2152
+ statusId: `work-item-authoring-status:${state.statusSeq}`,
2153
+ ...status
2154
+ };
2155
+ emit(ctx, "status", statusFact);
2156
+ emitAudit(ctx, state, "work-item-authoring-status", statusFact);
2157
+ }
2158
+ function emitRequestStatus(ctx, state, status) {
2159
+ state.statusSeq += 1;
2160
+ const statusFact = {
2161
+ kind: "work-item-validation-status",
2162
+ statusId: `work-item-verification-request-status:${state.statusSeq}`,
2163
+ ...status
2164
+ };
2165
+ emit(ctx, "status", statusFact);
2166
+ emitAudit(ctx, state, "work-item-verification-request-status", statusFact);
2167
+ }
2168
+ function emitResultStatus(ctx, state, status) {
2169
+ state.statusSeq += 1;
2170
+ const statusFact = {
2171
+ kind: "work-item-validation-status",
2172
+ statusId: `work-item-verification-result-status:${state.statusSeq}`,
2173
+ ...status
2174
+ };
2175
+ emit(ctx, "status", statusFact);
2176
+ emitAudit(ctx, state, "work-item-verification-result-status", statusFact);
2177
+ }
2178
+ function emitAudit(ctx, state, kind, status) {
2179
+ state.auditSeq += 1;
2180
+ emit(ctx, "audit", {
2181
+ id: `${kind}:${state.auditSeq}`,
2182
+ kind,
2183
+ subjectId: status.workItemId,
2184
+ message: status.message,
2185
+ issueCode: status.code,
2186
+ sourceRefs: status.sourceRefs,
2187
+ metadata: {
2188
+ statusId: status.statusId,
2189
+ state: status.state,
2190
+ revision: status.revision,
2191
+ executionInputRevision: status.executionInputRevision,
2192
+ ...status.metadata ?? {}
2193
+ }
2194
+ });
2195
+ }
2196
+ function emit(ctx, kind, value) {
2197
+ ctx.down([["DATA", { kind, value }]]);
2198
+ }
2199
+ function project(graph, runtime, name, factory, select) {
2200
+ return graph.node(
2201
+ [runtime],
2202
+ (ctx) => {
2203
+ for (const raw of depBatch(ctx, 0) ?? []) {
2204
+ const selected = select(raw);
2205
+ if (selected !== void 0) ctx.down([["DATA", selected]]);
2206
+ }
2207
+ },
2208
+ { name, factory, partial: true, completeWhenDepsComplete: false, errorWhenDepsError: false }
2209
+ );
2210
+ }
2211
+ function normalizePlan(draft) {
2212
+ if (draft.verificationPlan !== void 0) return draft.verificationPlan;
2213
+ if (draft.verificationSteps !== void 0)
2214
+ return { planId: "default", steps: draft.verificationSteps };
2215
+ return void 0;
2216
+ }
2217
+ function normalizePlanFromUnknown(draft) {
2218
+ const verificationPlan = draft.verificationPlan;
2219
+ if (verificationPlan !== void 0) {
2220
+ if (!isRecord(verificationPlan) || !Array.isArray(verificationPlan.steps)) {
2221
+ return { planId: "malformed", steps: [] };
2222
+ }
2223
+ return verificationPlan;
2224
+ }
2225
+ const verificationSteps = draft.verificationSteps;
2226
+ if (verificationSteps !== void 0) {
2227
+ if (!Array.isArray(verificationSteps)) return { planId: "malformed", steps: [] };
2228
+ return { planId: "default", steps: verificationSteps };
2229
+ }
2230
+ return void 0;
2231
+ }
2232
+ function isVerificationPlanShape(value) {
2233
+ return isRecord(value) && typeof value.planId === "string" && Array.isArray(value.steps);
2234
+ }
2235
+ function applyDraftPatch(existing, patch) {
2236
+ return {
2237
+ summary: patchValue(patch, existing, "summary"),
2238
+ detail: patchValue(patch, existing, "detail"),
2239
+ detailRefs: patchValue(patch, existing, "detailRefs"),
2240
+ acceptanceCriteria: patchValue(patch, existing, "acceptanceCriteria"),
2241
+ verificationPlan: patchValue(patch, existing, "verificationPlan"),
2242
+ verificationSteps: patchValue(patch, existing, "verificationSteps"),
2243
+ kind: patchValue(patch, existing, "kind"),
2244
+ priority: patchValue(patch, existing, "priority"),
2245
+ tags: patchValue(patch, existing, "tags"),
2246
+ owner: patchValue(patch, existing, "owner"),
2247
+ assignee: patchValue(patch, existing, "assignee"),
2248
+ deadlineMs: patchValue(patch, existing, "deadlineMs"),
2249
+ customFields: patchValue(patch, existing, "customFields"),
2250
+ sourceRefs: patchValue(patch, existing, "sourceRefs"),
2251
+ metadata: patchValue(patch, existing, "metadata")
2252
+ };
2253
+ }
2254
+ function patchValue(patch, existing, key) {
2255
+ return Object.hasOwn(patch, key) ? patch[key] : existing[key];
2256
+ }
2257
+ function validateEvidenceCoverage(workItem, stepIds, criterionIds) {
2258
+ const plan = normalizePlan(workItem);
2259
+ const validStepIds = new Set((plan?.steps ?? []).map((step) => step.stepId));
2260
+ const validCriterionIds = new Set(
2261
+ (workItem.acceptanceCriteria ?? []).map((criterion) => criterion.criterionId)
2262
+ );
2263
+ for (const stepId of stepIds) {
2264
+ if (!validStepIds.has(stepId)) {
2265
+ return issue("dangling-ref", `unknown verification step '${stepId}'`, workItem.workItemId, {
2266
+ stepId
2267
+ });
2268
+ }
2269
+ }
2270
+ for (const criterionId of criterionIds) {
2271
+ if (!validCriterionIds.has(criterionId)) {
2272
+ return issue(
2273
+ "dangling-ref",
2274
+ `unknown acceptance criterion '${criterionId}'`,
2275
+ workItem.workItemId,
2276
+ { criterionId }
2277
+ );
2278
+ }
2279
+ }
2280
+ return void 0;
2281
+ }
2282
+ function executionRelevant(policy, fields) {
2283
+ return /* @__PURE__ */ new Set([
2284
+ ...executionRelevantDefaults,
2285
+ ...policy?.executionRelevantFields ?? [],
2286
+ ...fields ?? []
2287
+ ]);
2288
+ }
2289
+ function touchesExecutionRelevant(patch, relevantFields) {
2290
+ const paths = patchPaths(patch);
2291
+ for (const path of paths) {
2292
+ if (relevantFields.has(path)) return true;
2293
+ }
2294
+ return false;
2295
+ }
2296
+ function patchPaths(patch) {
2297
+ const paths = [];
2298
+ for (const [key, value] of Object.entries(patch)) {
2299
+ paths.push(key);
2300
+ if (isRecord(value)) {
2301
+ for (const childKey of Object.keys(value)) paths.push(`${key}.${childKey}`);
2302
+ }
2303
+ }
2304
+ return paths;
2305
+ }
2306
+ function isStepSatisfied(state, workItem, stepId) {
2307
+ return state.passedSteps.get(revisionKey(workItem.workItemId, workItem.executionInputRevision))?.has(stepId) === true;
2308
+ }
2309
+ function revisionKey(workItemId, executionInputRevision) {
2310
+ return `${workItemId}:${executionInputRevision}`;
2311
+ }
2312
+ function replayEvidence(ctx, state, workItemId) {
2313
+ for (const evidence of state.evidenceById.values()) {
2314
+ if (evidence.workItemId === workItemId) mapEvidence(ctx, state, evidence, true);
2315
+ }
2316
+ }
2317
+ function validateMappingPolicy(policy) {
2318
+ if (!isRecord(policy) || policy.kind !== "work-item-verification-mapping-policy" || typeof policy.policyId !== "string" || policy.policyId.trim() === "") {
2319
+ return [
2320
+ issue(
2321
+ "policy-mismatch",
2322
+ "WorkItemVerificationMappingPolicy requires kind and policyId",
2323
+ void 0
2324
+ )
2325
+ ];
2326
+ }
2327
+ if (policy.actionProposals !== void 0 && !Array.isArray(policy.actionProposals)) {
2328
+ return [
2329
+ issue(
2330
+ "policy-mismatch",
2331
+ "WorkItemVerificationMappingPolicy.actionProposals must be an array",
2332
+ void 0,
2333
+ {
2334
+ policyId: policy.policyId
2335
+ }
2336
+ )
2337
+ ];
2338
+ }
2339
+ const out = [];
2340
+ for (const [index, spec] of (policy.actionProposals ?? []).entries()) {
2341
+ if (!isRecord(spec) || typeof spec.actionKind !== "string") {
2342
+ out.push(
2343
+ issue("policy-mismatch", "WorkItem action proposal requires actionKind", void 0, {
2344
+ policyId: policy.policyId,
2345
+ index
2346
+ })
2347
+ );
2348
+ }
2349
+ }
2350
+ return out;
2351
+ }
2352
+ function findCycle(steps) {
2353
+ const byId = new Map(steps.map((step) => [step.stepId, step.dependsOnStepIds ?? []]));
2354
+ const visiting = /* @__PURE__ */ new Set();
2355
+ const visited = /* @__PURE__ */ new Set();
2356
+ const stack = [];
2357
+ const visit = (id) => {
2358
+ if (visiting.has(id)) return [...stack.slice(stack.indexOf(id)), id];
2359
+ if (visited.has(id)) return void 0;
2360
+ visiting.add(id);
2361
+ stack.push(id);
2362
+ for (const dep of byId.get(id) ?? []) {
2363
+ if (!byId.has(dep)) continue;
2364
+ const cycle = visit(dep);
2365
+ if (cycle !== void 0) return cycle;
2366
+ }
2367
+ stack.pop();
2368
+ visiting.delete(id);
2369
+ visited.add(id);
2370
+ return void 0;
2371
+ };
2372
+ for (const step of steps) {
2373
+ const cycle = visit(step.stepId);
2374
+ if (cycle !== void 0) return cycle;
2375
+ }
2376
+ return void 0;
2377
+ }
2378
+ function resultStatus(status) {
2379
+ if (status === "completed") return "passed";
2380
+ if (status === "failed") return "failed";
2381
+ if (status === "blocked") return "blocked";
2382
+ if (status === "canceled") return "canceled";
2383
+ if (status === "timeout") return "timeout";
2384
+ return "waived";
2385
+ }
2386
+ function goalWithInlineInput(goal, input, inputId, inputKind, subjectRefs) {
2387
+ if (input === void 0 || goal.input !== void 0) return goal;
2388
+ return {
2389
+ ...goal,
2390
+ input: {
2391
+ inputId,
2392
+ inputKind,
2393
+ dataMode: "inline",
2394
+ value: input,
2395
+ subjectRefs
2396
+ }
2397
+ };
2398
+ }
2399
+ function actionProposalPayload(spec, evidence, result) {
2400
+ if (spec.payload !== void 0) return spec.payload;
2401
+ if (spec.payloadFrom === "effect-run-result")
2402
+ return { kind: "effect-run-result-ref", resultId: result.effectRunResultId };
2403
+ if (spec.payloadFrom === "output") return evidence.output;
2404
+ if (spec.payloadFrom === "evidence")
2405
+ return { kind: "work-item-evidence-ref", evidenceId: evidence.evidenceId };
2406
+ return void 0;
2407
+ }
2408
+ function actionProposalIssue(policy, spec, evidence, reason) {
2409
+ return issue(
2410
+ "policy-mismatch",
2411
+ `Verification mapping policy '${policy.policyId}' has an invalid action proposal: ${reason}`,
2412
+ evidence.workItemId,
2413
+ { policyId: policy.policyId, actionKind: spec.actionKind }
2414
+ );
2415
+ }
2416
+ function issue(code, message, workItemId, metadata) {
2417
+ return {
2418
+ kind: "issue",
2419
+ code,
2420
+ message,
2421
+ severity: "error",
2422
+ source: "work-item-scheduling",
2423
+ subjectId: workItemId,
2424
+ metadata
2425
+ };
2426
+ }
2427
+ function refs(kind, id, rest) {
2428
+ return [ref(kind, id), ...rest ?? []];
2429
+ }
2430
+ function ref(kind, id) {
2431
+ return { kind, id };
2432
+ }
2433
+ function stringArray(value) {
2434
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
2435
+ }
2436
+ function isRecord(value) {
2437
+ return value !== null && typeof value === "object";
2438
+ }
2439
+ // Annotate the CommonJS export names for ESM import in node:
2440
+ 0 && (module.exports = {
2441
+ acceptanceCriteriaChanged,
2442
+ validateAcceptanceCriteria,
2443
+ validateVerificationPlan,
2444
+ validateWorkItemDraft,
2445
+ validateWorkItemEffectPlan,
2446
+ verificationPlanChanged,
2447
+ workItemAuthoringProjector,
2448
+ workItemCreatedFromDraft,
2449
+ workItemEffectPlanProjector,
2450
+ workItemSpawnProposed,
2451
+ workItemVerificationRequestLowerer,
2452
+ workItemVerificationResultMapper
2453
+ });
2454
+ //# sourceMappingURL=scheduling.cjs.map