@sema-agent/server 7.147.0 → 7.148.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 (725) hide show
  1. package/MIGRATION.md +1039 -24
  2. package/README.md +20 -7
  3. package/README.zh-CN.md +14 -8
  4. package/USAGE.md +380 -163
  5. package/deploy/sema-up/README.md +16 -5
  6. package/deploy/sema-up/chart/templates/NOTES.txt +1 -1
  7. package/deploy/sema-up/chart/templates/_helpers.tpl +20 -4
  8. package/deploy/sema-up/chart/values.yaml +3 -2
  9. package/deploy/sema-up/cluster-up.sh +74 -176
  10. package/deploy/sema-up/kube-up.sh +29 -49
  11. package/deploy/sema-up/lib/chart-run.sh +23 -0
  12. package/deploy/sema-up/lib/dataroot.sh +3 -3
  13. package/deploy/sema-up/lib/health.sh +62 -13
  14. package/deploy/sema-up/lib/helm-values-cluster.py +18 -0
  15. package/deploy/sema-up/lib/helm-values-kube.py +35 -0
  16. package/deploy/sema-up/lib/regcred.py +8 -0
  17. package/deploy/sema-up/lib/remote/helm-install.sh +3 -0
  18. package/deploy/sema-up/lib/remote/image-import.sh +6 -0
  19. package/deploy/sema-up/lib/remote/machine-precheck.sh +11 -0
  20. package/deploy/sema-up/lib/remote/region-probe.sh +3 -0
  21. package/deploy/sema-up/lib/remote/stack-ready.sh +26 -0
  22. package/deploy/sema-up/lib/remote/vxlan-guard.sh +8 -0
  23. package/deploy/sema-up/lib/render-stack.py +17 -0
  24. package/deploy/sema-up/lib/shell-text.sh +87 -0
  25. package/deploy/sema-up/lib/usage-flags.txt +10 -0
  26. package/deploy/sema-up/lib/usage-head.txt +1 -0
  27. package/deploy/sema-up/lib/usage-tail.txt +13 -0
  28. package/deploy/sema-up/preflight.sh +10 -8
  29. package/deploy/sema-up/sema-up.sh +14 -39
  30. package/deploy/sema-up/smoke.sh +7 -6
  31. package/deploy/sema-up/stack/compose.dataroot.yaml +3 -0
  32. package/deploy/sema-up/stack/compose.yaml +13 -1
  33. package/deploy/sema-up/stack/sema-stack-cluster.yaml +21 -0
  34. package/dist/adoption/plan.d.ts +24 -0
  35. package/dist/adoption/plan.js +53 -1
  36. package/dist/adoption/runner.d.ts +10 -1
  37. package/dist/adoption/runner.js +36 -16
  38. package/dist/adoption/wire.d.ts +3 -3
  39. package/dist/approval-card.d.ts +28 -30
  40. package/dist/approval-gate-currency.js +3 -2
  41. package/dist/approval-reconciler.d.ts +4 -13
  42. package/dist/approval-reconciler.js +2 -2
  43. package/dist/approval.d.ts +13 -11
  44. package/dist/approval.js +3 -3
  45. package/dist/audit.d.ts +10 -3
  46. package/dist/audit.js +15 -7
  47. package/dist/auth-bridge.d.ts +0 -14
  48. package/dist/auth-bridge.js +0 -7
  49. package/dist/auto-mode-face.d.ts +10 -7
  50. package/dist/auto-mode-face.js +7 -4
  51. package/dist/background-agent-name.d.ts +19 -1
  52. package/dist/background-agent-name.js +12 -2
  53. package/dist/background-session-reap.d.ts +1 -1
  54. package/dist/bake-runner/main.js +9 -6
  55. package/dist/bench/s1/arms.js +6 -5
  56. package/dist/bench/s1/live-deps.js +5 -2
  57. package/dist/bench/s1/run-firm.js +6 -5
  58. package/dist/bind-host.d.ts +25 -0
  59. package/dist/bind-host.js +25 -0
  60. package/dist/boot/adoption.d.ts +3 -0
  61. package/dist/boot/adoption.js +1 -0
  62. package/dist/boot/deployment-mods.d.ts +1 -1
  63. package/dist/boot/execution-env.d.ts +17 -7
  64. package/dist/boot/execution-env.js +37 -31
  65. package/dist/boot/exit-boundary.d.ts +2 -2
  66. package/dist/boot/exit-boundary.js +6 -5
  67. package/dist/boot/fatal-exit.d.ts +3 -5
  68. package/dist/boot/fatal-exit.js +2 -2
  69. package/dist/boot/leader.d.ts +15 -0
  70. package/dist/boot/leader.js +17 -15
  71. package/dist/boot/memory-consolidation.d.ts +37 -29
  72. package/dist/boot/memory-consolidation.js +11 -5
  73. package/dist/boot/org-memory.js +1 -1
  74. package/dist/boot/parked-revive-gate.js +2 -2
  75. package/dist/boot/reapers.d.ts +4 -3
  76. package/dist/boot/reapers.js +19 -16
  77. package/dist/boot/resolve-spec.d.ts +5 -3
  78. package/dist/boot/resolve-spec.js +55 -67
  79. package/dist/boot/retention-lane.d.ts +4 -4
  80. package/dist/boot/retention-lane.js +2 -2
  81. package/dist/boot/runner-deps.d.ts +28 -7
  82. package/dist/boot/runner-deps.js +11 -4
  83. package/dist/boot/runtime-caps.d.ts +2 -2
  84. package/dist/boot/runtime-caps.js +16 -2
  85. package/dist/boot/session-faces.d.ts +16 -7
  86. package/dist/boot/session-faces.js +114 -94
  87. package/dist/boot/shutdown.d.ts +5 -4
  88. package/dist/boot/shutdown.js +6 -4
  89. package/dist/boot/stage-01-config.js +9 -1
  90. package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
  91. package/dist/boot/stage-02-web-admin-pull.js +6 -1
  92. package/dist/boot/stage-03-store-backend.d.ts +3 -0
  93. package/dist/boot/stage-03-store-backend.js +4 -3
  94. package/dist/boot/stage-04-stores.d.ts +2 -0
  95. package/dist/boot/stage-04-stores.js +2 -2
  96. package/dist/boot/stage-05-execution-env.d.ts +7 -3
  97. package/dist/boot/stage-05-execution-env.js +2 -2
  98. package/dist/boot/stage-06-runners.d.ts +10 -12
  99. package/dist/boot/stage-06-runners.js +23 -15
  100. package/dist/boot/stage-07-capability-layer.d.ts +11 -8
  101. package/dist/boot/stage-07-capability-layer.js +5 -3
  102. package/dist/boot/stage-08-reapers.d.ts +11 -8
  103. package/dist/boot/stage-08-reapers.js +3 -3
  104. package/dist/boot/stage-09-leader.d.ts +12 -15
  105. package/dist/boot/stage-09-leader.js +12 -4
  106. package/dist/boot/stage-10-http-server.d.ts +12 -15
  107. package/dist/boot/stage-10-http-server.js +7 -4
  108. package/dist/boot/store-evidence.d.ts +20 -0
  109. package/dist/boot/store-evidence.js +13 -0
  110. package/dist/boot/stores.d.ts +3 -0
  111. package/dist/boot/stores.js +21 -10
  112. package/dist/boot/task-list-lane.d.ts +4 -4
  113. package/dist/boot/web-admin.d.ts +4 -2
  114. package/dist/boot/web-admin.js +55 -35
  115. package/dist/boot/webfetch-summarize-lane.d.ts +1 -1
  116. package/dist/boot-reclaim.d.ts +3 -1
  117. package/dist/boot-reclaim.js +1 -1
  118. package/dist/brain.d.ts +7 -18
  119. package/dist/brain.js +5 -17
  120. package/dist/budget.js +6 -6
  121. package/dist/capabilities/center-plugins.d.ts +7 -1
  122. package/dist/capabilities/center-plugins.js +32 -10
  123. package/dist/capabilities/center-wiring.js +1 -1
  124. package/dist/capabilities/composite-members.d.ts +2 -2
  125. package/dist/capabilities/composite-members.js +2 -2
  126. package/dist/capabilities/repo-tools.d.ts +2 -0
  127. package/dist/capabilities/repo-tools.js +14 -12
  128. package/dist/capabilities/scenarios.d.ts +6 -15
  129. package/dist/capabilities/scenarios.js +11 -16
  130. package/dist/capabilities/skills.d.ts +1 -1
  131. package/dist/capabilities/tool-defer.d.ts +1 -1
  132. package/dist/capability-facts.d.ts +38 -11
  133. package/dist/capability-facts.js +47 -8
  134. package/dist/card-void.d.ts +4 -4
  135. package/dist/card-void.js +1 -1
  136. package/dist/center-credential-renewer.d.ts +6 -2
  137. package/dist/center-credential-renewer.js +7 -3
  138. package/dist/config-catalog.d.ts +16 -1
  139. package/dist/config-catalog.js +62 -56
  140. package/dist/config-dir-trust.d.ts +37 -4
  141. package/dist/config-dir-trust.js +88 -44
  142. package/dist/config-invariants.d.ts +42 -3
  143. package/dist/config-invariants.js +69 -5
  144. package/dist/config-lkg.d.ts +23 -1
  145. package/dist/config-lkg.js +17 -3
  146. package/dist/config-provider.d.ts +9 -9
  147. package/dist/config-provider.js +25 -110
  148. package/dist/config-pull-failure.d.ts +50 -0
  149. package/dist/config-pull-failure.js +48 -0
  150. package/dist/config-types.d.ts +26 -17
  151. package/dist/config.d.ts +8 -16
  152. package/dist/config.js +113 -47
  153. package/dist/delegated-session-owner.d.ts +1 -1
  154. package/dist/deleted-session-ids.d.ts +3 -2
  155. package/dist/deployment-governance.d.ts +3 -3
  156. package/dist/deployment-shape.d.ts +30 -4
  157. package/dist/deployment-shape.js +7 -0
  158. package/dist/egress-redirect.d.ts +25 -7
  159. package/dist/egress-redirect.js +20 -2
  160. package/dist/elicitation.d.ts +6 -5
  161. package/dist/elicitation.js +23 -22
  162. package/dist/engine-identity.d.ts +28 -0
  163. package/dist/engine-identity.js +10 -0
  164. package/dist/entry-problems.d.ts +5 -7
  165. package/dist/entry-problems.js +1 -1
  166. package/dist/env-facts.js +2 -1
  167. package/dist/env-witness.d.ts +7 -0
  168. package/dist/env-witness.js +16 -0
  169. package/dist/execution-lane-caps.d.ts +5 -18
  170. package/dist/execution-lane-caps.js +0 -22
  171. package/dist/execution-placement.d.ts +58 -18
  172. package/dist/execution-placement.js +41 -2
  173. package/dist/field-conflict.d.ts +7 -11
  174. package/dist/field-conflict.js +3 -3
  175. package/dist/file-history-capture.d.ts +3 -3
  176. package/dist/file-history-disclosure.js +1 -0
  177. package/dist/fleet/fleet-bus.d.ts +21 -3
  178. package/dist/fleet/fleet-bus.js +35 -25
  179. package/dist/fleet/fleet-reconciler.js +2 -2
  180. package/dist/fleet/serving-lease.js +3 -3
  181. package/dist/fleet-client.js +3 -3
  182. package/dist/fleet-lease.d.ts +0 -1
  183. package/dist/fleet-lease.js +4 -5
  184. package/dist/history-anchor.d.ts +23 -3
  185. package/dist/history-anchor.js +24 -4
  186. package/dist/hitl-delivery.d.ts +90 -0
  187. package/dist/hitl-delivery.js +98 -0
  188. package/dist/hooks/classic-stations.d.ts +8 -11
  189. package/dist/hooks/classic-stations.js +0 -7
  190. package/dist/hooks/hook-llm.d.ts +5 -1
  191. package/dist/hooks/hook-llm.js +24 -15
  192. package/dist/hooks/hook-runner.d.ts +67 -57
  193. package/dist/hooks/hook-runner.js +260 -186
  194. package/dist/host-lsp-manager.d.ts +22 -8
  195. package/dist/host-lsp-manager.js +4 -1
  196. package/dist/http/active-run-conflict.d.ts +2 -43
  197. package/dist/http/active-run-conflict.js +3 -7
  198. package/dist/http/admission.d.ts +4 -18
  199. package/dist/http/admission.js +75 -78
  200. package/dist/http/approval-sweeps.d.ts +3 -3
  201. package/dist/http/approval-sweeps.js +54 -30
  202. package/dist/http/caller-trust.d.ts +8 -10
  203. package/dist/http/caller-trust.js +1 -2
  204. package/dist/http/claim-heartbeat.d.ts +49 -0
  205. package/dist/http/claim-heartbeat.js +46 -0
  206. package/dist/http/claimed-run.d.ts +4 -3
  207. package/dist/http/dispatch.d.ts +8 -1
  208. package/dist/http/dispatch.js +76 -30
  209. package/dist/http/durable-run-leg.d.ts +3 -3
  210. package/dist/http/durable-run-leg.js +17 -12
  211. package/dist/http/execution-context.d.ts +17 -43
  212. package/dist/http/execution-context.js +7 -5
  213. package/dist/http/health-reader.d.ts +36 -0
  214. package/dist/http/health-reader.js +21 -0
  215. package/dist/http/health-self-report.d.ts +9 -9
  216. package/dist/http/health-self-report.js +4 -4
  217. package/dist/http/idempotency.d.ts +9 -5
  218. package/dist/http/idempotency.js +4 -4
  219. package/dist/http/memory-compliance-failure-reply.d.ts +15 -16
  220. package/dist/http/memory-compliance-failure-reply.js +4 -2
  221. package/dist/http/memory-face-fault-reply.d.ts +67 -0
  222. package/dist/http/memory-face-fault-reply.js +71 -0
  223. package/dist/http/memory-store-refusal-reply.d.ts +1 -1
  224. package/dist/http/memory-store-refusal-reply.js +3 -0
  225. package/dist/http/owner-access.d.ts +391 -67
  226. package/dist/http/owner-access.js +371 -35
  227. package/dist/http/principal-gate.d.ts +24 -81
  228. package/dist/http/principal-gate.js +24 -68
  229. package/dist/http/refusal-body.d.ts +35 -2
  230. package/dist/http/refusal-body.js +34 -0
  231. package/dist/http/request-guards.d.ts +9 -13
  232. package/dist/http/request-guards.js +34 -68
  233. package/dist/http/resume-composition.d.ts +37 -0
  234. package/dist/http/resume-composition.js +18 -0
  235. package/dist/http/resume-ctx-read.d.ts +35 -12
  236. package/dist/http/resume-ctx-read.js +25 -6
  237. package/dist/http/resume-legs.d.ts +21 -18
  238. package/dist/http/resume-legs.js +189 -129
  239. package/dist/http/retired-skill-manifest.d.ts +1 -1
  240. package/dist/http/route-ctx.d.ts +25 -32
  241. package/dist/http/routes/a2a-serve.d.ts +43 -5
  242. package/dist/http/routes/a2a-serve.js +58 -37
  243. package/dist/http/routes/admin-config-refresh.js +2 -2
  244. package/dist/http/routes/admin-drain.js +2 -2
  245. package/dist/http/routes/admin-memory-optout.js +4 -3
  246. package/dist/http/routes/adoption.d.ts +3 -0
  247. package/dist/http/routes/adoption.js +17 -10
  248. package/dist/http/routes/agents-roster.js +13 -7
  249. package/dist/http/routes/approvals-assistant.js +70 -65
  250. package/dist/http/routes/attachments.js +2 -2
  251. package/dist/http/routes/background.d.ts +3 -3
  252. package/dist/http/routes/background.js +9 -17
  253. package/dist/http/routes/capabilities.js +15 -18
  254. package/dist/http/routes/config-catalog.js +2 -2
  255. package/dist/http/routes/devices.d.ts +3 -3
  256. package/dist/http/routes/devices.js +4 -4
  257. package/dist/http/routes/diagnostics.d.ts +27 -3
  258. package/dist/http/routes/diagnostics.js +27 -21
  259. package/dist/http/routes/engine.js +2 -2
  260. package/dist/http/routes/fleet.js +5 -3
  261. package/dist/http/routes/images.js +10 -6
  262. package/dist/http/routes/leader.d.ts +7 -2
  263. package/dist/http/routes/leader.js +12 -3
  264. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  265. package/dist/http/routes/mcp-reconnect.js +7 -15
  266. package/dist/http/routes/memory-bundle.js +4 -7
  267. package/dist/http/routes/memory-compliance.js +4 -4
  268. package/dist/http/routes/memory-consolidation.js +6 -9
  269. package/dist/http/routes/memory-origin.d.ts +2 -0
  270. package/dist/http/routes/memory-origin.js +7 -8
  271. package/dist/http/routes/memory-policy.js +17 -12
  272. package/dist/http/routes/notify-wake.js +10 -19
  273. package/dist/http/routes/observability.js +3 -3
  274. package/dist/http/routes/principal-inbox.d.ts +1 -1
  275. package/dist/http/routes/principal-inbox.js +2 -2
  276. package/dist/http/routes/projects.d.ts +1 -1
  277. package/dist/http/routes/projects.js +3 -2
  278. package/dist/http/routes/retention-ops.js +6 -9
  279. package/dist/http/routes/rules.js +20 -5
  280. package/dist/http/routes/run-memory-capture.d.ts +2 -2
  281. package/dist/http/routes/run-memory-capture.js +6 -12
  282. package/dist/http/routes/run-permission-mode.d.ts +2 -2
  283. package/dist/http/routes/run-permission-mode.js +10 -17
  284. package/dist/http/routes/runs.js +146 -231
  285. package/dist/http/routes/session-memory-sync.d.ts +2 -2
  286. package/dist/http/routes/session-memory-sync.js +7 -13
  287. package/dist/http/routes/session-sync.d.ts +4 -2
  288. package/dist/http/routes/session-sync.js +21 -20
  289. package/dist/http/routes/sessions-list.d.ts +3 -3
  290. package/dist/http/routes/sessions-list.js +9 -9
  291. package/dist/http/routes/sessions.js +87 -124
  292. package/dist/http/routes/shared-memory.js +6 -6
  293. package/dist/http/routes/side-query.js +2 -2
  294. package/dist/http/routes/tasks.js +136 -120
  295. package/dist/http/routes/trace-usage.d.ts +0 -12
  296. package/dist/http/routes/trace-usage.js +40 -46
  297. package/dist/http/routes/workflows.d.ts +39 -4
  298. package/dist/http/routes/workflows.js +42 -14
  299. package/dist/http/run-concurrency-cap.d.ts +20 -12
  300. package/dist/http/run-concurrency-cap.js +39 -26
  301. package/dist/http/run-read-face.d.ts +3 -5
  302. package/dist/http/run-read-face.js +8 -13
  303. package/dist/http/send.d.ts +12 -3
  304. package/dist/http/send.js +42 -6
  305. package/dist/http/server.d.ts +39 -40
  306. package/dist/http/server.js +36 -11
  307. package/dist/http/sse-log.d.ts +17 -10
  308. package/dist/http/sse-log.js +7 -7
  309. package/dist/http/stored-body-replay.d.ts +12 -0
  310. package/dist/http/stored-body-replay.js +2 -2
  311. package/dist/http/submit-ctx.d.ts +16 -8
  312. package/dist/http/submit-ctx.js +6 -2
  313. package/dist/http/submit-replay.d.ts +19 -6
  314. package/dist/http/submit-replay.js +18 -6
  315. package/dist/http/sync-submit-body.d.ts +3 -4
  316. package/dist/http/sync-submit-body.js +4 -5
  317. package/dist/http/wire-types.d.ts +4 -3
  318. package/dist/identity-source.d.ts +36 -5
  319. package/dist/identity-source.js +27 -0
  320. package/dist/index.d.ts +1 -0
  321. package/dist/index.js +1 -0
  322. package/dist/key-resolver.d.ts +32 -0
  323. package/dist/key-resolver.js +23 -9
  324. package/dist/leader/diffup.js +2 -1
  325. package/dist/leader/endpoint.d.ts +26 -5
  326. package/dist/leader/endpoint.js +154 -14
  327. package/dist/leader/fanout.d.ts +3 -0
  328. package/dist/leader/fanout.js +78 -63
  329. package/dist/leader/leader.d.ts +16 -0
  330. package/dist/leader/leader.js +43 -3
  331. package/dist/leader/merge.d.ts +9 -1
  332. package/dist/leader/merge.js +16 -1
  333. package/dist/leader/repair-wire.js +1 -1
  334. package/dist/leader/wire.d.ts +36 -3
  335. package/dist/leader/wire.js +59 -18
  336. package/dist/lsp-evict.d.ts +6 -4
  337. package/dist/lsp-evict.js +2 -3
  338. package/dist/memory-operator-faces.d.ts +5 -4
  339. package/dist/memory-operator-faces.js +1 -1
  340. package/dist/memory-scope.d.ts +29 -2
  341. package/dist/memory-scope.js +64 -15
  342. package/dist/memory-store-refusal.d.ts +5 -2
  343. package/dist/memory-sync-client.d.ts +3 -2
  344. package/dist/memory-sync-client.js +6 -3
  345. package/dist/model-compat.d.ts +17 -8
  346. package/dist/model-compat.js +6 -2
  347. package/dist/model-context-window.d.ts +18 -0
  348. package/dist/model-context-window.js +2 -0
  349. package/dist/model-entry-headers.d.ts +46 -4
  350. package/dist/model-entry-headers.js +2 -2
  351. package/dist/model-entry-refusal.d.ts +35 -16
  352. package/dist/model-entry-refusal.js +40 -27
  353. package/dist/model-plane-face.d.ts +19 -11
  354. package/dist/model-plane-face.js +9 -1
  355. package/dist/model-plane-probe.d.ts +2 -0
  356. package/dist/model-plane-probe.js +17 -0
  357. package/dist/model-provider.d.ts +3 -3
  358. package/dist/model-route-endpoint.d.ts +9 -5
  359. package/dist/model-route-endpoint.js +29 -7
  360. package/dist/model-select.d.ts +16 -0
  361. package/dist/model-select.js +4 -0
  362. package/dist/mountinfo.d.ts +37 -0
  363. package/dist/mountinfo.js +47 -0
  364. package/dist/namespaced-rule-name.d.ts +23 -14
  365. package/dist/namespaced-rule-name.js +8 -11
  366. package/dist/net-address.d.ts +1 -1
  367. package/dist/observability/corrupt-read-seat.d.ts +4 -4
  368. package/dist/observability/corrupt-read-seat.js +5 -3
  369. package/dist/observability/fail-open.d.ts +58 -38
  370. package/dist/observability/fail-open.js +60 -38
  371. package/dist/observability/logger.d.ts +22 -1
  372. package/dist/observability/logger.js +89 -12
  373. package/dist/observability/metrics.js +3 -4
  374. package/dist/observability/otel-exporter.js +2 -1
  375. package/dist/observability/principal-context.d.ts +14 -7
  376. package/dist/observability/principal-context.js +8 -3
  377. package/dist/observability/run-terminal.d.ts +7 -1
  378. package/dist/observability/run-terminal.js +5 -2
  379. package/dist/orchestration/hardened-vm-runner.d.ts +1 -0
  380. package/dist/orchestration/hardened-vm-runner.js +11 -5
  381. package/dist/orchestration/hardened-vm-worker-runner.d.ts +0 -14
  382. package/dist/orchestration/hardened-vm-worker-runner.js +5 -0
  383. package/dist/orchestration/hardened-vm-worker.js +2 -1
  384. package/dist/orchestration/workflow-completion-inbox.d.ts +3 -3
  385. package/dist/orchestration/workflow-completion-inbox.js +3 -2
  386. package/dist/org-delivery-gate.d.ts +5 -4
  387. package/dist/org-delivery-gate.js +7 -6
  388. package/dist/outbound-dispatcher.d.ts +1 -1
  389. package/dist/outbound-dispatcher.js +6 -12
  390. package/dist/owner-brands.d.ts +81 -0
  391. package/dist/owner-brands.js +42 -0
  392. package/dist/owner-faces.d.ts +531 -0
  393. package/dist/owner-faces.js +126 -0
  394. package/dist/parked-decide.d.ts +67 -5
  395. package/dist/parked-decide.js +127 -5
  396. package/dist/parked-revive-surface.d.ts +14 -4
  397. package/dist/parked-revive-surface.js +5 -4
  398. package/dist/peer-directory.d.ts +6 -8
  399. package/dist/peer-directory.js +3 -2
  400. package/dist/permission-rule-vocab.d.ts +53 -8
  401. package/dist/permission-rule-vocab.js +30 -2
  402. package/dist/plugins/adoption-log-sql.d.ts +0 -22
  403. package/dist/plugins/adoption-log-sql.js +5 -3
  404. package/dist/plugins/approval-ask-retired-delete-by-task-m50.d.ts +7 -0
  405. package/dist/plugins/approval-ask-retired-delete-by-task-m50.js +17 -0
  406. package/dist/plugins/approval-ask-store-file.d.ts +18 -7
  407. package/dist/plugins/approval-ask-store-file.js +37 -14
  408. package/dist/plugins/approval-ask-store-memory.d.ts +12 -4
  409. package/dist/plugins/approval-ask-store-memory.js +24 -10
  410. package/dist/plugins/approval-ask-store-sql.d.ts +39 -20
  411. package/dist/plugins/approval-ask-store-sql.js +41 -10
  412. package/dist/plugins/approval-exemption-skill-m46.d.ts +20 -0
  413. package/dist/plugins/approval-exemption-skill-m46.js +25 -0
  414. package/dist/plugins/approval-exemption-store.d.ts +6 -1
  415. package/dist/plugins/approval-exemption-store.js +14 -0
  416. package/dist/plugins/approval-nonce-store.d.ts +39 -12
  417. package/dist/plugins/approval-nonce-store.js +72 -23
  418. package/dist/plugins/blob-backend.d.ts +2 -0
  419. package/dist/plugins/blob-backend.js +9 -6
  420. package/dist/plugins/caching-session-store.d.ts +13 -1
  421. package/dist/plugins/caching-session-store.js +43 -4
  422. package/dist/plugins/checkpoint-index-columns.d.ts +32 -5
  423. package/dist/plugins/checkpoint-index-columns.js +36 -1
  424. package/dist/plugins/checkpoint-store-face.d.ts +83 -10
  425. package/dist/plugins/checkpoint-store-face.js +18 -1
  426. package/dist/plugins/device-store-sql.js +1 -0
  427. package/dist/plugins/ensure-index.d.ts +13 -1
  428. package/dist/plugins/ensure-index.js +154 -21
  429. package/dist/plugins/ensure-schema-lock-policy.d.ts +0 -15
  430. package/dist/plugins/ensure-schema-lock-policy.js +3 -2
  431. package/dist/plugins/file-run-store.d.ts +63 -23
  432. package/dist/plugins/file-run-store.js +138 -83
  433. package/dist/plugins/host-platform.d.ts +24 -3
  434. package/dist/plugins/host-platform.js +15 -1
  435. package/dist/plugins/image-bake-store-sql.js +2 -0
  436. package/dist/plugins/imported-layer-root-retirement.d.ts +2 -2
  437. package/dist/plugins/k8s-pod-reaper.d.ts +1 -3
  438. package/dist/plugins/k8s-pod-reaper.js +0 -1
  439. package/dist/plugins/leader-run-store-sql.d.ts +22 -0
  440. package/dist/plugins/leader-run-store-sql.js +34 -4
  441. package/dist/plugins/local-checkpoint-store.d.ts +58 -23
  442. package/dist/plugins/local-checkpoint-store.js +195 -76
  443. package/dist/plugins/local-data-dir-modes-m39.js +2 -1
  444. package/dist/plugins/local-docker-capacity.d.ts +93 -0
  445. package/dist/plugins/local-docker-capacity.js +194 -0
  446. package/dist/plugins/local-docker-reaper.d.ts +92 -0
  447. package/dist/plugins/local-docker-reaper.js +102 -0
  448. package/dist/plugins/local-engine-high-water.d.ts +4 -2
  449. package/dist/plugins/local-engine-high-water.js +4 -1
  450. package/dist/plugins/local-session-store.d.ts +358 -125
  451. package/dist/plugins/local-session-store.js +824 -251
  452. package/dist/plugins/local-session-window.d.ts +3 -2
  453. package/dist/plugins/local-session-window.js +3 -2
  454. package/dist/plugins/local-sidecar-quarantine.js +3 -2
  455. package/dist/plugins/local-task-attachment-store.d.ts +18 -1
  456. package/dist/plugins/local-task-attachment-store.js +22 -1
  457. package/dist/plugins/memory-embedder.js +9 -7
  458. package/dist/plugins/memory-engine-pg.d.ts +3 -2
  459. package/dist/plugins/memory-engine-pg.js +14 -5
  460. package/dist/plugins/memory-engine-sql-apply.d.ts +8 -4
  461. package/dist/plugins/memory-engine-sql-apply.js +6 -8
  462. package/dist/plugins/memory-engine-tidb.d.ts +4 -2
  463. package/dist/plugins/memory-engine-tidb.js +11 -2
  464. package/dist/plugins/memory-optout-grant-store-sql.d.ts +1 -1
  465. package/dist/plugins/memory-optout-grant-store-sql.js +3 -3
  466. package/dist/plugins/memory-run-store.d.ts +39 -27
  467. package/dist/plugins/memory-run-store.js +72 -70
  468. package/dist/plugins/one-time-migration-marker.d.ts +10 -0
  469. package/dist/plugins/one-time-migration-marker.js +7 -0
  470. package/dist/plugins/one-time-migrations.d.ts +186 -45
  471. package/dist/plugins/one-time-migrations.js +442 -119
  472. package/dist/plugins/org-delivery-quota-store.js +2 -1
  473. package/dist/plugins/permission-rule-store-file.d.ts +3 -3
  474. package/dist/plugins/permission-rule-store-sql.d.ts +4 -63
  475. package/dist/plugins/permission-rule-store-sql.js +6 -86
  476. package/dist/plugins/pg-pool.d.ts +1 -31
  477. package/dist/plugins/pg-pool.js +16 -7
  478. package/dist/plugins/remote-env-e2b.d.ts +7 -25
  479. package/dist/plugins/remote-env-e2b.js +34 -25
  480. package/dist/plugins/remote-env-host.d.ts +2 -9
  481. package/dist/plugins/remote-env-host.js +34 -22
  482. package/dist/plugins/remote-env-k8s.d.ts +40 -45
  483. package/dist/plugins/remote-env-k8s.js +107 -58
  484. package/dist/plugins/remote-env-local-docker.d.ts +148 -14
  485. package/dist/plugins/remote-env-local-docker.js +367 -72
  486. package/dist/plugins/remote-scratchpad.js +4 -0
  487. package/dist/plugins/retention-deployment.d.ts +49 -17
  488. package/dist/plugins/retention-deployment.js +39 -8
  489. package/dist/plugins/run-preview-m45.d.ts +11 -0
  490. package/dist/plugins/run-preview-m45.js +19 -0
  491. package/dist/plugins/run-store-sql.d.ts +56 -68
  492. package/dist/plugins/run-store-sql.js +127 -116
  493. package/dist/plugins/s3-answer.d.ts +2 -1
  494. package/dist/plugins/sandbox-reaper.d.ts +26 -0
  495. package/dist/plugins/sandbox-reaper.js +2 -0
  496. package/dist/plugins/scenario-prefix-switch-m42.d.ts +54 -0
  497. package/dist/plugins/scenario-prefix-switch-m42.js +55 -0
  498. package/dist/plugins/scheduler-support.d.ts +16 -1
  499. package/dist/plugins/scheduler-support.js +22 -2
  500. package/dist/plugins/schema-consistency.d.ts +42 -9
  501. package/dist/plugins/schema-consistency.js +212 -11
  502. package/dist/plugins/schema-drift-sentence.d.ts +4 -1
  503. package/dist/plugins/schema-drift-sentence.js +4 -4
  504. package/dist/plugins/schema-ensure-legs.d.ts +9 -0
  505. package/dist/plugins/schema-ensure-legs.js +1 -1
  506. package/dist/plugins/schema-indexes.js +3 -0
  507. package/dist/plugins/schema-live-columns.d.ts +14 -5
  508. package/dist/plugins/schema-live-columns.js +10 -10
  509. package/dist/plugins/send-user-file.js +2 -1
  510. package/dist/plugins/session-birth.d.ts +37 -0
  511. package/dist/plugins/session-birth.js +38 -0
  512. package/dist/plugins/session-epoch-anchor.d.ts +40 -12
  513. package/dist/plugins/session-epoch-anchor.js +33 -11
  514. package/dist/plugins/session-ext-table.d.ts +27 -3
  515. package/dist/plugins/session-ext-table.js +19 -6
  516. package/dist/plugins/session-fork.d.ts +15 -1
  517. package/dist/plugins/session-fork.js +3 -0
  518. package/dist/plugins/session-ownership.d.ts +1 -1
  519. package/dist/plugins/session-placement.d.ts +22 -16
  520. package/dist/plugins/session-placement.js +15 -12
  521. package/dist/plugins/session-row-sql.d.ts +12 -0
  522. package/dist/plugins/session-row-sql.js +3 -3
  523. package/dist/plugins/session-run-rollup.d.ts +29 -0
  524. package/dist/plugins/session-run-rollup.js +40 -0
  525. package/dist/plugins/session-store-sql.d.ts +38 -12
  526. package/dist/plugins/session-store-sql.js +130 -30
  527. package/dist/plugins/session-withdraw-sql.d.ts +36 -0
  528. package/dist/plugins/session-withdraw-sql.js +42 -0
  529. package/dist/plugins/shared-memory-store-sql.d.ts +0 -69
  530. package/dist/plugins/shared-memory-store-sql.js +2 -1
  531. package/dist/plugins/shell-sentinel-owner-m48.d.ts +20 -0
  532. package/dist/plugins/shell-sentinel-owner-m48.js +3 -0
  533. package/dist/plugins/snapshot-bucket-presence.d.ts +2 -1
  534. package/dist/plugins/sql-driver.d.ts +1 -1
  535. package/dist/plugins/sql-driver.js +2 -1
  536. package/dist/plugins/sql-errors.d.ts +32 -5
  537. package/dist/plugins/sql-errors.js +55 -7
  538. package/dist/plugins/sql-json-column.d.ts +8 -7
  539. package/dist/plugins/sql-json-column.js +10 -6
  540. package/dist/plugins/store-backend.d.ts +84 -15
  541. package/dist/plugins/store-backend.js +186 -55
  542. package/dist/plugins/store-contracts.d.ts +90 -30
  543. package/dist/plugins/store-contracts.js +22 -1
  544. package/dist/plugins/store-fault.d.ts +28 -2
  545. package/dist/plugins/store-fault.js +20 -2
  546. package/dist/plugins/task-attachment-store.d.ts +15 -3
  547. package/dist/plugins/task-attachment-store.js +22 -9
  548. package/dist/plugins/tidb-pool.js +23 -8
  549. package/dist/plugins/web-search.js +5 -3
  550. package/dist/plugins/workflow-run-store-sql.d.ts +6 -1
  551. package/dist/plugins/workflow-run-store-sql.js +11 -5
  552. package/dist/principal-jwt.d.ts +4 -4
  553. package/dist/principal-jwt.js +20 -5
  554. package/dist/principal-shape.d.ts +41 -0
  555. package/dist/principal-shape.js +19 -0
  556. package/dist/question.d.ts +13 -23
  557. package/dist/question.js +21 -39
  558. package/dist/request-declaration-refusal.d.ts +35 -12
  559. package/dist/request-declaration-refusal.js +21 -9
  560. package/dist/request-form.d.ts +58 -0
  561. package/dist/request-form.js +72 -0
  562. package/dist/request-image-urls.d.ts +8 -2
  563. package/dist/request-image-urls.js +2 -1
  564. package/dist/request-images.d.ts +20 -0
  565. package/dist/request-images.js +59 -0
  566. package/dist/request-key-closure.d.ts +6 -7
  567. package/dist/request-key-closure.js +15 -2
  568. package/dist/resource-suspend.d.ts +7 -16
  569. package/dist/resource-suspend.js +1 -1
  570. package/dist/retired-name-host-notice.d.ts +21 -0
  571. package/dist/retired-name-host-notice.js +12 -0
  572. package/dist/rule-entry-list.d.ts +2 -2
  573. package/dist/rule-entry-list.js +3 -4
  574. package/dist/rule-issue-reading.d.ts +58 -0
  575. package/dist/rule-issue-reading.js +14 -0
  576. package/dist/rules-consent.d.ts +5 -3
  577. package/dist/rules-consent.js +1 -0
  578. package/dist/run-acceptance.d.ts +3 -1
  579. package/dist/run-acceptance.js +3 -0
  580. package/dist/run-local.d.ts +14 -6
  581. package/dist/run-local.js +92 -80
  582. package/dist/run-stale-default.d.ts +7 -0
  583. package/dist/run-stale-default.js +2 -0
  584. package/dist/runs.d.ts +26 -15
  585. package/dist/runs.js +39 -27
  586. package/dist/runtime-caps-resolver.d.ts +21 -6
  587. package/dist/runtime-caps-resolver.js +17 -4
  588. package/dist/runtime-governance.d.ts +2 -2
  589. package/dist/runtime-governance.js +5 -3
  590. package/dist/sealed-key-layout.d.ts +12 -5
  591. package/dist/sealed-key-layout.js +5 -0
  592. package/dist/sealed-key.d.ts +12 -2
  593. package/dist/sealed-key.js +115 -27
  594. package/dist/security.d.ts +128 -158
  595. package/dist/security.js +163 -59
  596. package/dist/sema-config-dir.d.ts +20 -0
  597. package/dist/sema-config-dir.js +25 -0
  598. package/dist/server-secret-env.d.ts +21 -5
  599. package/dist/server-secret-env.js +14 -4
  600. package/dist/session-children-retire.d.ts +7 -5
  601. package/dist/session-children-retire.js +7 -2
  602. package/dist/session-deletion.d.ts +88 -0
  603. package/dist/session-deletion.js +8 -0
  604. package/dist/session-erase.d.ts +145 -0
  605. package/dist/session-erase.js +115 -0
  606. package/dist/session-error-wire.d.ts +5 -5
  607. package/dist/session-error-wire.js +1 -1
  608. package/dist/session-incarnation.d.ts +52 -5
  609. package/dist/session-incarnation.js +19 -2
  610. package/dist/session-policy-wire.d.ts +6 -3
  611. package/dist/session-policy-wire.js +11 -1
  612. package/dist/session-resident-background.d.ts +0 -71
  613. package/dist/session-resident-background.js +4 -3
  614. package/dist/session-row.d.ts +2 -1
  615. package/dist/session-rules-seat.d.ts +12 -0
  616. package/dist/session-rules-seat.js +19 -0
  617. package/dist/session-titler.d.ts +7 -15
  618. package/dist/session-titler.js +1 -1
  619. package/dist/spec-fields.d.ts +57 -3
  620. package/dist/spec-fields.js +72 -51
  621. package/dist/store-posture.d.ts +136 -20
  622. package/dist/store-posture.js +188 -3
  623. package/dist/stored-request-hooks-m20.js +2 -2
  624. package/dist/stores-sql/background-agent-store-sql.d.ts +11 -2
  625. package/dist/stores-sql/background-agent-store-sql.js +73 -20
  626. package/dist/stores-sql/checkpoint-store-sql.d.ts +33 -28
  627. package/dist/stores-sql/checkpoint-store-sql.js +75 -44
  628. package/dist/stores-sql/mailbox-store-sql.d.ts +7 -4
  629. package/dist/stores-sql/mailbox-store-sql.js +31 -32
  630. package/dist/stores-sql/pg-session-storage.d.ts +7 -5
  631. package/dist/stores-sql/pg-session-storage.js +54 -46
  632. package/dist/stores-sql/retention-store-sql.d.ts +87 -19
  633. package/dist/stores-sql/retention-store-sql.js +92 -27
  634. package/dist/stores-sql/session-policy-store-sql.d.ts +32 -10
  635. package/dist/stores-sql/session-policy-store-sql.js +44 -36
  636. package/dist/stores-sql/session-write-hooks.d.ts +12 -6
  637. package/dist/stores-sql/tidb-session-storage.d.ts +4 -4
  638. package/dist/stores-sql/tidb-session-storage.js +13 -8
  639. package/dist/stores-sql/tidb-session-store.d.ts +36 -17
  640. package/dist/stores-sql/tidb-session-store.js +69 -39
  641. package/dist/stores-sql/windowed-session-storage.d.ts +5 -0
  642. package/dist/stores-sql/windowed-session-storage.js +9 -0
  643. package/dist/submission-exit.d.ts +50 -0
  644. package/dist/submission-exit.js +108 -0
  645. package/dist/task-a2a.d.ts +1 -1
  646. package/dist/task-a2a.js +3 -3
  647. package/dist/task-cwd.d.ts +20 -0
  648. package/dist/task-cwd.js +8 -0
  649. package/dist/task-mcp.d.ts +1 -1
  650. package/dist/task-mcp.js +3 -3
  651. package/dist/task-settings.d.ts +14 -10
  652. package/dist/task-settings.js +18 -7
  653. package/dist/terminal.d.ts +25 -43
  654. package/dist/terminal.js +31 -11
  655. package/dist/tool-approval.d.ts +131 -129
  656. package/dist/tool-approval.js +189 -193
  657. package/dist/trace/core-keyset-guard.d.ts +13 -6
  658. package/dist/trace/core-vocab-wire.d.ts +95 -0
  659. package/dist/trace/core-vocab-wire.js +15 -0
  660. package/dist/trace/exit-seat.d.ts +30 -4
  661. package/dist/trace/exit-seat.js +40 -36
  662. package/dist/trace/extension-call-face.d.ts +3 -2
  663. package/dist/trace/extension-call-face.js +3 -1
  664. package/dist/trace/ledger-events.d.ts +4 -7
  665. package/dist/trace/ledger-sink.d.ts +1 -30
  666. package/dist/trace/ledger-sink.js +0 -11
  667. package/dist/trace/model-segment.d.ts +5 -5
  668. package/dist/trace/model-segment.js +5 -5
  669. package/dist/trace/project.d.ts +55 -42
  670. package/dist/trace/project.js +52 -19
  671. package/dist/trace/redact.d.ts +123 -27
  672. package/dist/trace/redact.js +880 -260
  673. package/dist/trace/self-minted-wire.d.ts +487 -19
  674. package/dist/trace/self-minted-wire.js +172 -23
  675. package/dist/trace/wire-projection-faces.d.ts +5 -6
  676. package/dist/trace/wire-projection-faces.js +2 -2
  677. package/dist/upstream-body.d.ts +23 -0
  678. package/dist/upstream-body.js +16 -0
  679. package/dist/url-refusal.d.ts +3 -3
  680. package/dist/url-refusal.js +11 -4
  681. package/dist/user-authored-text.d.ts +1 -1
  682. package/dist/user-input-ledger.d.ts +7 -8
  683. package/dist/user-input-ledger.js +1 -1
  684. package/dist/web-admin-client/apply-effective.d.ts +6 -3
  685. package/dist/web-admin-client/apply-effective.js +13 -16
  686. package/dist/web-admin-client/apply-ledger.d.ts +16 -7
  687. package/dist/web-admin-client/apply-ledger.js +5 -2
  688. package/dist/web-admin-client/center-request.d.ts +2 -2
  689. package/dist/web-admin-client/center-request.js +15 -15
  690. package/dist/web-admin-client/effective-keys.d.ts +1 -1
  691. package/dist/web-admin-client/effective-keys.js +1 -1
  692. package/dist/web-admin-client/entry-metadata.d.ts +8 -0
  693. package/dist/web-admin-client/entry-metadata.js +13 -0
  694. package/dist/web-admin-client/http-client.d.ts +1 -1
  695. package/dist/web-admin-client/http-client.js +23 -4
  696. package/dist/web-admin-client/mcp-revocation.d.ts +1 -1
  697. package/dist/web-admin-client/mcp-revocation.js +2 -1
  698. package/dist/web-admin-client/read-warnings.d.ts +1 -0
  699. package/dist/web-admin-client/read-warnings.js +1 -0
  700. package/dist/web-admin-client/restart-signal.js +8 -4
  701. package/dist/web-admin-client/skills-mcp.d.ts +2 -2
  702. package/dist/web-admin-client/types.d.ts +1 -2
  703. package/dist/workspace-space.d.ts +3 -2
  704. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +4 -4
  705. package/package.json +6 -3
  706. package/scripts/drain-check-local.mjs +118 -147
  707. package/scripts/drain-check.mysql.sql +22 -2
  708. package/scripts/drain-check.pg.sql +22 -2
  709. package/wire-changes/server@7.148.0.json +1517 -0
  710. package/dist/http/memory-control-plane-corrupt-reply.d.ts +0 -25
  711. package/dist/http/memory-control-plane-corrupt-reply.js +0 -19
  712. package/dist/http/memory-layer-reply.d.ts +0 -30
  713. package/dist/http/memory-layer-reply.js +0 -24
  714. package/dist/lsp/e2b-bridge.d.ts +0 -57
  715. package/dist/lsp/e2b-bridge.js +0 -139
  716. package/dist/lsp/e2b-manager.d.ts +0 -93
  717. package/dist/lsp/e2b-manager.js +0 -178
  718. package/dist/lsp/lsp-frames.d.ts +0 -14
  719. package/dist/lsp/lsp-frames.js +0 -25
  720. package/dist/lsp/manager.d.ts +0 -129
  721. package/dist/lsp/manager.js +0 -127
  722. package/dist/lsp/types.d.ts +0 -12
  723. package/dist/lsp/types.js +0 -2
  724. package/dist/lsp/ws-transport.d.ts +0 -40
  725. package/dist/lsp/ws-transport.js +0 -210
