@sema-agent/server 7.148.0 → 7.150.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 (360) hide show
  1. package/MIGRATION.md +551 -9
  2. package/README.md +17 -2
  3. package/README.zh-CN.md +5 -1
  4. package/USAGE.md +126 -68
  5. package/dist/adoption/wire.d.ts +3 -3
  6. package/dist/approval-card.d.ts +33 -33
  7. package/dist/approval-gate-currency.d.ts +1 -1
  8. package/dist/approval-leg-origin.d.ts +33 -0
  9. package/dist/approval-leg-origin.js +4 -0
  10. package/dist/audit.d.ts +1 -1
  11. package/dist/audit.js +2 -2
  12. package/dist/auth-bridge.d.ts +9 -1
  13. package/dist/auth-bridge.js +4 -4
  14. package/dist/auth-keys.d.ts +10 -1
  15. package/dist/auth-keys.js +8 -0
  16. package/dist/background-session-reap.d.ts +1 -1
  17. package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
  18. package/dist/boot/deferred-sandbox-path-env.js +1 -2
  19. package/dist/boot/execution-env.js +10 -11
  20. package/dist/boot/execution-lane.d.ts +6 -4
  21. package/dist/boot/execution-lane.js +3 -1
  22. package/dist/boot/org-delivery.d.ts +3 -2
  23. package/dist/boot/parked-revive-gate.d.ts +5 -5
  24. package/dist/boot/parked-revive-gate.js +2 -3
  25. package/dist/boot/resolve-spec.d.ts +4 -5
  26. package/dist/boot/resolve-spec.js +66 -28
  27. package/dist/boot/retention-lane.d.ts +1 -1
  28. package/dist/boot/runner-deps.js +3 -1
  29. package/dist/boot/session-faces.js +21 -21
  30. package/dist/boot/stage-01-config.d.ts +1 -0
  31. package/dist/boot/stage-01-config.js +4 -3
  32. package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
  33. package/dist/boot/stage-02-web-admin-pull.js +10 -2
  34. package/dist/boot/stage-03-store-backend.d.ts +1 -0
  35. package/dist/boot/stage-03-store-backend.js +4 -4
  36. package/dist/boot/stage-04-stores.d.ts +1 -0
  37. package/dist/boot/stage-05-execution-env.d.ts +1 -0
  38. package/dist/boot/stage-06-runners.d.ts +2 -1
  39. package/dist/boot/stage-06-runners.js +1 -2
  40. package/dist/boot/stage-07-capability-layer.d.ts +2 -1
  41. package/dist/boot/stage-07-capability-layer.js +1 -1
  42. package/dist/boot/stage-08-reapers.d.ts +2 -1
  43. package/dist/boot/stage-09-leader.d.ts +2 -1
  44. package/dist/boot/stage-10-http-server.d.ts +35 -2
  45. package/dist/boot/stage-10-http-server.js +9 -4
  46. package/dist/boot/stores.d.ts +3 -0
  47. package/dist/boot/stores.js +22 -19
  48. package/dist/boot/web-admin.d.ts +1 -1
  49. package/dist/capabilities/tool-defer.d.ts +1 -1
  50. package/dist/capability-facts.d.ts +70 -60
  51. package/dist/capability-facts.js +45 -49
  52. package/dist/card-settle-stored-scope.d.ts +56 -0
  53. package/dist/card-settle-stored-scope.js +27 -0
  54. package/dist/card-void.d.ts +7 -12
  55. package/dist/card-void.js +2 -7
  56. package/dist/config-catalog.d.ts +12 -0
  57. package/dist/config-catalog.js +37 -33
  58. package/dist/config-invariants.d.ts +5 -4
  59. package/dist/config-invariants.js +4 -4
  60. package/dist/config-types.d.ts +49 -16
  61. package/dist/config.d.ts +6 -5
  62. package/dist/config.js +35 -24
  63. package/dist/context-window-notice.d.ts +31 -0
  64. package/dist/context-window-notice.js +28 -0
  65. package/dist/deployment-governance.d.ts +7 -28
  66. package/dist/deployment-governance.js +1 -14
  67. package/dist/deployment-shape.d.ts +20 -11
  68. package/dist/deployment-shape.js +1 -0
  69. package/dist/device-ws-hub.d.ts +1 -0
  70. package/dist/device-ws-hub.js +64 -28
  71. package/dist/device-ws-protocol.d.ts +20 -6
  72. package/dist/device-ws-protocol.js +9 -2
  73. package/dist/engine-identity.d.ts +7 -1
  74. package/dist/engine-identity.js +5 -0
  75. package/dist/env-name-allowlist-knobs.d.ts +6 -5
  76. package/dist/env-name-allowlist-knobs.js +5 -0
  77. package/dist/execution-lane-caps.d.ts +20 -5
  78. package/dist/execution-lane-caps.js +18 -4
  79. package/dist/field-conflict.d.ts +2 -2
  80. package/dist/fleet/engine-signal.d.ts +14 -1
  81. package/dist/fleet/engine-signal.js +5 -1
  82. package/dist/fleet/fleet-reconciler.d.ts +1 -1
  83. package/dist/fleet/serving-lease.d.ts +18 -3
  84. package/dist/fleet/serving-lease.js +81 -35
  85. package/dist/fleet-client.d.ts +13 -11
  86. package/dist/fleet-client.js +53 -33
  87. package/dist/history-anchor.js +1 -1
  88. package/dist/hitl-delivery.d.ts +1 -3
  89. package/dist/hitl-delivery.js +1 -1
  90. package/dist/hooks/command-spawn.d.ts +7 -2
  91. package/dist/hooks/command-spawn.js +13 -6
  92. package/dist/hooks/hook-runner.d.ts +5 -0
  93. package/dist/hooks/hook-runner.js +11 -7
  94. package/dist/http/active-run-conflict.d.ts +3 -7
  95. package/dist/http/active-run-conflict.js +2 -2
  96. package/dist/http/admission.js +5 -5
  97. package/dist/http/approval-sweeps.js +5 -3
  98. package/dist/http/caller-trust.d.ts +2 -2
  99. package/dist/http/caller-trust.js +3 -3
  100. package/dist/http/checkpoint-ctx.d.ts +18 -63
  101. package/dist/http/checkpoint-ctx.js +1 -24
  102. package/dist/http/claim-heartbeat.d.ts +6 -6
  103. package/dist/http/claim-heartbeat.js +6 -6
  104. package/dist/http/claimed-run.d.ts +16 -9
  105. package/dist/http/claimed-run.js +8 -0
  106. package/dist/http/dispatch.js +7 -5
  107. package/dist/http/durable-run-leg.d.ts +8 -1
  108. package/dist/http/durable-run-leg.js +34 -15
  109. package/dist/http/execution-context.d.ts +115 -14
  110. package/dist/http/execution-context.js +130 -40
  111. package/dist/http/owner-access.d.ts +246 -21
  112. package/dist/http/owner-access.js +186 -8
  113. package/dist/http/principal-gate.d.ts +18 -11
  114. package/dist/http/principal-gate.js +3 -1
  115. package/dist/http/readiness.d.ts +4 -2
  116. package/dist/http/resume-ctx-read.d.ts +14 -3
  117. package/dist/http/resume-ctx-read.js +24 -3
  118. package/dist/http/resume-legs.d.ts +35 -3
  119. package/dist/http/resume-legs.js +262 -106
  120. package/dist/http/route-ctx.d.ts +29 -11
  121. package/dist/http/routes/a2a-serve.js +17 -14
  122. package/dist/http/routes/approvals-assistant.d.ts +3 -2
  123. package/dist/http/routes/approvals-assistant.js +11 -11
  124. package/dist/http/routes/capabilities.js +5 -4
  125. package/dist/http/routes/config-catalog.d.ts +1 -1
  126. package/dist/http/routes/diagnostics.d.ts +3 -1
  127. package/dist/http/routes/diagnostics.js +30 -5
  128. package/dist/http/routes/mcp-reconnect.js +2 -2
  129. package/dist/http/routes/memory-origin.d.ts +1 -1
  130. package/dist/http/routes/notify-wake.js +2 -3
  131. package/dist/http/routes/principal-inbox.d.ts +3 -1
  132. package/dist/http/routes/principal-inbox.js +3 -2
  133. package/dist/http/routes/projects.d.ts +1 -0
  134. package/dist/http/routes/projects.js +5 -3
  135. package/dist/http/routes/retention-ops.d.ts +1 -1
  136. package/dist/http/routes/run-permission-mode.d.ts +1 -1
  137. package/dist/http/routes/run-permission-mode.js +2 -2
  138. package/dist/http/routes/runs.d.ts +1 -1
  139. package/dist/http/routes/runs.js +33 -37
  140. package/dist/http/routes/session-memory-sync.js +4 -5
  141. package/dist/http/routes/session-sync.d.ts +24 -5
  142. package/dist/http/routes/session-sync.js +45 -37
  143. package/dist/http/routes/sessions-list.d.ts +1 -1
  144. package/dist/http/routes/sessions.d.ts +1 -1
  145. package/dist/http/routes/sessions.js +18 -44
  146. package/dist/http/routes/tasks.js +136 -101
  147. package/dist/http/routes/trace-usage.js +14 -14
  148. package/dist/http/routes/workflows.d.ts +1 -0
  149. package/dist/http/routes/workflows.js +20 -38
  150. package/dist/http/server.d.ts +12 -9
  151. package/dist/http/server.js +35 -6
  152. package/dist/http/stored-body-replay.d.ts +3 -24
  153. package/dist/http/stored-body-replay.js +2 -12
  154. package/dist/http/submit-ctx.d.ts +2 -2
  155. package/dist/http/submit-ctx.js +5 -5
  156. package/dist/http/submit-replay.d.ts +15 -2
  157. package/dist/http/submit-replay.js +10 -4
  158. package/dist/http/wire-types.d.ts +6 -3
  159. package/dist/index.d.ts +3 -1
  160. package/dist/index.js +1 -0
  161. package/dist/leader/endpoint.js +9 -8
  162. package/dist/leg-facts.d.ts +13 -2
  163. package/dist/leg-facts.js +2 -0
  164. package/dist/local-store-declaration.d.ts +54 -0
  165. package/dist/local-store-declaration.js +59 -0
  166. package/dist/mcp-assertion-header.d.ts +1 -1
  167. package/dist/mcp-assertion-header.js +1 -1
  168. package/dist/mcp-authorization-face.d.ts +18 -14
  169. package/dist/mcp-authorization-face.js +3 -2
  170. package/dist/memory-project-layer.js +1 -1
  171. package/dist/memory-scope.d.ts +4 -4
  172. package/dist/memory-scope.js +4 -4
  173. package/dist/memory-store-refusal.d.ts +1 -1
  174. package/dist/memory-sync-client.js +2 -2
  175. package/dist/model-context-window.d.ts +50 -11
  176. package/dist/model-context-window.js +20 -1
  177. package/dist/model-entry-refusal.d.ts +5 -4
  178. package/dist/model-entry-refusal.js +17 -3
  179. package/dist/model-reach-scope.d.ts +2 -1
  180. package/dist/observability/corrupt-read-seat.d.ts +1 -1
  181. package/dist/observability/fail-open.d.ts +19 -7
  182. package/dist/observability/fail-open.js +19 -7
  183. package/dist/observability/logger.d.ts +7 -0
  184. package/dist/observability/logger.js +3 -1
  185. package/dist/observability/metrics.js +1 -1
  186. package/dist/observability/run-terminal.d.ts +1 -1
  187. package/dist/observability/run-terminal.js +1 -0
  188. package/dist/observability/secret-env-scrub.d.ts +1 -1
  189. package/dist/observability/secret-env-scrub.js +1 -1
  190. package/dist/org-delivery-gate.d.ts +31 -6
  191. package/dist/org-delivery-gate.js +7 -4
  192. package/dist/owner-faces.d.ts +30 -5
  193. package/dist/owner-faces.js +2 -0
  194. package/dist/park-row-commit.d.ts +67 -0
  195. package/dist/park-row-commit.js +76 -0
  196. package/dist/parked-decide.d.ts +9 -7
  197. package/dist/parked-decide.js +25 -6
  198. package/dist/peer-directory.d.ts +1 -1
  199. package/dist/peer-seat.d.ts +1 -1
  200. package/dist/peer-seat.js +52 -59
  201. package/dist/plugins/adoption-log-sql.d.ts +3 -3
  202. package/dist/plugins/adoption-log-sql.js +19 -19
  203. package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
  204. package/dist/plugins/approval-ask-store-sql.js +3 -5
  205. package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
  206. package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
  207. package/dist/plugins/approval-exemption-skill-m46.d.ts +0 -6
  208. package/dist/plugins/approval-exemption-skill-m46.js +6 -10
  209. package/dist/plugins/approval-exemption-store.d.ts +26 -1
  210. package/dist/plugins/approval-exemption-store.js +28 -19
  211. package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -3
  212. package/dist/plugins/ensure-schema-lock-policy.js +75 -9
  213. package/dist/plugins/exec-path-law.d.ts +34 -0
  214. package/dist/plugins/exec-path-law.js +13 -0
  215. package/dist/plugins/file-run-store.d.ts +22 -9
  216. package/dist/plugins/file-run-store.js +51 -23
  217. package/dist/plugins/local-checkpoint-store.d.ts +8 -1
  218. package/dist/plugins/local-checkpoint-store.js +5 -1
  219. package/dist/plugins/local-data-root-admission.d.ts +52 -0
  220. package/dist/plugins/local-data-root-admission.js +100 -0
  221. package/dist/plugins/local-engine-high-water.d.ts +28 -7
  222. package/dist/plugins/local-engine-high-water.js +27 -22
  223. package/dist/plugins/local-session-store.d.ts +134 -49
  224. package/dist/plugins/local-session-store.js +149 -108
  225. package/dist/plugins/memory-run-store.d.ts +14 -9
  226. package/dist/plugins/memory-run-store.js +48 -22
  227. package/dist/plugins/one-time-migration-marker.d.ts +19 -3
  228. package/dist/plugins/one-time-migration-marker.js +7 -1
  229. package/dist/plugins/one-time-migrations.d.ts +110 -59
  230. package/dist/plugins/one-time-migrations.js +224 -136
  231. package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
  232. package/dist/plugins/org-delivery-quota-store.js +29 -14
  233. package/dist/plugins/permission-rule-store-sql.d.ts +1 -1
  234. package/dist/plugins/permission-rule-store-sql.js +5 -9
  235. package/dist/plugins/pg-pool.d.ts +1 -1
  236. package/dist/plugins/pg-pool.js +14 -12
  237. package/dist/plugins/posix-shell-fs.js +4 -2
  238. package/dist/plugins/remote-env-adb.js +3 -2
  239. package/dist/plugins/remote-env-device.d.ts +3 -2
  240. package/dist/plugins/remote-env-device.js +8 -6
  241. package/dist/plugins/remote-env-e2b.d.ts +4 -8
  242. package/dist/plugins/remote-env-e2b.js +21 -15
  243. package/dist/plugins/remote-env-host.d.ts +51 -10
  244. package/dist/plugins/remote-env-host.js +97 -31
  245. package/dist/plugins/remote-env-k8s.js +7 -4
  246. package/dist/plugins/remote-env-local-docker.d.ts +6 -3
  247. package/dist/plugins/remote-env-local-docker.js +11 -25
  248. package/dist/plugins/remote-env-ssh.js +4 -3
  249. package/dist/plugins/remote-shell.d.ts +3 -1
  250. package/dist/plugins/remote-shell.js +3 -3
  251. package/dist/plugins/replica-registration.d.ts +35 -0
  252. package/dist/plugins/replica-registration.js +48 -0
  253. package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
  254. package/dist/plugins/run-store-sql.d.ts +27 -8
  255. package/dist/plugins/run-store-sql.js +46 -18
  256. package/dist/plugins/scenario-prefix-switch-m42.d.ts +8 -12
  257. package/dist/plugins/scenario-prefix-switch-m42.js +9 -6
  258. package/dist/plugins/schema-consistency.d.ts +91 -5
  259. package/dist/plugins/schema-consistency.js +189 -7
  260. package/dist/plugins/schema-drift-sentence.d.ts +6 -5
  261. package/dist/plugins/schema-drift-sentence.js +13 -5
  262. package/dist/plugins/serving-requirement.d.ts +49 -0
  263. package/dist/plugins/serving-requirement.js +53 -0
  264. package/dist/plugins/session-placement.d.ts +5 -4
  265. package/dist/plugins/shell-sentinel-owner-m48.d.ts +22 -0
  266. package/dist/plugins/shell-sentinel-owner-m48.js +6 -0
  267. package/dist/plugins/stop-then-start-sentence.d.ts +55 -0
  268. package/dist/plugins/stop-then-start-sentence.js +51 -0
  269. package/dist/plugins/store-backend.d.ts +23 -9
  270. package/dist/plugins/store-backend.js +58 -24
  271. package/dist/plugins/store-contracts.d.ts +45 -5
  272. package/dist/plugins/store-contracts.js +19 -0
  273. package/dist/plugins/tidb-pool.d.ts +11 -6
  274. package/dist/plugins/tidb-pool.js +22 -12
  275. package/dist/plugins/workspace-custody.d.ts +44 -0
  276. package/dist/plugins/workspace-custody.js +47 -0
  277. package/dist/process-instance.d.ts +3 -0
  278. package/dist/process-instance.js +7 -0
  279. package/dist/project-context.d.ts +66 -0
  280. package/dist/project-context.js +70 -0
  281. package/dist/project-identity.d.ts +8 -7
  282. package/dist/project-identity.js +40 -17
  283. package/dist/project-layer-key.d.ts +13 -2
  284. package/dist/project-layer-key.js +9 -1
  285. package/dist/question.d.ts +9 -21
  286. package/dist/question.js +28 -19
  287. package/dist/read-deny-floor-notice.d.ts +36 -0
  288. package/dist/read-deny-floor-notice.js +40 -0
  289. package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
  290. package/dist/request-declaration-disposition.js +39 -0
  291. package/dist/run-cancel-card.d.ts +28 -0
  292. package/dist/run-cancel-card.js +20 -0
  293. package/dist/run-cancel-context.d.ts +10 -0
  294. package/dist/run-cancel-context.js +1 -0
  295. package/dist/run-local.js +28 -13
  296. package/dist/runs.d.ts +31 -7
  297. package/dist/runs.js +34 -16
  298. package/dist/security.d.ts +3 -3
  299. package/dist/server-secret-env.d.ts +34 -20
  300. package/dist/server-secret-env.js +61 -18
  301. package/dist/session-agent.d.ts +4 -12
  302. package/dist/session-agent.js +0 -6
  303. package/dist/session-children-retire.d.ts +6 -3
  304. package/dist/session-children-retire.js +2 -5
  305. package/dist/session-incarnation.d.ts +18 -4
  306. package/dist/session-incarnation.js +4 -1
  307. package/dist/session-notify-door.d.ts +4 -4
  308. package/dist/session-notify-door.js +5 -6
  309. package/dist/session-rules-seat.d.ts +4 -3
  310. package/dist/session-rules-seat.js +3 -11
  311. package/dist/session-sync.js +3 -3
  312. package/dist/session-workspace.d.ts +3 -3
  313. package/dist/store-admission.d.ts +33 -0
  314. package/dist/store-admission.js +49 -0
  315. package/dist/store-posture.d.ts +5 -0
  316. package/dist/store-posture.js +18 -1
  317. package/dist/stores-sql/checkpoint-store-sql.d.ts +22 -3
  318. package/dist/stores-sql/checkpoint-store-sql.js +109 -23
  319. package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
  320. package/dist/stores-sql/file-history-store-sql.js +3 -5
  321. package/dist/stores-sql/retention-store-sql.d.ts +1 -1
  322. package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
  323. package/dist/stores-sql/tool-result-store-sql.js +4 -6
  324. package/dist/task-a2a.d.ts +3 -8
  325. package/dist/task-a2a.js +25 -27
  326. package/dist/task-cwd.d.ts +27 -10
  327. package/dist/task-cwd.js +3 -0
  328. package/dist/task-mcp.d.ts +3 -3
  329. package/dist/task-mcp.js +1 -1
  330. package/dist/task-settings.d.ts +13 -0
  331. package/dist/task-settings.js +14 -7
  332. package/dist/terminal.d.ts +2 -0
  333. package/dist/terminal.js +21 -6
  334. package/dist/tool-approval.d.ts +50 -41
  335. package/dist/tool-approval.js +96 -73
  336. package/dist/trace/engine-notice-wire.d.ts +38 -21
  337. package/dist/trace/engine-notice-wire.js +25 -4
  338. package/dist/trace/ledger-sink.d.ts +3 -1
  339. package/dist/trace/project.d.ts +8 -5
  340. package/dist/trace/project.js +11 -9
  341. package/dist/trace/projection-table.d.ts +33 -2
  342. package/dist/trace/redact.d.ts +12 -0
  343. package/dist/trace/redact.js +5 -1
  344. package/dist/trace/self-minted-wire.d.ts +268 -56
  345. package/dist/trace/self-minted-wire.js +110 -40
  346. package/dist/trace/tool-card.d.ts +3 -0
  347. package/dist/trace/tool-card.js +24 -0
  348. package/dist/trace/tool-output-media.d.ts +2 -1
  349. package/dist/unattended-permission-mode.d.ts +1 -1
  350. package/dist/web-admin-client/apply-effective.d.ts +1 -1
  351. package/dist/web-admin-client/apply-effective.js +22 -9
  352. package/dist/web-admin-client/effective-keys.d.ts +1 -1
  353. package/dist/web-admin-client/skills-mcp.d.ts +1 -1
  354. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -29
  355. package/docs/error-text-lexicon.json +317 -0
  356. package/package.json +4 -2
  357. package/scripts/embed-minimal.mjs +183 -0
  358. package/wire-changes/server@7.149.0.json +372 -0
  359. package/wire-changes/server@7.150.0.json +335 -0
  360. package/dist/plain-string-record.js +0 -70
