@lostgradient/weft 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (508) hide show
  1. package/README.md +79 -24
  2. package/dist/cli/conformance.js +7 -1
  3. package/dist/cli/generated/operation-client.generated.d.ts +28 -13
  4. package/dist/cli/generated/operation-client.generated.js +1 -0
  5. package/dist/cli/help-text.d.ts +1 -1
  6. package/dist/cli/help-text.js +1 -0
  7. package/dist/cli/operation-catalog-snapshot.d.ts +8 -0
  8. package/dist/cli/operation-catalog-snapshot.js +11 -0
  9. package/dist/cli/parse-schedule-arguments.js +3 -1
  10. package/dist/cli/schedule.js +2 -1
  11. package/dist/cli/types.d.ts +1 -0
  12. package/dist/cli-main.js +79 -78
  13. package/dist/client/handle-delegation.d.ts +3 -2
  14. package/dist/client/handle-delegation.js +3 -1
  15. package/dist/client/http-client-requests.d.ts +2 -1
  16. package/dist/client/http-client-requests.js +7 -0
  17. package/dist/client/http-client.d.ts +9 -6
  18. package/dist/client/http-client.js +10 -1
  19. package/dist/client/http-request.d.ts +11 -1
  20. package/dist/client/http-request.js +17 -7
  21. package/dist/client/index.d.ts +1 -1
  22. package/dist/client/interface.d.ts +46 -5
  23. package/dist/client/local.d.ts +4 -1
  24. package/dist/client/local.js +12 -4
  25. package/dist/client/start-body.d.ts +4 -3
  26. package/dist/core/byte-arrays.d.ts +5 -0
  27. package/dist/core/byte-arrays.js +5 -0
  28. package/dist/core/checkpoint/lifecycle.d.ts +3 -0
  29. package/dist/core/checkpoint/lifecycle.js +9 -4
  30. package/dist/core/checkpoint/serialization.js +12 -5
  31. package/dist/core/codec/extension-codec.d.ts +16 -0
  32. package/dist/core/codec/extension-codec.js +100 -6
  33. package/dist/core/context/activity-retry-state.d.ts +38 -0
  34. package/dist/core/context/activity-retry-state.js +89 -0
  35. package/dist/core/context/activity-schedule-to-close.d.ts +159 -0
  36. package/dist/core/context/activity-schedule-to-close.js +69 -0
  37. package/dist/core/context/child-workflow-pipe.d.ts +5 -5
  38. package/dist/core/context/child-workflow-pipe.js +15 -2
  39. package/dist/core/context/context-presence.d.ts +19 -0
  40. package/dist/core/context/context-presence.js +13 -0
  41. package/dist/core/context/durable-operations.d.ts +25 -0
  42. package/dist/core/context/durable-operations.js +64 -0
  43. package/dist/core/context/index.d.ts +9 -5
  44. package/dist/core/context/index.js +17 -12
  45. package/dist/core/context/internals.d.ts +20 -0
  46. package/dist/core/context/internals.js +3 -1
  47. package/dist/core/context/operation-request.d.ts +35 -0
  48. package/dist/core/context/parallel-cache-entry.d.ts +14 -5
  49. package/dist/core/context/run-operation.d.ts +6 -1
  50. package/dist/core/context/run-operation.js +41 -87
  51. package/dist/core/context/session-state.js +7 -8
  52. package/dist/core/context/speculative-child.js +2 -0
  53. package/dist/core/context/types.d.ts +15 -0
  54. package/dist/core/context/version-patching.d.ts +8 -0
  55. package/dist/core/context/version-patching.js +40 -0
  56. package/dist/core/context/workflow-logger.d.ts +98 -0
  57. package/dist/core/context/workflow-logger.js +68 -0
  58. package/dist/core/engine/activity-heartbeat-tracking.d.ts +64 -0
  59. package/dist/core/engine/activity-heartbeat-tracking.js +42 -0
  60. package/dist/core/engine/activity-per-attempt-timeout.d.ts +41 -0
  61. package/dist/core/engine/activity-per-attempt-timeout.js +36 -0
  62. package/dist/core/engine/activity-reconciliation.d.ts +1 -0
  63. package/dist/core/engine/activity-reconciliation.js +12 -1
  64. package/dist/core/engine/activity-resolution.d.ts +23 -0
  65. package/dist/core/engine/activity-resolution.js +37 -0
  66. package/dist/core/engine/aggregate.js +66 -30
  67. package/dist/core/engine/async-activity-completion.d.ts +23 -6
  68. package/dist/core/engine/async-activity-completion.js +53 -12
  69. package/dist/core/engine/attributes-tags.js +9 -4
  70. package/dist/core/engine/bulk-operations-purge.d.ts +26 -0
  71. package/dist/core/engine/bulk-operations-purge.js +38 -3
  72. package/dist/core/engine/bulk-operations-shared.d.ts +2 -0
  73. package/dist/core/engine/bulk-operations-shared.js +8 -2
  74. package/dist/core/engine/bulk-operations.d.ts +4 -1
  75. package/dist/core/engine/bulk-operations.js +235 -24
  76. package/dist/core/engine/callback-creators-bundles.d.ts +9 -0
  77. package/dist/core/engine/callback-creators-bundles.js +30 -2
  78. package/dist/core/engine/callback-creators-core.js +6 -4
  79. package/dist/core/engine/callback-creators-router.js +10 -0
  80. package/dist/core/engine/callback-creators-schedule.d.ts +2 -2
  81. package/dist/core/engine/callback-creators-schedule.js +12 -8
  82. package/dist/core/engine/candidate-read-batching.d.ts +6 -0
  83. package/dist/core/engine/candidate-read-batching.js +1 -0
  84. package/dist/core/engine/checkpoint-io.js +61 -25
  85. package/dist/core/engine/checkpoint-reads.js +3 -2
  86. package/dist/core/engine/checkpoint-replay.d.ts +20 -0
  87. package/dist/core/engine/checkpoint-replay.js +242 -0
  88. package/dist/core/engine/checkpoint-side-effects.d.ts +23 -0
  89. package/dist/core/engine/checkpoint-side-effects.js +35 -0
  90. package/dist/core/engine/child-workflow-cancellation.d.ts +10 -0
  91. package/dist/core/engine/child-workflow-cancellation.js +40 -0
  92. package/dist/core/engine/child-workflow.js +27 -4
  93. package/dist/core/engine/condition-waiters.d.ts +14 -0
  94. package/dist/core/engine/condition-waiters.js +5 -0
  95. package/dist/core/engine/construction.d.ts +3 -0
  96. package/dist/core/engine/construction.js +21 -8
  97. package/dist/core/engine/coordination-branch-executors.d.ts +70 -0
  98. package/dist/core/engine/coordination-branch-executors.js +107 -0
  99. package/dist/core/engine/deferred-consume-envelope.d.ts +59 -0
  100. package/dist/core/engine/deferred-consume-envelope.js +14 -0
  101. package/dist/core/engine/disposal.js +13 -0
  102. package/dist/core/engine/engine-create-types.d.ts +14 -4
  103. package/dist/core/engine/engine-internal-types.d.ts +26 -3
  104. package/dist/core/engine/errors.d.ts +47 -0
  105. package/dist/core/engine/errors.js +20 -0
  106. package/dist/core/engine/event-log-compaction.d.ts +8 -0
  107. package/dist/core/engine/event-log-compaction.js +20 -2
  108. package/dist/core/engine/fenced-write.d.ts +65 -0
  109. package/dist/core/engine/fenced-write.js +71 -0
  110. package/dist/core/engine/finalizer-state.d.ts +28 -0
  111. package/dist/core/engine/finalizer-state.js +16 -0
  112. package/dist/core/engine/handles.d.ts +8 -0
  113. package/dist/core/engine/index.d.ts +34 -16
  114. package/dist/core/engine/index.js +133 -8
  115. package/dist/core/engine/inline-parking.js +3 -2
  116. package/dist/core/engine/internals.d.ts +107 -3
  117. package/dist/core/engine/lease-codec.d.ts +35 -0
  118. package/dist/core/engine/lease-codec.js +32 -0
  119. package/dist/core/engine/lease-deposition.d.ts +66 -0
  120. package/dist/core/engine/lease-deposition.js +10 -0
  121. package/dist/core/engine/lease-errors.d.ts +99 -0
  122. package/dist/core/engine/lease-errors.js +30 -0
  123. package/dist/core/engine/lease-manager.d.ts +114 -0
  124. package/dist/core/engine/lease-manager.js +135 -0
  125. package/dist/core/engine/lifecycle/persist.js +10 -32
  126. package/dist/core/engine/lifecycle/recovered-services.d.ts +8 -6
  127. package/dist/core/engine/lifecycle/recovered-services.js +18 -3
  128. package/dist/core/engine/lifecycle/resume.js +16 -9
  129. package/dist/core/engine/lifecycle/shared.d.ts +8 -1
  130. package/dist/core/engine/lifecycle/start-batch.d.ts +1 -1
  131. package/dist/core/engine/lifecycle/start-batch.js +2 -1
  132. package/dist/core/engine/lifecycle/start-commit.d.ts +9 -0
  133. package/dist/core/engine/lifecycle/start-commit.js +50 -8
  134. package/dist/core/engine/lifecycle/start-or-signal-create.d.ts +58 -0
  135. package/dist/core/engine/lifecycle/start-or-signal-create.js +95 -0
  136. package/dist/core/engine/lifecycle/start-or-signal.d.ts +3 -2
  137. package/dist/core/engine/lifecycle/start-or-signal.js +11 -81
  138. package/dist/core/engine/lifecycle/start-terminal-conflict-purge.d.ts +39 -0
  139. package/dist/core/engine/lifecycle/start-terminal-conflict-purge.js +28 -0
  140. package/dist/core/engine/lifecycle/start.d.ts +4 -4
  141. package/dist/core/engine/lifecycle/start.js +17 -9
  142. package/dist/core/engine/lifecycle/transition.js +17 -5
  143. package/dist/core/engine/lifecycle.d.ts +1 -1
  144. package/dist/core/engine/list-candidate-resolution.js +2 -2
  145. package/dist/core/engine/listing.js +9 -5
  146. package/dist/core/engine/operations-activity.d.ts +4 -11
  147. package/dist/core/engine/operations-activity.js +22 -49
  148. package/dist/core/engine/operations-coordination.d.ts +10 -0
  149. package/dist/core/engine/operations-coordination.js +43 -8
  150. package/dist/core/engine/operations-router.d.ts +6 -0
  151. package/dist/core/engine/operations-router.js +2 -0
  152. package/dist/core/engine/operations-speculate.js +6 -2
  153. package/dist/core/engine/operations-stream.js +12 -2
  154. package/dist/core/engine/operations-time.d.ts +4 -2
  155. package/dist/core/engine/operations-time.js +14 -2
  156. package/dist/core/engine/operations-wait-condition.d.ts +23 -0
  157. package/dist/core/engine/operations-wait-condition.js +62 -0
  158. package/dist/core/engine/ownership-options.d.ts +23 -0
  159. package/dist/core/engine/ownership-options.js +26 -0
  160. package/dist/core/engine/payload-size-policy.d.ts +3 -0
  161. package/dist/core/engine/payload-size-policy.js +4 -0
  162. package/dist/core/engine/pending-updates.d.ts +17 -0
  163. package/dist/core/engine/pending-updates.js +33 -11
  164. package/dist/core/engine/queries.js +1 -1
  165. package/dist/core/engine/registration.d.ts +1 -0
  166. package/dist/core/engine/registration.js +18 -3
  167. package/dist/core/engine/schedule-jitter.d.ts +5 -0
  168. package/dist/core/engine/schedule-jitter.js +10 -0
  169. package/dist/core/engine/schedule-run.d.ts +17 -0
  170. package/dist/core/engine/schedule-run.js +38 -0
  171. package/dist/core/engine/schedule-timer.js +81 -17
  172. package/dist/core/engine/schedules.d.ts +7 -4
  173. package/dist/core/engine/schedules.js +37 -16
  174. package/dist/core/engine/search-attribute-records.d.ts +4 -0
  175. package/dist/core/engine/search-attribute-records.js +17 -0
  176. package/dist/core/engine/signals.d.ts +18 -2
  177. package/dist/core/engine/signals.js +42 -21
  178. package/dist/core/engine/state-utilities.d.ts +49 -2
  179. package/dist/core/engine/state-utilities.js +114 -3
  180. package/dist/core/engine/storage-io.d.ts +16 -2
  181. package/dist/core/engine/storage-io.js +26 -5
  182. package/dist/core/engine/stream-chunk-loading.d.ts +2 -0
  183. package/dist/core/engine/stream-chunk-loading.js +24 -1
  184. package/dist/core/engine/sub-operation.js +22 -3
  185. package/dist/core/engine/termination/cleanup.d.ts +3 -1
  186. package/dist/core/engine/termination/cleanup.js +25 -1
  187. package/dist/core/engine/termination/complete.js +44 -6
  188. package/dist/core/engine/termination/finalizer-activity.d.ts +53 -0
  189. package/dist/core/engine/termination/finalizer-activity.js +30 -0
  190. package/dist/core/engine/termination/finalizer-claim.d.ts +110 -0
  191. package/dist/core/engine/termination/finalizer-claim.js +80 -0
  192. package/dist/core/engine/termination/finalizer.d.ts +48 -0
  193. package/dist/core/engine/termination/finalizer.js +159 -0
  194. package/dist/core/engine/termination/suspend.d.ts +3 -1
  195. package/dist/core/engine/termination.d.ts +1 -0
  196. package/dist/core/engine/termination.js +4 -0
  197. package/dist/core/engine/updates.js +5 -25
  198. package/dist/core/engine/validation/schedule.d.ts +2 -1
  199. package/dist/core/engine/validation/schedule.js +51 -2
  200. package/dist/core/engine/validation.js +32 -5
  201. package/dist/core/engine/waiting-update-response.d.ts +8 -0
  202. package/dist/core/engine/waiting-update-response.js +22 -0
  203. package/dist/core/engine/workflow-concurrency.d.ts +10 -0
  204. package/dist/core/engine/workflow-concurrency.js +136 -0
  205. package/dist/core/engine/workflow-feed.d.ts +4 -5
  206. package/dist/core/engine/workflow-feed.js +4 -1
  207. package/dist/core/engine/workflow-indexes.d.ts +9 -0
  208. package/dist/core/engine/workflow-indexes.js +10 -0
  209. package/dist/core/engine/workflow-state-stream.js +33 -13
  210. package/dist/core/engine/workflow-visibility-queries.d.ts +2 -2
  211. package/dist/core/engine-helpers.js +1 -0
  212. package/dist/core/events/activity-events.d.ts +43 -12
  213. package/dist/core/events/activity-events.js +28 -0
  214. package/dist/core/events/attribute-events.d.ts +2 -3
  215. package/dist/core/events/event-map.d.ts +18 -12
  216. package/dist/core/events/index.d.ts +1 -0
  217. package/dist/core/events/index.js +1 -0
  218. package/dist/core/events/schedule-events.d.ts +71 -0
  219. package/dist/core/events/schedule-events.js +29 -0
  220. package/dist/core/events/signal-events.d.ts +4 -6
  221. package/dist/core/events/system-events.d.ts +29 -19
  222. package/dist/core/events/system-events.js +26 -0
  223. package/dist/core/events/update-events.d.ts +6 -8
  224. package/dist/core/events/workflow-events.d.ts +88 -23
  225. package/dist/core/events/workflow-events.js +26 -0
  226. package/dist/core/failure-categories.js +5 -17
  227. package/dist/core/fault-code.d.ts +9 -3
  228. package/dist/core/fault-code.js +1 -0
  229. package/dist/core/inline-execution-strategy.context-options.d.ts +69 -0
  230. package/dist/core/inline-execution-strategy.context-options.js +56 -0
  231. package/dist/core/inline-execution-strategy.d.ts +31 -36
  232. package/dist/core/inline-execution-strategy.js +16 -27
  233. package/dist/core/list-filter-validation.d.ts +1 -1
  234. package/dist/core/payload-size.d.ts +1 -1
  235. package/dist/core/persisted-data-incompatible-error.d.ts +9 -7
  236. package/dist/core/review/events.d.ts +6 -8
  237. package/dist/core/scheduler/scheduler-class.d.ts +10 -1
  238. package/dist/core/scheduler/scheduler-class.js +38 -11
  239. package/dist/core/scheduler/timer-batch.js +9 -1
  240. package/dist/core/scheduler/timer-sources.d.ts +1 -0
  241. package/dist/core/scheduler/timer-sources.js +11 -5
  242. package/dist/core/session-state.d.ts +0 -1
  243. package/dist/core/session-state.js +2 -2
  244. package/dist/core/start-workflow-validation.d.ts +34 -0
  245. package/dist/core/start-workflow-validation.js +19 -0
  246. package/dist/core/types/activity-verification.d.ts +67 -0
  247. package/dist/core/types/activity-verification.js +0 -0
  248. package/dist/core/types/activity.d.ts +80 -61
  249. package/dist/core/types/bulk.d.ts +50 -9
  250. package/dist/core/types/checkpoint.d.ts +44 -8
  251. package/dist/core/types/list-options.d.ts +146 -0
  252. package/dist/core/types/list-options.js +0 -0
  253. package/dist/core/types/options.d.ts +121 -165
  254. package/dist/core/types/schedules.d.ts +39 -3
  255. package/dist/core/types/services-resolution.d.ts +2 -2
  256. package/dist/core/types/workflow-builder-runtime.d.ts +12 -3
  257. package/dist/core/types/workflow-builder-runtime.js +11 -2
  258. package/dist/core/types/workflow-builder.d.ts +42 -11
  259. package/dist/core/types/workflow-concurrency.d.ts +39 -0
  260. package/dist/core/types/workflow-concurrency.js +0 -0
  261. package/dist/core/types/workflow-context.d.ts +157 -14
  262. package/dist/core/types/workflow-definition.d.ts +53 -10
  263. package/dist/core/types/workflow-function.d.ts +84 -9
  264. package/dist/core/types/workflow-log.d.ts +98 -0
  265. package/dist/core/types/workflow-log.js +0 -0
  266. package/dist/core/types/workflow-registries.d.ts +14 -3
  267. package/dist/core/types/workflow-registry.d.ts +3 -0
  268. package/dist/core/types.d.ts +4 -0
  269. package/dist/core/types.js +4 -0
  270. package/dist/core/versioning.d.ts +9 -39
  271. package/dist/core/versioning.js +2 -12
  272. package/dist/core/weft-error.d.ts +44 -1
  273. package/dist/core/weft-error.js +16 -0
  274. package/dist/core/worker-execution-strategy-options.d.ts +26 -0
  275. package/dist/core/worker-execution-strategy.js +40 -36
  276. package/dist/core/worker-inbound-message.d.ts +38 -0
  277. package/dist/core/worker-inbound-message.js +37 -0
  278. package/dist/core/worker-log-abuse-counter.d.ts +175 -0
  279. package/dist/core/worker-log-abuse-counter.js +107 -0
  280. package/dist/core/worker-message-helpers.d.ts +47 -0
  281. package/dist/core/worker-message-helpers.js +26 -0
  282. package/dist/core/worker-protocol-guard.js +1 -1
  283. package/dist/core/worker-protocol-log.d.ts +56 -0
  284. package/dist/core/worker-protocol-log.js +18 -0
  285. package/dist/core/worker-protocol.d.ts +23 -0
  286. package/dist/core/worker-protocol.js +12 -2
  287. package/dist/core/workflow-version-tuple.d.ts +3 -9
  288. package/dist/core/workflow-version-tuple.js +2 -3
  289. package/dist/diagnostics/format.js +1 -6
  290. package/dist/diagnostics/types.d.ts +4 -5
  291. package/dist/diagnostics/validate.d.ts +0 -1
  292. package/dist/diagnostics/version-check.d.ts +1 -1
  293. package/dist/diagnostics/version-check.js +4 -9
  294. package/dist/index.d.ts +12 -10
  295. package/dist/index.js +29 -3
  296. package/dist/json-schema.js +3 -3
  297. package/dist/mcp/cli.js +27 -27
  298. package/dist/mcp/dispatcher.js +1 -1
  299. package/dist/mcp/http.js +16 -6
  300. package/dist/mcp/protocol.d.ts +2 -0
  301. package/dist/mcp/protocol.js +1 -1
  302. package/dist/mcp/session.d.ts +16 -0
  303. package/dist/mcp/session.js +59 -6
  304. package/dist/mcp/tools.js +73 -6
  305. package/dist/observability/index.js +2 -2
  306. package/dist/server/asyncapi-channels.js +5 -2
  307. package/dist/server/attribute-filters.d.ts +8 -3
  308. package/dist/server/attribute-filters.js +6 -1
  309. package/dist/server/authentication/api-key.d.ts +2 -1
  310. package/dist/server/authentication/api-key.js +5 -2
  311. package/dist/server/authentication/constant-time-api-key.d.ts +15 -0
  312. package/dist/server/authentication/constant-time-api-key.js +24 -0
  313. package/dist/server/authentication/index.d.ts +1 -1
  314. package/dist/server/authentication/index.js +7 -4
  315. package/dist/server/authentication/rotating-api-key-store.d.ts +5 -3
  316. package/dist/server/authentication/rotating-api-key-store.js +19 -11
  317. package/dist/server/engine-event-feed-backend.d.ts +4 -5
  318. package/dist/server/fault-to-http.js +8 -1
  319. package/dist/server/fault-to-json-rpc.js +1 -0
  320. package/dist/server/fleet-event-feed.d.ts +31 -0
  321. package/dist/server/fleet-event-feed.js +157 -0
  322. package/dist/server/handler/index.js +1 -1
  323. package/dist/server/handler/response-helpers.js +2 -1
  324. package/dist/server/handler/route-dispatch.d.ts +6 -3
  325. package/dist/server/handler/route-dispatch.js +2 -2
  326. package/dist/server/handler.js +23 -23
  327. package/dist/server/index.d.ts +32 -2
  328. package/dist/server/index.js +26 -26
  329. package/dist/server/json-rpc-transport-helpers.d.ts +1 -0
  330. package/dist/server/json-rpc-transport-helpers.js +2 -1
  331. package/dist/server/json-rpc-websocket-runtime.d.ts +11 -2
  332. package/dist/server/json-rpc-websocket-runtime.js +1 -0
  333. package/dist/server/json-rpc-websocket-subscriptions.d.ts +10 -0
  334. package/dist/server/json-rpc-websocket-subscriptions.js +29 -0
  335. package/dist/server/json-rpc-websocket-types.d.ts +22 -0
  336. package/dist/server/json-rpc-websocket-types.js +0 -0
  337. package/dist/server/json-rpc-websocket-validation.js +20 -4
  338. package/dist/server/json-rpc-websocket.d.ts +2 -43
  339. package/dist/server/json-rpc-websocket.js +57 -74
  340. package/dist/server/openapi.d.ts +2 -1
  341. package/dist/server/openapi.js +1 -3
  342. package/dist/server/openrpc-document-schema.d.ts +78 -0
  343. package/dist/server/openrpc-document-schema.js +27 -1
  344. package/dist/server/openrpc-errors.d.ts +3 -0
  345. package/dist/server/openrpc-errors.js +2 -1
  346. package/dist/server/openrpc.js +32 -0
  347. package/dist/server/operation-catalog/index.d.ts +1 -1
  348. package/dist/server/operation-catalog/pipeline-helpers.js +1 -0
  349. package/dist/server/operation-catalog/pipeline-stages.js +26 -12
  350. package/dist/server/operation-catalog/pipeline.js +8 -1
  351. package/dist/server/operation-catalog/registry.js +13 -0
  352. package/dist/server/operation-catalog/types.d.ts +20 -9
  353. package/dist/server/operation-fault.d.ts +10 -0
  354. package/dist/server/operation-fault.js +2 -0
  355. package/dist/server/operation-registry.d.ts +12 -11
  356. package/dist/server/operation-registry.js +12 -3
  357. package/dist/server/operations/aggregate-workflows.d.ts +15 -15
  358. package/dist/server/operations/async-activity.d.ts +2 -2
  359. package/dist/server/operations/async-activity.js +12 -7
  360. package/dist/server/operations/bulk-cancel-workflows.d.ts +1 -1
  361. package/dist/server/operations/bulk-cancel-workflows.js +2 -2
  362. package/dist/server/operations/bulk-delete-workflows.d.ts +1 -1
  363. package/dist/server/operations/bulk-delete-workflows.js +2 -2
  364. package/dist/server/operations/bulk-filter-helpers.d.ts +8 -6
  365. package/dist/server/operations/bulk-filter-helpers.js +54 -24
  366. package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +11 -9
  367. package/dist/server/operations/bulk-mutate-workflow-tags.js +2 -2
  368. package/dist/server/operations/bulk-operation-helpers.d.ts +2 -2
  369. package/dist/server/operations/bulk-retry-failed-workflows.d.ts +7 -0
  370. package/dist/server/operations/bulk-retry-failed-workflows.js +64 -0
  371. package/dist/server/operations/bulk-signal-workflows.d.ts +11 -9
  372. package/dist/server/operations/bulk-signal-workflows.js +2 -2
  373. package/dist/server/operations/cancel-schedule.d.ts +1 -1
  374. package/dist/server/operations/create-schedule.d.ts +3 -1
  375. package/dist/server/operations/create-schedule.js +29 -11
  376. package/dist/server/operations/fleet-events-subscription.d.ts +54 -0
  377. package/dist/server/operations/fleet-events-subscription.js +99 -0
  378. package/dist/server/operations/fork-workflow.d.ts +1 -1
  379. package/dist/server/operations/fork-workflow.js +3 -2
  380. package/dist/server/operations/get-checkpoint-at.d.ts +1 -1
  381. package/dist/server/operations/get-registry.d.ts +1 -1
  382. package/dist/server/operations/get-retention-overview.d.ts +1 -1
  383. package/dist/server/operations/get-review.d.ts +1 -1
  384. package/dist/server/operations/get-schedule.d.ts +1 -1
  385. package/dist/server/operations/get-stream-chunks.d.ts +1 -1
  386. package/dist/server/operations/get-system-metrics.d.ts +2 -2
  387. package/dist/server/operations/get-task-diagnostics.d.ts +45 -6
  388. package/dist/server/operations/get-task-diagnostics.js +101 -7
  389. package/dist/server/operations/get-update-result.d.ts +1 -1
  390. package/dist/server/operations/get-workflow-attributes.d.ts +1 -1
  391. package/dist/server/operations/get-workflow-events.d.ts +1 -1
  392. package/dist/server/operations/get-workflow-result.d.ts +1 -1
  393. package/dist/server/operations/get-workflow-timeline.d.ts +1 -1
  394. package/dist/server/operations/get-workflow.d.ts +1 -1
  395. package/dist/server/operations/list-checkpoints.d.ts +1 -1
  396. package/dist/server/operations/list-reviews.d.ts +1 -1
  397. package/dist/server/operations/list-schedules.d.ts +1 -1
  398. package/dist/server/operations/list-task-queues.d.ts +2 -2
  399. package/dist/server/operations/list-workers.d.ts +2 -2
  400. package/dist/server/operations/list-workflows.d.ts +1 -1
  401. package/dist/server/operations/operation-helpers.d.ts +16 -1
  402. package/dist/server/operations/operation-helpers.js +15 -3
  403. package/dist/server/operations/pause-schedule.d.ts +1 -1
  404. package/dist/server/operations/purge-workflows.d.ts +5 -5
  405. package/dist/server/operations/purge-workflows.js +2 -2
  406. package/dist/server/operations/query-workflow.d.ts +1 -1
  407. package/dist/server/operations/query-workflow.js +3 -2
  408. package/dist/server/operations/recover-all.d.ts +1 -1
  409. package/dist/server/operations/replay-workflow.d.ts +1 -1
  410. package/dist/server/operations/resume-schedule.d.ts +1 -1
  411. package/dist/server/operations/set-workflow-attributes.d.ts +1 -1
  412. package/dist/server/operations/set-workflow-attributes.js +6 -3
  413. package/dist/server/operations/signal-workflow.js +8 -3
  414. package/dist/server/operations/single-workflow-tag-mutation.js +13 -3
  415. package/dist/server/operations/start-or-signal-workflow.d.ts +6 -1
  416. package/dist/server/operations/start-or-signal-workflow.js +14 -24
  417. package/dist/server/operations/start-workflow-options.d.ts +6 -0
  418. package/dist/server/operations/start-workflow-rest-input.d.ts +14 -0
  419. package/dist/server/operations/start-workflow-rest-input.js +31 -0
  420. package/dist/server/operations/start-workflow.d.ts +1 -1
  421. package/dist/server/operations/start-workflow.js +8 -23
  422. package/dist/server/operations/storage.d.ts +6 -6
  423. package/dist/server/operations/storage.js +24 -14
  424. package/dist/server/operations/stream-workflow-sse.d.ts +1 -1
  425. package/dist/server/operations/submit-review-decision.d.ts +1 -1
  426. package/dist/server/operations/submit-review-decision.js +6 -3
  427. package/dist/server/operations/update-schedule.d.ts +1 -1
  428. package/dist/server/operations/update-schedule.js +7 -4
  429. package/dist/server/operations/update-workflow.d.ts +1 -1
  430. package/dist/server/operations/update-workflow.js +7 -3
  431. package/dist/server/operations/worker-drain.d.ts +8 -8
  432. package/dist/server/operations/worker-drain.js +11 -8
  433. package/dist/server/operations/workflow-events-subscription.d.ts +7 -8
  434. package/dist/server/operations/workflow-events-subscription.js +43 -8
  435. package/dist/server/rest-binding.d.ts +3 -1
  436. package/dist/server/rest-bindings.js +12 -0
  437. package/dist/server/rest-body.d.ts +10 -0
  438. package/dist/server/rest-body.js +80 -0
  439. package/dist/server/runtime/authentication-bridge.d.ts +1 -0
  440. package/dist/server/runtime/authentication-bridge.js +33 -6
  441. package/dist/server/runtime/client-visible-events.d.ts +3 -0
  442. package/dist/server/runtime/client-visible-events.js +65 -0
  443. package/dist/server/runtime/context.d.ts +7 -0
  444. package/dist/server/runtime/event-broadcasting.d.ts +6 -0
  445. package/dist/server/runtime/event-broadcasting.js +72 -38
  446. package/dist/server/runtime/retry.d.ts +1 -0
  447. package/dist/server/runtime/retry.js +14 -0
  448. package/dist/server/runtime/shutdown.d.ts +7 -6
  449. package/dist/server/runtime/shutdown.js +6 -1
  450. package/dist/server/runtime/task-polling.js +61 -20
  451. package/dist/server/runtime/task-reconciliation.js +9 -1
  452. package/dist/server/runtime/task-result-resolution.d.ts +15 -0
  453. package/dist/server/runtime/task-result-resolution.js +81 -0
  454. package/dist/server/runtime/websocket-stream.d.ts +20 -1
  455. package/dist/server/runtime/websocket-stream.js +173 -7
  456. package/dist/server/runtime/websocket-upgrade.js +22 -3
  457. package/dist/server/runtime/websocket-worker.d.ts +1 -1
  458. package/dist/server/runtime/websocket-worker.js +38 -30
  459. package/dist/server/serve-internals.d.ts +3 -1
  460. package/dist/server/serve-internals.js +18 -2
  461. package/dist/server/task-state.d.ts +30 -0
  462. package/dist/server/task-state.js +28 -0
  463. package/dist/server/workflow-event-feed.d.ts +36 -115
  464. package/dist/server/workflow-event-feed.js +92 -27
  465. package/dist/service-worker/index.js +30 -30
  466. package/dist/storage/auto.js +1 -1
  467. package/dist/storage/bun-sql.js +24 -0
  468. package/dist/storage/compressed-storage.js +1 -1
  469. package/dist/storage/default-scope.d.ts +7 -4
  470. package/dist/storage/http.js +2 -2
  471. package/dist/storage/index.d.ts +76 -4
  472. package/dist/storage/indexeddb.js +1 -1
  473. package/dist/storage/interface.d.ts +163 -0
  474. package/dist/storage/interface.js +1 -1
  475. package/dist/storage/key-prefixes.d.ts +1 -1
  476. package/dist/storage/key-prefixes.js +10 -0
  477. package/dist/storage/lmdb.d.ts +4 -3
  478. package/dist/storage/lmdb.js +1 -1
  479. package/dist/storage/memory.js +1 -1
  480. package/dist/storage/neon-batch.d.ts +30 -0
  481. package/dist/storage/neon-batch.js +30 -0
  482. package/dist/storage/neon-value-mapping.d.ts +30 -3
  483. package/dist/storage/neon-value-mapping.js +12 -0
  484. package/dist/storage/neon.d.ts +16 -0
  485. package/dist/storage/neon.js +9 -4
  486. package/dist/storage/node-sqlite.js +23 -0
  487. package/dist/storage/postgres-key-value-queries.d.ts +69 -44
  488. package/dist/storage/postgres-key-value-queries.js +62 -24
  489. package/dist/storage/resolve.js +1 -1
  490. package/dist/storage/scoped-storage.js +1 -1
  491. package/dist/storage/testing.d.ts +168 -0
  492. package/dist/storage/testing.js +2 -0
  493. package/dist/storage/turso.d.ts +8 -0
  494. package/dist/storage/turso.js +2 -2
  495. package/dist/storage/typed-storage.js +1 -1
  496. package/dist/storage/web-extension.js +1 -1
  497. package/dist/testing/index.js +28 -28
  498. package/dist/version.d.ts +1 -1
  499. package/dist/version.js +1 -1
  500. package/dist/worker/protocol.js +1 -1
  501. package/dist/workers/worker-replay-state.d.ts +32 -0
  502. package/dist/workers/worker-replay-state.js +35 -0
  503. package/dist/workers/worker-state-namespace.d.ts +21 -0
  504. package/dist/workers/worker-state-namespace.js +13 -0
  505. package/dist/workers/workflow-runner.d.ts +19 -15
  506. package/dist/workers/workflow-runner.js +72 -60
  507. package/dist/workers/workflow-worker-entry.js +5 -2
  508. package/package.json +5 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Weft
