@sema-agent/server 7.150.0 → 7.152.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (514) hide show
  1. package/MIGRATION.md +451 -0
  2. package/README.md +15 -3
  3. package/README.zh-CN.md +10 -2
  4. package/USAGE.md +144 -87
  5. package/deploy/sema-up/README.md +11 -4
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
  9. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
  10. package/deploy/sema-up/chart/templates/server.yaml +5 -3
  11. package/deploy/sema-up/chart/values-full-single.yaml +3 -1
  12. package/deploy/sema-up/chart/values.yaml +8 -1
  13. package/deploy/sema-up/cluster-up.sh +7 -6
  14. package/deploy/sema-up/kube-up.sh +6 -6
  15. package/deploy/sema-up/lib/flagshape.sh +36 -8
  16. package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
  17. package/deploy/sema-up/lib/helm-values-kube.py +2 -0
  18. package/deploy/sema-up/machines.example.yaml +3 -1
  19. package/deploy/sema-up/sema-up.sh +22 -16
  20. package/dist/adoption/import.js +3 -3
  21. package/dist/approval-ask-audit-store.d.ts +1 -1
  22. package/dist/approval-ask-machine.d.ts +4 -10
  23. package/dist/approval-ask-retention.d.ts +1 -1
  24. package/dist/approval-card.d.ts +12 -14
  25. package/dist/approval-gate-currency.d.ts +9 -9
  26. package/dist/approval-gate-currency.js +3 -4
  27. package/dist/approval-hmac.d.ts +17 -1
  28. package/dist/approval-hmac.js +7 -1
  29. package/dist/approval-queue-kind.d.ts +1 -1
  30. package/dist/approval.d.ts +2 -2
  31. package/dist/approval.js +2 -2
  32. package/dist/auth-bridge.d.ts +20 -0
  33. package/dist/auth-bridge.js +9 -0
  34. package/dist/background-session-reap.d.ts +1 -1
  35. package/dist/bake-runner/main.d.ts +4 -2
  36. package/dist/bind-host.d.ts +3 -6
  37. package/dist/bind-host.js +4 -7
  38. package/dist/boot/budget-tracing.js +1 -1
  39. package/dist/boot/coordinators.d.ts +1 -1
  40. package/dist/boot/coordinators.js +9 -10
  41. package/dist/boot/device-lane.js +2 -0
  42. package/dist/boot/engine-lease.d.ts +5 -0
  43. package/dist/boot/engine-lease.js +1 -0
  44. package/dist/boot/execution-env.d.ts +9 -14
  45. package/dist/boot/execution-env.js +85 -22
  46. package/dist/boot/execution-lane.js +32 -5
  47. package/dist/boot/late-binds.d.ts +8 -4
  48. package/dist/boot/late-binds.js +7 -1
  49. package/dist/boot/leader.d.ts +31 -30
  50. package/dist/boot/leader.js +38 -28
  51. package/dist/boot/leg-path-adjudication.d.ts +40 -0
  52. package/dist/boot/leg-path-adjudication.js +18 -0
  53. package/dist/boot/memory-consolidation.d.ts +3 -2
  54. package/dist/boot/memory-consolidation.js +6 -6
  55. package/dist/boot/parked-revive-gate.js +3 -15
  56. package/dist/boot/reapers.d.ts +6 -1
  57. package/dist/boot/reapers.js +13 -2
  58. package/dist/boot/resolve-spec.d.ts +3 -3
  59. package/dist/boot/resolve-spec.js +43 -48
  60. package/dist/boot/runner-deps.d.ts +46 -35
  61. package/dist/boot/runner-deps.js +94 -91
  62. package/dist/boot/session-age-out.d.ts +36 -0
  63. package/dist/boot/session-age-out.js +101 -0
  64. package/dist/boot/session-faces.d.ts +5 -14
  65. package/dist/boot/session-faces.js +9 -5
  66. package/dist/boot/shutdown.d.ts +6 -0
  67. package/dist/boot/shutdown.js +10 -4
  68. package/dist/boot/stage-01-config.js +2 -0
  69. package/dist/boot/stage-02-web-admin-pull.js +4 -5
  70. package/dist/boot/stage-05-execution-env.d.ts +5 -3
  71. package/dist/boot/stage-05-execution-env.js +3 -2
  72. package/dist/boot/stage-06-runners.d.ts +9 -4
  73. package/dist/boot/stage-06-runners.js +24 -9
  74. package/dist/boot/stage-07-capability-layer.d.ts +8 -4
  75. package/dist/boot/stage-07-capability-layer.js +3 -2
  76. package/dist/boot/stage-08-reapers.d.ts +8 -4
  77. package/dist/boot/stage-08-reapers.js +4 -2
  78. package/dist/boot/stage-09-leader.d.ts +12 -5
  79. package/dist/boot/stage-09-leader.js +14 -5
  80. package/dist/boot/stage-10-http-server.d.ts +19 -5
  81. package/dist/boot/stage-10-http-server.js +14 -21
  82. package/dist/boot/stores.js +7 -4
  83. package/dist/boot/web-admin.js +5 -8
  84. package/dist/boot/workflow-orchestration.d.ts +7 -2
  85. package/dist/boot/workflow-orchestration.js +24 -7
  86. package/dist/bounded-rotation.d.ts +29 -0
  87. package/dist/bounded-rotation.js +24 -0
  88. package/dist/capabilities/approvals-push.d.ts +3 -3
  89. package/dist/capabilities/scenarios.d.ts +28 -13
  90. package/dist/capabilities/scenarios.js +2 -2
  91. package/dist/capability-facts.d.ts +43 -32
  92. package/dist/capability-facts.js +45 -51
  93. package/dist/card-rule-offers.d.ts +32 -0
  94. package/dist/card-rule-offers.js +130 -0
  95. package/dist/center-credential.d.ts +25 -6
  96. package/dist/center-credential.js +25 -5
  97. package/dist/config-catalog.d.ts +26 -7
  98. package/dist/config-catalog.js +26 -22
  99. package/dist/config-dir-trust.js +4 -2
  100. package/dist/config-invariants.d.ts +20 -8
  101. package/dist/config-invariants.js +55 -12
  102. package/dist/config-lkg.d.ts +5 -19
  103. package/dist/config-lkg.js +8 -62
  104. package/dist/config-provider.d.ts +1 -1
  105. package/dist/config-root-migration.d.ts +2 -2
  106. package/dist/config-types.d.ts +38 -42
  107. package/dist/config.d.ts +58 -7
  108. package/dist/config.js +90 -40
  109. package/dist/control-socket.d.ts +51 -0
  110. package/dist/control-socket.js +115 -0
  111. package/dist/deployment-governance.d.ts +2 -1
  112. package/dist/deployment-shape.d.ts +9 -1
  113. package/dist/deployment-shape.js +2 -1
  114. package/dist/device-protocol.d.ts +5 -4
  115. package/dist/device-protocol.js +1 -1
  116. package/dist/device-ws-hub.d.ts +7 -0
  117. package/dist/device-ws-hub.js +10 -3
  118. package/dist/device-ws-protocol.d.ts +63 -10
  119. package/dist/device-ws-protocol.js +56 -25
  120. package/dist/elicitation.js +2 -2
  121. package/dist/engine-identity.d.ts +19 -7
  122. package/dist/engine-identity.js +10 -2
  123. package/dist/entry-mode-clamp-notice.d.ts +2 -1
  124. package/dist/entry-problems.d.ts +40 -3
  125. package/dist/entry-problems.js +3 -1
  126. package/dist/execution-env-refusal.d.ts +29 -0
  127. package/dist/execution-env-refusal.js +8 -0
  128. package/dist/execution-lane-caps.d.ts +3 -1
  129. package/dist/field-conflict.d.ts +1 -1
  130. package/dist/file-history-capture.d.ts +11 -4
  131. package/dist/file-history-capture.js +9 -6
  132. package/dist/file-history-disclosure.d.ts +7 -5
  133. package/dist/file-history-disclosure.js +7 -5
  134. package/dist/fleet/drain-entry.d.ts +4 -0
  135. package/dist/fleet/engine-signal.d.ts +12 -29
  136. package/dist/fleet/engine-signal.js +1 -7
  137. package/dist/fleet-client.js +2 -5
  138. package/dist/gate-settlement.d.ts +1 -8
  139. package/dist/gate-settlement.js +0 -4
  140. package/dist/history-anchor.js +1 -1
  141. package/dist/hitl-delivery.d.ts +2 -3
  142. package/dist/hitl-delivery.js +0 -2
  143. package/dist/hooks/hook-llm.js +4 -2
  144. package/dist/hooks/hook-runner.d.ts +3 -2
  145. package/dist/hooks/hook-runner.js +18 -3
  146. package/dist/host-decision.d.ts +11 -11
  147. package/dist/host-lsp-manager.d.ts +2 -2
  148. package/dist/http/active-run-conflict.d.ts +35 -2
  149. package/dist/http/active-run-conflict.js +48 -19
  150. package/dist/http/admission.js +17 -2
  151. package/dist/http/approval-sweeps.d.ts +1 -1
  152. package/dist/http/approval-sweeps.js +10 -7
  153. package/dist/http/checkpoint-ctx.d.ts +4 -0
  154. package/dist/http/checkpoint-ctx.js +2 -0
  155. package/dist/http/dispatch.d.ts +8 -3
  156. package/dist/http/dispatch.js +59 -32
  157. package/dist/http/durable-run-leg.js +16 -17
  158. package/dist/http/health-reader.d.ts +16 -9
  159. package/dist/http/health-reader.js +2 -1
  160. package/dist/http/health-self-report.d.ts +9 -1
  161. package/dist/http/health-self-report.js +3 -1
  162. package/dist/http/owner-access.d.ts +33 -14
  163. package/dist/http/owner-access.js +40 -10
  164. package/dist/http/principal-gate.d.ts +49 -21
  165. package/dist/http/principal-gate.js +61 -11
  166. package/dist/http/request-channel.d.ts +23 -0
  167. package/dist/http/request-channel.js +9 -0
  168. package/dist/http/request-guards.js +17 -2
  169. package/dist/http/resume-ctx-read.js +42 -3
  170. package/dist/http/resume-legs.d.ts +4 -3
  171. package/dist/http/resume-legs.js +367 -117
  172. package/dist/http/route-ctx.d.ts +91 -15
  173. package/dist/http/route-ctx.js +17 -0
  174. package/dist/http/route-table.d.ts +5 -1
  175. package/dist/http/route-table.js +4 -0
  176. package/dist/http/routes/admin-config-refresh.js +3 -3
  177. package/dist/http/routes/admin-drain.d.ts +3 -0
  178. package/dist/http/routes/admin-drain.js +7 -7
  179. package/dist/http/routes/admin-memory-optout.d.ts +1 -1
  180. package/dist/http/routes/admin-memory-optout.js +3 -3
  181. package/dist/http/routes/adoption.js +3 -5
  182. package/dist/http/routes/agents-roster.js +2 -3
  183. package/dist/http/routes/approvals-assistant.d.ts +2 -1
  184. package/dist/http/routes/approvals-assistant.js +99 -51
  185. package/dist/http/routes/background.d.ts +3 -3
  186. package/dist/http/routes/capabilities.d.ts +4 -0
  187. package/dist/http/routes/capabilities.js +38 -10
  188. package/dist/http/routes/config-catalog.js +2 -2
  189. package/dist/http/routes/devices.js +1 -1
  190. package/dist/http/routes/diagnostics.d.ts +3 -3
  191. package/dist/http/routes/diagnostics.js +19 -7
  192. package/dist/http/routes/fleet.js +10 -8
  193. package/dist/http/routes/images.js +10 -10
  194. package/dist/http/routes/memory-bundle.js +3 -3
  195. package/dist/http/routes/memory-compliance.js +3 -3
  196. package/dist/http/routes/memory-consolidation.js +2 -2
  197. package/dist/http/routes/memory-origin.js +3 -3
  198. package/dist/http/routes/memory-policy.js +2 -2
  199. package/dist/http/routes/observability.js +3 -3
  200. package/dist/http/routes/projects.d.ts +3 -2
  201. package/dist/http/routes/projects.js +4 -5
  202. package/dist/http/routes/retention-ops.js +3 -3
  203. package/dist/http/routes/rules.js +5 -5
  204. package/dist/http/routes/run-permission-mode.d.ts +2 -1
  205. package/dist/http/routes/run-permission-mode.js +2 -2
  206. package/dist/http/routes/runs.d.ts +4 -9
  207. package/dist/http/routes/runs.js +171 -65
  208. package/dist/http/routes/session-sync.d.ts +22 -9
  209. package/dist/http/routes/session-sync.js +204 -107
  210. package/dist/http/routes/sessions-list.js +13 -7
  211. package/dist/http/routes/sessions.js +30 -15
  212. package/dist/http/routes/tasks.js +46 -41
  213. package/dist/http/routes/trace-usage.js +2 -2
  214. package/dist/http/routes/workflows.js +1 -1
  215. package/dist/http/server.d.ts +30 -30
  216. package/dist/http/server.js +16 -4
  217. package/dist/http/submit-ctx.d.ts +1 -1
  218. package/dist/http/submit-ctx.js +7 -4
  219. package/dist/http/wire-types.d.ts +14 -4
  220. package/dist/human-facing-args.d.ts +33 -0
  221. package/dist/human-facing-args.js +33 -0
  222. package/dist/identity-source.d.ts +20 -3
  223. package/dist/identity-source.js +14 -0
  224. package/dist/index.d.ts +5 -1
  225. package/dist/k8s-api-credentials.d.ts +29 -0
  226. package/dist/k8s-api-credentials.js +25 -0
  227. package/dist/lane-home-probe.d.ts +3 -7
  228. package/dist/lane-home-probe.js +2 -2
  229. package/dist/leader/diffup.d.ts +19 -0
  230. package/dist/leader/diffup.js +7 -0
  231. package/dist/leader/leader.d.ts +116 -11
  232. package/dist/leader/leader.js +69 -5
  233. package/dist/leader/repair-wire.js +2 -2
  234. package/dist/leader/run-entry.d.ts +2 -1
  235. package/dist/leader/run-entry.js +1 -1
  236. package/dist/leader/wire.d.ts +42 -132
  237. package/dist/leader/wire.js +81 -67
  238. package/dist/leg-facts.d.ts +13 -5
  239. package/dist/leg-facts.js +2 -1
  240. package/dist/memory-scope.d.ts +23 -11
  241. package/dist/memory-scope.js +18 -6
  242. package/dist/memory-sync-client.d.ts +30 -2
  243. package/dist/memory-sync-client.js +16 -9
  244. package/dist/model-entry-headers.d.ts +9 -10
  245. package/dist/model-entry-headers.js +0 -4
  246. package/dist/model-entry-refusal.d.ts +7 -4
  247. package/dist/model-entry-refusal.js +11 -5
  248. package/dist/model-plane-face.d.ts +1 -1
  249. package/dist/model-plane-face.js +3 -1
  250. package/dist/model-route-endpoint.d.ts +13 -7
  251. package/dist/model-route-endpoint.js +14 -11
  252. package/dist/model-select.d.ts +22 -0
  253. package/dist/model-select.js +9 -0
  254. package/dist/model-unreachable-notice.d.ts +11 -0
  255. package/dist/model-unreachable-notice.js +4 -4
  256. package/dist/object-store-buckets.d.ts +640 -6
  257. package/dist/object-store-buckets.js +166 -0
  258. package/dist/observability/err-text.d.ts +7 -0
  259. package/dist/observability/err-text.js +5 -0
  260. package/dist/observability/fail-open.d.ts +25 -17
  261. package/dist/observability/fail-open.js +25 -17
  262. package/dist/observability/logger.js +3 -1
  263. package/dist/observability/metrics.js +1 -0
  264. package/dist/operator-roster.d.ts +68 -0
  265. package/dist/operator-roster.js +32 -0
  266. package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
  267. package/dist/orchestration/workflow-notify-journal.js +12 -1
  268. package/dist/orchestration/workflow-park-decision.d.ts +70 -18
  269. package/dist/orchestration/workflow-park-decision.js +49 -10
  270. package/dist/orchestration/workflow-park-holder.d.ts +65 -0
  271. package/dist/orchestration/workflow-park-holder.js +98 -0
  272. package/dist/orchestration/workflow-record-fence.d.ts +36 -0
  273. package/dist/orchestration/workflow-record-fence.js +42 -0
  274. package/dist/outbound-dispatcher.d.ts +71 -8
  275. package/dist/outbound-dispatcher.js +48 -7
  276. package/dist/owner-faces.d.ts +2 -2
  277. package/dist/parked-decide.d.ts +106 -55
  278. package/dist/parked-decide.js +153 -117
  279. package/dist/peer-directory.d.ts +2 -2
  280. package/dist/peer-inbound-face.d.ts +2 -6
  281. package/dist/peer-inbound-face.js +0 -3
  282. package/dist/permission-mode-admission.d.ts +74 -5
  283. package/dist/permission-mode-admission.js +56 -3
  284. package/dist/plugins/adoption-log-sql.d.ts +3 -1
  285. package/dist/plugins/adoption-log-sql.js +7 -1
  286. package/dist/plugins/approval-ask-store-file.d.ts +14 -2
  287. package/dist/plugins/approval-ask-store-file.js +11 -0
  288. package/dist/plugins/approval-ask-store-memory.d.ts +10 -1
  289. package/dist/plugins/approval-ask-store-memory.js +35 -10
  290. package/dist/plugins/approval-ask-store-sql.d.ts +69 -4
  291. package/dist/plugins/approval-ask-store-sql.js +45 -5
  292. package/dist/plugins/approval-exemption-store.js +3 -0
  293. package/dist/plugins/approval-nonce-store.js +2 -0
  294. package/dist/plugins/blob-backend.d.ts +83 -7
  295. package/dist/plugins/blob-backend.js +57 -6
  296. package/dist/plugins/breaker-state-sql.js +2 -0
  297. package/dist/plugins/caching-session-store.d.ts +9 -15
  298. package/dist/plugins/caching-session-store.js +6 -0
  299. package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
  300. package/dist/plugins/checkpoint-index-columns.js +3 -6
  301. package/dist/plugins/checkpoint-store-face.d.ts +119 -61
  302. package/dist/plugins/checkpoint-store-face.js +134 -55
  303. package/dist/plugins/device-store-sql.js +6 -0
  304. package/dist/plugins/error-origin.d.ts +18 -0
  305. package/dist/plugins/error-origin.js +10 -0
  306. package/dist/plugins/execution-placement-sql.js +6 -6
  307. package/dist/plugins/image-bake-store-sql.js +6 -0
  308. package/dist/plugins/image-index-sql.js +4 -0
  309. package/dist/plugins/landed-attendants.d.ts +212 -0
  310. package/dist/plugins/landed-attendants.js +161 -0
  311. package/dist/plugins/leader-run-store-sql.js +4 -0
  312. package/dist/plugins/local-checkpoint-store.d.ts +13 -3
  313. package/dist/plugins/local-checkpoint-store.js +38 -49
  314. package/dist/plugins/local-session-live-reference.d.ts +40 -0
  315. package/dist/plugins/local-session-live-reference.js +39 -0
  316. package/dist/plugins/local-session-store.d.ts +71 -33
  317. package/dist/plugins/local-session-store.js +129 -27
  318. package/dist/plugins/memory-engine-pg.js +4 -0
  319. package/dist/plugins/memory-engine-sql-apply.js +5 -2
  320. package/dist/plugins/memory-engine-tidb.js +4 -0
  321. package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
  322. package/dist/plugins/memory-sync-store-pg.js +5 -0
  323. package/dist/plugins/memory-sync-store-tidb.js +5 -0
  324. package/dist/plugins/one-time-migrations.d.ts +104 -80
  325. package/dist/plugins/one-time-migrations.js +226 -132
  326. package/dist/plugins/org-delivery-quota-store.js +4 -1
  327. package/dist/plugins/outcome-ledger-sql.js +2 -0
  328. package/dist/plugins/permission-rule-store-sql.js +11 -4
  329. package/dist/plugins/pg-cost-quota.js +4 -0
  330. package/dist/plugins/pg-pool.js +35 -10
  331. package/dist/plugins/pg-rate-limiter.js +2 -0
  332. package/dist/plugins/posix-shell-fs.d.ts +6 -1
  333. package/dist/plugins/posix-shell-fs.js +4 -1
  334. package/dist/plugins/remote-env-adb.d.ts +19 -15
  335. package/dist/plugins/remote-env-adb.js +41 -15
  336. package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
  337. package/dist/plugins/remote-env-connect-seat.js +72 -0
  338. package/dist/plugins/remote-env-device.d.ts +22 -5
  339. package/dist/plugins/remote-env-device.js +106 -8
  340. package/dist/plugins/remote-env-e2b.d.ts +15 -6
  341. package/dist/plugins/remote-env-e2b.js +42 -32
  342. package/dist/plugins/remote-env-file-error.js +6 -2
  343. package/dist/plugins/remote-env-host.d.ts +46 -10
  344. package/dist/plugins/remote-env-host.js +124 -52
  345. package/dist/plugins/remote-env-k8s.d.ts +109 -41
  346. package/dist/plugins/remote-env-k8s.js +160 -54
  347. package/dist/plugins/remote-env-local-docker.d.ts +13 -8
  348. package/dist/plugins/remote-env-local-docker.js +34 -41
  349. package/dist/plugins/remote-env-ssh.d.ts +18 -12
  350. package/dist/plugins/remote-env-ssh.js +60 -59
  351. package/dist/plugins/remote-shell.d.ts +98 -1
  352. package/dist/plugins/remote-shell.js +218 -0
  353. package/dist/plugins/replica-registration.d.ts +1 -1
  354. package/dist/plugins/replica-registration.js +1 -1
  355. package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
  356. package/dist/plugins/resume-anchor-store-sql.js +12 -5
  357. package/dist/plugins/retention-lane-store-sql.js +4 -0
  358. package/dist/plugins/retention-sql.d.ts +20 -2
  359. package/dist/plugins/retention-sql.js +11 -0
  360. package/dist/plugins/run-store-sql.d.ts +21 -2
  361. package/dist/plugins/run-store-sql.js +31 -7
  362. package/dist/plugins/s3-presign.d.ts +23 -0
  363. package/dist/plugins/s3-presign.js +37 -3
  364. package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
  365. package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
  366. package/dist/plugins/scheduler-support.d.ts +2 -2
  367. package/dist/plugins/scheduler-support.js +0 -3
  368. package/dist/plugins/schema-consistency.d.ts +4 -2
  369. package/dist/plugins/schema-consistency.js +19 -2
  370. package/dist/plugins/schema-indexes.js +2 -0
  371. package/dist/plugins/send-file-ledger.d.ts +2 -2
  372. package/dist/plugins/send-file-ledger.js +5 -2
  373. package/dist/plugins/send-user-file.d.ts +3 -4
  374. package/dist/plugins/send-user-file.js +56 -52
  375. package/dist/plugins/serving-requirement.d.ts +26 -7
  376. package/dist/plugins/serving-requirement.js +11 -4
  377. package/dist/plugins/session-birth.d.ts +6 -2
  378. package/dist/plugins/session-blob-claim-token.d.ts +15 -0
  379. package/dist/plugins/session-blob-claim-token.js +20 -0
  380. package/dist/plugins/session-blob-namespace.d.ts +46 -0
  381. package/dist/plugins/session-blob-namespace.js +116 -0
  382. package/dist/plugins/session-capture-record-store-sql.js +2 -0
  383. package/dist/plugins/session-ext-table.d.ts +14 -1
  384. package/dist/plugins/session-ext-table.js +5 -1
  385. package/dist/plugins/session-row-sql.d.ts +49 -2
  386. package/dist/plugins/session-row-sql.js +56 -13
  387. package/dist/plugins/session-store-sql.d.ts +34 -18
  388. package/dist/plugins/session-store-sql.js +98 -17
  389. package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
  390. package/dist/plugins/shared-memory-store-sql.js +6 -2
  391. package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
  392. package/dist/plugins/snapshot-bucket-presence.js +8 -2
  393. package/dist/plugins/sql-driver.d.ts +2 -1
  394. package/dist/plugins/sql-driver.js +18 -3
  395. package/dist/plugins/sql-errors.d.ts +11 -6
  396. package/dist/plugins/sql-errors.js +5 -6
  397. package/dist/plugins/sql-json-column.d.ts +1 -1
  398. package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
  399. package/dist/plugins/stop-then-start-sentence.js +14 -10
  400. package/dist/plugins/stop-then-start.d.ts +109 -0
  401. package/dist/plugins/stop-then-start.js +104 -0
  402. package/dist/plugins/store-backend.d.ts +84 -15
  403. package/dist/plugins/store-backend.js +236 -72
  404. package/dist/plugins/store-boundary.d.ts +57 -0
  405. package/dist/plugins/store-boundary.js +139 -0
  406. package/dist/plugins/store-contracts.d.ts +17 -0
  407. package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
  408. package/dist/plugins/store-fault-sentence-m53.js +25 -0
  409. package/dist/plugins/store-fault.d.ts +26 -7
  410. package/dist/plugins/store-fault.js +18 -2
  411. package/dist/plugins/task-attachment-store.d.ts +2 -1
  412. package/dist/plugins/task-attachment-store.js +14 -1
  413. package/dist/plugins/task-list-store-sql.d.ts +2 -2
  414. package/dist/plugins/task-list-store-sql.js +10 -8
  415. package/dist/plugins/tidb-cost-quota.js +4 -0
  416. package/dist/plugins/tidb-pool.js +21 -25
  417. package/dist/plugins/tidb-rate-limiter.js +4 -0
  418. package/dist/plugins/user-input-ledger-sql.js +4 -0
  419. package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
  420. package/dist/plugins/workflow-run-store-sql.js +64 -4
  421. package/dist/plugins/workspace-custody.d.ts +4 -3
  422. package/dist/plugins/workspace-fill.d.ts +4 -7
  423. package/dist/plugins/workspace-fill.js +2 -1
  424. package/dist/plugins/write-behind-counter.js +5 -0
  425. package/dist/project-context.d.ts +0 -2
  426. package/dist/project-context.js +4 -8
  427. package/dist/project-registry.d.ts +46 -0
  428. package/dist/project-registry.js +44 -0
  429. package/dist/question.d.ts +2 -1
  430. package/dist/question.js +5 -13
  431. package/dist/request-form.d.ts +6 -1
  432. package/dist/request-form.js +4 -1
  433. package/dist/request-key-closure.js +1 -1
  434. package/dist/request-value-closure.d.ts +4 -0
  435. package/dist/request-value-closure.js +10 -0
  436. package/dist/rule-issue-reading.d.ts +1 -1
  437. package/dist/rules-consent.d.ts +1 -1
  438. package/dist/run-acceptance.d.ts +3 -2
  439. package/dist/run-acceptance.js +4 -6
  440. package/dist/run-local.js +9 -9
  441. package/dist/runs.d.ts +54 -16
  442. package/dist/runs.js +67 -13
  443. package/dist/runtime-governance.d.ts +5 -4
  444. package/dist/security.d.ts +30 -32
  445. package/dist/security.js +41 -7
  446. package/dist/sema-config-dir.d.ts +2 -1
  447. package/dist/server-secret-env.d.ts +12 -10
  448. package/dist/server-secret-env.js +24 -15
  449. package/dist/session-bindings.d.ts +82 -0
  450. package/dist/session-bindings.js +18 -0
  451. package/dist/session-children-retire.d.ts +2 -2
  452. package/dist/session-children-retire.js +2 -6
  453. package/dist/session-deletion.d.ts +16 -1
  454. package/dist/session-error-wire.d.ts +3 -3
  455. package/dist/session-error-wire.js +3 -3
  456. package/dist/session-incarnation.d.ts +10 -0
  457. package/dist/session-incarnation.js +10 -1
  458. package/dist/session-kind.d.ts +57 -0
  459. package/dist/session-kind.js +22 -0
  460. package/dist/session-row.d.ts +21 -1
  461. package/dist/session-row.js +7 -1
  462. package/dist/session-sync-kernel.d.ts +24 -14
  463. package/dist/session-sync-kernel.js +3 -6
  464. package/dist/session-sync.d.ts +25 -103
  465. package/dist/session-sync.js +14 -76
  466. package/dist/session-titler.d.ts +10 -3
  467. package/dist/session-titler.js +19 -6
  468. package/dist/ssh-host-key.d.ts +5 -0
  469. package/dist/ssh-host-key.js +3 -0
  470. package/dist/stores-sql/blob-index-sql.d.ts +30 -9
  471. package/dist/stores-sql/blob-index-sql.js +40 -21
  472. package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
  473. package/dist/stores-sql/checkpoint-store-sql.js +70 -146
  474. package/dist/stores-sql/file-history-store-sql.d.ts +113 -15
  475. package/dist/stores-sql/file-history-store-sql.js +205 -95
  476. package/dist/stores-sql/pg-session-storage.d.ts +34 -7
  477. package/dist/stores-sql/pg-session-storage.js +37 -13
  478. package/dist/stores-sql/retention-store-sql.d.ts +1 -9
  479. package/dist/stores-sql/retention-store-sql.js +5 -19
  480. package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
  481. package/dist/stores-sql/session-policy-store-sql.js +61 -44
  482. package/dist/stores-sql/session-write-hooks.d.ts +11 -0
  483. package/dist/stores-sql/tidb-session-store.d.ts +58 -7
  484. package/dist/stores-sql/tidb-session-store.js +37 -13
  485. package/dist/submission-exit.d.ts +3 -2
  486. package/dist/submission-exit.js +9 -1
  487. package/dist/task-cwd.d.ts +2 -2
  488. package/dist/task-settings.d.ts +7 -5
  489. package/dist/task-settings.js +3 -3
  490. package/dist/terminal.d.ts +33 -2
  491. package/dist/terminal.js +139 -9
  492. package/dist/tool-approval.d.ts +465 -507
  493. package/dist/tool-approval.js +606 -1222
  494. package/dist/trace/core-keyset-guard.d.ts +1 -1
  495. package/dist/trace/ledger-events.d.ts +3 -3
  496. package/dist/trace/project.d.ts +2 -3
  497. package/dist/trace/redact.js +3 -2
  498. package/dist/trace/self-minted-wire.d.ts +571 -178
  499. package/dist/trace/self-minted-wire.js +189 -56
  500. package/dist/web-admin-client/apply-effective.js +2 -2
  501. package/dist/web-admin-client/read-warnings.d.ts +2 -2
  502. package/dist/web-admin-client/read-warnings.js +1 -1
  503. package/dist/web-admin-client/types.d.ts +1 -1
  504. package/dist/workspace-space.d.ts +10 -4
  505. package/dist/workspace-space.js +4 -1
  506. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +79 -28
  507. package/package.json +7 -3
  508. package/scripts/embed-minimal.mjs +3 -3
  509. package/wire-changes/server@7.151.0.json +762 -0
  510. package/wire-changes/server@7.152.0.json +900 -0
  511. package/dist/config-d-migration.d.ts +0 -37
  512. package/dist/config-d-migration.js +0 -60
  513. package/dist/http/session-inherit-env.d.ts +0 -36
  514. package/dist/http/session-inherit-env.js +0 -6