@@ -1,7 +1,8 @@
1
1
  import { redactErrorMessage, redactHead, redactTerminalResult } from "../../observability/run-terminal.js";
2
2
  import { runWithVerification, runCascade, taskNotificationDedupKey, uuidv7 } from "@sema-agent/core";
3
3
  import { heldFor } from "../../peer-seat.js";
4
- import { beatRunHeartbeat, graftParkToolCallId, markChildrenStoppedByUserOnAbort, syncRefusalHttpStatus, zeroWorkRefusalFacts, releaseKeyIfZeroWorkRefusal, createPromptCommitReader, settleResumeAnchor, TurnAnchorCapture, HEARTBEAT_MS } from "../../runs.js";
4
+ import { beatRunHeartbeat, graftParkToolCallId, heldParkOf, markChildrenStoppedByUserOnAbort, syncRefusalHttpStatus, zeroWorkRefusalFacts, releaseKeyIfZeroWorkRefusal, createPromptCommitReader, settleResumeAnchor, TurnAnchorCapture, HEARTBEAT_MS } from "../../runs.js";
5
+ import { commitParkRow } from "../../park-row-commit.js";
5
6
  import { atHostBoundary, failureCodeOf, sealResultForExit, outwardPlane } from "../../terminal.js";
6
7
  import { voidVerifierPauseCard } from "../../verifier-pause-card.js";
