@sema-agent/server 7.150.0 → 7.152.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 (514) hide show
  1. package/MIGRATION.md +451 -0
  2. package/README.md +15 -3
  3. package/README.zh-CN.md +10 -2
  4. package/USAGE.md +144 -87
  5. package/deploy/sema-up/README.md +11 -4
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
  9. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
  10. package/deploy/sema-up/chart/templates/server.yaml +5 -3
  11. package/deploy/sema-up/chart/values-full-single.yaml +3 -1
  12. package/deploy/sema-up/chart/values.yaml +8 -1
  13. package/deploy/sema-up/cluster-up.sh +7 -6
  14. package/deploy/sema-up/kube-up.sh +6 -6
  15. package/deploy/sema-up/lib/flagshape.sh +36 -8
  16. package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
  17. package/deploy/sema-up/lib/helm-values-kube.py +2 -0
  18. package/deploy/sema-up/machines.example.yaml +3 -1
  19. package/deploy/sema-up/sema-up.sh +22 -16
  20. package/dist/adoption/import.js +3 -3
  21. package/dist/approval-ask-audit-store.d.ts +1 -1
  22. package/dist/approval-ask-machine.d.ts +4 -10
  23. package/dist/approval-ask-retention.d.ts +1 -1
  24. package/dist/approval-card.d.ts +12 -14
  25. package/dist/approval-gate-currency.d.ts +9 -9
  26. package/dist/approval-gate-currency.js +3 -4
  27. package/dist/approval-hmac.d.ts +17 -1
  28. package/dist/approval-hmac.js +7 -1
  29. package/dist/approval-queue-kind.d.ts +1 -1
  30. package/dist/approval.d.ts +2 -2
  31. package/dist/approval.js +2 -2
  32. package/dist/auth-bridge.d.ts +20 -0
  33. package/dist/auth-bridge.js +9 -0
  34. package/dist/background-session-reap.d.ts +1 -1
  35. package/dist/bake-runner/main.d.ts +4 -2
  36. package/dist/bind-host.d.ts +3 -6
  37. package/dist/bind-host.js +4 -7
  38. package/dist/boot/budget-tracing.js +1 -1
  39. package/dist/boot/coordinators.d.ts +1 -1
  40. package/dist/boot/coordinators.js +9 -10
  41. package/dist/boot/device-lane.js +2 -0
  42. package/dist/boot/engine-lease.d.ts +5 -0
  43. package/dist/boot/engine-lease.js +1 -0
  44. package/dist/boot/execution-env.d.ts +9 -14
  45. package/dist/boot/execution-env.js +85 -22
  46. package/dist/boot/execution-lane.js +32 -5
  47. package/dist/boot/late-binds.d.ts +8 -4
  48. package/dist/boot/late-binds.js +7 -1
  49. package/dist/boot/leader.d.ts +31 -30
  50. package/dist/boot/leader.js +38 -28
  51. package/dist/boot/leg-path-adjudication.d.ts +40 -0
  52. package/dist/boot/leg-path-adjudication.js +18 -0
  53. package/dist/boot/memory-consolidation.d.ts +3 -2
  54. package/dist/boot/memory-consolidation.js +6 -6
  55. package/dist/boot/parked-revive-gate.js +3 -15
  56. package/dist/boot/reapers.d.ts +6 -1
  57. package/dist/boot/reapers.js +13 -2
  58. package/dist/boot/resolve-spec.d.ts +3 -3
  59. package/dist/boot/resolve-spec.js +43 -48
  60. package/dist/boot/runner-deps.d.ts +46 -35
  61. package/dist/boot/runner-deps.js +94 -91
  62. package/dist/boot/session-age-out.d.ts +36 -0
  63. package/dist/boot/session-age-out.js +101 -0
  64. package/dist/boot/session-faces.d.ts +5 -14
  65. package/dist/boot/session-faces.js +9 -5
  66. package/dist/boot/shutdown.d.ts +6 -0
  67. package/dist/boot/shutdown.js +10 -4
  68. package/dist/boot/stage-01-config.js +2 -0
  69. package/dist/boot/stage-02-web-admin-pull.js +4 -5
  70. package/dist/boot/stage-05-execution-env.d.ts +5 -3
  71. package/dist/boot/stage-05-execution-env.js +3 -2
  72. package/dist/boot/stage-06-runners.d.ts +9 -4
  73. package/dist/boot/stage-06-runners.js +24 -9
  74. package/dist/boot/stage-07-capability-layer.d.ts +8 -4
  75. package/dist/boot/stage-07-capability-layer.js +3 -2
  76. package/dist/boot/stage-08-reapers.d.ts +8 -4
  77. package/dist/boot/stage-08-reapers.js +4 -2
  78. package/dist/boot/stage-09-leader.d.ts +12 -5
  79. package/dist/boot/stage-09-leader.js +14 -5
  80. package/dist/boot/stage-10-http-server.d.ts +19 -5
  81. package/dist/boot/stage-10-http-server.js +14 -21
  82. package/dist/boot/stores.js +7 -4
  83. package/dist/boot/web-admin.js +5 -8
  84. package/dist/boot/workflow-orchestration.d.ts +7 -2
  85. package/dist/boot/workflow-orchestration.js +24 -7
  86. package/dist/bounded-rotation.d.ts +29 -0
  87. package/dist/bounded-rotation.js +24 -0
  88. package/dist/capabilities/approvals-push.d.ts +3 -3
  89. package/dist/capabilities/scenarios.d.ts +28 -13
  90. package/dist/capabilities/scenarios.js +2 -2
  91. package/dist/capability-facts.d.ts +43 -32
  92. package/dist/capability-facts.js +45 -51
  93. package/dist/card-rule-offers.d.ts +32 -0
  94. package/dist/card-rule-offers.js +130 -0
  95. package/dist/center-credential.d.ts +25 -6
  96. package/dist/center-credential.js +25 -5
  97. package/dist/config-catalog.d.ts +26 -7
  98. package/dist/config-catalog.js +26 -22
  99. package/dist/config-dir-trust.js +4 -2
  100. package/dist/config-invariants.d.ts +20 -8
  101. package/dist/config-invariants.js +55 -12
  102. package/dist/config-lkg.d.ts +5 -19
  103. package/dist/config-lkg.js +8 -62
  104. package/dist/config-provider.d.ts +1 -1
  105. package/dist/config-root-migration.d.ts +2 -2
  106. package/dist/config-types.d.ts +38 -42
  107. package/dist/config.d.ts +58 -7
  108. package/dist/config.js +90 -40
  109. package/dist/control-socket.d.ts +51 -0
  110. package/dist/control-socket.js +115 -0
  111. package/dist/deployment-governance.d.ts +2 -1
  112. package/dist/deployment-shape.d.ts +9 -1
  113. package/dist/deployment-shape.js +2 -1
  114. package/dist/device-protocol.d.ts +5 -4
  115. package/dist/device-protocol.js +1 -1
  116. package/dist/device-ws-hub.d.ts +7 -0
  117. package/dist/device-ws-hub.js +10 -3
  118. package/dist/device-ws-protocol.d.ts +63 -10
  119. package/dist/device-ws-protocol.js +56 -25
  120. package/dist/elicitation.js +2 -2
  121. package/dist/engine-identity.d.ts +19 -7
  122. package/dist/engine-identity.js +10 -2
  123. package/dist/entry-mode-clamp-notice.d.ts +2 -1
  124. package/dist/entry-problems.d.ts +40 -3
  125. package/dist/entry-problems.js +3 -1
  126. package/dist/execution-env-refusal.d.ts +29 -0
  127. package/dist/execution-env-refusal.js +8 -0
  128. package/dist/execution-lane-caps.d.ts +3 -1
  129. package/dist/field-conflict.d.ts +1 -1
  130. package/dist/file-history-capture.d.ts +11 -4
  131. package/dist/file-history-capture.js +9 -6
  132. package/dist/file-history-disclosure.d.ts +7 -5
  133. package/dist/file-history-disclosure.js +7 -5
  134. package/dist/fleet/drain-entry.d.ts +4 -0
  135. package/dist/fleet/engine-signal.d.ts +12 -29
  136. package/dist/fleet/engine-signal.js +1 -7
  137. package/dist/fleet-client.js +2 -5
  138. package/dist/gate-settlement.d.ts +1 -8
  139. package/dist/gate-settlement.js +0 -4
  140. package/dist/history-anchor.js +1 -1
  141. package/dist/hitl-delivery.d.ts +2 -3
  142. package/dist/hitl-delivery.js +0 -2
  143. package/dist/hooks/hook-llm.js +4 -2
  144. package/dist/hooks/hook-runner.d.ts +3 -2
  145. package/dist/hooks/hook-runner.js +18 -3
  146. package/dist/host-decision.d.ts +11 -11
  147. package/dist/host-lsp-manager.d.ts +2 -2
  148. package/dist/http/active-run-conflict.d.ts +35 -2
  149. package/dist/http/active-run-conflict.js +48 -19
  150. package/dist/http/admission.js +17 -2
  151. package/dist/http/approval-sweeps.d.ts +1 -1
  152. package/dist/http/approval-sweeps.js +10 -7
  153. package/dist/http/checkpoint-ctx.d.ts +4 -0
  154. package/dist/http/checkpoint-ctx.js +2 -0
  155. package/dist/http/dispatch.d.ts +8 -3
  156. package/dist/http/dispatch.js +59 -32
  157. package/dist/http/durable-run-leg.js +16 -17
  158. package/dist/http/health-reader.d.ts +16 -9
  159. package/dist/http/health-reader.js +2 -1
  160. package/dist/http/health-self-report.d.ts +9 -1
  161. package/dist/http/health-self-report.js +3 -1
  162. package/dist/http/owner-access.d.ts +33 -14
  163. package/dist/http/owner-access.js +40 -10
  164. package/dist/http/principal-gate.d.ts +49 -21
  165. package/dist/http/principal-gate.js +61 -11
  166. package/dist/http/request-channel.d.ts +23 -0
  167. package/dist/http/request-channel.js +9 -0
  168. package/dist/http/request-guards.js +17 -2
  169. package/dist/http/resume-ctx-read.js +42 -3
  170. package/dist/http/resume-legs.d.ts +4 -3
  171. package/dist/http/resume-legs.js +367 -117
  172. package/dist/http/route-ctx.d.ts +91 -15
  173. package/dist/http/route-ctx.js +17 -0
  174. package/dist/http/route-table.d.ts +5 -1
  175. package/dist/http/route-table.js +4 -0
  176. package/dist/http/routes/admin-config-refresh.js +3 -3
  177. package/dist/http/routes/admin-drain.d.ts +3 -0
  178. package/dist/http/routes/admin-drain.js +7 -7
  179. package/dist/http/routes/admin-memory-optout.d.ts +1 -1
  180. package/dist/http/routes/admin-memory-optout.js +3 -3
  181. package/dist/http/routes/adoption.js +3 -5
  182. package/dist/http/routes/agents-roster.js +2 -3
  183. package/dist/http/routes/approvals-assistant.d.ts +2 -1
  184. package/dist/http/routes/approvals-assistant.js +99 -51
  185. package/dist/http/routes/background.d.ts +3 -3
  186. package/dist/http/routes/capabilities.d.ts +4 -0
  187. package/dist/http/routes/capabilities.js +38 -10
  188. package/dist/http/routes/config-catalog.js +2 -2
  189. package/dist/http/routes/devices.js +1 -1
  190. package/dist/http/routes/diagnostics.d.ts +3 -3
  191. package/dist/http/routes/diagnostics.js +19 -7
  192. package/dist/http/routes/fleet.js +10 -8
  193. package/dist/http/routes/images.js +10 -10
  194. package/dist/http/routes/memory-bundle.js +3 -3
  195. package/dist/http/routes/memory-compliance.js +3 -3
  196. package/dist/http/routes/memory-consolidation.js +2 -2
  197. package/dist/http/routes/memory-origin.js +3 -3
  198. package/dist/http/routes/memory-policy.js +2 -2
  199. package/dist/http/routes/observability.js +3 -3
  200. package/dist/http/routes/projects.d.ts +3 -2
  201. package/dist/http/routes/projects.js +4 -5
  202. package/dist/http/routes/retention-ops.js +3 -3
  203. package/dist/http/routes/rules.js +5 -5
  204. package/dist/http/routes/run-permission-mode.d.ts +2 -1
  205. package/dist/http/routes/run-permission-mode.js +2 -2
  206. package/dist/http/routes/runs.d.ts +4 -9
  207. package/dist/http/routes/runs.js +171 -65
  208. package/dist/http/routes/session-sync.d.ts +22 -9
  209. package/dist/http/routes/session-sync.js +204 -107
  210. package/dist/http/routes/sessions-list.js +13 -7
  211. package/dist/http/routes/sessions.js +30 -15
  212. package/dist/http/routes/tasks.js +46 -41
  213. package/dist/http/routes/trace-usage.js +2 -2
  214. package/dist/http/routes/workflows.js +1 -1
  215. package/dist/http/server.d.ts +30 -30
  216. package/dist/http/server.js +16 -4
  217. package/dist/http/submit-ctx.d.ts +1 -1
  218. package/dist/http/submit-ctx.js +7 -4
  219. package/dist/http/wire-types.d.ts +14 -4
  220. package/dist/human-facing-args.d.ts +33 -0
  221. package/dist/human-facing-args.js +33 -0
  222. package/dist/identity-source.d.ts +20 -3
  223. package/dist/identity-source.js +14 -0
  224. package/dist/index.d.ts +5 -1
  225. package/dist/k8s-api-credentials.d.ts +29 -0
  226. package/dist/k8s-api-credentials.js +25 -0
  227. package/dist/lane-home-probe.d.ts +3 -7
  228. package/dist/lane-home-probe.js +2 -2
  229. package/dist/leader/diffup.d.ts +19 -0
  230. package/dist/leader/diffup.js +7 -0
  231. package/dist/leader/leader.d.ts +116 -11
  232. package/dist/leader/leader.js +69 -5
  233. package/dist/leader/repair-wire.js +2 -2
  234. package/dist/leader/run-entry.d.ts +2 -1
  235. package/dist/leader/run-entry.js +1 -1
  236. package/dist/leader/wire.d.ts +42 -132
  237. package/dist/leader/wire.js +81 -67
  238. package/dist/leg-facts.d.ts +13 -5
  239. package/dist/leg-facts.js +2 -1
  240. package/dist/memory-scope.d.ts +23 -11
  241. package/dist/memory-scope.js +18 -6
  242. package/dist/memory-sync-client.d.ts +30 -2
  243. package/dist/memory-sync-client.js +16 -9
  244. package/dist/model-entry-headers.d.ts +9 -10
  245. package/dist/model-entry-headers.js +0 -4
  246. package/dist/model-entry-refusal.d.ts +7 -4
  247. package/dist/model-entry-refusal.js +11 -5
  248. package/dist/model-plane-face.d.ts +1 -1
  249. package/dist/model-plane-face.js +3 -1
  250. package/dist/model-route-endpoint.d.ts +13 -7
  251. package/dist/model-route-endpoint.js +14 -11
  252. package/dist/model-select.d.ts +22 -0
  253. package/dist/model-select.js +9 -0
  254. package/dist/model-unreachable-notice.d.ts +11 -0
  255. package/dist/model-unreachable-notice.js +4 -4
  256. package/dist/object-store-buckets.d.ts +640 -6
  257. package/dist/object-store-buckets.js +166 -0
  258. package/dist/observability/err-text.d.ts +7 -0
  259. package/dist/observability/err-text.js +5 -0
  260. package/dist/observability/fail-open.d.ts +25 -17
  261. package/dist/observability/fail-open.js +25 -17
  262. package/dist/observability/logger.js +3 -1
  263. package/dist/observability/metrics.js +1 -0
  264. package/dist/operator-roster.d.ts +68 -0
  265. package/dist/operator-roster.js +32 -0
  266. package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
  267. package/dist/orchestration/workflow-notify-journal.js +12 -1
  268. package/dist/orchestration/workflow-park-decision.d.ts +70 -18
  269. package/dist/orchestration/workflow-park-decision.js +49 -10
  270. package/dist/orchestration/workflow-park-holder.d.ts +65 -0
  271. package/dist/orchestration/workflow-park-holder.js +98 -0
  272. package/dist/orchestration/workflow-record-fence.d.ts +36 -0
  273. package/dist/orchestration/workflow-record-fence.js +42 -0
  274. package/dist/outbound-dispatcher.d.ts +71 -8
  275. package/dist/outbound-dispatcher.js +48 -7
  276. package/dist/owner-faces.d.ts +2 -2
  277. package/dist/parked-decide.d.ts +106 -55
  278. package/dist/parked-decide.js +153 -117
  279. package/dist/peer-directory.d.ts +2 -2
  280. package/dist/peer-inbound-face.d.ts +2 -6
  281. package/dist/peer-inbound-face.js +0 -3
  282. package/dist/permission-mode-admission.d.ts +74 -5
  283. package/dist/permission-mode-admission.js +56 -3
  284. package/dist/plugins/adoption-log-sql.d.ts +3 -1
  285. package/dist/plugins/adoption-log-sql.js +7 -1
  286. package/dist/plugins/approval-ask-store-file.d.ts +14 -2
  287. package/dist/plugins/approval-ask-store-file.js +11 -0
  288. package/dist/plugins/approval-ask-store-memory.d.ts +10 -1
  289. package/dist/plugins/approval-ask-store-memory.js +35 -10
  290. package/dist/plugins/approval-ask-store-sql.d.ts +69 -4
  291. package/dist/plugins/approval-ask-store-sql.js +45 -5
  292. package/dist/plugins/approval-exemption-store.js +3 -0
  293. package/dist/plugins/approval-nonce-store.js +2 -0
  294. package/dist/plugins/blob-backend.d.ts +83 -7
  295. package/dist/plugins/blob-backend.js +57 -6
  296. package/dist/plugins/breaker-state-sql.js +2 -0
  297. package/dist/plugins/caching-session-store.d.ts +9 -15
  298. package/dist/plugins/caching-session-store.js +6 -0
  299. package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
  300. package/dist/plugins/checkpoint-index-columns.js +3 -6
  301. package/dist/plugins/checkpoint-store-face.d.ts +119 -61
  302. package/dist/plugins/checkpoint-store-face.js +134 -55
  303. package/dist/plugins/device-store-sql.js +6 -0
  304. package/dist/plugins/error-origin.d.ts +18 -0
  305. package/dist/plugins/error-origin.js +10 -0
  306. package/dist/plugins/execution-placement-sql.js +6 -6
  307. package/dist/plugins/image-bake-store-sql.js +6 -0
  308. package/dist/plugins/image-index-sql.js +4 -0
  309. package/dist/plugins/landed-attendants.d.ts +212 -0
  310. package/dist/plugins/landed-attendants.js +161 -0
  311. package/dist/plugins/leader-run-store-sql.js +4 -0
  312. package/dist/plugins/local-checkpoint-store.d.ts +13 -3
  313. package/dist/plugins/local-checkpoint-store.js +38 -49
  314. package/dist/plugins/local-session-live-reference.d.ts +40 -0
  315. package/dist/plugins/local-session-live-reference.js +39 -0
  316. package/dist/plugins/local-session-store.d.ts +71 -33
  317. package/dist/plugins/local-session-store.js +129 -27
  318. package/dist/plugins/memory-engine-pg.js +4 -0
  319. package/dist/plugins/memory-engine-sql-apply.js +5 -2
  320. package/dist/plugins/memory-engine-tidb.js +4 -0
  321. package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
  322. package/dist/plugins/memory-sync-store-pg.js +5 -0
  323. package/dist/plugins/memory-sync-store-tidb.js +5 -0
  324. package/dist/plugins/one-time-migrations.d.ts +104 -80
  325. package/dist/plugins/one-time-migrations.js +226 -132
  326. package/dist/plugins/org-delivery-quota-store.js +4 -1
  327. package/dist/plugins/outcome-ledger-sql.js +2 -0
  328. package/dist/plugins/permission-rule-store-sql.js +11 -4
  329. package/dist/plugins/pg-cost-quota.js +4 -0
  330. package/dist/plugins/pg-pool.js +35 -10
  331. package/dist/plugins/pg-rate-limiter.js +2 -0
  332. package/dist/plugins/posix-shell-fs.d.ts +6 -1
  333. package/dist/plugins/posix-shell-fs.js +4 -1
  334. package/dist/plugins/remote-env-adb.d.ts +19 -15
  335. package/dist/plugins/remote-env-adb.js +41 -15
  336. package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
  337. package/dist/plugins/remote-env-connect-seat.js +72 -0
  338. package/dist/plugins/remote-env-device.d.ts +22 -5
  339. package/dist/plugins/remote-env-device.js +106 -8
  340. package/dist/plugins/remote-env-e2b.d.ts +15 -6
  341. package/dist/plugins/remote-env-e2b.js +42 -32
  342. package/dist/plugins/remote-env-file-error.js +6 -2
  343. package/dist/plugins/remote-env-host.d.ts +46 -10
  344. package/dist/plugins/remote-env-host.js +124 -52
  345. package/dist/plugins/remote-env-k8s.d.ts +109 -41
  346. package/dist/plugins/remote-env-k8s.js +160 -54
  347. package/dist/plugins/remote-env-local-docker.d.ts +13 -8
  348. package/dist/plugins/remote-env-local-docker.js +34 -41
  349. package/dist/plugins/remote-env-ssh.d.ts +18 -12
  350. package/dist/plugins/remote-env-ssh.js +60 -59
  351. package/dist/plugins/remote-shell.d.ts +98 -1
  352. package/dist/plugins/remote-shell.js +218 -0
  353. package/dist/plugins/replica-registration.d.ts +1 -1
  354. package/dist/plugins/replica-registration.js +1 -1
  355. package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
  356. package/dist/plugins/resume-anchor-store-sql.js +12 -5
  357. package/dist/plugins/retention-lane-store-sql.js +4 -0
  358. package/dist/plugins/retention-sql.d.ts +20 -2
  359. package/dist/plugins/retention-sql.js +11 -0
  360. package/dist/plugins/run-store-sql.d.ts +21 -2
  361. package/dist/plugins/run-store-sql.js +31 -7
  362. package/dist/plugins/s3-presign.d.ts +23 -0
  363. package/dist/plugins/s3-presign.js +37 -3
  364. package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
  365. package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
  366. package/dist/plugins/scheduler-support.d.ts +2 -2
  367. package/dist/plugins/scheduler-support.js +0 -3
  368. package/dist/plugins/schema-consistency.d.ts +4 -2
  369. package/dist/plugins/schema-consistency.js +19 -2
  370. package/dist/plugins/schema-indexes.js +2 -0
  371. package/dist/plugins/send-file-ledger.d.ts +2 -2
  372. package/dist/plugins/send-file-ledger.js +5 -2
  373. package/dist/plugins/send-user-file.d.ts +3 -4
  374. package/dist/plugins/send-user-file.js +56 -52
  375. package/dist/plugins/serving-requirement.d.ts +26 -7
  376. package/dist/plugins/serving-requirement.js +11 -4
  377. package/dist/plugins/session-birth.d.ts +6 -2
  378. package/dist/plugins/session-blob-claim-token.d.ts +15 -0
  379. package/dist/plugins/session-blob-claim-token.js +20 -0
  380. package/dist/plugins/session-blob-namespace.d.ts +46 -0
  381. package/dist/plugins/session-blob-namespace.js +116 -0
  382. package/dist/plugins/session-capture-record-store-sql.js +2 -0
  383. package/dist/plugins/session-ext-table.d.ts +14 -1
  384. package/dist/plugins/session-ext-table.js +5 -1
  385. package/dist/plugins/session-row-sql.d.ts +49 -2
  386. package/dist/plugins/session-row-sql.js +56 -13
  387. package/dist/plugins/session-store-sql.d.ts +34 -18
  388. package/dist/plugins/session-store-sql.js +98 -17
  389. package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
  390. package/dist/plugins/shared-memory-store-sql.js +6 -2
  391. package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
  392. package/dist/plugins/snapshot-bucket-presence.js +8 -2
  393. package/dist/plugins/sql-driver.d.ts +2 -1
  394. package/dist/plugins/sql-driver.js +18 -3
  395. package/dist/plugins/sql-errors.d.ts +11 -6
  396. package/dist/plugins/sql-errors.js +5 -6
  397. package/dist/plugins/sql-json-column.d.ts +1 -1
  398. package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
  399. package/dist/plugins/stop-then-start-sentence.js +14 -10
  400. package/dist/plugins/stop-then-start.d.ts +109 -0
  401. package/dist/plugins/stop-then-start.js +104 -0
  402. package/dist/plugins/store-backend.d.ts +84 -15
  403. package/dist/plugins/store-backend.js +236 -72
  404. package/dist/plugins/store-boundary.d.ts +57 -0
  405. package/dist/plugins/store-boundary.js +139 -0
  406. package/dist/plugins/store-contracts.d.ts +17 -0
  407. package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
  408. package/dist/plugins/store-fault-sentence-m53.js +25 -0
  409. package/dist/plugins/store-fault.d.ts +26 -7
  410. package/dist/plugins/store-fault.js +18 -2
  411. package/dist/plugins/task-attachment-store.d.ts +2 -1
  412. package/dist/plugins/task-attachment-store.js +14 -1
  413. package/dist/plugins/task-list-store-sql.d.ts +2 -2
  414. package/dist/plugins/task-list-store-sql.js +10 -8
  415. package/dist/plugins/tidb-cost-quota.js +4 -0
  416. package/dist/plugins/tidb-pool.js +21 -25
  417. package/dist/plugins/tidb-rate-limiter.js +4 -0
  418. package/dist/plugins/user-input-ledger-sql.js +4 -0
  419. package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
  420. package/dist/plugins/workflow-run-store-sql.js +64 -4
  421. package/dist/plugins/workspace-custody.d.ts +4 -3
  422. package/dist/plugins/workspace-fill.d.ts +4 -7
  423. package/dist/plugins/workspace-fill.js +2 -1
  424. package/dist/plugins/write-behind-counter.js +5 -0
  425. package/dist/project-context.d.ts +0 -2
  426. package/dist/project-context.js +4 -8
  427. package/dist/project-registry.d.ts +46 -0
  428. package/dist/project-registry.js +44 -0
  429. package/dist/question.d.ts +2 -1
  430. package/dist/question.js +5 -13
  431. package/dist/request-form.d.ts +6 -1
  432. package/dist/request-form.js +4 -1
  433. package/dist/request-key-closure.js +1 -1
  434. package/dist/request-value-closure.d.ts +4 -0
  435. package/dist/request-value-closure.js +10 -0
  436. package/dist/rule-issue-reading.d.ts +1 -1
  437. package/dist/rules-consent.d.ts +1 -1
  438. package/dist/run-acceptance.d.ts +3 -2
  439. package/dist/run-acceptance.js +4 -6
  440. package/dist/run-local.js +9 -9
  441. package/dist/runs.d.ts +54 -16
  442. package/dist/runs.js +67 -13
  443. package/dist/runtime-governance.d.ts +5 -4
  444. package/dist/security.d.ts +30 -32
  445. package/dist/security.js +41 -7
  446. package/dist/sema-config-dir.d.ts +2 -1
  447. package/dist/server-secret-env.d.ts +12 -10
  448. package/dist/server-secret-env.js +24 -15
  449. package/dist/session-bindings.d.ts +82 -0
  450. package/dist/session-bindings.js +18 -0
  451. package/dist/session-children-retire.d.ts +2 -2
  452. package/dist/session-children-retire.js +2 -6
  453. package/dist/session-deletion.d.ts +16 -1
  454. package/dist/session-error-wire.d.ts +3 -3
  455. package/dist/session-error-wire.js +3 -3
  456. package/dist/session-incarnation.d.ts +10 -0
  457. package/dist/session-incarnation.js +10 -1
  458. package/dist/session-kind.d.ts +57 -0
  459. package/dist/session-kind.js +22 -0
  460. package/dist/session-row.d.ts +21 -1
  461. package/dist/session-row.js +7 -1
  462. package/dist/session-sync-kernel.d.ts +24 -14
  463. package/dist/session-sync-kernel.js +3 -6
  464. package/dist/session-sync.d.ts +25 -103
  465. package/dist/session-sync.js +14 -76
  466. package/dist/session-titler.d.ts +10 -3
  467. package/dist/session-titler.js +19 -6
  468. package/dist/ssh-host-key.d.ts +5 -0
  469. package/dist/ssh-host-key.js +3 -0
  470. package/dist/stores-sql/blob-index-sql.d.ts +30 -9
  471. package/dist/stores-sql/blob-index-sql.js +40 -21
  472. package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
  473. package/dist/stores-sql/checkpoint-store-sql.js +70 -146
  474. package/dist/stores-sql/file-history-store-sql.d.ts +113 -15
  475. package/dist/stores-sql/file-history-store-sql.js +205 -95
  476. package/dist/stores-sql/pg-session-storage.d.ts +34 -7
  477. package/dist/stores-sql/pg-session-storage.js +37 -13
  478. package/dist/stores-sql/retention-store-sql.d.ts +1 -9
  479. package/dist/stores-sql/retention-store-sql.js +5 -19
  480. package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
  481. package/dist/stores-sql/session-policy-store-sql.js +61 -44
  482. package/dist/stores-sql/session-write-hooks.d.ts +11 -0
  483. package/dist/stores-sql/tidb-session-store.d.ts +58 -7
  484. package/dist/stores-sql/tidb-session-store.js +37 -13
  485. package/dist/submission-exit.d.ts +3 -2
  486. package/dist/submission-exit.js +9 -1
  487. package/dist/task-cwd.d.ts +2 -2
  488. package/dist/task-settings.d.ts +7 -5
  489. package/dist/task-settings.js +3 -3
  490. package/dist/terminal.d.ts +33 -2
  491. package/dist/terminal.js +139 -9
  492. package/dist/tool-approval.d.ts +465 -507
  493. package/dist/tool-approval.js +606 -1222
  494. package/dist/trace/core-keyset-guard.d.ts +1 -1
  495. package/dist/trace/ledger-events.d.ts +3 -3
  496. package/dist/trace/project.d.ts +2 -3
  497. package/dist/trace/redact.js +3 -2
  498. package/dist/trace/self-minted-wire.d.ts +571 -178
  499. package/dist/trace/self-minted-wire.js +189 -56
  500. package/dist/web-admin-client/apply-effective.js +2 -2
  501. package/dist/web-admin-client/read-warnings.d.ts +2 -2
  502. package/dist/web-admin-client/read-warnings.js +1 -1
  503. package/dist/web-admin-client/types.d.ts +1 -1
  504. package/dist/workspace-space.d.ts +10 -4
  505. package/dist/workspace-space.js +4 -1
  506. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +79 -28
  507. package/package.json +7 -3
  508. package/scripts/embed-minimal.mjs +3 -3
  509. package/wire-changes/server@7.151.0.json +762 -0
  510. package/wire-changes/server@7.152.0.json +900 -0
  511. package/dist/config-d-migration.d.ts +0 -37
  512. package/dist/config-d-migration.js +0 -60
  513. package/dist/http/session-inherit-env.d.ts +0 -36
  514. package/dist/http/session-inherit-env.js +0 -6
