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

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