7
8
  import { withSubject } from "../../observability/principal-context.js";
@@ -20,13 +21,15 @@ import { writeLiveFrame, writeLiveHeartbeat } from "../live-frame.js";
20
21
  import { contextUsageEventData, turnEndEventData, toolStartEventData, toolEndEventData, taskProgressEventData, taskStartedEventData, taskNotificationEventData, compactedEventData, diagnosticsEventData, brainStatusEventData, steeringInjectedEventData, compactionOutcomeEventData, compactionStartedEventData, workspaceChangedEventData, wiringManifestFaceEventData, toolRosterDeltaEventData, toolProgressEventData, toolDisclosureEventData, humanInputEventData, appendModelUsageDelta, attachModelUsage, createPromptManifestSeat, identityFields } from "../../trace/project.js";
21
22
  import { cascadeConfig, fillRunPreviewOnDelivery, runMeta } from "../run-meta.js";
22
23
  import { idemCallerOf, inflightKeyOf, submissionIdemOf } from "../idempotency.js";
23
- import { isReplayedOutcome, replayedOutcome, replayOfExistingRun } from "../submit-replay.js";
24
+ import { answerReplay, isReplayedOutcome, replayedOutcome, replayOfExistingRun } from "../submit-replay.js";
25
+ import { readReplayHit, runFactsOf } from "../owner-access.js";
24
26
  import { httpErrorCode, sendJson, sseHeaders } from "../send.js";