@@ -1,16 +1,18 @@
1
1
  import { redactErrorMessage, redactHead } from "../observability/run-terminal.js";
2
2
  import { createHash } from "node:crypto";
3
3
  import { uuidv7, resumeWithVerification, resumeCascade, CheckpointError, judgeCheckpointRow, defaultTaskRegistry, taskNotificationDedupKey, validatePendingSteer, GLOBAL_USAGE_KEY } from "@sema-agent/core";
4
- import { decideParkedAgent, deliverToHoldingRun, denyWorkflowParkForked, denyWorkflowParksUnreadable, findParkOrigin, heldWorkflowParkDecisions, planWorkflowParkedDecide } from "../parked-decide.js";
4
+ import { answerOfHolderFence, answerOfHolderRedeem, decideParkedAgent, deliverableEntryOf, denyWorkflowParkForked, denyWorkflowParksUnreadable, findParkOrigin, heldWorkflowParkDecisions, holderFenceFaultAnswer, planWorkflowParkedDecide, redeemHere, runChannelEnded, workflowParkGuidance } from "../parked-decide.js";
5
5
  import { parkDecisionFingerprint } from "../orchestration/workflow-park-decision.js";
6
- import { runFactsOf, sealRouteDeps, sessionFactsReadOf } from "./owner-access.js";
6
+ import { heldParksOf, readRunParks } from "../orchestration/workflow-agent-session-index.js";
7
+ import { isAdoptionQuiescing, trackMaintenanceLeg } from "../adoption/quiesce.js";
8
+ import { runFactsOf, sealRouteDeps, sessionFactsReadOf, sessionOccupantReadOf } from "./owner-access.js";
7
9
  import { createSessionWorkspaceRecorder, sessionWorkspaceStoreOf } from "../session-workspace.js";