@@ -1,29 +1,33 @@
1
1
  import { redactErrorMessage, redactHead } from "../observability/run-terminal.js";
2
2
  import { createHash } from "node:crypto";
3
- import { uuidv7, resumeWithVerification, CheckpointError, judgeCheckpointRow, defaultTaskRegistry, taskNotificationDedupKey, validatePendingSteer, GLOBAL_USAGE_KEY } from "@sema-agent/core";
4
- import { decideParkedAgent, denyWorkflowParkForked, denyWorkflowParksUnreadable, findParkOrigin, heldWorkflowParkDecisions, planWorkflowParkedDecide } from "../parked-decide.js";
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";
5
5
  import { parkDecisionFingerprint } from "../orchestration/workflow-park-decision.js";
6
6
  import { headReadOf } from "../session-incarnation.js";
7
7
  import { createSessionWorkspaceRecorder, sessionWorkspaceStoreOf } from "../session-workspace.js";
8
8
  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, decodeCheckpointScope, CHECKPOINT_PUBLIC_SCOPE } from "../security.js";
10
- import { graftParkToolCallId, parkToolCallId, TurnAnchorCapture, HEARTBEAT_MS, markChildrenStoppedByUserOnAbort, voidHeldParkCard } from "../runs.js";
11
- import { atHostBoundary, failureCodeOf, nestedPauseOf, sealResultForExit, outwardPlane } from "../terminal.js";
9
+ import { HttpError, checkpointPartsOf, decodeCheckpointScope, scopeCellOf, CHECKPOINT_PUBLIC_SCOPE } from "../security.js";
10
+ import { keyAdmits } from "../owner-faces.js";
11
+ import { personOf } from "../owner-brands.js";
12
+ import { recoveredSubject } from "../owner-faces.js";
13
+ import { beatRunHeartbeat, graftParkToolCallId, parkToolCallId, TurnAnchorCapture, HEARTBEAT_MS, markChildrenStoppedByUserOnAbort, voidHeldParkCard } from "../runs.js";
14
+ import { atHostBoundary, failureCodeOf, nestedPauseOf, sealResultForExit, outwardPlane, outwardThrownMessage } from "../terminal.js";
12
15
  import { voidVerifierPauseCard } from "../verifier-pause-card.js";
