@smthrs/flow 0.0.0-stage → 1.0.0-rc.12

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 (654) hide show
  1. package/CHANGELOG.md +161 -0
  2. package/LICENSE +21 -0
  3. package/README.md +212 -2
  4. package/THIRD_PARTY_NOTICES.md +52 -0
  5. package/dist/cjs/Action/Action.d.ts +250 -0
  6. package/dist/cjs/Action/Action.d.ts.map +1 -0
  7. package/dist/cjs/Action/Action.js +42 -0
  8. package/dist/cjs/Action/Action.js.map +7 -0
  9. package/dist/cjs/Action/AttemptTimedOut.d.ts +33 -0
  10. package/dist/cjs/Action/AttemptTimedOut.d.ts.map +1 -0
  11. package/dist/cjs/Action/AttemptTimedOut.js +51 -0
  12. package/dist/cjs/Action/AttemptTimedOut.js.map +7 -0
  13. package/dist/cjs/Action/BoundaryMode.d.ts +29 -0
  14. package/dist/cjs/Action/BoundaryMode.d.ts.map +1 -0
  15. package/dist/cjs/Action/BoundaryMode.js +36 -0
  16. package/dist/cjs/Action/BoundaryMode.js.map +7 -0
  17. package/dist/cjs/Action/CacheEnvironment.d.ts +158 -0
  18. package/dist/cjs/Action/CacheEnvironment.d.ts.map +1 -0
  19. package/dist/cjs/Action/CacheEnvironment.js +57 -0
  20. package/dist/cjs/Action/CacheEnvironment.js.map +7 -0
  21. package/dist/cjs/Action/ConcurrentKeylessDispatch.d.ts +34 -0
  22. package/dist/cjs/Action/ConcurrentKeylessDispatch.d.ts.map +1 -0
  23. package/dist/cjs/Action/ConcurrentKeylessDispatch.js +46 -0
  24. package/dist/cjs/Action/ConcurrentKeylessDispatch.js.map +7 -0
  25. package/dist/cjs/Action/Context.d.ts +131 -0
  26. package/dist/cjs/Action/Context.d.ts.map +1 -0
  27. package/dist/cjs/Action/Context.js +68 -0
  28. package/dist/cjs/Action/Context.js.map +7 -0
  29. package/dist/cjs/Action/DuplicateImplementation.d.ts +20 -0
  30. package/dist/cjs/Action/DuplicateImplementation.d.ts.map +1 -0
  31. package/dist/cjs/Action/DuplicateImplementation.js +46 -0
  32. package/dist/cjs/Action/DuplicateImplementation.js.map +7 -0
  33. package/dist/cjs/Action/FileBoundary.d.ts +59 -0
  34. package/dist/cjs/Action/FileBoundary.d.ts.map +1 -0
  35. package/dist/cjs/Action/FileBoundary.js +81 -0
  36. package/dist/cjs/Action/FileBoundary.js.map +7 -0
  37. package/dist/cjs/Action/FileInput.d.ts +28 -0
  38. package/dist/cjs/Action/FileInput.d.ts.map +1 -0
  39. package/dist/cjs/Action/FileInput.js +42 -0
  40. package/dist/cjs/Action/FileInput.js.map +7 -0
  41. package/dist/cjs/Action/Filegroup.d.ts +16 -0
  42. package/dist/cjs/Action/Filegroup.d.ts.map +1 -0
  43. package/dist/cjs/Action/Filegroup.js +27 -0
  44. package/dist/cjs/Action/Filegroup.js.map +7 -0
  45. package/dist/cjs/Action/Glob.d.ts +8 -0
  46. package/dist/cjs/Action/Glob.d.ts.map +1 -0
  47. package/dist/cjs/Action/Glob.js +28 -0
  48. package/dist/cjs/Action/Glob.js.map +7 -0
  49. package/dist/cjs/Action/ImplementationVersionMismatch.d.ts +26 -0
  50. package/dist/cjs/Action/ImplementationVersionMismatch.d.ts.map +1 -0
  51. package/dist/cjs/Action/ImplementationVersionMismatch.js +45 -0
  52. package/dist/cjs/Action/ImplementationVersionMismatch.js.map +7 -0
  53. package/dist/cjs/Action/Implementations.d.ts +114 -0
  54. package/dist/cjs/Action/Implementations.d.ts.map +1 -0
  55. package/dist/cjs/Action/Implementations.js +65 -0
  56. package/dist/cjs/Action/Implementations.js.map +7 -0
  57. package/dist/cjs/Action/InfraInterrupt.d.ts +26 -0
  58. package/dist/cjs/Action/InfraInterrupt.d.ts.map +1 -0
  59. package/dist/cjs/Action/InfraInterrupt.js +46 -0
  60. package/dist/cjs/Action/InfraInterrupt.js.map +7 -0
  61. package/dist/cjs/Action/InfraInterruptRetriesExhausted.d.ts +33 -0
  62. package/dist/cjs/Action/InfraInterruptRetriesExhausted.d.ts.map +1 -0
  63. package/dist/cjs/Action/InfraInterruptRetriesExhausted.js +54 -0
  64. package/dist/cjs/Action/InfraInterruptRetriesExhausted.js.map +7 -0
  65. package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts +26 -0
  66. package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts.map +1 -0
  67. package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.js +47 -0
  68. package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.js.map +7 -0
  69. package/dist/cjs/Action/StepIdentity.d.ts +153 -0
  70. package/dist/cjs/Action/StepIdentity.d.ts.map +1 -0
  71. package/dist/cjs/Action/StepIdentity.js +75 -0
  72. package/dist/cjs/Action/StepIdentity.js.map +7 -0
  73. package/dist/cjs/Action/TreeArtifact.d.ts +8 -0
  74. package/dist/cjs/Action/TreeArtifact.d.ts.map +1 -0
  75. package/dist/cjs/Action/TreeArtifact.js +25 -0
  76. package/dist/cjs/Action/TreeArtifact.js.map +7 -0
  77. package/dist/cjs/Action/TypeId.d.ts +8 -0
  78. package/dist/cjs/Action/TypeId.d.ts.map +1 -0
  79. package/dist/cjs/Action/TypeId.js +25 -0
  80. package/dist/cjs/Action/TypeId.js.map +7 -0
  81. package/dist/cjs/Action/UncanonicalIdempotencyKey.d.ts +32 -0
  82. package/dist/cjs/Action/UncanonicalIdempotencyKey.d.ts.map +1 -0
  83. package/dist/cjs/Action/UncanonicalIdempotencyKey.js +51 -0
  84. package/dist/cjs/Action/UncanonicalIdempotencyKey.js.map +7 -0
  85. package/dist/cjs/Action/idempotencyKey.d.ts +21 -0
  86. package/dist/cjs/Action/idempotencyKey.d.ts.map +1 -0
  87. package/dist/cjs/Action/idempotencyKey.js +59 -0
  88. package/dist/cjs/Action/idempotencyKey.js.map +7 -0
  89. package/dist/cjs/Action/index.d.ts +29 -0
  90. package/dist/cjs/Action/index.d.ts.map +1 -0
  91. package/dist/cjs/Action/index.js +60 -0
  92. package/dist/cjs/Action/index.js.map +7 -0
  93. package/dist/cjs/Action/make.d.ts +128 -0
  94. package/dist/cjs/Action/make.d.ts.map +1 -0
  95. package/dist/cjs/Action/make.js +387 -0
  96. package/dist/cjs/Action/make.js.map +7 -0
  97. package/dist/cjs/Action/raceAll.d.ts +21 -0
  98. package/dist/cjs/Action/raceAll.d.ts.map +1 -0
  99. package/dist/cjs/Action/raceAll.js +46 -0
  100. package/dist/cjs/Action/raceAll.js.map +7 -0
  101. package/dist/cjs/Action/retry.d.ts +19 -0
  102. package/dist/cjs/Action/retry.d.ts.map +1 -0
  103. package/dist/cjs/Action/retry.js +75 -0
  104. package/dist/cjs/Action/retry.js.map +7 -0
  105. package/dist/cjs/Deadline.d.ts +110 -0
  106. package/dist/cjs/Deadline.d.ts.map +1 -0
  107. package/dist/cjs/Deadline.js +112 -0
  108. package/dist/cjs/Deadline.js.map +7 -0
  109. package/dist/cjs/DurableClock.d.ts +60 -0
  110. package/dist/cjs/DurableClock.d.ts.map +1 -0
  111. package/dist/cjs/DurableClock.js +107 -0
  112. package/dist/cjs/DurableClock.js.map +7 -0
  113. package/dist/cjs/DurableDeferred.d.ts +311 -0
  114. package/dist/cjs/DurableDeferred.d.ts.map +1 -0
  115. package/dist/cjs/DurableDeferred.js +322 -0
  116. package/dist/cjs/DurableDeferred.js.map +7 -0
  117. package/dist/cjs/DurableQueue.d.ts +160 -0
  118. package/dist/cjs/DurableQueue.d.ts.map +1 -0
  119. package/dist/cjs/DurableQueue.js +229 -0
  120. package/dist/cjs/DurableQueue.js.map +7 -0
  121. package/dist/cjs/ExternalJob.d.ts +179 -0
  122. package/dist/cjs/ExternalJob.d.ts.map +1 -0
  123. package/dist/cjs/ExternalJob.js +339 -0
  124. package/dist/cjs/ExternalJob.js.map +7 -0
  125. package/dist/cjs/Fault.d.ts +131 -0
  126. package/dist/cjs/Fault.d.ts.map +1 -0
  127. package/dist/cjs/Fault.js +157 -0
  128. package/dist/cjs/Fault.js.map +7 -0
  129. package/dist/cjs/Flow/Annotations.d.ts +245 -0
  130. package/dist/cjs/Flow/Annotations.d.ts.map +1 -0
  131. package/dist/cjs/Flow/Annotations.js +72 -0
  132. package/dist/cjs/Flow/Annotations.js.map +7 -0
  133. package/dist/cjs/Flow/CapabilityCeiling.d.ts +21 -0
  134. package/dist/cjs/Flow/CapabilityCeiling.d.ts.map +1 -0
  135. package/dist/cjs/Flow/CapabilityCeiling.js +49 -0
  136. package/dist/cjs/Flow/CapabilityCeiling.js.map +7 -0
  137. package/dist/cjs/Flow/DeadlineExceeded.d.ts +33 -0
  138. package/dist/cjs/Flow/DeadlineExceeded.d.ts.map +1 -0
  139. package/dist/cjs/Flow/DeadlineExceeded.js +52 -0
  140. package/dist/cjs/Flow/DeadlineExceeded.js.map +7 -0
  141. package/dist/cjs/Flow/ExecutionIdRequired.d.ts +25 -0
  142. package/dist/cjs/Flow/ExecutionIdRequired.d.ts.map +1 -0
  143. package/dist/cjs/Flow/ExecutionIdRequired.js +46 -0
  144. package/dist/cjs/Flow/ExecutionIdRequired.js.map +7 -0
  145. package/dist/cjs/Flow/ExecutionIds.d.ts +80 -0
  146. package/dist/cjs/Flow/ExecutionIds.d.ts.map +1 -0
  147. package/dist/cjs/Flow/ExecutionIds.js +66 -0
  148. package/dist/cjs/Flow/ExecutionIds.js.map +7 -0
  149. package/dist/cjs/Flow/Flow.d.ts +422 -0
  150. package/dist/cjs/Flow/Flow.d.ts.map +1 -0
  151. package/dist/cjs/Flow/Flow.js +17 -0
  152. package/dist/cjs/Flow/Flow.js.map +7 -0
  153. package/dist/cjs/Flow/MaxRoundsExceeded.d.ts +35 -0
  154. package/dist/cjs/Flow/MaxRoundsExceeded.d.ts.map +1 -0
  155. package/dist/cjs/Flow/MaxRoundsExceeded.js +50 -0
  156. package/dist/cjs/Flow/MaxRoundsExceeded.js.map +7 -0
  157. package/dist/cjs/Flow/Outcome.d.ts +162 -0
  158. package/dist/cjs/Flow/Outcome.d.ts.map +1 -0
  159. package/dist/cjs/Flow/Outcome.js +80 -0
  160. package/dist/cjs/Flow/Outcome.js.map +7 -0
  161. package/dist/cjs/Flow/Result.d.ts +186 -0
  162. package/dist/cjs/Flow/Result.d.ts.map +1 -0
  163. package/dist/cjs/Flow/Result.js +159 -0
  164. package/dist/cjs/Flow/Result.js.map +7 -0
  165. package/dist/cjs/Flow/Runtime.d.ts +98 -0
  166. package/dist/cjs/Flow/Runtime.d.ts.map +1 -0
  167. package/dist/cjs/Flow/Runtime.js +186 -0
  168. package/dist/cjs/Flow/Runtime.js.map +7 -0
  169. package/dist/cjs/Flow/TypeId.d.ts +8 -0
  170. package/dist/cjs/Flow/TypeId.d.ts.map +1 -0
  171. package/dist/cjs/Flow/TypeId.js +25 -0
  172. package/dist/cjs/Flow/TypeId.js.map +7 -0
  173. package/dist/cjs/Flow/index.d.ts +17 -0
  174. package/dist/cjs/Flow/index.d.ts.map +1 -0
  175. package/dist/cjs/Flow/index.js +29 -0
  176. package/dist/cjs/Flow/index.js.map +7 -0
  177. package/dist/cjs/Flow/internal.d.ts +34 -0
  178. package/dist/cjs/Flow/internal.d.ts.map +1 -0
  179. package/dist/cjs/Flow/internal.js +187 -0
  180. package/dist/cjs/Flow/internal.js.map +7 -0
  181. package/dist/cjs/Flow/make.d.ts +135 -0
  182. package/dist/cjs/Flow/make.d.ts.map +1 -0
  183. package/dist/cjs/Flow/make.js +107 -0
  184. package/dist/cjs/Flow/make.js.map +7 -0
  185. package/dist/cjs/FlowRuntime/CancelRequestFailed.d.ts +55 -0
  186. package/dist/cjs/FlowRuntime/CancelRequestFailed.d.ts.map +1 -0
  187. package/dist/cjs/FlowRuntime/CancelRequestFailed.js +51 -0
  188. package/dist/cjs/FlowRuntime/CancelRequestFailed.js.map +7 -0
  189. package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.d.ts +23 -0
  190. package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.d.ts.map +1 -0
  191. package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.js +55 -0
  192. package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.js.map +7 -0
  193. package/dist/cjs/FlowRuntime/FlowCycleDetected.d.ts +28 -0
  194. package/dist/cjs/FlowRuntime/FlowCycleDetected.d.ts.map +1 -0
  195. package/dist/cjs/FlowRuntime/FlowCycleDetected.js +49 -0
  196. package/dist/cjs/FlowRuntime/FlowCycleDetected.js.map +7 -0
  197. package/dist/cjs/FlowRuntime/FlowExecutionNotFound.d.ts +38 -0
  198. package/dist/cjs/FlowRuntime/FlowExecutionNotFound.d.ts.map +1 -0
  199. package/dist/cjs/FlowRuntime/FlowExecutionNotFound.js +53 -0
  200. package/dist/cjs/FlowRuntime/FlowExecutionNotFound.js.map +7 -0
  201. package/dist/cjs/FlowRuntime/FlowInstance.d.ts +115 -0
  202. package/dist/cjs/FlowRuntime/FlowInstance.d.ts.map +1 -0
  203. package/dist/cjs/FlowRuntime/FlowInstance.js +37 -0
  204. package/dist/cjs/FlowRuntime/FlowInstance.js.map +7 -0
  205. package/dist/cjs/FlowRuntime/FlowRuntime.d.ts +204 -0
  206. package/dist/cjs/FlowRuntime/FlowRuntime.d.ts.map +1 -0
  207. package/dist/cjs/FlowRuntime/FlowRuntime.js +37 -0
  208. package/dist/cjs/FlowRuntime/FlowRuntime.js.map +7 -0
  209. package/dist/cjs/FlowRuntime/NodeRecord.d.ts +177 -0
  210. package/dist/cjs/FlowRuntime/NodeRecord.d.ts.map +1 -0
  211. package/dist/cjs/FlowRuntime/NodeRecord.js +17 -0
  212. package/dist/cjs/FlowRuntime/NodeRecord.js.map +7 -0
  213. package/dist/cjs/FlowRuntime/WaitingAnnotation.d.ts +69 -0
  214. package/dist/cjs/FlowRuntime/WaitingAnnotation.d.ts.map +1 -0
  215. package/dist/cjs/FlowRuntime/WaitingAnnotation.js +53 -0
  216. package/dist/cjs/FlowRuntime/WaitingAnnotation.js.map +7 -0
  217. package/dist/cjs/FlowRuntime/index.d.ts +14 -0
  218. package/dist/cjs/FlowRuntime/index.d.ts.map +1 -0
  219. package/dist/cjs/FlowRuntime/index.js +26 -0
  220. package/dist/cjs/FlowRuntime/index.js.map +7 -0
  221. package/dist/cjs/Graph.d.ts +325 -0
  222. package/dist/cjs/Graph.d.ts.map +1 -0
  223. package/dist/cjs/Graph.js +1020 -0
  224. package/dist/cjs/Graph.js.map +7 -0
  225. package/dist/cjs/HumanTask.d.ts +442 -0
  226. package/dist/cjs/HumanTask.d.ts.map +1 -0
  227. package/dist/cjs/HumanTask.js +413 -0
  228. package/dist/cjs/HumanTask.js.map +7 -0
  229. package/dist/cjs/Interpreter.d.ts +223 -0
  230. package/dist/cjs/Interpreter.d.ts.map +1 -0
  231. package/dist/cjs/Interpreter.js +908 -0
  232. package/dist/cjs/Interpreter.js.map +7 -0
  233. package/dist/cjs/Poll.d.ts +240 -0
  234. package/dist/cjs/Poll.d.ts.map +1 -0
  235. package/dist/cjs/Poll.js +154 -0
  236. package/dist/cjs/Poll.js.map +7 -0
  237. package/dist/cjs/RetryPolicy.d.ts +273 -0
  238. package/dist/cjs/RetryPolicy.d.ts.map +1 -0
  239. package/dist/cjs/RetryPolicy.js +251 -0
  240. package/dist/cjs/RetryPolicy.js.map +7 -0
  241. package/dist/cjs/Sleep.d.ts +98 -0
  242. package/dist/cjs/Sleep.d.ts.map +1 -0
  243. package/dist/cjs/Sleep.js +141 -0
  244. package/dist/cjs/Sleep.js.map +7 -0
  245. package/dist/cjs/Stall.d.ts +173 -0
  246. package/dist/cjs/Stall.d.ts.map +1 -0
  247. package/dist/cjs/Stall.js +92 -0
  248. package/dist/cjs/Stall.js.map +7 -0
  249. package/dist/cjs/WaitFor.d.ts +109 -0
  250. package/dist/cjs/WaitFor.d.ts.map +1 -0
  251. package/dist/cjs/WaitFor.js +117 -0
  252. package/dist/cjs/WaitFor.js.map +7 -0
  253. package/dist/cjs/index.d.ts +107 -0
  254. package/dist/cjs/index.d.ts.map +1 -0
  255. package/dist/cjs/index.js +69 -0
  256. package/dist/cjs/index.js.map +7 -0
  257. package/dist/cjs/internal/BoundedJson.d.ts +48 -0
  258. package/dist/cjs/internal/BoundedJson.d.ts.map +1 -0
  259. package/dist/cjs/internal/BoundedJson.js +96 -0
  260. package/dist/cjs/internal/BoundedJson.js.map +7 -0
  261. package/dist/cjs/internal/DeclarationSite.d.ts +135 -0
  262. package/dist/cjs/internal/DeclarationSite.d.ts.map +1 -0
  263. package/dist/cjs/internal/DeclarationSite.js +89 -0
  264. package/dist/cjs/internal/DeclarationSite.js.map +7 -0
  265. package/dist/cjs/internal/Declarations.d.ts +35 -0
  266. package/dist/cjs/internal/Declarations.d.ts.map +1 -0
  267. package/dist/cjs/internal/Declarations.js +50 -0
  268. package/dist/cjs/internal/Declarations.js.map +7 -0
  269. package/dist/cjs/internal/ExecutionMiddleware.d.ts +21 -0
  270. package/dist/cjs/internal/ExecutionMiddleware.d.ts.map +1 -0
  271. package/dist/cjs/internal/ExecutionMiddleware.js +39 -0
  272. package/dist/cjs/internal/ExecutionMiddleware.js.map +7 -0
  273. package/dist/cjs/internal/JsonSchemaSubset.d.ts +133 -0
  274. package/dist/cjs/internal/JsonSchemaSubset.d.ts.map +1 -0
  275. package/dist/cjs/internal/JsonSchemaSubset.js +229 -0
  276. package/dist/cjs/internal/JsonSchemaSubset.js.map +7 -0
  277. package/dist/cjs/internal/OutcomeMarker.d.ts +18 -0
  278. package/dist/cjs/internal/OutcomeMarker.d.ts.map +1 -0
  279. package/dist/cjs/internal/OutcomeMarker.js +27 -0
  280. package/dist/cjs/internal/OutcomeMarker.js.map +7 -0
  281. package/dist/cjs/package.json +1 -0
  282. package/dist/esm/Action/Action.d.ts +250 -0
  283. package/dist/esm/Action/Action.d.ts.map +1 -0
  284. package/dist/esm/Action/Action.js +30 -0
  285. package/dist/esm/Action/Action.js.map +1 -0
  286. package/dist/esm/Action/AttemptTimedOut.d.ts +33 -0
  287. package/dist/esm/Action/AttemptTimedOut.d.ts.map +1 -0
  288. package/dist/esm/Action/AttemptTimedOut.js +32 -0
  289. package/dist/esm/Action/AttemptTimedOut.js.map +1 -0
  290. package/dist/esm/Action/BoundaryMode.d.ts +29 -0
  291. package/dist/esm/Action/BoundaryMode.d.ts.map +1 -0
  292. package/dist/esm/Action/BoundaryMode.js +23 -0
  293. package/dist/esm/Action/BoundaryMode.js.map +1 -0
  294. package/dist/esm/Action/CacheEnvironment.d.ts +158 -0
  295. package/dist/esm/Action/CacheEnvironment.d.ts.map +1 -0
  296. package/dist/esm/Action/CacheEnvironment.js +130 -0
  297. package/dist/esm/Action/CacheEnvironment.js.map +1 -0
  298. package/dist/esm/Action/ConcurrentKeylessDispatch.d.ts +34 -0
  299. package/dist/esm/Action/ConcurrentKeylessDispatch.d.ts.map +1 -0
  300. package/dist/esm/Action/ConcurrentKeylessDispatch.js +33 -0
  301. package/dist/esm/Action/ConcurrentKeylessDispatch.js.map +1 -0
  302. package/dist/esm/Action/Context.d.ts +131 -0
  303. package/dist/esm/Action/Context.d.ts.map +1 -0
  304. package/dist/esm/Action/Context.js +99 -0
  305. package/dist/esm/Action/Context.js.map +1 -0
  306. package/dist/esm/Action/DuplicateImplementation.d.ts +20 -0
  307. package/dist/esm/Action/DuplicateImplementation.d.ts.map +1 -0
  308. package/dist/esm/Action/DuplicateImplementation.js +20 -0
  309. package/dist/esm/Action/DuplicateImplementation.js.map +1 -0
  310. package/dist/esm/Action/FileBoundary.d.ts +59 -0
  311. package/dist/esm/Action/FileBoundary.d.ts.map +1 -0
  312. package/dist/esm/Action/FileBoundary.js +60 -0
  313. package/dist/esm/Action/FileBoundary.js.map +1 -0
  314. package/dist/esm/Action/FileInput.d.ts +28 -0
  315. package/dist/esm/Action/FileInput.d.ts.map +1 -0
  316. package/dist/esm/Action/FileInput.js +32 -0
  317. package/dist/esm/Action/FileInput.js.map +1 -0
  318. package/dist/esm/Action/Filegroup.d.ts +16 -0
  319. package/dist/esm/Action/Filegroup.d.ts.map +1 -0
  320. package/dist/esm/Action/Filegroup.js +15 -0
  321. package/dist/esm/Action/Filegroup.js.map +1 -0
  322. package/dist/esm/Action/Glob.d.ts +8 -0
  323. package/dist/esm/Action/Glob.d.ts.map +1 -0
  324. package/dist/esm/Action/Glob.js +7 -0
  325. package/dist/esm/Action/Glob.js.map +1 -0
  326. package/dist/esm/Action/ImplementationVersionMismatch.d.ts +26 -0
  327. package/dist/esm/Action/ImplementationVersionMismatch.d.ts.map +1 -0
  328. package/dist/esm/Action/ImplementationVersionMismatch.js +24 -0
  329. package/dist/esm/Action/ImplementationVersionMismatch.js.map +1 -0
  330. package/dist/esm/Action/Implementations.d.ts +114 -0
  331. package/dist/esm/Action/Implementations.d.ts.map +1 -0
  332. package/dist/esm/Action/Implementations.js +94 -0
  333. package/dist/esm/Action/Implementations.js.map +1 -0
  334. package/dist/esm/Action/InfraInterrupt.d.ts +26 -0
  335. package/dist/esm/Action/InfraInterrupt.d.ts.map +1 -0
  336. package/dist/esm/Action/InfraInterrupt.js +25 -0
  337. package/dist/esm/Action/InfraInterrupt.js.map +1 -0
  338. package/dist/esm/Action/InfraInterruptRetriesExhausted.d.ts +33 -0
  339. package/dist/esm/Action/InfraInterruptRetriesExhausted.d.ts.map +1 -0
  340. package/dist/esm/Action/InfraInterruptRetriesExhausted.js +32 -0
  341. package/dist/esm/Action/InfraInterruptRetriesExhausted.js.map +1 -0
  342. package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts +26 -0
  343. package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts.map +1 -0
  344. package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.js +25 -0
  345. package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.js.map +1 -0
  346. package/dist/esm/Action/StepIdentity.d.ts +153 -0
  347. package/dist/esm/Action/StepIdentity.d.ts.map +1 -0
  348. package/dist/esm/Action/StepIdentity.js +139 -0
  349. package/dist/esm/Action/StepIdentity.js.map +1 -0
  350. package/dist/esm/Action/TreeArtifact.d.ts +8 -0
  351. package/dist/esm/Action/TreeArtifact.d.ts.map +1 -0
  352. package/dist/esm/Action/TreeArtifact.js +7 -0
  353. package/dist/esm/Action/TreeArtifact.js.map +1 -0
  354. package/dist/esm/Action/TypeId.d.ts +8 -0
  355. package/dist/esm/Action/TypeId.d.ts.map +1 -0
  356. package/dist/esm/Action/TypeId.js +9 -0
  357. package/dist/esm/Action/TypeId.js.map +1 -0
  358. package/dist/esm/Action/UncanonicalIdempotencyKey.d.ts +32 -0
  359. package/dist/esm/Action/UncanonicalIdempotencyKey.d.ts.map +1 -0
  360. package/dist/esm/Action/UncanonicalIdempotencyKey.js +31 -0
  361. package/dist/esm/Action/UncanonicalIdempotencyKey.js.map +1 -0
  362. package/dist/esm/Action/idempotencyKey.d.ts +21 -0
  363. package/dist/esm/Action/idempotencyKey.d.ts.map +1 -0
  364. package/dist/esm/Action/idempotencyKey.js +50 -0
  365. package/dist/esm/Action/idempotencyKey.js.map +1 -0
  366. package/dist/esm/Action/index.d.ts +29 -0
  367. package/dist/esm/Action/index.d.ts.map +1 -0
  368. package/dist/esm/Action/index.js +30 -0
  369. package/dist/esm/Action/index.js.map +1 -0
  370. package/dist/esm/Action/make.d.ts +128 -0
  371. package/dist/esm/Action/make.d.ts.map +1 -0
  372. package/dist/esm/Action/make.js +413 -0
  373. package/dist/esm/Action/make.js.map +1 -0
  374. package/dist/esm/Action/raceAll.d.ts +21 -0
  375. package/dist/esm/Action/raceAll.d.ts.map +1 -0
  376. package/dist/esm/Action/raceAll.js +20 -0
  377. package/dist/esm/Action/raceAll.js.map +1 -0
  378. package/dist/esm/Action/retry.d.ts +19 -0
  379. package/dist/esm/Action/retry.d.ts.map +1 -0
  380. package/dist/esm/Action/retry.js +72 -0
  381. package/dist/esm/Action/retry.js.map +1 -0
  382. package/dist/esm/Deadline.d.ts +110 -0
  383. package/dist/esm/Deadline.d.ts.map +1 -0
  384. package/dist/esm/Deadline.js +164 -0
  385. package/dist/esm/Deadline.js.map +1 -0
  386. package/dist/esm/DurableClock.d.ts +60 -0
  387. package/dist/esm/DurableClock.d.ts.map +1 -0
  388. package/dist/esm/DurableClock.js +122 -0
  389. package/dist/esm/DurableClock.js.map +1 -0
  390. package/dist/esm/DurableDeferred.d.ts +311 -0
  391. package/dist/esm/DurableDeferred.d.ts.map +1 -0
  392. package/dist/esm/DurableDeferred.js +357 -0
  393. package/dist/esm/DurableDeferred.js.map +1 -0
  394. package/dist/esm/DurableQueue.d.ts +160 -0
  395. package/dist/esm/DurableQueue.d.ts.map +1 -0
  396. package/dist/esm/DurableQueue.js +303 -0
  397. package/dist/esm/DurableQueue.js.map +1 -0
  398. package/dist/esm/ExternalJob.d.ts +179 -0
  399. package/dist/esm/ExternalJob.d.ts.map +1 -0
  400. package/dist/esm/ExternalJob.js +296 -0
  401. package/dist/esm/ExternalJob.js.map +1 -0
  402. package/dist/esm/Fault.d.ts +131 -0
  403. package/dist/esm/Fault.d.ts.map +1 -0
  404. package/dist/esm/Fault.js +198 -0
  405. package/dist/esm/Fault.js.map +1 -0
  406. package/dist/esm/Flow/Annotations.d.ts +245 -0
  407. package/dist/esm/Flow/Annotations.d.ts.map +1 -0
  408. package/dist/esm/Flow/Annotations.js +110 -0
  409. package/dist/esm/Flow/Annotations.js.map +1 -0
  410. package/dist/esm/Flow/CapabilityCeiling.d.ts +21 -0
  411. package/dist/esm/Flow/CapabilityCeiling.d.ts.map +1 -0
  412. package/dist/esm/Flow/CapabilityCeiling.js +27 -0
  413. package/dist/esm/Flow/CapabilityCeiling.js.map +1 -0
  414. package/dist/esm/Flow/DeadlineExceeded.d.ts +33 -0
  415. package/dist/esm/Flow/DeadlineExceeded.d.ts.map +1 -0
  416. package/dist/esm/Flow/DeadlineExceeded.js +34 -0
  417. package/dist/esm/Flow/DeadlineExceeded.js.map +1 -0
  418. package/dist/esm/Flow/ExecutionIdRequired.d.ts +25 -0
  419. package/dist/esm/Flow/ExecutionIdRequired.d.ts.map +1 -0
  420. package/dist/esm/Flow/ExecutionIdRequired.js +30 -0
  421. package/dist/esm/Flow/ExecutionIdRequired.js.map +1 -0
  422. package/dist/esm/Flow/ExecutionIds.d.ts +80 -0
  423. package/dist/esm/Flow/ExecutionIds.d.ts.map +1 -0
  424. package/dist/esm/Flow/ExecutionIds.js +91 -0
  425. package/dist/esm/Flow/ExecutionIds.js.map +1 -0
  426. package/dist/esm/Flow/Flow.d.ts +422 -0
  427. package/dist/esm/Flow/Flow.d.ts.map +1 -0
  428. package/dist/esm/Flow/Flow.js +3 -0
  429. package/dist/esm/Flow/Flow.js.map +1 -0
  430. package/dist/esm/Flow/MaxRoundsExceeded.d.ts +35 -0
  431. package/dist/esm/Flow/MaxRoundsExceeded.d.ts.map +1 -0
  432. package/dist/esm/Flow/MaxRoundsExceeded.js +34 -0
  433. package/dist/esm/Flow/MaxRoundsExceeded.js.map +1 -0
  434. package/dist/esm/Flow/Outcome.d.ts +162 -0
  435. package/dist/esm/Flow/Outcome.d.ts.map +1 -0
  436. package/dist/esm/Flow/Outcome.js +115 -0
  437. package/dist/esm/Flow/Outcome.js.map +1 -0
  438. package/dist/esm/Flow/Result.d.ts +186 -0
  439. package/dist/esm/Flow/Result.d.ts.map +1 -0
  440. package/dist/esm/Flow/Result.js +171 -0
  441. package/dist/esm/Flow/Result.js.map +1 -0
  442. package/dist/esm/Flow/Runtime.d.ts +98 -0
  443. package/dist/esm/Flow/Runtime.d.ts.map +1 -0
  444. package/dist/esm/Flow/Runtime.js +252 -0
  445. package/dist/esm/Flow/Runtime.js.map +1 -0
  446. package/dist/esm/Flow/TypeId.d.ts +8 -0
  447. package/dist/esm/Flow/TypeId.d.ts.map +1 -0
  448. package/dist/esm/Flow/TypeId.js +9 -0
  449. package/dist/esm/Flow/TypeId.js.map +1 -0
  450. package/dist/esm/Flow/index.d.ts +17 -0
  451. package/dist/esm/Flow/index.d.ts.map +1 -0
  452. package/dist/esm/Flow/index.js +18 -0
  453. package/dist/esm/Flow/index.js.map +1 -0
  454. package/dist/esm/Flow/internal.d.ts +34 -0
  455. package/dist/esm/Flow/internal.d.ts.map +1 -0
  456. package/dist/esm/Flow/internal.js +149 -0
  457. package/dist/esm/Flow/internal.js.map +1 -0
  458. package/dist/esm/Flow/make.d.ts +135 -0
  459. package/dist/esm/Flow/make.d.ts.map +1 -0
  460. package/dist/esm/Flow/make.js +111 -0
  461. package/dist/esm/Flow/make.js.map +1 -0
  462. package/dist/esm/FlowRuntime/CancelRequestFailed.d.ts +55 -0
  463. package/dist/esm/FlowRuntime/CancelRequestFailed.d.ts.map +1 -0
  464. package/dist/esm/FlowRuntime/CancelRequestFailed.js +53 -0
  465. package/dist/esm/FlowRuntime/CancelRequestFailed.js.map +1 -0
  466. package/dist/esm/FlowRuntime/ExecutionIdentityConflict.d.ts +23 -0
  467. package/dist/esm/FlowRuntime/ExecutionIdentityConflict.d.ts.map +1 -0
  468. package/dist/esm/FlowRuntime/ExecutionIdentityConflict.js +24 -0
  469. package/dist/esm/FlowRuntime/ExecutionIdentityConflict.js.map +1 -0
  470. package/dist/esm/FlowRuntime/FlowCycleDetected.d.ts +28 -0
  471. package/dist/esm/FlowRuntime/FlowCycleDetected.d.ts.map +1 -0
  472. package/dist/esm/FlowRuntime/FlowCycleDetected.js +35 -0
  473. package/dist/esm/FlowRuntime/FlowCycleDetected.js.map +1 -0
  474. package/dist/esm/FlowRuntime/FlowExecutionNotFound.d.ts +38 -0
  475. package/dist/esm/FlowRuntime/FlowExecutionNotFound.d.ts.map +1 -0
  476. package/dist/esm/FlowRuntime/FlowExecutionNotFound.js +40 -0
  477. package/dist/esm/FlowRuntime/FlowExecutionNotFound.js.map +1 -0
  478. package/dist/esm/FlowRuntime/FlowInstance.d.ts +115 -0
  479. package/dist/esm/FlowRuntime/FlowInstance.d.ts.map +1 -0
  480. package/dist/esm/FlowRuntime/FlowInstance.js +24 -0
  481. package/dist/esm/FlowRuntime/FlowInstance.js.map +1 -0
  482. package/dist/esm/FlowRuntime/FlowRuntime.d.ts +204 -0
  483. package/dist/esm/FlowRuntime/FlowRuntime.d.ts.map +1 -0
  484. package/dist/esm/FlowRuntime/FlowRuntime.js +34 -0
  485. package/dist/esm/FlowRuntime/FlowRuntime.js.map +1 -0
  486. package/dist/esm/FlowRuntime/NodeRecord.d.ts +177 -0
  487. package/dist/esm/FlowRuntime/NodeRecord.d.ts.map +1 -0
  488. package/dist/esm/FlowRuntime/NodeRecord.js +21 -0
  489. package/dist/esm/FlowRuntime/NodeRecord.js.map +1 -0
  490. package/dist/esm/FlowRuntime/WaitingAnnotation.d.ts +69 -0
  491. package/dist/esm/FlowRuntime/WaitingAnnotation.d.ts.map +1 -0
  492. package/dist/esm/FlowRuntime/WaitingAnnotation.js +53 -0
  493. package/dist/esm/FlowRuntime/WaitingAnnotation.js.map +1 -0
  494. package/dist/esm/FlowRuntime/index.d.ts +14 -0
  495. package/dist/esm/FlowRuntime/index.d.ts.map +1 -0
  496. package/dist/esm/FlowRuntime/index.js +15 -0
  497. package/dist/esm/FlowRuntime/index.js.map +1 -0
  498. package/dist/esm/Graph.d.ts +325 -0
  499. package/dist/esm/Graph.d.ts.map +1 -0
  500. package/dist/esm/Graph.js +1485 -0
  501. package/dist/esm/Graph.js.map +1 -0
  502. package/dist/esm/HumanTask.d.ts +442 -0
  503. package/dist/esm/HumanTask.d.ts.map +1 -0
  504. package/dist/esm/HumanTask.js +798 -0
  505. package/dist/esm/HumanTask.js.map +1 -0
  506. package/dist/esm/Interpreter.d.ts +223 -0
  507. package/dist/esm/Interpreter.d.ts.map +1 -0
  508. package/dist/esm/Interpreter.js +1289 -0
  509. package/dist/esm/Interpreter.js.map +1 -0
  510. package/dist/esm/Poll.d.ts +240 -0
  511. package/dist/esm/Poll.d.ts.map +1 -0
  512. package/dist/esm/Poll.js +289 -0
  513. package/dist/esm/Poll.js.map +1 -0
  514. package/dist/esm/RetryPolicy.d.ts +273 -0
  515. package/dist/esm/RetryPolicy.d.ts.map +1 -0
  516. package/dist/esm/RetryPolicy.js +429 -0
  517. package/dist/esm/RetryPolicy.js.map +1 -0
  518. package/dist/esm/Sleep.d.ts +98 -0
  519. package/dist/esm/Sleep.d.ts.map +1 -0
  520. package/dist/esm/Sleep.js +256 -0
  521. package/dist/esm/Sleep.js.map +1 -0
  522. package/dist/esm/Stall.d.ts +173 -0
  523. package/dist/esm/Stall.d.ts.map +1 -0
  524. package/dist/esm/Stall.js +138 -0
  525. package/dist/esm/Stall.js.map +1 -0
  526. package/dist/esm/WaitFor.d.ts +109 -0
  527. package/dist/esm/WaitFor.d.ts.map +1 -0
  528. package/dist/esm/WaitFor.js +184 -0
  529. package/dist/esm/WaitFor.js.map +1 -0
  530. package/dist/esm/index.d.ts +107 -0
  531. package/dist/esm/index.d.ts.map +1 -0
  532. package/dist/esm/index.js +108 -0
  533. package/dist/esm/index.js.map +1 -0
  534. package/dist/esm/internal/BoundedJson.d.ts +48 -0
  535. package/dist/esm/internal/BoundedJson.d.ts.map +1 -0
  536. package/dist/esm/internal/BoundedJson.js +107 -0
  537. package/dist/esm/internal/BoundedJson.js.map +1 -0
  538. package/dist/esm/internal/DeclarationSite.d.ts +135 -0
  539. package/dist/esm/internal/DeclarationSite.d.ts.map +1 -0
  540. package/dist/esm/internal/DeclarationSite.js +196 -0
  541. package/dist/esm/internal/DeclarationSite.js.map +1 -0
  542. package/dist/esm/internal/Declarations.d.ts +35 -0
  543. package/dist/esm/internal/Declarations.d.ts.map +1 -0
  544. package/dist/esm/internal/Declarations.js +43 -0
  545. package/dist/esm/internal/Declarations.js.map +1 -0
  546. package/dist/esm/internal/ExecutionMiddleware.d.ts +21 -0
  547. package/dist/esm/internal/ExecutionMiddleware.d.ts.map +1 -0
  548. package/dist/esm/internal/ExecutionMiddleware.js +13 -0
  549. package/dist/esm/internal/ExecutionMiddleware.js.map +1 -0
  550. package/dist/esm/internal/JsonSchemaSubset.d.ts +133 -0
  551. package/dist/esm/internal/JsonSchemaSubset.d.ts.map +1 -0
  552. package/dist/esm/internal/JsonSchemaSubset.js +363 -0
  553. package/dist/esm/internal/JsonSchemaSubset.js.map +1 -0
  554. package/dist/esm/internal/OutcomeMarker.d.ts +18 -0
  555. package/dist/esm/internal/OutcomeMarker.d.ts.map +1 -0
  556. package/dist/esm/internal/OutcomeMarker.js +18 -0
  557. package/dist/esm/internal/OutcomeMarker.js.map +1 -0
  558. package/docs/README.md +152 -0
  559. package/docs/api.md +440 -0
  560. package/docs/concepts/bodies-and-plans.md +167 -0
  561. package/docs/concepts/execution-identity.md +142 -0
  562. package/docs/concepts/flows-and-actions.md +129 -0
  563. package/docs/concepts/suspension-and-replay.md +130 -0
  564. package/docs/concepts/the-runtime-port.md +110 -0
  565. package/docs/concepts/trampoline-rounds.md +151 -0
  566. package/docs/guides/ask-a-person.md +184 -0
  567. package/docs/guides/build-a-body.md +164 -0
  568. package/docs/guides/cancel-and-roll-back.md +112 -0
  569. package/docs/guides/implement-an-action.md +155 -0
  570. package/docs/guides/inspect-the-plan.md +235 -0
  571. package/docs/guides/poll-until-ready.md +169 -0
  572. package/docs/guides/queue-work-to-a-worker.md +122 -0
  573. package/docs/guides/retry-a-failing-action.md +243 -0
  574. package/docs/guides/reuse-a-recorded-result.md +129 -0
  575. package/docs/guides/run-a-child-flow.md +108 -0
  576. package/docs/guides/run-an-external-job.md +86 -0
  577. package/docs/guides/use-a-prompt.md +38 -0
  578. package/docs/guides/wait-for-a-deadline.md +141 -0
  579. package/docs/guides/wait-for-an-external-signal.md +151 -0
  580. package/docs/installation.md +87 -0
  581. package/docs/quickstart.md +164 -0
  582. package/docs/reference/flow.md +1835 -0
  583. package/docs/testing.md +157 -0
  584. package/docs/troubleshooting.md +286 -0
  585. package/package.json +327 -3
  586. package/src/Action/Action.ts +333 -0
  587. package/src/Action/AttemptTimedOut.ts +37 -0
  588. package/src/Action/BoundaryMode.ts +33 -0
  589. package/src/Action/CacheEnvironment.ts +170 -0
  590. package/src/Action/ConcurrentKeylessDispatch.ts +38 -0
  591. package/src/Action/Context.ts +156 -0
  592. package/src/Action/DuplicateImplementation.ts +24 -0
  593. package/src/Action/FileBoundary.ts +77 -0
  594. package/src/Action/FileInput.ts +42 -0
  595. package/src/Action/Filegroup.ts +16 -0
  596. package/src/Action/Glob.ts +8 -0
  597. package/src/Action/ImplementationVersionMismatch.ts +27 -0
  598. package/src/Action/Implementations.ts +149 -0
  599. package/src/Action/InfraInterrupt.ts +30 -0
  600. package/src/Action/InfraInterruptRetriesExhausted.ts +37 -0
  601. package/src/Action/IrreversibleRetryRequiresIdempotencyKey.ts +32 -0
  602. package/src/Action/StepIdentity.ts +219 -0
  603. package/src/Action/TreeArtifact.ts +8 -0
  604. package/src/Action/TypeId.ts +9 -0
  605. package/src/Action/UncanonicalIdempotencyKey.ts +36 -0
  606. package/src/Action/idempotencyKey.ts +67 -0
  607. package/src/Action/index.ts +31 -0
  608. package/src/Action/make.ts +671 -0
  609. package/src/Action/raceAll.ts +48 -0
  610. package/src/Action/retry.ts +92 -0
  611. package/src/Deadline.ts +201 -0
  612. package/src/DurableClock.ts +176 -0
  613. package/src/DurableDeferred.ts +753 -0
  614. package/src/DurableQueue.ts +519 -0
  615. package/src/ExternalJob.ts +437 -0
  616. package/src/Fault.ts +279 -0
  617. package/src/Flow/Annotations.ts +151 -0
  618. package/src/Flow/CapabilityCeiling.ts +37 -0
  619. package/src/Flow/DeadlineExceeded.ts +40 -0
  620. package/src/Flow/ExecutionIdRequired.ts +36 -0
  621. package/src/Flow/ExecutionIds.ts +133 -0
  622. package/src/Flow/Flow.ts +576 -0
  623. package/src/Flow/MaxRoundsExceeded.ts +39 -0
  624. package/src/Flow/Outcome.ts +179 -0
  625. package/src/Flow/Result.ts +284 -0
  626. package/src/Flow/Runtime.ts +339 -0
  627. package/src/Flow/TypeId.ts +9 -0
  628. package/src/Flow/index.ts +19 -0
  629. package/src/Flow/internal.ts +237 -0
  630. package/src/Flow/make.ts +285 -0
  631. package/src/FlowRuntime/CancelRequestFailed.ts +56 -0
  632. package/src/FlowRuntime/ExecutionIdentityConflict.ts +32 -0
  633. package/src/FlowRuntime/FlowCycleDetected.ts +41 -0
  634. package/src/FlowRuntime/FlowExecutionNotFound.ts +46 -0
  635. package/src/FlowRuntime/FlowInstance.ts +128 -0
  636. package/src/FlowRuntime/FlowRuntime.ts +339 -0
  637. package/src/FlowRuntime/NodeRecord.ts +185 -0
  638. package/src/FlowRuntime/WaitingAnnotation.ts +85 -0
  639. package/src/FlowRuntime/index.ts +17 -0
  640. package/src/Graph.ts +1865 -0
  641. package/src/HumanTask.ts +1007 -0
  642. package/src/Interpreter.ts +1620 -0
  643. package/src/Poll.ts +420 -0
  644. package/src/RetryPolicy.ts +550 -0
  645. package/src/Sleep.ts +296 -0
  646. package/src/Stall.ts +217 -0
  647. package/src/WaitFor.ts +228 -0
  648. package/src/index.ts +125 -0
  649. package/src/internal/BoundedJson.ts +109 -0
  650. package/src/internal/DeclarationSite.ts +214 -0
  651. package/src/internal/Declarations.ts +49 -0
  652. package/src/internal/ExecutionMiddleware.ts +29 -0
  653. package/src/internal/JsonSchemaSubset.ts +392 -0
  654. package/src/internal/OutcomeMarker.ts +19 -0