8
10
  const DELIVERY_NOT_RECORDED = "workflow park decide: this delivery no longer holds the host session (its claim was released) — the decision was not recorded and this delivery was not started";
9
- import { HttpError, checkpointPartsOf, decodeCheckpointScope, scopeCellOf, CHECKPOINT_PUBLIC_SCOPE } from "../security.js";
11
+ import { HttpError, checkpointPartsOf, decodeCheckpointScope, ownerOfCheckpointScope, scopeCellOf, CHECKPOINT_PUBLIC_SCOPE } from "../security.js";
10
12
  import { keyAdmits } from "../owner-faces.js";
11
13
  import { personOf } from "../owner-brands.js";
12
14
  import { recoveredSubject } from "../owner-faces.js";
13
- import { beatRunHeartbeat, graftParkToolCallId, heldParkOf, parkToolCallId, TurnAnchorCapture, HEARTBEAT_MS, markChildrenStoppedByUserOnAbort, voidHeldParkCard } from "../runs.js";
15
+ import { beatRunHeartbeat, createRunAnchorWriter, graftParkToolCallId, heldParkOf, parkToolCallId, TurnAnchorCapture, HEARTBEAT_MS, markChildrenStoppedByUserOnAbort, voidHeldParkCard } from "../runs.js";
14
16
  import { commitParkRow } from "../park-row-commit.js";