2
2
 
3
- A Bun-native durable execution engine. Current release: `0.3.0`.
3
+ A Bun-native durable execution engine. Current release: `0.4.0`.
4
4
 
5
5
  Install the library from npm as `@lostgradient/weft`:
6
6
 
@@ -16,7 +16,7 @@ The CLI binaries remain unscoped: package installs place `weft` and `weft-mcp` o
16
16
 
17
17
  Imagine you're building an e-commerce checkout: charge the customer's credit card, reserve inventory, send a confirmation email, schedule shipping. What happens if your server crashes between step one and step two? The customer has been charged, but the inventory was never reserved. You can't just re-run the whole flow—you'd double-charge them.
18
18
 
19
- **Durable execution** solves this. You write a normal-looking function and the runtime guarantees it will complete—even if the process crashes and restarts a hundred times along the way. Each step is checkpointed so recovery picks up exactly where it stopped.
19
+ **Durable execution** solves this. You write a normal-looking function around durable boundaries; with durable storage, Weft checkpoints those boundaries and automatically resumes persisted work after a process restart. The exact guarantee, including the current activity crash-window limit, is spelled out in [Durability Guarantee](documentation/architecture/durability-guarantee.md).
20
20
 
21
21
  Temporal is the most prominent durable execution engine, built in 2019 with Go, gRPC, and Cassandra. It works. But we can do better with modern tools.