13
16
  import { buildCancelledLedgerRow, CARD_SETTLED_BY_CANCEL_MESSAGE, createRunAbort, mintCancelledResult, withCardSettledByCancelMessage } from "../run-cancel-context.js";
14
- import { isTerminalRunStatus } from "../plugins/store-contracts.js";
17
+ import { isTerminalRunStatus, runProvenElsewhere } from "../plugins/store-contracts.js";
15
18
  import { readTurnActivityMs, recordTurnActivity } from "../turn-activity.js";
16
19
  import { recordResumeResourceWindow } from "../resource-window.js";
17
20
  import { emitPendingWorkflowCompletions, taskNotificationInboxEntry, taskNotificationStreamKeyOf, NotifiedKeys } from "../orchestration/workflow-completion-inbox.js";
18
21
  import { fleetRunPublisher, fleetRunLabels, fleetRunResiduals } from "../fleet/fleet-bus.js";
19
22
  import { defaultSubagentTailBus } from "../fleet/subagent-tail-bus.js";
20
23
  import { currentApprovalGateToken, currentGateFacesOf, sightsCurrentGate } from "../approval-gate-currency.js";
21
- import { approverFacingArgs, createApprovalCardEmitter, declaredApprovalFrameFamilies, parkRowStandingAnswerFacts, resolveApprovalLeg, resolveStreamApprovalGate, standingAnswerDurablyRecordable } from "../tool-approval.js";
24
+ import { approverFacingArgs, declaredApprovalFrameFamilies, parkRowStandingAnswerFacts, resolveApprovalLeg, resolveStreamApprovalGate, standingAnswerDurablyRecordable } from "../tool-approval.js";
25
+ import { createHitlTransport } from "../hitl-delivery.js";
22
26
  import { buildCheckpointAnchorHash } from "../approval-ask-audit-store.js";