25
27
  import { collectSsePreamble } from "../sse-log.js";
26
28
  import { buildApprovalPreamble } from "../../approval-card.js";
29
+ import { approvalLegOriginOf } from "../../approval-leg-origin.js";
27
30
  import { approvalPreambleReplays, declaredApprovalFrameFamilies, resolveApprovalLeg, resolveStreamApprovalGate } from "../../tool-approval.js";
28
31
  import { buildActiveRunConflict, isActiveRunConflictBody, toDoneFrameResult } from "../active-run-conflict.js";
29
- import { commitExecutionContext } from "../execution-context.js";
32
+ import { SUBMISSION_CLAIM_FACE, commitExecutionContext, faultedAnswerOf } from "../execution-context.js";
30
33
  import { rootSessionAbsentAnswer } from "../execution-context.js";
31
34
  import { recheckClaimBeforeLaunch, startClaimHeartbeat } from "../claim-heartbeat.js";
32
35
  import { timeClaim } from "../claim-latency.js";
@@ -34,7 +37,7 @@ import { commitSessionInheritEnv } from "../session-inherit-env.js";
34
37
  import { headerStr, gatedPerson, gatedSubject, explicitOperatorOk, runIdentityOf } from "../principal-gate.js";
35
38
  import { recoveredSubject } from "../../owner-faces.js";
36
39
  import { recordFailOpen } from "../../observability/fail-open.js";
37
- import { buildSyncSubmitBody } from "../sync-submit-body.js";
40
+ import { buildSyncSubmitBody, syncSubmitBodyOfRow } from "../sync-submit-body.js";
38
41
  import { assertNever } from "../route-ctx.js";
39
42
  import * as facts from "../../capability-facts.js";
40
43
  import { persistSubmissionCtx, SUBMIT_CTX_CLAIM_LOST } from "../submit-ctx.js";
@@ -42,6 +45,7 @@ import { withModelReachScope } from "../../model-reach-scope.js";
42
45
  import { createInstructionSelectionLeg } from "../../instruction-selection.js";
43
46
  import { refusalBody } from "../refusal-body.js";
44
47
  import { heldWorkflowParkDecisions } from "../../parked-decide.js";
48
+ import { compositionLegRoot } from "../../task-cwd.js";
45
49
  import { createSessionWorkspaceRecorder, sessionWorkspaceStoreOf } from "../../session-workspace.js";
46
50
  const DISCONNECT_PARK_GRACE_MS = 10_000;