22
22
 
@@ -56,6 +56,17 @@ The public path to 1.0 is tracked in the [roadmap to 1.0](documentation/roadmap-
56
56
 
57
57
  The browser surfaces graduate on a specific, mechanical criterion: the IndexedDB and WebExtension adapters and the Service Worker runtime stay experimental until their real-browser smoke tests are green in a **required** CI gate. The [browser-surface promotion gate](documentation/roadmap-to-1.0.md#browser-surface-promotion-gate) documents how the `browser-smoke` CI job flips from non-blocking to required, and why real-browser coverage — not fake-IndexedDB or stubbed-`chrome.storage` unit tests — is the evidence that moves them to stable.
58
58
 
59
+ ## Durability Guarantee
60
+
61
+ Weft's durability promise is checkpoint-level and explicit:
62
+
63
+ - Every `yield*` boundary is persisted before the workflow advances to the next durable step.
64
+ - `Engine.create()` recovers by default after registering workflow definitions, so fresh processes resume persisted running workflows without a separate boot hook.
65
+ - Recovery resumes from the last checkpoint position instead of replaying the workflow from the beginning.
66
+ - External activity side effects still need idempotency keys, provider lookup, or verifier logic. Without that, a crash after the external side effect but before Weft commits the activity result can dispatch the activity again.
67
+
68
+ The full [Durability Guarantee](documentation/architecture/durability-guarantee.md) separates what is guaranteed today from the Tier-0 activity-reconciliation work that narrows the remaining crash window.
69
+
59
70
  ## Hello, World
60
71
 
61
72
  The smallest useful Weft program has four moving pieces: a storage backend, a named activity, a named workflow, and a handle that waits for the result.
@@ -92,6 +103,8 @@ That's the core loop: `workflow({ name })` is a **chained builder** that co-loca
92
103
 
93
104
  `Engine.create()` does the registration dance for you: it constructs the engine and registers each workflow in the `workflows` map, pulling in all the activities each workflow declares. It then **recovers by default** — `engine.recoverAll()` runs after registration, so any workflows still running from a previous process pick up where they left off. That's the point of durable storage, so you don't have to ask for it. Pass `recover: false` to opt out (handy for tests, for `ScopedStorage`-isolated engines, or when you want to inspect a store before migrating it). Durability is separate: each step is persisted before it commits no matter what `recover` is set to — `recover` only decides whether _this_ engine resumes that persisted work on boot. Run a single engine per durable store; pointing two at the same store is not yet coordinated and can double-resume a workflow.
94
105
 
106
+ Passing an explicitly empty workflow map is the same default-registry boot shape as omitting `workflows`: `Engine.create({ workflows: {} })` recovers after registration and returns an engine whose TypeScript type is compatible with default-registry consumers such as `serve({ engine })`. Use a non-empty `workflows` map when you want TypeScript to narrow `engine.start(...)` to the registered names.
107
+
95
108
  If you'd rather wire things up by hand — useful for tests, isolating engines onto separate storage scopes via `ScopedStorage`, or adding new workflows after the engine starts up — `new Engine({ storage })`, `engine.register(workflow)` or `engine.registerWorkflows({ ... })`, and `await engine.recoverAll()` are the underlying primitives. Each `engine.register(workflow)` call returns the engine with that workflow's name and types baked in, so `engine.start('welcome', ...)` autocompletes immediately.
96
109
 
97
110
  When a workflow needs a live host capability that cannot be checkpointed, pass it as per-run `services`:
@@ -123,7 +136,7 @@ Because recovery never re-executes the workflow from the beginning, your workflo
123
136
  | **Checkpoint** | A serialized snapshot of a workflow's position and local variables, written at every yield. |
124
137
  | **Signal** | A fire-and-forget message sent _into_ a running workflow. Workflows pause at `ctx.waitForSignal()` until one arrives. |
125
138
  | **Update** | A request-response message sent into a running workflow. The caller blocks until the workflow returns a result. |
126
- | **Query** | A read-only peek at a running workflow's state. Never mutates anything. |
139
+ | **Query** | A read-only request sent with `engine.query()` or `handle.query()` to inspect workflow state without mutating it. |
127
140
  | **Search attribute** | Indexed metadata on a workflow (customer ID, region, status) set via `ctx.setAttribute()` and queryable through the list API. |
128
141
  | **Worker** | A process or thread that executes activities. Inline by default; can run remote over WebSocket. |
129
142
  | **Interceptor** | A composable hook that wraps context operations for tracing, validation, encryption, or any cross-cutting concern. |
@@ -134,7 +147,9 @@ Because recovery never re-executes the workflow from the beginning, your workflo
134
147
 
135
148
  ### Durable Workflows
136
149
 
137
- Generator functions with automatic checkpointing at every `yield*` boundary. Activities, sleeps, signals, queries, updates, parallel execution via `ctx.all()`, race semantics via `ctx.race()`, memoization via `ctx.memo()`, sagas via `ctx.saga()`, child workflows, and forks.
150
+ Generator functions with automatic checkpointing at every `yield*` boundary. Activities, sleeps, signals, condition gates with `ctx.waitUntil()`, queries, updates, structured logs with `ctx.log`, parallel execution via `ctx.all()`, race semantics via `ctx.race()`, memoization via `ctx.memo()`, sagas via `ctx.saga()`, child workflows, and forks. `ctx.all()` and `ctx.race()` can branch over activities, sleeps, and signal waits; use `ctx.race([ctx.waitForSignal(name), ctx.sleep(timeout)])` for signal timeouts instead of placing an unbounded signal wait directly in `ctx.all()`.
151
+
152
+ Every workflow context exposes `ctx.workflowId` and `ctx.workflowType`. `workflowType` is the registered name from `workflow({ name })`, so shared workflow code can log, tag, or branch on the current workflow type without closing over definition-site state.
138
153
 
139
154
  ```typescript
140
155
  const checkout = workflow({ name: 'checkout' })
@@ -180,9 +195,28 @@ const handle = await engine.start('approval', { orderId: 'order-123' });
180
195
  await engine.signal(handle.id, approvalSignal, { approved: true });
181
196
  ```
182
197
 
198
+ For state that changes through synchronous updates, use `ctx.waitUntil(predicate, timeout?)` as a durable condition gate. It re-checks a pure predicate when `ctx.onUpdate()` handlers mutate workflow-local state, or when the optional timeout fires. It is inline-only because the predicate closure stays in the engine process; signals do not re-drive it because signals are pull-based messages consumed by `ctx.waitForSignal()`.
199
+
200
+ ```typescript partial
201
+ const quorum = workflow({ name: 'quorum' })
202
+ .updates({
203
+ vote: update<void, number>('vote'),
204
+ })
205
+ .execute(async function* (ctx) {
206
+ let votes = 0;
207
+ ctx.onUpdate('vote', () => {
208
+ votes += 1;
209
+ return votes;
210
+ });
211
+
212
+ const reached = yield* ctx.waitUntil(() => votes >= 3, '1h');
213
+ return reached ? 'accepted' : 'expired';
214
+ });
215
+ ```
216
+
183
217
  ### Live Workflow Events
184
218
 
185
- Workflow handles expose lifecycle events through `addEventListener`, and client handles can open a live tail for progress UIs or operators. `LocalClient` reads from the in-process engine stream; `HttpClient` uses the per-workflow `/v1/workflows/:id/watch` WebSocket channel with history catch-up on connect and reconnect, so `addEventListener`, `client.tail(id)`, and `handle.tail()` are push-based rather than a polling loop.
219
+ Workflow handles expose lifecycle events through `addEventListener`, and client handles can open a live tail for progress UIs or operators. `LocalClient` reads from the in-process engine stream; `HttpClient` uses the per-workflow `/v1/workflows/:id/watch` WebSocket channel with history catch-up on connect and reconnect, so `addEventListener`, `client.tail(id)`, and `handle.tail()` are push-based rather than a polling loop. JSON-RPC clients can subscribe over WebSocket with `weft.workflows.subscribe` for one workflow or `weft.events.subscribe` for the fleet-wide event feed. Client code that receives a workflow id from another process can call `client.getHandle(id)` to re-attach a `ClientHandle` or get `null` when the run does not exist.
186
220
 
187
221
  ```typescript
188
222
  const handle = await client.start('checkout', order);
@@ -199,15 +233,17 @@ The tail is single-consumer and stops on terminal workflow events or `tail.close
199
233
 
200
234
  ### Idempotent Starts and Signal-With-Start
201
235
 
202
- Retried webhooks and queue deliveries should not double-start workflows. Pass a stable `idempotencyKey` to `engine.start()` to make every retry return a handle for the same run. Use `engine.startOrSignal()` when the first event should create the workflow and later events should signal the existing non-terminal run.
236
+ Retried webhooks and queue deliveries should not double-start workflows. Pass a stable `idempotencyKey` to `engine.start()` to make every retry return a handle for the same run. Use `engine.startOrSignal()` when the first event should create the workflow and later events should signal the existing non-terminal run. The call returns `{ handle, outcome }`, where `outcome` is `'started'` for the caller that created the run and `'signalled'` for callers that delivered to, or converged onto, an existing run.
203
237
 
204
238
  ```typescript
205
- const handle = await engine.startOrSignal(
239
+ const { handle, outcome } = await engine.startOrSignal(
206
240
  'approval',
207
241
  { orderId: 'order-123' },
208
242
  { name: 'payment', payload: { status: 'succeeded' } },
209
243
  { idempotencyKey: 'payment-webhook-order-123' },
210
244
  );
245
+
246
+ console.log(handle.id, outcome); // outcome is 'started' or 'signalled'
211
247
  ```
212
248
 
213
249
  The idempotency mapping intentionally outlives terminal cleanup. If retention removes the workflow record, the key is spent and future calls return a conflict instead of starting a replacement.
@@ -239,10 +275,14 @@ const orders = await engine.list({
239
275
 
240
276
  Workflow visibility extends the same list surface with operator filters for `idPrefix`, failure categories, created/updated/deadline ranges, and status arrays. Use `engine.aggregate()` or `GET /api/v1/workflows/aggregate` for grouped counts by status, type, failure category, or a search attribute. Existing Bun SQLite deployments should run the [workflow visibility backfill](documentation/guides/workflow-visibility-backfill.md) before relying on the indexed fast path for older workflows.
241
277
 
278
+ Failure-category filters use the current execution taxonomy only: `application`, `timeout`, `cancellation`, `resource`, and `system`. Older category names from pre-1.0 experiments are dropped during decode and are not expanded in list or aggregate filters.
279
+
242
280
  ### Human-in-the-Loop Review
243
281
 
244
282
  Weft can pause a workflow at any checkpoint and surface a decision payload to a human reviewer. The workflow resumes with the reviewer's decision—no polling, no special infrastructure.
245
283
 
284
+ As of June 12, 2026, [Temporal's public human-approval example](https://docs.temporal.io/ai-cookbook/human-in-the-loop-python) models approval with Signals, and [Inngest's TypeScript docs](https://www.inngest.com/docs/reference/typescript/v4/functions/step-wait-for-event) model approval waits with `step.waitForEvent()`. Weft makes the review itself a durable workflow operation: [`ctx.review()`](src/core/context/durable-operations.ts) creates a stored review request, exposes review list/get/decision APIs, emits review events, and resumes the workflow with the submitted decision.
285
+
246
286
  ```typescript
247
287
  import { Engine, workflow } from '@lostgradient/weft';
248
288
  import { SQLiteStorage } from '@lostgradient/weft/storage/sqlite';
@@ -280,7 +320,7 @@ const paymentWorkflow = workflow({ name: 'payment' })
280
320
  });
281
321
  ```
282
322
 
283
- If the process crashes between the approval decision arriving and `chargeCard` executing, the engine resumes from the last checkpoint—the charge runs exactly once. The reviewer's decision is persisted as part of the checkpoint; there is no resubmission.
323
+ If the process crashes after the approval decision is checkpointed, the reviewer is not asked again. The `chargeCard` activity is still an at-least-once side effect: if the payment provider accepts the charge and the process crashes before Weft commits the activity result, recovery can run `chargeCard` again. Pass an idempotency key, provider transaction lookup, or equivalent verifier to the payment provider; the [activities guide](documentation/guides/activities.md#per-call-options) explains that boundary in more detail.
284
324
 
285
325
  ### Pluggable Storage
286
326
 
@@ -320,7 +360,7 @@ await using server = serve({ engine, port: 7233 });
320
360
  // server.url is e.g. "http://0.0.0.0:7233"
321
361
  ```
322
362
 
323
- Endpoints under `/api/v1/` cover the full lifecycle: start workflows, list, signal, update, query, cancel, fork, and stream events. Content negotiation supports JSON and MessagePack. The server can also mount an externally supplied dashboard shell at known page routes; see the [server guide](documentation/guides/server.md#external-dashboard-mounting) for the hosting contract.
363
+ Endpoints under `/api/v1/` cover the full lifecycle: start workflows, list, signal, update, query, cancel, fork, and stream events. JSON-RPC over WebSocket also exposes workflow and fleet event subscriptions for operator UIs that need live state without polling. Content negotiation supports JSON and MessagePack. The server can also mount an externally supplied dashboard shell at known page routes; see the [server guide](documentation/guides/server.md#external-dashboard-mounting) for the hosting contract.
324
364
 
325
365
  ### Remote Workers
326
366
 
@@ -350,6 +390,8 @@ The core engine runs inside a Web Worker, with a Service Worker acting as the du
350
390
 
351
391
  Built-in event system (`EventTarget`-based, so it composes with everything), W3C `traceparent` propagation, and OpenTelemetry-compatible metrics. Composable interceptors layer cross-cutting concerns—tracing, validation, encryption—without any of them knowing about each other.
352
392
 
393
+ Schedules also emit `schedule:fired` on the live engine each time a schedule actually launches a workflow run. The event carries `scheduleId`, `workflowId`, `firedAt`, and the scheduled `occurrence` when one is retained, so in-process dispatchers can react to cadence without polling schedule state.
394
+
353
395
  ```typescript
354
396
  import { createObservabilityInterceptors, createOpenTelemetryMetrics } from '@lostgradient/weft';
355
397
 
@@ -364,6 +406,8 @@ const engine = new Engine({
364
406
  });
365
407
  ```
366
408
 
409
+ Inside workflow code, `ctx.log` emits structured console records with `workflowId`, `workflowType`, `level`, and `timestamp` attached. Caller attributes are nested under `attributes`, so they cannot overwrite the envelope. Logs at already-restored checkpoint positions are suppressed on recovery; logs at the live frontier still emit, and in worker mode the destination is the worker process console.
410
+
367
411
  ### Testing
368
412
 
369
413
  `TestEngine` swaps the production engine in tests and gives you a virtual clock. `engine.advanceTime('1 hour')` jumps timers forward without waiting; `engine.mock(activity, fake)` swaps in fake activity implementations with type-checked signatures, call recording, and per-call overrides.
@@ -428,6 +472,16 @@ function isAlreadyRunning(error: unknown): boolean {
428
472
  }
429
473
  ```
430
474
 
475
+ When the same producer might run through either `LocalClient` or `HttpClient`, use `isWeftFault(error, code)` for a specific branch. It matches same-process `WeftError` instances and HTTP-wrapped errors whose REST response carried the originating public `weftCode`.
476
+
477
+ ```typescript
478
+ import { isWeftFault } from '@lostgradient/weft';
479
+
480
+ function isMissingWorkflow(error: unknown): boolean {
481
+ return isWeftFault(error, 'WorkflowNotFoundError');
482
+ }
483
+ ```
484
+
431
485
  The exported `WeftErrorCode` union lists every code that belongs to a public, exported error class; those codes are stable contract and safe to `switch` on exhaustively. Errors that are internal to Weft also extend `WeftError` but carry codes intentionally left out of `WeftErrorCode` — `isWeftErrorCode` and `isWeftErrorLike` return `false` for them — so internal codes may change between releases without breaking your types.
432
486
 
433
487
  ## Installation
@@ -466,21 +520,22 @@ const welcome = workflow({ name: 'welcome' }).execute(
466
520
  engine.register(welcome);
467
521
  ```
468
522
 
469
- Each `ctx.step()` is a checkpoint boundary. The engine compiles step-style workflows to generator form at registration time. When you need durable timers, signals, or parallel execution, switch to the generator API.
523
+ Each `ctx.step()` is a checkpoint boundary. Completed steps replay from storage after crash recovery instead of re-running, and `compileStepWorkflow(...)` compiles the step-style function into the generator form the engine runs internally. Await each step before starting the next. When you need durable timers, signals, parallel execution, or worker-mode isolation, switch to the generator API.
470
524
 
471
525
  ## Weft vs. Temporal
472
526
 
473
- | Concept | Temporal | Weft |
474
- | ---------------------- | --------------------------------------------- | -------------------------------------------------------------------------- |
475
- | Core mental model | Replay determinism | Generators pause and resume |
476
- | Workflow language | Go, Java, TypeScript, Python, .NET, Ruby, PHP | TypeScript only (activities can be any language via `RemoteWorker`) |
477
- | Activity invocation | `proxyActivities()` + type import | `yield* ctx.run('activityName', input)` (declared in `.activities({...})`) |
478
- | Timer | Deterministic `workflow.sleep()` | `yield* ctx.sleep("1 hour")` |
479
- | Signal | `setHandler` + `condition` | `yield* ctx.waitForSignal(name)` |
480
- | Versioning | `patched()` / `deprecatePatch()` | Deploy new code (migration optional) |
481
- | Long-running workflows | `continueAsNew()` | None needed (checkpoint size is bounded by live state, not history length) |
482
- | Dev environment | Docker Compose + Temporal server | `bun add @lostgradient/weft` |
483
- | Bundling | Webpack for workflow sandbox | None |
527
+ | Concept | Temporal | Weft |
528
+ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- |
529
+ | Core mental model | Replay determinism | Generators pause and resume |
530
+ | Workflow language | Go, Java, TypeScript, Python, .NET, Ruby, PHP | TypeScript only (activities can be any language via `RemoteWorker`) |
531
+ | Activity invocation | `proxyActivities()` + type import | `yield* ctx.run('activityName', input)` (declared in `.activities({...})`) |
532
+ | Timer | Deterministic `workflow.sleep()` | `yield* ctx.sleep("1 hour")` |
533
+ | Signal | `setHandler` + `condition` | `yield* ctx.waitForSignal(name)` |
534
+ | Human review | Signals/queries/updates as [message-passing primitives](https://docs.temporal.io/develop/typescript/workflows/message-passing) | `yield* ctx.review(...)` with [durable review request](src/core/review/index.ts) and decision APIs |
535
+ | Versioning | `patched()` / `deprecatePatch()` | Stored and registered versions are strict recovery guards |
536
+ | Long-running workflows | `continueAsNew()` | None needed (checkpoint size is bounded by live state, not history length) |
537
+ | Dev environment | Docker Compose + Temporal server | `bun add @lostgradient/weft` |
538
+ | Bundling | Webpack for workflow sandbox | None |
484
539
 
485
540
  > Weft is for teams whose primary backend language is TypeScript. If you need workflows in multiple languages, [Temporal](https://temporal.io) is the right answer. For the design rationale, see [ADR 0001 — Workflows Are TypeScript-Only by Design](documentation/contributing/architecture-decisions/0001-workflows-typescript-only.md).
486
541
  >
@@ -505,9 +560,9 @@ Guides:
505
560
 
506
561
  Architecture and reference:
507
562
 
508
- - [Design Philosophy](documentation/architecture/design-philosophy.md), [Checkpoint vs. Replay](documentation/architecture/checkpoint-versus-replay.md), [Web Standards](documentation/architecture/web-standards.md)
509
- - [Browser Runtime](documentation/architecture/browser-runtime.md), [Web Workers](documentation/architecture/web-workers.md), [Single Binary](documentation/architecture/single-binary.md)
510
- - [API Reference](documentation/reference/) (Engine, Context, Storage, Server, Workers, Testing, Events, Interceptors, Observability, CLI, Configuration, Types)
563
+ - [Design Philosophy](documentation/architecture/design-philosophy.md), [Durability Guarantee](documentation/architecture/durability-guarantee.md), [Checkpoint vs. Replay](documentation/architecture/checkpoint-versus-replay.md), [Web Standards](documentation/architecture/web-standards.md)
564
+ - [Temporal Comparison](documentation/architecture/temporal-comparison.md), [Inngest Comparison](documentation/architecture/inngest-comparison.md), [Browser Runtime](documentation/architecture/browser-runtime.md), [Web Workers](documentation/architecture/web-workers.md), [Single Binary](documentation/architecture/single-binary.md)
565
+ - [API Reference](documentation/reference/) (Engine, Context, Storage, Server, Workers, Testing, Events, Errors, Interceptors, Observability, CLI, Configuration, Types)
511
566
 
512
567
  Contributing:
513
568
 
@@ -139,7 +139,13 @@ async function dispatchAndWait(server, storage, operationId, activityName, input
139
139
  await waitForResolvedStatus(storage, operationId, expectedStatus, timeoutMs);
140
140
  }
141
141
  async function runConformanceChecks(command, timeoutMs) {
142
- const storage = new MemoryStorage, engine = new Engine({ storage }), server = serve({ engine, port: 0, hostname: "127.0.0.1" }), checks = [];
142
+ const storage = new MemoryStorage, engine = new Engine({ storage }), server = serve({
143
+ engine,
144
+ port: 0,
145
+ hostname: "127.0.0.1",
146
+ workerReconnectGracePeriodMs: 100,
147
+ workerShutdownTimeoutMs: timeoutMs
148
+ }), checks = [];
143
149
  let worker;
144
150
  try {
145
151
  worker = startWorker(command, server);
@@ -1,8 +1,9 @@
1
1
  import { type CatalogWeftClient, type WeftClientConnection } from '../operation-client-runtime.ts';
2
- export declare const CATALOG_OPERATION_NAMES: readonly ["weft.activities.complete", "weft.activities.fail", "weft.recover.all", "weft.retention.get", "weft.reviews.decision.submit", "weft.reviews.get", "weft.reviews.list", "weft.schedules.cancel", "weft.schedules.create", "weft.schedules.get", "weft.schedules.list", "weft.schedules.pause", "weft.schedules.resume", "weft.schedules.update", "weft.system.metrics", "weft.system.registry", "weft.task.queues.list", "weft.tasks.diagnostics", "weft.updates.result.get", "weft.worker.deployments.drain", "weft.worker.deployments.resume", "weft.workers.drain", "weft.workers.list", "weft.workers.resume", "weft.workflows.aggregate", "weft.workflows.attributes.get", "weft.workflows.attributes.set", "weft.workflows.bulk.cancel", "weft.workflows.bulk.delete", "weft.workflows.bulk.signal", "weft.workflows.bulk.tags", "weft.workflows.cancel", "weft.workflows.checkpoints.get", "weft.workflows.checkpoints.list", "weft.workflows.events.list", "weft.workflows.fork", "weft.workflows.get", "weft.workflows.list", "weft.workflows.purge", "weft.workflows.query", "weft.workflows.replay", "weft.workflows.result.get", "weft.workflows.resume", "weft.workflows.signal", "weft.workflows.start", "weft.workflows.startorsignal", "weft.workflows.streams.chunks", "weft.workflows.suspend", "weft.workflows.tags.add", "weft.workflows.tags.remove", "weft.workflows.timeline.get", "weft.workflows.timeout", "weft.workflows.update"];
2
+ export declare const CATALOG_OPERATION_NAMES: readonly ["weft.activities.complete", "weft.activities.fail", "weft.recover.all", "weft.retention.get", "weft.reviews.decision.submit", "weft.reviews.get", "weft.reviews.list", "weft.schedules.cancel", "weft.schedules.create", "weft.schedules.get", "weft.schedules.list", "weft.schedules.pause", "weft.schedules.resume", "weft.schedules.update", "weft.system.metrics", "weft.system.registry", "weft.task.queues.list", "weft.tasks.diagnostics", "weft.updates.result.get", "weft.worker.deployments.drain", "weft.worker.deployments.resume", "weft.workers.drain", "weft.workers.list", "weft.workers.resume", "weft.workflows.aggregate", "weft.workflows.attributes.get", "weft.workflows.attributes.set", "weft.workflows.bulk.cancel", "weft.workflows.bulk.delete", "weft.workflows.bulk.retryfailed", "weft.workflows.bulk.signal", "weft.workflows.bulk.tags", "weft.workflows.cancel", "weft.workflows.checkpoints.get", "weft.workflows.checkpoints.list", "weft.workflows.events.list", "weft.workflows.fork", "weft.workflows.get", "weft.workflows.list", "weft.workflows.purge", "weft.workflows.query", "weft.workflows.replay", "weft.workflows.result.get", "weft.workflows.resume", "weft.workflows.signal", "weft.workflows.start", "weft.workflows.startorsignal", "weft.workflows.streams.chunks", "weft.workflows.suspend", "weft.workflows.tags.add", "weft.workflows.tags.remove", "weft.workflows.timeline.get", "weft.workflows.timeout", "weft.workflows.update"];
3
3
  export type CatalogOperationName = (typeof CATALOG_OPERATION_NAMES)[number];
4
- type SharedAttributesConfirmationTo_f933f774 = {
4
+ type SharedAttributesBulkConcurrenc_73ecbca6 = {
5
5
  readonly attributes?: ReadonlyArray<SharedGtGteKey_896a0c41>;
6
+ readonly bulkConcurrency?: number;
6
7
  readonly confirmationToken?: string;
7
8
  readonly createdAt?: SharedGtGteLt_d9a61361;
8
9
  readonly dryRun?: boolean;
@@ -104,7 +105,7 @@ export type CatalogOperationTypes = {
104
105
  'weft.reviews.list': {
105
106
  readonly input: {
106
107
  readonly reviewType?: string;
107
- readonly status?: string;
108
+ readonly status?: 'pending' | 'completed';
108
109
  readonly workflowId?: string;
109
110
  };
110
111
  readonly output: {
@@ -126,6 +127,7 @@ export type CatalogOperationTypes = {
126
127
  readonly every?: unknown;
127
128
  readonly id?: unknown;
128
129
  readonly input?: unknown;
130
+ readonly jitter?: unknown;
129
131
  readonly overlap?: unknown;
130
132
  readonly type: unknown;
131
133
  };
@@ -198,7 +200,7 @@ export type CatalogOperationTypes = {
198
200
  readonly oldestEnqueuedAt: unknown;
199
201
  readonly oldestQueuedAgeMs: unknown;
200
202
  readonly queue: string;
201
- readonly schedulingPolicy: string;
203
+ readonly schedulingPolicy: 'priority' | 'fifo' | 'lifo';
202
204
  readonly waitingPollers: number;
203
205
  }>;
204
206
  };
@@ -217,24 +219,29 @@ export type CatalogOperationTypes = {
217
219
  readonly output: {
218
220
  readonly items: ReadonlyArray<{
219
221
  readonly activityName?: string;
222
+ readonly deadLetterReason?: string;
223
+ readonly deadLetteredAt?: number;
220
224
  readonly evidence: ReadonlyArray<string>;
221
225
  readonly executionLatencyMs?: number;
222
226
  readonly heartbeatAgeMs?: number;
223
- readonly kind: string;
224
- readonly lastRequeueReason?: string;
227
+ readonly kind: 'stuck-queued' | 'stale-inflight' | 'retry-storm' | 'all-workers-at-capacity' | 'dead-lettered';
228
+ readonly lastRequeueReason?: 'visibility-timeout' | 'worker-disconnect';
225
229
  readonly operationId?: string;
226
230
  readonly queue?: string;
227
231
  readonly queueLatencyMs?: number;
228
232
  readonly requeueCount: number;
229
233
  readonly resolutionReason?: string;
234
+ readonly retryAttempts?: number;
230
235
  readonly retryCount: number;
231
- readonly state: string;
236
+ readonly state: 'queued' | 'inflight' | 'resolved' | 'capacity' | 'dead-lettered';
237
+ readonly storageError?: string;
232
238
  readonly workerId?: string;
233
239
  readonly workflowId?: string;
234
240
  }>;
235
241
  readonly limit: number;
236
242
  readonly summary: {
237
243
  readonly allWorkersAtCapacity: number;
244
+ readonly deadLettered: number;
238
245
  readonly retryStorms: number;
239
246
  readonly staleInflight: number;
240
247
  readonly stuckQueued: number;
@@ -282,7 +289,7 @@ export type CatalogOperationTypes = {
282
289
  readonly drainedWorkers: number;
283
290
  readonly drainingWorkers: number;
284
291
  readonly gitSha: unknown;
285
- readonly health: string;
292
+ readonly health: 'active' | 'draining' | 'drained';
286
293
  readonly inFlight: number;
287
294
  readonly oldestStartedAt: unknown;
288
295
  readonly runtimeVersion: unknown;
@@ -297,7 +304,7 @@ export type CatalogOperationTypes = {
297
304
  readonly connectedAt: number;
298
305
  readonly deploymentName?: string;
299
306
  readonly gitSha?: string;
300
- readonly health: string;
307
+ readonly health: 'active' | 'draining' | 'drained';
301
308
  readonly heartbeatAgeMs: number;
302
309
  readonly id: string;
303
310
  readonly inFlight: number;
@@ -306,7 +313,7 @@ export type CatalogOperationTypes = {
306
313
  readonly runtimeVersion?: string;
307
314
  readonly startedAt: number;
308
315
  }>;
309
- readonly routingPolicy: string;
316
+ readonly routingPolicy: 'least-loaded' | 'round-robin' | 'fair-share';
310
317
  };
311
318
  readonly faults: never;
312
319
  };
@@ -366,18 +373,24 @@ export type CatalogOperationTypes = {
366
373
  readonly faults: never;
367
374
  };
368
375
  'weft.workflows.bulk.cancel': {
369
- readonly input: SharedAttributesConfirmationTo_f933f774;
376
+ readonly input: SharedAttributesBulkConcurrenc_73ecbca6;
370
377
  readonly output: unknown;
371
378
  readonly faults: never;
372
379
  };
373
380
  'weft.workflows.bulk.delete': {
374
- readonly input: SharedAttributesConfirmationTo_f933f774;
381
+ readonly input: SharedAttributesBulkConcurrenc_73ecbca6;
375
382
  readonly output: unknown;
376
383
  readonly faults: 'Unprocessable';
377
384
  };
385
+ 'weft.workflows.bulk.retryfailed': {
386
+ readonly input: SharedAttributesBulkConcurrenc_73ecbca6;
387
+ readonly output: unknown;
388
+ readonly faults: never;
389
+ };
378
390
  'weft.workflows.bulk.signal': {
379
391
  readonly input: {
380
392
  readonly attributes?: ReadonlyArray<SharedGtGteKey_896a0c41>;
393
+ readonly bulkConcurrency?: number;
381
394
  readonly confirmationToken?: string;
382
395
  readonly createdAt?: SharedGtGteLt_d9a61361;
383
396
  readonly dryRun?: boolean;
@@ -399,10 +412,11 @@ export type CatalogOperationTypes = {
399
412
  };
400
413
  'weft.workflows.bulk.tags': {
401
414
  readonly input: {
415
+ readonly bulkConcurrency?: number;
402
416
  readonly confirmationToken?: string;
403
417
  readonly dryRun?: boolean;
404
418
  readonly filter?: SharedAttributesCreatedAtExecu_c9ba5dc6;
405
- readonly operation: string;
419
+ readonly operation: 'add' | 'remove';
406
420
  readonly requestId?: string;
407
421
  readonly tags: ReadonlyArray<string>;
408
422
  };
@@ -557,6 +571,7 @@ export type CatalogOperationTypes = {
557
571
  };
558
572
  readonly output: {
559
573
  readonly id: string;
574
+ readonly outcome: 'started' | 'signalled';
560
575
  };
561
576
  readonly faults: 'Conflict';
562
577
  };
@@ -32,6 +32,7 @@ export const CATALOG_OPERATION_NAMES = [
32
32
  "weft.workflows.attributes.set",
33
33
  "weft.workflows.bulk.cancel",
34
34
  "weft.workflows.bulk.delete",
35
+ "weft.workflows.bulk.retryfailed",
35
36
  "weft.workflows.bulk.signal",
36
37
  "weft.workflows.bulk.tags",
37
38
  "weft.workflows.cancel",
@@ -4,7 +4,7 @@ export declare const CONFORMANCE_HELP_TEXT = "\nweft conformance - Run RemoteWor
4
4
  export declare const DOCTOR_HELP_TEXT = "\nweft doctor - Run diagnostics on the Weft database\n\nUsage: weft doctor [options]\n\nOptions:\n -d, --database <path> Database file path (default: ./weft.db)\n -j, --json Output results as JSON\n -h, --help Show this help message\n";
5
5
  export declare const VERSION_CHECK_HELP_TEXT = "\nweft version:check - Check workflow version compatibility\n\nUsage: weft version:check [options]\n\nOptions:\n -d, --database <path> Database file path (default: ./weft.db)\n -w, --workflows <path> Path to workflows module\n -j, --json Output results as JSON\n -h, --help Show this help message\n";
6
6
  export declare const TIMELINE_HELP_TEXT = "\nweft timeline - Inspect workflow timeline and replay history\n\nUsage:\n weft timeline <workflowId> [options]\n weft timeline <workflowId> --diff <fromStep> <toStep> [options]\n\nOptions:\n -d, --database <path> Database file path (default: ./weft.db)\n --step <step> Show replay details for one checkpoint step\n --diff Diff two checkpoint steps (requires two positional step numbers)\n -h, --help Show this help message\n";
7
- export declare const SCHEDULE_HELP_TEXT = "\nweft schedule - Manage recurring schedules\n\nUsage:\n weft schedule list [options]\n weft schedule create <workflowType> <cronExpression> [options]\n weft schedule create <workflowType> --every <duration> [options]\n weft schedule pause <scheduleId> [options]\n weft schedule resume <scheduleId> [options]\n weft schedule cancel <scheduleId> [options]\n\nProvide a cron expression positional OR an --every interval (e.g. \"30s\", \"1h\"),\nbut not both. Interval schedules fire one period after creation, then every\nperiod after that.\n\nOptions:\n -d, --database <path> Database file path (default: ./weft.db)\n -s, --storage <backend> Storage backend: sqlite, lmdb (default: sqlite)\n -w, --workflows <path> Path to workflow registrations module (required for create)\n --every <duration> Interval cadence for create (e.g. 30s, 5m, 1h); mutually exclusive with the cron positional\n --input <json> JSON input payload for create (default: null)\n --id <id> Custom schedule id for create\n --overlap <policy> Overlap policy: skip, queue, cancel-running, allow\n --backfill Run missed ticks on recovery\n -j, --json Output results as JSON\n -h, --help Show this help message\n";
7
+ export declare const SCHEDULE_HELP_TEXT = "\nweft schedule - Manage recurring schedules\n\nUsage:\n weft schedule list [options]\n weft schedule create <workflowType> <cronExpression> [options]\n weft schedule create <workflowType> --every <duration> [options]\n weft schedule pause <scheduleId> [options]\n weft schedule resume <scheduleId> [options]\n weft schedule cancel <scheduleId> [options]\n\nProvide a cron expression positional OR an --every interval (e.g. \"30s\", \"1h\"),\nbut not both. Interval schedules fire one period after creation, then every\nperiod after that.\n\nOptions:\n -d, --database <path> Database file path (default: ./weft.db)\n -s, --storage <backend> Storage backend: sqlite, lmdb (default: sqlite)\n -w, --workflows <path> Path to workflow registrations module (required for create)\n --every <duration> Interval cadence for create (e.g. 30s, 5m, 1h); mutually exclusive with the cron positional\n --input <json> JSON input payload for create (default: null)\n --id <id> Custom schedule id for create\n --overlap <policy> Overlap policy: skip, queue, cancel-running, allow\n --backfill Run missed ticks on recovery\n --jitter <duration> Deterministic dispatch jitter for create (e.g. 30s, 5m)\n -j, --json Output results as JSON\n -h, --help Show this help message\n";
8
8
  export declare const VALIDATE_HELP_TEXT = "\nweft validate - Lint workflow registrations for design-time anti-patterns\n\nUsage: weft validate <entry.ts>... [options]\n\nArguments:\n <entry.ts>... One or more TypeScript modules or glob patterns that\n resolve to workflow registrations and/or activity\n definitions.\n\nOptions:\n -j, --json Output results as JSON\n -h, --help Show this help message\n\nExit codes:\n 0 No errors (warnings may be present)\n 1 One or more errors detected\n 2 Entry file could not be loaded (takes precedence over validation errors)\n\nJSON output:\n { entries, valid, hasLoadErrors, hasValidationErrors }\n\nChecks performed:\n unbounded-retry Activity retry.maxAttempts is Infinity\n stateful-without-compensator Non-idempotent activity has no compensate fn\n";
9
9
  export declare const SERVER_HELP_TEXT = "\nweft server - Inspect a running server's health and operation surface\n\nUsage:\n weft server health [options]\n weft server info [options]\n\nOptions:\n --server <url> Server URL (default: WEFT_ADDR, profile, run lockfile, or localhost)\n --token <token> Bearer token (default: WEFT_TOKEN)\n --profile <name> Profile from ~/.weft/config\n --wait (health) Poll until the server is reachable\n --wait-timeout <ms> (health) Maximum time to wait, in milliseconds (default: 30000)\n -j, --json Emit machine-readable JSON output\n -q, --quiet Suppress success/error text (use the exit code)\n -h, --help Show this help message\n\nExit codes:\n 0 Healthy\n 1 Unreachable / unhealthy\n 2 Connection error\n";
10
10
  export declare const WORKFLOW_HELP_TEXT = "\nweft workflow - List, inspect, start, signal, and cancel workflows on a server\n\nUsage:\n weft workflow ls [--type <type>] [--status <status>] [--limit <n>] [options]\n weft workflow get <workflow-id> [options]\n weft workflow events <workflow-id> [options]\n weft workflow start <workflow-type> [--input <json> | --input-file <path|->] [--id <id>] [options]\n weft workflow cancel <workflow-id> [--yes] [--dry-run] [options]\n weft workflow signal <workflow-id> <signal-name> [--input <json> | --input-file <path|->] [options]\n\nOptions:\n --server <url> Server URL (default: WEFT_ADDR, profile, run lockfile, or localhost)\n --token <token> Bearer token (default: WEFT_TOKEN)\n --profile <name> Profile from ~/.weft/config\n --type <type> (ls) Filter by workflow type\n --status <status> (ls) Filter by workflow status\n --limit <n> (ls) Maximum number of rows\n --input <json> (start/signal) JSON input payload\n --input-file <path> (start/signal) Read JSON input from a file, or '-' for stdin\n --id <id> (start) Explicit workflow id\n -y, --yes (cancel) Confirm without prompting\n --dry-run (cancel) Print affected count without cancelling\n -j, --json Emit machine-readable output (NDJSON for lists)\n -q, --quiet Print ids only / suppress success text\n -h, --help Show this help message\n\nExit codes:\n 0 Success\n 1 Operation failed or destructive operation was not confirmed\n 2 Connection error\n 3 Usage or input error\n 4 Operation unavailable on this server (version skew)\n";
@@ -123,6 +123,7 @@ Options:
123
123
  --id <id> Custom schedule id for create
124
124
  --overlap <policy> Overlap policy: skip, queue, cancel-running, allow
125
125
  --backfill Run missed ticks on recovery
126
+ --jitter <duration> Deterministic dispatch jitter for create (e.g. 30s, 5m)
126
127
  -j, --json Output results as JSON
127
128
  -h, --help Show this help message
128
129
  `, VALIDATE_HELP_TEXT = `
@@ -23,6 +23,14 @@ export type CatalogOperationSnapshot = {
23
23
  readonly tags: ReadonlyArray<string>;
24
24
  readonly destructive: boolean;
25
25
  readonly access: CatalogAccessSnapshot;
26
+ readonly parameterizedAccess?: {
27
+ readonly discriminator: string;
28
+ readonly defaultValue?: string;
29
+ readonly variants: ReadonlyArray<{
30
+ readonly value: string;
31
+ readonly access: CatalogAccessSnapshot;
32
+ }>;
33
+ };
26
34
  readonly transports: TransportAvailability;
27
35
  readonly producibleFaults: ReadonlyArray<FaultCode>;
28
36
  readonly inputSchema: Record<string, unknown>;
@@ -22,6 +22,7 @@ function operationToSnapshot(operation) {
22
22
  tags: [...operation.tags].toSorted(compareStrings),
23
23
  destructive: operation.destructive ?? !1,
24
24
  access: accessToSnapshot(operation.access),
25
+ ...operation.parameterizedAccess === void 0 ? {} : { parameterizedAccess: parameterizedAccessToSnapshot(operation.parameterizedAccess) },
25
26
  transports: { ...operation.transports },
26
27
  producibleFaults: [...operation.producibleFaults ?? []].toSorted(compareStrings),
27
28
  inputSchema: normalizeJsonObject(definitionSchemaToJsonSchema(operation.inputSchema, "input")),
@@ -29,6 +30,16 @@ function operationToSnapshot(operation) {
29
30
  ...eventSchema === void 0 ? {} : { eventSchema: normalizeJsonObject(definitionSchemaToJsonSchema(eventSchema, "output")) }
30
31
  };
31
32
  }
33
+ function parameterizedAccessToSnapshot(hint) {
34
+ return {
35
+ discriminator: hint.discriminator,
36
+ ...hint.defaultValue === void 0 ? {} : { defaultValue: hint.defaultValue },
37
+ variants: hint.variants.map((variant) => ({
38
+ value: variant.value,
39
+ access: accessToSnapshot(variant.access)
40
+ })).toSorted((left, right) => compareStrings(left.value, right.value))
41
+ };
42
+ }
32
43
  function accessToSnapshot(access) {
33
44
  if (access.kind === "public")
34
45
  return { kind: "public" };
@@ -13,6 +13,7 @@ function parseScheduleCliValues(args) {
13
13
  id: { type: "string" },
14
14
  overlap: { type: "string" },
15
15
  backfill: { type: "boolean", default: !1 },
16
+ jitter: { type: "string" },
16
17
  help: { type: "boolean", short: "h", default: !1 },
17
18
  json: { type: "boolean", short: "j", default: !1 }
18
19
  },
@@ -79,7 +80,8 @@ function buildScheduleCreateOptionalFields(values) {
79
80
  const overlap = parseScheduleOverlapPolicy(values.overlap);
80
81
  return {
81
82
  ...values.id !== void 0 ? { id: values.id } : {},
82
- ...overlap !== void 0 ? { overlap } : {}
83
+ ...overlap !== void 0 ? { overlap } : {},
84
+ ...values.jitter !== void 0 ? { jitter: values.jitter } : {}
83
85
  };
84
86
  }
85
87
  function buildScheduleCreateCommand(values, positionals) {
@@ -67,7 +67,8 @@ async function executeScheduleCreate(options, engine, loadRegistrationsFromModul
67
67
  const spec = options.every !== void 0 ? { every: options.every } : options.cronExpression, handle = await engine.schedule(options.workflowType, parsedInput.value, spec, {
68
68
  ...options.id !== void 0 ? { id: options.id } : {},
69
69
  ...options.overlap !== void 0 ? { overlap: options.overlap } : {},
70
- ...options.backfill ? { backfill: !0 } : {}
70
+ ...options.backfill ? { backfill: !0 } : {},
71
+ ...options.jitter !== void 0 ? { jitter: options.jitter } : {}
71
72
  }), schedule = await handle.describe();
72
73
  return {
73
74
  stdout: formatScheduleCommandOutput(schedule, options.json, `Created schedule ${handle.id}`),
@@ -84,6 +84,7 @@ export type CliCommand = {
84
84
  id?: string;
85
85
  overlap?: ScheduleOverlapPolicy;
86
86
  backfill: boolean;
87
+ jitter?: string;
87
88
  help: boolean;
88
89
  json: boolean;
89
90
  } | {