23
27
  import { APPROVAL_ENDING_CAUSES } from "../approval-deny-reasons.js";
24
28
  import { serviceVersion } from "../service-version.js";
25
29
  import { TERMINAL_PARK_GATE_KINDS, UnreadableCheckpointRowError } from "../plugins/checkpoint-store-face.js";
26
- import { withPrincipal } from "../observability/principal-context.js";
30
+ import { withSubject } from "../observability/principal-context.js";
27
31
  import { withModelReachScope } from "../model-reach-scope.js";
28
32
  import { legFactsOf } from "../leg-facts.js";
29
33
  import { createInstructionSelectionLeg } from "../instruction-selection.js";
@@ -35,7 +39,7 @@ import { registerEngineNoticeLeg } from "../trace/engine-notice-wire.js";
35
39
  import { blockText, reasoningDeltaBytes, reasoningSegmentEventId } from "../trace/model-segment.js";
36
40
  import { errorText } from "../observability/err-text.js";
37
41
  import { recordFailOpen } from "../observability/fail-open.js";
38
- import { verifyRoundsFromBody } from "./verify-rounds.js";
42
+ import { resumeCompositionOf } from "./resume-composition.js";
39
43
  import { planReviewDecisionExitsPlan, storedBodyPermissionMode } from "../task-settings.js";
40
44
  import { acceptedResumingReceipt, acceptedTaskIdOf } from "./route-ctx.js";
41
45
  import { heldFor } from "../peer-seat.js";
@@ -46,7 +50,7 @@ import { createSessionsLocal } from "./routes/sessions.js";
46
50
  import { createSessionSyncLocal } from "./routes/session-sync.js";
47
51
  import { createImagesLocal } from "./routes/images.js";
48
52
  import { createCapabilitiesLocal } from "./routes/capabilities.js";
49
- import { gatedPrincipal, explicitOperatorOk, runIdentityOf } from "./principal-gate.js";
53
+ import { gatedSubject, explicitOperatorOk, runIdentityOf } from "./principal-gate.js";
50
54
  import { buildActiveRunConflict, resumeEntryForGate } from "./active-run-conflict.js";
51
55
  import { commitExecutionContext, isRootSessionGoneError, resolveExecutionContext, rootSessionAbsentAnswer, stampSpecRoot } from "./execution-context.js";
52
56
  import { timeClaim } from "./claim-latency.js";
@@ -54,7 +58,7 @@ import { commitSessionInheritEnv } from "./session-inherit-env.js";
54
58
  import { ASK_USER_QUESTION_TOOL_NAME, isApprovalGateKind, isEngineQuestionRow } from "../approval-content-kind.js";
55
59
  import { deploymentListAsks } from "../approval.js";
56
60
  import { isParkLedgerEventType } from "../trace/ledger-events.js";
57
- import { readResumeCtx, resumeCtxCorruptAnswer, resumeCtxUnsealableAnswer } from "./resume-ctx-read.js";
61
+ import { readResumeCtx, resumeCtxCorruptAnswer, resumeCtxUnreadableAnswer, resumeCtxUnsealableAnswer, resumeStoreReadFailureOf } from "./resume-ctx-read.js";
58
62
  import { objectiveWithheldIn } from "./submit-ctx.js";
59
63
  import { buildCheckpointVersionKeys, resumeAssemblyRefusalAnswer, resumeRefusalWithCard, sealCheckpointCtx, storedBodyReplayAnswer, storedBodyReplayLogFields, withPermissionModeRewritten } from "./checkpoint-ctx.js";
60
64
  import { refusalBody, resumeRefusalFacts } from "./refusal-body.js";
@@ -62,8 +66,12 @@ import { storedBodyReplayRefusal } from "./stored-body-replay.js";
62
66
  import { restateResumeCtx } from "./resume-restatement.js";
63
67
  import { httpErrorRefusal } from "./send.js";
64
68
  import { createRunAcceptance } from "../run-acceptance.js";
69
+ import { createSubmissionSeat } from "../submission-exit.js";
65
70
  import { fieldConflictFacts } from "../field-conflict.js";
66
71
  import { createSessionNotifyDoor } from "../session-notify-door.js";
72
+ function compositionUnlinkedAnswer() {
73
+ 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" }) };
74
+ }
67
75
  function legMayHaveReopenedCheckpoint(r) {
68
76
  return r.terminal.kind === "failed" && nestedPauseOf(r.terminal) === undefined;
69
77
  }
@@ -213,6 +221,11 @@ function rowRefusalAnswer(verdict, diagnostic, ctx) {
213
221
  const refusal = new CheckpointError(verdict.code, diagnostic === undefined ? verdict.sentence : `${verdict.sentence} Diagnostic: ${diagnostic}`, verdict.reason === undefined ? undefined : { reason: verdict.reason });
214
222
  return checkpointRefusalAnswer(refusal, { gate: "policy_ask", retriable: resumeRefusalDisposition(refusal) === "retriable", versionKeys: refusalVersionKeys(refusal, ctx) });
215
223
  }
224
+ export function rowReadRefusalAnswer(e) {
225
+ if (e instanceof UnreadableCheckpointRowError && e.rowVerdict.kind !== "ok")
226
+ return rowRefusalAnswer(e.rowVerdict, errorText(e), {});
227
+ return { status: 409, body: refusalBody({ errorCode: "conflict.checkpoint_unreadable", message: errorText(e) }) };
228
+ }
216
229
  function refusalVersionKeys(e, ctx) {
217
230
  return e.code === "checkpoint.unsupported_version" ? buildCheckpointVersionKeys(ctx.writerVersion, serviceVersion()) : {};
218
231
  }
@@ -249,9 +262,9 @@ export function decidedActionOf(binding) {
249
262
  return missingKeys.length === 0 ? { action: { boundCallId: boundCallId, boundInputHash: boundInputHash } } : { missingKeys };
250
263
  }
