@sema-agent/server 7.149.0 → 7.151.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 (441) hide show
  1. package/MIGRATION.md +307 -9
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +92 -40
  5. package/deploy/sema-up/README.md +7 -1
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
  9. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
  10. package/deploy/sema-up/chart/templates/server.yaml +5 -3
  11. package/deploy/sema-up/chart/values-full-single.yaml +3 -1
  12. package/deploy/sema-up/chart/values.yaml +8 -1
  13. package/deploy/sema-up/cluster-up.sh +1 -0
  14. package/deploy/sema-up/kube-up.sh +1 -1
  15. package/deploy/sema-up/lib/flagshape.sh +1 -1
  16. package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
  17. package/deploy/sema-up/lib/helm-values-kube.py +2 -0
  18. package/dist/adoption/import.js +3 -3
  19. package/dist/approval-ask-machine.d.ts +1 -1
  20. package/dist/approval-card.d.ts +3 -3
  21. package/dist/approval-gate-currency.d.ts +2 -2
  22. package/dist/audit.d.ts +1 -1
  23. package/dist/audit.js +2 -2
  24. package/dist/auth-bridge.d.ts +20 -0
  25. package/dist/auth-bridge.js +9 -0
  26. package/dist/background-session-reap.d.ts +2 -2
  27. package/dist/bake-runner/main.d.ts +4 -2
  28. package/dist/bind-host.d.ts +2 -3
  29. package/dist/bind-host.js +2 -4
  30. package/dist/boot/budget-tracing.js +1 -1
  31. package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
  32. package/dist/boot/deferred-sandbox-path-env.js +1 -2
  33. package/dist/boot/engine-lease.d.ts +5 -0
  34. package/dist/boot/engine-lease.js +1 -0
  35. package/dist/boot/execution-env.d.ts +8 -14
  36. package/dist/boot/execution-env.js +54 -17
  37. package/dist/boot/execution-lane.js +32 -5
  38. package/dist/boot/late-binds.d.ts +8 -4
  39. package/dist/boot/late-binds.js +7 -1
  40. package/dist/boot/memory-consolidation.d.ts +3 -2
  41. package/dist/boot/memory-consolidation.js +6 -6
  42. package/dist/boot/parked-revive-gate.d.ts +5 -5
  43. package/dist/boot/parked-revive-gate.js +2 -3
  44. package/dist/boot/reapers.d.ts +5 -0
  45. package/dist/boot/reapers.js +12 -1
  46. package/dist/boot/resolve-spec.d.ts +7 -8
  47. package/dist/boot/resolve-spec.js +80 -35
  48. package/dist/boot/retention-lane.d.ts +1 -1
  49. package/dist/boot/runner-deps.d.ts +9 -2
  50. package/dist/boot/runner-deps.js +3 -3
  51. package/dist/boot/session-age-out.d.ts +36 -0
  52. package/dist/boot/session-age-out.js +101 -0
  53. package/dist/boot/session-faces.d.ts +5 -14
  54. package/dist/boot/session-faces.js +28 -24
  55. package/dist/boot/stage-01-config.js +2 -0
  56. package/dist/boot/stage-03-store-backend.js +2 -2
  57. package/dist/boot/stage-05-execution-env.d.ts +5 -3
  58. package/dist/boot/stage-05-execution-env.js +2 -2
  59. package/dist/boot/stage-06-runners.d.ts +7 -4
  60. package/dist/boot/stage-06-runners.js +16 -8
  61. package/dist/boot/stage-07-capability-layer.d.ts +7 -4
  62. package/dist/boot/stage-07-capability-layer.js +3 -2
  63. package/dist/boot/stage-08-reapers.d.ts +7 -4
  64. package/dist/boot/stage-08-reapers.js +4 -2
  65. package/dist/boot/stage-09-leader.d.ts +11 -5
  66. package/dist/boot/stage-09-leader.js +12 -3
  67. package/dist/boot/stage-10-http-server.d.ts +44 -6
  68. package/dist/boot/stage-10-http-server.js +12 -10
  69. package/dist/boot/web-admin.d.ts +1 -1
  70. package/dist/boot/web-admin.js +3 -1
  71. package/dist/boot/workflow-orchestration.d.ts +7 -2
  72. package/dist/boot/workflow-orchestration.js +24 -7
  73. package/dist/bounded-rotation.d.ts +29 -0
  74. package/dist/bounded-rotation.js +24 -0
  75. package/dist/capability-facts.d.ts +84 -66
  76. package/dist/capability-facts.js +58 -41
  77. package/dist/center-credential.d.ts +25 -6
  78. package/dist/center-credential.js +25 -5
  79. package/dist/config-catalog.d.ts +26 -7
  80. package/dist/config-catalog.js +15 -12
  81. package/dist/config-invariants.d.ts +2 -1
  82. package/dist/config-invariants.js +4 -4
  83. package/dist/config-types.d.ts +22 -15
  84. package/dist/config.d.ts +51 -2
  85. package/dist/config.js +35 -24
  86. package/dist/deployment-governance.d.ts +7 -28
  87. package/dist/deployment-governance.js +1 -14
  88. package/dist/deployment-shape.d.ts +9 -1
  89. package/dist/deployment-shape.js +2 -1
  90. package/dist/device-protocol.d.ts +5 -4
  91. package/dist/device-protocol.js +1 -1
  92. package/dist/device-ws-hub.d.ts +1 -0
  93. package/dist/device-ws-hub.js +66 -29
  94. package/dist/device-ws-protocol.d.ts +79 -12
  95. package/dist/device-ws-protocol.js +64 -26
  96. package/dist/engine-identity.d.ts +23 -5
  97. package/dist/engine-identity.js +13 -0
  98. package/dist/entry-mode-clamp-notice.d.ts +2 -1
  99. package/dist/execution-env-refusal.d.ts +23 -0
  100. package/dist/execution-env-refusal.js +5 -0
  101. package/dist/execution-lane-caps.d.ts +3 -1
  102. package/dist/field-conflict.d.ts +3 -3
  103. package/dist/file-history-capture.d.ts +11 -4
  104. package/dist/file-history-capture.js +9 -6
  105. package/dist/file-history-disclosure.d.ts +7 -5
  106. package/dist/file-history-disclosure.js +7 -5
  107. package/dist/fleet/drain-entry.d.ts +4 -0
  108. package/dist/fleet/engine-signal.d.ts +14 -1
  109. package/dist/fleet/engine-signal.js +5 -1
  110. package/dist/fleet/fleet-reconciler.d.ts +1 -1
  111. package/dist/fleet/serving-lease.d.ts +18 -3
  112. package/dist/fleet/serving-lease.js +81 -35
  113. package/dist/fleet-client.d.ts +13 -11
  114. package/dist/fleet-client.js +53 -33
  115. package/dist/history-anchor.js +1 -1
  116. package/dist/hitl-delivery.d.ts +1 -3
  117. package/dist/hitl-delivery.js +1 -1
  118. package/dist/hooks/hook-runner.js +2 -2
  119. package/dist/host-lsp-manager.d.ts +2 -2
  120. package/dist/http/active-run-conflict.d.ts +3 -7
  121. package/dist/http/active-run-conflict.js +2 -2
  122. package/dist/http/admission.js +19 -4
  123. package/dist/http/approval-sweeps.js +7 -6
  124. package/dist/http/caller-trust.d.ts +2 -2
  125. package/dist/http/caller-trust.js +3 -3
  126. package/dist/http/checkpoint-ctx.d.ts +20 -63
  127. package/dist/http/checkpoint-ctx.js +2 -24
  128. package/dist/http/claim-heartbeat.d.ts +4 -4
  129. package/dist/http/claim-heartbeat.js +3 -3
  130. package/dist/http/dispatch.d.ts +2 -1
  131. package/dist/http/dispatch.js +36 -29
  132. package/dist/http/durable-run-leg.js +17 -17
  133. package/dist/http/health-self-report.d.ts +9 -1
  134. package/dist/http/health-self-report.js +2 -0
  135. package/dist/http/owner-access.d.ts +264 -20
  136. package/dist/http/owner-access.js +215 -5
  137. package/dist/http/readiness.d.ts +4 -2
  138. package/dist/http/resume-ctx-read.js +38 -1
  139. package/dist/http/resume-legs.d.ts +2 -1
  140. package/dist/http/resume-legs.js +273 -89
  141. package/dist/http/route-ctx.d.ts +41 -19
  142. package/dist/http/route-table.d.ts +1 -1
  143. package/dist/http/routes/a2a-serve.js +15 -14
  144. package/dist/http/routes/admin-memory-optout.d.ts +1 -1
  145. package/dist/http/routes/agents-roster.js +2 -3
  146. package/dist/http/routes/approvals-assistant.d.ts +3 -2
  147. package/dist/http/routes/approvals-assistant.js +12 -12
  148. package/dist/http/routes/background.d.ts +3 -3
  149. package/dist/http/routes/capabilities.js +10 -6
  150. package/dist/http/routes/config-catalog.d.ts +1 -1
  151. package/dist/http/routes/fleet.js +10 -8
  152. package/dist/http/routes/mcp-reconnect.js +2 -2
  153. package/dist/http/routes/memory-origin.d.ts +1 -1
  154. package/dist/http/routes/notify-wake.js +2 -3
  155. package/dist/http/routes/projects.d.ts +4 -2
  156. package/dist/http/routes/projects.js +7 -6
  157. package/dist/http/routes/retention-ops.d.ts +1 -1
  158. package/dist/http/routes/run-permission-mode.d.ts +1 -1
  159. package/dist/http/routes/run-permission-mode.js +2 -2
  160. package/dist/http/routes/runs.d.ts +1 -1
  161. package/dist/http/routes/runs.js +125 -66
  162. package/dist/http/routes/session-memory-sync.js +4 -5
  163. package/dist/http/routes/session-sync.d.ts +4 -3
  164. package/dist/http/routes/session-sync.js +174 -83
  165. package/dist/http/routes/sessions-list.js +13 -7
  166. package/dist/http/routes/sessions.d.ts +1 -1
  167. package/dist/http/routes/sessions.js +26 -48
  168. package/dist/http/routes/tasks.js +38 -23
  169. package/dist/http/routes/trace-usage.js +14 -14
  170. package/dist/http/routes/workflows.d.ts +1 -0
  171. package/dist/http/routes/workflows.js +20 -38
  172. package/dist/http/server.d.ts +28 -30
  173. package/dist/http/server.js +7 -3
  174. package/dist/http/stored-body-replay.d.ts +3 -24
  175. package/dist/http/stored-body-replay.js +2 -12
  176. package/dist/http/submit-ctx.d.ts +1 -2
  177. package/dist/http/submit-ctx.js +8 -6
  178. package/dist/http/submit-replay.d.ts +15 -2
  179. package/dist/http/submit-replay.js +10 -4
  180. package/dist/http/wire-types.d.ts +19 -6
  181. package/dist/identity-source.d.ts +20 -3
  182. package/dist/identity-source.js +14 -0
  183. package/dist/index.d.ts +4 -0
  184. package/dist/lane-home-probe.d.ts +3 -7
  185. package/dist/lane-home-probe.js +0 -1
  186. package/dist/leader/endpoint.js +9 -8
  187. package/dist/leader/leader.d.ts +2 -1
  188. package/dist/leg-facts.d.ts +19 -5
  189. package/dist/leg-facts.js +3 -1
  190. package/dist/mcp-authorization-face.d.ts +18 -14
  191. package/dist/mcp-authorization-face.js +3 -2
  192. package/dist/memory-scope.d.ts +5 -4
  193. package/dist/memory-scope.js +4 -4
  194. package/dist/memory-store-refusal.d.ts +1 -1
  195. package/dist/memory-sync-client.d.ts +30 -2
  196. package/dist/memory-sync-client.js +16 -9
  197. package/dist/observability/corrupt-read-seat.d.ts +1 -1
  198. package/dist/observability/err-text.d.ts +7 -0
  199. package/dist/observability/err-text.js +5 -0
  200. package/dist/observability/fail-open.d.ts +12 -8
  201. package/dist/observability/fail-open.js +12 -8
  202. package/dist/observability/logger.d.ts +7 -0
  203. package/dist/observability/logger.js +3 -1
  204. package/dist/observability/metrics.js +1 -0
  205. package/dist/observability/run-terminal.d.ts +1 -1
  206. package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
  207. package/dist/orchestration/workflow-notify-journal.js +12 -1
  208. package/dist/orchestration/workflow-park-decision.d.ts +70 -18
  209. package/dist/orchestration/workflow-park-decision.js +49 -10
  210. package/dist/orchestration/workflow-park-holder.d.ts +65 -0
  211. package/dist/orchestration/workflow-park-holder.js +98 -0
  212. package/dist/orchestration/workflow-record-fence.d.ts +36 -0
  213. package/dist/orchestration/workflow-record-fence.js +42 -0
  214. package/dist/owner-faces.d.ts +28 -4
  215. package/dist/owner-faces.js +2 -0
  216. package/dist/parked-decide.d.ts +104 -53
  217. package/dist/parked-decide.js +153 -117
  218. package/dist/peer-directory.d.ts +2 -2
  219. package/dist/peer-inbound-face.d.ts +2 -6
  220. package/dist/peer-inbound-face.js +0 -3
  221. package/dist/peer-seat.d.ts +1 -1
  222. package/dist/peer-seat.js +52 -59
  223. package/dist/permission-mode-admission.d.ts +41 -5
  224. package/dist/permission-mode-admission.js +29 -3
  225. package/dist/plugins/adoption-log-sql.d.ts +3 -1
  226. package/dist/plugins/adoption-log-sql.js +7 -1
  227. package/dist/plugins/approval-ask-store-file.d.ts +10 -2
  228. package/dist/plugins/approval-ask-store-file.js +8 -0
  229. package/dist/plugins/approval-ask-store-memory.d.ts +6 -1
  230. package/dist/plugins/approval-ask-store-memory.js +28 -9
  231. package/dist/plugins/approval-ask-store-sql.d.ts +43 -2
  232. package/dist/plugins/approval-ask-store-sql.js +34 -5
  233. package/dist/plugins/approval-exemption-store.js +3 -0
  234. package/dist/plugins/approval-nonce-store.js +2 -0
  235. package/dist/plugins/breaker-state-sql.js +2 -0
  236. package/dist/plugins/caching-session-store.d.ts +9 -15
  237. package/dist/plugins/caching-session-store.js +6 -0
  238. package/dist/plugins/device-store-sql.js +6 -0
  239. package/dist/plugins/error-origin.d.ts +18 -0
  240. package/dist/plugins/error-origin.js +10 -0
  241. package/dist/plugins/exec-path-law.d.ts +34 -0
  242. package/dist/plugins/exec-path-law.js +13 -0
  243. package/dist/plugins/execution-placement-sql.js +6 -6
  244. package/dist/plugins/file-run-store.js +1 -1
  245. package/dist/plugins/image-bake-store-sql.js +6 -0
  246. package/dist/plugins/image-index-sql.js +4 -0
  247. package/dist/plugins/landed-attendants.d.ts +212 -0
  248. package/dist/plugins/landed-attendants.js +161 -0
  249. package/dist/plugins/leader-run-store-sql.js +4 -0
  250. package/dist/plugins/local-checkpoint-store.d.ts +4 -1
  251. package/dist/plugins/local-checkpoint-store.js +3 -0
  252. package/dist/plugins/local-session-live-reference.d.ts +40 -0
  253. package/dist/plugins/local-session-live-reference.js +39 -0
  254. package/dist/plugins/local-session-store.d.ts +71 -33
  255. package/dist/plugins/local-session-store.js +129 -27
  256. package/dist/plugins/memory-engine-pg.js +4 -0
  257. package/dist/plugins/memory-engine-sql-apply.js +5 -2
  258. package/dist/plugins/memory-engine-tidb.js +4 -0
  259. package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
  260. package/dist/plugins/memory-run-store.js +1 -1
  261. package/dist/plugins/memory-sync-store-pg.js +5 -0
  262. package/dist/plugins/memory-sync-store-tidb.js +5 -0
  263. package/dist/plugins/one-time-migrations.d.ts +80 -61
  264. package/dist/plugins/one-time-migrations.js +241 -104
  265. package/dist/plugins/org-delivery-quota-store.js +4 -1
  266. package/dist/plugins/outcome-ledger-sql.js +2 -0
  267. package/dist/plugins/permission-rule-store-sql.js +11 -4
  268. package/dist/plugins/pg-cost-quota.js +4 -0
  269. package/dist/plugins/pg-pool.js +28 -1
  270. package/dist/plugins/pg-rate-limiter.js +2 -0
  271. package/dist/plugins/posix-shell-fs.d.ts +6 -1
  272. package/dist/plugins/posix-shell-fs.js +8 -3
  273. package/dist/plugins/remote-env-adb.d.ts +19 -15
  274. package/dist/plugins/remote-env-adb.js +44 -17
  275. package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
  276. package/dist/plugins/remote-env-connect-seat.js +72 -0
  277. package/dist/plugins/remote-env-device.d.ts +22 -5
  278. package/dist/plugins/remote-env-device.js +114 -14
  279. package/dist/plugins/remote-env-e2b.d.ts +18 -7
  280. package/dist/plugins/remote-env-e2b.js +53 -40
  281. package/dist/plugins/remote-env-file-error.js +6 -2
  282. package/dist/plugins/remote-env-host.d.ts +18 -1
  283. package/dist/plugins/remote-env-host.js +48 -47
  284. package/dist/plugins/remote-env-k8s.d.ts +41 -39
  285. package/dist/plugins/remote-env-k8s.js +56 -32
  286. package/dist/plugins/remote-env-local-docker.d.ts +13 -8
  287. package/dist/plugins/remote-env-local-docker.js +37 -43
  288. package/dist/plugins/remote-env-ssh.d.ts +18 -12
  289. package/dist/plugins/remote-env-ssh.js +64 -62
  290. package/dist/plugins/remote-shell.d.ts +101 -2
  291. package/dist/plugins/remote-shell.js +221 -3
  292. package/dist/plugins/replica-registration.d.ts +35 -0
  293. package/dist/plugins/replica-registration.js +48 -0
  294. package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
  295. package/dist/plugins/resume-anchor-store-sql.js +12 -5
  296. package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
  297. package/dist/plugins/retention-lane-store-sql.js +4 -0
  298. package/dist/plugins/retention-sql.d.ts +20 -2
  299. package/dist/plugins/retention-sql.js +11 -0
  300. package/dist/plugins/run-store-sql.d.ts +22 -3
  301. package/dist/plugins/run-store-sql.js +33 -9
  302. package/dist/plugins/scenario-prefix-switch-m42.d.ts +6 -12
  303. package/dist/plugins/scenario-prefix-switch-m42.js +7 -5
  304. package/dist/plugins/schema-consistency.d.ts +9 -5
  305. package/dist/plugins/schema-consistency.js +48 -18
  306. package/dist/plugins/schema-drift-sentence.js +1 -1
  307. package/dist/plugins/send-file-ledger.js +3 -0
  308. package/dist/plugins/serving-requirement.d.ts +68 -0
  309. package/dist/plugins/serving-requirement.js +60 -0
  310. package/dist/plugins/session-birth.d.ts +6 -2
  311. package/dist/plugins/session-capture-record-store-sql.js +2 -0
  312. package/dist/plugins/session-ext-table.d.ts +14 -1
  313. package/dist/plugins/session-ext-table.js +5 -1
  314. package/dist/plugins/session-row-sql.d.ts +49 -2
  315. package/dist/plugins/session-row-sql.js +56 -13
  316. package/dist/plugins/session-store-sql.d.ts +34 -18
  317. package/dist/plugins/session-store-sql.js +98 -17
  318. package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
  319. package/dist/plugins/shared-memory-store-sql.js +6 -2
  320. package/dist/plugins/sql-driver.d.ts +2 -1
  321. package/dist/plugins/sql-driver.js +18 -3
  322. package/dist/plugins/sql-errors.d.ts +11 -6
  323. package/dist/plugins/sql-errors.js +5 -6
  324. package/dist/plugins/stop-then-start-sentence.d.ts +48 -3
  325. package/dist/plugins/stop-then-start-sentence.js +48 -0
  326. package/dist/plugins/stop-then-start.d.ts +109 -0
  327. package/dist/plugins/stop-then-start.js +104 -0
  328. package/dist/plugins/store-backend.d.ts +40 -13
  329. package/dist/plugins/store-backend.js +169 -27
  330. package/dist/plugins/store-boundary.d.ts +57 -0
  331. package/dist/plugins/store-boundary.js +139 -0
  332. package/dist/plugins/store-contracts.d.ts +29 -2
  333. package/dist/plugins/store-contracts.js +3 -0
  334. package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
  335. package/dist/plugins/store-fault-sentence-m53.js +25 -0
  336. package/dist/plugins/store-fault.d.ts +26 -7
  337. package/dist/plugins/store-fault.js +18 -2
  338. package/dist/plugins/task-attachment-store.js +9 -0
  339. package/dist/plugins/task-list-store-sql.d.ts +2 -2
  340. package/dist/plugins/task-list-store-sql.js +10 -8
  341. package/dist/plugins/tidb-cost-quota.js +4 -0
  342. package/dist/plugins/tidb-pool.js +6 -1
  343. package/dist/plugins/tidb-rate-limiter.js +4 -0
  344. package/dist/plugins/user-input-ledger-sql.js +4 -0
  345. package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
  346. package/dist/plugins/workflow-run-store-sql.js +64 -4
  347. package/dist/plugins/workspace-fill.d.ts +4 -7
  348. package/dist/plugins/workspace-fill.js +2 -1
  349. package/dist/plugins/write-behind-counter.js +5 -0
  350. package/dist/process-instance.d.ts +3 -0
  351. package/dist/process-instance.js +7 -0
  352. package/dist/project-context.d.ts +64 -0
  353. package/dist/project-context.js +66 -0
  354. package/dist/project-registry.d.ts +46 -0
  355. package/dist/project-registry.js +44 -0
  356. package/dist/question.d.ts +9 -21
  357. package/dist/question.js +28 -19
  358. package/dist/request-key-closure.js +1 -1
  359. package/dist/request-value-closure.d.ts +4 -0
  360. package/dist/request-value-closure.js +10 -0
  361. package/dist/run-acceptance.d.ts +3 -2
  362. package/dist/run-acceptance.js +4 -6
  363. package/dist/run-cancel-card.d.ts +1 -1
  364. package/dist/run-cancel-card.js +2 -1
  365. package/dist/run-local.js +1 -0
  366. package/dist/runs.d.ts +37 -8
  367. package/dist/runs.js +53 -12
  368. package/dist/runtime-governance.d.ts +5 -4
  369. package/dist/security.d.ts +31 -33
  370. package/dist/security.js +41 -7
  371. package/dist/server-secret-env.d.ts +12 -10
  372. package/dist/server-secret-env.js +24 -15
  373. package/dist/session-agent.d.ts +1 -10
  374. package/dist/session-agent.js +0 -6
  375. package/dist/session-bindings.d.ts +82 -0
  376. package/dist/session-bindings.js +18 -0
  377. package/dist/session-children-retire.d.ts +2 -2
  378. package/dist/session-children-retire.js +2 -6
  379. package/dist/session-deletion.d.ts +16 -1
  380. package/dist/session-error-wire.d.ts +3 -3
  381. package/dist/session-error-wire.js +3 -3
  382. package/dist/session-incarnation.d.ts +28 -4
  383. package/dist/session-incarnation.js +14 -2
  384. package/dist/session-kind.d.ts +57 -0
  385. package/dist/session-kind.js +22 -0
  386. package/dist/session-notify-door.d.ts +4 -4
  387. package/dist/session-notify-door.js +5 -6
  388. package/dist/session-row.d.ts +21 -1
  389. package/dist/session-row.js +7 -1
  390. package/dist/session-rules-seat.d.ts +4 -3
  391. package/dist/session-rules-seat.js +3 -11
  392. package/dist/session-sync-kernel.d.ts +24 -14
  393. package/dist/session-sync-kernel.js +3 -6
  394. package/dist/session-sync.d.ts +4 -98
  395. package/dist/session-sync.js +4 -74
  396. package/dist/session-titler.d.ts +10 -3
  397. package/dist/session-titler.js +19 -6
  398. package/dist/ssh-host-key.d.ts +5 -0
  399. package/dist/ssh-host-key.js +3 -0
  400. package/dist/stores-sql/checkpoint-store-sql.d.ts +21 -2
  401. package/dist/stores-sql/checkpoint-store-sql.js +106 -18
  402. package/dist/stores-sql/file-history-store-sql.d.ts +52 -2
  403. package/dist/stores-sql/file-history-store-sql.js +108 -70
  404. package/dist/stores-sql/pg-session-storage.d.ts +34 -7
  405. package/dist/stores-sql/pg-session-storage.js +37 -13
  406. package/dist/stores-sql/retention-store-sql.d.ts +2 -10
  407. package/dist/stores-sql/retention-store-sql.js +2 -10
  408. package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
  409. package/dist/stores-sql/session-policy-store-sql.js +61 -44
  410. package/dist/stores-sql/session-write-hooks.d.ts +11 -0
  411. package/dist/stores-sql/tidb-session-store.d.ts +58 -7
  412. package/dist/stores-sql/tidb-session-store.js +37 -13
  413. package/dist/submission-exit.d.ts +3 -2
  414. package/dist/submission-exit.js +9 -1
  415. package/dist/task-cwd.d.ts +6 -5
  416. package/dist/task-settings.d.ts +19 -5
  417. package/dist/task-settings.js +13 -7
  418. package/dist/terminal.d.ts +33 -2
  419. package/dist/terminal.js +139 -9
  420. package/dist/tool-approval.d.ts +147 -12
  421. package/dist/tool-approval.js +206 -109
  422. package/dist/trace/engine-notice-wire.d.ts +14 -0
  423. package/dist/trace/engine-notice-wire.js +18 -1
  424. package/dist/trace/project.d.ts +4 -3
  425. package/dist/trace/project.js +3 -2
  426. package/dist/trace/projection-table.d.ts +33 -2
  427. package/dist/trace/self-minted-wire.d.ts +422 -26
  428. package/dist/trace/self-minted-wire.js +149 -23
  429. package/dist/trace/tool-card.d.ts +3 -0
  430. package/dist/trace/tool-card.js +24 -0
  431. package/dist/trace/tool-output-media.d.ts +2 -1
  432. package/dist/unattended-permission-mode.d.ts +1 -1
  433. package/dist/web-admin-client/apply-effective.d.ts +1 -1
  434. package/dist/web-admin-client/effective-keys.d.ts +1 -1
  435. package/dist/web-admin-client/skills-mcp.d.ts +1 -1
  436. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +120 -41
  437. package/package.json +3 -3
  438. package/wire-changes/server@7.150.0.json +335 -0
  439. package/wire-changes/server@7.151.0.json +762 -0
  440. package/dist/http/session-inherit-env.d.ts +0 -36
  441. package/dist/http/session-inherit-env.js +0 -6
