deepline 0.3.89 → 0.3.90

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 (211) hide show
  1. package/contracts/install-commands.json +29 -0
  2. package/dist/bundling-sources/sdk/src/client.ts +120 -37
  3. package/dist/bundling-sources/sdk/src/index.ts +4 -0
  4. package/dist/bundling-sources/sdk/src/pagination.ts +25 -0
  5. package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +1 -1
  6. package/dist/bundling-sources/sdk/src/release.ts +16 -9
  7. package/dist/bundling-sources/sdk/src/types.ts +23 -0
  8. package/dist/bundling-sources/shared_libs/monitors/analytics-public.ts +10 -0
  9. package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +3 -0
  10. package/dist/bundling-sources/shared_libs/monitors/inbound-queue.ts +4 -4
  11. package/dist/bundling-sources/shared_libs/monitors/inventory-reconciliation.ts +59 -0
  12. package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +7 -9
  13. package/dist/bundling-sources/shared_libs/monitors/package.json +7 -0
  14. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +44 -2
  15. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-consumer-health.ts +2 -2
  16. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-identity-claims.ts +2 -2
  17. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-public-aliases.ts +1 -1
  18. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-dead-letter.ts +245 -0
  19. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-message.ts +38 -0
  20. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue-ack-probe.ts +94 -0
  21. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue-delivery.ts +60 -0
  22. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue.ts +60 -0
  23. package/dist/bundling-sources/shared_libs/monitors/snitcher-install-validation.ts +1 -1
  24. package/dist/bundling-sources/shared_libs/monitors/snitcher-ip2company.ts +2 -2
  25. package/dist/bundling-sources/shared_libs/monitors/snitcher-radar.ts +1 -1
  26. package/dist/bundling-sources/shared_libs/monitors/tracking-provider-integrations.ts +1 -1
  27. package/dist/bundling-sources/shared_libs/observability/build-context.ts +13 -0
  28. package/dist/bundling-sources/shared_libs/observability/log-metadata.ts +160 -0
  29. package/dist/bundling-sources/shared_libs/observability/request-context.ts +68 -0
  30. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +654 -0
  31. package/dist/bundling-sources/shared_libs/observability/scheduled-work-manual.ts +35 -0
  32. package/dist/bundling-sources/shared_libs/observability/scheduled-work.ts +5 -0
  33. package/dist/bundling-sources/shared_libs/play-data-plane/neon-constants.ts +9 -0
  34. package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +272 -0
  35. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +45 -0
  36. package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +66 -1
  37. package/dist/bundling-sources/shared_libs/play-runtime/async-play-invocation.ts +0 -1
  38. package/dist/bundling-sources/shared_libs/play-runtime/bounceban-batching.ts +137 -0
  39. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +779 -140
  40. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +46 -0
  41. package/dist/bundling-sources/shared_libs/play-runtime/daytona-payload-contract.ts +68 -0
  42. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +103 -0
  43. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +725 -0
  44. package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +29 -0
  45. package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +23 -0
  46. package/dist/bundling-sources/shared_libs/play-runtime/execution-gateway-invocation-fence.ts +442 -0
  47. package/dist/bundling-sources/shared_libs/play-runtime/execution-protocol.ts +3 -3
  48. package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +18 -0
  49. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +9 -0
  50. package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +1 -1
  51. package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +1 -1
  52. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/contracts.ts +66 -0
  53. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/job.ts +145 -0
  54. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/ports.ts +21 -0
  55. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/postgres-store.ts +170 -0
  56. package/dist/bundling-sources/shared_libs/play-runtime/internal-bootstrap-token.ts +1322 -0
  57. package/dist/bundling-sources/shared_libs/play-runtime/internal-step-ids.ts +2 -2
  58. package/dist/bundling-sources/shared_libs/play-runtime/lane-retirement-gate.ts +1 -1
  59. package/dist/bundling-sources/shared_libs/play-runtime/launch-source-policy.ts +112 -0
  60. package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +8 -0
  61. package/dist/bundling-sources/shared_libs/play-runtime/perf-trace.ts +127 -0
  62. package/dist/bundling-sources/shared_libs/play-runtime/play-artifact-runtime-contract.ts +5 -0
  63. package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +24 -1
  64. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/contracts.ts +56 -0
  65. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/index.ts +13 -0
  66. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/job.ts +41 -0
  67. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/ports.ts +17 -0
  68. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/postgres-adapter.ts +54 -0
  69. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/contracts.ts +114 -0
  70. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/engine-suspension.ts +108 -0
  71. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/index.ts +36 -0
  72. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/job.ts +97 -0
  73. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/ports.ts +104 -0
  74. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/postgres-fence-adapter.ts +263 -0
  75. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/worker-terminal-projection.ts +64 -0
  76. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/contracts.ts +29 -0
  77. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/gateway-adapter.ts +56 -0
  78. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/index.ts +15 -0
  79. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/job.ts +65 -0
  80. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/ports.ts +17 -0
  81. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/contracts.ts +42 -0
  82. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/index.ts +17 -0
  83. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +142 -0
  84. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/ports.ts +42 -0
  85. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/postgres-adapter.ts +102 -0
  86. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/contracts.ts +60 -0
  87. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/index.ts +16 -0
  88. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/job.ts +78 -0
  89. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/ports.ts +54 -0
  90. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/postgres-adapter.ts +71 -0
  91. package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +4 -0
  92. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +2 -0
  93. package/dist/bundling-sources/shared_libs/play-runtime/receipt-status.ts +5 -8
  94. package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +3 -5
  95. package/dist/bundling-sources/shared_libs/play-runtime/run-identity.ts +168 -0
  96. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +72 -9
  97. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +6 -12
  98. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +19 -0
  99. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/bundle.ts +0 -1
  100. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +14 -44
  101. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +57 -205
  102. package/dist/bundling-sources/shared_libs/play-runtime/runtime-authority.ts +201 -0
  103. package/dist/bundling-sources/shared_libs/play-runtime/runtime-env.ts +6 -0
  104. package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +67 -0
  105. package/dist/bundling-sources/shared_libs/play-runtime/runtime-release-environment.ts +2 -0
  106. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sandbox-contract.ts +68 -0
  107. package/dist/bundling-sources/shared_libs/play-runtime/runtime-scheduler-topology.ts +14 -2
  108. package/dist/bundling-sources/shared_libs/play-runtime/runtime-telemetry.ts +108 -0
  109. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +4 -0
  110. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +3 -0
  111. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +7 -0
  112. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-deadline-reconciliation.ts +88 -0
  113. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-deploy-task.ts +124 -0
  114. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-run-task.ts +68 -0
  115. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-pool.ts +193 -0
  116. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-queue-lifecycle.ts +269 -0
  117. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-queue-suffix.ts +73 -0
  118. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +6642 -0
  119. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +897 -0
  120. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-metrics.ts +120 -0
  121. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +76 -0
  122. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd.ts +476 -0
  123. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-heavy-request-admission.ts +47 -0
  124. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-progress-registry.ts +147 -0
  125. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/index.ts +27 -0
  126. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/lazy.ts +50 -0
  127. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/play-run-recovery.ts +98 -0
  128. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-budget-state.ts +260 -0
  129. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +1416 -0
  130. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +1255 -0
  131. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +942 -0
  132. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +14636 -0
  133. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +888 -0
  134. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +355 -0
  135. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-terminal-transition.ts +46 -0
  136. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runner-push.ts +60 -0
  137. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-api-origin.ts +33 -0
  138. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-receipt-gateway-health.ts +64 -0
  139. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +835 -0
  140. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-ledger-reconciliation.ts +1218 -0
  141. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-operation.ts +207 -0
  142. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-scheduler-schema.ts +10 -0
  143. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/scheduler-capacity.ts +123 -0
  144. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/scheduler-launch-read-observability.ts +78 -0
  145. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/submit-admission.ts +169 -0
  146. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/terminal-contract.ts +20 -0
  147. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-queue-metrics.ts +34 -0
  148. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-resource-metrics.ts +249 -0
  149. package/dist/bundling-sources/shared_libs/play-runtime/sheet-attempt-sql.ts +7 -0
  150. package/dist/bundling-sources/shared_libs/play-runtime/step-progress.ts +296 -0
  151. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/native-batch.ts +3 -3
  152. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/runtime-step-receipts-adapter.ts +20 -1
  153. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +60 -15
  154. package/dist/bundling-sources/shared_libs/play-runtime/tool-execution-outcome.ts +20 -0
  155. package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +12 -0
  156. package/dist/bundling-sources/shared_libs/play-runtime/vercel-protection.ts +14 -1
  157. package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +165 -0
  158. package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +15 -23
  159. package/dist/bundling-sources/shared_libs/play-runtime/workflow-executor-auth.ts +169 -0
  160. package/dist/bundling-sources/shared_libs/play-runtime/zerobounce-batching.ts +122 -0
  161. package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +2 -0
  162. package/dist/bundling-sources/shared_libs/plays/contracts.ts +2 -0
  163. package/dist/bundling-sources/shared_libs/plays/deployment-status.ts +1 -1
  164. package/dist/bundling-sources/shared_libs/plays/docflow.ts +1 -1
  165. package/dist/bundling-sources/shared_libs/plays/play-grep-search.ts +39 -0
  166. package/dist/bundling-sources/shared_libs/plays/share/copy.ts +271 -0
  167. package/dist/bundling-sources/shared_libs/plays/share/metrics.ts +140 -0
  168. package/dist/bundling-sources/shared_libs/plays/share/public-read-model.ts +86 -0
  169. package/dist/bundling-sources/shared_libs/plays/share/seo-quality.ts +181 -0
  170. package/dist/bundling-sources/shared_libs/plays/share/static-pipeline-summary.ts +658 -0
  171. package/dist/bundling-sources/shared_libs/plays/share/types.ts +197 -0
  172. package/dist/bundling-sources/shared_libs/plays/slack-hitl-timeout-error.ts +37 -0
  173. package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +6 -1
  174. package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +1 -1
  175. package/dist/bundling-sources/shared_libs/product-notifications/configuration.ts +7 -1
  176. package/dist/bundling-sources/shared_libs/product-notifications/default-policy.ts +3 -2
  177. package/dist/bundling-sources/shared_libs/product-notifications/overflow.ts +18 -0
  178. package/dist/bundling-sources/shared_libs/product-notifications/rolling-limit.ts +24 -0
  179. package/dist/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +624 -0
  180. package/dist/bundling-sources/shared_libs/product-notifications/slack-payload.ts +140 -0
  181. package/dist/bundling-sources/shared_libs/product-notifications/slack-transport.ts +75 -0
  182. package/dist/bundling-sources/shared_libs/runtime-env.ts +6 -0
  183. package/dist/bundling-sources/shared_libs/security/email-blacklist.ts +42 -0
  184. package/dist/bundling-sources/shared_libs/security/header-safe-env.ts +10 -3
  185. package/dist/bundling-sources/shared_libs/security/slack-sanitize.ts +133 -0
  186. package/dist/cli/getting-started.d.mts +52 -0
  187. package/dist/cli/getting-started.d.ts +52 -0
  188. package/dist/cli/getting-started.js +65 -0
  189. package/dist/cli/getting-started.mjs +36 -0
  190. package/dist/cli/index.d.mts +9 -0
  191. package/dist/cli/index.d.ts +9 -0
  192. package/dist/cli/index.js +545 -264
  193. package/dist/cli/index.mjs +543 -271
  194. package/dist/{compiler-manifest-DsLbQaew.d.mts → compiler-manifest-BaJfE-5H.d.mts} +5 -3
  195. package/dist/{compiler-manifest-DsLbQaew.d.ts → compiler-manifest-BaJfE-5H.d.ts} +5 -3
  196. package/dist/index.d.mts +81 -148
  197. package/dist/index.d.ts +81 -148
  198. package/dist/index.js +83 -26
  199. package/dist/index.mjs +83 -26
  200. package/dist/install-integrity.json +130 -2
  201. package/dist/monitor-fleet-contract.d.mts +138 -0
  202. package/dist/monitor-fleet-contract.d.ts +138 -0
  203. package/dist/monitor-fleet-contract.js +404 -0
  204. package/dist/monitor-fleet-contract.mjs +367 -0
  205. package/dist/plays/bundle-play-file.d.mts +2 -2
  206. package/dist/plays/bundle-play-file.d.ts +2 -2
  207. package/dist/release.d.mts +255 -0
  208. package/dist/release.d.ts +255 -0
  209. package/dist/release.js +215 -0
  210. package/dist/release.mjs +188 -0
  211. package/package.json +21 -4