@@ -1,3 +1,4 @@
1
+ import { createHash } from "node:crypto";
1
2
  import { SessionError, materializeA2aTools, materializeMcpTools, sanitizePathComponent } from "@sema-agent/core";
2
3
  import { a2aForScenario, mcpForScenario } from "../../web-admin-client/facade.js";
3
4
  import { HttpError, isUuidShape } from "../../security.js";
@@ -14,8 +15,9 @@ import { readWritableSessionPermissionRules } from "../../session-policy-wire.js
14
15
  import { sendJson, sendError, sendSessionError, sendSessionPolicyError, sseHeaders, httpErrorBody } from "../send.js";
15
16
  import { gatedPerson, gatedSubject, sendPrincipalRefusal } from "../principal-gate.js";
16
17
  import { personOf } from "../../owner-brands.js";
18
+ import { scenarioRequestedBySubject } from "../../request-form.js";
17
19
  import { leafOfAdmittedHead, sessionFaceOfHead } from "../../session-incarnation.js";
18
- import { admitSessionById, admitSessionForDeletion, admitSessionRow, admitSessionView, admittedAsFleet, callerEntry, callerOf, deliverVerdict, enter, judgeSessionById, protocolEntry, readOwnerCell, readVisibleLatestRun, refuse, sessionOwnerUnchanged } from "../owner-access.js";
20
+ import { admitSessionById, admitSessionForDeletion, admitSessionRow, admitSessionView, admittedAsFleet, callerEntry, callerOf, deliverVerdict, enter, judgeSessionById, protocolEntry, readOwnerCell, readVisibleLatestRun, refuse, sessionOccupantUnchanged } from "../owner-access.js";
19
21
  import { assertNever } from "../route-ctx.js";