@@ -4,6 +4,7 @@ import { sendUnauthorized } from "../principal-gate.js";
4
4
  import { routeListFilter } from "../owner-access.js";
5
5
  import { assertNever } from "../route-ctx.js";
6
6
  import * as facts from "../../capability-facts.js";
7
+ import { projectVisibleTo, visibleProjectOf } from "../../project-registry.js";
7
8
  import { projectByTable } from "../../trace/projection-table.js";
8
9
  export const PROJECT_NOT_FOUND_MESSAGE = "no such project";
9
10
  export const PROJECT_ROW_DISPOSITIONS = {
@@ -19,6 +20,7 @@ export const PROJECT_ROW_DISPOSITIONS = {
19
20
  registeredBy: "forward",
20
21
  registeredAt: "forward",
21
22
  archivedAt: "forward",
23
+ contentAttestedAt: "forward",
22
24
  };
23
25
  export function projectRowOf(id, registration) {
24
26
  return projectByTable("project", PROJECT_ROW_DISPOSITIONS, registration, { id });
@@ -37,8 +39,8 @@ function readArchivedQuery(raw) {
37
39
  export async function handleProjects(req, res, match, ctx) {
38
40
  const { deps } = ctx;
39
41
  const { safeDecode } = ctx.helpers;
40
- const { fleetWide, gateOwner } = routeListFilter(req, deps, match.decl.id);
41
- if (!fleetWide && gateOwner === null) {
42
+ const viewer = routeListFilter(req, deps, match.decl.id);
43
+ if (!viewer.fleetWide && viewer.gateOwner === null) {
42
44
  sendUnauthorized(res, "identity");
43
45
  return;
44
46
  }
@@ -47,7 +49,6 @@ export async function handleProjects(req, res, match, ctx) {
47
49
  sendError(res, 501, "capability.unavailable", "the project registry is not available on this deployment: projects are published only by the configuration center, and no center configuration is applied here");
48
50
  return;
49
51
  }
50
- const visible = (registration) => fleetWide || registration.registeredBy === gateOwner;
51
52
  switch (match.decl.id) {
52
53
  case "projects-list": {
53
54
  const archived = readArchivedQuery(new URLSearchParams(match.search).get("archived"));
@@ -56,7 +57,7 @@ export async function handleProjects(req, res, match, ctx) {
56
57
  return;
57
58
  }
58
59
  const projects = Object.entries(registry.registry)
59
- .filter(([, registration]) => visible(registration) && (registration.archivedAt !== undefined) === archived)
60
+ .filter(([, registration]) => projectVisibleTo(viewer, registration) && (registration.archivedAt !== undefined) === archived)
60
61
  .map(([id, registration]) => projectRowOf(id, registration));
61
62
  sendJson(res, 200, { projects });
62
63
  return;
@@ -68,8 +69,8 @@ export async function handleProjects(req, res, match, ctx) {
68
69
  return;
69
70
  }
70
71
  const id = raw.toLowerCase();
71
- const registration = Object.hasOwn(registry.registry, id) ? registry.registry[id] : undefined;
72
- if (registration === undefined || !visible(registration)) {
72
+ const registration = visibleProjectOf(registry.registry, id, viewer);
73
+ if (registration === undefined) {
73
74
  sendError(res, 404, "not_found.project", PROJECT_NOT_FOUND_MESSAGE);
74
75
  return;
75
76
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * [ref] 车2 —— **托管留存的 operator 治理面**(设计稿 `docs/DESIGN-270-retention-lane.md` §5/§6)。
2
+ * [ref] 车2 —— **托管留存的 operator 治理面**(设计稿 `docs/[ref]-retention-lane.md` §5/§6)。
3
3
  *
4
4
  * · `PUT /v1/ops/retention/holds/:domain` —— 放置 legal hold;
5
5
  * · `DELETE /v1/ops/retention/holds/:domain` —— 解除;
@@ -43,7 +43,7 @@ export type PermissionModePersistMiss = (typeof PERMISSION_MODE_PERSIST_MISSES)[
43
43
  * · run 行仍在本副本(`runProvenElsewhere` 的反面 —— 别的副本续跑了它,续跑的 CAS 赢点把行上的副本改成它自己);
44
44
  * · 本副本这条 run 此刻登记的活流仍是接下切档的那一只(本副本上续跑的新腿登记的是另一只流对象;腿收场时按对象身份摘掉自己的)。
45
45
  */
46
- export declare function switchLegHolds<S extends object>(fenced: FencedRun, thisInstanceId: string | undefined, liveNow: S | undefined, switched: S): boolean;
46
+ export declare function switchLegHolds<S extends object>(fenced: Pick<FencedRun, "instanceId">, thisInstanceId: string | undefined, liveNow: S | undefined, switched: S): boolean;
47
47
  /** 本判官改了词时回执旁的那一格(`admission`)。 */
48
48
  interface PermissionModeAdmissionNote {
49
49
  readonly requested: PermissionMode;
@@ -7,7 +7,7 @@ import * as facts from "../../capability-facts.js";
7
7
  import { PERMISSION_MODE_WORDS, coercePermissionModeStrict, parseTaskSettings } from "../../task-settings.js";
8
8
  import { admitPermissionModeWord } from "../../permission-mode-admission.js";
9
9
  import { readResumeCtx, resumeCtxCorruptAnswer, resumeCtxUnreadableAnswer, resumeCtxUnsealableAnswer } from "../resume-ctx-read.js";
10
- import { sealCheckpointCtx, withPermissionModeRewritten } from "../checkpoint-ctx.js";
10
+ import { sealCheckpointCtx } from "../checkpoint-ctx.js";
11
11
  import { serviceVersion } from "../../service-version.js";
12
12
  import { recordFailOpen } from "../../observability/fail-open.js";
13
13
  export const PERMISSION_MODE_PERSIST_MISSES = ["claim_released", "context_absent", "store_failed"];
@@ -114,7 +114,7 @@ export async function handlePermissionMode(req, res, match, ctx) {
114
114
  }
115
115
  let persistMiss;
116
116
  try {
117
- const next = sealCheckpointCtx({ ...withPermissionModeRewritten(stored, { ...stored.body, permissionMode: admitted }), writerVersion: serviceVersion() }, deps.checkpointCtxSealing, sessionId);
117
+ const next = sealCheckpointCtx({ ...stored, body: { ...stored.body, permissionMode: admitted }, writerVersion: serviceVersion() }, deps.checkpointCtxSealing, sessionId);
118
118
  const rewrite = await checkpointStore.rewriteCtxWhileClaimed(sessionId, next, { fence: runStore, taskId, legHolds: (fenced) => switchLegHolds(fenced, deps.instanceId, ctx.registry.steerableRuns.get(taskId), live) });
119
119
  persistMiss = rewrite === "written" ? undefined : rewrite;
120
120
  }
@@ -13,7 +13,7 @@ export declare function handleRuns(req: IncomingMessage, res: ServerResponse, ma
13
13
  /** 同上纪律(子代理 / 任务句柄 / HITL 应答段)。 */
14
14
  export declare function handleRunVerbs(req: IncomingMessage, res: ServerResponse, match: RouteMatch<RunVerbsRouteId>, ctx: RouteCtx): Promise<void>;
15
15
  /**
16
- * DESIGN-269 车2 件2 —— `POST /v1/runs` 的**建行 + 驱动**段,从路由体里原样搬出来的具名腿。
16
+ * [ref] 车2 件2 —— `POST /v1/runs` 的**建行 + 驱动**段,从路由体里原样搬出来的具名腿。
17
17
  *
18
18
  * 🔴 为什么提取:A2A 的 `message/send`(routes/a2a-serve.ts)必须走**同一条**提交链 —— 第二条提交
19
19
  * 路径就是第二个写者,而这条链上挂着 durable taskId 幂等重放、lease/治理窗 pre-admission、
@@ -16,8 +16,8 @@ import { idemCallerOf, idemKeyOf, inflightKeyOf, submissionIdemOf } from "../ide
16
16
  import { streamSseLog } from "../sse-log.js";
17
17
  import { bindSseLifecycle } from "../sse-lifecycle.js";
18
18
  import { buildApprovalPreamble, buildApprovalPreambleSseFrames, readClosedWordSeat, storedCardDemandsAPerson } from "../../approval-card.js";
19
- import { heldAskOf, liveHostSource, readDecider, retiredDecisionKeyFacts, DECIDED_BY_NOT_IN_PROOF, POLICY_CANNOT_ALLOW_PERSON_ASK } from "../../host-decision.js";
20
- import { ASK_DECISION_CONSUMER_ABSENT, approvalPreambleReplays, outcomeOfDecidedRow, parkSessionOf, presentedApprovalFrameFamily, resolveStreamApprovalGate } from "../../tool-approval.js";
19
+ import { heldAskOf, readDecider, retiredDecisionKeyFacts, DECIDED_BY_NOT_IN_PROOF, POLICY_CANNOT_ALLOW_PERSON_ASK } from "../../host-decision.js";
20
+ import { ASK_DECISION_CONSUMER_ABSENT, approvalPreambleReplays, decidedRowFacts, outcomeOfDecidedRow, parkSessionOf, presentedApprovalFrameFamily, resolveStreamApprovalGate } from "../../tool-approval.js";
21
21
  import { MAX_DECISION_NOTE_CHARS, noteLandedOnRow, noteRecordedReceipt } from "../../approval-ask-machine.js";
22
22
  import { askRowEndingCause } from "../../approval-deny-reasons.js";
23
23
  import { normalizeRunEventType, screenedStoredEventData } from "../../trace/project.js";
@@ -30,16 +30,16 @@ import { ActorAssertionWire } from "@sema-agent/settings-schema";
30
30
  import * as facts from "../../capability-facts.js";
31
31
  import { assertNever } from "../route-ctx.js";
32
32
  import { readRunFace } from "../run-read-face.js";
33
- import { replayOfExistingRun } from "../submit-replay.js";
33
+ import { replayOfExistingRun, replayOfKey } from "../submit-replay.js";
34
34
  import { mintAndDriveDurableRun } from "../durable-run-leg.js";
35
35
  import { SUBMISSION_CLAIM_FACE } from "../execution-context.js";
36
- import { admitRunById, admitRunRow, enter, runRowAt } from "../owner-access.js";
36
+ import { admitRunById, admitRunByIdem, enter, readVisibleRun, sessionFactsReadOf } from "../owner-access.js";
37
37
  import { keyAdmission, ownerCellOf, recoveredSubject } from "../../owner-faces.js";
38
+ import { engineScopeOfOwner } from "../../engine-identity.js";
38
39
  import { personOf } from "../../owner-brands.js";
39
40
  import { withSubject } from "../../observability/principal-context.js";
40
41
  import { readResumeCtx, resumeCtxUnreadableAnswer } from "../resume-ctx-read.js";
41
42
  import { storedBodyReplayAnswer, storedBodyReplayLogFields } from "../checkpoint-ctx.js";
42
- import { headReadOf } from "../../session-incarnation.js";
43
43
  import { serviceVersion } from "../../service-version.js";
44
44
  import { storedBodyReplayRefusal } from "../stored-body-replay.js";
45
45
  import { haltBodyIssue, steerBodyKeyIssue } from "../../request-key-closure.js";
@@ -50,6 +50,11 @@ const STEER_PRIORITY_CHOICES = STEER_PRIORITY_WORDS.length <= 2 ? STEER_PRIORITY
50
50
  const ASK_PARKING_RETRY_AFTER_SEC = 2;
51
51
  const ASK_ACTOR_LABEL_MAX = 256;
52
52
  const AskDecisionActorSchema = ActorAssertionWire.strip();
53
+ function mirrorRetryAfter(res, body) {
54
+ const retryAfterSec = body !== null && typeof body === "object" ? body.retryAfterSec : undefined;
55
+ if (typeof retryAfterSec === "number" && Number.isFinite(retryAfterSec) && retryAfterSec >= 0)
56
+ res.setHeader("retry-after", String(Math.ceil(retryAfterSec)));
57
+ }
53
58
  const AskDecisionBodySchema = z
54
59
  .object({
55
60
  decision: z.enum(["approve", "deny"]),
@@ -106,7 +111,7 @@ function sendHandleMiss(res, run, thisInstanceId) {
106
111
  }
107
112
  return false;
108
113
  }
109
- async function streamRunEvents(req, res, deps, runStore, taskId) {
114
+ async function streamRunEvents(req, res, deps, runStore, entry, taskId) {
110
115
  await streamSseLog(req, res, {
111
116
  preamble: async (signal) => {
112
117
  const gate = resolveStreamApprovalGate({
@@ -135,10 +140,7 @@ async function streamRunEvents(req, res, deps, runStore, taskId) {
135
140
  return buildApprovalPreambleSseFrames(frames);
136
141
  },
137
142
  onPreambleFailure: (reason, err) => deps.logger?.warn?.("approval_preamble_failed", { taskId, reason, face: "run.events", error: err instanceof Error ? err.message : String(err ?? "") }),
138
- statusOf: async (id) => {
139
- const run = await runStore.getRun(id);
140
- return run ? runRowAt("run-events", runStore, run) : undefined;
141
- },
143
+ statusOf: async (id) => (await readVisibleRun(entry, runStore, id))?.row,
142
144
  getEvents: (id, after) => runStore.getEvents(id, after),
143
145
  formatEvent: (ev) => {
144
146
  const type = normalizeRunEventType(ev.type);
@@ -208,9 +210,9 @@ export async function handleRuns(req, res, match, ctx) {
208
210
  return;
209
211
  }
210
212
  const inflight = idemCache.peek(inflightKeyOf(idem, "durable", clientTaskId));
211
- const keyedRow = inflight ? undefined : await runStore.getRunByIdem(idem.key);
212
- if (inflight || keyedRow) {
213
- const resp = inflight ? await inflight : await replayOfExistingRun(keyedRow, { subject: submitter, idem, ...(clientTaskId !== undefined ? { clientTaskId } : {}) }, "durable", deps, runStore);
213
+ const replayed = inflight ? undefined : await replayOfKey({ idemKey: idem.key }, { subject: submitter, idem, ...(clientTaskId !== undefined ? { clientTaskId } : {}) }, "durable", deps, runStore);
214
+ const resp = inflight ? await inflight : replayed;
215
+ if (resp !== undefined) {
214
216
  sendJson(res, resp.status, resp.body);
215
217
  return;
216
218
  }
@@ -246,26 +248,23 @@ export async function handleRuns(req, res, match, ctx) {
246
248
  const entry = enter(req, res, deps, match.decl.id);
247
249
  if (entry === undefined)
248
250
  return;
249
- let run;
250
- let pathId;
251
+ let admitted;
251
252
  if (match.decl.id === "runs-by-idem") {
252
253
  const rawKey = new URLSearchParams(match.search).get("idempotencyKey");
253
254
  if (!rawKey) {
254
255
  sendError(res, 400, "request.query_invalid", "idempotencyKey is required: pass the raw Idempotency-Key the submission was sent with");
255
256
  return;
256
257
  }
257
- run = await runStore.getRunByIdem(idemKeyOf(rawKey, idemCallerOf(req, ctx), "run"));
258
+ admitted = await admitRunByIdem(entry, res, runStore, idemKeyOf(rawKey, idemCallerOf(req, ctx), "run"));
258
259
  }
259
260
  else {
260
- pathId = match.params.taskId;
261
- run = await runStore.getRun(pathId);
261
+ admitted = await admitRunById(entry, res, runStore, match.params.taskId);
262
262
  }
263
- const admitted = await admitRunRow(entry, res, runStore, run, pathId);
264
263
  if (admitted === undefined)
265
264
  return;
266
265
  const taskId = admitted.row.taskId;
267
266
  if (match.decl.id === "run-events") {
268
- await streamRunEvents(req, res, deps, runStore, taskId);
267
+ await streamRunEvents(req, res, deps, runStore, entry, taskId);
269
268
  }
270
269
  else {
271
270
  sendJson(res, 200, await readRunFace(deps, runStore, admitted.row));
@@ -296,7 +295,7 @@ export async function handleRuns(req, res, match, ctx) {
296
295
  if (token) {
297
296
  const won = (await expireCardUnderStoredScope(cs, token)) === CARD_EXPIRE_OUTCOME.expired;
298
297
  if (!won) {
299
- const now = await rs.getRun(taskId);
298
+ const now = (await readVisibleRun(entry, rs, taskId))?.row;
300
299
  const st = now?.status;
301
300
  if (st !== undefined && (isParkedRunStatus(st) || st === "running")) {
302
301
  sendError(res, 409, "conflict.approval_settled", "pending approval was settled concurrently (decided or expired) — re-check the run and retry cancel if it is still active", { taskId, status: st });
@@ -310,7 +309,7 @@ export async function handleRuns(req, res, match, ctx) {
310
309
  else {
311
310
  const claimed = await rs.markResuming(taskId, deps.instanceId ?? "default");
312
311
  if (!claimed) {
313
- const now = await rs.getRun(taskId);
312
+ const now = (await readVisibleRun(entry, rs, taskId))?.row;
314
313
  const st = now?.status;
315
314
  if (st !== undefined && (st === "running" || isParkedRunStatus(st))) {
316
315
  sendError(res, 409, "conflict.approval_settled", "pending approval was settled concurrently (decided or expired) — re-check the run and retry cancel if it is still active", { taskId, status: st });
@@ -350,7 +349,7 @@ export async function handleRuns(req, res, match, ctx) {
350
349
  sendError(res, 500, "internal.cancel_not_terminalized", `cancel progressed (${note}) but could not terminalize the run row (retried) — retry cancel; a stuck row is reaped after the stale window (${e instanceof Error ? e.message : String(e)})`, { taskId });
351
350
  return;
352
351
  }
353
- const finalRow = await rs.getRun(taskId).catch(() => undefined);
352
+ const finalRow = (await readVisibleRun(entry, rs, taskId).catch(() => undefined))?.row;
354
353
  if (finalRow && finalRow.errorCode !== "cancelled" && isTerminalRunStatus(finalRow.status)) {
355
354
  sendJson(res, 202, { taskId, status: finalRow.status, errorCode: finalRow.errorCode ?? null, cancelRequested: finalRow.cancelRequested, note: `session unlocked; the run was terminalized concurrently (${finalRow.errorCode ?? finalRow.status}) before this cancel's write — reporting the actual ledger state` });
356
355
  return;
@@ -361,7 +360,7 @@ export async function handleRuns(req, res, match, ctx) {
361
360
  let flagged = await runStore.requestCancel(taskId, run.owner);
362
361
  const CANCEL_RECLASSIFY_ATTEMPTS = 3;
363
362
  for (let attempt = 0; !flagged; attempt++) {
364
- const now = await runStore.getRun(taskId);
363
+ const now = (await readVisibleRun(entry, runStore, taskId))?.row;
365
364
  if (now !== undefined && isParkedRunStatus(now.status)) {
366
365
  await cancelSuspended(now.result);
367
366
  return;
@@ -505,7 +504,7 @@ export async function handleRuns(req, res, match, ctx) {
505
504
  }
506
505
  if (code !== "steering.not_running")
507
506
  throw e;
508
- const freshBeforePark = await runStore.getRun(taskId).catch(() => undefined);
507
+ const freshBeforePark = (await readVisibleRun(entry, runStore, taskId).catch(() => undefined))?.row;
509
508
  const raced = await tryPark();
510
509
  if (raced === "parked") {
511
510
  sendParked(freshBeforePark?.status ?? run.status);
@@ -554,8 +553,8 @@ export async function handleRuns(req, res, match, ctx) {
554
553
  }
555
554
  return;
556
555
  }
557
- const sessionHeadOf = headReadOf(deps.sessionStorage);
558
- if (deps.checkpointStore && sessionHeadOf) {
556
+ const sessionFactsOf = sessionFactsReadOf(deps.sessionStorage);
557
+ if (deps.checkpointStore && sessionFactsOf) {
559
558
  const activeTaskId = await runStore.getActiveTaskId?.(run.sessionId).catch(() => undefined);
560
559
  if (activeTaskId !== undefined && activeTaskId !== null && activeTaskId !== taskId) {
561
560
  sendNotRunning(`run is ${run.status} and its session has an ACTIVE run (${activeTaskId}) — steer that run instead`);
@@ -605,7 +604,7 @@ export async function handleRuns(req, res, match, ctx) {
605
604
  mintResult.duplicateKey = true;
606
605
  return;
607
606
  }
608
- const leafId = await sessionHeadOf(run.sessionId).then((h) => h?.leafId).catch(() => undefined);
607
+ const leafId = await sessionFactsOf(run.sessionId).then((h) => h?.leafId).catch(() => undefined);
609
608
  if (leafId === undefined || leafId === null)
610
609
  return;
611
610
  const resumeRead = await readResumeCtx(cs.getCtx(run.sessionId), { sessionId: run.sessionId, opener: deps.checkpointCtxSealing });
@@ -779,7 +778,7 @@ export async function handleRuns(req, res, match, ctx) {
779
778
  catch (e) {
780
779
  if (e.code !== "steering.not_running")
781
780
  throw e;
782
- const freshRun = await runStore.getRun(taskId).catch(() => undefined);
781
+ const freshRun = (await readVisibleRun(entry, runStore, taskId).catch(() => undefined))?.row;
783
782
  sendNoLiveTurn(freshRun?.status ?? run.status, true);
784
783
  return;
785
784
  }
@@ -892,7 +891,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
892
891
  if (!gated)
893
892
  return;
894
893
  const { run } = gated;
895
- const out = await subagentTaskOutput(target, { owner: runId, scope: run.owner ?? "default", ...(run.sessionId ? { sessionId: run.sessionId } : {}) });
894
+ const out = await subagentTaskOutput(target, { owner: runId, scope: engineScopeOfOwner(run.owner), ...(run.sessionId ? { sessionId: run.sessionId } : {}) });
896
895
  const details = out.details;
897
896
  if (details?.error === "not_found" || details?.type !== "background_agent") {
898
897
  if (!sendHandleMiss(res, run, deps.instanceId))
@@ -921,7 +920,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
921
920
  return;
922
921
  const { run } = gatedTail;
923
922
  const it = defaultSubagentTailBus.subscribe(target);
924
- const probe = await subagentTaskOutput(target, { owner: runId, scope: run.owner ?? "default", ...(run.sessionId ? { sessionId: run.sessionId } : {}) });
923
+ const probe = await subagentTaskOutput(target, { owner: runId, scope: engineScopeOfOwner(run.owner), ...(run.sessionId ? { sessionId: run.sessionId } : {}) });
925
924
  const probeDetails = probe.details;
926
925
  if (probeDetails?.error === "not_found" || probeDetails?.type !== "background_agent") {
927
926
  void it.return?.();
@@ -989,7 +988,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
989
988
  return;
990
989
  const { run } = gatedB;
991
990
  const q = new URLSearchParams(match.search);
992
- const access = { owner: runId, scope: run.owner ?? "default", ...(run.sessionId ? { sessionId: run.sessionId } : {}) };
991
+ const access = { owner: runId, scope: engineScopeOfOwner(run.owner), ...(run.sessionId ? { sessionId: run.sessionId } : {}) };
993
992
  if (q.get("filter") !== null) {
994
993
  sendError(res, 400, "request.param_unsupported", "filter is not accepted on the wire — fetch the output and filter client-side (note: the wire serves the clipped projection)");
995
994
  return;
@@ -1196,10 +1195,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1196
1195
  }
1197
1196
  const body = await readJson(req);
1198
1197
  const { status, body: respBody } = await approvalFact.coordinator.respond(id, principal, body, req, { readRootGrantAccepted: facts.readRootGrant(deps).available });
1199
- const retryAfterSec = respBody.retryAfterSec;
1200
- if (typeof retryAfterSec === "number" && Number.isFinite(retryAfterSec) && retryAfterSec >= 0) {
1201
- res.setHeader("retry-after", String(Math.ceil(retryAfterSec)));
1202
- }
1198
+ mirrorRetryAfter(res, respBody);
1203
1199
  sendJson(res, status, respBody);
1204
1200
  return;
1205
1201
  }
@@ -1212,6 +1208,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1212
1208
  return;
1213
1209
  }
1214
1210
  const askStore = streamFact.askStore;
1211
+ const coordinator = streamFact.coordinator;
1215
1212
  const principal = gatedSubject(req, deps.config);
1216
1213
  if (deps.config.requirePrincipal && principal === undefined) {
1217
1214
  sendPrincipalRefusal(res, req, deps.config);
@@ -1254,7 +1251,8 @@ export async function handleRunVerbs(req, res, match, ctx) {
1254
1251
  askNotFound();
1255
1252
  return;
1256
1253
  }
1257
- const askAdmission = keyAdmission("ask.decide", { subject: principal, operator: explicitOperatorOk(principal === undefined ? undefined : personOf(principal), deps.config) }, ownerCellOf(row0.owner));
1254
+ const callerIsOperator = explicitOperatorOk(principal === undefined ? undefined : personOf(principal), deps.config);
1255
+ const askAdmission = keyAdmission("ask.decide", { subject: principal, operator: callerIsOperator }, ownerCellOf(row0.owner));
1258
1256
  if (askAdmission === undefined) {
1259
1257
  askNotFound();
1260
1258
  return;
@@ -1266,7 +1264,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1266
1264
  via: askAdmission === "row" ? "owner" : "operator",
1267
1265
  };
1268
1266
  const decidedRowIsAuthoritative = (row) => {
1269
- if (row.state !== "DECIDED" || row.decision !== "approve" && row.decision !== "deny" || row.provisional || row.decidedAtMs === null) {
1267
+ if (decidedRowFacts(row) === undefined) {
1270
1268
  deps.logger?.error?.("ask_decision_row_not_authoritative", {
1271
1269
  taskId,
1272
1270
  askId,
@@ -1297,8 +1295,8 @@ export async function handleRunVerbs(req, res, match, ctx) {
1297
1295
  const replayDecided = (row) => {
1298
1296
  const storedActor = projectDecisionActor(row.decisionActor);
1299
1297
  sendJson(res, 200, {
1300
- askId: row.askId,
1301
- taskId: row.taskId,
1298
+ askId,
1299
+ taskId,
1302
1300
  decision: row.decision,
1303
1301
  decidedAtMs: row.decidedAtMs,
1304
1302
  ...(storedActor ? { actor: storedActor } : {}),
@@ -1306,7 +1304,78 @@ export async function handleRunVerbs(req, res, match, ctx) {
1306
1304
  ...noteReceipt(row),
1307
1305
  });
1308
1306
  };
1309
- const sendTerminal = (row) => {
1307
+ const policyMayNotApprove = (row) => body.decision === "approve" && policyCannotAnswer(heldAskOf(storedCardDemandsAPerson(row.cardJson)), decider.decidedBy);
1308
+ const refusePolicyApprove = () => sendError(res, 400, "request.field_conflict", POLICY_CANNOT_ALLOW_PERSON_ASK, fieldConflictFacts("policy_person_ask", ["decidedBy", "decision"]));
1309
+ const conflictWithFirst = (row) => {
1310
+ const first = projectDecisionActor(row.decisionActor);
1311
+ sendError(res, 409, "conflict.ask_decided", "this ask was already decided — the first decision stands and is echoed here", {
1312
+ decision: row.decision,
1313
+ decidedAtMs: row.decidedAtMs,
1314
+ ...(first ? { actor: first } : {}),
1315
+ ...decisionNoteEcho(row),
1316
+ });
1317
+ };
1318
+ const answerParked = async (row) => {
1319
+ const answer = await coordinator.decideParkedAsk(askStore, row, {
1320
+ write: { decision: body.decision, decider, ...(body.note !== undefined ? { note: body.note } : {}), actor, ...(body.idempotencyKey !== undefined ? { idempotencyKey: body.idempotencyKey } : {}) },
1321
+ ...(body.decision === "approve" && hasUpdatedInput ? { updatedInput: body.updatedInput } : {}),
1322
+ ...(principal !== undefined ? { principal } : {}),
1323
+ operator: callerIsOperator,
1324
+ policyMayNotApprove: policyMayNotApprove(row),
1325
+ httpReq: req,
1326
+ }, body.idempotencyKey);
1327
+ switch (answer.kind) {
1328
+ case "standing": {
1329
+ const first = { decision: answer.decision, decidedAtMs: answer.decidedAtMs, decisionActor: answer.actor ?? null, decisionNote: answer.decisionNote ?? null };
1330
+ if (answer.byThisRequest)
1331
+ replayDecided(first);
1332
+ else
1333
+ conflictWithFirst(first);
1334
+ return;
1335
+ }
1336
+ case "refused":
1337
+ if (answer.status === 404) {
1338
+ askNotFound();
1339
+ return;
1340
+ }
1341
+ mirrorRetryAfter(res, answer.body);
1342
+ sendJson(res, answer.status, answer.body);
1343
+ return;
1344
+ case "gone":
1345
+ askNotFound();
1346
+ return;
1347
+ case "policy_refused":
1348
+ refusePolicyApprove();
1349
+ return;
1350
+ case "gate_only":
1351
+ sendError(res, 410, "gone.ask_parked", "the in-stream window closed and this ask was parked onto the durable approval gate — decide it through that gate for the session echoed here", {
1352
+ sessionId: parkSessionOf(row),
1353
+ gateBoundCallId: row.gateBoundCallId,
1354
+ gateBoundInputHash: row.gateBoundInputHash,
1355
+ });
1356
+ return;
1357
+ case "accepted": {
1358
+ const recorded = answer.recorded ?? { decisionNote: null };
1359
+ sendJson(res, 200, {
1360
+ ...answer.body,
1361
+ askId,
1362
+ taskId,
1363
+ decision: body.decision,
1364
+ decidedAtMs: answer.recorded?.decidedAtMs ?? Date.now(),
1365
+ actor,
1366
+ accepted: "parked_redeemed",
1367
+ ...decisionNoteEcho(recorded),
1368
+ ...noteReceipt(recorded),
1369
+ });
1370
+ return;
1371
+ }
1372
+ default: {
1373
+ const unhandled = answer;
1374
+ throw new Error(`unhandled parked ask answer: ${JSON.stringify(unhandled)}`);
1375
+ }
1376
+ }
1377
+ };
1378
+ const sendTerminal = async (row) => {
1310
1379
  switch (row.state) {
1311
1380
  case "DECIDED": {
1312
1381
  if (!syncLiveFromDecidedRow(row))
@@ -1315,21 +1384,11 @@ export async function handleRunVerbs(req, res, match, ctx) {
1315
1384
  replayDecided(row);
1316
1385
  return;
1317
1386
  }
1318
- const first = projectDecisionActor(row.decisionActor);
1319
- sendError(res, 409, "conflict.ask_decided", "this ask was already decided — the first decision stands and is echoed here", {
1320
- decision: row.decision,
1321
- decidedAtMs: row.decidedAtMs,
1322
- ...(first ? { actor: first } : {}),
1323
- ...decisionNoteEcho(row),
1324
- });
1387
+ conflictWithFirst(row);
1325
1388
  return;
1326
1389
  }
1327
1390
  case "PARKED":
1328
- sendError(res, 410, "gone.ask_parked", "the in-stream window closed and this ask was parked onto the durable approval gate — decide it through that gate for the session echoed here", {
1329
- sessionId: parkSessionOf(row),
1330
- gateBoundCallId: row.gateBoundCallId,
1331
- gateBoundInputHash: row.gateBoundInputHash,
1332
- });
1391
+ await answerParked(row);
1333
1392
  return;
1334
1393
  case "DENIED":
1335
1394
  case "VOID": {
@@ -1374,23 +1433,23 @@ export async function handleRunVerbs(req, res, match, ctx) {
1374
1433
  }
1375
1434
  }
1376
1435
  if (row0.state !== "STREAM_PENDING") {
1377
- sendTerminal(row0);
1436
+ await sendTerminal(row0);
1378
1437
  return;
1379
1438
  }
1380
- if (body.decision === "approve" && policyCannotAnswer(heldAskOf(storedCardDemandsAPerson(row0.cardJson)), decider.decidedBy)) {
1381
- sendError(res, 400, "request.field_conflict", POLICY_CANNOT_ALLOW_PERSON_ASK, fieldConflictFacts("policy_person_ask", ["decidedBy", "decision"]));
1439
+ if (policyMayNotApprove(row0)) {
1440
+ refusePolicyApprove();
1382
1441
  return;
1383
1442
  }
1384
1443
  let outcome;
1385
1444
  const releaseEditMark = body.decision === "approve" && hasUpdatedInput ? deps.toolApproval?.markEditedDecisionInFlight(askId) : undefined;
1386
1445
  try {
1387
- outcome = await askStore.decideAsk(askId, row0.batchId, row0.owner, {
1446
+ outcome = await coordinator.writeAskDecision(askStore, askId, { kind: "live", batchId: row0.batchId }, row0.owner, {
1388
1447
  decision: body.decision,
1389
- decisionActor: actor,
1390
- decisionNote: body.note ?? null,
1391
- idempotencyKey: body.idempotencyKey ?? null,
1392
- ...liveHostSource(decider),
1393
- ...(body.decision === "approve" && hasUpdatedInput ? { updatedInput: body.updatedInput } : {}),
1448
+ decider,
1449
+ actor,
1450
+ ...(body.note !== undefined ? { note: body.note } : {}),
1451
+ ...(body.idempotencyKey !== undefined ? { idempotencyKey: body.idempotencyKey } : {}),
1452
+ ...(hasUpdatedInput ? { updatedInput: body.updatedInput } : {}),
1394
1453
  });
1395
1454
  }
1396
1455
  catch (err) {
@@ -1450,7 +1509,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1450
1509
  askNotFound();
1451
1510
  return;
1452
1511
  }
1453
- sendTerminal(outcome.row);
1512
+ await sendTerminal(outcome.row);
1454
1513
  return;
1455
1514
  }
1456
1515
  if (!decidedRowIsAuthoritative(outcome.row))
@@ -1509,9 +1568,9 @@ async function createDurableRunHeld(req, res, ctx, prepared, idem) {
1509
1568
  const submitter = gatedSubject(req, deps.config);
1510
1569
  const caller = { subject: submitter, idem, ...(clientTaskId !== undefined ? { clientTaskId } : {}) };
1511
1570
  if (clientTaskId) {
1512
- const existing = await runStore.getRun(clientTaskId);
1513
- if (existing)
1514
- return await replayOfExistingRun(existing, caller, "durable", deps, runStore);
1571
+ const replayed = await replayOfKey({ taskId: clientTaskId }, caller, "durable", deps, runStore);
1572
+ if (replayed !== undefined)
1573
+ return replayed;
1515
1574
  }
1516
1575
  if ((await leaseDenied(req, res, seat)) || (await usageWindowDenied(req, res, seat)))
1517
1576
  return null;
@@ -1,6 +1,6 @@
1
1
  import { memorySyncReportOf } from "@sema-agent/core";
2
2
  import { sendJson, sendError } from "../send.js";
3
- import { admitSessionById, enter } from "../owner-access.js";
3
+ import { admitSessionById, enter, latestRunIdOf, readVisibleSession } from "../owner-access.js";
4
4
  import { assertNever } from "../route-ctx.js";
5
5
  import * as facts from "../../capability-facts.js";
6
6
  import { leafOfAdmittedHead } from "../../session-incarnation.js";
@@ -94,7 +94,6 @@ export async function handleSessionMemorySync(req, res, match, ctx) {
94
94
  sendError(res, 400, "request.path_malformed", "session id segment is not valid percent-encoding");
95
95
  return;
96
96
  }
97
- const readHead = () => sessionStorage.headOf(sessionId);
98
97
  const admitted = await admitSessionById(entry, res, sessionStorage, sessionId);
99
98
  if (admitted === undefined)
100
99
  return;
@@ -122,10 +121,10 @@ export async function handleSessionMemorySync(req, res, match, ctx) {
122
121
  const quiet = async () => {
123
122
  if ((await runStore.getActiveTaskId(sessionId)) !== undefined)
124
123
  return false;
125
- if ((await runStore.latestRunForSession(sessionId))?.taskId !== observedTaskId)
124
+ if ((await latestRunIdOf(runStore, sessionId)) !== observedTaskId)
126
125
  return false;
127
- const now = await readHead();
128
- return now !== undefined && leafOfAdmittedHead(now) === sourceRevision;
126
+ const now = await readVisibleSession(entry, sessionStorage, sessionId);
127
+ return now !== undefined && leafOfAdmittedHead(now.row) === sourceRevision;
129
128
  };
130
129
  const fenced = () => reportOf({ target, sourceRevision, scopes, refused: { code: "session_active", message: SESSION_ACTIVE_SYNC_MESSAGE } });
131
130
  let report;
@@ -13,6 +13,7 @@ import { type ImportAnchor, type StagingHandle } from "../../session-sync-kernel
13
13
  import type { DurableOwnerKey } from "../../owner-brands.js";
14
14
  import type { RouteCtx, RouteMatch, RouteIdsOf } from "../route-ctx.js";
15
15
  import { type SessionRowPatch } from "../../session-row.js";
16
+ import { type SessionFace } from "../../session-incarnation.js";
16
17
  export type PendingStaging = {
17
18
  handle: StagingHandle;
18
19
  realSessionId: string;
@@ -33,9 +34,9 @@ export type PendingStaging = {
33
34
  /** The principal that opened this staging, kept as the handle's owner key (`null` = a fleet caller opened it) — a different caller may not drive it
34
35
  * (404, no oracle; compared through `owner-faces.ts` `sameKey` only). */
35
36
  openedBy: DurableOwnerKey | null;
36
- /** The owner cell the gate judged when it opened this staging (head-read reading `headOf(id)?.owner`: `undefined` = no such session) — the commit lands only on
37
- * this same cell (`StagedCommitOptions.expectedOwner`, `session-sync-kernel.ts`); `owner` above (the re-stamped importing principal) is derived from it for a fleet caller. */
38
- expectedOwner: string | null | undefined;
37
+ /** The live occupant the gate judged when it opened this staging (owner ∧ incarnation, the head read: `undefined` = no live session) — the commit lands only on
38
+ * this same occupant (`StagedCommitOptions.expectedOccupant`, `session-sync-kernel.ts`); `owner` above (the re-stamped importing principal) is derived from its owner for a fleet caller. */
39
+ expectedOccupant: SessionFace | undefined;
39
40
  /** 开这张暂存时占下的导入租约的键({@link importLeaseKey});续期与放掉都按它,不再从会话 id 重算。 */
40
41
  leaseKey: string;
41
42
  };