@@ -4,9 +4,9 @@
4
4
  * Static analysis turns top-level play statements it cannot attribute to a
5
5
  * structured step into `run_javascript` glue substeps whose alias is a
6
6
  * machine-generated source line range (`lines_<startLine>_<endLine>`, built in
7
- * `src/lib/plays/static-analysis.ts` → `createCodeStageForStatements`). The
7
+ * `apps/deepline-api/src/lib/plays/static-analysis.ts` → `createCodeStageForStatements`). The
8
8
  * execution plan / runtime node ids namespace every substep by its type
9
- * (`getStaticSubstepNodeId` in `src/lib/plays/step-progress.ts`), so glue nodes are ALWAYS
9
+ * (`getStaticSubstepNodeId` in `packages/play-runtime/step-progress.ts`), so glue nodes are ALWAYS
10
10
  * `run_javascript:<alias>` on the wire (ledger stepsById, snapshot
11
11
  * nodeStates, `play.step.*` stream events).
12
12
  *
@@ -5,7 +5,7 @@
5
5
  * reach exactly the same verdict and none of them may drag the others'
6
6
  * dependencies in:
7
7
  *
8
- * - the Next.js app (`src/lib/plays/runtime-lanes.ts`, the admin and internal
8
+ * - the Next.js app (`apps/deepline-api/src/lib/plays/runtime-lanes.ts`, the admin and internal
9
9
  * lane endpoints), which also talks to Convex;
10
10
  * - `scripts/fly-absurd-lane.ts` retire, run by the release controller; and
11
11
  * - `apps/absurd-release-scaler/index.ts`, which owns retirement of every lane
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Queue-admission policy is about *how the run was invoked*, not whether its
3
+ * artifact is published, ad-hoc, or draft. A manual API run can launch a
4
+ * published artifact, while a webhook can launch a draft artifact.
5
+ */
6
+ export type PlayLaunchTriggerSource =
7
+ | 'api'
8
+ | 'webhook'
9
+ | 'cron'
10
+ | 'sql_listener'
11
+ | 'async_child';
12
+
13
+ export type PlayLaunchQueuePolicy = {
14
+ triggerSource: PlayLaunchTriggerSource;
15
+ /**
16
+ * Relative ordering within one scheduler queue. This only decides which
17
+ * runnable run gets a newly available worker/sandbox slot; it never
18
+ * preempts a running customer sandbox or bypasses cross-org fairness.
19
+ */
20
+ priority: number;
21
+ /**
22
+ * Absurd's maximum time waiting to be claimed, in seconds. `null` means the
23
+ * accepted launch is allowed to wait durably for capacity.
24
+ */
25
+ maxDelaySeconds: number | null;
26
+ /**
27
+ * Maximum total time an accepted run may wait for a live sandbox slot. This
28
+ * is evaluated by the worker after a claim, where Absurd's `max_delay`
29
+ * cannot help. Zero gives an interactive caller an immediate, typed
30
+ * capacity-full result instead of a stuck watch.
31
+ */
32
+ sandboxCapacityMaxWaitSeconds: number | null;
33
+ };
34
+
35
+ export function shouldTerminalizeSandboxCapacityRejection(input: {
36
+ triggerSource?: PlayLaunchTriggerSource | null;
37
+ submittedAtMs?: number | null;
38
+ nowMs?: number;
39
+ }): boolean {
40
+ const policy = resolvePlayLaunchQueuePolicy(input.triggerSource);
41
+ const maxWaitSeconds = policy.sandboxCapacityMaxWaitSeconds;
42
+ if (maxWaitSeconds === 0) return true;
43
+ if (maxWaitSeconds === null) return false;
44
+ const submittedAtMs = input.submittedAtMs;
45
+ if (
46
+ typeof submittedAtMs !== 'number' ||
47
+ !Number.isFinite(submittedAtMs) ||
48
+ submittedAtMs <= 0
49
+ ) {
50
+ // Old launch rows did not persist submit time. Preserve their historical
51
+ // durable behavior rather than making an age guess at execution time.
52
+ return false;
53
+ }
54
+ return (input.nowMs ?? Date.now()) >= submittedAtMs + maxWaitSeconds * 1_000;
55
+ }
56
+
57
+ /**
58
+ * Resolve the single queue-admission policy for every top-level play launch.
59
+ *
60
+ * Missing source is deliberately manual/API for backwards-compatible direct
61
+ * callers of `startPlayRunExecution`; webhook and cron callers must opt into
62
+ * their durable trigger source explicitly.
63
+ */
64
+ export function resolvePlayLaunchQueuePolicy(
65
+ triggerSource?: PlayLaunchTriggerSource | null,
66
+ ): PlayLaunchQueuePolicy {
67
+ switch (triggerSource ?? 'api') {
68
+ case 'api':
69
+ return {
70
+ triggerSource: 'api',
71
+ // A person waiting in the CLI/UI should get the next slot in their
72
+ // own organization rather than sitting behind that org's automation.
73
+ // The bounded deadline gives the caller a typed terminal outcome
74
+ // instead of an indefinite watch.
75
+ priority: 100,
76
+ maxDelaySeconds: 10,
77
+ sandboxCapacityMaxWaitSeconds: 0,
78
+ };
79
+ case 'webhook':
80
+ return {
81
+ triggerSource: 'webhook',
82
+ priority: 0,
83
+ // A 202 webhook response is a durable delivery promise. Capacity is
84
+ // not a delivery failure: retain it until it executes, is explicitly
85
+ // cancelled, or an operator terminalizes it. Interactive API launches
86
+ // remain separately bounded above.
87
+ maxDelaySeconds: null,
88
+ sandboxCapacityMaxWaitSeconds: null,
89
+ };
90
+ case 'cron':
91
+ return {
92
+ triggerSource: 'cron',
93
+ priority: -10,
94
+ maxDelaySeconds: 30 * 60,
95
+ sandboxCapacityMaxWaitSeconds: 30 * 60,
96
+ };
97
+ case 'sql_listener':
98
+ return {
99
+ triggerSource: 'sql_listener',
100
+ priority: -10,
101
+ maxDelaySeconds: 30 * 60,
102
+ sandboxCapacityMaxWaitSeconds: 30 * 60,
103
+ };
104
+ case 'async_child':
105
+ return {
106
+ triggerSource: 'async_child',
107
+ priority: 0,
108
+ maxDelaySeconds: null,
109
+ sandboxCapacityMaxWaitSeconds: null,
110
+ };
111
+ }
112
+ }
@@ -10,6 +10,14 @@ export function cloneMapFrame(frame: MapExecutionFrame): MapExecutionFrame {
10
10
  ...frame,
11
11
  completedRowKeys: [...frame.completedRowKeys],
12
12
  pendingRowKeys: [...frame.pendingRowKeys],
13
+ ...(frame.suspendedInputRows
14
+ ? {
15
+ suspendedInputRows: frame.suspendedInputRows.map((row) => ({
16
+ inputIndex: row.inputIndex,
17
+ data: { ...row.data },
18
+ })),
19
+ }
20
+ : {}),
13
21
  };
14
22
  }