15
17
  import { atHostBoundary, failureCodeOf, nestedPauseOf, sealResultForExit, outwardPlane, outwardThrownMessage } from "../terminal.js";
16
18
  import { voidVerifierPauseCard } from "../verifier-pause-card.js";
@@ -22,7 +24,7 @@ import { emitPendingWorkflowCompletions, taskNotificationInboxEntry, taskNotific
22
24
  import { fleetRunPublisher, fleetRunLabels, fleetRunResiduals } from "../fleet/fleet-bus.js";
23
25
  import { defaultSubagentTailBus } from "../fleet/subagent-tail-bus.js";
24
26
  import { currentApprovalGateToken, currentGateFacesOf, sightsCurrentGate } from "../approval-gate-currency.js";
25
- import { approverFacingArgs, declaredApprovalFrameFamilies, parkRowStandingAnswerFacts, resolveApprovalLeg, resolveStreamApprovalGate, standingAnswerDurablyRecordable } from "../tool-approval.js";
27
+ import { approverFacingArgs, declaredApprovalFrameFamilies, parkRowStandingAnswerFacts, readCardRuleRecordOfAskRow, readCardRuleRecordOfParkRow, redeemCardRule, resolveApprovalLeg, resolveStreamApprovalGate, standingAnswerDurablyRecordable } from "../tool-approval.js";
26
28
  import { createHitlTransport } from "../hitl-delivery.js";
27
29
  import { buildCheckpointAnchorHash } from "../approval-ask-audit-store.js";
28
30
  import { APPROVAL_ENDING_CAUSES } from "../approval-deny-reasons.js";
@@ -60,7 +62,7 @@ import { buildActiveRunConflict, resumeEntryForGate } from "./active-run-conflic
60
62
  import { refusalAfterLostClaim } from "./claim-heartbeat.js";
61
63
  import { CONTINUATION_CLAIM_FACE, ClaimFaultAnswer, commitExecutionContext, faultedAnswerOf, isRootSessionGoneError, resolveBeforeClaim, rootSessionAbsentAnswer, stampSpecRoot, withdrawClaim } from "./execution-context.js";
62
64
  import { timeClaim } from "./claim-latency.js";
63
- import { commitSessionInheritEnv } from "./session-inherit-env.js";
65
+ import { commitLegBindings } from "../session-bindings.js";
64
66
  import { ASK_USER_QUESTION_TOOL_NAME, isApprovalGateKind, isEngineQuestionRow } from "../approval-content-kind.js";
65
67
  import { deploymentListAsks } from "../approval.js";
66
68
  import { isParkLedgerEventType } from "../trace/ledger-events.js";
@@ -70,11 +72,18 @@ import { buildCheckpointVersionKeys, resumeAssemblyRefusalAnswer, resumeRefusalW
70
72
  import { refusalBody, resumeRefusalFacts } from "./refusal-body.js";
71
73
  import { storedBodyReplayRefusal } from "./stored-body-replay.js";
72
74
  import { restateResumeCtx } from "./resume-restatement.js";
75
+ import { stampReplayEntryMode, withStoredPermissionMode } from "../permission-mode-admission.js";
73
76
  import { httpErrorRefusal } from "./send.js";
74
77
  import { createRunAcceptance } from "../run-acceptance.js";
75
78
  import { createSubmissionSeat } from "../submission-exit.js";
76
79
  import { fieldConflictFacts } from "../field-conflict.js";
77
80
  import { createSessionNotifyDoor } from "../session-notify-door.js";
81
+ const HANDOFF_RETRY_CODES = new Set(["conflict.session_active_run", "not_found.parked_checkpoint", "conflict.claim_lost"]);
82
+ function handoffResultOf(refusal, refusedWhy) {
83
+ const errorCode = "errorCode" in refusal.body ? refusal.body.errorCode : undefined;
84
+ const code = typeof errorCode === "string" ? errorCode : `status_${refusal.status}`;
85
+ return refusal.status >= 500 || HANDOFF_RETRY_CODES.has(code) ? { kind: "retry", why: code } : { kind: "refused", why: refusedWhy ?? code };
86
+ }
78
87
  function compositionUnlinkedAnswer() {
79
88
  return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context does not match this card — the run is a cascade but the card records no ladder rung, so the ladder cannot be continued" }) };
80
89
  }
@@ -210,6 +219,35 @@ function decisionRefusalCauseOf(e, gate) {
210
219
  function notResumableAnswer() {
211
220
  return { status: 409, body: refusalBody({ errorCode: "conflict.not_resumable", message: "run is not in a resumable (suspended) state (already resumed, decided, or expired)" }) };
212
221
  }
222
+ function planeOfEndedRow(row) {
223
+ return { status: row?.status ?? "failed", errorCode: row?.errorCode ?? undefined, errorMessage: row?.error ?? undefined };
224
+ }
225
+ async function landedTerminalRow(runStore, taskId, arm) {
226
+ let row;
227
+ try {
228
+ row = await runStore.getRun(taskId);
229
+ }
230
+ catch (e) {
231
+ recordFailOpen("server.resume.cancel-answer-row-unreadable", `task=${taskId} arm=${arm} err=${errorText(e)}`);
232
+ return undefined;
233
+ }
234
+ return row !== undefined && isTerminalRunStatus(row.status) ? row : undefined;
235
+ }
236
+ function settledLegAnswer(o) {
237
+ return {
238
+ status: 200,
239
+ body: {
240
+ ...(o.taskId !== undefined ? { taskId: o.taskId } : {}),
241
+ sessionId: o.sessionId,
242
+ status: o.plane.status,
243
+ bindingEnforced: true,
244
+ ...(o.plane.errorCode ? { errorCode: o.plane.errorCode } : {}),
245
+ ...(o.plane.errorMessage ? { errorMessage: redactErrorMessage(o.plane.errorMessage) ?? "" } : {}),
246
+ ...(o.reparked ? { retriable: true } : {}),
247
+ ...o.evidence,
248
+ },
249
+ };
250
+ }
213
251
  function resumeClaimFaultAnswerOf(e) {
214
252
  return faultedAnswerOf(e, CONTINUATION_CLAIM_FACE.faulted);
215
253
  }
@@ -270,7 +308,7 @@ function acceptableFormFacts(detail) {
270
308
  const rewritten = detail !== null && typeof detail === "object" ? detail.editRewritten : undefined;
271
309
  if (rewritten === null || typeof rewritten !== "object" || !Object.hasOwn(rewritten, "acceptableForm"))
272
310
  return {};
273
- const shown = approverFacingArgs(rewritten.acceptableForm);
311
+ const shown = approverFacingArgs(rewritten.acceptableForm, undefined);
274
312
  return shown === undefined ? {} : { acceptableForm: shown };
275
313
  }
276
314
  export function checkpointRefusalAnswer(e, at) {
@@ -302,6 +340,12 @@ export function decidedActionOf(binding) {
302
340
  export function createResumeLegs(ctx) {
303
341
  const { deps, runnerFor, idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters, readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, admitRun, safeDecode, prepareSpec, finalizeTaskResult, ownerCostQuotaDenied, ownerFleetLeaseDenied, usageWindowDenialFor } = ctx;
304
342
  const ctxOpening = (sessionId) => ({ sessionId, opener: deps.checkpointCtxSealing });
343
+ const replayCtxOf = (stored, restatement) => {
344
+ const restated = restateResumeCtx(stored, restatement);
345
+ if (restated.unattendedLeg === true)
346
+ return restated;
347
+ return stampReplayEntryMode(restated, deps.config);
348
+ };
305
349
  const resumeFleetScope = (req, auth) => req ? (gatedSubject(req, deps.config) ?? "default") : (auth.subject ?? "default");
306
350
  function createRememberIntent(sessionId, remember) {
307
351
  let pending;
@@ -327,9 +371,23 @@ export function createResumeLegs(ctx) {
327
371
  },
328
372
  };
329
373
  }
330
- async function resumeCheckpoint(sessionId, decision, reason, hostDecision, req, answer, binding, remember, acceptEarly, decider, restatement) {
374
+ function createRuleIntent(persistRule) {
375
+ let reading;
376
+ return {
377
+ record: (r) => {
378
+ reading = r;
379
+ },
380
+ settle: async (committed) => {
381
+ if (!committed || reading === undefined)
382
+ return { rulePersisted: false, ruleRefusal: "rule_lane_unavailable" };
383
+ return redeemCardRule(deps.ruleConsent, reading, persistRule.slot, { inputWasEdited: persistRule.inputWasEdited, eligible: true });
384
+ },
385
+ };
386
+ }
387
+ async function resumeCheckpoint(sessionId, decision, reason, hostDecision, req, answer, binding, remember, acceptEarly, decider, restatement, persistRule) {
331
388
  const cs = deps.checkpointStore;
332
389
  const intent = remember !== undefined ? createRememberIntent(sessionId, remember) : undefined;
390
+ const ruleIntent = persistRule !== undefined ? createRuleIntent(persistRule) : undefined;
333
391
  const token = await currentApprovalGateToken(cs, sessionId);
334
392
  if (binding.checkpointToken && !sightsCurrentGate({ face: "checkpointToken", value: binding.checkpointToken }, token ? { checkpointToken: token } : null)) {
335
393
  let seenUnreadable = false;
@@ -460,12 +518,36 @@ export function createResumeLegs(ctx) {
460
518
  return approvalStaleAnswer(s57CurrentPending ? { currentPending: s57CurrentPending } : {});
461
519
  }
462
520
  const paForGrant = cp.pendingAction.kind === "tool_approval" ? cp.pendingAction : undefined;
521
+ const parkFacts = paForGrant !== undefined && paForGrant.toolName ? parkRowStandingAnswerFacts(paForGrant, cp.gate, deps.config, deploymentListAsks(deps.config, { toolName: paForGrant.toolName })) : undefined;
463
522
  const rememberableTool = paForGrant !== undefined &&
464
- paForGrant.toolName &&
523
+ parkFacts !== undefined &&
465
524
  paForGrant.toolName !== ASK_USER_QUESTION_TOOL_NAME &&
466
- standingAnswerDurablyRecordable(parkRowStandingAnswerFacts(paForGrant, cp.gate, deps.config, deploymentListAsks(deps.config, { toolName: paForGrant.toolName })))
525
+ standingAnswerDurablyRecordable(parkFacts)
467
526
  ? paForGrant.toolName
468
527
  : null;
528
+ if (ruleIntent !== undefined) {
529
+ const owner = ownerOfCheckpointScope(cp.scope);
530
+ if (paForGrant === undefined || parkFacts === undefined || !token || !paForGrant.toolCallId || !paForGrant.boundInputHash)
531
+ ruleIntent.record({ kind: "absent", refusal: "rule_material_absent" });
532
+ else {
533
+ const asked = deps.toolApproval !== undefined ? await deps.toolApproval.readParkedAskOfGate(cp.sessionId, { boundCallId: paForGrant.toolCallId, boundInputHash: paForGrant.boundInputHash }) : { kind: "none" };
534
+ switch (asked.kind) {
535
+ case "row":
536
+ ruleIntent.record(readCardRuleRecordOfAskRow(asked.row, owner));
537
+ break;
538
+ case "unreadable":
539
+ ruleIntent.record({ kind: "absent", refusal: "rule_store_error" });
540
+ break;
541
+ case "none":
542
+ ruleIntent.record(readCardRuleRecordOfParkRow(paForGrant, { owner, governanceForced: parkFacts.governanceForced, scopeRoot: await cs.cardScopeRootOf(token) }));
543
+ break;
544
+ default: {
545
+ const unhandled = asked;
546
+ throw new Error(`resumeCheckpoint: unhandled parked-ask reading ${JSON.stringify(unhandled)}`);
547
+ }
548
+ }
549
+ }
550
+ }
469
551
  const boundGrant = intent
470
552
  ? (overrideSessionId) => intent.record({ ...(overrideSessionId !== undefined ? { overrideSessionId } : {}), rememberableToolName: rememberableTool })
471
553
  : undefined;
@@ -490,7 +572,11 @@ export function createResumeLegs(ctx) {
490
572
  const landAfterCommit = async (out) => {
491
573
  const committed = decisionCommittedOf(out);
492
574
  noteLateSettleIfAccepted(committed);
493
- return intent === undefined ? out : { ...out, rememberApplied: await intent.settle(committed) };
575
+ return {
576
+ ...out,
577
+ ...(intent !== undefined ? { rememberApplied: await intent.settle(committed) } : {}),
578
+ ...(ruleIntent !== undefined ? { ruleReceipt: await ruleIntent.settle(committed) } : {}),
579
+ };
494
580
  };
495
581
  const parkedForkQuotaDenial = req !== undefined ? ownerCostQuotaDenied(checkpointPartsOf(cp.scope)?.person) : undefined;
496
582
  if (parkedForkQuotaDenial)
@@ -569,73 +655,56 @@ export function createResumeLegs(ctx) {
569
655
  if (!plan.ok)
570
656
  return plan.deny;
571
657
  const fingerprint = parkDecisionFingerprint(plan.outcome, restatement);
572
- const live = await deliverToHoldingRun(origin, { token, outcome: plan.outcome, decision: parkedReq.decision, fingerprint, restated: restatement !== undefined });
573
- if (live.kind === "answered")
574
- return live.answer;
575
658
  const decisions = deps.workflowParkDecisions;
576
- const runStore = deps.runStore;
577
- if (decisions === undefined || runStore === undefined) {
659
+ if (decisions === undefined || deps.runStore === undefined) {
578
660
  return { status: 501, body: refusalBody({ errorCode: "capability.run_store_required", message: "delivering this decision requires a durable run store (DB_BACKEND=mysql|pg|local)" }) };
579
661
  }
580
- const liveReceiptOf = async (held) => {
581
- if (held === null || held.fingerprint !== fingerprint)
582
- return undefined;
583
- const run = await runFactsOf(runStore, held.deliveredTaskId);
584
- return run != null && !isTerminalRunStatus(run.status) ? acceptedResumingReceipt(held.deliveredTaskId, held.hostSessionId, NO_SETTLEMENT_EVIDENCE) : undefined;
585
- };
586
- const replay = await liveReceiptOf(await decisions.get(token));
587
- if (replay !== undefined)
588
- return replay;
589
- let recordFailure;
590
- const answerOfRecordFailure = async (failed) => {
591
- if (failed.kind === "faulted")
592
- return faultedAnswerOf(failed.err, CONTINUATION_CLAIM_FACE.faulted);
662
+ if (origin.run.status === "running") {
663
+ let verdict;
593
664
  try {
594
- return await refusalAfterLostClaim(deps, runStore, plan.hostSessionId, failed.deliveredTaskId);
665
+ verdict = await decisions.recordForRunningHolder({ token, runId: plan.runId, hostSessionId: plan.hostSessionId, outcome: plan.outcome, fingerprint, deliveredTaskId: plan.runId, acceptedAtMs: Date.now() }, { restated: restatement !== undefined });
595
666
  }
596
- catch (e) {
597
- return faultedAnswerOf(e, CONTINUATION_CLAIM_FACE.faulted);
667
+ catch (err) {
668
+ return faultedAnswerOf(err, () => holderFenceFaultAnswer(plan.runId));
598
669
  }
599
- };
600
- const delivery = {
601
- carried: [{ runId: plan.runId, token, outcome: plan.outcome }],
602
- commitBeforeLaunch: async (deliveredTaskId) => {
603
- let recorded;
604
- try {
605
- recorded = await decisions.record({ token, runId: plan.runId, hostSessionId: plan.hostSessionId, outcome: plan.outcome, fingerprint, deliveredTaskId, acceptedAtMs: Date.now() });
606
- }
607
- catch (err) {
608
- recordFailure = { kind: "faulted", err };
609
- throw err;
610
- }
611
- if (!recorded) {
612
- recordFailure = { kind: "not_recorded", deliveredTaskId };
613
- throw new Error(DELIVERY_NOT_RECORDED);
670
+ switch (verdict) {
671
+ case "not_running":
672
+ break;
673
+ case "not_held":
674
+ case "restated":
675
+ case "other_decision":
676
+ return answerOfHolderFence(verdict, plan.runId);
677
+ case "stands":
678
+ return answerOfHolderRedeem(await redeemHere(plan.runId, origin.run.scope, { token, outcome: plan.outcome }), plan.runId, parkedReq.decision);
679
+ default: {
680
+ const unhandled = verdict;
681
+ throw new Error(`unhandled workflow holder fence verdict: ${String(unhandled)}`);
614
682
  }
615
- },
616
- };
617
- const hostToken = await cs
618
- .findPendingTokenBySession(plan.hostSessionId, undefined, { gateKinds: TERMINAL_PARK_GATE_KINDS, pick: "oldest" })
619
- .catch(() => undefined);
620
- const admittedPayer = decodeCheckpointScope(cp.scope);
621
- let out;
622
- try {
623
- out = hostToken
624
- ? await resumeWake(plan.hostSessionId, plan.message, decider?.subject, req, acceptEarly, delivery, admittedPayer, restatement)
625
- : await startFreshHostTurn(plan.hostSessionId, plan.message.text, admittedPayer, req, delivery, plan.runId, restatement);
683
+ }
626
684
  }
627
- catch (err) {
628
- const failed = recordFailure;
629
- if (failed === undefined)
630
- throw err;
631
- return await answerOfRecordFailure(failed);
685
+ const laned = await deliverViaResumeLane({
686
+ hostSessionId: plan.hostSessionId,
687
+ runId: plan.runId,
688
+ runScope: origin.run.scope,
689
+ token,
690
+ outcome: plan.outcome,
691
+ fingerprint,
692
+ message: plan.message,
693
+ ...(restatement !== undefined ? { restatement } : {}),
694
+ initiator: { kind: "decide", req, caller: decider?.subject, ...(acceptEarly === true ? { acceptEarly: true } : {}), admittedPayer: decodeCheckpointScope(cp.scope) },
695
+ });
696
+ switch (laned.kind) {
697
+ case "launched":
698
+ case "replayed":
699
+ case "refused":
700
+ return laned.out;
701
+ case "record_failed":
702
+ return await answerOfRecordFailure(laned.failure, plan.hostSessionId);
703
+ default: {
704
+ const unhandled = laned;
705
+ throw new Error(`unhandled resume lane delivery: ${JSON.stringify(unhandled)}`);
706
+ }
632
707
  }
633
- const failed = recordFailure;
634
- if (failed !== undefined)
635
- return await answerOfRecordFailure(failed);
636
- if (acceptedTaskIdOf(out) === undefined)
637
- return (await liveReceiptOf(await decisions.get(token))) ?? out;
638
- return out;
639
708
  }
640
709
  }
641
710
  const runCtx = await ctxPromise;
@@ -644,7 +713,7 @@ export function createResumeLegs(ctx) {
644
713
  if (runCtx === undefined || runCtx.ctx === null)
645
714
  return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
646
715
  const { runSessionId, ctx: storedCtx } = runCtx;
647
- const ctx = restateResumeCtx(storedCtx, restatement);
716
+ const ctx = replayCtxOf(storedCtx, restatement);
648
717
  const auth = { sessionId: runSessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
649
718
  const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
650
719
  if (!resolved.ok)
@@ -691,6 +760,7 @@ export function createResumeLegs(ctx) {
691
760
  onNotice: (n) => engineNotices.push(n),
692
761
  ...(ctx.unattendedLeg === true ? { unattendedLeg: true } : {}),
693
762
  ...(ctx.projectContext !== undefined ? { projectContext: ctx.projectContext } : {}),
763
+ ...(ctx.memorySeed !== undefined ? { memorySeed: ctx.memorySeed } : {}),
694
764
  lease,
695
765
  execution,
696
766
  });
@@ -771,7 +841,6 @@ export function createResumeLegs(ctx) {
771
841
  const legKey = createHash("sha256").update(String(token)).digest("hex");
772
842
  const streamApprovalOn = resolveStreamApprovalGate({
773
843
  toolApprovalEnabled: Boolean(deps.toolApproval),
774
- streamApprovalEnabled: deps.config.streamApproval?.enabled === true,
775
844
  backend: deps.backend,
776
845
  checkpointStore: deps.checkpointStore,
777
846
  }).active;
@@ -797,7 +866,7 @@ export function createResumeLegs(ctx) {
797
866
  let legClaim;
798
867
  let engineHandedOff = false;
799
868
  let restored;
800
- const cancelledInClaimWindow = () => restored?.kind === "ended" && restored.row?.errorCode === CANCELLED_CODE;
869
+ const claimWindowCancelRow = () => (restored?.kind === "ended" && restored.row?.errorCode === CANCELLED_CODE ? restored.row : undefined);
801
870
  if (args.mintFreshRun && taskId && deps.runStore) {
802
871
  return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, sessionId, taskId) };
803
872
  }
@@ -948,7 +1017,8 @@ export function createResumeLegs(ctx) {
948
1017
  if (placementReject) {
949
1018
  if (inflightRuns.get(claimedTask) === cancelCtrl)
950
1019
  inflightRuns.delete(claimedTask);
951
- return cancelledInClaimWindow() ? { status: 200, body: { taskId: claimedTask, sessionId, status: "failed", errorCode: "cancelled" } } : placementReject;
1020
+ const cancelledRow = claimWindowCancelRow();
1021
+ return cancelledRow !== undefined ? settledLegAnswer({ taskId: claimedTask, sessionId, plane: planeOfEndedRow(cancelledRow), reparked: false, evidence: NO_SETTLEMENT_EVIDENCE }) : placementReject;
952
1022
  }
953
1023
  }
954
1024
  markChildrenStoppedByUserOnAbort(cancelCtrl.signal, taskId, subject);
@@ -979,7 +1049,7 @@ export function createResumeLegs(ctx) {
979
1049
  ...heldDecisions,
980
1050
  ...(workflowDecision !== undefined && taskId !== undefined ? { afterCheckpointResolve: () => workflowDecision.commitBeforeLaunch(taskId) } : {}),
981
1051
  };
982
- commitSessionInheritEnv(deps, sessionId, resumeCtx.ctx.body);
1052
+ commitLegBindings(deps, undefined, sessionId, args.legFacts?.sessionBindings);
983
1053
  if (args.onResumeCommitted)
984
1054
  await args.onResumeCommitted();
985
1055
  let unregisterEngineNotice;
@@ -1036,7 +1106,7 @@ export function createResumeLegs(ctx) {
1036
1106
  const verifyTailContentMode = resumeTaskConfig.forwardSubagentEvents === true ? "on" : "progress_only";
1037
1107
  const verifyInternals = {
1038
1108
  ...launchInternals,
1039
- ...compositionLegRoot(args.legFacts?.registeredCwd),
1109
+ ...compositionLegRoot(args.legFacts?.sessionBindings.cwd),
1040
1110
  ...(taskId ? { onActivity: () => recordTurnActivity(taskId) } : {}),
1041
1111
  onForwardEvent: (e) => {
1042
1112
  fleetPub?.onForwardEvent(e);
@@ -1148,15 +1218,18 @@ export function createResumeLegs(ctx) {
1148
1218
  const append = (type, data) => (rs && taskId ? serialAppend(type, data) : Promise.resolve());
1149
1219
  cancelLedgerAppend = append;
1150
1220
  await openEngineNoticePort(append);
1151
- const anchorOwner = subject ?? null;
1152
1221
  const sessionFactsOf = sessionFactsReadOf(deps.sessionStorage);
1153
- const captureTurnAnchor = deps.resumeAnchorStore && sessionFactsOf
1154
- ? async (eventId) => { const leaf = (await sessionFactsOf(sessionId))?.leafId; if (leaf)
1155
- await deps.resumeAnchorStore.put(sessionId, eventId, leaf, anchorOwner); }
1156
- : undefined;
1157
- const captureUserMessageAnchor = deps.resumeAnchorStore && taskId && freshRunClaimed
1158
- ? async (entryId) => { await deps.resumeAnchorStore.put(sessionId, taskId, entryId, anchorOwner); }
1159
- : undefined;
1222
+ const anchors = createRunAnchorWriter({
1223
+ seat: deps.backend?.landedAttendants(),
1224
+ sessionId,
1225
+ owner: subject ?? null,
1226
+ promptKey: taskId && freshRunClaimed ? taskId : undefined,
1227
+ witness: args.legFacts?.sessionWitness,
1228
+ occupantOf: sessionOccupantReadOf(deps.sessionStorage),
1229
+ leafOf: sessionFactsOf === undefined ? undefined : async (id) => (await sessionFactsOf(id))?.leafId,
1230
+ });
1231
+ const captureTurnAnchor = anchors.turn;
1232
+ const captureUserMessageAnchor = anchors.prompt;
1160
1233
  const anchor = new TurnAnchorCapture(captureTurnAnchor, "resume", captureUserMessageAnchor);
1161
1234
  const flush = async () => {
1162
1235
  if (reasoning) {
@@ -1430,16 +1503,19 @@ export function createResumeLegs(ctx) {
1430
1503
  const disposition = resumeRefusalDisposition(e);
1431
1504
  if (disposition === "cancelled") {
1432
1505
  const abortedText = (await settleCardForCancel()) ? CARD_SETTLED_BY_CANCEL_MESSAGE : e.message;
1506
+ const handleCause = cancelCtrl.cause();
1507
+ if (handleCause === undefined)
1508
+ recordFailOpen("server.runs.abort-cause-missing", `task=${taskId ?? ""} arm=resume-aborted`);
1509
+ const c = mintCancelledResult({ taskId: taskId ?? "", sessionId, startedAtMs: resumeLegStartedAt, message: abortedText, cause: handleCause ?? "cancel_verb" });
1510
+ const cancelled = outwardPlane(c.terminal);
1511
+ let landed;
1433
1512
  if (claimedRow && taskId && deps.runStore) {
1434
- const handleCause = cancelCtrl.cause();
1435
- if (handleCause === undefined)
1436
- recordFailOpen("server.runs.abort-cause-missing", `task=${taskId} arm=resume-aborted`);
1437
- const c = mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: abortedText, cause: handleCause ?? "cancel_verb" });
1438
1513
  await cancelLedgerAppend?.("failed", buildCancelledLedgerRow(c)).catch((err) => recordFailOpen("server.runs.terminal-ledger-write-failed", `arm=resume-append-resume-aborted ${errorText(err)}`));
1439
- await deps.runStore.setTerminal(taskId, "failed", c, abortedText).catch(() => undefined);
1514
+ await deps.runStore.setTerminal(taskId, "failed", c, cancelled.errorMessage ?? null).catch(() => undefined);
1515
+ landed = await landedTerminalRow(deps.runStore, taskId, "resume-aborted");
1440
1516
  }
1441
1517
  settleFleet("failed");
1442
- return { status: 200, body: { taskId, sessionId, status: "failed", errorCode: "cancelled" } };
1518
+ return settledLegAnswer({ taskId, sessionId, plane: landed !== undefined ? planeOfEndedRow(landed) : cancelled, reparked: false, evidence: NO_SETTLEMENT_EVIDENCE });
1443
1519
  }
1444
1520
  const retriable = disposition === "retriable";
1445
1521
  let reparkEnded = false;
@@ -1466,22 +1542,26 @@ export function createResumeLegs(ctx) {
1466
1542
  }
1467
1543
  const thrownCause = cancelCtrl.cause();
1468
1544
  if (thrownCause !== undefined) {
1545
+ const c = mintCancelledResult({ taskId: taskId ?? "", sessionId, startedAtMs: resumeLegStartedAt, message: "cancelled by user", cause: thrownCause });
1546
+ const cancelled = outwardPlane(c.terminal);
1547
+ let landed;
1469
1548
  if (taskId && deps.runStore) {
1470
1549
  await voidHeldParkCard(heldPark, sessionId, deps.checkpointStore, "resume");
1471
- const c = mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: "cancelled by user", cause: thrownCause });
1472
1550
  await cancelLedgerAppend?.("failed", buildCancelledLedgerRow(c)).catch((err) => recordFailOpen("server.runs.terminal-ledger-write-failed", `arm=resume-append-thrown-cancel ${errorText(err)}`));
1473
- await deps.runStore.setTerminal(taskId, "failed", c, "cancelled by user").catch(() => undefined);
1551
+ await deps.runStore.setTerminal(taskId, "failed", c, cancelled.errorMessage ?? null).catch(() => undefined);
1552
+ landed = await landedTerminalRow(deps.runStore, taskId, "thrown-cancel");
1474
1553
  }
1475
1554
  settleFleet("failed");
1476
- return { status: 200, body: { taskId, sessionId, status: "failed", errorCode: "cancelled" } };
1555
+ return settledLegAnswer({ taskId, sessionId, plane: landed !== undefined ? planeOfEndedRow(landed) : cancelled, reparked: false, evidence: NO_SETTLEMENT_EVIDENCE });
1477
1556
  }
1478
1557
  if (!engineHandedOff && legClaim !== undefined) {
1479
1558
  const claim = legClaim;
1480
1559
  await withdrawClaim(deps, claim, `the resume could not be handed to the engine: ${outwardThrownMessage(e, errorText(e))}`, "faulted");
1481
1560
  const parkedAgain = claim.kind === "resumed" && restored?.kind !== "ended";
1482
1561
  settleFleet(parkedAgain ? reparkStatus : "failed");
1483
- if (cancelledInClaimWindow())
1484
- return { status: 200, body: { taskId, sessionId, status: "failed", errorCode: "cancelled" } };
1562
+ const cancelledRow = claimWindowCancelRow();
1563
+ if (cancelledRow !== undefined)
1564
+ return settledLegAnswer({ taskId, sessionId, plane: planeOfEndedRow(cancelledRow), reparked: false, evidence: NO_SETTLEMENT_EVIDENCE });
1485
1565
  return resumeClaimFaultAnswerOf(e);
1486
1566
  }
1487
1567
  const heldParkWord = heldPark === undefined ? undefined : heldParkOf(heldPark);
@@ -1536,20 +1616,13 @@ export function createResumeLegs(ctx) {
1536
1616
  await deps.runStore.setTerminal(taskId, resumePlane.status, sealed, resumePlane.errorMessage ?? null);
1537
1617
  }
1538
1618
  settleFleet(parkEnded !== undefined ? "failed" : checkpointReopened ? reparkStatus : resumePlane.status, fleetRunResiduals(sealed, sealed ? failureCodeOf(sealed.terminal) : undefined));
1539
- const answered = parkEnded !== undefined
1540
- ? { status: parkEnded.row?.status ?? "failed", errorCode: parkEnded.row?.errorCode ?? undefined, errorMessage: parkEnded.row?.error ?? undefined }
1541
- : { status: resumePlane.status, errorCode: resumePlane.errorCode, errorMessage: resumePlane.errorMessage };
1542
- return {
1543
- status: 200,
1544
- body: {
1545
- taskId, sessionId, status: answered.status,
1546
- bindingEnforced: true,
1547
- ...(answered.errorCode ? { errorCode: answered.errorCode } : {}),
1548
- ...(answered.errorMessage ? { errorMessage: redactErrorMessage(answered.errorMessage) ?? "" } : {}),
1549
- ...(checkpointReopened && parkEnded === undefined ? { retriable: true } : {}),
1550
- ...buildSettlementEvidence({ at: "engine_terminal", commitment: args.commitment }),
1551
- },
1552
- };
1619
+ return settledLegAnswer({
1620
+ taskId,
1621
+ sessionId,
1622
+ plane: parkEnded !== undefined ? planeOfEndedRow(parkEnded.row) : resumePlane,
1623
+ reparked: checkpointReopened && parkEnded === undefined,
1624
+ evidence: buildSettlementEvidence({ at: "engine_terminal", commitment: args.commitment }),
1625
+ });
1553
1626
  }
1554
1627
  async function mayDiscloseRowError(cs, token, decider) {
1555
1628
  if (decider === undefined || decider.operator)
@@ -1623,7 +1696,7 @@ export function createResumeLegs(ctx) {
1623
1696
  return resumeCtxUnreadableAnswer();
1624
1697
  if (ctxRead.kind === "absent")
1625
1698
  return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
1626
- const ctx = restateResumeCtx(ctxRead.ctx, restatement);
1699
+ const ctx = replayCtxOf(ctxRead.ctx, restatement);
1627
1700
  const auth = { sessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
1628
1701
  const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
1629
1702
  if (!resolved.ok)
@@ -1668,7 +1741,7 @@ export function createResumeLegs(ctx) {
1668
1741
  }),
1669
1742
  };
1670
1743
  }
1671
- const ctx = restateResumeCtx(storedCtx, restatement);
1744
+ const ctx = replayCtxOf(storedCtx, restatement);
1672
1745
  const windowDenial = await usageWindowDenialFor(subject === undefined ? undefined : personOf(recoveredSubject(subject)));
1673
1746
  if (windowDenial)
1674
1747
  return { status: windowDenial.status, body: windowDenial.body };
@@ -1680,7 +1753,7 @@ export function createResumeLegs(ctx) {
1680
1753
  const { spec, engineNotices } = resolved;
1681
1754
  const hostSpec = { ...spec, objective };
1682
1755
  const out = await mintAndDriveDurableRun(routeCtxBase, deps.runStore, {
1683
- prepared: { spec: hostSpec, runner: resolved.runner, legFacts: resolved.legFacts, auth, body: ctx.body, ...(objectiveWithheldIn(ctx) ? { bodyFromScreenedCtx: true } : {}), seat: createSubmissionSeat({ deployment: deps.config }), acceptance: createRunAcceptance({}, { objective, screened: false }), peerLease: resolved.peerLease, execution: resolved.execution, ...(engineNotices.length > 0 ? { engineNotices } : {}) },
1756
+ prepared: { spec: hostSpec, runner: resolved.runner, legFacts: resolved.legFacts, auth, body: ctx.body, ...(objectiveWithheldIn(ctx) ? { bodyFromScreenedCtx: true } : {}), bodyPermissionModeWrite: { stored: ctx.permissionModeWrite }, seat: createSubmissionSeat({ deployment: deps.config }), acceptance: createRunAcceptance({}, { objective, screened: false }), peerLease: resolved.peerLease, execution: resolved.execution, ...(engineNotices.length > 0 ? { engineNotices } : {}) },
1684
1757
  fleetScope: resumeFleetScope(req, auth),
1685
1758
  elicitOwner: subject ?? null,
1686
1759
  source: "workflow_parked_decide",
@@ -1706,7 +1779,7 @@ export function createResumeLegs(ctx) {
1706
1779
  const token = (await cs.findPendingTokenBySession(sessionId, undefined, wakeBinding)) ?? (await cs.findPendingTokenBySession(sessionId));
1707
1780
  if (!token)
1708
1781
  return { status: 404, body: refusalBody({ errorCode: "not_found.parked_checkpoint", message: "no parked checkpoint for this session (nothing to wake)" }) };
1709
- const who = { subject: caller, operator: explicitOperatorOk(caller === undefined ? undefined : personOf(caller), deps.config) };
1782
+ const who = { subject: caller, operator: explicitOperatorOk(caller === undefined ? undefined : personOf(caller), deps.config, "operate") };
1710
1783
  if (!who.operator) {
1711
1784
  const scope = await cs.peekPendingScope(sessionId, wakeBinding).then((s) => (s === undefined ? cs.peekPendingScope(sessionId) : s)).catch(() => undefined);
1712
1785
  if (!keyAdmits("scope.decide", who, scopeCellOf(scope ?? CHECKPOINT_PUBLIC_SCOPE))) {
@@ -1757,7 +1830,7 @@ export function createResumeLegs(ctx) {
1757
1830
  return resumeCtxUnreadableAnswer();
1758
1831
  if (ctxRead.kind === "absent")
1759
1832
  return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
1760
- const ctx = restateResumeCtx(ctxRead.ctx, restatement);
1833
+ const ctx = replayCtxOf(ctxRead.ctx, restatement);
1761
1834
  const auth = { sessionId: cp.sessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
1762
1835
  const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
1763
1836
  if (!resolved.ok)
@@ -1784,7 +1857,7 @@ export function createResumeLegs(ctx) {
1784
1857
  ...(workflowDecision !== undefined ? { workflowDecision } : {}),
1785
1858
  ...(engineNotices.length > 0 ? { engineNotices } : {}),
1786
1859
  ...(acceptEarly === true ? { acceptEarly: true } : {}),
1787
- ...(req !== undefined ? { callerInitiated: true } : {}),
1860
+ ...(req !== undefined || workflowDecision !== undefined ? { callerInitiated: true } : {}),
1788
1861
  ...(ownerLeaseAdmittedFor !== undefined && auth.subject === ownerLeaseAdmittedFor ? { ownerLeaseAdmitted: true } : {}),
1789
1862
  });
1790
1863
  }
@@ -1792,6 +1865,183 @@ export function createResumeLegs(ctx) {
1792
1865
  resolved.peerLease.release();
1793
1866
  }
1794
1867
  }
1868
+ async function answerOfRecordFailure(failed, hostSessionId) {
1869
+ if (failed.kind === "faulted")
1870
+ return faultedAnswerOf(failed.err, CONTINUATION_CLAIM_FACE.faulted);
1871
+ const runStore = deps.runStore;
1872
+ if (runStore === undefined)
1873
+ throw new Error("workflow park decide: a decision row failed to land without a run store — the claim fence it was written under is the run store");
1874
+ try {
1875
+ return await refusalAfterLostClaim(deps, runStore, hostSessionId, failed.deliveredTaskId);
1876
+ }
1877
+ catch (e) {
1878
+ return faultedAnswerOf(e, CONTINUATION_CLAIM_FACE.faulted);
1879
+ }
1880
+ }
1881
+ async function deliverViaResumeLane(d) {
1882
+ const decisions = deps.workflowParkDecisions;
1883
+ const runStore = deps.runStore;
1884
+ const cs = deps.checkpointStore;
1885
+ if (decisions === undefined || runStore === undefined || cs === undefined) {
1886
+ return { kind: "refused", out: { status: 501, body: refusalBody({ errorCode: "capability.run_store_required", message: "delivering this decision requires a durable run store (DB_BACKEND=mysql|pg|local)" }) } };
1887
+ }
1888
+ const liveReceiptOf = async (held) => {
1889
+ if (held === null || held.fingerprint !== d.fingerprint)
1890
+ return undefined;
1891
+ const run = await runFactsOf(runStore, held.deliveredTaskId);
1892
+ return run != null && !isTerminalRunStatus(run.status) ? acceptedResumingReceipt(held.deliveredTaskId, held.hostSessionId, NO_SETTLEMENT_EVIDENCE) : undefined;
1893
+ };
1894
+ const replay = await liveReceiptOf(await decisions.get(d.token));
1895
+ if (replay !== undefined)
1896
+ return { kind: "replayed", out: replay };
1897
+ await runChannelEnded(d.runId, d.runScope);
1898
+ const condition = d.initiator.kind === "run_ended" ? { expect: d.fingerprint } : undefined;
1899
+ let recordFailure;
1900
+ const delivery = {
1901
+ carried: [{ runId: d.runId, token: d.token, outcome: d.outcome }],
1902
+ commitBeforeLaunch: async (deliveredTaskId) => {
1903
+ let recorded;
1904
+ try {
1905
+ recorded = await decisions.record({ token: d.token, runId: d.runId, hostSessionId: d.hostSessionId, outcome: d.outcome, fingerprint: d.fingerprint, deliveredTaskId, acceptedAtMs: Date.now() }, condition);
1906
+ }
1907
+ catch (err) {
1908
+ recordFailure = { kind: "faulted", err };
1909
+ throw err;
1910
+ }
1911
+ if (!recorded) {
1912
+ recordFailure = { kind: "not_recorded", deliveredTaskId };
1913
+ throw new Error(DELIVERY_NOT_RECORDED);
1914
+ }
1915
+ },
1916
+ };
1917
+ const hostToken = await cs.findPendingTokenBySession(d.hostSessionId, undefined, { gateKinds: TERMINAL_PARK_GATE_KINDS, pick: "oldest" }).catch(() => undefined);
1918
+ const req = d.initiator.kind === "decide" ? d.initiator.req : undefined;
1919
+ const acceptEarly = d.initiator.kind === "decide" ? d.initiator.acceptEarly : undefined;
1920
+ let out;
1921
+ try {
1922
+ out = hostToken
1923
+ ? await resumeWake(d.hostSessionId, d.message, d.initiator.caller, req, acceptEarly, delivery, d.initiator.admittedPayer, d.restatement)
1924
+ : await startFreshHostTurn(d.hostSessionId, d.message.text, d.initiator.admittedPayer, req, delivery, d.runId, d.restatement);
1925
+ }
1926
+ catch (err) {
1927
+ const failed = recordFailure;
1928
+ if (failed === undefined)
1929
+ throw err;
1930
+ return { kind: "record_failed", failure: failed };
1931
+ }
1932
+ const failed = recordFailure;
1933
+ if (failed !== undefined)
1934
+ return { kind: "record_failed", failure: failed };
1935
+ if (acceptedTaskIdOf(out) === undefined) {
1936
+ const raced = await liveReceiptOf(await decisions.get(d.token));
1937
+ return raced !== undefined ? { kind: "replayed", out: raced } : { kind: "refused", out };
1938
+ }
1939
+ return { kind: "launched", out };
1940
+ }
1941
+ async function handOverRunEndedDecisions(runId) {
1942
+ if (isAdoptionQuiescing())
1943
+ throw new Error(`workflow run ${runId}: an adoption arc is running in this process — the decision handoff yields and is retried on the next recovery sweep`);
1944
+ const handing = handOverHeldRows(runId);
1945
+ trackMaintenanceLeg(handing);
1946
+ await handing;
1947
+ }
1948
+ async function handOverHeldRows(runId) {
1949
+ const decisions = deps.workflowParkDecisions;
1950
+ const records = deps.workflowRunStore;
1951
+ const cs = deps.checkpointStore;
1952
+ const index = deps.workflowAgentSessionIndex;
1953
+ if (decisions === undefined || records === undefined || cs === undefined || index === undefined)
1954
+ return;
1955
+ const run = await records.get(runId);
1956
+ if (run === null)
1957
+ return;
1958
+ const parks = readRunParks(run);
1959
+ if (parks === undefined) {
1960
+ deps.logger?.warn?.("workflow_park_handoff_refused", { runId, why: "parks_unreadable" });
1961
+ return;
1962
+ }
1963
+ const held = heldParksOf(runId, parks);
1964
+ if (run.status === "running") {
1965
+ for (const park of held) {
1966
+ if ((await decisions.get(park.token)) !== null) {
1967
+ throw new Error(`workflow run ${runId}: its completion arrived while its record still reads running (the terminal record write did not land) and it holds an accepted decision — leaving the completion pending until recovery ends the record`);
1968
+ }
1969
+ }
1970
+ return;
1971
+ }
1972
+ for (const park of held) {
1973
+ const row = await decisions.get(park.token);
1974
+ if (row === null)
1975
+ continue;
1976
+ const deliverable = await deliverableEntryOf({ checkpointStore: cs, workflowAgentSessionIndex: index, workflowRunStore: records }, row);
1977
+ if (deliverable.kind === "unreadable")
1978
+ throw new Error(`workflow run ${runId}: the card or the holder of a recorded decision could not be read — leaving the completion pending for the next recovery sweep`);
1979
+ if (deliverable.kind === "not_deliverable" || deliverable.entry.runId !== runId)
1980
+ continue;
1981
+ const result = await handOverOne(runId, run.scope, deliverable, row);
1982
+ deps.metrics?.inc("workflow_park_handoff_total", { result: result.kind });
1983
+ switch (result.kind) {
1984
+ case "delivered":
1985
+ continue;
1986
+ case "retry":
1987
+ throw new Error(`workflow run ${runId}: the decision handoff must be retried (${result.why}) — leaving the completion pending for the next recovery sweep`);
1988
+ case "refused":
1989
+ deps.logger?.warn?.("workflow_park_handoff_refused", { runId, why: result.why });
1990
+ continue;
1991
+ default: {
1992
+ const unhandled = result;
1993
+ throw new Error(`unhandled workflow park handoff result: ${JSON.stringify(unhandled)}`);
1994
+ }
1995
+ }
1996
+ }
1997
+ }
1998
+ async function handOverOne(runId, runScope, parkEntry, row) {
1999
+ const cs = deps.checkpointStore;
2000
+ const hostSessionId = parkEntry.origin.run.originatingSessionId;
2001
+ if (hostSessionId === undefined || hostSessionId === "")
2002
+ return { kind: "refused", why: "host_unknown" };
2003
+ const ownerScope = parkEntry.card.scope;
2004
+ const hostToken = await cs.findPendingTokenBySession(hostSessionId, undefined, { gateKinds: TERMINAL_PARK_GATE_KINDS, pick: "oldest" });
2005
+ if (hostToken) {
2006
+ const hostCard = await cs.get(hostToken);
2007
+ if (hostCard !== null && hostCard.scope !== ownerScope)
2008
+ return { kind: "refused", why: "owner_mismatch" };
2009
+ }
2010
+ const parts = checkpointPartsOf(ownerScope);
2011
+ const quota = ownerCostQuotaDenied(parts?.person);
2012
+ if (quota !== undefined)
2013
+ return handoffResultOf(quota, "payer_cost_quota");
2014
+ const lease = await ownerFleetLeaseDenied(parts?.person);
2015
+ if (lease !== undefined)
2016
+ return handoffResultOf(lease, "payer_fleet_lease");
2017
+ const laned = await deliverViaResumeLane({
2018
+ hostSessionId,
2019
+ runId,
2020
+ runScope,
2021
+ token: row.token,
2022
+ outcome: row.outcome,
2023
+ fingerprint: row.fingerprint,
2024
+ message: workflowParkGuidance(runId, parkEntry.origin.park.callKey, row.outcome.decision === "allow" ? "approve" : "deny"),
2025
+ initiator: { kind: "run_ended", caller: parts?.subject, admittedPayer: decodeCheckpointScope(ownerScope) },
2026
+ });
2027
+ switch (laned.kind) {
2028
+ case "launched":
2029
+ case "replayed":
2030
+ return { kind: "delivered" };
2031
+ case "refused":
2032
+ return handoffResultOf(laned.out);
2033
+ case "record_failed": {
2034
+ if (laned.failure.kind === "faulted")
2035
+ return { kind: "retry", why: "store_fault" };
2036
+ const now = await deps.workflowParkDecisions.get(row.token);
2037
+ return now?.fingerprint === row.fingerprint ? { kind: "retry", why: "claim_lost" } : { kind: "refused", why: "superseded" };
2038
+ }
2039
+ default: {
2040
+ const unhandled = laned;
2041
+ throw new Error(`unhandled resume lane delivery: ${JSON.stringify(unhandled)}`);
2042
+ }
2043
+ }
2044
+ }
1795
2045
  async function preparePlanReview(sessionId, log, decider, sighting, restatement) {
1796
2046
  const cs = deps.checkpointStore;
1797
2047
  const refuse = (answer) => ({ ok: false, answer });
@@ -1865,7 +2115,7 @@ export function createResumeLegs(ctx) {
1865
2115
  return refuse(resumeCtxUnreadableAnswer());
1866
2116
  if (ctxRead.kind === "absent")
1867
2117
  return refuse({ status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) });
1868
- const ctx = restateResumeCtx(ctxRead.ctx, restatement);
2118
+ const ctx = replayCtxOf(ctxRead.ctx, restatement);
1869
2119
  const replay = storedBodyReplayRefusal(ctx, deps.config);
1870
2120
  if (replay !== undefined)
1871
2121
  return refuse(refuseStoredBodyReplay(sessionId, replay));
@@ -1881,7 +2131,7 @@ export function createResumeLegs(ctx) {
1881
2131
  throw new Error("drivePlanReview: permissionModeAfter was passed for a task whose stored permission mode is not \"plan\" — the caller must refuse this before any state changes (see the plan_review route's pre-nonce gate)");
1882
2132
  }
1883
2133
  const approvedMode = planReviewDecisionExitsPlan(decision) && effMode === "plan" ? (permissionModeAfter ?? "default") : undefined;
1884
- const rebuildCtx = approvedMode === undefined ? ctx : { ...ctx, body: { ...ctx.body, permissionMode: approvedMode } };
2134
+ const rebuildCtx = approvedMode === undefined ? ctx : withStoredPermissionMode(ctx, approvedMode, "plan_review");
1885
2135
  const resolved = await resolveResumeSpecOrBlocked(rebuildCtx, req, auth);
1886
2136
  if (!resolved.ok)
1887
2137
  return resolved.answer;
@@ -1920,6 +2170,6 @@ export function createResumeLegs(ctx) {
1920
2170
  local: { images: createImagesLocal(deps), sessions: createSessionsLocal(), sessionSync: createSessionSyncLocal(), capabilities: createCapabilitiesLocal() },
1921
2171
  legs: { prepareSpec, finalizeTaskResult, resumeCheckpoint, driveResumeIntoRunLog, resumePreempted, resumeWake, preparePlanReview, drivePlanReview, sessionNotify: sessionNotifyDoor },
1922
2172
  };
1923
- return { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, decisionRowAdmits, resumePreempted, startFreshHostTurn, resumeWake, preparePlanReview, drivePlanReview, sessionNotifyDoor };
2173
+ return { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, decisionRowAdmits, resumePreempted, startFreshHostTurn, resumeWake, preparePlanReview, drivePlanReview, sessionNotifyDoor, handOverRunEndedDecisions };
1924
2174
  }
1925
2175
  //# sourceMappingURL=resume-legs.js.map