@@ -0,0 +1,1289 @@
1
+ /**
2
+ * The body interpreter: what a flow does when it runs.
3
+ *
4
+ * A `Flow` has no handler to register — its `body` IS the behavior, per
5
+ * `docs/concepts/flows-and-actions.md` — so something has to turn
6
+ * the graph that body describes into execution. That is this
7
+ * module. {@link layer} registers a flow with the runtime, and the
8
+ * handler it installs builds the graph with {@link module:Graph.build} and
9
+ * walks it: each node settles once, in dependency order, and the root's value
10
+ * is the flow's result.
11
+ *
12
+ * What each variant does is the run-time half of what the AST recorded. An
13
+ * `ActionCall` runs its declaration's implementation — looked up by tag in
14
+ * {@link module:Implementations.Implementations} before the walk starts — as
15
+ * the ordinary durable action `toLayer` built, so a node driven here takes
16
+ * the same attempt journal, retry policy, and tier as the same action called
17
+ * from a handler. Its invocation identity additionally folds this node's
18
+ * structural address, keeping concurrent graph sites replay-stable. A `Map`
19
+ * applies its deferred function to the real upstream value. A `Branch`
20
+ * evaluates its digested predicate on the real
21
+ * subject and settles ONLY the arm it took: the other arm is topology the plan
22
+ * shows and the run skipped, and it is reported as such rather than silently
23
+ * absent. An `All` joins its members by name, a `Succeed` yields its value, and
24
+ * an inline `FlowCall` was already flattened by graph building, so it settles
25
+ * with the body spliced beneath it. A `FlowCall` the author wrote as
26
+ * `.child(payload)` is the one node that is NOT flattened: it opens a real child
27
+ * execution under a deterministically derived id
28
+ * ({@link childExecutionId}), which is what gives it its own journal lineage and
29
+ * makes the parent's interruption and the child's suspension travel between
30
+ * them.
31
+ *
32
+ * Planned references are resolved the way the plan names them: a payload
33
+ * placeholder carries the `Ref` `{from, path}` its key material recorded, so
34
+ * `result.files` reads `files` off the settled value of the node that produced
35
+ * it.
36
+ *
37
+ * The walk is demand-driven from the root rather than a sweep over the node
38
+ * list, because dependency order puts BOTH branch arms before the branch that
39
+ * chooses between them, and executing an arm to discover it was not taken is
40
+ * exactly what static topology exists to avoid.
41
+ *
42
+ * @since 0.1.0
43
+ */
44
+ import { isRecord } from "@smthrs/canonical/Record";
45
+ import * as CapabilitySet from "@smthrs/capability/CapabilitySet";
46
+ import { DerivedKey, digest } from "@smthrs/keys";
47
+ import { isFatalDiagnostic } from "@smthrs/plan/GraphBuildError";
48
+ import * as KeyMaterial from "@smthrs/plan/KeyMaterial";
49
+ import * as Node from "@smthrs/plan/Node";
50
+ import * as Planned from "@smthrs/plan/Planned";
51
+ import * as StepKey from "@smthrs/plan/StepKey";
52
+ import * as Cause from "effect/Cause";
53
+ import * as Context from "effect/Context";
54
+ import * as Deferred from "effect/Deferred";
55
+ import * as Effect from "effect/Effect";
56
+ import * as Exit from "effect/Exit";
57
+ import * as Layer from "effect/Layer";
58
+ import * as Option from "effect/Option";
59
+ import * as Predicate from "effect/Predicate";
60
+ import * as Schema from "effect/Schema";
61
+ import * as Scope from "effect/Scope";
62
+ import { Implementations, layerImplementations } from "./Action/Implementations.js";
63
+ import { DispatchReport, DispatchSite } from "./Action/StepIdentity.js";
64
+ import * as DurableDeferred from "./DurableDeferred.js";
65
+ import { attenuateCapabilities } from "./Flow/CapabilityCeiling.js";
66
+ import * as Outcome from "./Flow/Outcome.js";
67
+ import { Handoff } from "./Flow/Result.js";
68
+ import { suspend } from "./Flow/Runtime.js";
69
+ import { TypeId as FlowTypeId } from "./Flow/TypeId.js";
70
+ import { FlowInstance } from "./FlowRuntime/FlowInstance.js";
71
+ import { FlowRuntime } from "./FlowRuntime/FlowRuntime.js";
72
+ import { annotateWaiting } from "./FlowRuntime/WaitingAnnotation.js";
73
+ import * as Graph from "./Graph.js";
74
+ import * as HumanTask from "./HumanTask.js";
75
+ import * as BoundedJson from "./internal/BoundedJson.js";
76
+ import { ExecutionMiddleware } from "./internal/ExecutionMiddleware.js";
77
+ import { OutcomeValueTypeId } from "./internal/OutcomeMarker.js";
78
+ import * as Sleep from "./Sleep.js";
79
+ import * as WaitFor from "./WaitFor.js";
80
+ /**
81
+ * A graph the interpreter will not drive.
82
+ *
83
+ * Every code names something the run cannot recover from on its own: a graph
84
+ * whose topology is incomplete, an action with no implementation wired up, a
85
+ * call the interpreter does not execute, and a deferred function that did not
86
+ * survive serialization beside its AST. `missing_implementation_version`
87
+ * names a content-reusable action that lacks the canonical version contract;
88
+ * `implementation_version_mismatch` names a declaration and registry that
89
+ * disagree. Both are preflight failures, before action dispatch.
90
+ * `join_mismatch` names a race, any, or quorum whose journaled decision this
91
+ * plan's members can no longer reproduce. `plan_changed` refuses a durable
92
+ * resume whose rebuilt graph differs from its first recorded plan.
93
+ *
94
+ * @category errors
95
+ * @since 0.1.0
96
+ */
97
+ export class InterpreterError extends Schema.TaggedError()("@smthrs/flow/InterpreterError", {
98
+ code: Schema.Literals([
99
+ "incomplete_graph",
100
+ "duplicate_node_id",
101
+ "unresolved_action",
102
+ "implementation_version_mismatch",
103
+ "missing_implementation_version",
104
+ "unresolved_reference",
105
+ "unsupported_call",
106
+ "missing_operation",
107
+ "node_record_too_large",
108
+ "plan_changed",
109
+ "join_mismatch"
110
+ ]),
111
+ flow: Schema.String,
112
+ node: Schema.String,
113
+ message: Schema.String
114
+ }) {
115
+ }
116
+ /** Reads one own data property without invoking an accessor or letting a proxy trap escape. */
117
+ const ownDataProperty = (value, key) => {
118
+ if (Object(value) !== value)
119
+ return undefined;
120
+ try {
121
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
122
+ return descriptor !== undefined && "value" in descriptor ? descriptor.value : undefined;
123
+ }
124
+ catch {
125
+ return undefined;
126
+ }
127
+ };
128
+ /**
129
+ * The execution id a `.child()` boundary runs its child under.
130
+ *
131
+ * DECIDED: the id is DERIVED from the parent
132
+ * execution and the child node's structural address, not minted. That is what
133
+ * makes a boundary at-most-once under replay, exactly as
134
+ * `docs/concepts/trampoline-rounds.md` requires of a round handoff: a
135
+ * parent that is re-driven re-derives the same id, so the engine lands on the
136
+ * child execution that already exists instead of starting a second copy of it.
137
+ * The canonical tuple includes the callee and a canonical payload digest, so
138
+ * delimiter splicing and a changed invocation cannot alias an earlier child.
139
+ * SHA-256 uses the same injected derivation services as the repository's
140
+ * other durable identities. The versioned key prefix is dropped because the
141
+ * child-id wire format is the bare digest. `digest` owns the
142
+ * prefix knowledge, so this package never guesses at a stored-key format.
143
+ *
144
+ * @since 0.1.0
145
+ * @category constructors
146
+ */
147
+ export const childExecutionId = (parentExecutionId, nodeId, calleeTag, payload) => Effect.gen(function* () {
148
+ const payloadDigest = yield* Schema.decodeUnknownEffect(DerivedKey)(payload).pipe(Effect.orDie);
149
+ const tupleDigest = yield* Schema.decodeUnknownEffect(DerivedKey)([
150
+ parentExecutionId,
151
+ nodeId,
152
+ calleeTag,
153
+ payloadDigest
154
+ ]).pipe(Effect.orDie);
155
+ return digest(tupleDigest);
156
+ });
157
+ /**
158
+ * The largest encoded page of a recorded plan.
159
+ *
160
+ * A journal entry has a byte bound and a projection clips an oversized one, so
161
+ * a graph is PAGED rather than truncated: whatever does not fit in the plan
162
+ * record follows as appended subgraph pages. The budget is deliberately well
163
+ * under the 16 KiB gateway limit on graph events. The runtime measures the
164
+ * encoded journal envelope; absent that hook, the complete node record is
165
+ * measured in UTF-8. A node too large for one page is a typed preflight refusal.
166
+ *
167
+ * @since 1.0.0
168
+ * @category constants
169
+ */
170
+ export const maximumPageBytes = 12_000;
171
+ /**
172
+ * How many distinct step key digests one node's settlement names.
173
+ *
174
+ * A journal entry has a byte bound and a digest is 64 characters, so the list
175
+ * is capped rather than left to grow with whatever a node dispatched. The
176
+ * cap is far above what any node reaches today — an action node drives one
177
+ * dispatch and keeps one step key however many times it is retried — and a
178
+ * node past it names the dispatches it started with rather than none.
179
+ *
180
+ * @since 1.0.0
181
+ * @category constants
182
+ */
183
+ export const maximumDispatchDigests = 16;
184
+ /** The declared tag a node dispatches, if it dispatches one. @private */
185
+ const actionTag = (ast) => ast._tag === "ActionCall" ? ast.action : ast._tag === "FlowCall" ? ast.flow : undefined;
186
+ /** What one node of a driven graph tells a monitor about itself. @private */
187
+ const summarize = (node) => {
188
+ const action = actionTag(node.ast);
189
+ return {
190
+ id: node.id,
191
+ kind: node.kind,
192
+ dependsOn: KeyMaterial.dependencies(node.draft.material),
193
+ tier: node.draft.material.kind,
194
+ effects: node.draft.effects,
195
+ ...(action === undefined ? {} : { action }),
196
+ ...(node.declaredAt === undefined ? {} : { declaredAt: node.declaredAt })
197
+ };
198
+ };
199
+ /**
200
+ * The graph, as the pages a journal can hold.
201
+ *
202
+ * Nothing about one node has to fit one page. A node's summary is seated on a
203
+ * page with no dependencies on it, and then its dependency list and the edges
204
+ * that END on it are spread over as many following pages as they need: a
205
+ * continuation page re-seats the same summary and carries the next disjoint
206
+ * slice of `dependsOn`, so a reader that unions `dependsOn` per node id and
207
+ * concatenates edges reassembles exactly the graph that was built. That is
208
+ * what lets an input-driven fan-in — `Node.all` over a caller-sized list — be
209
+ * recorded at any width instead of refused.
210
+ *
211
+ * A node's summary is seated no later than the first page naming one of its
212
+ * dependencies or one of its incoming edges, so an assembled PREFIX of pages
213
+ * never names an edge whose destination is unknown.
214
+ *
215
+ * The typed refusal is left for the one thing paging cannot divide: a node
216
+ * whose summary with NO dependencies on it still exceeds the budget.
217
+ *
218
+ * @private
219
+ */
220
+ const planPages = (flow, graph, measure) => Effect.gen(function* () {
221
+ const identity = yield* StepKey.content({
222
+ body: { flow, nodes: Graph.drafts(graph), edges: Graph.edges(graph) },
223
+ inputs: {},
224
+ layers: [],
225
+ capabilities: {}
226
+ }).pipe(Effect.mapError((cause) => new InterpreterError({
227
+ code: "incomplete_graph",
228
+ flow,
229
+ node: "root",
230
+ message: `Cannot identify recorded plan: ${String(cause)}`
231
+ })));
232
+ const incoming = new Map();
233
+ let edgeCount = 0;
234
+ for (const edge of Graph.edges(graph)) {
235
+ edgeCount += 1;
236
+ const summary = { from: edge.from, to: edge.to, reason: edge.reason };
237
+ const existing = incoming.get(edge.to);
238
+ if (existing === undefined)
239
+ incoming.set(edge.to, [summary]);
240
+ else
241
+ existing.push(summary);
242
+ }
243
+ const graphNodes = Graph.nodes(graph);
244
+ const pages = [];
245
+ let current = { nodes: [], edges: [] };
246
+ const record = (page, index, count) => ({
247
+ ...(index === 0
248
+ ? { _tag: "PlanRecorded", nodeCount: graphNodes.length, digest: identity }
249
+ : { _tag: "SubgraphAppended" }),
250
+ sourceId: `plan/0/${index}`,
251
+ flow,
252
+ generation: 0,
253
+ page: index,
254
+ pages: count,
255
+ ...page
256
+ });
257
+ // Every page is started by a node seat or by an edge, and a node is seated
258
+ // once plus at most once per dependency that starts a continuation page,
259
+ // so the page count is at most nodes + dependencies + edges. Reserving
260
+ // that many digits is what makes replacing the reservation with the final
261
+ // count shrink an encoded envelope or leave it alone, never grow it.
262
+ const reserved = graphNodes.reduce((total, node) => total + KeyMaterial.dependencies(node.draft.material).length, graphNodes.length + edgeCount);
263
+ const fits = (page) => Effect.map(measure(record(page, pages.length, reserved)), (bytes) => bytes <= maximumPageBytes);
264
+ const flush = () => {
265
+ pages.push(current);
266
+ current = { nodes: [], edges: [] };
267
+ };
268
+ /**
269
+ * How many of the remaining items the page still holds.
270
+ *
271
+ * A page only grows as items are added to it, so the boundary is found by
272
+ * bisection: a thousand-way fan-in costs a logarithmic number of
273
+ * measurements per page rather than one per item. Taking none is the page
274
+ * as it stands, which was measured before anything was offered to it.
275
+ */
276
+ const admits = (rest, grow) => Effect.gen(function* () {
277
+ if (yield* fits(grow(rest.length)))
278
+ return rest.length;
279
+ let low = 0;
280
+ let high = rest.length - 1;
281
+ while (low < high) {
282
+ const mid = low + Math.ceil((high - low) / 2);
283
+ if (yield* fits(grow(mid)))
284
+ low = mid;
285
+ else
286
+ high = mid - 1;
287
+ }
288
+ return low;
289
+ });
290
+ /**
291
+ * Puts every item somewhere, starting a page whenever the current one is
292
+ * full. `resume` prepares a freshly started page so what follows still
293
+ * says which node it belongs to, and a page that was just started and
294
+ * admits nothing is the end of what paging can do.
295
+ */
296
+ const spread = (items, onto, resume, refusal) => Effect.gen(function* () {
297
+ let rest = items;
298
+ let started = false;
299
+ while (rest.length > 0) {
300
+ const take = yield* admits(rest, (count) => onto(current, rest.slice(0, count)));
301
+ if (take > 0) {
302
+ current = onto(current, rest.slice(0, take));
303
+ rest = rest.slice(take);
304
+ started = false;
305
+ continue;
306
+ }
307
+ if (started)
308
+ return yield* refusal();
309
+ flush();
310
+ current = resume(current);
311
+ started = true;
312
+ }
313
+ });
314
+ for (const node of graphNodes) {
315
+ const summary = summarize(node);
316
+ const arriving = incoming.get(node.id) ?? [];
317
+ // The summary alone first. What a page must hold whole is the node
318
+ // itself, and that is the only thing left to refuse.
319
+ const bare = { ...summary, dependsOn: [] };
320
+ const seat = (page) => ({ nodes: [...page.nodes, bare], edges: page.edges });
321
+ const tooLarge = () => new InterpreterError({
322
+ code: "node_record_too_large",
323
+ flow,
324
+ node: node.id,
325
+ message: `Node "${node.id}" and its encoded envelope exceed ${maximumPageBytes} bytes with no dependencies on it`
326
+ });
327
+ if (!(yield* fits(seat(current)))) {
328
+ if (current.nodes.length > 0 || current.edges.length > 0)
329
+ flush();
330
+ if (!(yield* fits(seat(current))))
331
+ return yield* tooLarge();
332
+ }
333
+ current = seat(current);
334
+ // Then its dependencies, onto the summary the page just seated, and then
335
+ // the edges that end on it. Either may run past this page onto the next.
336
+ yield* spread(summary.dependsOn, (page, taken) => {
337
+ const seated = page.nodes[page.nodes.length - 1];
338
+ return {
339
+ nodes: [...page.nodes.slice(0, -1), { ...seated, dependsOn: [...seated.dependsOn, ...taken] }],
340
+ edges: page.edges
341
+ };
342
+ }, seat, tooLarge);
343
+ yield* spread(arriving, (page, taken) => ({ nodes: page.nodes, edges: [...page.edges, ...taken] }), (page) => page, tooLarge);
344
+ }
345
+ pages.push(current);
346
+ return pages.map((page, index) => record(page, index, pages.length));
347
+ });
348
+ /**
349
+ * Interprets a flow body, or a bare node, against real values.
350
+ *
351
+ * The graph is built first and in full — planning is a pure function of the
352
+ * declarations and the payload, so the whole shape of the round is known before
353
+ * the first action runs — and then driven. The low-level default permits
354
+ * process-local callbacks; pass `callbackIdentity: "stable"` for reproducible
355
+ * callback identity. {@link layerWithImplementations} selects that policy by
356
+ * default.
357
+ *
358
+ * @since 0.1.0
359
+ * @category constructors
360
+ */
361
+ export const interpret = (flowOrNode, payload, options = {}) => interpretWithPolicy(flowOrNode, payload, options);
362
+ /** Every interpreter requires versions before permitting content-key reuse. @private */
363
+ const interpretWithPolicy = (flowOrNode, payload, options, registerReachable) => Effect.gen(function* () {
364
+ const table = yield* Implementations;
365
+ const name = "_tag" in flowOrNode ? flowOrNode._tag : "node";
366
+ const refuse = (code, node, message) => Effect.fail(new InterpreterError({ code, flow: name, node, message }));
367
+ const graph = yield* Effect.try({
368
+ try: () => Graph.build(flowOrNode, payload, options),
369
+ catch: (cause) => {
370
+ // Graph.build normalizes its own refusals to GraphBuildError, but the
371
+ // flow body runs inside this boundary and a body throws whatever it
372
+ // throws. Reading `node` and `message` off the value without checking
373
+ // built an InterpreterError its own schema rejects, and the
374
+ // constructor's "Schema validation failed" then replaced the reason
375
+ // the author needed. All three fields are read through own data
376
+ // descriptors and narrowed here so a plain Error from a body arrives
377
+ // as a typed failure that still says why. A body that threw produced no
378
+ // topology, so it reports `incomplete_graph`.
379
+ const refusalNode = ownDataProperty(cause, "node");
380
+ const refusalCode = ownDataProperty(cause, "code");
381
+ const refusalMessage = ownDataProperty(cause, "message");
382
+ const node = typeof refusalNode === "string" ? refusalNode : "";
383
+ const reported = typeof refusalMessage === "string" ? refusalMessage : "";
384
+ return new InterpreterError({
385
+ code: refusalCode === "duplicate_node" ? "duplicate_node_id" : "incomplete_graph",
386
+ flow: name,
387
+ node,
388
+ message: reported === ""
389
+ ? `building the graph of flow ${name} threw ${typeof cause === "string" ? cause : BoundedJson.render(cause, 512)}`
390
+ : reported
391
+ });
392
+ }
393
+ });
394
+ const graphNodes = Graph.nodes(graph);
395
+ const byId = new Map(graphNodes.map((node) => [node.id, node]));
396
+ // Advisory diagnostics describe a graph that is exactly what will run, so
397
+ // they are reported by `Graph.diagnostics` and do not stop a run. A fatal
398
+ // one means the topology is not what the author wrote.
399
+ const fatal = graph.diagnostics.find(isFatalDiagnostic);
400
+ if (fatal !== undefined) {
401
+ return yield* refuse("incomplete_graph", fatal.node, `Graph of "${name}" is missing topology and cannot be driven: ${fatal.message}`);
402
+ }
403
+ /**
404
+ * The node records this walk writes, if the runtime keeps any.
405
+ *
406
+ * A runtime without the seam costs a comparison per node and nothing else:
407
+ * the record is built by the thunk only when something will hold it.
408
+ */
409
+ const runtime = yield* FlowRuntime;
410
+ const recordNode = runtime.recordNode;
411
+ const record = recordNode === undefined
412
+ ? (_) => Effect.void
413
+ : (make) => recordNode(make());
414
+ // The whole graph, before the first node runs. Planning is pure, so this
415
+ // is the complete declared ceiling of the round rather than a prefix of
416
+ // what happened to run, and a monitor can draw the round it is watching
417
+ // from the first record it receives.
418
+ if (recordNode !== undefined) {
419
+ const measure = runtime.nodeRecordBytes ??
420
+ ((record) => Effect.succeed(new TextEncoder().encode(JSON.stringify(record)).byteLength));
421
+ // Validate every page before writing the first or dispatching any action.
422
+ const pages = yield* planPages(name, graph, measure);
423
+ yield* Effect.forEach(pages, (page) => recordNode(page), { discard: true });
424
+ }
425
+ // Everything the walk needs that the built graph can be asked for before it
426
+ // runs, is asked for here — so no such refusal can surface halfway through a
427
+ // body with the actions ahead of it already committed.
428
+ //
429
+ // A reference out of the graph is the first: a round may be PLANNED against
430
+ // a node an earlier generation settled — `Plan.append` exists for exactly
431
+ // that — but one interpretation settles one graph, so there is nothing to
432
+ // read it from. A missing implementation is the second, and it is a wiring
433
+ // error rather than a run-time contingency: every action the graph names
434
+ // is resolved up front, including the ones only an untaken branch arm would
435
+ // have reached, because the plan is the declared ceiling of what may run.
436
+ // Deferred operations must likewise survive beside every AST, even when
437
+ // the walk would skip their branch or catch arm.
438
+ const implementations = new Map();
439
+ const handoffDeclarations = new Map();
440
+ const childDeclarations = new Map();
441
+ for (const node of graphNodes) {
442
+ const ast = node.ast;
443
+ if (ast._tag === "Map" && Node.mapper(ast) === undefined) {
444
+ return yield* refuse("missing_operation", node.id, `Map at "${node.id}" lost its mapper.`);
445
+ }
446
+ if (ast._tag === "Branch" && Node.predicate(ast) === undefined) {
447
+ return yield* refuse("missing_operation", node.id, `Branch at "${node.id}" lost its predicate.`);
448
+ }
449
+ if (ast._tag === "Catch" && ast.filter !== undefined && Node.catchFilter(ast) === undefined) {
450
+ return yield* refuse("missing_operation", node.id, `Catch at "${node.id}" lost its schema filter.`);
451
+ }
452
+ for (const dependency of KeyMaterial.dependencies(node.draft.material)) {
453
+ if (byId.has(dependency))
454
+ continue;
455
+ return yield* refuse("unresolved_reference", node.id, `Node "${node.id}" reads "${dependency}", which this graph does not hold.`);
456
+ }
457
+ }
458
+ // Diagnose lost operations before action declarations, regardless of graph order.
459
+ for (const node of graphNodes) {
460
+ if (node.ast._tag === "FlowCall" && node.ast.mode === "handoff") {
461
+ const declaration = Node.declaration(node.ast);
462
+ if (!Predicate.hasProperty(declaration, FlowTypeId)) {
463
+ return yield* refuse("unsupported_call", node.id, `Handoff to flow "${node.ast.flow}" at "${node.id}" lost its declaration. ` +
464
+ "Build and interpret the authored node in the same process so its payload can be encoded.");
465
+ }
466
+ handoffDeclarations.set(node.id, declaration);
467
+ if (registerReachable !== undefined)
468
+ yield* registerReachable(declaration);
469
+ continue;
470
+ }
471
+ if (node.ast._tag === "FlowCall" && node.ast.mode === "boundary") {
472
+ // A boundary is one node here and a real execution underneath, so what
473
+ // it needs resolved up front is the callee itself: the declaration is
474
+ // what `execute` is called on, and losing it is a wiring error rather
475
+ // than a run-time contingency, exactly like an unimplemented action.
476
+ const declaration = Node.declaration(node.ast);
477
+ if (!Predicate.hasProperty(declaration, FlowTypeId)) {
478
+ return yield* refuse("unsupported_call", node.id, `Child boundary to flow "${node.ast.flow}" at "${node.id}" lost its declaration. ` +
479
+ "Build and interpret the authored node in the same process so the child can be executed.");
480
+ }
481
+ childDeclarations.set(node.id, declaration);
482
+ if (registerReachable !== undefined)
483
+ yield* registerReachable(declaration);
484
+ continue;
485
+ }
486
+ if (node.ast._tag !== "ActionCall")
487
+ continue;
488
+ const implementation = yield* table.get(node.ast.action);
489
+ if (Option.isNone(implementation)) {
490
+ return yield* refuse("unresolved_action", node.id, `Action "${node.ast.action}" has no implementation. ` +
491
+ `Provide ONE Action.layerImplementations under both ${node.ast.action}.toLayer(execute) and ` +
492
+ "this interpreter layer: an implementation files itself with the table that is in scope " +
493
+ "while IT is built, so a table merged beside it, or a second one built above it, is not the " +
494
+ "table this driver reads.");
495
+ }
496
+ const declaration = Node.declaration(node.ast);
497
+ const declaredVersion = ownDataProperty(declaration, "implementationVersion");
498
+ const tier = ownDataProperty(declaration, "tier");
499
+ if (tier === undefined) {
500
+ return yield* refuse("incomplete_graph", node.id, `Action "${node.ast.action}" lost its declaration, so its implementation identity cannot be checked. ` +
501
+ "Build the canonical composition from the authored action nodes.");
502
+ }
503
+ if (tier === "sealed" && ownDataProperty(declaration, "idempotencyKey") !== undefined &&
504
+ declaredVersion === undefined) {
505
+ return yield* refuse("missing_implementation_version", node.id, `Sealed action "${node.ast.action}" declares an idempotency key and can reuse recorded content. ` +
506
+ "Declare implementationVersion on Action.make and attest the same version in toLayer.");
507
+ }
508
+ if (declaredVersion !== implementation.value.implementationVersion) {
509
+ return yield* refuse("implementation_version_mismatch", node.id, `Action "${node.ast.action}" does not match its registered implementationVersion. ` +
510
+ "Register the declared version and start a newly planned execution when its semantics change.");
511
+ }
512
+ implementations.set(node.ast.action, implementation.value);
513
+ }
514
+ // Graph.build also accepts authored references. Unlike Plan.compile, this
515
+ // entry point has not yet checked them for cycles: a self-reference would
516
+ // join its own in-flight deferred forever. Validate the entire dependency
517
+ // graph before dispatch, including branch arms the execution might skip.
518
+ const remaining = new Map();
519
+ const dependents = new Map();
520
+ const ready = [];
521
+ for (const node of graphNodes) {
522
+ const dependencies = KeyMaterial.dependencies(node.draft.material);
523
+ remaining.set(node.id, dependencies.length);
524
+ if (dependencies.length === 0)
525
+ ready.push(node.id);
526
+ for (const dependency of dependencies) {
527
+ const consumers = dependents.get(dependency);
528
+ if (consumers === undefined)
529
+ dependents.set(dependency, [node.id]);
530
+ else
531
+ consumers.push(node.id);
532
+ }
533
+ }
534
+ for (let index = 0; index < ready.length; index++) {
535
+ for (const consumer of dependents.get(ready[index]) ?? []) {
536
+ const count = remaining.get(consumer) - 1;
537
+ remaining.set(consumer, count);
538
+ if (count === 0)
539
+ ready.push(consumer);
540
+ }
541
+ }
542
+ if (ready.length !== graphNodes.length) {
543
+ const blocked = graphNodes.find((node) => remaining.get(node.id) > 0);
544
+ return yield* refuse("incomplete_graph", blocked.id, `Graph of "${name}" contains a dependency cycle blocking "${blocked.id}". ` +
545
+ "Use an acyclic reference, a child boundary, or a trampoline handoff.");
546
+ }
547
+ // The children a node settles with, in the order graph building recorded
548
+ // them: `first` then the arms of a branch, `first` then the continuation of
549
+ // a sequence, the members of a combination, the spliced body of an inline
550
+ // call. Payload references are NOT here — they are named by the key
551
+ // material, and settled from it.
552
+ const sources = new Map();
553
+ for (const edge of Graph.edges(graph)) {
554
+ if (edge.reason !== "value")
555
+ continue;
556
+ sources.set(edge.to, [...sources.get(edge.to) ?? [], edge.from]);
557
+ }
558
+ const settled = new Map();
559
+ const failed = new Map();
560
+ /**
561
+ * Projects a settled value along the property path a `Ref` recorded —
562
+ * through `StepKey.project`, the one projection semantics for the value
563
+ * channel. The scheduler digests exactly what this returns; resolving a
564
+ * `Ref` any other way here would let two executions that key identically
565
+ * consume different values.
566
+ */
567
+ const project = StepKey.project;
568
+ /**
569
+ * Replaces every placeholder in a hydrated payload with what it stands for.
570
+ *
571
+ * The record is rebuilt with a null prototype and `defineProperty`, for the
572
+ * reason {@link module:Graph.build}'s cloners are: `output[key] = …` on an
573
+ * object literal routes `__proto__` through `Object.prototype`'s accessor,
574
+ * which drops an own `__proto__` field carrying a primitive and reparents
575
+ * the clone when it carries an object. A graph hydrates that field as data,
576
+ * so the value handed to an action has to keep it as data too.
577
+ */
578
+ const resolve = (value) => {
579
+ const reference = Planned.reference(value);
580
+ if (reference !== undefined) {
581
+ return project(settled.has(reference.node) ? settled.get(reference.node) : failed.get(reference.node), reference.path);
582
+ }
583
+ if (Array.isArray(value))
584
+ return value.map((item) => resolve(item));
585
+ if (!isRecord(value))
586
+ return value;
587
+ const output = Object.create(null);
588
+ for (const key of Object.keys(value)) {
589
+ Object.defineProperty(output, key, {
590
+ configurable: true,
591
+ enumerable: true,
592
+ value: resolve(value[key]),
593
+ writable: true
594
+ });
595
+ }
596
+ const outcome = Object.getOwnPropertyDescriptor(value, OutcomeValueTypeId);
597
+ if (outcome !== undefined && "value" in outcome) {
598
+ Object.defineProperty(output, OutcomeValueTypeId, {
599
+ configurable: false,
600
+ enumerable: false,
601
+ value: outcome.value,
602
+ writable: false
603
+ });
604
+ }
605
+ return output;
606
+ };
607
+ /**
608
+ * The settlement currently in flight for a node, for as long as it is.
609
+ *
610
+ * `settled.has(id)` alone is not a memo once the walk runs concurrently: it
611
+ * answers "has this node FINISHED", and two demands that arrive while the
612
+ * node is still running both see `false` and both execute it. A diamond
613
+ * would then run its shared node twice, which for an action with effects is
614
+ * a correctness bug rather than a wasted cycle.
615
+ *
616
+ * The check-and-register below is the whole reason this is a `suspend` and
617
+ * not a generator: the callback runs synchronously, so no other fiber can
618
+ * observe the gap between the lookup and the insert.
619
+ *
620
+ * Every computation runs on a fiber forked into `nodes`, the
621
+ * interpretation's own scope, and every demand — the first included — is a
622
+ * join on the node's deferred. Ownership by the interpretation rather than
623
+ * by whichever demand arrived first is what makes a ref-diamond sound: a
624
+ * failing `All` interrupts its member JOINS, never a shared node's
625
+ * execution, so recovery arms above can still join the shared work; and
626
+ * when the walk itself ends, closing the scope interrupts whatever is
627
+ * still running, so an orphaned execution cannot outlive the
628
+ * interpretation or write a phantom success into `settled` afterwards
629
+ * (Skyframe's and `MemoMap`'s ownership model).
630
+ */
631
+ const inFlight = new Map();
632
+ const nodes = yield* Scope.make();
633
+ /**
634
+ * The execution fiber of every node still running, so a join that settled
635
+ * early can interrupt the work of the members it no longer waits for.
636
+ */
637
+ const executions = new Map();
638
+ /**
639
+ * The child execution id each `.child()` node opened. Interrupting the
640
+ * node's fiber only stops its join: a losing child is cancelled through
641
+ * the runtime, the same request a caller's cancellation makes.
642
+ */
643
+ const childExecutions = new Map();
644
+ /**
645
+ * The nodes this walk has already settled a record for.
646
+ *
647
+ * Everything else is what the walk never reached, which is exactly the
648
+ * `skipped` set reported below — an untaken branch arm, or a dependent of
649
+ * something that failed.
650
+ */
651
+ const reported = new Set();
652
+ const settleNode = (id) => Effect.suspend(() => {
653
+ if (settled.has(id))
654
+ return Effect.succeed(settled.get(id));
655
+ const waiting = inFlight.get(id);
656
+ // A later demand joins the execution rather than starting one.
657
+ if (waiting !== undefined)
658
+ return Deferred.await(waiting);
659
+ const deferred = Deferred.makeUnsafe();
660
+ inFlight.set(id, deferred);
661
+ const node = byId.get(id);
662
+ const action = actionTag(node.ast);
663
+ // What this node's dispatches did, reported by the engine underneath
664
+ // it: a node whose dispatches were ALL served from durable records
665
+ // rebuilt nothing, and says so. The digests name those dispatches, so
666
+ // the attempt rows the engine wrote under them belong to THIS node,
667
+ // and the highest attempt reported is the node's real attempt count.
668
+ // A `Set` keeps the digests unrepeated in report order: one dispatch
669
+ // retried three times keeps one step key and reports it three times.
670
+ const dispatches = { executed: 0, replayed: 0, attempts: 1, digests: new Set() };
671
+ const settleRecord = (outcome, settlement) => () => ({
672
+ _tag: "NodeSettled",
673
+ sourceId: `node/${id}/1/settled`,
674
+ nodeId: id,
675
+ outcome,
676
+ attempts: dispatches.attempts,
677
+ stepKeyDigests: [...dispatches.digests],
678
+ value: settlement.value,
679
+ ...(action === undefined ? {} : { action })
680
+ });
681
+ const execution = record(() => ({
682
+ _tag: "NodeScheduled",
683
+ sourceId: `node/${id}/1`,
684
+ nodeId: id,
685
+ kind: node.kind,
686
+ attempt: 1,
687
+ ...(action === undefined ? {} : { action })
688
+ })).pipe(Effect.andThen(compute(node).pipe(Effect.provideService(DispatchReport, DispatchReport.of({
689
+ dispatched: (dispatch) => Effect.sync(() => {
690
+ if (dispatch.outcome === "executed")
691
+ dispatches.executed = dispatches.executed + 1;
692
+ else
693
+ dispatches.replayed = dispatches.replayed + 1;
694
+ // Bounded where it is COLLECTED, not where it is
695
+ // written: a cap applied at the end still holds every
696
+ // digest in memory until then, and the point of the cap
697
+ // is that one node cannot grow without bound.
698
+ if (dispatch.stepKeyDigest !== undefined &&
699
+ dispatches.digests.size < maximumDispatchDigests) {
700
+ dispatches.digests.add(dispatch.stepKeyDigest);
701
+ }
702
+ if (dispatch.attempt !== undefined && dispatch.attempt > dispatches.attempts) {
703
+ dispatches.attempts = dispatch.attempt;
704
+ }
705
+ })
706
+ })))), Effect.tap((value) => Effect.sync(() => {
707
+ settled.set(id, value);
708
+ reported.add(id);
709
+ }).pipe(Effect.andThen(record(settleRecord(dispatches.executed === 0 && dispatches.replayed > 0 ? "clean" : "built", { value }))))), Effect.tapError((error) => Effect.sync(() => {
710
+ failed.set(id, error);
711
+ reported.add(id);
712
+ }).pipe(Effect.andThen(record(settleRecord("failed", { value: error }))))), Effect.onExit((exit) => {
713
+ // An interrupted execution is evicted, not memoized: current
714
+ // joiners observe the interruption, but a LATER demand — a
715
+ // recovery arm, a re-driven walk — re-executes the node instead
716
+ // of replaying an interrupt that says nothing about it.
717
+ if (Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause))
718
+ inFlight.delete(id);
719
+ executions.delete(id);
720
+ return Deferred.done(deferred, exit);
721
+ }));
722
+ // `startImmediately` keeps the first demand's latency identical to the
723
+ // old inline execution: the node runs synchronously until its first
724
+ // real suspension, so a body that parks does so before the driver's
725
+ // next tick — the same observable cadence a sequential walk had.
726
+ return Effect.forkIn(Effect.withFiber((fiber) => {
727
+ executions.set(id, fiber);
728
+ return execution;
729
+ }), nodes, { startImmediately: true }).pipe(Effect.andThen(Deferred.await(deferred)));
730
+ });
731
+ /**
732
+ * The nodes that read each node's value through their key material: the
733
+ * payload references and barriers a structural subtree does not show.
734
+ */
735
+ const readers = new Map();
736
+ for (const node of graphNodes) {
737
+ for (const dependency of KeyMaterial.dependencies(node.draft.material)) {
738
+ readers.set(dependency, [...readers.get(dependency) ?? [], node.id]);
739
+ }
740
+ }
741
+ /**
742
+ * The work of the members a join no longer waits for: their running node
743
+ * fibers and the child executions those nodes opened.
744
+ *
745
+ * A member's structural subtree is its own, so its running executions are
746
+ * interrupted; nothing else demands them again. A node something outside that
747
+ * subtree also reads is shared work the interpretation owns — the same
748
+ * ownership an `All` failure respects — and keeps running, together with
749
+ * everything inside the subtree it depends on.
750
+ */
751
+ // Graph building gives every node exactly one structural parent and reads
752
+ // each child through that parent's key material, so the walk below never
753
+ // reaches a node twice and every node in a subtree has a reader.
754
+ const losingWork = (joinId, roots) => {
755
+ const subtree = new Set();
756
+ const pending = [...roots];
757
+ while (pending.length > 0) {
758
+ const id = pending.pop();
759
+ subtree.add(id);
760
+ pending.push(...sources.get(id) ?? []);
761
+ }
762
+ const kept = new Set();
763
+ const shared = [...subtree].filter((id) => readers.get(id).some((reader) => reader !== joinId && !subtree.has(reader)));
764
+ while (shared.length > 0) {
765
+ const id = shared.pop();
766
+ if (kept.has(id) || !subtree.has(id))
767
+ continue;
768
+ kept.add(id);
769
+ shared.push(...sources.get(id) ?? [], ...KeyMaterial.dependencies(byId.get(id).draft.material));
770
+ }
771
+ const fibers = [];
772
+ const childRuns = [];
773
+ for (const id of subtree) {
774
+ if (kept.has(id))
775
+ continue;
776
+ const fiber = executions.get(id);
777
+ if (fiber === undefined)
778
+ continue;
779
+ fibers.push(fiber);
780
+ const executionId = childExecutions.get(id);
781
+ if (executionId !== undefined)
782
+ childRuns.push({ node: id, executionId });
783
+ }
784
+ return { fibers, childRuns };
785
+ };
786
+ /**
787
+ * Cancels the child executions a join's losers opened, through the
788
+ * runtime: interrupting a node's fiber only stops its join, so a losing
789
+ * child is cancelled with the same request a caller's cancellation makes.
790
+ */
791
+ const cancelChildren = (childRuns) => Effect.forEach(childRuns, ({ executionId, node }) => Effect.orDie(runtime.interrupt(childDeclarations.get(node), executionId)), { discard: true });
792
+ /**
793
+ * Settles a `Race` node: `race`, `any`, or `quorum`.
794
+ *
795
+ * The members that decided are journaled, in the order they decided,
796
+ * under a durable deferred named for the node before any loser is
797
+ * interrupted. A resumed walk that finds the record settles exactly those
798
+ * members — whose own dispatches replay from their durable records — and
799
+ * never demands the others, so it reaches the same verdict without
800
+ * running a loser again. A defect or an interpreter refusal in a member is
801
+ * not a decision: it propagates unjournaled, as it would from an `All`.
802
+ *
803
+ * The same record names the child executions the losers had opened, so a
804
+ * process that dies between the journal write and their cancellation does
805
+ * not orphan them: the resumed walk never demands a loser, and it cancels
806
+ * those children from the record instead (#2892). Cancellation is a
807
+ * first-writer-wins request, so repeating it on every replay is harmless.
808
+ */
809
+ const join = (node, ast, children) => Effect.gen(function* () {
810
+ const members = Object.keys(ast.nodes);
811
+ const journal = DurableDeferred.make(`join/${node.id}`, { success: JoinDecision });
812
+ const instance = yield* FlowInstance;
813
+ // A join is not a wait: reading its record must not consume the
814
+ // waiting classification a parked sibling declared.
815
+ const waiting = instance.waiting;
816
+ const recorded = yield* runtime.deferredResult(journal);
817
+ instance.waiting = waiting;
818
+ if (Option.isSome(recorded) && Exit.isSuccess(recorded.value)) {
819
+ const record = recorded.value.value;
820
+ const decided = "members" in record ? record.members : record;
821
+ const opened = "members" in record ? record.children : [];
822
+ const indices = decided.map((member) => members.indexOf(member));
823
+ if (indices.some((index) => index < 0) || new Set(indices).size !== indices.length) {
824
+ return yield* refuse("join_mismatch", node.id, `Join at "${node.id}" journaled members ${JSON.stringify(decided)}, which it no longer holds.`);
825
+ }
826
+ const lost = opened.find((child) => !childDeclarations.has(child.node));
827
+ if (lost !== undefined) {
828
+ return yield* refuse("join_mismatch", node.id, `Join at "${node.id}" journaled a losing child at "${lost.node}", which the plan no longer holds.`);
829
+ }
830
+ yield* cancelChildren(opened);
831
+ // The losers are never demanded, so nothing of theirs starts again.
832
+ const exits = yield* Effect.forEach(indices, (index) => Effect.exit(settleNode(children[index])), {
833
+ concurrency: "unbounded"
834
+ });
835
+ // The verdict must close on the LAST journaled member, exactly as it
836
+ // did live: one that closes earlier, or never, is a different join.
837
+ const outcomes = [];
838
+ for (let position = 0; position < exits.length; position++) {
839
+ const exit = exits[position];
840
+ if (classify(exit) !== "decisive")
841
+ return yield* exit;
842
+ outcomes.push({ member: members[indices[position]], exit });
843
+ const verdict = decide(ast, members.length, outcomes);
844
+ if (verdict !== undefined && position === exits.length - 1)
845
+ return yield* verdict;
846
+ if (verdict !== undefined)
847
+ break;
848
+ }
849
+ return yield* refuse("join_mismatch", node.id, `Join at "${node.id}" replayed members ${JSON.stringify(decided)} without reaching its verdict.`);
850
+ }
851
+ const outcomes = [];
852
+ let verdict;
853
+ let journaled = false;
854
+ const over = Deferred.makeUnsafe();
855
+ const watch = (index) => Effect.exit(settleNode(children[index])).pipe(Effect.flatMap((exit) => Effect.sync(() => {
856
+ if (verdict !== undefined)
857
+ return;
858
+ const kind = classify(exit);
859
+ // An interrupted member is still undecided: it parked, or a
860
+ // join elsewhere cancelled shared work. The others may still
861
+ // decide without it.
862
+ if (kind === "pending")
863
+ return;
864
+ if (kind === "fatal") {
865
+ verdict = exit;
866
+ }
867
+ else {
868
+ outcomes.push({ member: members[index], exit });
869
+ verdict = decide(ast, members.length, outcomes);
870
+ journaled = verdict !== undefined;
871
+ }
872
+ if (verdict !== undefined)
873
+ Deferred.doneUnsafe(over, Exit.void);
874
+ })));
875
+ yield* Effect.raceFirst(Effect.forEach(children, (_, index) => watch(index), { concurrency: "unbounded", discard: true }), Deferred.await(over));
876
+ // Every member ended interrupted: the join cannot decide in this
877
+ // round, and the walk parks or ends with it.
878
+ if (verdict === undefined)
879
+ return yield* Effect.interrupt;
880
+ const decidedMembers = outcomes.map((outcome) => outcome.member);
881
+ yield* Effect.uninterruptible(Effect.gen(function* () {
882
+ const { childRuns, fibers } = losingWork(node.id, children.filter((_, index) => !decidedMembers.includes(members[index])));
883
+ if (journaled) {
884
+ yield* runtime.deferredDone(journal, {
885
+ flowName: instance.flow._tag,
886
+ executionId: instance.executionId,
887
+ deferredName: journal.name,
888
+ exit: Exit.succeed({ members: decidedMembers, children: childRuns })
889
+ });
890
+ }
891
+ // The interruption is requested, not awaited: a loser's finalizers
892
+ // may wait on work that only settles after the join returns, and
893
+ // the node scope awaits every fiber when the walk ends anyway.
894
+ yield* Effect.withFiber((current) => Effect.sync(() => {
895
+ for (const fiber of fibers)
896
+ fiber.interruptUnsafe(current.id);
897
+ }));
898
+ yield* cancelChildren(childRuns);
899
+ }));
900
+ return yield* verdict;
901
+ });
902
+ const compute = Effect.fnUntraced(function* (node) {
903
+ const children = sources.get(node.id) ?? [];
904
+ const ast = node.ast;
905
+ if (ast._tag === "AndThen" && ast.next !== undefined) {
906
+ // An explicit sequence is a success boundary for the WHOLE next
907
+ // subtree. Joining first and then concurrently lets a nested All,
908
+ // Map, or inline call start effects before its prerequisite settles.
909
+ // bindPlanned is distinct: it declares data dependencies and can
910
+ // expose independent work while the producer is still running.
911
+ yield* settleNode(children[0]);
912
+ return yield* settleNode(children[1]);
913
+ }
914
+ if (ast._tag === "Branch") {
915
+ // The predicate decides on the REAL value, and only the arm it chose
916
+ // is settled. Both arms are still in the plan; the untaken one is
917
+ // reported as skipped.
918
+ const decide = Node.predicate(ast);
919
+ const subject = yield* settleNode(children[0]);
920
+ return yield* settleNode(decide(subject) ? children[1] : children[2]);
921
+ }
922
+ if (ast._tag === "Catch") {
923
+ // DECIDED: catch observes only typed
924
+ // failures from ordinary protected execution. Interpreter refusals
925
+ // propagate unchanged. Effect defects and
926
+ // compensation failures remain outside this interpreter's error
927
+ // channel, so recovery cannot conceal a broken invariant or weaken
928
+ // withRollback's compensation guarantees.
929
+ const protectedId = children[0];
930
+ return yield* Effect.matchEffect(settleNode(protectedId), {
931
+ onFailure: (error) => {
932
+ if (Schema.is(InterpreterError)(error))
933
+ return Effect.fail(error);
934
+ const filter = Node.catchFilter(ast);
935
+ if (filter !== undefined && !Schema.is(filter)(error)) {
936
+ return Effect.fail(error);
937
+ }
938
+ // The failure arm's planned subject resolves through the
939
+ // protected node id. Filing the typed failure as that settlement
940
+ // also prevents its static failure edge from re-running the
941
+ // protected graph while the recovery arm is driven.
942
+ failed.set(protectedId, error);
943
+ return settleNode(children[1]);
944
+ },
945
+ onSuccess: Effect.succeed
946
+ });
947
+ }
948
+ if (ast._tag === "Race") {
949
+ // A join must not wait for every member, so its members are left
950
+ // out of the dependency barrier below; its other dependencies — the
951
+ // references and barriers it reads — still settle first.
952
+ const members = new Set(children);
953
+ yield* Effect.forEach(KeyMaterial.dependencies(node.draft.material).filter((dependency) => !members.has(dependency) && !failed.has(dependency)), settleNode, { concurrency: "unbounded", discard: true });
954
+ return yield* join(node, ast, children);
955
+ }
956
+ // Dependency order, from the key material: the same `Ref` and `Pending`
957
+ // inputs the plan turns into edges, settled before the node that reads
958
+ // them — and settled CONCURRENTLY, because independent dependencies are
959
+ // exactly what the scheduler admits under separate permits. Two
960
+ // execution surfaces disagreeing about concurrency is a correctness
961
+ // hazard, not just a latency one.
962
+ yield* Effect.forEach(KeyMaterial.dependencies(node.draft.material).filter((dependency) => !failed.has(dependency)), settleNode, { concurrency: "unbounded", discard: true });
963
+ switch (ast._tag) {
964
+ case "ActionCall":
965
+ // Resolved by the pre-pass above, which refuses the whole graph
966
+ // when an action it names has no implementation. The structural
967
+ // node address is durable dispatch identity, scoped to this one
968
+ // implementation call; it never comes from fiber arrival order.
969
+ return yield* implementations.get(ast.action).action(resolve(node.payload)).pipe(Effect.provideService(DispatchSite, node.id), attenuateCapabilities(node.capabilityCeilings));
970
+ case "Succeed":
971
+ return resolve(node.payload);
972
+ case "Fail":
973
+ // The typed error channel, from a constant the plan already holds.
974
+ // An enclosing catch observes it exactly as it observes an action's
975
+ // failure, and an uncaught one is the body's typed failure.
976
+ return yield* Effect.fail(resolve(node.payload));
977
+ case "Map": {
978
+ const transform = Node.mapper(ast);
979
+ return transform(yield* settleNode(children[0]));
980
+ }
981
+ case "All": {
982
+ // `All` is a combination, so its members settle concurrently — the
983
+ // same semantics `PlanScheduler` gives the same graph. Fail-fast
984
+ // matches `Effect.forEach`'s default and the scheduler's halt
985
+ // rule — with the ownership caveat: what a failure interrupts is
986
+ // each sibling's JOIN, not the node execution itself, which the
987
+ // interpretation owns and interrupts when the walk ends. A node
988
+ // whose execution was interrupted is evicted from the memo and
989
+ // records nothing, so it reports as skipped rather than as a
990
+ // phantom success.
991
+ const members = Object.keys(ast.nodes);
992
+ const values = yield* Effect.forEach(members, (_, index) => settleNode(children[index]), {
993
+ concurrency: "unbounded"
994
+ });
995
+ const joined = Object.create(null);
996
+ for (let index = 0; index < members.length; index++) {
997
+ Object.defineProperty(joined, members[index], {
998
+ configurable: true,
999
+ enumerable: true,
1000
+ value: values[index],
1001
+ writable: true
1002
+ });
1003
+ }
1004
+ return joined;
1005
+ }
1006
+ case "AndThen":
1007
+ return yield* settleNode(children[1]);
1008
+ case "FlowCall": {
1009
+ if (ast.mode === "handoff") {
1010
+ const declaration = handoffDeclarations.get(node.id);
1011
+ // DECIDED: a handoff target's schema
1012
+ // services come from the context registration captured. A
1013
+ // body's type cannot enumerate declarations hidden in its
1014
+ // topology, so erase only that dynamic service parameter after
1015
+ // resolving the concrete declaration here.
1016
+ const payload = yield* Effect.flatMap(Effect.orDie(declaration.payloadSchema.makeEffect(resolve(node.payload))), (decoded) => Effect.orDie(Schema.encodeEffect(Schema.toCodecJson(declaration.payloadSchema))(decoded)));
1017
+ const ceiling = (yield* attenuateCapabilities(node.capabilityCeilings)(CapabilitySet.current)).groups;
1018
+ const outcome = {
1019
+ _tag: "To",
1020
+ flow: ast.flow,
1021
+ payload,
1022
+ ...(ceiling.length === 0 ? {} : { capabilityCeilings: ceiling })
1023
+ };
1024
+ Object.defineProperty(outcome, OutcomeValueTypeId, {
1025
+ configurable: false,
1026
+ enumerable: false,
1027
+ value: "To",
1028
+ writable: false
1029
+ });
1030
+ return outcome;
1031
+ }
1032
+ if (ast.mode === "boundary") {
1033
+ // The real boundary of `docs/guides/run-a-child-flow.md`: an
1034
+ // ordinary child execution, opened through the same `execute` a
1035
+ // handler would call. The parent's `FlowInstance` is in scope, so
1036
+ // the engine records the lineage edge, interrupts the child with
1037
+ // the parent, and turns a suspended child into a suspended
1038
+ // parent — genuine nesting, not a spliced imitation of it. It is
1039
+ // deliberately NOT `Effect.scoped`: the interrupt link the engine
1040
+ // installs is a finalizer of the PARENT's scope, and closing a
1041
+ // scope of our own here would run it the moment the child
1042
+ // settled. The same dynamic schema-service erasure the handoff
1043
+ // above records applies to the cast: a body's type cannot
1044
+ // enumerate the declarations hidden in its topology.
1045
+ const declaration = childDeclarations.get(node.id);
1046
+ const instance = yield* FlowInstance;
1047
+ const childPayload = resolve(node.payload);
1048
+ const executionId = yield* childExecutionId(instance.executionId, node.id, declaration._tag, childPayload);
1049
+ childExecutions.set(node.id, executionId);
1050
+ return yield* declaration.execute(childPayload, {
1051
+ executionId
1052
+ }).pipe(attenuateCapabilities(node.capabilityCeilings));
1053
+ }
1054
+ const spliced = children[0];
1055
+ if (spliced === undefined) {
1056
+ return yield* refuse("unsupported_call", node.id, `Flow "${ast.flow}" is called at "${node.id}" as a leaf, which this interpreter does not drive. ` +
1057
+ "An inline .call() is spliced into the graph with the callee's body and driven with it, and " +
1058
+ "only a call that lost its declaration has no body to splice. Build and interpret the authored " +
1059
+ `node in the same process, or call it as ${ast.flow}.child(payload) to run it as its own execution.`);
1060
+ }
1061
+ return yield* settleNode(spliced);
1062
+ }
1063
+ }
1064
+ });
1065
+ // Closing the node scope on every exit — value, failure, or the
1066
+ // interpretation's own interruption — is the fail-fast half of the
1067
+ // ownership model: whatever is still running when the walk ends is
1068
+ // interrupted before the interpretation reports, so no execution
1069
+ // outlives it.
1070
+ /**
1071
+ * Everything the walk never reached, recorded once the walk is over.
1072
+ *
1073
+ * Only a walk that ENDED reports this. An interrupted one is a run that
1074
+ * parked or was cancelled, and its nodes are not skipped — the resumed
1075
+ * walk settles them, and recording them as skipped first would leave the
1076
+ * journal claiming a node never ran that later did. A typed failure is
1077
+ * terminal for the round, so its stranded nodes are skipped exactly as a
1078
+ * completed walk's untaken branch arm is.
1079
+ */
1080
+ const recordSkipped = (exit) => Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause) ? Effect.void : Effect.forEach(graphNodes.filter((node) => !reported.has(node.id)), (node) => {
1081
+ const action = actionTag(node.ast);
1082
+ return record(() => ({
1083
+ _tag: "NodeSettled",
1084
+ sourceId: `node/${node.id}/1/settled`,
1085
+ nodeId: node.id,
1086
+ outcome: "skipped",
1087
+ attempts: 0,
1088
+ // A node the walk never reached dispatched nothing, so it claims
1089
+ // no step key and there is no value it settled with.
1090
+ stepKeyDigests: [],
1091
+ ...(action === undefined ? {} : { action })
1092
+ }));
1093
+ }, { discard: true });
1094
+ const value = yield* settleNode(options.root ?? "root").pipe(Effect.onExit((exit) => Scope.close(nodes, exit)), Effect.onExit(recordSkipped));
1095
+ return {
1096
+ value,
1097
+ settled,
1098
+ failed,
1099
+ skipped: Graph.nodes(graph).filter((node) => !settled.has(node.id) && !failed.has(node.id)).map((node) => node.id)
1100
+ };
1101
+ });
1102
+ /** A child execution a losing join member opened. @private */
1103
+ const JoinChild = Schema.Struct({ node: Schema.String, executionId: Schema.String });
1104
+ /**
1105
+ * The members a join decided on, in the order they decided, and the child
1106
+ * executions its losers had opened. A bare member list is the record written
1107
+ * before losing children were journaled; it names none, and still replays.
1108
+ *
1109
+ * @private
1110
+ */
1111
+ const JoinDecision = Schema.Union([
1112
+ Schema.Struct({ members: Schema.Array(Schema.String), children: Schema.Array(JoinChild) }),
1113
+ Schema.Array(Schema.String)
1114
+ ]);
1115
+ /**
1116
+ * How a member's settlement counts toward a join: a value or a typed failure
1117
+ * decides, an interruption is still undecided, and a defect or interpreter
1118
+ * refusal is fatal to the join.
1119
+ *
1120
+ * @private
1121
+ */
1122
+ const classify = (exit) => {
1123
+ if (Exit.isSuccess(exit))
1124
+ return "decisive";
1125
+ if (Cause.hasInterruptsOnly(exit.cause))
1126
+ return "pending";
1127
+ const reasons = exit.cause.reasons;
1128
+ const typed = reasons.every((reason) => reason._tag !== "Die") &&
1129
+ reasons.some((reason) => reason._tag === "Fail") &&
1130
+ !reasons.some((reason) => reason._tag === "Fail" && Schema.is(InterpreterError)(reason.error));
1131
+ return typed ? "decisive" : "fatal";
1132
+ };
1133
+ /**
1134
+ * A join's verdict over the members that decided, in the order they decided,
1135
+ * or `undefined` while it is still open.
1136
+ *
1137
+ * `race` takes the first settlement. `any` and `quorum` succeed once `count`
1138
+ * members succeed, and fail with the failure that leaves too few members able
1139
+ * to: for `any`, that is the last one.
1140
+ *
1141
+ * @private
1142
+ */
1143
+ const decide = (ast, width, outcomes) => {
1144
+ if (ast.mode === "race")
1145
+ return outcomes[0]?.exit;
1146
+ const successes = outcomes.filter((outcome) => Exit.isSuccess(outcome.exit));
1147
+ if (successes.length >= ast.count) {
1148
+ if (ast.mode === "any")
1149
+ return successes[0].exit;
1150
+ const joined = Object.create(null);
1151
+ for (const success of successes) {
1152
+ Object.defineProperty(joined, success.member, {
1153
+ configurable: true,
1154
+ enumerable: true,
1155
+ value: success.exit.value,
1156
+ writable: true
1157
+ });
1158
+ }
1159
+ return Exit.succeed(joined);
1160
+ }
1161
+ if (outcomes.length - successes.length > width - ast.count)
1162
+ return outcomes[outcomes.length - 1].exit;
1163
+ return undefined;
1164
+ };
1165
+ /**
1166
+ * Turns a body's root value into the settlement the engine acts on.
1167
+ *
1168
+ * Three of them exist, and only three
1169
+ * (`docs/concepts/trampoline-rounds.md`): `done(value)` is the answer, so the
1170
+ * value passes straight through; `Next.to(payload)` is the next round, recorded in the instance's
1171
+ * handoff slot so `Flow.intoResult` answers `Flow.Handoff`; and `park(reason)`
1172
+ * is a durable suspension, declared through the ordinary waiting vocabulary so
1173
+ * a durable driver parks the run under the flow's own reason and wake token
1174
+ * rather than the derived `timer`/`event` default. Anything else is an ordinary
1175
+ * value and is the answer as it stands, which is what keeps a body that never
1176
+ * heard of the trampoline working unchanged.
1177
+ *
1178
+ * @private
1179
+ */
1180
+ const settleOutcome = (value) => {
1181
+ if (!Outcome.isOutcome(value))
1182
+ return Effect.succeed(value);
1183
+ switch (value._tag) {
1184
+ case "Done":
1185
+ return Effect.succeed(value.value);
1186
+ case "To":
1187
+ return Effect.gen(function* () {
1188
+ const instance = yield* FlowInstance;
1189
+ const current = yield* CapabilitySet.current;
1190
+ instance.handoff = new Handoff({
1191
+ flow: value.flow,
1192
+ payload: value.payload,
1193
+ capabilityCeilings: [...current.groups, ...(value.capabilityCeilings ?? [])]
1194
+ });
1195
+ });
1196
+ case "Park":
1197
+ return Effect.andThen(annotateWaiting(value.reason), Effect.flatMap(FlowInstance, suspend));
1198
+ }
1199
+ };
1200
+ /**
1201
+ * Registers a flow with the runtime, driven by its body.
1202
+ *
1203
+ * This is the only way a flow's behavior reaches the runtime, and the reason a
1204
+ * flow has no `toLayer`: a flow has one behavior and it is the body, so there
1205
+ * is no second, opaque one to attach. An Action is what carries an
1206
+ * implementation, and it attaches that implementation with its own `toLayer`.
1207
+ * Compose this beside the action implementation layers the body calls, over the
1208
+ * {@link module:Implementations.layerImplementations} table they file
1209
+ * themselves in — the table goes UNDER them, because filing happens while an
1210
+ * implementation layer is built:
1211
+ *
1212
+ * ```ts
1213
+ * Layer.mergeAll(Read.toLayer(read), Write.toLayer(write), Interpreter.layer(Pipeline)).pipe(
1214
+ * Layer.provideMerge(Action.layerImplementations)
1215
+ * )
1216
+ * ```
1217
+ *
1218
+ * It accepts a flow whatever its requirement channel says, and requires only
1219
+ * the table. Registering a body is not running one: the handler installed here
1220
+ * resolves each call by tag when the run reaches it, which is the same thing a
1221
+ * driver does for a plan read back out of a journal. `Flow.execute` is where
1222
+ * the requirements are asked for.
1223
+ *
1224
+ * This low-level registration keeps the `process-local` callback policy for
1225
+ * compatibility. Select `callbackIdentity: "stable"`, or use
1226
+ * {@link layerWithImplementations}, to refuse unstable callbacks before
1227
+ * dispatch. Without that selection it makes no reproducible-plan guarantee.
1228
+ *
1229
+ * @since 0.1.0
1230
+ * @category layers
1231
+ */
1232
+ export const layer = (flow, options = {}) => makeLayer(flow, options).pipe(Layer.provide(systemActions));
1233
+ // These layers only register handlers at construction. Crypto is supplied by
1234
+ // the executing interpreter (Services), not required to register a flow.
1235
+ const systemActions = Layer.mergeAll(HumanTask.layer, Sleep.layer, WaitFor.layer);
1236
+ /** Registers the interpreter and reachable child flows under one policy. @private */
1237
+ const makeLayer = (flow, options, reachable, ifAbsent = false) => Layer.effectDiscard(Effect.gen(function* () {
1238
+ const runtime = yield* FlowRuntime;
1239
+ const registered = reachable ?? new Set();
1240
+ if (registered.has(flow))
1241
+ return;
1242
+ // Lazy registration can be skipped by an independent live owner. Recheck
1243
+ // on later executions so releasing that owner permits fresh admission.
1244
+ if (!ifAbsent)
1245
+ registered.add(flow);
1246
+ const scope = yield* Effect.scope;
1247
+ const context = yield* Effect.context();
1248
+ const implementations = Context.get(context, Implementations);
1249
+ // Keep discovered declarations in the host registration scope, rather
1250
+ // than the executing parent's scope: handoffs outlive that parent.
1251
+ // Dynamic declarations erase their codec services, just like execute;
1252
+ // those services still come from the registering host's context.
1253
+ const registerReachable = (declaration) => Layer.buildWithScope(makeLayer(declaration, options, registered, true), scope).pipe(Effect.provide(context), Effect.asVoid);
1254
+ const middleware = Context.get(flow.annotations, ExecutionMiddleware);
1255
+ yield* runtime.register(flow, ((payload) => {
1256
+ const body = Effect.flatMap(interpretWithPolicy(flow, payload, options, registerReachable), (interpretation) => settleOutcome(interpretation.value));
1257
+ // Registration owns action resolution. A caller may supply a different
1258
+ // table when entering this flow as a child; retain dynamic execution
1259
+ // services while restoring this flow's registered implementations.
1260
+ return (middleware === undefined ? body : middleware.wrap(payload, body)).pipe(Effect.provideService(Implementations, implementations));
1261
+ }), { ifAbsent });
1262
+ }));
1263
+ /**
1264
+ * Composes one flow and its implementation layers around one isolated registry.
1265
+ *
1266
+ * The implementation layer must provide every action requirement carried by the
1267
+ * flow. Callback identity defaults to `stable`: raw callbacks are refused before
1268
+ * dispatch, with a diagnostic naming the callback and `Node.capture`. Captures
1269
+ * must cover semantic configuration and implementation versions, including
1270
+ * behavior reached through imports. Explicit `callbackIdentity: "process-local"`
1271
+ * is available for local experimentation, without a reproducible-plan claim.
1272
+ * Sealed actions with an idempotency key must declare `implementationVersion`
1273
+ * and register that exact version. This rule is independent of callback policy:
1274
+ * those declarations can reuse recorded content even if their code changes.
1275
+ * Keyless sealed actions use invocation identity; compensable and irreversible
1276
+ * actions do not use content-key caching. Their versions remain optional.
1277
+ * Versions must cover semantic handler and service changes; callback stability
1278
+ * cannot establish that declaration's completeness.
1279
+ *
1280
+ * The interpreter validates all named graph actions before dispatching any
1281
+ * of them. Conflicting registrations fail while the layer builds; use an explicit
1282
+ * `toLayer(handler, { override: true })` only for intentional scoped substitution.
1283
+ *
1284
+ * @category layers
1285
+ * @since 0.1.0
1286
+ */
1287
+ export const layerWithImplementations = (flow, implementations, options = {}) => Layer.merge(implementations, makeLayer(flow, { ...options, callbackIdentity: options.callbackIdentity ?? "stable" }).pipe(Layer.provide(systemActions)))
1288
+ .pipe(Layer.provide(layerImplementations), Layer.fresh);
1289
+ //# sourceMappingURL=Interpreter.js.map