251
264
  export function createResumeLegs(ctx) {
252
- const { deps, runnerFor, idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters, readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, admitRun, safeDecode, runOwnerOk, sessionOwnerOk, runSessionAcceptOk, prepareSpec, finalizeTaskResult, ownerCostQuotaDenied, ownerFleetLeaseDenied, usageWindowDenialFor } = ctx;
265
+ 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;
253
266
  const ctxOpening = (sessionId) => ({ sessionId, opener: deps.checkpointCtxSealing });
254
- const resumeFleetScope = (req, auth) => req ? (gatedPrincipal(req, deps.config) ?? "default") : (auth.principal ?? "default");
267
+ const resumeFleetScope = (req, auth) => req ? (gatedSubject(req, deps.config) ?? "default") : (auth.subject ?? "default");
255
268
  function createRememberIntent(sessionId, remember) {
256
269
  let pending;
257
270
  return {
@@ -302,8 +315,7 @@ export function createResumeLegs(ctx) {
302
315
  return null;
303
316
  });
304
317
  const curPa = cur?.pendingAction;
305
- const curOwner = cur ? decodeCheckpointScope(cur.scope) : undefined;
306
- const scopeOk = cur !== null && (decider.explicitOperator || curOwner === undefined || curOwner === decider.principal);
318
+ const scopeOk = cur != null && (await decisionRowAdmits(cs, token, decider, cur.scope));
307
319
  if (cur && cur.sessionId === sessionId && !scopeOk) {
308
320
  deps.logger?.info?.("approval_decide_no_pending", { sessionId, staleTokenEchoed: true, foreignCurrentSuppressed: true });
309
321
  return { status: 404, body: refusalBody({ errorCode: "not_found.approval", message: "approval not found" }) };
@@ -323,10 +335,24 @@ export function createResumeLegs(ctx) {
323
335
  return { status: 404, body: refusalBody({ errorCode: "not_found.approval", message: "approval not found" }) };
324
336
  }
325
337
  const cpPromise = cs.get(token);
326
- const ctxPromise = cs.getCtx(sessionId);
338
+ const runSessionPromise = cs.hostSessionOfCard(token).then((id) => (typeof id === "string" ? { kind: "owned", id } : { kind: "unowned" }), (e) => ({ kind: "failed", failure: resumeStoreReadFailureOf(e) }));
339
+ const runCtxOf = async () => {
340
+ const owner = await runSessionPromise;
341
+ if (owner.kind === "unowned")
342
+ return undefined;
343
+ const read = owner.kind === "failed" ? owner.failure : await readResumeCtx(cs.getCtx(owner.id), ctxOpening(owner.id));
344
+ if (read.kind === "corrupt")
345
+ return { refusal: resumeCtxCorruptAnswer(read.where) };
346
+ if (read.kind === "unsealable")
347
+ return { refusal: resumeCtxUnsealableAnswer(read) };
348
+ if (read.kind === "unreadable")
349
+ return { refusal: resumeCtxUnreadableAnswer() };
350
+ return owner.kind === "owned" ? { runSessionId: owner.id, ctx: read.kind === "ok" ? read.ctx : null } : undefined;
351
+ };
352
+ const ctxPromise = runCtxOf();
327
353
  void ctxPromise.catch(() => { });
328
354
  const noApproval = { status: 404, body: refusalBody({ errorCode: "not_found.approval", message: "approval not found" }) };
329
- const rowOwnRefusal = async (verdict, diagnostic) => rowRefusalAnswer(verdict, diagnostic, verdict.code === "checkpoint.unsupported_version" ? ((await ctxPromise.catch(() => null)) ?? {}) : {});
355
+ const rowOwnRefusal = async (verdict) => rowRefusalAnswer(verdict, undefined, verdict.code === "checkpoint.unsupported_version" ? await ctxPromise.then((r) => (r !== undefined && "ctx" in r ? (r.ctx ?? {}) : {}), () => ({})) : {});
330
356
  let cp;
331
357
  try {
332
358
  cp = await cpPromise;
@@ -337,31 +363,28 @@ export function createResumeLegs(ctx) {
337
363
  deps.logger?.warn?.("approval_decide_unreadable_row_withheld", { sessionId, note: "row unreadable and the caller's ownership of THAT token is unproven — folded into the uniform 404" });
338
364
  return noApproval;
339
365
  }
340
- if (e instanceof UnreadableCheckpointRowError && e.rowVerdict.kind !== "ok")
341
- return rowOwnRefusal(e.rowVerdict, errorText(e));
342
- return { status: 409, body: refusalBody({ errorCode: "conflict.checkpoint_unreadable", message: errorText(e) }) };
366
+ return rowReadRefusalAnswer(e);
343
367
  }
344
368
  if (!cp) {
345
369
  if (!(await mayDiscloseRowError(cs, token, decider)))
346
370
  return noApproval;
347
371
  return { status: 404, body: refusalBody({ errorCode: "not_found.checkpoint", message: "checkpoint not found" }) };
348
372
  }
349
- if (decider !== undefined && !decider.explicitOperator) {
350
- const cpOwner = decodeCheckpointScope(cp.scope);
351
- if (cpOwner !== undefined && cpOwner !== decider.principal) {
352
- deps.logger?.warn?.("approval_decide_row_scope_mismatch", { sessionId, note: "loaded pending row is foreign to the verified caller — TOCTOU fold" });
353
- return { status: 404, body: refusalBody({ errorCode: "not_found.approval", message: "approval not found" }) };
354
- }
373
+ if (!(await decisionRowAdmits(cs, token, decider, cp.scope))) {
374
+ deps.logger?.warn?.("approval_decide_row_scope_mismatch", { sessionId, note: "loaded pending row is foreign to the verified caller — TOCTOU fold" });
375
+ return { status: 404, body: refusalBody({ errorCode: "not_found.approval", message: "approval not found" }) };
355
376
  }
377
+ const verdict = judgeCheckpointRow(cp);
378
+ if (verdict.kind !== "ok")
379
+ return rowOwnRefusal(verdict);
356
380
  const decideGateKind = cp.gate?.kind;
357
381
  if (!isApprovalGateKind(decideGateKind)) {
358
- const verdict = judgeCheckpointRow(cp);
359
- if (verdict.kind !== "ok")
360
- return rowOwnRefusal(verdict);
361
382
  if (typeof decideGateKind !== "string" || decideGateKind === "") {
362
383
  return { status: 409, body: refusalBody({ errorCode: "gate_not_tool_approval", message: "task is suspended on a gate whose kind this engine cannot read, so it cannot say which endpoint resolves it" }) };
363
384
  }
364
- const activeForPath = await deps.runStore?.getActiveTaskId(sessionId).catch(() => undefined);
385
+ const ownerForPath = await runSessionPromise;
386
+ const runSessionForPath = ownerForPath.kind === "owned" ? ownerForPath.id : undefined;
387
+ const activeForPath = typeof runSessionForPath === "string" ? await deps.runStore?.getActiveTaskId(runSessionForPath).catch(() => undefined) : undefined;
365
388
  const gnPath = activeForPath ? resumeEntryForGate(decideGateKind, { sessionId, taskId: activeForPath }) : null;
366
389
  return {
367
390
  status: 409,
@@ -432,10 +455,10 @@ export function createResumeLegs(ctx) {
432
455
  noteLateSettleIfAccepted(committed);
433
456
  return intent === undefined ? out : { ...out, rememberApplied: await intent.settle(committed) };
434
457
  };
435
- const parkedForkQuotaDenial = req !== undefined ? ownerCostQuotaDenied(decodeCheckpointScope(cp.scope)) : undefined;
458
+ const parkedForkQuotaDenial = req !== undefined ? ownerCostQuotaDenied(checkpointPartsOf(cp.scope)?.person) : undefined;
436
459
  if (parkedForkQuotaDenial)
437
460
  return parkedForkQuotaDenial;
438
- const parkedForkLeaseDenial = req !== undefined ? await ownerFleetLeaseDenied(decodeCheckpointScope(cp.scope)) : undefined;
461
+ const parkedForkLeaseDenial = req !== undefined ? await ownerFleetLeaseDenied(checkpointPartsOf(cp.scope)?.person) : undefined;
439
462
  if (parkedForkLeaseDenial)
440
463
  return parkedForkLeaseDenial;
441
464
  const ownerLeaseAdmittedHere = req !== undefined;
@@ -460,19 +483,18 @@ export function createResumeLegs(ctx) {
460
483
  ...(boundGrant && intent ? { remember: { anchor: (rootSessionId) => boundGrant(rootSessionId), laneCannotRecord: intent.laneCannotRecord } } : {}),
461
484
  };
462
485
  if (origin?.kind === "background" && parkedAgentStore !== undefined && parkedSurface !== undefined) {
463
- const parked = await withPrincipal(decodeCheckpointScope(cp.scope), () => decideParkedAgent({
486
+ const parked = await withSubject(checkpointPartsOf(cp.scope)?.subject, () => decideParkedAgent({
464
487
  agentStore: parkedAgentStore,
465
488
  checkpointStore: cs,
466
489
  registry: defaultTaskRegistry,
467
490
  reviveSurface: parkedSurface,
468
- ...(deps.parkedKnownAgentTypes ? { knownAgentTypes: deps.parkedKnownAgentTypes } : {}),
469
491
  ...(deps.parkedReviveInheritedGate ? { rebuildInheritedGate: deps.parkedReviveInheritedGate } : {}),
470
492
  ...(deps.toolApproval ? { approverSeatFor: windowZeroSeatOf(deps.toolApproval) } : {}),
471
493
  execution: {
472
494
  resolve: async (root) => {
473
495
  let ctx;
474
496
  try {
475
- ctx = await resolveExecutionContext(deps, { kind: "continuation", root, principal: decodeCheckpointScope(cp.scope) });
497
+ ctx = await resolveExecutionContext(deps, { kind: "continuation", root, principal: checkpointPartsOf(cp.scope)?.person });
476
498
  }
477
499
  catch (e) {
478
500
  if (isRootSessionGoneError(e))
@@ -507,12 +529,15 @@ export function createResumeLegs(ctx) {
507
529
  const plan = planWorkflowParkedDecide(origin, parkedReq);
508
530
  if (!plan.ok)
509
531
  return plan.deny;
532
+ const fingerprint = parkDecisionFingerprint(plan.outcome, restatement);
533
+ const live = await deliverToHoldingRun(origin, { token, outcome: plan.outcome, decision: parkedReq.decision, fingerprint, restated: restatement !== undefined });
534
+ if (live.kind === "answered")
535
+ return live.answer;
510
536
  const decisions = deps.workflowParkDecisions;
511
537
  const runStore = deps.runStore;
512
538
  if (decisions === undefined || runStore === undefined) {
513
539
  return { status: 501, body: refusalBody({ errorCode: "capability.run_store_required", message: "delivering this decision requires a durable run store (DB_BACKEND=mysql|pg|local)" }) };
514
540
  }
515
- const fingerprint = parkDecisionFingerprint(plan.outcome, restatement);
516
541
  const liveReceiptOf = async (held) => {
517
542
  if (held === null || held.fingerprint !== fingerprint)
518
543
  return undefined;
@@ -542,7 +567,7 @@ export function createResumeLegs(ctx) {
542
567
  .catch(() => undefined);
543
568
  const admittedPayer = decodeCheckpointScope(cp.scope);
544
569
  const out = hostToken
545
- ? await resumeWake(plan.hostSessionId, plan.message, decider?.principal, req, acceptEarly, delivery, admittedPayer, restatement)
570
+ ? await resumeWake(plan.hostSessionId, plan.message, decider?.subject, req, acceptEarly, delivery, admittedPayer, restatement)
546
571
  : await startFreshHostTurn(plan.hostSessionId, plan.message.text, admittedPayer, req, delivery, plan.runId, restatement);
547
572
  if (recordFailure !== undefined)
548
573
  throw recordFailure.err;
@@ -551,16 +576,14 @@ export function createResumeLegs(ctx) {
551
576
  return out;
552
577
  }
553
578
  }
554
- const ctxRead0 = await readResumeCtx(ctxPromise, ctxOpening(sessionId));
555
- if (ctxRead0.kind === "corrupt")
556
- return resumeCtxCorruptAnswer(ctxRead0.where);
557
- if (ctxRead0.kind === "unsealable")
558
- return resumeCtxUnsealableAnswer(ctxRead0);
559
- const storedCtx = ctxRead0.kind === "ok" ? ctxRead0.ctx : null;
560
- if (!storedCtx)
579
+ const runCtx = await ctxPromise;
580
+ if (runCtx !== undefined && "refusal" in runCtx)
581
+ return runCtx.refusal;
582
+ if (runCtx === undefined || runCtx.ctx === null)
561
583
  return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
584
+ const { runSessionId, ctx: storedCtx } = runCtx;
562
585
  const ctx = restateResumeCtx(storedCtx, restatement);
563
- const auth = { sessionId: cp.sessionId, principal: decodeCheckpointScope(cp.scope), memoryScope: ctx.memoryScope };
586
+ const auth = { sessionId: runSessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
564
587
  const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
565
588
  if (!resolved.ok)
566
589
  return resolved.answer;
@@ -586,8 +609,10 @@ export function createResumeLegs(ctx) {
586
609
  ...(answer !== undefined ? { answer } : {}),
587
610
  hostDecision,
588
611
  };
589
- const verifyRounds = verifyRoundsFromBody(ctx.body);
590
- const driven = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: resolved.runner, legFacts: resolved.legFacts, token, sessionId: cp.sessionId, principal: auth.principal, fleetScope: resumeFleetScope(req, auth), taskConfig, resumeObjective, outcome, commitment: { kind: "gate_resolved", ...captureSelectedGate() }, verifyRounds, resumeCtx: { sessionId, ctx }, ...(engineNotices.length > 0 ? { engineNotices } : {}), ...(boundGrant ? { onResumeCommitted: boundGrant } : {}), ...(acceptEarly === true ? { acceptEarly: true } : {}), ...(req !== undefined ? { callerInitiated: true } : {}), ...(ownerLeaseAdmittedHere ? { ownerLeaseAdmitted: true } : {}) });
612
+ const composition = resumeCompositionOf(ctx.body, cp, deps.config.cascadeLadder);
613
+ if (composition?.entry === "cascade_unlinked")
614
+ return compositionUnlinkedAnswer();
615
+ const driven = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: resolved.runner, legFacts: resolved.legFacts, token, sessionId: runSessionId, subject: auth.subject, fleetScope: resumeFleetScope(req, auth), taskConfig, resumeObjective, outcome, commitment: { kind: "gate_resolved", ...captureSelectedGate() }, composition, resumeCtx: { sessionId: runSessionId, ctx }, ...(engineNotices.length > 0 ? { engineNotices } : {}), ...(boundGrant ? { onResumeCommitted: boundGrant } : {}), ...(acceptEarly === true ? { acceptEarly: true } : {}), ...(req !== undefined ? { callerInitiated: true } : {}), ...(ownerLeaseAdmittedHere ? { ownerLeaseAdmitted: true } : {}) });
591
616
  return await landAfterCommit(driven);
592
617
  }
593
618
  finally {
@@ -598,7 +623,7 @@ export function createResumeLegs(ctx) {
598
623
  const ONE_SHOT_SUBMIT_STRIP = Object.fromEntries(ONE_SHOT_SUBMIT_KEYS.map((k) => [k, undefined]));
599
624
  const resolveResumeSpec = async (ctx, req, auth, lease) => {
600
625
  const engineNotices = [];
601
- const execution = await resolveExecutionContext(deps, { kind: "continuation", root: auth.sessionId, principal: auth.principal });
626
+ const execution = await resolveExecutionContext(deps, { kind: "continuation", root: auth.sessionId, principal: auth.subject === undefined ? undefined : personOf(recoveredSubject(auth.subject)) });
602
627
  const resolved = await deps.resolveSpec({ ...ctx.body, ...ONE_SHOT_SUBMIT_STRIP }, req, auth, {
603
628
  leg: "resume",
604
629
  onNotice: (n) => engineNotices.push(n),
@@ -608,7 +633,7 @@ export function createResumeLegs(ctx) {
608
633
  });
609
634
  const legFacts = legFactsOf(resolved);
610
635
  const runner = runnerFor(resolved);
611
- const spec = stampSpecRoot(resolved, execution);
636
+ const spec = stampSpecRoot(resolved, execution, ctx.body);
612
637
  return { spec, runner, legFacts, engineNotices, execution };
613
638
  };
614
639
  const refuseStoredBodyReplay = (sessionId, refusal) => {
@@ -654,13 +679,22 @@ export function createResumeLegs(ctx) {
654
679
  }
655
680
  async function driveResumeLeg(args, onAccepted) {
656
681
  const resumeLegStartedAt = Date.now();
657
- const { runner: legRunner, token, sessionId, principal, fleetScope, taskConfig, resumeObjective, outcome, verifyRounds, resumeCtx, execution } = args;
682
+ const { runner: legRunner, token, sessionId, subject, fleetScope, taskConfig, resumeObjective, outcome, composition, resumeCtx, execution } = args;
683
+ const legSubject = recoveredSubject(subject);
684
+ const payer = legSubject === undefined ? undefined : personOf(legSubject);
658
685
  const heldObjective = objectiveWithheldIn(resumeCtx.ctx) ? undefined : resumeObjective;
659
686
  const reparkStatus = outcome.gate === "plan_review" ? "needs_review" : "suspended";
660
- const commitResumeCtx = () => Promise.resolve().then(() => deps.checkpointStore.putCtx(resumeCtx.sessionId, sealCheckpointCtx({ ...resumeCtx.ctx, writerVersion: serviceVersion() }, deps.checkpointCtxSealing, resumeCtx.sessionId))).catch((e) => {
687
+ const resumeCtxNotPersisted = (why) => {
661
688
  deps.metrics?.inc("resume_ctx_not_persisted_total");
662
- deps.logger?.warn?.("resume_ctx_not_persisted", { sessionId: resumeCtx.sessionId, gate: outcome.gate, error: errorText(e), note: "this continuation runs with the body it was given; the durable rebuild input still holds the PREVIOUS body, so the NEXT continuation of this session rebuilds from that one — its permission mode is never wider than this leg's, but if this leg restated its MCP / A2A peer tables (mcpServers / a2aPeers on the resume request), a later continuation that does not restate them runs with the previous tables again" });
663
- });
689
+ deps.logger?.warn?.("resume_ctx_not_persisted", { sessionId: resumeCtx.sessionId, gate: outcome.gate, error: why, note: "this continuation runs with the body it was given; the durable rebuild input still holds the PREVIOUS body, so the NEXT continuation of this session rebuilds from that one — its permission mode is never wider than this leg's, but if this leg restated its MCP / A2A peer tables (mcpServers / a2aPeers on the resume request), a later continuation that does not restate them runs with the previous tables again" });
690
+ };
691
+ const commitResumeCtx = () => Promise.resolve().then(async () => {
692
+ const sealed = sealCheckpointCtx({ ...resumeCtx.ctx, writerVersion: serviceVersion() }, deps.checkpointCtxSealing, resumeCtx.sessionId);
693
+ const claim = claimedRow && taskId !== undefined && deps.runStore !== undefined ? { fence: deps.runStore, taskId, legHolds: (run) => !runProvenElsewhere(run, deps.instanceId) } : undefined;
694
+ const landed = await deps.checkpointStore.putCtx(resumeCtx.sessionId, sealed, claim);
695
+ if (landed === "claim_released")
696
+ resumeCtxNotPersisted("claim_released: this run no longer holds the session claim (settled or reaped before the write-back landed) — nothing written");
697
+ }).catch((e) => resumeCtxNotPersisted(errorText(e)));
664
698
  const legKey = createHash("sha256").update(String(token)).digest("hex");
665
699
  const streamApprovalOn = resolveStreamApprovalGate({
666
700
  toolApprovalEnabled: Boolean(deps.toolApproval),
@@ -677,21 +711,21 @@ export function createResumeLegs(ctx) {
677
711
  declaredFamilies: declaredApprovalFrameFamilies(resumeCtx.ctx.body.settings),
678
712
  });
679
713
  const legDeadlineMonotonic = approvalLeg.legDeadlineMonotonic;
680
- const ownerQuotaDenial = args.callerInitiated === true ? ownerCostQuotaDenied(principal) : undefined;
714
+ const ownerQuotaDenial = args.callerInitiated === true ? ownerCostQuotaDenied(payer) : undefined;
681
715
  if (ownerQuotaDenial)
682
716
  return ownerQuotaDenial;
683
- const ownerLeaseDenial = args.callerInitiated === true && args.ownerLeaseAdmitted !== true ? await ownerFleetLeaseDenied(principal) : undefined;
717
+ const ownerLeaseDenial = args.callerInitiated === true && args.ownerLeaseAdmitted !== true ? await ownerFleetLeaseDenied(payer) : undefined;
684
718
  if (ownerLeaseDenial)
685
719
  return ownerLeaseDenial;
686
720
  const heldDecisions = await heldWorkflowParkDecisions(deps, sessionId, args.workflowDecision?.carried);
687
721
  let taskId = await deps.runStore?.getActiveTaskId(sessionId);
688
722
  let freshRunClaimed = false;
689
723
  if (args.mintFreshRun && taskId && deps.runStore) {
690
- return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, runStaleSec: deps.config.runStaleSec, turnActivity: readTurnActivityMs }, sessionId, taskId) };
724
+ return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, sessionId, taskId) };
691
725
  }
692
726
  if (!taskId && args.mintFreshRun && deps.runStore) {
693
727
  const freshId = uuidv7();
694
- const created = await timeClaim(deps.metrics, "run_claim", deps.runStore.createRun(freshId, sessionId, principal ?? null, deps.instanceId ?? "default", {
728
+ const created = await timeClaim(deps.metrics, "run_claim", deps.runStore.createRun(freshId, sessionId, subject ?? null, deps.instanceId ?? "default", {
695
729
  source: args.mintFreshRun.source,
696
730
  identity: args.mintFreshRun.identity,
697
731
  objectivePreview: heldObjective === undefined ? null : buildRunObjectivePreview(heldObjective),
@@ -702,7 +736,7 @@ export function createResumeLegs(ctx) {
702
736
  if (created.sessionAbsent)
703
737
  return rootSessionAbsentAnswer();
704
738
  if (!created.ok) {
705
- return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, runStaleSec: deps.config.runStaleSec, turnActivity: readTurnActivityMs }, sessionId, created.activeTaskId) };
739
+ return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, sessionId, created.activeTaskId) };
706
740
  }
707
741
  const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: freshId }, execution);
708
742
  if (placementReject)
@@ -717,9 +751,9 @@ export function createResumeLegs(ctx) {
717
751
  if (deps.toolApproval && taskId) {
718
752
  const toolApproval = deps.toolApproval;
719
753
  resumeTaskConfig.onAsk = approvalLeg.unattended
720
- ? toolApproval.boundUnattendedAsk({ owner: principal ?? null, taskId, sessionId, executionLane: execution.lane }, approvalLeg.unattended)
754
+ ? toolApproval.boundUnattendedAsk({ owner: subject ?? null, taskId, sessionId, executionLane: execution.lane }, approvalLeg.unattended)
721
755
  : toolApproval.boundAsk({
722
- owner: principal ?? null,
756
+ owner: subject ?? null,
723
757
  taskId,
724
758
  sessionId,
725
759
  executionLane: execution.lane,
@@ -751,6 +785,8 @@ export function createResumeLegs(ctx) {
751
785
  }
752
786
  };
753
787
  const settleCardForCancel = async () => {
788
+ if (freshRunClaimed)
789
+ return false;
754
790
  const cs2 = deps.checkpointStore;
755
791
  if (!cs2)
756
792
  return false;
@@ -786,7 +822,7 @@ export function createResumeLegs(ctx) {
786
822
  let resumeLegLive = false;
787
823
  const subagentHandleEvictions = [];
788
824
  let claimedRow = false;
789
- const cancelCtrl = createRunAbort(principal ?? null);
825
+ const cancelCtrl = createRunAbort(subject ?? null);
790
826
  let cancelLedgerAppend;
791
827
  const preemptCtrl = new AbortController();
792
828
  if (taskId && deps.runStore) {
@@ -798,14 +834,14 @@ export function createResumeLegs(ctx) {
798
834
  if (placementReject)
799
835
  return placementReject;
800
836
  }
801
- markChildrenStoppedByUserOnAbort(cancelCtrl.signal, taskId, principal);
837
+ markChildrenStoppedByUserOnAbort(cancelCtrl.signal, taskId, subject);
802
838
  fleetPub?.onStart();
803
839
  const rs = deps.runStore;
804
- const owner = principal ?? null;
840
+ const owner = subject ?? null;
805
841
  inflightRuns.set(taskId, cancelCtrl);
806
842
  preemptableRuns.set(taskId, preemptCtrl);
807
843
  resumeHeartbeat = setInterval(() => {
808
- void rs.heartbeat(taskId, owner).catch(() => undefined);
844
+ beatRunHeartbeat(rs, taskId, owner, () => cancelCtrl.abort("stall_verdict"), () => undefined);
809
845
  if (!cancelCtrl.signal.aborted) {
810
846
  void rs.isCancelRequested(taskId, owner).then((c) => { if (c)
811
847
  cancelCtrl.abort("cancel_verb"); }).catch(() => undefined);
@@ -834,12 +870,12 @@ export function createResumeLegs(ctx) {
834
870
  try {
835
871
  const instructionLeg = createInstructionSelectionLeg();
836
872
  const legWiringSections = () => ({ instructions: instructionLeg.segment(), skills: args.legFacts?.skills });
837
- result = await instructionLeg.run(sessionId, () => withModelReachScope({ sessionId, taskId }, () => withPrincipal(principal, async () => {
873
+ result = await instructionLeg.run(sessionId, () => withModelReachScope({ sessionId, taskId }, () => withSubject(legSubject, async () => {
838
874
  const resumeNotifiedKeys = new NotifiedKeys();
839
875
  if (deps.runStore && taskId) {
840
876
  const rs0 = deps.runStore;
841
877
  let drainSeq = (await rs0.maxSeq(taskId)) + 1;
842
- await emitPendingWorkflowCompletions(deps.workflowCompletionInbox, sessionId, principal ?? null, (frame) => {
878
+ await emitPendingWorkflowCompletions(deps.workflowCompletionInbox, sessionId, subject ?? null, (frame) => {
843
879
  const { type, ...rest } = frame;
844
880
  const f = frame;
845
881
  const write = rs0.appendEvent(taskId, drainSeq++, type, rest);
@@ -849,7 +885,7 @@ export function createResumeLegs(ctx) {
849
885
  return write;
850
886
  }, { route: "resume-open", connection: "durable-append", log: (m, x) => deps.logger?.info?.(m, x) });
851
887
  }
852
- if (verifyRounds !== undefined) {
888
+ if (composition !== undefined) {
853
889
  const rsV = deps.runStore;
854
890
  const vSeqBase = rsV && taskId ? await rsV.maxSeq(taskId) : 0;
855
891
  const verifySink = createLedgerSink({
@@ -891,7 +927,7 @@ export function createResumeLegs(ctx) {
891
927
  const parked = !resumeLegLive && Boolean(deps.workflowCompletionInbox && sessionId);
892
928
  deps.logger?.info?.("task_notification_observed", { route: "resume-verify", taskId: n.task_id, taskType: n.task_type, status: n.status, legLive: resumeLegLive, parkedDurable: parked });
893
929
  if (parked) {
894
- void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(sessionId, principal ?? null, n, Date.now(), taskId, opts?.priority)).catch((err) => deps.logger?.warn?.("park_enqueue_failed", { route: "resume-verify", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
930
+ void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(sessionId, subject ?? null, n, Date.now(), taskId, opts?.priority)).catch((err) => deps.logger?.warn?.("park_enqueue_failed", { route: "resume-verify", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
895
931
  }
896
932
  else if (resumeLegLive) {
897
933
  const key = taskNotificationDedupKey(n);
@@ -909,10 +945,23 @@ export function createResumeLegs(ctx) {
909
945
  : {}),
910
946
  };
911
947
  resumeLegLive = true;
912
- const vrEngine = await resumeWithVerification(legRunner, token, outcome, { ...resumeTaskConfig, signal: cancelCtrl.signal, preemptSignal: preemptCtrl.signal }, resumeObjective, verifyRounds, verifyInternals);
948
+ const legSpec = { ...resumeTaskConfig, signal: cancelCtrl.signal, preemptSignal: preemptCtrl.signal };
949
+ let vrEngine;
950
+ switch (composition.entry) {
951
+ case "verify":
952
+ vrEngine = await resumeWithVerification(legRunner, token, outcome, legSpec, resumeObjective, composition.rounds, verifyInternals);
953
+ break;
954
+ case "cascade":
955
+ vrEngine = await resumeCascade(legRunner, token, outcome, stampSpecRoot({ ...legSpec, ...composition.objectiveInputs, objective: resumeObjective }, execution, resumeCtx.ctx.body), composition.config, composition.parkedLeg, verifyInternals);
956
+ break;
957
+ default: {
958
+ const unhandled = composition;
959
+ throw new Error(`unhandled resume composition: ${JSON.stringify(unhandled)}`);
960
+ }
961
+ }
913
962
  const vrCause = cancelCtrl.cause();
914
963
  await voidVerifierPauseCard(vrEngine, legRunner);
915
- const vrJudged = atHostBoundary(vrEngine, sessionId);
964
+ const vrJudged = atHostBoundary(vrEngine);
916
965
  if (vrJudged.terminal.kind === "paused")
917
966
  heldPark = vrJudged;
918
967
  const vrMinted = vrCause !== undefined && taskId !== undefined ? mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: "cancelled by user", engineResult: vrJudged, cause: vrCause }) : vrJudged;
@@ -971,7 +1020,7 @@ export function createResumeLegs(ctx) {
971
1020
  });
972
1021
  if (deps.userInputLedger && taskId)
973
1022
  await deps.userInputLedger.announceUndrained({ sessionId, taskId });
974
- const anchorOwner = principal ?? null;
1023
+ const anchorOwner = subject ?? null;
975
1024
  const headOf = headReadOf(deps.sessionStorage);
976
1025
  const captureTurnAnchor = deps.resumeAnchorStore && headOf
977
1026
  ? async (eventId) => { const leaf = (await headOf(sessionId))?.leafId; if (leaf)
@@ -1037,7 +1086,7 @@ export function createResumeLegs(ctx) {
1037
1086
  const parked = !resumeLegLive && Boolean(deps.workflowCompletionInbox && sessionId);
1038
1087
  deps.logger?.info?.("task_notification_observed", { route: "resume", taskId: n.task_id, taskType: n.task_type, status: n.status, legLive: resumeLegLive, parkedDurable: parked });
1039
1088
  if (parked) {
1040
- void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(sessionId, principal ?? null, n, Date.now(), taskId, opts?.priority)).catch((err) => deps.logger?.warn?.("park_enqueue_failed", { route: "resume", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
1089
+ void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(sessionId, subject ?? null, n, Date.now(), taskId, opts?.priority)).catch((err) => deps.logger?.warn?.("park_enqueue_failed", { route: "resume", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
1041
1090
  }
1042
1091
  else if (resumeLegLive) {
1043
1092
  const key = taskNotificationDedupKey(n);
@@ -1227,25 +1276,22 @@ export function createResumeLegs(ctx) {
1227
1276
  }
1228
1277
  return safe;
1229
1278
  };
1230
- const approvalEmit = (frame) => {
1231
- const { type, ...rest } = frame;
1232
- return append(type, rest);
1233
- };
1279
+ const hitlTransport = createHitlTransport({ ledger: append });
1234
1280
  const withApproval = () => deps.toolApproval && taskId && approvalLeg.active && approvalLeg.unattended === undefined
1235
1281
  ? deps.toolApproval.runWithContext({
1236
1282
  taskId,
1237
- owner: principal ?? null,
1283
+ owner: subject ?? null,
1238
1284
  abortSignal: cancelCtrl.signal,
1239
1285
  sessionId,
1240
1286
  executionLane: execution.lane,
1241
- emitCard: createApprovalCardEmitter({ appendDurable: (f) => approvalEmit(f) }),
1242
- emitRevoke: (f) => approvalEmit(f),
1287
+ family: "approval_request",
1288
+ transport: hitlTransport,
1243
1289
  legKey,
1244
1290
  ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}),
1245
1291
  }, driveResume)
1246
1292
  : driveResume();
1247
1293
  const withElicitation = () => deps.elicitation && taskId
1248
- ? deps.elicitation.runWithContext({ taskId, owner: principal ?? null, emit: (frame) => { const { type, ...rest } = frame; return append(type, rest); }, abortSignal: cancelCtrl.signal }, withApproval)
1294
+ ? deps.elicitation.runWithContext({ taskId, owner: subject ?? null, transport: hitlTransport, abortSignal: cancelCtrl.signal }, withApproval)
1249
1295
  : withApproval();
1250
1296
  return await (deps.sendUserFile && taskId
1251
1297
  ? deps.sendUserFile.runWithContext({ taskId, emit: async (frame) => { const { type, ...rest } = frame; await append(type, rest); } }, withElicitation)
@@ -1301,7 +1347,7 @@ export function createResumeLegs(ctx) {
1301
1347
  }
1302
1348
  if (claimedRow && taskId && deps.runStore) {
1303
1349
  await voidHeldParkCard(heldPark, sessionId, deps.checkpointStore, "resume");
1304
- await deps.runStore.setTerminal(taskId, "failed", null, errorText(e)).catch(() => undefined);
1350
+ await deps.runStore.setTerminal(taskId, "failed", null, outwardThrownMessage(e, errorText(e))).catch(() => undefined);
1305
1351
  }
1306
1352
  settleFleet("failed");
1307
1353
  throw e;
@@ -1339,7 +1385,7 @@ export function createResumeLegs(ctx) {
1339
1385
  else
1340
1386
  await deps.runStore.setTerminal(taskId, resumePlane.status, sealed, resumePlane.errorMessage ?? null);
1341
1387
  }
1342
- settleFleet(checkpointReopened ? reparkStatus : resumePlane.status, fleetRunResiduals(sealed));
1388
+ settleFleet(checkpointReopened ? reparkStatus : resumePlane.status, fleetRunResiduals(sealed, sealed ? failureCodeOf(sealed.terminal) : undefined));
1343
1389
  return {
1344
1390
  status: 200,
1345
1391
  body: {
@@ -1353,7 +1399,7 @@ export function createResumeLegs(ctx) {
1353
1399
  };
1354
1400
  }
1355
1401
  async function mayDiscloseRowError(cs, token, decider) {
1356
- if (decider === undefined || decider.explicitOperator)
1402
+ if (decider === undefined || decider.operator)
1357
1403
  return true;
1358
1404
  let scope;
1359
1405
  try {
@@ -1365,24 +1411,28 @@ export function createResumeLegs(ctx) {
1365
1411
  }
1366
1412
  if (scope === undefined)
1367
1413
  return false;
1368
- const owner = decodeCheckpointScope(scope ?? CHECKPOINT_PUBLIC_SCOPE);
1369
- return owner === undefined || owner === decider.principal;
1414
+ return keyAdmits("scope.decide", decider, scopeCellOf(scope ?? CHECKPOINT_PUBLIC_SCOPE));
1415
+ }
1416
+ async function decisionRowAdmits(cs, token, who, bodyScope) {
1417
+ if (who === undefined)
1418
+ return true;
1419
+ const cell = bodyScope === undefined ? undefined : scopeCellOf(bodyScope);
1420
+ return cell !== undefined ? keyAdmits("scope.decide", who, cell) : mayDiscloseRowError(cs, token, who);
1370
1421
  }
1371
1422
  async function resumePreempted(sessionId, req, acceptEarly, decider, restatement) {
1372
1423
  const cs = deps.checkpointStore;
1373
1424
  const RESUMABLE_GATE_KIND = "resource_limit";
1374
- const preemptBinding = { gateKinds: [RESUMABLE_GATE_KIND] };
1375
- const token = (await cs.findPendingTokenBySession(sessionId, undefined, preemptBinding)) ?? (await cs.findPendingTokenBySession(sessionId));
1425
+ const preemptBinding = { gateKinds: [RESUMABLE_GATE_KIND], axis: "run" };
1426
+ const token = (await cs.findPendingTokenBySession(sessionId, undefined, preemptBinding)) ?? (await cs.findPendingTokenBySession(sessionId, undefined, { axis: "run" }));
1376
1427
  const noSuspension = { status: 404, body: refusalBody({ errorCode: "not_found.suspension", message: "no resumable suspension for this task (already running, resumed, or expired)" }) };
1377
1428
  if (!token)
1378
1429
  return noSuspension;
1379
- if (decider !== undefined && !decider.explicitOperator) {
1430
+ if (decider !== undefined && !decider.operator) {
1380
1431
  const peeked = await cs
1381
1432
  .peekPendingScope(sessionId, preemptBinding)
1382
- .then((sc) => (sc === undefined ? cs.peekPendingScope(sessionId) : sc))
1433
+ .then((sc) => (sc === undefined ? cs.peekPendingScope(sessionId, { axis: "run" }) : sc))
1383
1434
  .catch(() => undefined);
1384
- const peekedOwner = peeked != null ? decodeCheckpointScope(peeked) : undefined;
1385
- if (peekedOwner !== undefined && peekedOwner !== decider.principal) {
1435
+ if (!keyAdmits("scope.decide", decider, scopeCellOf(peeked ?? CHECKPOINT_PUBLIC_SCOPE))) {
1386
1436
  deps.logger?.warn?.("assistant_resume_row_scope_mismatch", { sessionId, note: "pending row is foreign to the verified caller — owner gate ahead of the row load" });
1387
1437
  return noSuspension;
1388
1438
  }
@@ -1396,14 +1446,14 @@ export function createResumeLegs(ctx) {
1396
1446
  deps.logger?.warn?.("assistant_resume_unreadable_row_withheld", { sessionId, note: "row unreadable and the caller's ownership of THAT token is unproven — folded into the uniform 404" });
1397
1447
  return noSuspension;
1398
1448
  }
1399
- return { status: 409, body: refusalBody({ errorCode: "conflict.checkpoint_unreadable", message: e instanceof Error ? e.message : String(e) }) };
1449
+ return rowReadRefusalAnswer(e);
1400
1450
  }
1401
1451
  if (!cp) {
1402
1452
  if (!(await mayDiscloseRowError(cs, token, decider)))
1403
1453
  return noSuspension;
1404
1454
  return { status: 404, body: refusalBody({ errorCode: "not_found.checkpoint", message: "checkpoint not found" }) };
1405
1455
  }
1406
- if (decider !== undefined && !decider.explicitOperator && cp.scope !== CHECKPOINT_PUBLIC_SCOPE && cp.scope !== decider.principal) {
1456
+ if (decider !== undefined && !keyAdmits("scope.decide", decider, scopeCellOf(cp.scope))) {
1407
1457
  deps.logger?.warn?.("assistant_resume_row_scope_mismatch", { sessionId, note: "loaded pending row is foreign to the verified caller — TOCTOU fold" });
1408
1458
  return noSuspension;
1409
1459
  }
@@ -1416,25 +1466,29 @@ export function createResumeLegs(ctx) {
1416
1466
  return resumeCtxCorruptAnswer(ctxRead.where);
1417
1467
  if (ctxRead.kind === "unsealable")
1418
1468
  return resumeCtxUnsealableAnswer(ctxRead);
1469
+ if (ctxRead.kind === "unreadable")
1470
+ return resumeCtxUnreadableAnswer();
1419
1471
  if (ctxRead.kind === "absent")
1420
1472
  return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
1421
1473
  const ctx = restateResumeCtx(ctxRead.ctx, restatement);
1422
- const auth = { sessionId: cp.sessionId, principal: decodeCheckpointScope(cp.scope), memoryScope: ctx.memoryScope };
1474
+ const auth = { sessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
1423
1475
  const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
1424
1476
  if (!resolved.ok)
1425
1477
  return resolved.answer;
1426
1478
  try {
1427
1479
  const { spec, engineNotices } = resolved;
1428
1480
  const { objective: resumeObjective, sessionId: _sessionId, ...taskConfig } = spec;
1429
- const verifyRounds = verifyRoundsFromBody(ctx.body);
1481
+ const composition = resumeCompositionOf(ctx.body, cp, deps.config.cascadeLadder);
1482
+ if (composition?.entry === "cascade_unlinked")
1483
+ return compositionUnlinkedAnswer();
1430
1484
  const selectedGate = durableRowIdentity("decision-receipt", cp.checkpointId, token);
1431
- return await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: resolved.runner, legFacts: resolved.legFacts, token, sessionId: cp.sessionId, principal: auth.principal, fleetScope: resumeFleetScope(req, auth), taskConfig, resumeObjective, outcome: { gate: "resource_limit", decision: "continue" }, commitment: { kind: "gate_resolved", ...selectedGate }, verifyRounds, resumeCtx: { sessionId, ctx }, ...(engineNotices.length > 0 ? { engineNotices } : {}), ...(acceptEarly === true ? { acceptEarly: true } : {}), ...(req !== undefined ? { callerInitiated: true } : {}) });
1485
+ return await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: resolved.runner, legFacts: resolved.legFacts, token, sessionId, subject: auth.subject, fleetScope: resumeFleetScope(req, auth), taskConfig, resumeObjective, outcome: { gate: "resource_limit", decision: "continue" }, commitment: { kind: "gate_resolved", ...selectedGate }, composition, resumeCtx: { sessionId, ctx }, ...(engineNotices.length > 0 ? { engineNotices } : {}), ...(acceptEarly === true ? { acceptEarly: true } : {}), ...(req !== undefined ? { callerInitiated: true } : {}) });
1432
1486
  }
1433
1487
  finally {
1434
1488
  resolved.peerLease.release();
1435
1489
  }
1436
1490
  }
1437
- async function startFreshHostTurn(sessionId, objective, principal, req, workflowDecision, runId, restatement) {
1491
+ async function startFreshHostTurn(sessionId, objective, subject, req, workflowDecision, runId, restatement) {
1438
1492
  const cs = deps.checkpointStore;
1439
1493
  if (!deps.runStore) {
1440
1494
  return { status: 501, body: refusalBody({ errorCode: "capability.run_store_required", message: "delivering this decision requires a durable run store (DB_BACKEND=mysql|pg|local)" }) };
@@ -1444,6 +1498,8 @@ export function createResumeLegs(ctx) {
1444
1498
  return resumeCtxCorruptAnswer(ctxRead.where);
1445
1499
  if (ctxRead.kind === "unsealable")
1446
1500
  return resumeCtxUnsealableAnswer(ctxRead);
1501
+ if (ctxRead.kind === "unreadable")
1502
+ return resumeCtxUnreadableAnswer();
1447
1503
  const storedCtx = ctxRead.kind === "ok" ? ctxRead.ctx : null;
1448
1504
  if (!storedCtx) {
1449
1505
  return {
@@ -1459,10 +1515,10 @@ export function createResumeLegs(ctx) {
1459
1515
  };
1460
1516
  }
1461
1517
  const ctx = restateResumeCtx(storedCtx, restatement);
1462
- const windowDenial = await usageWindowDenialFor(principal || GLOBAL_USAGE_KEY);
1518
+ const windowDenial = await usageWindowDenialFor(subject === undefined ? undefined : personOf(recoveredSubject(subject)));
1463
1519
  if (windowDenial)
1464
1520
  return { status: windowDenial.status, body: windowDenial.body };
1465
- const auth = { sessionId, principal, memoryScope: ctx.memoryScope };
1521
+ const auth = { sessionId, subject, memoryScope: ctx.memoryScope };
1466
1522
  const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
1467
1523
  if (!resolved.ok)
1468
1524
  return resolved.answer;
@@ -1470,11 +1526,11 @@ export function createResumeLegs(ctx) {
1470
1526
  const { spec, engineNotices } = resolved;
1471
1527
  const hostSpec = { ...spec, objective };
1472
1528
  const out = await mintAndDriveDurableRun(routeCtxBase, deps.runStore, {
1473
- prepared: { spec: hostSpec, runner: resolved.runner, legFacts: resolved.legFacts, auth, body: ctx.body, ...(objectiveWithheldIn(ctx) ? { bodyFromScreenedCtx: true } : {}), acceptance: createRunAcceptance({}, { objective, screened: false }), peerLease: resolved.peerLease, execution: resolved.execution, ...(engineNotices.length > 0 ? { engineNotices } : {}) },
1529
+ 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 } : {}) },
1474
1530
  fleetScope: resumeFleetScope(req, auth),
1475
- elicitOwner: principal ?? null,
1531
+ elicitOwner: subject ?? null,
1476
1532
  source: "workflow_parked_decide",
1477
- identity: runIdentityOf(req, deps.config, principal ?? null),
1533
+ identity: runIdentityOf(req, deps.config, subject ?? null),
1478
1534
  workflowDecision,
1479
1535
  });
1480
1536
  if (out.existing) {
@@ -1495,11 +1551,10 @@ export function createResumeLegs(ctx) {
1495
1551
  const token = (await cs.findPendingTokenBySession(sessionId, undefined, wakeBinding)) ?? (await cs.findPendingTokenBySession(sessionId));
1496
1552
  if (!token)
1497
1553
  return { status: 404, body: refusalBody({ errorCode: "not_found.parked_checkpoint", message: "no parked checkpoint for this session (nothing to wake)" }) };
1498
- const operator = explicitOperatorOk(caller, deps.config);
1499
- if (!operator) {
1554
+ const who = { subject: caller, operator: explicitOperatorOk(caller === undefined ? undefined : personOf(caller), deps.config) };
1555
+ if (!who.operator) {
1500
1556
  const scope = await cs.peekPendingScope(sessionId, wakeBinding).then((s) => (s === undefined ? cs.peekPendingScope(sessionId) : s)).catch(() => undefined);
1501
- const decodedScope = scope != null ? decodeCheckpointScope(scope) : undefined;
1502
- if (decodedScope !== undefined && decodedScope !== caller) {
1557
+ if (!keyAdmits("scope.decide", who, scopeCellOf(scope ?? CHECKPOINT_PUBLIC_SCOPE))) {
1503
1558
  return { status: 404, body: refusalBody({ errorCode: "not_found.parked_checkpoint", message: "no parked checkpoint for this session (nothing to wake)" }) };
1504
1559
  }
1505
1560
  }
@@ -1508,19 +1563,19 @@ export function createResumeLegs(ctx) {
1508
1563
  cp = await cs.get(token);
1509
1564
  }
1510
1565
  catch (e) {
1511
- if (!(await mayDiscloseRowError(cs, token, { principal: caller, explicitOperator: operator }))) {
1566
+ if (!(await mayDiscloseRowError(cs, token, who))) {
1512
1567
  deps.logger?.warn?.("wake_unreadable_row_withheld", { sessionId, note: "row unreadable and the caller's ownership of THAT token is unproven — folded into the uniform 404" });
1513
1568
  return { status: 404, body: refusalBody({ errorCode: "not_found.parked_checkpoint", message: "no parked checkpoint for this session (nothing to wake)" }) };
1514
1569
  }
1515
- return { status: 409, body: refusalBody({ errorCode: "conflict.checkpoint_unreadable", message: e instanceof Error ? e.message : String(e) }) };
1570
+ return rowReadRefusalAnswer(e);
1516
1571
  }
1517
1572
  if (!cp) {
1518
- if (!(await mayDiscloseRowError(cs, token, { principal: caller, explicitOperator: operator }))) {
1573
+ if (!(await mayDiscloseRowError(cs, token, who))) {
1519
1574
  return { status: 404, body: refusalBody({ errorCode: "not_found.parked_checkpoint", message: "no parked checkpoint for this session (nothing to wake)" }) };
1520
1575
  }
1521
1576
  return { status: 404, body: refusalBody({ errorCode: "not_found.checkpoint", message: "checkpoint not found" }) };
1522
1577
  }
1523
- if (!operator && cp.scope !== CHECKPOINT_PUBLIC_SCOPE && cp.scope !== caller) {
1578
+ if (!keyAdmits("scope.decide", who, scopeCellOf(cp.scope))) {
1524
1579
  return { status: 404, body: refusalBody({ errorCode: "not_found.parked_checkpoint", message: "no parked checkpoint for this session (nothing to wake)" }) };
1525
1580
  }
1526
1581
  const gateKind = cp.gate?.kind;
@@ -1543,10 +1598,12 @@ export function createResumeLegs(ctx) {
1543
1598
  return resumeCtxCorruptAnswer(ctxRead.where);
1544
1599
  if (ctxRead.kind === "unsealable")
1545
1600
  return resumeCtxUnsealableAnswer(ctxRead);
1601
+ if (ctxRead.kind === "unreadable")
1602
+ return resumeCtxUnreadableAnswer();
1546
1603
  if (ctxRead.kind === "absent")
1547
1604
  return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
1548
1605
  const ctx = restateResumeCtx(ctxRead.ctx, restatement);
1549
- const auth = { sessionId: cp.sessionId, principal: decodeCheckpointScope(cp.scope), memoryScope: ctx.memoryScope };
1606
+ const auth = { sessionId: cp.sessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
1550
1607
  const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
1551
1608
  if (!resolved.ok)
1552
1609
  return resolved.answer;
@@ -1560,20 +1617,20 @@ export function createResumeLegs(ctx) {
1560
1617
  legFacts: resolved.legFacts,
1561
1618
  token,
1562
1619
  sessionId: cp.sessionId,
1563
- principal: auth.principal,
1620
+ subject: auth.subject,
1564
1621
  fleetScope: resumeFleetScope(req, auth),
1565
1622
  taskConfig,
1566
1623
  resumeObjective,
1567
1624
  outcome: { gate: "wake", ...(message !== undefined ? { message } : {}) },
1568
1625
  commitment: { kind: "delivered" },
1569
- verifyRounds: undefined,
1626
+ composition: undefined,
1570
1627
  resumeCtx: { sessionId, ctx },
1571
- mintFreshRun: { source: "wake", identity: runIdentityOf(req, deps.config, auth.principal ?? null) },
1628
+ mintFreshRun: { source: "wake", identity: runIdentityOf(req, deps.config, auth.subject ?? null) },
1572
1629
  ...(workflowDecision !== undefined ? { workflowDecision } : {}),
1573
1630
  ...(engineNotices.length > 0 ? { engineNotices } : {}),
1574
1631
  ...(acceptEarly === true ? { acceptEarly: true } : {}),
1575
1632
  ...(req !== undefined ? { callerInitiated: true } : {}),
1576
- ...(ownerLeaseAdmittedFor !== undefined && auth.principal === ownerLeaseAdmittedFor ? { ownerLeaseAdmitted: true } : {}),
1633
+ ...(ownerLeaseAdmittedFor !== undefined && auth.subject === ownerLeaseAdmittedFor ? { ownerLeaseAdmitted: true } : {}),
1577
1634
  });
1578
1635
  }
1579
1636
  finally {
@@ -1589,20 +1646,19 @@ export function createResumeLegs(ctx) {
1589
1646
  ...(log?.principalPresent !== undefined ? { principalPresent: log.principalPresent } : {}),
1590
1647
  });
1591
1648
  const PLAN_REVIEW_GATE_KIND = "plan_review";
1592
- const planReviewBinding = { gateKinds: [PLAN_REVIEW_GATE_KIND] };
1593
- const token = (await cs.findPendingTokenBySession(sessionId, undefined, planReviewBinding)) ?? (await cs.findPendingTokenBySession(sessionId));
1649
+ const planReviewBinding = { gateKinds: [PLAN_REVIEW_GATE_KIND], axis: "run" };
1650
+ const token = (await cs.findPendingTokenBySession(sessionId, undefined, planReviewBinding)) ?? (await cs.findPendingTokenBySession(sessionId, undefined, { axis: "run" }));
1594
1651
  const noPending = { status: 404, body: refusalBody({ errorCode: "not_found.plan_review", message: "no pending plan_review for this session (already decided or expired)" }) };
1595
1652
  if (!token) {
1596
1653
  log404("no-pending-checkpoint");
1597
1654
  return refuse(noPending);
1598
1655
  }
1599
- if (decider !== undefined && !decider.explicitOperator) {
1656
+ if (decider !== undefined && !decider.operator) {
1600
1657
  const peeked = await cs
1601
1658
  .peekPendingScope(sessionId, planReviewBinding)
1602
- .then((sc) => (sc === undefined ? cs.peekPendingScope(sessionId) : sc))
1659
+ .then((sc) => (sc === undefined ? cs.peekPendingScope(sessionId, { axis: "run" }) : sc))
1603
1660
  .catch(() => undefined);
1604
- const peekedOwner = peeked != null ? decodeCheckpointScope(peeked) : undefined;
1605
- if (peekedOwner !== undefined && peekedOwner !== decider.principal) {
1661
+ if (!keyAdmits("scope.decide", decider, scopeCellOf(peeked ?? CHECKPOINT_PUBLIC_SCOPE))) {
1606
1662
  deps.logger?.warn?.("plan_review_row_scope_mismatch", { sessionId, note: "pending row is foreign to the verified caller — owner gate ahead of the row load" });
1607
1663
  return refuse(noPending);
1608
1664
  }
@@ -1616,7 +1672,7 @@ export function createResumeLegs(ctx) {
1616
1672
  deps.logger?.warn?.("plan_review_unreadable_row_withheld", { sessionId, note: "row unreadable and the caller's ownership of THAT token is unproven — folded into the uniform 404" });
1617
1673
  return refuse(noPending);
1618
1674
  }
1619
- return refuse({ status: 409, body: refusalBody({ errorCode: "conflict.checkpoint_unreadable", message: e instanceof Error ? e.message : String(e) }) });
1675
+ return refuse(rowReadRefusalAnswer(e));
1620
1676
  }
1621
1677
  if (!cp) {
1622
1678
  log404("checkpoint-missing");
@@ -1624,7 +1680,7 @@ export function createResumeLegs(ctx) {
1624
1680
  return refuse(noPending);
1625
1681
  return refuse({ status: 404, body: refusalBody({ errorCode: "not_found.checkpoint", message: "checkpoint not found" }) });
1626
1682
  }
1627
- if (decider !== undefined && !decider.explicitOperator && cp.scope !== CHECKPOINT_PUBLIC_SCOPE && cp.scope !== decider.principal) {
1683
+ if (decider !== undefined && !keyAdmits("scope.decide", decider, scopeCellOf(cp.scope))) {
1628
1684
  deps.logger?.warn?.("plan_review_row_scope_mismatch", { sessionId, note: "loaded pending row is foreign to the verified caller — TOCTOU fold" });
1629
1685
  return refuse(noPending);
1630
1686
  }
@@ -1650,6 +1706,8 @@ export function createResumeLegs(ctx) {
1650
1706
  return refuse(resumeCtxCorruptAnswer(ctxRead.where));
1651
1707
  if (ctxRead.kind === "unsealable")
1652
1708
  return refuse(resumeCtxUnsealableAnswer(ctxRead));
1709
+ if (ctxRead.kind === "unreadable")
1710
+ return refuse(resumeCtxUnreadableAnswer());
1653
1711
  if (ctxRead.kind === "absent")
1654
1712
  return refuse({ status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) });
1655
1713
  const ctx = restateResumeCtx(ctxRead.ctx, restatement);
@@ -1660,9 +1718,9 @@ export function createResumeLegs(ctx) {
1660
1718
  }
1661
1719
  async function drivePlanReview(prepared, decision, editedPlan, reason, hostDecision, req, acceptEarly, permissionModeAfter) {
1662
1720
  const { sessionId, token, cp, ctx } = prepared;
1663
- if ((await deps.checkpointStore.findPendingTokenBySession(sessionId, undefined, { gateKinds: ["plan_review"] })) !== token)
1721
+ if ((await deps.checkpointStore.findPendingTokenBySession(sessionId, undefined, { gateKinds: ["plan_review"], axis: "run" })) !== token)
1664
1722
  return notResumableAnswer();
1665
- const auth = { sessionId: cp.sessionId, principal: decodeCheckpointScope(cp.scope), memoryScope: ctx.memoryScope };
1723
+ const auth = { sessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
1666
1724
  const effMode = storedBodyPermissionMode(ctx.body);
1667
1725
  if (permissionModeAfter !== undefined && effMode !== "plan") {
1668
1726
  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)");
@@ -1675,7 +1733,9 @@ export function createResumeLegs(ctx) {
1675
1733
  try {
1676
1734
  const { spec, engineNotices } = resolved;
1677
1735
  const { objective: resumeObjective, sessionId: _sessionId, ...taskConfig } = spec;
1678
- const verifyRounds = verifyRoundsFromBody(ctx.body);
1736
+ const composition = resumeCompositionOf(ctx.body, cp, deps.config.cascadeLadder);
1737
+ if (composition?.entry === "cascade_unlinked")
1738
+ return compositionUnlinkedAnswer();
1679
1739
  const outcome = {
1680
1740
  gate: "plan_review",
1681
1741
  decision,
@@ -1684,7 +1744,7 @@ export function createResumeLegs(ctx) {
1684
1744
  hostDecision,
1685
1745
  };
1686
1746
  const selectedGate = durableRowIdentity("decision-receipt", cp.checkpointId, token);
1687
- const out = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: resolved.runner, legFacts: resolved.legFacts, token, sessionId: cp.sessionId, principal: auth.principal, fleetScope: resumeFleetScope(req, auth), taskConfig, resumeObjective, outcome, commitment: { kind: "gate_resolved", ...selectedGate }, verifyRounds, resumeCtx: { sessionId, ctx: rebuildCtx }, ...(engineNotices.length > 0 ? { engineNotices } : {}), ...(acceptEarly === true ? { acceptEarly: true } : {}), ...(req !== undefined ? { callerInitiated: true } : {}) });
1747
+ const out = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: resolved.runner, legFacts: resolved.legFacts, token, sessionId, subject: auth.subject, fleetScope: resumeFleetScope(req, auth), taskConfig, resumeObjective, outcome, commitment: { kind: "gate_resolved", ...selectedGate }, composition, resumeCtx: { sessionId, ctx: rebuildCtx }, ...(engineNotices.length > 0 ? { engineNotices } : {}), ...(acceptEarly === true ? { acceptEarly: true } : {}), ...(req !== undefined ? { callerInitiated: true } : {}) });
1688
1748
  return out;
1689
1749
  }
1690
1750
  finally {
@@ -1700,10 +1760,10 @@ export function createResumeLegs(ctx) {
1700
1760
  const routeCtxBase = {
1701
1761
  deps,
1702
1762
  registry: { idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters },
1703
- helpers: { readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, admitRun, safeDecode, runOwnerOk, sessionOwnerOk, runSessionAcceptOk },
1763
+ helpers: { readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, admitRun, safeDecode },
1704
1764
  local: { images: createImagesLocal(deps), sessions: createSessionsLocal(), sessionSync: createSessionSyncLocal(), capabilities: createCapabilitiesLocal() },
1705
1765
  legs: { prepareSpec, finalizeTaskResult, resumeCheckpoint, driveResumeIntoRunLog, resumePreempted, resumeWake, preparePlanReview, drivePlanReview, sessionNotify: sessionNotifyDoor },
1706
1766
  };
1707
- return { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, mayDiscloseRowError, resumePreempted, startFreshHostTurn, resumeWake, preparePlanReview, drivePlanReview, sessionNotifyDoor };
1767
+ return { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, decisionRowAdmits, resumePreempted, startFreshHostTurn, resumeWake, preparePlanReview, drivePlanReview, sessionNotifyDoor };
1708
1768
  }
1709
1769
  //# sourceMappingURL=resume-legs.js.map