20
22
  import * as facts from "../../capability-facts.js";
21
23
  import { rosterAgentId } from "./agents-roster.js";
@@ -23,6 +25,7 @@ import { projectSessionListRow } from "./sessions-list.js";
23
25
  import { readSessionRowPatch } from "../../session-row.js";
24
26
  import { forkPathOf, resolveExecutionContext } from "../execution-context.js";
25
27
  import { executionPlacementView } from "../../execution-placement.js";
28
+ import { readSessionOccupant, refusalOccupantOf } from "../active-run-conflict.js";
26
29
  import { anchorReaderOf, resolveHistoryAnchor } from "../../history-anchor.js";
27
30
  import { engineRefusalAnswerOf } from "../engine-refusal.js";
28
31
  import { buildRewindFilesReply } from "../rewind-files-reply.js";
@@ -135,7 +138,7 @@ export async function handleSessions(req, res, match, ctx) {
135
138
  const ledgerHalf = lastLegMcp === undefined ? {} : { lastLegMcp };
136
139
  let scenarioName;
137
140
  try {
138
- scenarioName = await deps.scenarioGate(principal, undefined);
141
+ ({ scenario: scenarioName } = await deps.scenarioGate(principal, scenarioRequestedBySubject(caller.subject, undefined)));
139
142
  }
140
143
  catch (e) {
141
144
  if (!(e instanceof HttpError))
@@ -192,7 +195,7 @@ export async function handleSessions(req, res, match, ctx) {
192
195
  sendPrincipalRefusal(res, req, deps.config);
193
196
  return;
194
197
  }
195
- const scenarioName = await deps.scenarioGate(principal, undefined);
198
+ const { scenario: scenarioName } = await deps.scenarioGate(principal, scenarioRequestedBySubject(gatedSubject(req, deps.config), undefined));
196
199
  const specs = a2aForScenario(deps.config.a2aPeers, scenarioName);
197
200
  if (!specs || specs.length === 0) {
198
201
  sendJson(res, 200, { peers: [], asOf: new Date().toISOString() });
@@ -256,13 +259,21 @@ export async function handleSessions(req, res, match, ctx) {
256
259
  if (admittedHead === undefined)
257
260
  return;
258
261
  const leafId = leafOfAdmittedHead(admittedHead.row);
259
- const etag = `"${leafId ?? "empty"}"`;
262
+ const runs = facts.durableRuns(deps);
263
+ const occupant = runs.available ? await readSessionOccupant(runs.runStore, headSession) : undefined;
264
+ if (occupant !== undefined && occupant.activeTaskId !== null && !(await sessionOccupantUnchanged(headEntry, headFact.sessionStorage, headSession, admittedHead.row))) {
265
+ refuse(headEntry, res, "missing");
266
+ return;
267
+ }
268
+ const body = { sessionId: headSession, leafId, ...occupant };
269
+ const bytes = JSON.stringify(body);
270
+ const etag = `"${createHash("sha256").update(bytes).digest("base64url")}"`;
260
271
  if (req.headers["if-none-match"] === etag) {
261
272
  res.writeHead(304, { etag }).end();
262
273
  return;
263
274
  }
264
- res.setHeader("etag", etag);
265
- sendJson(res, 200, { sessionId: headSession, leafId });
275
+ res.writeHead(200, { "content-type": "application/json", etag });
276
+ res.end(bytes);
266
277
  return;
267
278
  }
268
279
  }
@@ -462,7 +473,7 @@ export async function handleSessions(req, res, match, ctx) {
462
473
  }
463
474
  ownerCheckPending = true;
464
475
  ownerCheckStartedAt = Date.now();
465
- void sessionOwnerUnchanged(evEntry, evFact.sessionStorage, evSession, owner).then((same) => {
476
+ void sessionOccupantUnchanged(evEntry, evFact.sessionStorage, evSession, evAdmitted.row).then((same) => {
466
477
  ownerCheckPending = false;
467
478
  if (!closed && !same)
468
479
  onEnd();
@@ -592,7 +603,7 @@ export async function handleSessions(req, res, match, ctx) {
592
603
  sendJson(res, 200, {
593
604
  sessionId,
594
605
  autoConsolidationArmed: deps.memoryAutoConsolidationArmed,
595
- ...(deps.memorySyncLeg !== undefined ? { memorySync: { parked: deps.memorySyncLeg.parked().map((p) => ({ scope: p.scope, wayOut: p.wayOut })) } } : {}),
606
+ ...(deps.memorySyncLeg !== undefined ? { memorySync: { parked: deps.memorySyncLeg.parked() } } : {}),
596
607
  ...(s.captureOptedOut !== undefined ? { captureOptedOut: s.captureOptedOut } : {}),
597
608
  ...(s.committedCount !== undefined ? { committedCount: s.committedCount } : {}),
598
609
  ...(s.foldedCount !== undefined ? { foldedCount: s.foldedCount } : {}),
@@ -767,9 +778,9 @@ export async function handleSessions(req, res, match, ctx) {
767
778
  return;
768
779
  }
769
780
  const entryId = await resolveHistoryAnchor("rewindFilesTo", anchors, anchorReaderOf(req, deps, rewindEntry.caller), sessionId, read.to, sessionOwner, "to");
770
- const activeTaskId = await deps.runStore?.getActiveTaskId(sessionId);
771
- if (activeTaskId) {
772
- sendError(res, 409, "conflict.session_active_run", `session has an active run (${activeTaskId}); its files cannot be rewound under it — wait for that run to end (or cancel it), then rewind`, { activeTaskId });
781
+ const holder = await deps.runStore?.getActiveTaskId(sessionId);
782
+ if (holder) {
783
+ sendError(res, 409, "conflict.session_active_run", `session has an active run (${holder}); its files cannot be rewound under it — wait for that run to end (or cancel it), then rewind`, await refusalOccupantOf(deps.runStore, holder));
773
784
  return;
774
785
  }
775
786
  let result;
@@ -883,7 +894,7 @@ export async function handleSessions(req, res, match, ctx) {
883
894
  const owner = deleteAdmitted.row.owner;
884
895
  const result = await purge(sessionId, owner);
885
896
  if ("active" in result) {
886
- sendError(res, 409, "conflict.session_active_run", "session has an active run; cancel it before deleting", { activeTaskId: result.active });
897
+ sendError(res, 409, "conflict.session_active_run", "session has an active run; cancel it before deleting", await refusalOccupantOf(deps.runStore, result.active));
887
898
  return;
888
899
  }
889
900
  if ("inProgress" in result) {
@@ -905,7 +916,7 @@ export async function handleSessions(req, res, match, ctx) {
905
916
  sendError(res, 501, "capability.session_store_required", "session policy requires a session-store backend");
906
917
  return;
907
918
  }
908
- const store = policyFact.policyStore;
919
+ const store = policyFact.backend.sessionPolicy();
909
920
  const policyEntry = enter(req, res, deps, match.decl.id);
910
921
  if (policyEntry === undefined)
911
922
  return;
@@ -947,8 +958,12 @@ export async function handleSessions(req, res, match, ctx) {
947
958
  }
948
959
  const rules = read.rules;
949
960
  try {
950
- const stored = await store.putRules(sessionId, target, rules, { ...(typeof body.expectedRev === "number" ? { expectedRev: body.expectedRev } : {}), operator });
951
- sendJson(res, 200, { rules: stored });
961
+ const stored = await policyFact.backend.landedAttendants().putPolicy(sessionId, sessionFaceOfHead(sessionId, policyAdmitted.row), target, rules, { ...(typeof body.expectedRev === "number" ? { expectedRev: body.expectedRev } : {}), operator });
962
+ if (!stored.landed) {
963
+ refuse(policyEntry, res, "missing");
964
+ return;
965
+ }
966
+ sendJson(res, 200, { rules: stored.value });
952
967
  }
953
968
  catch (e) {
954
969
  if (sendSessionPolicyError(res, e))
@@ -1,7 +1,7 @@
1
1
  import { redactErrorMessage, redactHead, redactTerminalResult } from "../../observability/run-terminal.js";
2
2
  import { runWithVerification, runCascade, taskNotificationDedupKey, uuidv7 } from "@sema-agent/core";
3
3
  import { heldFor } from "../../peer-seat.js";
4
- import { beatRunHeartbeat, graftParkToolCallId, heldParkOf, markChildrenStoppedByUserOnAbort, syncRefusalHttpStatus, zeroWorkRefusalFacts, releaseKeyIfZeroWorkRefusal, createPromptCommitReader, settleResumeAnchor, TurnAnchorCapture, HEARTBEAT_MS } from "../../runs.js";
4
+ import { beatRunHeartbeat, createRunAnchorWriter, graftParkToolCallId, heldParkOf, markChildrenStoppedByUserOnAbort, syncRefusalHttpStatus, zeroWorkRefusalFacts, releaseKeyIfZeroWorkRefusal, TurnAnchorCapture, HEARTBEAT_MS } from "../../runs.js";
5
5
  import { commitParkRow } from "../../park-row-commit.js";
6
6
  import { atHostBoundary, failureCodeOf, sealResultForExit, outwardPlane } from "../../terminal.js";
7
7
  import { voidVerifierPauseCard } from "../../verifier-pause-card.js";
@@ -22,7 +22,7 @@ import { contextUsageEventData, turnEndEventData, toolStartEventData, toolEndEve
22
22
  import { cascadeConfig, fillRunPreviewOnDelivery, runMeta } from "../run-meta.js";
23
23
  import { idemCallerOf, inflightKeyOf, submissionIdemOf } from "../idempotency.js";
24
24
  import { answerReplay, isReplayedOutcome, replayedOutcome, replayOfExistingRun } from "../submit-replay.js";
25
- import { readReplayHit, runFactsOf } from "../owner-access.js";
25
+ import { readReplayHit, runFactsOf, sessionOccupantReadOf } from "../owner-access.js";
26
26
  import { httpErrorCode, sendJson, sseHeaders } from "../send.js";
27
27
  import { collectSsePreamble } from "../sse-log.js";
28
28
  import { buildApprovalPreamble } from "../../approval-card.js";
@@ -33,7 +33,7 @@ import { SUBMISSION_CLAIM_FACE, commitExecutionContext, faultedAnswerOf } from "
33
33
  import { rootSessionAbsentAnswer } from "../execution-context.js";
34
34
  import { recheckClaimBeforeLaunch, startClaimHeartbeat } from "../claim-heartbeat.js";
35
35
  import { timeClaim } from "../claim-latency.js";
36
- import { commitSessionInheritEnv } from "../session-inherit-env.js";
36
+ import { commitLegBindings } from "../../session-bindings.js";
37
37
  import { headerStr, gatedPerson, gatedSubject, explicitOperatorOk, runIdentityOf } from "../principal-gate.js";
38
38
  import { recoveredSubject } from "../../owner-faces.js";
39
39
  import { recordFailOpen } from "../../observability/fail-open.js";
@@ -172,7 +172,7 @@ export async function handleTasks(req, res, match, ctx) {
172
172
  };
173
173
  const assembleApprovalLeg = (streamApprovalOn) => resolveApprovalLeg({ ...approvalLegInput(streamApprovalOn), nowMonotonicMs: performance.now() });
174
174
  const principal = prepared.auth?.subject;
175
- const wiringOperatorFace = explicitOperatorOk(gatedPerson(req, deps.config), deps.config);
175
+ const wiringOperatorFace = explicitOperatorOk(gatedPerson(req, deps.config), deps.config, "operate");
176
176
  let wiringReceipt;
177
177
  const instructionLeg = createInstructionSelectionLeg();
178
178
  const legWiringSections = () => ({ instructions: instructionLeg.segment(), skills: prepared.legFacts?.skills });
@@ -236,7 +236,6 @@ export async function handleTasks(req, res, match, ctx) {
236
236
  onDisconnect();
237
237
  const replayGate = resolveStreamApprovalGate({
238
238
  toolApprovalEnabled: Boolean(deps.toolApproval),
239
- streamApprovalEnabled: deps.config.streamApproval?.enabled === true,
240
239
  backend: deps.backend,
241
240
  checkpointStore: deps.checkpointStore,
242
241
  });
@@ -291,18 +290,6 @@ export async function handleTasks(req, res, match, ctx) {
291
290
  let durableLegId;
292
291
  let durableHeartbeat;
293
292
  const cancelledResult = (errorMessage, cause) => mintCancelledResult({ taskId: durableTaskId ?? "", sessionId: prepared.spec.sessionId, startedAtMs: streamLegStartedAt, message: errorMessage, cause });
294
- let userMsgEntryId;
295
- const promptCommit = createPromptCommitReader();
296
- let anchorPut = false;
297
- const putRewindAnchor = async () => {
298
- const store = deps.resumeAnchorStore;
299
- const key = durableTaskId;
300
- const entryId = userMsgEntryId;
301
- if (anchorPut || !entryId || !key || !store)
302
- return;
303
- anchorPut = true;
304
- await settleResumeAnchor(() => store.put(prepared.spec.sessionId, key, entryId, principal ?? null), { leg: "stream", kind: "prompt" });
305
- };
306
293
  try {
307
294
  if (deps.runStore) {
308
295
  const tid = earlyDurableTid ?? uuidv7();
@@ -358,7 +345,7 @@ export async function handleTasks(req, res, match, ctx) {
358
345
  writeTerminalFrame(doneFrameOfOutcome(claimFault));
359
346
  return claimFault;
360
347
  }
361
- commitSessionInheritEnv(deps, prepared.spec.sessionId, prepared.body);
348
+ commitLegBindings(deps, prepared.seat, prepared.spec.sessionId, prepared.legFacts?.sessionBindings);
362
349
  markChildrenStoppedByUserOnAbort(ac.signal, durableTaskId ?? prepared.spec.sessionId, prepared.auth?.subject);
363
350
  let ledgerSink;
364
351
  let ledgerTerminal = false;
@@ -519,19 +506,36 @@ export async function handleTasks(req, res, match, ctx) {
519
506
  steerableRuns.set(durableTaskId, liveStream);
520
507
  prepared.acceptance.attachStream({ reachable: () => !closed && !res.writableEnded && !res.destroyed, write: (frame) => writeLiveFrame(res, { ...frame }) });
521
508
  const liveWorkspace = createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), prepared.legFacts?.sessionWitness);
509
+ const anchor = new TurnAnchorCapture(undefined, "stream", createRunAnchorWriter({
510
+ seat: deps.backend?.landedAttendants(),
511
+ sessionId: prepared.spec.sessionId,
512
+ owner: principal ?? null,
513
+ promptKey: durableTaskId,
514
+ witness: prepared.legFacts?.sessionWitness,
515
+ occupantOf: sessionOccupantReadOf(deps.sessionStorage),
516
+ leafOf: undefined,
517
+ }).prompt);
522
518
  for await (const ev of liveStream) {
523
519
  if (closed)
524
520
  break;
525
521
  for (const f of ev.type === "done" ? [...childText.cut(), ...topText.cut()] : topText.onEvent(ev))
526
522
  writeLiveFrame(res, f);
527
- const promptEntryId = promptCommit(ev);
528
- if (promptEntryId !== undefined)
529
- userMsgEntryId = promptEntryId;
530
523
  const causeAtDone = ev.type === "done" ? ac.cause() : undefined;
524
+ switch (ev.type) {
525
+ case "human_input":
526
+ anchor.onHumanInput(ev);
527
+ break;
528
+ case "message_committed":
529
+ await anchor.onMessageCommitted(ev.role, ev.entryId);
530
+ break;
531
+ case "turn_end":
532
+ await anchor.onTurnEnd();
533
+ break;
534
+ }
531
535
  await deps.userInputLedger?.observeLegEvent(liveStream, ev);
532
536
  await prepared.acceptance.observe(ev);
533
537
  if (ev.type === "done")
534
- prepared.acceptance.settle(ev.result);
538
+ await prepared.acceptance.settle(ev.result);
535
539
  await liveWorkspace.observe(ev);
536
540
  if (ledgerSink)
537
541
  await manifestSeat?.drain(ledgerSink.append);
@@ -545,7 +549,6 @@ export async function handleTasks(req, res, match, ctx) {
545
549
  }
546
550
  finalizeTaskResult(ev.result, principal, prepared.spec.objective);
547
551
  noteRunOutcome(finalResult);
548
- await putRewindAnchor();
549
552
  if (!(durableTaskId && deps.runStore && deps.checkpointStore && heldCard !== undefined))
550
553
  settleFleet(outwardPlane(finalResult.terminal).status, fleetRunResiduals(finalResult, failureCodeOf(finalResult.terminal)));
551
554
  if (ledgerSink && finalResult) {
@@ -687,7 +690,6 @@ export async function handleTasks(req, res, match, ctx) {
687
690
  : withElicit();
688
691
  const streamApprovalOn = resolveStreamApprovalGate({
689
692
  toolApprovalEnabled: Boolean(deps.toolApproval),
690
- streamApprovalEnabled: deps.config.streamApproval?.enabled === true,
691
693
  backend: deps.backend,
692
694
  checkpointStore: deps.checkpointStore,
693
695
  }).active;
@@ -701,14 +703,10 @@ export async function handleTasks(req, res, match, ctx) {
701
703
  abortSignal: ac.signal,
702
704
  sessionId: prepared.spec.sessionId,
703
705
  ...approvalLegOriginOf(prepared.execution),
704
- ...(streamApprovalOn
705
- ? {
706
- family: "approval_request",
707
- transport: hitlTransport,
708
- legKey: "",
709
- ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}),
710
- }
711
- : { family: "tool_approval", transport: hitlTransport }),
706
+ family: "approval_request",
707
+ transport: hitlTransport,
708
+ legKey: "",
709
+ ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}),
712
710
  }
713
711
  : undefined;
714
712
  if (deps.toolApproval) {
@@ -720,7 +718,8 @@ export async function handleTasks(req, res, match, ctx) {
720
718
  taskId: askTaskId,
721
719
  sessionId: prepared.spec.sessionId,
722
720
  ...approvalLegOriginOf(prepared.execution),
723
- ...(streamApprovalOn ? { legKey: "", ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}) } : {}),
721
+ legKey: "",
722
+ ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}),
724
723
  });
725
724
  }
726
725
  const withApproval = () => approvalCtx && deps.toolApproval ? deps.toolApproval.runWithContext(approvalCtx, withQuestion) : withQuestion();
@@ -748,7 +747,6 @@ export async function handleTasks(req, res, match, ctx) {
748
747
  await releaseKeyIfZeroWorkRefusal(deps.runStore, durableTaskId, finalResult);
749
748
  }
750
749
  else {
751
- await putRewindAnchor();
752
750
  const pending = await deps.checkpointStore?.findPendingTokenBySession(prepared.spec.sessionId, undefined, { axis: "run" });
753
751
  const dcCause = ac.cause();
754
752
  if (pending) {
@@ -939,7 +937,7 @@ export async function handleTasks(req, res, match, ctx) {
939
937
  catch (e) {
940
938
  return faultedAnswerOf(e, SUBMISSION_CLAIM_FACE.faulted);
941
939
  }
942
- commitSessionInheritEnv(deps, prepared.spec.sessionId, prepared.body);
940
+ commitLegBindings(deps, prepared.seat, prepared.spec.sessionId, prepared.legFacts?.sessionBindings);
943
941
  const syncCancelCtrl = createRunAbort(principal ?? null);
944
942
  markChildrenStoppedByUserOnAbort(syncCancelCtrl.signal, durableTaskId ?? prepared.spec.sessionId, prepared.auth?.subject);
945
943
  if (durableTaskId && deps.runStore) {
@@ -975,15 +973,22 @@ export async function handleTasks(req, res, match, ctx) {
975
973
  counters.uncountedBillableInflight++;
976
974
  try {
977
975
  const heldDecisions = await heldWorkflowParkDecisions(deps, prepared.spec.sessionId);
978
- const compositionInternals = { ...heldDecisions, ...compositionLegRoot(prepared.legFacts?.registeredCwd) };
976
+ const compositionInternals = { ...heldDecisions, ...compositionLegRoot(prepared.legFacts?.sessionBindings.cwd) };
979
977
  const verifyLeg = (v) => runWithVerification(prepared.runner, specWithSignal, v, compositionInternals);
980
978
  const cascadeLeg = () => runCascade(prepared.runner, specWithSignal, cascadeConfig(deps.config.cascadeLadder, prepared.spec.limits?.maxCostUsd), compositionInternals);
981
979
  const plainLeg = async () => {
982
980
  const stream = prepared.runner.runTaskStream(specWithSignal, undefined, heldDecisions);
983
981
  const syncWorkspace = createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), prepared.legFacts?.sessionWitness);
984
- const anchorKey = durableTaskId;
985
- const anchorStore = deps.resumeAnchorStore;
986
- const anchor = new TurnAnchorCapture(undefined, "sync", anchorStore && anchorKey ? async (entryId) => { await anchorStore.put(prepared.spec.sessionId, anchorKey, entryId, principal ?? null); } : undefined);
982
+ const anchorWriter = createRunAnchorWriter({
983
+ seat: deps.backend?.landedAttendants(),
984
+ sessionId: prepared.spec.sessionId,
985
+ owner: principal ?? null,
986
+ promptKey: durableTaskId,
987
+ witness: prepared.legFacts?.sessionWitness,
988
+ occupantOf: sessionOccupantReadOf(deps.sessionStorage),
989
+ leafOf: undefined,
990
+ });
991
+ const anchor = new TurnAnchorCapture(undefined, "sync", anchorWriter.prompt);
987
992
  for await (const ev of stream) {
988
993
  observeSyncLegEvent(ev);
989
994
  switch (ev.type) {
@@ -1040,18 +1045,18 @@ export async function handleTasks(req, res, match, ctx) {
1040
1045
  const syncPlane = outwardPlane(result.terminal);
1041
1046
  const syncHeld = heldParkOf(result);
1042
1047
  if (syncHeld !== undefined && deps.checkpointStore && deps.runStore && durableTaskId) {
1048
+ await prepared.acceptance.settle(result);
1043
1049
  const parked = await commitParkRow({
1044
1050
  runStore: deps.runStore, taskId: durableTaskId, word: syncHeld.word, result: exitResult, card: { token: syncHeld.token, sessionId: prepared.spec.sessionId }, cards: deps.checkpointStore, leg: "sync",
1045
1051
  legId: heldLegOf(durableLegId, durableTaskId), staleWindowMs: deps.config.runStaleSec * 1000,
1046
1052
  });
1047
- prepared.acceptance.settle(result);
1048
1053
  if (parked.kind === "ended")
1049
1054
  return { status: 200, body: withSyncSubmitKeys(parked.row !== undefined ? syncSubmitBodyOfRow(parked.row) : { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "failed" }) };
1050
1055
  return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: syncHeld.word })) };
1051
1056
  }
1057
+ await prepared.acceptance.settle(result);
1052
1058
  if (durableTaskId && deps.runStore)
1053
1059
  await deps.runStore.setTerminal(durableTaskId, syncPlane.status, exitResult, syncPlane.errorMessage ?? null);
1054
- prepared.acceptance.settle(result);
1055
1060
  finalizeTaskResult(result, principal, prepared.spec.objective);
1056
1061
  noteRunOutcome(result);
1057
1062
  return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult)) };
@@ -9,7 +9,7 @@ import { bindSseLifecycle } from "../sse-lifecycle.js";
9
9
  import { sendJson, sendError, sseHeaders, SSE_MAX_STREAM_MS, SSE_HEARTBEAT_IDLE_MS } from "../send.js";
10
10
  import { filterFingerprint } from "../cursor-fingerprint.js";
11
11
  import { sendUnauthorized } from "../principal-gate.js";
12
- import { admitRunById, enter, entryIsFleet, listVisibleRuns, readVisibleRun, routeListFilter, runListOwnerOf, toolResultRefOwned } from "../owner-access.js";
12
+ import { admitRunById, enter, entryIsFleet, listVisibleRuns, readVisibleRun, routeListFilter, listOwnerOf, toolResultRefOwned } from "../owner-access.js";
13
13
  import { listFilterOf } from "../../owner-faces.js";
14
14
  import { assertNever } from "../route-ctx.js";
15
15
  import * as facts from "../../capability-facts.js";
@@ -166,7 +166,7 @@ async function handleTaskList(res, runStore, query, filter) {
166
166
  const jobId = query.get("jobId") ?? undefined;
167
167
  const source = query.get("source") ?? undefined;
168
168
  const namedOwner = query.get("owner") ?? undefined;
169
- const owner = runListOwnerOf(filter, namedOwner);
169
+ const owner = listOwnerOf(filter, namedOwner);
170
170
  const limit = Math.min(100, Math.max(1, Number(query.get("limit") ?? 50) || 50));
171
171
  const f = filterFingerprint([status, jobId, source, owner]);
172
172
  const cursor = decodeCursor(query.get("cursor"), f);
@@ -192,7 +192,7 @@ export async function handleWorkflowAgentSteer(req, res, match, ctx) {
192
192
  sendError(res, 413, "steer.content_too_large", `content exceeds ${STEER_IN_MAX_REQUEST_CHARS} characters (got ${body.content.length}); note only the first ${STEER_IN_MAX_CHARS} are delivered anyway`);
193
193
  return;
194
194
  }
195
- const trusted = explicitOperatorOk(principal, deps.config);
195
+ const trusted = explicitOperatorOk(principal, deps.config, "operate");
196
196
  const wfVerdict = await judgeWorkflowRun(steerEntry, runs.store, wfRunId);
197
197
  if (wfVerdict === "session_mismatch") {
198
198
  refuse(steerEntry, res, "session_mismatch");
@@ -1,10 +1,11 @@
1
1
  import http from "node:http";
2
2
  import type { MemoryComplianceFaces, MemoryOriginFaces, SessionMemoryStatusFace } from "../memory-operator-faces.js";
3
3
  import type { SideQueryAccounting } from "../budget.js";
4
- import type { SessionPurgeOutcome } from "../session-deletion.js";
4
+ import type { SessionAgeOutExpectation, SessionPurgeOutcome } from "../session-deletion.js";
5
5
  import type { IncomingMessage } from "node:http";
6
6
  import { type Runner, type RunnerDeps, type TaskSpec, type TaskResult, type WorkflowRunStore, type MemoryEntry, type MemoryExportBundle, type MemoryImportReport, type SideQuerySpec, type SideQueryResult, type Brain, type EngineNotice } from "@sema-agent/core";
7
7
  import type { ProjectContext } from "../project-context.js";
8
+ import type { MemorySeed } from "../project-registry.js";
8
9
  import type { TaskRequestBody } from "./wire-types.js";
9
10
  import type { ServiceConfig } from "../config-types.js";
10
11
  import { type SessionMirrorRuling } from "../web-admin-client/facade.js";
@@ -12,7 +13,7 @@ import type { RestartSignal } from "@sema-agent/settings-schema/fleet";
12
13
  import { type AuthorizeInput, type OwnerAwareSessionStore } from "../security.js";
13
14
  import type { PeerDesk, PeerLease } from "../peer-seat.js";
14
15
  import type { ExecutionRoot, ResolvedTaskSpec } from "./execution-context.js";
15
- import type { RunStore, ImageIndex, ImageBake, CheckpointStoreFull, ResumeAnchorStore, ApprovalExemptionStore, ApprovalNonceStore, ServiceSessionPolicyStore, ServiceFileHistoryStore, ToolResultStoreFull, StoreBackend } from "../plugins/store-backend.js";
16
+ import type { RunStore, ImageIndex, ImageBake, CheckpointStoreFull, ApprovalExemptionStore, ApprovalNonceStore, ToolResultStoreFull, StoreBackend } from "../plugins/store-backend.js";
16
17
  import type { RuleConsentLane } from "../rules-consent.js";
17
18
  import { type MemorySyncAnswer, type MemorySyncRequest } from "../memory-sync.js";
18
19
  import type { MemorySyncRunner } from "../memory-sync-client.js";
@@ -58,9 +59,9 @@ export interface RequestAuth {
58
59
  sessionId: string;
59
60
  memoryScope?: string;
60
61
  /** 142-S4:the SHAPE-VALIDATED **且已归一(小写)** 的 `body.projectId`(authorizer 的 core
61
- * `PROJECT_ID_REGEX` 门通过后折小写回传;[ref]/[ref] 宽读严写)。main.ts 拿它查 config.projects 的
62
- * defaultScopes(memory.scopes 种子)。resume 腿(checkpoint 重建 auth)缺席 — 回落持久化的
63
- * body.projectId(原始提交已验形),那条回落腿自己再折一次小写,两腿查同一个键。 */
62
+ * `PROJECT_ID_REGEX` 门通过后折小写回传;[ref]/[ref] 宽读严写)。装配器拿它判 memory.scopes 种子项目(对提交者可见才算,
63
+ * `project-registry.ts`)与这条腿的项目。resume 腿(checkpoint 重建 auth)缺席 — 项目回落持久化的
64
+ * body.projectId(原始提交已验形,那条回落腿自己再折一次小写);种子不回落,读冻结的种子项目。 */
64
65
  resolvedProjectId?: string;
65
66
  /** authorizer 判过的头(`security.ts` `createAuthorizer` 交出;语义见 `AuthContext.head`)⇒ fresh 执行上下文的 `judged`。自建 authorizer 不给 = 解析器不比住客。 */
66
67
  head?: import("@sema-agent/core").SessionHead;
@@ -133,7 +134,9 @@ export interface ServiceCoreDeps {
133
134
  * 装配器在**全部折叠之后**经首跑同一只合并口 `withUnattendedLeg` 重挂那条腿(`default` + 按类作答的 onAsk)。只由续跑腿
134
135
  * 按服务端写的 ctx 位递,绝不从请求体读。
135
136
  * `opts.projectContext`(项目上下文继承):续跑家族把提交腿冻结的那一份(`CheckpointCtx.projectContext`,服务端写)原样递回 —— 装配器在续跑腿上只重放它、不读登记簿;
136
- * 新提交腿不递(装配器自己在头部判)。同样只由续跑腿按服务端写的 ctx 位递,绝不从请求体读。 */
137
+ * 新提交腿不递(装配器自己在头部判)。同样只由续跑腿按服务端写的 ctx 位递,绝不从请求体读。
138
+ * `opts.memorySeed`(登记簿默认读层种子):续跑家族把提交腿冻结的种子(`CheckpointCtx.memorySeed`:种子项目 + 判出它的那一位观者,服务端写)原样递回 —— 装配器在续跑腿上
139
+ * 只认它(以冻结的观者经同一只可见性判读此刻的登记)、不推观者、不按存体的 `projectId` 现查;新提交腿不递(装配器自己在头部判)。只由续跑腿按服务端写的 ctx 位递,绝不从请求体读。 */
137
140
  /** `opts.execution`(必填):这条腿的执行上下文(`http/execution-context.ts`;只 `fresh` / `continuation` 两形,`root` 恒在)。装配器要用这条腿的根会话
138
141
  * (场景设施的分区键、受理见证)读 `opts.execution.root` —— 它与 server 随后盖进 spec 的根是同一个值,装配器自己不写根。 */
139
142
  /** `opts.lease`(必填):这条腿的**宿主租约** —— 装配在它之下登记本腿交给引擎的对端声明(`peerDesk.declare(草稿, opts.lease)`)。
@@ -145,6 +148,7 @@ export interface ServiceCoreDeps {
145
148
  onNotice?: (notice: EngineNotice) => void;
146
149
  unattendedLeg?: true;
147
150
  projectContext?: ProjectContext;
151
+ memorySeed?: MemorySeed | null;
148
152
  lease: PeerLease;
149
153
  execution: ExecutionRoot;
150
154
  }) => ResolvedTaskSpec | Promise<ResolvedTaskSpec>;
@@ -165,11 +169,12 @@ export interface ServiceCoreDeps {
165
169
  * `GET /v1/sessions/:id/mcp` 与 `…/a2a` 两张会话面板 —— 的场景名都由它给,**点名与缺席都问**:点名 ⇒ 判在册 / allowlist,
166
170
  * 拒体(400 `scenario_unknown` 附在册词表 / 400 `scenario_not_allowed` 附 allowlist)与任务提交腿逐字同;缺席 ⇒ 指派链(中心 ruling 胜者,
167
171
  * 否则部署缺省),与这位主体 run 时同一读法(指派悬空 ⇒ 503 `state.scenario_assignment_unknown`,同提交腿)。中心配了却答不出这位主体的裁定 ⇒
168
- * 点名与缺席同答 503 `state.scenario_assignment_unavailable`(同提交腿)。
172
+ * 点名与缺席同答 503 `state.scenario_assignment_unavailable`(同提交腿)。门的答是 `{ scenario, source }`(`ScenarioChoice`):上面三张面只取名字,
173
+ * `GET /v1/capabilities/scenario` 把整只答原样交给客户端(这次请求会生效哪只场景、它从哪一层来)—— 名字与来层只有门这一处铸。
169
174
  * 读面上这只门走**只读腿**(`createScenarioGate(…, "peek")`):问中心裁定时 center 抖动的那一拍,不替这个主体的真提交留下 fail-closed 降级项
170
175
  * (提交腿自己是 `"enforce"`)。
171
176
  * 🔴 **必填**:读口的场景名只有这一个来源,没有「缺接缝 ⇒ 读部署缺省 / 点名 404」这类第二种读法 —— 漏接是**编译错**(嵌入方自己装配时,工厂与它的型从包根导出:
172
- * `createScenarioGate` / `ScenarioGate` / `ScenarioGateLeg` / `ScenarioGateSources`)。
177
+ * `createScenarioGate` / `ScenarioGate` / `ScenarioGateLeg` / `ScenarioGateSources` / `ScenarioChoice` / `ScenarioSource`)。
173
178
  */
174
179
  scenarioGate: import("../capabilities/scenarios.js").ScenarioGate;
175
180
  /**
@@ -196,9 +201,6 @@ export interface ServiceCoreDeps {
196
201
  export interface ServiceStoreDeps {
197
202
  /** Durable async-run registry + event log (S1/S2). Enables /v1/runs when present. */
198
203
  runStore?: RunStore;
199
- /** E18 resume-at: the eventId→entryId anchor map (tidb/pg/local). Present whenever a backend is — resolveSpec
200
- * resolves body.resumeAt(eventId)→entryId, the run lifecycle captures per-turn anchors, E21 purges them. */
201
- resumeAnchorStore?: ResumeAnchorStore;
202
204
  /** Per-session approval exemption store — enables decide body `remember:"session"` + the
203
205
  * exemptions list/revoke surfaces on /v1/approvals. The ask-gate probe is wired separately (main.ts). */
204
206
  approvalExemptionStore?: ApprovalExemptionStore;
@@ -215,9 +217,6 @@ export interface ServiceStoreDeps {
215
217
  * 封不了就不落,没有「明文照写」的第二种装配。嵌入方:`checkpointCtxSealing: await ensureCheckpointCtxSealing(sealedKeyDir)`
216
218
  * (保管目录要跨重启持久、多副本各副本是同一份钥匙,否则封它的那把钥匙不在 ⇒ 409 `conflict.checkpoint_ctx_unsealable` `reason:"key_not_held"`)。 */
217
219
  checkpointCtxSealing?: import("./checkpoint-ctx.js").CheckpointCtxSealing;
218
- /** E6 durable SessionPolicyStore (operator-tightened per-session tool rules). Enables PUT/GET /v1/sessions/:id/policy
219
- * when present; core reads the rules at prepare-time (subtract-only) via RunnerDeps.sessionPolicyStore (wired separately). */
220
- sessionPolicyStore?: ServiceSessionPolicyStore;
221
220
  /** [ref] tool-results 读面([ref] 请求,core [ref] `buildToolResultRef` 到货):`GET /v1/tasks/:id/
222
221
  * tool-results/:ref` 的数据源 —— 与 RunnerDeps 侧的 offload 店**同实例**(main.ts 的 `toolResultStore`,
223
222
  * 即「durable 后端在场」那一只;无 backend 部署里 Runner 用的内存兜底 `runnerOffloadStore` **不接**这里)。
@@ -225,14 +224,6 @@ export interface ServiceStoreDeps {
225
224
  * 与 unknown-ref / 归属不符两臂**同形** 404 才是防 oracle 的收口([ref] 的「另定」项按防 oracle 收紧)。
226
225
  * 这是本组「absent ⇒ 501 诚实缺席」通例的**唯一具名例外**,例外理由即上一句。 */
227
226
  toolResultStore?: ToolResultStoreFull;
228
- /** [ref] per-edited-file rewind history store. Present ⇒ the rewind capabilities are advertised; core uses it
229
- * via RunnerDeps.fileHistoryStore (first-touch tracking + per-turn boundaries + tracked-set restore, ANY
230
- * env). Also the 2c history-transfer store (exportHistory/importHistory + blob negotiation faces).
231
- * 🔴 [ref]:这是装配单点 `assembleFileHistory` 的**店**(后端在即在,与 `FILE_HISTORY_CAPTURE` 无关 —— 旋钮只关捕获,
232
- * 落在 core 的 `RunnerDeps.fileHistoryCapture` 上)。rewind 族四位与 2c sync 路由族跟它走;能力词 `fileHistoryCapture`
233
- * = `fileHistoryCaptureOf(本键, config.fileHistoryCapture)`(与 core 捕获位同一只判定)。
234
- * 擦除(E21 / 孤儿 blob GC)不读本键,读 boot 侧的擦除脸。 */
235
- fileHistoryStore?: ServiceFileHistoryStore;
236
227
  /** D-1 通用文件上传(clay 拍 2026-07-27:独立附件 store,不骑 snapshot blob 面):enables
237
228
  * POST/GET/DELETE /v1/attachments*。缺席 ⇒ 501(与其他可选 store 面同姿)。绑定/物化半场在
238
229
  * main.ts(resolveSpec + env factory 包装);本面只管上传/取回/删除三动词 + server 权威上限。 */
@@ -331,7 +322,7 @@ export interface ServiceCoordinatorDeps {
331
322
  question?: QuestionCoordinator;
332
323
  /** [ref]/[ref]②: live tool-approval coordinator (core onAsk → CC three-choice card). Set when
333
324
  * TOOL_APPROVAL_ENABLED. Wired onto the runner's onAsk seam AND consumed here by
334
- * `POST /v1/tool-approvals/:id/respond` + the per-run ALS wrap on the SYNC streaming leg (live-only by design —
325
+ * the ask decision door (`POST /v1/tasks/:taskId/asks/:askId/decision`) + the per-run ALS wrap on the SYNC streaming leg (live-only by design —
335
326
  * every other leg keeps core's fail-closed headless auto-deny, [ref]⑤/[ref]④). */
336
327
  toolApproval?: ToolApprovalCoordinator;
337
328
  /** [ref] 裁 (c) 审计半场:local 车道的 File ask **审计**读面(`GET /v1/approvals` 的 additive 键
@@ -423,11 +414,11 @@ export interface ServiceSeamDeps {
423
414
  */
424
415
  deviceEnrollment?: import("../device-enrollment.js").DeviceEnrollment;
425
416
  /**
426
- * [ref] × 7.106.0 合并复审 X1:host 车道会话登记簿的 `inheritEnv` **写口**(`boot/execution-env.ts` 的 `setSessionInheritEnv`)。
427
- * 唯一调用者 = `http/session-inherit-env.ts` 的 `commitSessionInheritEnv`(四个 run 认领点在认领之后调;判据与残余见那只文件)。
428
- * 缺席 = 本部署不是 host 车道(没有工厂读这一格)⇒ 提交点 no-op。装配 = `boot/stage-10-http-server.ts`(host 车道才给)。
417
+ * 会话登记簿的**绑定写座**(`boot/execution-env.ts` `createSessionScopedRegistries`:cwd / shellEnv / inheritEnv 三格写一笔、按回执撤一笔)。
418
+ * 唯一写者 = `session-bindings.ts` 的 `commitLegBindings`(四个 run 认领点在认领之后调);唯一撤回者 = 提交出口(`submission-exit.ts`,
419
+ * 写了之后才收场 `refused` 的提交)。律与残余见 `session-bindings.ts` 头注。缺席(夹具 / 嵌入方没接)= 没有登记簿 ⇒ 提交点 no-op。
429
420
  */
430
- bindSessionInheritEnv?: import("./session-inherit-env.js").SessionInheritEnvCommitCtx["bindSessionInheritEnv"];
421
+ sessionBindings?: import("../session-bindings.js").SessionBindingSeat;
431
422
  /**
432
423
  * 会话登记簿四表(cwd / shellEnv / inheritEnv / 属主,`boot/execution-env.ts` `createSessionScopedRegistries` 的 `dropSessionOf`)按**住客**清掉一只 ——
433
424
  * 记下的住客恰是交来的化身才清、答 `true`。读者只有提交出口(`submission-exit.ts`):被拒提交铸下的会话撤回之后清(同 id 的下一位已登记、写下的条目不动)。
@@ -442,12 +433,14 @@ export interface ServiceSeamDeps {
442
433
  } & Record<string, unknown>) | undefined>;
443
434
  /** E21 删除协调器(会话三态 活 → 在删 → 没了,`session-deletion.ts`):删会话的对话史与服务自己的 run 账 / 检查点 / 卸载结果等全部挂靠行,一次调用。
444
435
  * 结局 = {@link SessionPurgeOutcome}(删了 / 不在 · 围栏判到认领 · 子代预检拒 · 被接管)。点亮 DELETE /v1/sessions/:id。 */
445
- purgeSession?: (sessionId: string, owner: string | null) => Promise<SessionPurgeOutcome>;
436
+ purgeSession?: (sessionId: string, owner: string | null, opts?: {
437
+ readonly ageOut?: SessionAgeOutExpectation;
438
+ }) => Promise<SessionPurgeOutcome>;
446
439
  /** [ref]③(b): read a BACKGROUND agent-handle child's final report / current status out of the core
447
440
  * TaskRegistry (the same face the TaskOutput tool reads — agent handles are NEVER in the run store).
448
441
  * Wired in main.ts to `defaultTaskRegistry.pollTask` (non-blocking). Access is the REGISTRATION tuple:
449
442
  * owner = the parent run's taskId (resume legs register children under the sessionId — the registry's
450
- * sessionScoped arm matches via `access.sessionId`), scope = the run's principal ?? "default". */
443
+ * sessionScoped arm matches via `access.sessionId`), scope = the run owner's engine-identity cell (`engineScopeOfOwner`). */
451
444
  subagentTaskOutput?: (handle: string, access: {
452
445
  owner: string;
453
446
  scope: string;
@@ -724,7 +717,7 @@ export interface ServiceDeploymentDeps {
724
717
  */
725
718
  deploymentModPackages?: number;
726
719
  /**
727
- * 会话 → 调用方登记的工作目录(提交体 `cwd` 的唯一写口 `setSessionCwd` 写的那一张进程内表,`boot/execution-env.ts` `createSessionScopedRegistries`)。
720
+ * 会话 → 登记的工作目录(受理的提交经绑定写座 {@link ServiceDeps.sessionBindings} 写的那一张进程内表,`boot/execution-env.ts` `createSessionScopedRegistries`)。
728
721
  * **只读**,读者只有 run 外回退口(`POST /v1/sessions/:id/rewind-files`):host 工厂按 `effectiveHostWorkspace(本表.get(会话), ctx)` 定根(`execution-env.ts`
729
722
  * host 臂),口在交引擎之前用**同一只函数、同一份入参**问「工厂这一次会不会落到一只用完即删的临时目录」—— 会 ⇒ 拒,不让台账说恢复了而项目没动。
730
723
  * 缺席(夹具 / 嵌入方没接)⇒ 读作「没有登记」⇒ host 车道上口拒(fail-closed)。
@@ -950,6 +943,13 @@ export declare function createHttpServer(rawDeps: ServiceDeps): http.Server & {
950
943
  redeemParkedAsk: ParkedAskRedeem;
951
944
  /** 会话通知门(装配层把它接进场景层后台完成 sink 的晚绑座;门与律见 `session-notify-door.ts`)。 */
952
945
  sessionNotifyDoor: SessionNotifyDoor;
946
+ /** run 收场送达的转交(装配层把它接进 workflow 编排面完成送达的晚绑座;律见 `resume-legs.ts` 的 `handOverRunEndedDecisions`)。 */
947
+ handOverRunEndedDecisions: (runId: string) => Promise<void>;
948
+ /**
949
+ * 本机控制 socket 那只 `http.Server`(建而不听):与本 server 同一只请求监听器,进门打通道标 `control-socket`(`request-channel.ts`),不挂设备 WS 的 upgrade 监听器。
950
+ * 开口(判 + 听)只经 `control-socket.ts` 的 `openControlSocket`;起服第 10 段在 TCP listen 之后开、收尾链与本 server 一起关。嵌入方不开 ⇒ 面缺席。
951
+ */
952
+ controlSocketServer: http.Server;
953
953
  };
954
954
  /** SSE: replay durable events after Last-Event-ID, then tail until the run is terminal (or stale). */
955
955
  /**
@@ -1,5 +1,6 @@
1
1
  import http from "node:http";
2
2
  import { outwardPlane } from "../terminal.js";
3
+ import { markControlSocketRequest } from "./request-channel.js";
3
4
  import { validatePendingSteer } from "@sema-agent/core";
4
5
  import {} from "../web-admin-client/facade.js";
5
6
  import { describeValueShape } from "@sema-agent/settings-schema";
@@ -28,7 +29,7 @@ import { parkDecisionStoreRefusal } from "../orchestration/workflow-park-decisio
28
29
  import { CHECKPOINT_CTX_SEALING_REQUIRED } from "./checkpoint-ctx.js";
29
30
  import { SERVING_LEASE_MEMBERSHIP_REQUIRED } from "../fleet/engine-signal.js";
30
31
  import { PARKED_REVIVE_EXECUTION_SEAT_REQUIRED } from "../parked-decide.js";
31
- import { a2aAudienceVerifiedSourceRefusal, operatorDeclarationRefusal } from "../config-invariants.js";
32
+ import { a2aAudienceVerifiedSourceRefusal, operatorDeclarationRefusal, operatorRosterWellFormedRefusal } from "../config-invariants.js";
32
33
  import { retiredServiceDepsRefusal } from "./retired-service-deps.js";
33
34
  import { createAdmission, MAX_SKILL_CONTENT_CHARS, MAX_SYSTEM_PROMPT_CHARS, MAX_OUTPUT_SCHEMA_CHARS, validateUserSkills } from "./admission.js";
34
35
  import { createResumeLegs } from "./resume-legs.js";
@@ -94,6 +95,12 @@ export function createHttpServer(rawDeps) {
94
95
  throw new Error(operatorDeclarationFailure);
95
96
  }
96
97
  }
98
+ {
99
+ const rosterFailure = operatorRosterWellFormedRefusal(deps.config);
100
+ if (rosterFailure !== undefined) {
101
+ throw new Error(rosterFailure);
102
+ }
103
+ }
97
104
  {
98
105
  const bridgeDeclared = configuredIdentitySources(deps.config).includes("sso");
99
106
  const verifierWired = deps.webAdminJwtVerifier !== undefined;
@@ -226,10 +233,10 @@ export function createHttpServer(rawDeps) {
226
233
  const { quotaExceeded, ownerCostQuotaDenied, ownerFleetLeaseDenied, ownerLeaseDenied, ownerQuotaDenied, leaseDenied, usageWindowDenialFor, usageWindowDenied, rateLimited, safeDecode, readJson, readRawBody } = createRequestGuards({ deps });
227
234
  const { prepareSpec } = createAdmission({ deps, readJson, runnerFor });
228
235
  const { admitRun } = createRunConcurrencyGate({ deps, inflightRuns, steerableRuns });
229
- const { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, decisionRowAdmits, resumePreempted, startFreshHostTurn, resumeWake, sessionNotifyDoor } = createResumeLegs({ deps, runnerFor, idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters, readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, admitRun, safeDecode, prepareSpec, finalizeTaskResult, ownerCostQuotaDenied, ownerFleetLeaseDenied, usageWindowDenialFor });
236
+ const { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, decisionRowAdmits, resumePreempted, startFreshHostTurn, resumeWake, sessionNotifyDoor, handOverRunEndedDecisions } = createResumeLegs({ deps, runnerFor, idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters, readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, admitRun, safeDecode, prepareSpec, finalizeTaskResult, ownerCostQuotaDenied, ownerFleetLeaseDenied, usageWindowDenialFor });
230
237
  const { denyExpiredApprovals, redeemParkedAsk } = createApprovalSweeps({ deps, resumeCheckpoint, decisionRowAdmits });
231
238
  const { handle } = createDispatch({ deps, noteActivity, routeCtxBase, counters });
232
- const server = http.createServer((req, res) => {
239
+ const onRequest = (req, res) => {
233
240
  attachResponseLogger(res, deps.logger);
234
241
  void handle(req, res).catch((err) => {
235
242
  if (err instanceof HttpError) {
@@ -258,6 +265,11 @@ export function createHttpServer(rawDeps) {
258
265
  }
259
266
  sendOpenFaceFault(res, err);
260
267
  });
268
+ };
269
+ const server = http.createServer(onRequest);
270
+ const controlSocketServer = http.createServer((req, res) => {
271
+ markControlSocketRequest(req);
272
+ onRequest(req, res);
261
273
  });
262
274
  const deviceLane = facts.deviceLane(deps);
263
275
  if (deviceLane.available)
@@ -289,6 +301,6 @@ export function createHttpServer(rawDeps) {
289
301
  deps.planCacheProbe?.record(principal, objective, result.terminal.kind === "completed");
290
302
  }
291
303
  const isRunLiveOnThisReplica = (taskId) => liveRunIdsOf(inflightRuns, steerableRuns).has(taskId);
292
- return Object.assign(server, { denyExpiredApprovals, isRunLiveOnThisReplica, redeemParkedAsk, sessionNotifyDoor });
304
+ return Object.assign(server, { denyExpiredApprovals, isRunLiveOnThisReplica, redeemParkedAsk, sessionNotifyDoor, handOverRunEndedDecisions, controlSocketServer });
293
305
  }
294
306
  //# sourceMappingURL=server.js.map