@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
@@ -27,6 +27,7 @@ import { APPROVAL_EXEMPTED_EVENT } from "./plugins/approval-exemption-store.js";
27
27
  import { refusalBody } from "./http/refusal-body.js";
28
28
  import { withoutSettlementEvidence } from "./gate-settlement.js";
29
29
  import { extensionRequesterOf } from "./trace/extension-call-face.js";
30
+ import { boundedRotation } from "./bounded-rotation.js";
30
31
  const defaultLogger = createLogger();
31
32
  const MAX_APPROVAL_ARGS_BYTES = 16384;
32
33
  const DEFAULT_APPROVAL_TTL_MS = 5 * 60_000;
@@ -69,7 +70,7 @@ function durableRuleMaterial(material) {
69
70
  }
70
71
  export const NOT_PENDING_UNKNOWN_CAUSE = "unknown_or_other_replica";
71
72
  export const TOOL_APPROVAL_READ_STATES = ["pending", "decided", "parked", "void"];
72
- function decidedRowFacts(row) {
73
+ export function decidedRowFacts(row) {
73
74
  if (row.state !== "DECIDED" || (row.decision !== "approve" && row.decision !== "deny") || row.provisional || row.decidedAtMs === null)
74
75
  return undefined;
75
76
  return { decision: row.decision === "approve" ? "allow" : "deny", decidedAtMs: row.decidedAtMs, ...(row.decisionNote !== null ? { decisionNote: row.decisionNote } : {}) };
@@ -85,6 +86,22 @@ function buildAskRowReadProjection(row, nowMs) {
85
86
  };
86
87
  }
87
88
  export const ASK_DECISION_CONSUMER_ABSENT = "absent";
89
+ function standingParkedDecision(gate, row, idempotencyKey) {
90
+ if (gate?.kind !== "decided")
91
+ return undefined;
92
+ const decision = gate.decision === "allow" ? "approve" : "deny";
93
+ if (row.decision === decision && row.decidedAtMs !== null && row.decidedAtMs >= gate.decidedAtMs) {
94
+ return {
95
+ kind: "standing",
96
+ decision,
97
+ decidedAtMs: row.decidedAtMs,
98
+ ...(row.decisionNote !== null ? { decisionNote: row.decisionNote } : {}),
99
+ ...(row.decisionActor !== null ? { actor: row.decisionActor } : {}),
100
+ byThisRequest: idempotencyKey !== undefined && row.idempotencyKey === idempotencyKey,
101
+ };
102
+ }
103
+ return { kind: "standing", decision, decidedAtMs: gate.decidedAtMs, ...(gate.decisionNote !== undefined ? { decisionNote: gate.decisionNote } : {}), byThisRequest: false };
104
+ }
88
105
  const MAX_INFLIGHT_TERMINAL_CLAIMS = 2;
89
106
  const DURABLE_CONVERGE_BACKOFF_MS = [50, 100, 200, 400, 800, 1600];
90
107
  export const DURABLE_CONVERGE_READ_TIMEOUT_MS = 2_000;
@@ -115,10 +132,28 @@ const FS_WRITE_TOOLS = pathConfinableWriteToolNames();
115
132
  function sessionAllowCategory(toolName) {
116
133
  return FS_WRITE_TOOLS.has(toolName) ? "fs-write" : `tool:${toolName}`;
117
134
  }
118
- function sessionAllowKey(owner, sessionId, incarnation, category, binding) {
119
- if (!sessionId || !incarnation)
120
- return undefined;
121
- return JSON.stringify([owner, sessionId, incarnation, category, binding.kind === "bound" ? binding.digest : null]);
135
+ function sessionAllowKey(owner, seat, category, binding) {
136
+ return JSON.stringify([owner, seat.sessionId, seat.incarnation, category, binding.kind === "bound" ? binding.digest : null]);
137
+ }
138
+ function sessionAllowSeatOf(leg) {
139
+ return leg.sessionId && leg.incarnation ? { sessionId: leg.sessionId, incarnation: leg.incarnation } : undefined;
140
+ }
141
+ function liveSessionAnswer(facts, leg) {
142
+ const home = standingAnswerHome(facts);
143
+ switch (home) {
144
+ case "none":
145
+ return { home: "none", occupantUnreadable: false };
146
+ case "seat": {
147
+ const seat = sessionAllowSeatOf(leg);
148
+ return seat !== undefined ? { home: "seat", seat } : { home: "none", occupantUnreadable: Boolean(leg.sessionId) };
149
+ }
150
+ case "server_store":
151
+ return leg.sessionId ? { home: "server_store", sessionId: leg.sessionId } : { home: "none", occupantUnreadable: false };
152
+ default: {
153
+ const unhandled = home;
154
+ throw new Error(`unhandled standing-answer home: ${String(unhandled)}`);
155
+ }
156
+ }
122
157
  }
123
158
  function askStandingAnswerFacts(req, governanceForced, deploymentListAsks) {
124
159
  const classes = screenAskClassMembers(req.askClass, req.classes)?.classes;
@@ -196,8 +231,8 @@ function pendingEntryStandingAnswerFacts(entry) {
196
231
  deploymentListQuestion: entry.deploymentListQuestion === true,
197
232
  };
198
233
  }
199
- function projectDecisionFacts(facts, frame, card) {
200
- const rememberRefused = standingAnswerHome(facts) === "none";
234
+ function projectDecisionFacts(facts, leg, frame, card) {
235
+ const rememberRefused = liveSessionAnswer(facts, leg).home === "none";
201
236
  if (frame !== undefined) {
202
237
  if (facts.requiresRealApproval)
203
238
  frame.requiresRealApproval = true;
@@ -256,7 +291,7 @@ function livePendingRowOf(e) {
256
291
  ...(e.requiresRealApproval ? { requiresRealApproval: true } : {}),
257
292
  ...(e.governanceForced ? { governanceForced: true } : {}),
258
293
  ...(listFrame.mandated === true ? { mandated: true } : {}),
259
- ...(standingAnswerHome(pendingEntryStandingAnswerFacts(e)) === "none" ? { rememberRefused: true } : {}),
294
+ ...(liveSessionAnswer(pendingEntryStandingAnswerFacts(e), e).home === "none" ? { rememberRefused: true } : {}),
260
295
  ...(listFrame.mandate !== undefined ? { mandate: listFrame.mandate } : {}),
261
296
  ...(listFrame.origin !== undefined ? { origin: listFrame.origin } : {}),
262
297
  ...(listFrame.type === "approval_request" && listFrame.liveFactsUnknown === true ? { liveFactsUnknown: true } : {}),
@@ -360,6 +395,18 @@ function parseToolApprovalFields(body, retired) {
360
395
  }
361
396
  return { ok: false, error: 'decision must be one of "allow" | "allow_session" | "deny"' };
362
397
  }
398
+ export function askDecisionRecordOf(write) {
399
+ return {
400
+ decision: write.decision,
401
+ ...(write.actor !== undefined ? { decisionActor: write.actor } : {}),
402
+ decisionNote: write.note ?? null,
403
+ idempotencyKey: write.idempotencyKey ?? null,
404
+ ...liveHostSource(write.decider),
405
+ };
406
+ }
407
+ function liveDecideInputOf(write) {
408
+ return { ...askDecisionRecordOf(write), ...(write.decision === "approve" && write.updatedInput !== undefined ? { updatedInput: write.updatedInput } : {}) };
409
+ }
363
410
  export function buildUnattendedPolicyRefusal(reason) {
364
411
  return { allow: false, settledBy: POLICY_REFUSAL_DECISION.settledBy, reason };
365
412
  }
@@ -544,8 +591,8 @@ export class ToolApprovalCoordinator {
544
591
  admitMaxPerOwner;
545
592
  admitByTask = new Map();
546
593
  admitByOwner = new Map();
547
- suspendedPollOffset = 0;
548
- adoptedPollOffset = 0;
594
+ suspendedPollCursor = { offset: 0 };
595
+ adoptedPollCursor = { offset: 0 };
549
596
  editedDecisionsInFlight = new Map();
550
597
  storeErrorWarned = false;
551
598
  storeErrorTally = 0;
@@ -959,8 +1006,8 @@ export class ToolApprovalCoordinator {
959
1006
  const sessionId = origin.sessionId;
960
1007
  if (!sessionId)
961
1008
  return false;
962
- const liveKey = sessionAllowKey(origin.owner, sessionId, origin.incarnation, sessionAllowCategory(req.toolName), facts.grantBinding);
963
- const live = liveKey !== undefined && this.allowAllSessions.has(liveKey);
1009
+ const seat = sessionAllowSeatOf(origin);
1010
+ const live = seat !== undefined && this.allowAllSessions.has(sessionAllowKey(origin.owner, seat, sessionAllowCategory(req.toolName), facts.grantBinding));
964
1011
  const durable = !live && facts.grantBinding.kind === "none" && (await this.durableGrantHas(sessionId, req.toolName));
965
1012
  if (!live && !durable)
966
1013
  return false;
@@ -1330,7 +1377,7 @@ export class ToolApprovalCoordinator {
1330
1377
  ...(askReasonsOfReq !== undefined ? { askReasons: askReasonsOfReq } : {}),
1331
1378
  ...(governanceForced ? { governanceForced: true } : {}),
1332
1379
  ...(req.mandated === true ? { mandated: true } : {}),
1333
- ...(standingAnswerHome(askStandingAnswerFacts(req, governanceForced, deploymentListAsks)) === "none" ? { rememberRefused: true } : {}),
1380
+ ...(liveSessionAnswer(askStandingAnswerFacts(req, governanceForced, deploymentListAsks), origin).home === "none" ? { rememberRefused: true } : {}),
1334
1381
  ...(typeof req.boundGrantDigest === "string" ? { boundGrantDigest: req.boundGrantDigest, ...(req.boundGrants !== undefined ? { boundGrants: req.boundGrants } : {}) } : {}),
1335
1382
  ...(noRulingCause !== undefined ? { classifierNoRuling: noRulingCause } : {}),
1336
1383
  ...(grantAbsence !== undefined ? { boundGrantAbsence: grantAbsence } : {}),
@@ -1897,7 +1944,7 @@ export class ToolApprovalCoordinator {
1897
1944
  grantBinding: entryGrantBinding,
1898
1945
  classes: entryClasses,
1899
1946
  ...(entryDeploymentListQuestion ? { deploymentListQuestion: true } : {}),
1900
- }), frame, cardForFrame);
1947
+ }), origin, frame, cardForFrame);
1901
1948
  const cardFrame = askId !== undefined && cardForFrame !== undefined
1902
1949
  ? buildApprovalRequestFrame({ askId, taskId: origin.taskId, approvalId: wireApprovalId, card: cardForFrame, expiresAtMs: persistedExpiresAtMs, nowMs: Date.now(), live: frame })
1903
1950
  : undefined;
@@ -1944,7 +1991,7 @@ export class ToolApprovalCoordinator {
1944
1991
  if (s.requiresRealApproval === true)
1945
1992
  continue;
1946
1993
  s.requiresRealApproval = true;
1947
- const card = projectDecisionFacts(pendingEntryStandingAnswerFacts(s), s.frame, s.cardFrame?.card);
1994
+ const card = projectDecisionFacts(pendingEntryStandingAnswerFacts(s), s, s.frame, s.cardFrame?.card);
1948
1995
  if (s.cardFrame !== undefined && card !== undefined && card !== s.cardFrame.card)
1949
1996
  s.cardFrame = { ...s.cardFrame, card };
1950
1997
  }
@@ -2097,11 +2144,10 @@ export class ToolApprovalCoordinator {
2097
2144
  }
2098
2145
  recordDeploymentListAnswer(decided, entry, judgedOwner, parsed, principal, eligibility) {
2099
2146
  const store = this.sessionGrants;
2100
- const sessionId = entry.sessionId;
2101
- if (parsed.value !== "allow_session" || !sessionId || store === undefined)
2102
- return decided;
2103
- if (standingAnswerHome(pendingEntryStandingAnswerFacts(entry)) !== "server_store")
2147
+ const answer = liveSessionAnswer(pendingEntryStandingAnswerFacts(entry), entry);
2148
+ if (parsed.value !== "allow_session" || answer.home !== "server_store" || store === undefined)
2104
2149
  return decided;
2150
+ const sessionId = answer.sessionId;
2105
2151
  return (async () => {
2106
2152
  const result = await decided;
2107
2153
  if (result.status !== 200)
@@ -2443,21 +2489,50 @@ export class ToolApprovalCoordinator {
2443
2489
  const openGenerationNow = this.lookupParkRedemption(row.askId) !== undefined ? await this.openGateGeneration(row) : undefined;
2444
2490
  const prior = this.lookupParkRedemption(row.askId);
2445
2491
  if (prior?.redeemed !== undefined && receiptAnswersNow(prior.redeemed.gateGeneration, openGenerationNow))
2446
- return this.replayRedeemReceipt(id, prior, row, prior.redeemed, parsed);
2492
+ return this.replayRedeemReceipt(id, prior, row, prior.redeemed, parsed, row);
2447
2493
  if (prior?.inflight !== undefined) {
2448
2494
  const shared = await prior.inflight;
2449
2495
  if (shared.status < 200 || shared.status >= 300)
2450
2496
  return shared;
2451
2497
  if (!receiptAnswersNow(shared.gateGeneration, openGenerationNow))
2452
2498
  return this.redeemParkedAsk(id, row, parsed, httpReq, principal);
2453
- return this.replayRedeemReceipt(id, prior, row, { decision: shared.decision, body: shared.body, gateGeneration: shared.gateGeneration, ...(shared.rule?.terminal === true ? { rule: shared.rule.body } : {}) }, parsed);
2499
+ return this.replayRedeemReceipt(id, prior, row, { decision: shared.decision, body: shared.body, gateGeneration: shared.gateGeneration, ...(shared.rule?.terminal === true ? { rule: shared.rule.body } : {}) }, parsed, shared.recorded ?? { decisionNote: null });
2454
2500
  }
2501
+ const store = this.askStore;
2502
+ if (store === undefined)
2503
+ return this.notPending();
2504
+ const request = {
2505
+ write: { decision: parsed.value === "deny" ? "deny" : "approve", decider: parsed.decider, ...(parsed.note !== undefined ? { note: parsed.note } : {}) },
2506
+ ...(parsed.value === "allow_session" ? { remember: "session" } : {}),
2507
+ ...(parsed.persistRule !== undefined ? { persistRule: parsed.persistRule } : {}),
2508
+ ...(parsed.updatedInput !== undefined && parsed.value !== "deny" ? { updatedInput: parsed.updatedInput } : {}),
2509
+ ...(principal !== undefined ? { principal } : {}),
2510
+ operator: false,
2511
+ ...(httpReq !== undefined ? { httpReq } : {}),
2512
+ };
2513
+ const out = await this.runParkedFlight(redeem, store, row, row.gateToken, request);
2514
+ if (out.status < 200 || out.status >= 300)
2515
+ return { status: out.status, body: out.body };
2516
+ const rule = out.rule;
2517
+ return {
2518
+ status: out.status,
2519
+ body: {
2520
+ ...out.body,
2521
+ approvalId: id,
2522
+ askId: row.askId,
2523
+ accepted: "parked_redeemed",
2524
+ ...(parsed.value === "allow_session" ? { rememberApplied: out.rememberApplied === true } : {}),
2525
+ ...noteRecordedReceipt(parsed.note, noteLandedOnRow(parsed.note, out.recorded?.decisionNote ?? null)),
2526
+ ...(rule?.body ?? {}),
2527
+ },
2528
+ };
2529
+ }
2530
+ async runParkedFlight(redeem, store, row, gateToken, request) {
2531
+ const decision = request.write.decision;
2455
2532
  const admission = this.parkRedemptionAdmission(row.owner);
2456
2533
  if (admission !== undefined)
2457
- return admission;
2534
+ return { ...admission, body: admission.body, decision };
2458
2535
  const memo = this.openParkRedemption(row.askId, row.owner);
2459
- const decision = parsed.value === "deny" ? "deny" : "approve";
2460
- const gateToken = row.gateToken;
2461
2536
  const flight = (async () => {
2462
2537
  let res;
2463
2538
  try {
@@ -2467,12 +2542,13 @@ export class ToolApprovalCoordinator {
2467
2542
  gateBoundCallId: row.gateBoundCallId,
2468
2543
  gateBoundInputHash: row.gateBoundInputHash,
2469
2544
  decision,
2470
- ...(parsed.note !== undefined ? { note: parsed.note } : {}),
2471
- decider: parsed.decider,
2472
- ...(parsed.updatedInput !== undefined && parsed.value !== "deny" ? { updatedInput: parsed.updatedInput } : {}),
2473
- ...(parsed.value === "allow_session" ? { remember: "session" } : {}),
2474
- ...(principal !== undefined ? { principal } : {}),
2475
- ...(httpReq !== undefined ? { httpReq } : {}),
2545
+ ...(request.write.note !== undefined ? { note: request.write.note } : {}),
2546
+ decider: request.write.decider,
2547
+ ...(request.updatedInput !== undefined && decision === "approve" ? { updatedInput: request.updatedInput } : {}),
2548
+ ...(request.remember !== undefined ? { remember: request.remember } : {}),
2549
+ ...(request.principal !== undefined ? { principal: request.principal } : {}),
2550
+ operator: request.operator,
2551
+ ...(request.httpReq !== undefined ? { httpReq: request.httpReq } : {}),
2476
2552
  });
2477
2553
  }
2478
2554
  catch (err) {
@@ -2481,8 +2557,9 @@ export class ToolApprovalCoordinator {
2481
2557
  }
2482
2558
  if (res.status < 200 || res.status >= 300)
2483
2559
  return { ...res, decision };
2484
- const rule = await this.persistRuleFromRow(row, parsed);
2485
- return { ...res, decision, ...(rule !== undefined ? { rule } : {}) };
2560
+ const recorded = await this.recordParkedOutcome(store, row, request.write);
2561
+ const rule = await this.persistRuleFromRow(row, request.persistRule, request.updatedInput !== undefined);
2562
+ return { ...res, decision, ...(recorded !== undefined ? { recorded } : {}), ...(rule !== undefined ? { rule } : {}) };
2486
2563
  })();
2487
2564
  memo.inflight = flight;
2488
2565
  let out;
@@ -2495,25 +2572,57 @@ export class ToolApprovalCoordinator {
2495
2572
  if (out.status < 200 || out.status >= 300) {
2496
2573
  if (this.parkRedemptions.get(row.askId) === memo)
2497
2574
  this.parkRedemptions.delete(row.askId);
2498
- return { status: out.status, body: out.body };
2575
+ return out;
2499
2576
  }
2500
- const rule = out.rule;
2501
2577
  if (this.retainParkRedemption(row.askId, memo))
2502
- memo.redeemed = { decision, body: out.body, gateGeneration: out.gateGeneration, ...(rule?.terminal === true ? { rule: rule.body } : {}) };
2503
- return {
2504
- status: out.status,
2505
- body: {
2506
- ...out.body,
2507
- approvalId: id,
2508
- askId: row.askId,
2509
- accepted: "parked_redeemed",
2510
- ...(parsed.value === "allow_session" ? { rememberApplied: out.rememberApplied === true } : {}),
2511
- ...(rule?.body ?? {}),
2512
- },
2513
- };
2578
+ memo.redeemed = { decision, body: out.body, gateGeneration: out.gateGeneration, ...(out.rule?.terminal === true ? { rule: out.rule.body } : {}) };
2579
+ return out;
2514
2580
  }
2515
- async persistRuleFromRow(row, parsed) {
2516
- const persistRule = parsed.persistRule;
2581
+ async recordParkedOutcome(store, row, write) {
2582
+ try {
2583
+ const out = await this.writeAskDecision(store, row.askId, { kind: "parked" }, row.owner, write);
2584
+ if (out.ok)
2585
+ return out.row;
2586
+ recordFailOpen("server.approval.parked-decision-not-recorded", `askId=${row.askId} reason=${out.reason}`);
2587
+ return undefined;
2588
+ }
2589
+ catch (err) {
2590
+ this.noteStoreError(err, "recordParkedDecision");
2591
+ recordFailOpen("server.approval.parked-decision-not-recorded", `askId=${row.askId} reason=store_error`);
2592
+ return undefined;
2593
+ }
2594
+ }
2595
+ async decideParkedAsk(store, row, request, idempotencyKey) {
2596
+ for (;;) {
2597
+ const gate = await this.readParkedGate(row);
2598
+ const current = await this.askRowFor(store, row.askId, "getAsk(parked-decision)");
2599
+ if (current === null || current.state !== "PARKED" || !askRowCarriesOwner(current, row.owner))
2600
+ return { kind: "gone" };
2601
+ const inflight = this.lookupParkRedemption(row.askId)?.inflight;
2602
+ if (inflight !== undefined) {
2603
+ await inflight;
2604
+ continue;
2605
+ }
2606
+ const standing = standingParkedDecision(gate, current, idempotencyKey);
2607
+ if (standing !== undefined)
2608
+ return standing;
2609
+ if (request.write.decision === "approve" && request.policyMayNotApprove === true)
2610
+ return { kind: "policy_refused" };
2611
+ const redeem = this.parkedRedeem?.();
2612
+ if (redeem === undefined || row.gateToken === null) {
2613
+ if (row.gateToken === null)
2614
+ defaultLogger.error("tool approval parked row carries no gate token — nothing to redeem", { askId: row.askId });
2615
+ return { kind: "gate_only" };
2616
+ }
2617
+ const out = await this.runParkedFlight(redeem, store, current, row.gateToken, request);
2618
+ if (out.status === 200)
2619
+ return { kind: "accepted", body: out.body, ...(out.recorded !== undefined ? { recorded: out.recorded } : {}) };
2620
+ if ((await this.readParkedGate(row))?.kind === "decided")
2621
+ continue;
2622
+ return { kind: "refused", status: out.status, body: out.body };
2623
+ }
2624
+ }
2625
+ async persistRuleFromRow(row, persistRule, inputWasEdited) {
2517
2626
  if (persistRule === undefined)
2518
2627
  return undefined;
2519
2628
  const flag = (rulePersisted, ruleRefusal, echo) => ({
@@ -2533,7 +2642,7 @@ export class ToolApprovalCoordinator {
2533
2642
  const command = row.ruleCommand;
2534
2643
  if (command === null)
2535
2644
  return flag(false, "rule_material_absent");
2536
- if (parsed.updatedInput !== undefined)
2645
+ if (inputWasEdited)
2537
2646
  return flag(false, "rule_input_edited");
2538
2647
  const offers = card.ruleOffers ?? [];
2539
2648
  const scope = row.ruleScopeRoot !== null ? { kind: "project", root: row.ruleScopeRoot } : undefined;
@@ -2590,10 +2699,10 @@ export class ToolApprovalCoordinator {
2590
2699
  return { ...flag(false, "rule_store_error"), terminal: false };
2591
2700
  }
2592
2701
  }
2593
- async replayRedeemReceipt(id, memo, row, receipt, parsed) {
2702
+ async replayRedeemReceipt(id, memo, row, receipt, parsed, recordedNote) {
2594
2703
  let rule = receipt.decision === "approve" ? receipt.rule : this.lateRuleRefusal(parsed);
2595
2704
  if (receipt.decision === "approve" && rule === undefined && parsed.persistRule !== undefined) {
2596
- const flight = memo.ruleInflight ?? this.persistRuleFromRow(row, parsed);
2705
+ const flight = memo.ruleInflight ?? this.persistRuleFromRow(row, parsed.persistRule, parsed.updatedInput !== undefined);
2597
2706
  const isOwner = memo.ruleInflight === undefined;
2598
2707
  if (isOwner)
2599
2708
  memo.ruleInflight = flight;
@@ -2619,6 +2728,7 @@ export class ToolApprovalCoordinator {
2619
2728
  accepted: "parked_redeemed",
2620
2729
  idempotent: true,
2621
2730
  decision: receipt.decision === "approve" ? "allow" : "deny",
2731
+ ...noteRecordedReceipt(parsed.note, noteLandedOnRow(parsed.note, recordedNote.decisionNote)),
2622
2732
  ...(rule ?? {}),
2623
2733
  },
2624
2734
  };
@@ -2702,19 +2812,36 @@ export class ToolApprovalCoordinator {
2702
2812
  return withFlag(false, "rule_store_error");
2703
2813
  }
2704
2814
  }
2815
+ writeAskDecision(store, askId, form, owner, write) {
2816
+ switch (form.kind) {
2817
+ case "live":
2818
+ return this.withStoreDeadline(store.decideAsk(askId, form.batchId, owner, liveDecideInputOf(write)), "decideAsk", DURABLE_CALL_TIMEOUT_MS, (late) => {
2819
+ if (!late.ok)
2820
+ return;
2821
+ if (decidedRowFacts(late.row) === undefined) {
2822
+ defaultLogger.error("ask decision landed after its deadline on a row that is not an authoritative human decision — not settled", { askId, state: late.row.state, provisional: late.row.provisional });
2823
+ return;
2824
+ }
2825
+ this.notifyExternalDecision(askId, outcomeOfDecidedRow(late.row));
2826
+ });
2827
+ case "parked":
2828
+ return this.withStoreDeadline(store.recordParkedDecision(askId, owner, askDecisionRecordOf(write)), "recordParkedDecision", DURABLE_CALL_TIMEOUT_MS);
2829
+ default: {
2830
+ const unhandled = form;
2831
+ throw new Error(`writeAskDecision: unhandled form ${JSON.stringify(unhandled)}`);
2832
+ }
2833
+ }
2834
+ }
2705
2835
  async respondWithCas(askStore, askId, batchId, owner, entry, parsed, ruleEligibility) {
2706
2836
  let winnerRow;
2707
2837
  let ambiguousConfirmedRow;
2708
2838
  let noteLanded = false;
2709
2839
  try {
2710
- const decided = await this.withStoreDeadline(askStore.decideAsk(askId, batchId, owner, {
2840
+ const decided = await this.writeAskDecision(askStore, askId, { kind: "live", batchId }, owner, {
2711
2841
  decision: parsed.value === "deny" ? "deny" : "approve",
2712
- ...(parsed.note !== undefined ? { decisionNote: parsed.note } : {}),
2713
- ...(parsed.value !== "deny" && parsed.updatedInput !== undefined ? { updatedInput: parsed.updatedInput } : {}),
2714
- ...liveHostSource(parsed.decider),
2715
- }), "decideAsk", DURABLE_CALL_TIMEOUT_MS, (late) => {
2716
- if (late.ok)
2717
- this.notifyExternalDecision(askId, outcomeOfDecidedRow(late.row));
2842
+ decider: parsed.decider,
2843
+ ...(parsed.note !== undefined ? { note: parsed.note } : {}),
2844
+ ...(parsed.updatedInput !== undefined ? { updatedInput: parsed.updatedInput } : {}),
2718
2845
  });
2719
2846
  if (decided.ok) {
2720
2847
  winnerRow = decided.row;
@@ -2781,25 +2908,11 @@ export class ToolApprovalCoordinator {
2781
2908
  }
2782
2909
  finishRespond(entry, judgedOwner, parsed, opts) {
2783
2910
  let rememberApplied;
2784
- const home = standingAnswerHome(pendingEntryStandingAnswerFacts(entry));
2785
- let grantable;
2786
- switch (home) {
2787
- case "seat":
2788
- grantable = true;
2789
- break;
2790
- case "none":
2791
- case "server_store":
2792
- grantable = false;
2793
- break;
2794
- default: {
2795
- const unhandled = home;
2796
- throw new Error(`unhandled standing-answer home: ${String(unhandled)}`);
2797
- }
2798
- }
2799
2911
  if (parsed.value === "allow_session") {
2800
- const grantKey = grantable ? sessionAllowKey(judgedOwner, entry.sessionId, entry.incarnation, sessionAllowCategory(entry.toolName), entry.grantBinding) : undefined;
2801
- rememberApplied = grantKey !== undefined;
2802
- if (grantKey !== undefined) {
2912
+ const answer = liveSessionAnswer(pendingEntryStandingAnswerFacts(entry), entry);
2913
+ rememberApplied = answer.home === "seat";
2914
+ if (answer.home === "seat") {
2915
+ const grantKey = sessionAllowKey(judgedOwner, answer.seat, sessionAllowCategory(entry.toolName), entry.grantBinding);
2803
2916
  if (this.allowAllSessions.size >= MAX_ALLOW_SESSIONS) {
2804
2917
  const oldest = this.allowAllSessions.values().next().value;
2805
2918
  if (oldest !== undefined)
@@ -2807,7 +2920,7 @@ export class ToolApprovalCoordinator {
2807
2920
  }
2808
2921
  this.allowAllSessions.add(grantKey);
2809
2922
  }
2810
- else if (grantable && entry.sessionId) {
2923
+ else if (answer.home === "none" && answer.occupantUnreadable) {
2811
2924
  defaultLogger.warn("session_grant_refused_occupant_unreadable", { sessionId: entry.sessionId, toolName: entry.toolName });
2812
2925
  }
2813
2926
  }
@@ -2880,7 +2993,8 @@ export class ToolApprovalCoordinator {
2880
2993
  grantBinding: { kind: "unreadable" },
2881
2994
  ...(card.classes !== undefined ? { classes: card.classes } : {}),
2882
2995
  };
2883
- const rememberRefused = standingAnswerHome(pendingEntryStandingAnswerFacts(facts)) === "none";
2996
+ const leg = row.sessionId !== row.taskId ? { sessionId: row.sessionId } : {};
2997
+ const rememberRefused = liveSessionAnswer(pendingEntryStandingAnswerFacts(facts), leg).home === "none";
2884
2998
  const cardFrame = (card.rememberRefused === true) === rememberRefused
2885
2999
  ? replayFrame
2886
3000
  : { ...replayFrame, card: rememberRefused ? { ...card, rememberRefused: true } : (({ rememberRefused: _stale, ...rest }) => rest)(card) };
@@ -2911,7 +3025,7 @@ export class ToolApprovalCoordinator {
2911
3025
  owner: row.owner,
2912
3026
  ownerReadSeq: this.rowReadSeq,
2913
3027
  executionLane: row.executionLane,
2914
- ...(row.sessionId !== row.taskId ? { sessionId: row.sessionId } : {}),
3028
+ ...leg,
2915
3029
  ...(card.fromSubagent === true ? { originTaskId: row.sourceSessionId } : {}),
2916
3030
  toolName: card.toolName,
2917
3031
  ...facts,
@@ -3042,28 +3156,11 @@ export class ToolApprovalCoordinator {
3042
3156
  continue;
3043
3157
  seen.add(entry.askId);
3044
3158
  }
3045
- const waitingStart = waiting.length > 0 ? this.suspendedPollOffset % waiting.length : 0;
3046
- const adoptedStart = adopted.length > 0 ? this.adoptedPollOffset % adopted.length : 0;
3047
- const ordered = [
3048
- ...[...waiting.slice(waitingStart), ...waiting.slice(0, waitingStart)].map((askId) => ({ askId, tier: "waiting" })),
3049
- ...[...adopted.slice(adoptedStart), ...adopted.slice(0, adoptedStart)].map((askId) => ({ askId, tier: "adopted" })),
3050
- ];
3051
- const deadlineMs = Date.now() + SUSPENDED_POLL_BUDGET_MS;
3052
3159
  let settled = 0;
3053
- let polled = 0;
3054
- let polledWaiting = 0;
3055
- let polledAdopted = 0;
3056
- let truncated = false;
3057
- for (const { askId, tier } of ordered) {
3058
- if (polled >= SUSPENDED_POLL_MAX_PER_TICK || Date.now() >= deadlineMs) {
3059
- truncated = true;
3060
- break;
3061
- }
3062
- polled++;
3063
- if (tier === "waiting")
3064
- this.suspendedPollOffset = waitingStart + ++polledWaiting;
3065
- else
3066
- this.adoptedPollOffset = adoptedStart + ++polledAdopted;
3160
+ const { visited: polled, truncated } = await boundedRotation([
3161
+ { items: waiting, cursor: this.suspendedPollCursor },
3162
+ { items: adopted, cursor: this.adoptedPollCursor },
3163
+ ], { maxPerTick: SUSPENDED_POLL_MAX_PER_TICK, budgetMs: SUSPENDED_POLL_BUDGET_MS }, async (askId) => {
3067
3164
  let row;
3068
3165
  const readSeq = this.nextRowReadSeq();
3069
3166
  try {
@@ -3071,24 +3168,24 @@ export class ToolApprovalCoordinator {
3071
3168
  }
3072
3169
  catch (err) {
3073
3170
  this.noteStoreError(err, "getAsk(poll-suspended)");
3074
- continue;
3171
+ return;
3075
3172
  }
3076
3173
  if (row === null) {
3077
3174
  this.forgetAdoptedAsk(askId);
3078
- continue;
3175
+ return;
3079
3176
  }
3080
3177
  if (row.state === "STREAM_PENDING") {
3081
3178
  this.followRowOwner(askId, row.owner, readSeq);
3082
- continue;
3179
+ return;
3083
3180
  }
3084
3181
  if (this.editedDecisionInFlight(askId))
3085
- continue;
3182
+ return;
3086
3183
  const endingCause = askRowEndingCause(row);
3087
3184
  if (endingCause !== undefined) {
3088
3185
  const before = this.waitingRegistrationCount(askId);
3089
3186
  this.settleVoidedSiblings([askId], endingCause);
3090
3187
  settled += before;
3091
- continue;
3188
+ return;
3092
3189
  }
3093
3190
  const outcome = replayTerminalAskRow(row);
3094
3191
  if (outcome === "unavailable") {
@@ -3096,11 +3193,11 @@ export class ToolApprovalCoordinator {
3096
3193
  const parkCause = askRowParkTrigger(row) ?? (Date.now() >= row.expiresAtMs ? APPROVAL_ENDING_CAUSES.TTL_EXPIRED : APPROVAL_ENDING_CAUSES.SHUTDOWN_BEFORE_PARK);
3097
3194
  this.settleSameAskIdParkRoute(askId, parkCause);
3098
3195
  settled += before;
3099
- continue;
3196
+ return;
3100
3197
  }
3101
3198
  const delivered = this.notifyExternalDecision(askId, outcome).settled;
3102
3199
  settled += delivered;
3103
- }
3200
+ });
3104
3201
  const backlog = Math.max(0, waiting.length + adopted.length - polled);
3105
3202
  if (truncated) {
3106
3203
  defaultLogger.warn("approval_suspended_poll_truncated", {
@@ -3109,8 +3206,8 @@ export class ToolApprovalCoordinator {
3109
3206
  backlog,
3110
3207
  maxPerTick: SUSPENDED_POLL_MAX_PER_TICK,
3111
3208
  budgetMs: SUSPENDED_POLL_BUDGET_MS,
3112
- resumeFromOffset: this.suspendedPollOffset,
3113
- resumeAdoptedFromOffset: this.adoptedPollOffset,
3209
+ resumeFromOffset: this.suspendedPollCursor.offset,
3210
+ resumeAdoptedFromOffset: this.adoptedPollCursor.offset,
3114
3211
  });
3115
3212
  }
3116
3213
  return { polled, settled, backlog, truncated };
@@ -1,3 +1,4 @@
1
+ import { projectMcpAuthorization } from "../mcp-authorization-face.js";
1
2
  /**
2
3
  * 上 wire 的通告码 —— **显式闭集常量表**(设计稿 ①,起步三码;今天的码数以本常量自身为准——
3
4
  * 在散文里抄数字必陈腐,codex 5.65 增量批 R1-[low] 实逮:上一句曾写「今天九码」而表里是十条。
@@ -108,6 +109,19 @@ export declare function redactNoticeMessage(message: unknown): string;
108
109
  * 交中和形,空白 / 超长的条目两只码不同)。其余字段、其余码原样。
109
110
  */
110
111
  export declare function redactNoticeRuleText(code: string, detail: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
112
+ /**
113
+ * 通告 `detail` 里**平铺着一条有处置表的记录**的码:码 → 那条记录的成员名与出门投影(一张表,不在 {@link engineNoticeEventData} 里写分支)。
114
+ * 记录成员只经那只投影出门(结构位:不过 {@link sanitizeWireText} 的脱敏与截断 —— 结构位的形与长由记录的属主判);detail 的其余成员照旧经
115
+ * {@link sanitizeNoticeDetail},合并按引擎 detail 的原键序。投影答 `undefined`(`reason` 出闭集 / 缺席)⇒ 记录成员整组缺席(在场而读不出由表的丢弃口计一次),
116
+ * 与状态面「整格缺席」同一失败方向。
117
+ * 运维日志腿(`boot/runner-deps.ts` 的转发席)不读这张登记:日志答「发生了什么」(给运维,整行过日志行的出口座),wire 答「用户拿到什么」—— 两个问题,两个读者。
118
+ */
119
+ export declare const NOTICE_DETAIL_RECORDS: {
120
+ readonly "mcp.authorization_required": {
121
+ readonly members: readonly string[];
122
+ readonly project: typeof projectMcpAuthorization;
123
+ };
124
+ };
111
125
  export declare function engineNoticeEventData(notice: {
112
126
  code: string;
113
127
  message: string;
@@ -2,6 +2,7 @@ import { uuidv7 } from "@sema-agent/core";
2
2
  import { redactSecrets } from "./redact.js";
3
3
  import { redactListEntry } from "../list-entry-display.js";
4
4
  import { recordFailOpen } from "../observability/fail-open.js";
5
+ import { MCP_AUTHORIZATION_MEMBERS, projectMcpAuthorization } from "../mcp-authorization-face.js";
5
6
  export const ENGINE_NOTICE_WIRE_CODES = [
6
7
  "memory.session_polluted",
7
8
  "memory.harvest_quarantined",
@@ -136,11 +137,27 @@ export function redactNoticeRuleText(code, detail) {
136
137
  });
137
138
  return { ...detail, [at.array]: redacted };
138
139
  }
140
+ export const NOTICE_DETAIL_RECORDS = {
141
+ "mcp.authorization_required": { members: MCP_AUTHORIZATION_MEMBERS, project: projectMcpAuthorization },
142
+ };
143
+ function noticeDetailOf(code, detail) {
144
+ const records = NOTICE_DETAIL_RECORDS;
145
+ const record = Object.hasOwn(records, code) ? records[code] : undefined;
146
+ if (record === undefined || detail === undefined)
147
+ return sanitizeNoticeDetail(redactNoticeRuleText(code, detail));
148
+ const own = (key) => record.members.includes(key);
149
+ const face = { ...record.project(Object.fromEntries(Object.entries(detail).filter(([k]) => own(k)))) };
150
+ const rest = sanitizeNoticeDetail(redactNoticeRuleText(code, Object.fromEntries(Object.entries(detail).filter(([k]) => !own(k)))));
151
+ return Object.fromEntries(Object.keys(detail).flatMap((k) => {
152
+ const from = own(k) ? face : rest;
153
+ return Object.hasOwn(from, k) ? [[k, from[k]]] : [];
154
+ }));
155
+ }
139
156
  export function engineNoticeEventData(notice, sessionId, nowMs, eventId) {
140
157
  return {
141
158
  code: notice.code,
142
159
  message: redactNoticeMessage(notice.message).slice(0, NOTICE_TEXT_MAX),
143
- detail: sanitizeNoticeDetail(redactNoticeRuleText(notice.code, notice.detail)),
160
+ detail: noticeDetailOf(notice.code, notice.detail),
144
161
  sessionId,
145
162
  ts: nowMs,
146
163
  eventId,
@@ -217,7 +217,7 @@ export declare function toolStartEventData(ev: {
217
217
  * `done` 永远到不了、重连恒复现同一处),而 `gate-outcome-defective` 那一格还不涨。
218
218
  *
219
219
  * ⇒ 兑现方式从「枚举」换成**结构**:任何逃出投影的异常同走既有的那一口 report + withhold。规则因此变少
220
- * (不是「守住已知的 N 种坏形」而是「坏字节一律 withhold」)。core 7.51.0 起筛本身对任意 JSON 形不抛(KL-1731-a:只覆盖 JSON ——
220
+ * (不是「守住已知的 N 种坏形」而是「坏字节一律 withhold」)。core 7.51.0 起筛本身对任意 JSON 形不抛([ref]:只覆盖 JSON ——
221
221
  * 访问器 / Proxy 这类非 JSON 值仍可能抛),本仓此前叠在筛前的具名形门与成员门(第二读法)随之退役,诊断串就是筛给的缺陷句。
222
222
  * ⛔ **刻意不动**「先脱敏后截断」的次序:截断在前会把跨界的密钥切成半截明文留在输出里,而且它只治
223
223
  * `note` 一条叶(`approver` 同病)—— 那是给一个类打两个特判,正是本仓要消掉的形。
@@ -294,7 +294,8 @@ export declare function reasoningEndEventData(ev: Record<string, unknown>): Segm
294
294
  * can never appear here) — SAME UNTRUSTED RAW contract as `output` (a card carries `originalFile`/stdout bodies),
295
295
  * so it gets the same deep redaction before it is persisted or echoed — except a media card's `file.base64` (image / document
296
296
  * cards: the second encoding of the same bytes the `output` block carries), which, like the block's `data`, is an encoding of
297
- * bytes and not text ({@link projectToolStructured}; the durable face drops it in the ledger confluence). `label`(core 展示名,同 tool_start 的
297
+ * bytes and not text; a card that carries a record with a disposition table (an MCP authorization failure card's `authorization`) has that member
298
+ * projected by the record's table ({@link projectToolCard}, the one reader of a tool card — session history reads `toolResult.details` with it too; the durable face drops the media bytes in the ledger confluence). `label`(core 展示名,同 tool_start 的
298
299
  * label 待遇 verbatim)白名单排查(2026-07-24)补齐进函数本体——此前外包给调用点各自手动拼接,7 处只有
299
300
  * 3 处记得拼,resume leg + ledger-sink 落盘两处漏了,持久化记录本身缺 label 一写盘就永久追不回来。 */
300
301
  export declare function toolEndEventData(ev: {
@@ -333,7 +334,7 @@ export declare function toolEndEventData(ev: {
333
334
  * · `toolCallId` / `toolName` —— 调用 id(🔴 [ref] 订正:出身是**服务商**在 tool_use / tool_calls 里给的,引擎缺席时自铸兜底、越界时折叠 ——
334
335
  * 此前写「引擎铸」不实)与名册里的工具名(与 `tool_start` 逐字同源)⇒ verbatim。调用 id 这一族的形状在**全部面的共同入口**一次施加 ——
335
336
  * core 7.36.0([ref])brain 建调用那一行的准入(在形原样 / 越界单射折叠,原字节只在转录 `ToolCall.wireId`),一方 brain 新铸的调用在逐帧面上
336
- * 恒是在形的引擎 id(残余两条 [ref]:≤7.106.0 写下的存量行 resume 出来的帧是服务商原串逐字;宿主 Brain 不准入 KL-1207-a —— 详见
337
+ * 恒是在形的引擎 id(残余两条 [ref]:≤7.106.0 写下的存量行 resume 出来的帧是服务商原串逐字;宿主 Brain 不准入 [ref] —— 详见
337
338
  * run-terminal `admitProviderEcho` 顶注);
338
339
  * 本仓不设第二道闸(见 run-terminal `admitProviderEcho` 顶注;[ref] 关)。
339
340
  * · `elapsedTimeSeconds` —— 引擎铸的整秒,单调、一 call 一个原点 ⇒ 有限数才铸键。