47
51
  async function mintSubmitExitResult(result, checkpoints) {
@@ -106,12 +110,12 @@ export async function handleTasks(req, res, match, ctx) {
106
110
  const idem = rawIdem ? submissionIdemOf(rawIdem, idemCallerOf(req, ctx), keyedBody) : undefined;
107
111
  const inflightKey = idem ? inflightKeyOf(idem, "sync") : undefined;
108
112
  const cached = inflightKey ? idemCache.peek(inflightKey) : undefined;
109
- const keyedRow = idem && !cached && deps.runStore ? await deps.runStore.getRunByIdem(idem.key) : undefined;
110
- if (keyedRow && deps.runStore) {
111
- const replay = await replayOfExistingRun(keyedRow, { subject: submitter, idem }, "sync", deps, deps.runStore);
112
- if (liveStream && replay.status === 200) {
113
- sseHeaders(res, { "x-task-id": keyedRow.taskId });
114
- writeMetaFrame(res, keyedRow.taskId, keyedRow.sessionId);
113
+ const keyedHit = idem && !cached && deps.runStore ? await readReplayHit(submitter, deps.config, deps.runStore, { idemKey: idem.key }, undefined) : undefined;
114
+ if (keyedHit && deps.runStore) {
115
+ const replay = await answerReplay(keyedHit, { subject: submitter, idem }, "sync", deps.runStore);
116
+ if (liveStream && replay.status === 200 && keyedHit.kind === "visible") {
117
+ sseHeaders(res, { "x-task-id": keyedHit.row.taskId });
118
+ writeMetaFrame(res, keyedHit.row.taskId, keyedHit.row.sessionId);
115
119
  writeLiveFrame(res, doneFrameOfOutcome(replay));
116
120
  res.end();
117
121
  }
@@ -277,8 +281,14 @@ export async function handleTasks(req, res, match, ctx) {
277
281
  const runStreamSubmitLeg = async () => {
278
282
  ranLive = true;
279
283
  let finalResult;
284
+ let heldCard;
285
+ const commitSyncPark = (runStore, runId, word, parkResult, cardToken) => commitParkRow({
286
+ runStore, taskId: runId, word, result: parkResult, card: { token: cardToken, sessionId: prepared.spec.sessionId }, cards: deps.checkpointStore, leg: "sync",
287
+ legId: heldLegOf(durableLegId, runId), staleWindowMs: deps.config.runStaleSec * 1000,
288
+ });
280
289
  let runRowSettled = false;
281
290
  let durableTaskId;
291
+ let durableLegId;
282
292
  let durableHeartbeat;
283
293
  const cancelledResult = (errorMessage, cause) => mintCancelledResult({ taskId: durableTaskId ?? "", sessionId: prepared.spec.sessionId, startedAtMs: streamLegStartedAt, message: errorMessage, cause });
284
294
  let userMsgEntryId;
@@ -293,52 +303,60 @@ export async function handleTasks(req, res, match, ctx) {
293
303
  anchorPut = true;
294
304
  await settleResumeAnchor(() => store.put(prepared.spec.sessionId, key, entryId, principal ?? null), { leg: "stream", kind: "prompt" });
295
305
  };
296
- if (deps.runStore) {
297
- const tid = earlyDurableTid ?? uuidv7();
298
- const created = await timeClaim(deps.metrics, "run_claim", deps.runStore.createRun(tid, prepared.spec.sessionId, principal ?? null, deps.instanceId ?? "default", { ...runMeta(prepared, source), identity: runIdentityOf(req, deps.config, principal ?? null), idem: idem ?? null }));
299
- if (created.ok)
300
- clearTurnActivity(tid);
301
- if (created.ok)
302
- recordResourceWindow(tid, prepared.spec.resourceSuspend);
303
- if (created.existing) {
304
- const replay = await replayOfExistingRun(created.existing, { subject: submitter, idem }, "sync", deps, deps.runStore);
305
- writeTerminalFrame(doneFrameOfOutcome(replay));
306
- return replay;
306
+ try {
307
+ if (deps.runStore) {
308
+ const tid = earlyDurableTid ?? uuidv7();
309
+ const created = await timeClaim(deps.metrics, "run_claim", deps.runStore.createRun(tid, prepared.spec.sessionId, principal ?? null, deps.instanceId ?? "default", { ...runMeta(prepared, source), identity: runIdentityOf(req, deps.config, principal ?? null), idem: idem ?? null }));
310
+ if (created.ok)
311
+ clearTurnActivity(tid);
312
+ if (created.ok)
313
+ recordResourceWindow(tid, prepared.spec.resourceSuspend);
314
+ if (created.existing) {
315
+ const replay = await replayOfExistingRun(created.existing, { subject: submitter, idem }, "sync", deps, deps.runStore);
316
+ writeTerminalFrame(doneFrameOfOutcome(replay));
317
+ return replay;
318
+ }
319
+ if (created.sessionAbsent) {
320
+ const refused = rootSessionAbsentAnswer();
321
+ writeTerminalFrame(doneFrameOfOutcome(refused));
322
+ return refused;
323
+ }
324
+ if (!created.ok) {
325
+ const conflict = await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId);
326
+ const refused = { status: 409, body: conflict };
327
+ writeTerminalFrame(doneFrameOfOutcome(refused));
328
+ return refused;
329
+ }
330
+ prepared.seat.noteOwnRun(tid);
331
+ stopClaimHeartbeat = startClaimHeartbeat(deps.runStore, tid, principal ?? null, deps.metrics);
332
+ const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: tid, legId: created.legId }, prepared.execution);
333
+ if (placementReject) {
334
+ writeTerminalFrame(doneFrameOfOutcome(placementReject));
335
+ return placementReject;
336
+ }
337
+ durableTaskId = tid;
338
+ durableLegId = created.legId;
339
+ fillRunPreviewOnDelivery(prepared.acceptance, deps.runStore, tid);
307
340
  }
308
- if (created.sessionAbsent) {
309
- const refused = rootSessionAbsentAnswer();
310
- writeTerminalFrame(doneFrameOfOutcome(refused));
311
- return refused;
341
+ if (deps.checkpointStore) {
342
+ const ctxRefusal = await persistSubmissionCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId, legId: heldLegOf(durableLegId, durableTaskId) } : undefined, prepared);
343
+ if (ctxRefusal !== undefined && ctxRefusal !== SUBMIT_CTX_CLAIM_LOST) {
344
+ writeTerminalFrame(doneFrameOfOutcome(ctxRefusal));
345
+ return ctxRefusal;
346
+ }
312
347
  }
313
- if (!created.ok) {
314
- const conflict = await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId);
315
- const refused = { status: 409, body: conflict };
316
- writeTerminalFrame(doneFrameOfOutcome(refused));
317
- return refused;
348
+ const lostClaim = durableTaskId !== undefined && deps.runStore ? await recheckClaimBeforeLaunch(deps, deps.runStore, prepared.spec.sessionId, durableTaskId, heldLegOf(durableLegId, durableTaskId)) : undefined;
349
+ if (lostClaim !== undefined) {
350
+ writeTerminalFrame(doneFrameOfOutcome(lostClaim));
351
+ return lostClaim;
318
352
  }
319
- prepared.seat.noteOwnRun(tid);
320
- if (detachOnDisconnect)
353
+ if (durableTaskId !== undefined && detachOnDisconnect)
321
354
  prepared.seat.markRecord();
322
- stopClaimHeartbeat = startClaimHeartbeat(deps.runStore, tid, principal ?? null, deps.metrics);
323
- const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: tid }, prepared.execution);
324
- if (placementReject) {
325
- writeTerminalFrame(doneFrameOfOutcome(placementReject));
326
- return placementReject;
327
- }
328
- durableTaskId = tid;
329
- fillRunPreviewOnDelivery(prepared.acceptance, deps.runStore, tid);
330
- }
331
- if (deps.checkpointStore) {
332
- const ctxRefusal = await persistSubmissionCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId } : undefined, prepared);
333
- if (ctxRefusal !== undefined && ctxRefusal !== SUBMIT_CTX_CLAIM_LOST) {
334
- writeTerminalFrame(doneFrameOfOutcome(ctxRefusal));
335
- return ctxRefusal;
336
- }
337
355
  }
338
- const lostClaim = durableTaskId !== undefined && deps.runStore ? await recheckClaimBeforeLaunch(deps, deps.runStore, prepared.spec.sessionId, durableTaskId) : undefined;
339
- if (lostClaim !== undefined) {
340
- writeTerminalFrame(doneFrameOfOutcome(lostClaim));
341
- return lostClaim;
356
+ catch (e) {
357
+ const claimFault = faultedAnswerOf(e, SUBMISSION_CLAIM_FACE.faulted);
358
+ writeTerminalFrame(doneFrameOfOutcome(claimFault));
359
+ return claimFault;
342
360
  }
343
361
  commitSessionInheritEnv(deps, prepared.spec.sessionId, prepared.body);
344
362
  markChildrenStoppedByUserOnAbort(ac.signal, durableTaskId ?? prepared.spec.sessionId, prepared.auth?.subject);
@@ -407,6 +425,7 @@ export async function handleTasks(req, res, match, ctx) {
407
425
  const noticeLedger = ledgerSink;
408
426
  const unregisterEngineNotice = registerEngineNoticeLeg({
409
427
  sessionId: prepared.spec.sessionId,
428
+ ...(durableTaskId !== undefined ? { taskId: durableTaskId } : {}),
410
429
  ...(prepared.engineNotices !== undefined ? { pending: prepared.engineNotices } : {}),
411
430
  live: (row) => {
412
431
  if (res.writableEnded || res.destroyed) {
@@ -517,6 +536,7 @@ export async function handleTasks(req, res, match, ctx) {
517
536
  if (ledgerSink)
518
537
  await manifestSeat?.drain(ledgerSink.append);
519
538
  if (ev.type === "done") {
539
+ heldCard = heldParkOf(ev.result);
520
540
  finalResult = await mintSubmitExitResult(ev.result, deps.checkpointStore);
521
541
  if (durableTaskId && finalResult)
522
542
  finalResult = { ...finalResult, taskId: durableTaskId };
@@ -526,7 +546,8 @@ export async function handleTasks(req, res, match, ctx) {
526
546
  finalizeTaskResult(ev.result, principal, prepared.spec.objective);
527
547
  noteRunOutcome(finalResult);
528
548
  await putRewindAnchor();
529
- settleFleet(outwardPlane(finalResult.terminal).status, fleetRunResiduals(finalResult, failureCodeOf(finalResult.terminal)));
549
+ if (!(durableTaskId && deps.runStore && deps.checkpointStore && heldCard !== undefined))
550
+ settleFleet(outwardPlane(finalResult.terminal).status, fleetRunResiduals(finalResult, failureCodeOf(finalResult.terminal)));
530
551
  if (ledgerSink && finalResult) {
531
552
  if (usageKey && deps.modelUsage && deps.runStore && durableTaskId) {
532
553
  const rs2 = deps.runStore;
@@ -679,7 +700,7 @@ export async function handleTasks(req, res, match, ctx) {
679
700
  owner: askOwner,
680
701
  abortSignal: ac.signal,
681
702
  sessionId: prepared.spec.sessionId,
682
- executionLane: prepared.execution.lane,
703
+ ...approvalLegOriginOf(prepared.execution),
683
704
  ...(streamApprovalOn
684
705
  ? {
685
706
  family: "approval_request",
@@ -693,12 +714,12 @@ export async function handleTasks(req, res, match, ctx) {
693
714
  if (deps.toolApproval) {
694
715
  const toolApproval = deps.toolApproval;
695
716
  prepared.spec.onAsk = unattended
696
- ? toolApproval.boundUnattendedAsk({ owner: askOwner, taskId: askTaskId, sessionId: prepared.spec.sessionId, executionLane: prepared.execution.lane }, unattended)
717
+ ? toolApproval.boundUnattendedAsk({ owner: askOwner, taskId: askTaskId, sessionId: prepared.spec.sessionId, ...approvalLegOriginOf(prepared.execution) }, unattended)
697
718
  : toolApproval.boundAsk({
698
719
  owner: askOwner,
699
720
  taskId: askTaskId,
700
721
  sessionId: prepared.spec.sessionId,
701
- executionLane: prepared.execution.lane,
722
+ ...approvalLegOriginOf(prepared.execution),
702
723
  ...(streamApprovalOn ? { legKey: "", ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}) } : {}),
703
724
  });
704
725
  }
@@ -718,10 +739,10 @@ export async function handleTasks(req, res, match, ctx) {
718
739
  : withApproval()));
719
740
  if (durableTaskId && deps.runStore) {
720
741
  const finalPlane = finalResult ? outwardPlane(finalResult.terminal) : undefined;
721
- if (finalResult && finalPlane?.status === "suspended" && deps.checkpointStore)
722
- await deps.runStore.setSuspended(durableTaskId, finalResult);
723
- else if (finalResult && finalPlane?.status === "needs_review" && deps.checkpointStore)
724
- await deps.runStore.setNeedsReview(durableTaskId, finalResult);
742
+ if (finalResult && heldCard !== undefined && deps.checkpointStore) {
743
+ const parked = await commitSyncPark(deps.runStore, durableTaskId, heldCard.word, finalResult, heldCard.token);
744
+ settleFleet(parked.kind === "ended" ? "failed" : outwardPlane(finalResult.terminal).status, fleetRunResiduals(finalResult, failureCodeOf(finalResult.terminal)));
745
+ }
725
746
  else if (finalResult && finalPlane) {
726
747
  await deps.runStore.setTerminal(durableTaskId, finalPlane.status, finalResult, finalPlane.errorMessage ?? null);
727
748
  await releaseKeyIfZeroWorkRefusal(deps.runStore, durableTaskId, finalResult);
@@ -736,8 +757,8 @@ export async function handleTasks(req, res, match, ctx) {
736
757
  await ledgerSink.flush().catch(() => undefined);
737
758
  await ledgerSink.appendParked("suspended", {}).catch(() => undefined);
738
759
  }
739
- await deps.runStore.setSuspended(durableTaskId, null);
740
- settleFleet("suspended");
760
+ const parked = await commitSyncPark(deps.runStore, durableTaskId, "suspended", null, pending);
761
+ settleFleet(parked.kind === "ended" ? "failed" : "suspended");
741
762
  }
742
763
  else if (dcCause !== undefined) {
743
764
  const dcErr = "stream client disconnected before completion (run aborted)";
@@ -780,7 +801,7 @@ export async function handleTasks(req, res, match, ctx) {
780
801
  evict();
781
802
  if (!runRowSettled && durableTaskId && deps.runStore) {
782
803
  try {
783
- const row = await deps.runStore.getRun(durableTaskId);
804
+ const row = await runFactsOf(deps.runStore, durableTaskId);
784
805
  if (row?.status === "running") {
785
806
  const pending = await deps.checkpointStore?.findPendingTokenBySession(prepared.spec.sessionId, undefined, { axis: "run" });
786
807
  const backstopCause = ac.cause();
@@ -790,8 +811,8 @@ export async function handleTasks(req, res, match, ctx) {
790
811
  await ledgerSink.flush().catch(() => undefined);
791
812
  await ledgerSink.appendParked("suspended", {}).catch(() => undefined);
792
813
  }
793
- await deps.runStore.setSuspended(durableTaskId, null);
794
- settleFleet("suspended");
814
+ const parked = await commitSyncPark(deps.runStore, durableTaskId, "suspended", null, pending);
815
+ settleFleet(parked.kind === "ended" ? "failed" : "suspended");
795
816
  }
796
817
  else if (finalResult) {
797
818
  if (ledgerSink && !ledgerTerminal) {
@@ -881,36 +902,43 @@ export async function handleTasks(req, res, match, ctx) {
881
902
  const runSyncSubmitLeg = async () => {
882
903
  const syncLegStartedAt = Date.now();
883
904
  let durableTaskId;
905
+ let durableLegId;
884
906
  let durableHeartbeat;
885
- if (deps.runStore) {
886
- const tid = uuidv7();
887
- const created = await timeClaim(deps.metrics, "run_claim", deps.runStore.createRun(tid, prepared.spec.sessionId, principal ?? null, deps.instanceId ?? "default", { ...runMeta(prepared, source), identity: runIdentityOf(req, deps.config, principal ?? null), idem: idem ?? null }));
888
- if (created.ok)
889
- clearTurnActivity(tid);
890
- if (created.ok)
891
- recordResourceWindow(tid, prepared.spec.resourceSuspend);
892
- if (created.existing)
893
- return await replayOfExistingRun(created.existing, { subject: submitter, idem }, "sync", deps, deps.runStore);
894
- if (created.sessionAbsent)
895
- return rootSessionAbsentAnswer();
896
- if (!created.ok)
897
- return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId) };
898
- prepared.seat.noteOwnRun(tid);
899
- stopSyncClaimHeartbeat = startClaimHeartbeat(deps.runStore, tid, principal ?? null, deps.metrics);
900
- const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: tid }, prepared.execution);
901
- if (placementReject)
902
- return placementReject;
903
- durableTaskId = tid;
904
- fillRunPreviewOnDelivery(prepared.acceptance, deps.runStore, tid);
907
+ try {
908
+ if (deps.runStore) {
909
+ const tid = uuidv7();
910
+ const created = await timeClaim(deps.metrics, "run_claim", deps.runStore.createRun(tid, prepared.spec.sessionId, principal ?? null, deps.instanceId ?? "default", { ...runMeta(prepared, source), identity: runIdentityOf(req, deps.config, principal ?? null), idem: idem ?? null }));
911
+ if (created.ok)
912
+ clearTurnActivity(tid);
913
+ if (created.ok)
914
+ recordResourceWindow(tid, prepared.spec.resourceSuspend);
915
+ if (created.existing)
916
+ return await replayOfExistingRun(created.existing, { subject: submitter, idem }, "sync", deps, deps.runStore);
917
+ if (created.sessionAbsent)
918
+ return rootSessionAbsentAnswer();
919
+ if (!created.ok)
920
+ return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId) };
921
+ prepared.seat.noteOwnRun(tid);
922
+ stopSyncClaimHeartbeat = startClaimHeartbeat(deps.runStore, tid, principal ?? null, deps.metrics);
923
+ const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: tid, legId: created.legId }, prepared.execution);
924
+ if (placementReject)
925
+ return placementReject;
926
+ durableTaskId = tid;
927
+ durableLegId = created.legId;
928
+ fillRunPreviewOnDelivery(prepared.acceptance, deps.runStore, tid);
929
+ }
930
+ if (deps.checkpointStore) {
931
+ const ctxRefusal = await persistSubmissionCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId, legId: heldLegOf(durableLegId, durableTaskId) } : undefined, prepared);
932
+ if (ctxRefusal !== undefined && ctxRefusal !== SUBMIT_CTX_CLAIM_LOST)
933
+ return ctxRefusal;
934
+ }
935
+ const lostClaim = durableTaskId !== undefined && deps.runStore ? await recheckClaimBeforeLaunch(deps, deps.runStore, prepared.spec.sessionId, durableTaskId, heldLegOf(durableLegId, durableTaskId)) : undefined;
936
+ if (lostClaim !== undefined)
937
+ return lostClaim;
905
938
  }
906
- if (deps.checkpointStore) {
907
- const ctxRefusal = await persistSubmissionCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId } : undefined, prepared);
908
- if (ctxRefusal !== undefined && ctxRefusal !== SUBMIT_CTX_CLAIM_LOST)
909
- return ctxRefusal;
939
+ catch (e) {
940
+ return faultedAnswerOf(e, SUBMISSION_CLAIM_FACE.faulted);
910
941
  }
911
- const lostClaim = durableTaskId !== undefined && deps.runStore ? await recheckClaimBeforeLaunch(deps, deps.runStore, prepared.spec.sessionId, durableTaskId) : undefined;
912
- if (lostClaim !== undefined)
913
- return lostClaim;
914
942
  commitSessionInheritEnv(deps, prepared.spec.sessionId, prepared.body);
915
943
  const syncCancelCtrl = createRunAbort(principal ?? null);
916
944
  markChildrenStoppedByUserOnAbort(syncCancelCtrl.signal, durableTaskId ?? prepared.spec.sessionId, prepared.auth?.subject);
@@ -947,8 +975,9 @@ export async function handleTasks(req, res, match, ctx) {
947
975
  counters.uncountedBillableInflight++;
948
976
  try {
949
977
  const heldDecisions = await heldWorkflowParkDecisions(deps, prepared.spec.sessionId);
950
- const verifyLeg = (v) => runWithVerification(prepared.runner, specWithSignal, v, heldDecisions);
951
- const cascadeLeg = () => runCascade(prepared.runner, specWithSignal, cascadeConfig(deps.config.cascadeLadder, prepared.spec.limits?.maxCostUsd), heldDecisions);
978
+ const compositionInternals = { ...heldDecisions, ...compositionLegRoot(prepared.legFacts?.registeredCwd) };
979
+ const verifyLeg = (v) => runWithVerification(prepared.runner, specWithSignal, v, compositionInternals);
980
+ const cascadeLeg = () => runCascade(prepared.runner, specWithSignal, cascadeConfig(deps.config.cascadeLadder, prepared.spec.limits?.maxCostUsd), compositionInternals);
952
981
  const plainLeg = async () => {
953
982
  const stream = prepared.runner.runTaskStream(specWithSignal, undefined, heldDecisions);
954
983
  const syncWorkspace = createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), prepared.legFacts?.sessionWitness);
@@ -1009,15 +1038,16 @@ export async function handleTasks(req, res, match, ctx) {
1009
1038
  }
1010
1039
  const exitResult = await mintSubmitExitResult(result, deps.checkpointStore);
1011
1040
  const syncPlane = outwardPlane(result.terminal);
1012
- if (syncPlane.status === "suspended" && deps.checkpointStore && deps.runStore && durableTaskId) {
1013
- await deps.runStore.setSuspended(durableTaskId, exitResult);
1014
- prepared.acceptance.settle(result);
1015
- return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "suspended" })) };
1016
- }
1017
- if (syncPlane.status === "needs_review" && deps.checkpointStore && deps.runStore && durableTaskId) {
1018
- await deps.runStore.setNeedsReview(durableTaskId, exitResult);
1041
+ const syncHeld = heldParkOf(result);
1042
+ if (syncHeld !== undefined && deps.checkpointStore && deps.runStore && durableTaskId) {
1043
+ const parked = await commitParkRow({
1044
+ runStore: deps.runStore, taskId: durableTaskId, word: syncHeld.word, result: exitResult, card: { token: syncHeld.token, sessionId: prepared.spec.sessionId }, cards: deps.checkpointStore, leg: "sync",
1045
+ legId: heldLegOf(durableLegId, durableTaskId), staleWindowMs: deps.config.runStaleSec * 1000,
1046
+ });
1019
1047
  prepared.acceptance.settle(result);
1020
- return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "needs_review" })) };
1048
+ if (parked.kind === "ended")
1049
+ return { status: 200, body: withSyncSubmitKeys(parked.row !== undefined ? syncSubmitBodyOfRow(parked.row) : { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "failed" }) };
1050
+ return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: syncHeld.word })) };
1021
1051
  }
1022
1052
  if (durableTaskId && deps.runStore)
1023
1053
  await deps.runStore.setTerminal(durableTaskId, syncPlane.status, exitResult, syncPlane.errorMessage ?? null);
@@ -1055,4 +1085,9 @@ export const TASKS_ROUTES = [
1055
1085
  { id: "tasks-submit", path: "/v1/tasks", billable: "submit", methods: ["POST"] },
1056
1086
  { id: "tasks-submit-stream", path: "/v1/tasks/stream", billable: "submit", methods: ["POST"] },
1057
1087
  ];
1088
+ function heldLegOf(legId, taskId) {
1089
+ if (legId === undefined)
1090
+ throw new Error(`tasks route: run ${taskId} has no record of the holding leg its createRun handed back — wiring error, nothing keyed on the leg can be written`);
1091
+ return legId;
1092
+ }
1058
1093
  //# sourceMappingURL=tasks.js.map
@@ -9,7 +9,7 @@ import { bindSseLifecycle } from "../sse-lifecycle.js";
9
9
  import { sendJson, sendError, sseHeaders, SSE_MAX_STREAM_MS, SSE_HEARTBEAT_IDLE_MS } from "../send.js";
10
10
  import { filterFingerprint } from "../cursor-fingerprint.js";
11
11
  import { sendUnauthorized } from "../principal-gate.js";
12
- import { admitRunById, enter, entryIsFleet, readVisibleRun, routeListFilter, runRowAt } from "../owner-access.js";
12
+ import { admitRunById, enter, entryIsFleet, listVisibleRuns, readVisibleRun, routeListFilter, runListOwnerOf, toolResultRefOwned } from "../owner-access.js";
13
13
  import { listFilterOf } from "../../owner-faces.js";
14
14
  import { assertNever } from "../route-ctx.js";
15
15
  import * as facts from "../../capability-facts.js";
@@ -42,7 +42,7 @@ export async function handleTraceUsage(req, res, match, ctx) {
42
42
  const traceEntry = enter(req, res, deps, match.decl.id);
43
43
  if (traceEntry === undefined)
44
44
  return;
45
- const gateOwner = listFilterOf(traceEntry.face, traceEntry.caller).gateOwner;
45
+ const traceFilter = listFilterOf(traceEntry.face, traceEntry.caller);
46
46
  const runs = facts.durableRuns(deps);
47
47
  if (!runs.available) {
48
48
  sendError(res, 501, "capability.run_store_required", "trace API requires a durable run store (DB_BACKEND=mysql|pg|local)");
@@ -61,20 +61,20 @@ export async function handleTraceUsage(req, res, match, ctx) {
61
61
  }
62
62
  switch (match.decl.id) {
63
63
  case "task-trace-list":
64
- await handleTaskList(res, runStore, query, gateOwner);
64
+ await handleTaskList(res, runStore, query, traceFilter);
65
65
  return;
66
66
  case "task-trace-turns":
67
67
  await handleTaskTurns(res, runStore, admittedRun, query);
68
68
  return;
69
69
  case "task-trace-stream":
70
- await streamTaskTrace(req, res, runStore, admittedRun, match.search);
70
+ await streamTaskTrace(req, res, runStore, traceEntry, admittedRun, match.search);
71
71
  return;
72
72
  case "task-trace-artifacts":
73
73
  await handleTaskArtifacts(res, runStore, admittedRun);
74
74
  return;
75
75
  case "task-tool-result": {
76
76
  const ownedRun = admittedRun;
77
- const readRun = ownedRun !== undefined ? async () => ownedRun : () => readVisibleRun(traceEntry, runStore, taskId);
77
+ const readRun = ownedRun !== undefined ? async () => ownedRun : async () => (await readVisibleRun(traceEntry, runStore, taskId))?.row;
78
78
  await handleToolResult(res, deps.toolResultStore, taskId, readRun, safeDecode(match.params.ref), query);
79
79
  return;
80
80
  }
@@ -161,11 +161,12 @@ function decodeCursor(s, expectF) {
161
161
  return undefined;
162
162
  }
163
163
  }
164
- async function handleTaskList(res, runStore, query, forceOwner) {
164
+ async function handleTaskList(res, runStore, query, filter) {
165
165
  const status = query.get("status") ?? undefined;
166
166
  const jobId = query.get("jobId") ?? undefined;
167
167
  const source = query.get("source") ?? undefined;
168
- const owner = forceOwner != null ? forceOwner : (query.get("owner") ?? undefined);
168
+ const namedOwner = query.get("owner") ?? undefined;
169
+ const owner = runListOwnerOf(filter, namedOwner);
169
170
  const limit = Math.min(100, Math.max(1, Number(query.get("limit") ?? 50) || 50));
170
171
  const f = filterFingerprint([status, jobId, source, owner]);
171
172
  const cursor = decodeCursor(query.get("cursor"), f);
@@ -173,7 +174,7 @@ async function handleTaskList(res, runStore, query, forceOwner) {
173
174
  sendError(res, 400, "request.cursor_filter_mismatch", "cursor was issued under a different filter (status/jobId/source/owner) — restart from the first page without a cursor");
174
175
  return;
175
176
  }
176
- const rows = await runStore.listRuns({ ...(status ? { status } : {}), ...(jobId ? { jobId } : {}), ...(source ? { source } : {}), ...(owner ? { owner } : {}), ...(cursor ? { cursor } : {}), limit: limit + 1 });
177
+ const rows = await listVisibleRuns(runStore, filter, namedOwner, { ...(status ? { status } : {}), ...(jobId ? { jobId } : {}), ...(source ? { source } : {}), ...(cursor ? { cursor } : {}), limit: limit + 1 });
177
178
  const hasMore = rows.length > limit;
178
179
  const page = hasMore ? rows.slice(0, limit) : rows;
179
180
  const tasks = page.map((r) => taskSummary(r));
@@ -216,8 +217,7 @@ async function handleToolResult(res, store, taskId, readRun, ref, query) {
216
217
  const run = await readRun();
217
218
  if (!run)
218
219
  return notFound();
219
- const owner = store?.ownerOf ? await store.ownerOf(ref) : undefined;
220
- const ownedByThisCaller = owner !== undefined && owner.sessionId === run.sessionId && (owner.taskId === undefined || owner.taskId === taskId);
220
+ const ownedByThisCaller = await toolResultRefOwned(store, ref, run);
221
221
  if (!ownedByThisCaller)
222
222
  return notFound();
223
223
  if (!store)
@@ -240,7 +240,7 @@ async function handleTaskTurns(res, runStore, run, query) {
240
240
  const nextCursor = eligible.length > limit && oldest ? String(oldest.seq) : undefined;
241
241
  sendJson(res, 200, { turns, ...(nextCursor ? { nextCursor } : {}), retainedFrom });
242
242
  }
243
- async function streamTaskTrace(req, res, runStore, admitted, search) {
243
+ async function streamTaskTrace(req, res, runStore, entry, admitted, search) {
244
244
  const taskId = admitted.taskId;
245
245
  const lastId = Number(req.headers["last-event-id"] ?? new URLSearchParams(search).get("from") ?? 0);
246
246
  let from = Number.isFinite(lastId) ? lastId : 0;
@@ -264,11 +264,11 @@ async function streamTaskTrace(req, res, runStore, admitted, search) {
264
264
  }
265
265
  };
266
266
  while (!closed) {
267
- const [events, raw] = await Promise.all([runStore.getEvents(taskId, from), runStore.getRun(taskId)]);
267
+ const [events, reread] = await Promise.all([runStore.getEvents(taskId, from), readVisibleRun(entry, runStore, taskId)]);
268
268
  write(events);
269
- if (!raw)
269
+ if (!reread)
270
270
  break;
271
- const run = await runRowAt("task-trace-stream", runStore, raw);
271
+ const run = reread.row;
272
272
  if (run.status !== "running") {
273
273
  write(await runStore.getEvents(taskId, from));
274
274
  if (!deliveredTerminal && isHolderDeathVerdict(run))
@@ -2,6 +2,7 @@ import type { IncomingMessage, ServerResponse } from "node:http";
2
2
  import { type WorkflowRun } from "@sema-agent/core";
3
3
  import { type Admit } from "../../trace/projection-table.js";
4
4
  import type { RouteCtx, RouteMatch, RouteIdsOf } from "../route-ctx.js";
5
+ /** SVC-5 的 steer 路——`handle()` 里位置在 tasks/runs 之后(鉴权门之后),故是**独立**的域入口。 */
5
6
  /** 路由体 = 从 `server.ts` 的 `handle()` 里**整段剪切**过来的原文(唯一改动:统一去缩进两格)。裸 `return;`
6
7
  * = 「本域已应答」;走到函数尾才是「没匹配上」。跨域的东西一律在首行解构出来。 */
7
8
  export declare function handleWorkflows(req: IncomingMessage, res: ServerResponse, match: RouteMatch<WorkflowsRouteId>, ctx: RouteCtx): Promise<void>;