15
23
 
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Structured per-run perf trace for play execution.
3
+ *
4
+ * Each call emits a single line JSON object prefixed with `[perf-trace]` to
5
+ * stdout. Server-side callers (Next.js dev server) ALSO append the same JSON
6
+ * object to `logs/perf-<runId>.jsonl` so post-mortem aggregation works even
7
+ * when stdout has been multiplexed across many runs.
8
+ *
9
+ * This is intentionally additive — it does NOT replace the existing
10
+ * `[perf][plays.start_run]` console.info lines that other tooling parses.
11
+ *
12
+ * Benchmark trace map:
13
+ * - `apps/deepline-api/src/app/api/v2/plays/run/route.ts` records start-route and watch/terminal
14
+ * spans, including the old "terminal wait" bucket.
15
+ * - `packages/play-runtime/scheduler-backends/*` and
16
+ * the submit path records scheduler submit
17
+ * and workflow-create spans.
18
+ * - the runner records execution,
19
+ * dataset, ledger, billing, and terminalization spans.
20
+ * - `scripts/analyze-v2-sdk-cli-benchmark.ts` reads these from local
21
+ * `logs/perf-*.jsonl`, dev logs, or exported Axiom JSONL.
22
+ *
23
+ * Design constraints:
24
+ * - Workerd-safe (Cloudflare Workers can't touch the filesystem). When
25
+ * `appendFileSync` isn't available we degrade silently to stdout-only.
26
+ * - No new dependencies; just `node:fs`.
27
+ * - Loud failures are NOT desired here — perf instrumentation must never
28
+ * break a real play run. We swallow FS errors, but never silently drop
29
+ * the stdout copy.
30
+ */
31
+
32
+ import {
33
+ createTelemetry,
34
+ type TelemetryEvent,
35
+ type TelemetryFields,
36
+ } from '../observability/telemetry';
37
+
38
+ export type PerfTraceEvent = {
39
+ ts?: number;
40
+ source: 'server' | 'coordinator' | 'dynamic_worker' | 'runner';
41
+ runId: string;
42
+ orgId?: string | null;
43
+ phase: string;
44
+ ms: number;
45
+ playName?: string;
46
+ graphHash?: string | null;
47
+ workerUrl?: string | null;
48
+ bytes?: number;
49
+ extra?: Record<string, unknown>;
50
+ };
51
+
52
+ const PERF_TRACE_PREFIX = '[perf-trace]';
53
+
54
+ let cachedAppendFile: ((path: string, data: string) => void) | null | undefined;
55
+
56
+ function getAppendFile(): ((path: string, data: string) => void) | null {
57
+ if (cachedAppendFile !== undefined) return cachedAppendFile;
58
+ try {
59
+ // Avoid bundling this into edge runtime call paths. Synchronous CJS
60
+ // require() is the right tool here: workerd will throw on load and we
61
+ // fall through to the null branch, which keeps the stdout-only path.
62
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
63
+ const fs = require('node:fs') as typeof import('node:fs');
64
+ cachedAppendFile = (path: string, data: string) => {
65
+ try {
66
+ fs.mkdirSync('logs', { recursive: true });
67
+ fs.appendFileSync(path, data);
68
+ } catch {
69
+ // Filesystem unavailable (workerd / read-only FS). Drop the sidecar
70
+ // copy; the stdout JSON line is still emitted by recordPerfTrace.
71
+ }
72
+ };
73
+ } catch {
74
+ cachedAppendFile = null;
75
+ }
76
+ return cachedAppendFile;
77
+ }
78
+
79
+ const perfTraceTelemetry = createTelemetry({
80
+ service: 'play-runtime',
81
+ component: 'perf-trace',
82
+ adapter: {
83
+ emit(event: TelemetryEvent) {
84
+ const json = JSON.stringify(event);
85
+ console.log(`${PERF_TRACE_PREFIX} ${json}`);
86
+ if (event.source === 'server' && typeof event.runId === 'string') {
87
+ getAppendFile()?.(
88
+ `logs/perf-${sanitizeRunIdForFilename(event.runId)}.jsonl`,
89
+ `${json}\n`,
90
+ );
91
+ }
92
+ },
93
+ },
94
+ });
95
+
96
+ function perfTraceFields(event: PerfTraceEvent): TelemetryFields {
97
+ return {
98
+ ts: typeof event.ts === 'number' ? event.ts : Date.now(),
99
+ source: event.source,
100
+ phase: event.phase,
101
+ ms: event.ms,
102
+ graphHash: event.graphHash ?? null,
103
+ workerUrl: event.workerUrl ?? null,
104
+ bytes: event.bytes,
105
+ ...(event.extra ?? {}),
106
+ };
107
+ }
108
+
109
+ export function recordPerfTrace(event: PerfTraceEvent): void {
110
+ const { runId, phase } = event;
111
+ if (!runId || !phase) return;
112
+ const orgId =
113
+ event.orgId ??
114
+ (typeof event.extra?.orgId === 'string' ? event.extra.orgId : null);
115
+ void perfTraceTelemetry
116
+ .child({
117
+ component: event.source,
118
+ context: { runId, orgId, playName: event.playName ?? null },
119
+ })
120
+ .info(phase, perfTraceFields(event), { tag: PERF_TRACE_PREFIX });
121
+ }
122
+
123
+ function sanitizeRunIdForFilename(runId: string): string {
124
+ return runId.replace(/[^a-zA-Z0-9._-]+/g, '_');
125
+ }
126
+
127
+ export const PERF_TRACE_LINE_PREFIX = PERF_TRACE_PREFIX;
@@ -24,6 +24,8 @@ import {
24
24
  */
25
25
  export type PlayArtifactRuntimeContract = Readonly<{
26
26
  semantics: PlayRuntimeSemantics;
27
+ /** Additive artifact fact; missing persisted fields resolve to `park`. */
28
+ slackHitlTimeoutOutcome: 'park' | 'error';
27
29
  toolErrorSchemaVersion: ToolExecutionErrorSchemaVersion;
28
30
  toolResponseContract: ToolResponseContract;
29
31
  toolResponseReceiptRevision?: string;
@@ -31,6 +33,7 @@ export type PlayArtifactRuntimeContract = Readonly<{
31
33
 
32
34
  export type PlayArtifactRuntimeContractInput = {
33
35
  authoringContractEdition?: PlayAuthoringContractEdition | null;
36
+ slackHitlTimeoutOutcome?: 'park' | 'error' | null;
34
37
  toolResponseContract?: ToolResponseContract | null;
35
38
  toolResponseReceiptRevision?: string | null;
36
39
  };
@@ -50,6 +53,8 @@ export function resolvePlayArtifactRuntimeContract(
50
53
  semantics: resolvePlayRuntimeSemantics(
51
54
  input.authoringContractEdition ?? PLAY_AUTHORING_CONTRACT_EDITION,
52
55
  ),
56
+ slackHitlTimeoutOutcome:
57
+ input.slackHitlTimeoutOutcome === 'error' ? 'error' : 'park',
53
58
  // Historic string-only failures are deliberately upgraded at the runtime
54
59
  // boundary. Rehydrating an old artifact must not regress a structured
55
60
  // durable failure into an unbranchable string.
@@ -41,6 +41,7 @@ export type PlayRunRecoveryReason =
41
41
  | 'modal_circuit_open_before_execution'
42
42
  | 'modal_sandbox_unavailable_before_execution'
43
43
  | 'modal_runner_start_failed_before_execution'
44
+ | 'daytona_sandbox_transition_pending_before_execution'
44
45
  | 'runtime_initialization_transport_before_execution'
45
46
  | 'runtime_traffic_hold_before_execution'
46
47
  | 'runtime_traffic_throttled_before_execution';
@@ -209,6 +210,27 @@ export function recoveryForRuntimeTrafficPolicy(input: {
209
210
  });
210
211
  }
211
212
 
213
+ /**
214
+ * Daytona acknowledged a named sandbox but has not finished creating it.
215
+ * Resume that durable provider operation after a bounded defer; another
216
+ * provider or a fresh Daytona create could execute the same Play twice.
217
+ */
218
+ export function recoveryForDaytonaSandboxTransitionPending(
219
+ error: unknown,
220
+ ): PlayRunRecoveryError {
221
+ return new PlayRunRecoveryError({
222
+ decision: {
223
+ stage: 'pre_code',
224
+ action: 'defer',
225
+ reason: 'daytona_sandbox_transition_pending_before_execution',
226
+ dependency: 'runtime',
227
+ },
228
+ message:
229
+ 'Daytona is still finishing a named sandbox create before customer execution began.',
230
+ cause: error,
231
+ });
232
+ }
233
+
212
234
  /**
213
235
  * This is constructed only by the detached-runner readiness check. That
214
236
  * check has not parked the runner or observed scheduler liveness, so it is a
@@ -241,7 +263,8 @@ export function recoveryForRuntimeInitializationTransportFailure(
241
263
  | 'runtime_postgres_connect'
242
264
  | 'runtime_api_transport'
243
265
  | 'runtime_receipt_gateway_transport'
244
- | 'daytona_public_status',
266
+ | 'daytona_public_status'
267
+ | 'daytona_runner_startup_transport',
245
268
  ): PlayRunRecoveryError {
246
269
  return new PlayRunRecoveryError({
247
270
  decision: {
@@ -0,0 +1,56 @@
1
+ import type { PlaySchedulerSubmitInput } from '../../scheduler-backend';
2
+
3
+ /**
4
+ * A fully prepared Play Run is ready to cross the one durable admission
5
+ * boundary. Construction, artifact validation, token minting, and provider
6
+ * resolution are intentionally finished before this value exists.
7
+ */
8
+ export type PlayRunAdmissionInput = {
9
+ launch: PlaySchedulerSubmitInput;
10
+ queueName: string;
11
+ recoverExistingTask?: boolean;
12
+ };
13
+
14
+ /** The durable facts returned by one atomic launch-row + queue-task commit. */
15
+ export type PlayRunAdmissionReceipt = {
16
+ taskId: string | null;
17
+ runCreated: boolean;
18
+ taskCreated: boolean;
19
+ taskRecoveryRequired: boolean;
20
+ };
21
+
22
+ /**
23
+ * The outcome makes the three useful cases explicit to callers. A retry may
24
+ * either observe its original queue task or repair the historical row-first
25
+ * crash window; it never creates a second Play Run.
26
+ */
27
+ export type PlayRunAdmissionOutcome =
28
+ | {
29
+ kind: 'created';
30
+ receipt: PlayRunAdmissionReceipt;
31
+ }
32
+ | {
33
+ kind: 'recovered';
34
+ receipt: PlayRunAdmissionReceipt;
35
+ }
36
+ | {
37
+ kind: 'replayed';
38
+ receipt: PlayRunAdmissionReceipt;
39
+ };
40
+
41
+ export type PlayRunAdmissionJob = {
42
+ admit(input: PlayRunAdmissionInput): Promise<PlayRunAdmissionOutcome>;
43
+ };
44
+
45
+ /** A stable, machine-readable rejection for a reused run id with new intent. */
46
+ export class PlayRunLaunchConflictError extends Error {
47
+ readonly code = 'PLAY_RUN_LAUNCH_CONFLICT';
48
+
49
+ constructor(runId: string, options?: { cause?: unknown }) {
50
+ super(
51
+ `Play run "${runId}" already exists with a different launch.`,
52
+ options,
53
+ );
54
+ this.name = 'PlayRunLaunchConflictError';
55
+ }
56
+ }
@@ -0,0 +1,13 @@
1
+ export { createPlayRunAdmissionJob } from '../../play-runs/admission/job';
2
+ export { createPostgresPlayRunAdmissionPorts } from '../../play-runs/admission/postgres-adapter';
3
+ export { PlayRunLaunchConflictError } from '../../play-runs/admission/contracts';
4
+ export type {
5
+ PlayRunAdmissionInput,
6
+ PlayRunAdmissionJob,
7
+ PlayRunAdmissionOutcome,
8
+ PlayRunAdmissionReceipt,
9
+ } from '../../play-runs/admission/contracts';
10
+ export type {
11
+ AtomicPlayRunQueueSubmitter,
12
+ PlayRunAdmissionPorts,
13
+ } from '../../play-runs/admission/ports';
@@ -0,0 +1,41 @@
1
+ import {
2
+ type PlayRunAdmissionInput,
3
+ type PlayRunAdmissionJob,
4
+ type PlayRunAdmissionOutcome,
5
+ } from '../../play-runs/admission/contracts';
6
+ import type { PlayRunAdmissionPorts } from '../../play-runs/admission/ports';
7
+
8
+ /**
9
+ * Play Run Admission owns the idempotency law for the launch boundary:
10
+ *
11
+ * exact launch retry -> original task
12
+ * existing queued row without task -> repair that row
13
+ * same run id + changed launch -> reject
14
+ *
15
+ * The storage Adapter enforces identity and atomicity. This job exposes the
16
+ * result without leaking SQL rows, scheduler queues, or task engine details.
17
+ */
18
+ export function createPlayRunAdmissionJob(
19
+ ports: PlayRunAdmissionPorts,
20
+ ): PlayRunAdmissionJob {
21
+ return {
22
+ async admit(
23
+ input: PlayRunAdmissionInput,
24
+ ): Promise<PlayRunAdmissionOutcome> {
25
+ validate(input);
26
+ const receipt = await ports.atomicQueueSubmitter.submit(input);
27
+ if (receipt.runCreated) return { kind: 'created', receipt };
28
+ if (receipt.taskCreated) return { kind: 'recovered', receipt };
29
+ return { kind: 'replayed', receipt };
30
+ },
31
+ };
32
+ }
33
+
34
+ function validate(input: PlayRunAdmissionInput): void {
35
+ if (!input.launch.runId.trim()) {
36
+ throw new Error('Play Run Admission requires a non-empty run id.');
37
+ }
38
+ if (!input.queueName.trim()) {
39
+ throw new Error('Play Run Admission requires a non-empty queue name.');
40
+ }
41
+ }
@@ -0,0 +1,17 @@
1
+ import type {
2
+ PlayRunAdmissionInput,
3
+ PlayRunAdmissionReceipt,
4
+ } from '../../play-runs/admission/contracts';
5
+
6
+ /**
7
+ * This port is deliberately one operation. Persisting a run and enqueueing
8
+ * it separately creates an unrepairable ambiguity: either can succeed after a
9
+ * lost reply. The implementation must commit both facts atomically.
10
+ */
11
+ export type AtomicPlayRunQueueSubmitter = {
12
+ submit(input: PlayRunAdmissionInput): Promise<PlayRunAdmissionReceipt>;
13
+ };
14
+
15
+ export type PlayRunAdmissionPorts = {
16
+ atomicQueueSubmitter: AtomicPlayRunQueueSubmitter;
17
+ };
@@ -0,0 +1,54 @@
1
+ import {
2
+ submitPostgresAbsurdPlayRun,
3
+ type PostgresSchedulerQueryClient,
4
+ } from '../../scheduler-backends/postgres';
5
+ import {
6
+ PlayRunLaunchConflictError,
7
+ type PlayRunAdmissionInput,
8
+ type PlayRunAdmissionReceipt,
9
+ } from '../../play-runs/admission/contracts';
10
+ import type { PlayRunAdmissionPorts } from '../../play-runs/admission/ports';
11
+
12
+ /**
13
+ * PostgreSQL/Absurd implementation of the admission seam. The delegated
14
+ * statement persists `runs` and invokes `absurd.spawn_task` in one data-
15
+ * modifying CTE; no caller can observe a persisted runnable Play Run without
16
+ * its corresponding queue task.
17
+ */
18
+ export function createPostgresPlayRunAdmissionPorts(input: {
19
+ client: PostgresSchedulerQueryClient;
20
+ schema?: string;
21
+ }): PlayRunAdmissionPorts {
22
+ const options = input.schema ? { schema: input.schema } : undefined;
23
+ return {
24
+ atomicQueueSubmitter: {
25
+ async submit(
26
+ admission: PlayRunAdmissionInput,
27
+ ): Promise<PlayRunAdmissionReceipt> {
28
+ try {
29
+ return await submitPostgresAbsurdPlayRun(
30
+ input.client,
31
+ admission.launch,
32
+ options,
33
+ admission.queueName,
34
+ admission.recoverExistingTask === true,
35
+ );
36
+ } catch (error) {
37
+ if (isLaunchConflict(error)) {
38
+ throw new PlayRunLaunchConflictError(admission.launch.runId, {
39
+ cause: error,
40
+ });
41
+ }
42
+ throw error;
43
+ }
44
+ },
45
+ },
46
+ };
47
+ }
48
+
49
+ function isLaunchConflict(error: unknown): boolean {
50
+ return (
51
+ error instanceof Error &&
52
+ /already exists with a different launch/i.test(error.message)
53
+ );
54
+ }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Play Run Attempt is the controller for one fenced execution leg.
3
+ *
4
+ * It deliberately does not know how a sandbox is created, how a runner is
5
+ * started, or how a terminal transaction is committed. Its only policy is
6
+ * the retry boundary: work known not to have crossed into user/provider code
7
+ * may be deferred; once that boundary may have been crossed, this job never
8
+ * asks Sandbox Runs to execute again.
9
+ */
10
+
11
+ /** The already-persisted run details required by this leg. */
12
+ export type PlayRunAttemptLaunch = {
13
+ runId: string;
14
+ /** Opaque to the attempt job; consumed by its execution implementation. */
15
+ launch: unknown;
16
+ };
17
+
18
+ import type { PlayExecutionSuspension } from '../../suspension';
19
+ import type { PlayRunRecoveryDecision } from '../../play-run-recovery-policy';
20
+
21
+ /** A scheduler fence granted to exactly one execution leg. */
22
+ export type PlayRunAttemptClaim = {
23
+ runId: string;
24
+ number: number;
25
+ /** Opaque authority used by scheduler/resource/terminal Adapters. */
26
+ fenceId: string;
27
+ checkpoint: unknown;
28
+ /**
29
+ * A detached runner keeps its original attempt-scoped executor token. A
30
+ * heartbeat wake must therefore reuse this claim rather than minting a
31
+ * successor that would fence its still-live runner out of heartbeats and
32
+ * terminal delivery.
33
+ */
34
+ origin: 'fresh' | 'detached_runner_resume';
35
+ /** Present only for an origin that resumed a detached runner. */
36
+ suspension?: Extract<PlayExecutionSuspension, { kind: 'detached_runner' }>;
37
+ };
38
+
39
+ /** A durable waiting/resumed lifecycle fact ready for read-model projection. */
40
+ export type PlayRunAttemptLifecycle = {
41
+ runId: string;
42
+ eventId: string;
43
+ };
44
+
45
+ /** Durable truth read before a new attempt may be claimed. */
46
+ export type PlayRunAttemptTerminal = {
47
+ status: 'completed' | 'failed' | 'cancelled';
48
+ output?: unknown;
49
+ error?: string;
50
+ };
51
+
52
+ export type PlayRunAttemptInput = {
53
+ run: PlayRunAttemptLaunch;
54
+ };
55
+
56
+ /**
57
+ * Sandbox Runs reports whether user/provider code was crossed. The payload
58
+ * is opaque here because only the terminal job owns interpretation and
59
+ * persistence of a runner result.
60
+ */
61
+ /**
62
+ * Evidence that no customer or provider code has begun. It is intentionally
63
+ * distinct from an ordinary thrown error: only these outcomes may put a run
64
+ * back into durable admission.
65
+ */
66
+ export type PlayRunAttemptPreCodeDeferral =
67
+ | { kind: 'capacity'; reason: string }
68
+ | {
69
+ kind: 'recovery';
70
+ reason: string;
71
+ decision: PlayRunRecoveryDecision;
72
+ };
73
+
74
+ /**
75
+ * The runner-to-terminal transport envelope. Attempt never interprets this
76
+ * result; Terminal owns first-write-wins persistence and result shaping.
77
+ */
78
+ export type PlayRunAttemptTerminalEnvelope =
79
+ | { status: 'completed'; output: unknown }
80
+ | { status: 'failed'; error: string };
81
+
82
+ export type PlayRunAttemptSandboxOutcome =
83
+ | { kind: 'pre_code_deferred'; deferral: PlayRunAttemptPreCodeDeferral }
84
+ | {
85
+ kind: 'suspended';
86
+ checkpoint: unknown;
87
+ suspension: PlayExecutionSuspension;
88
+ }
89
+ | { kind: 'terminal'; result: PlayRunAttemptTerminalEnvelope }
90
+ | { kind: 'post_code_unknown'; reason: string };
91
+
92
+ export type PlayRunAttemptTerminalHandoff =
93
+ | { kind: 'committed' }
94
+ | { kind: 'already_terminal' }
95
+ | { kind: 'fence_lost' };
96
+
97
+ /** Outcomes visible to the worker Adapter after one execution leg. */
98
+ export type PlayRunAttemptOutcome =
99
+ | { kind: 'already_terminal'; terminal: PlayRunAttemptTerminal }
100
+ | { kind: 'claim_rejected' }
101
+ | { kind: 'pre_code_deferred'; deferral: PlayRunAttemptPreCodeDeferral }
102
+ | {
103
+ kind: 'parked';
104
+ checkpoint: unknown;
105
+ suspension: PlayExecutionSuspension;
106
+ }
107
+ | { kind: 'post_code_unknown'; reason: string }
108
+ | { kind: 'terminal_committed' }
109
+ | { kind: 'terminal_already_committed' }
110
+ | { kind: 'terminal_fence_lost' };
111
+
112
+ export type PlayRunAttemptJob = {
113
+ execute(input: PlayRunAttemptInput): Promise<PlayRunAttemptOutcome>;
114
+ };