@sema-agent/server 7.147.0 → 7.148.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (725) hide show
  1. package/MIGRATION.md +1039 -24
  2. package/README.md +20 -7
  3. package/README.zh-CN.md +14 -8
  4. package/USAGE.md +380 -163
  5. package/deploy/sema-up/README.md +16 -5
  6. package/deploy/sema-up/chart/templates/NOTES.txt +1 -1
  7. package/deploy/sema-up/chart/templates/_helpers.tpl +20 -4
  8. package/deploy/sema-up/chart/values.yaml +3 -2
  9. package/deploy/sema-up/cluster-up.sh +74 -176
  10. package/deploy/sema-up/kube-up.sh +29 -49
  11. package/deploy/sema-up/lib/chart-run.sh +23 -0
  12. package/deploy/sema-up/lib/dataroot.sh +3 -3
  13. package/deploy/sema-up/lib/health.sh +62 -13
  14. package/deploy/sema-up/lib/helm-values-cluster.py +18 -0
  15. package/deploy/sema-up/lib/helm-values-kube.py +35 -0
  16. package/deploy/sema-up/lib/regcred.py +8 -0
  17. package/deploy/sema-up/lib/remote/helm-install.sh +3 -0
  18. package/deploy/sema-up/lib/remote/image-import.sh +6 -0
  19. package/deploy/sema-up/lib/remote/machine-precheck.sh +11 -0
  20. package/deploy/sema-up/lib/remote/region-probe.sh +3 -0
  21. package/deploy/sema-up/lib/remote/stack-ready.sh +26 -0
  22. package/deploy/sema-up/lib/remote/vxlan-guard.sh +8 -0
  23. package/deploy/sema-up/lib/render-stack.py +17 -0
  24. package/deploy/sema-up/lib/shell-text.sh +87 -0
  25. package/deploy/sema-up/lib/usage-flags.txt +10 -0
  26. package/deploy/sema-up/lib/usage-head.txt +1 -0
  27. package/deploy/sema-up/lib/usage-tail.txt +13 -0
  28. package/deploy/sema-up/preflight.sh +10 -8
  29. package/deploy/sema-up/sema-up.sh +14 -39
  30. package/deploy/sema-up/smoke.sh +7 -6
  31. package/deploy/sema-up/stack/compose.dataroot.yaml +3 -0
  32. package/deploy/sema-up/stack/compose.yaml +13 -1
  33. package/deploy/sema-up/stack/sema-stack-cluster.yaml +21 -0
  34. package/dist/adoption/plan.d.ts +24 -0
  35. package/dist/adoption/plan.js +53 -1
  36. package/dist/adoption/runner.d.ts +10 -1
  37. package/dist/adoption/runner.js +36 -16
  38. package/dist/adoption/wire.d.ts +3 -3
  39. package/dist/approval-card.d.ts +28 -30
  40. package/dist/approval-gate-currency.js +3 -2
  41. package/dist/approval-reconciler.d.ts +4 -13
  42. package/dist/approval-reconciler.js +2 -2
  43. package/dist/approval.d.ts +13 -11
  44. package/dist/approval.js +3 -3
  45. package/dist/audit.d.ts +10 -3
  46. package/dist/audit.js +15 -7
  47. package/dist/auth-bridge.d.ts +0 -14
  48. package/dist/auth-bridge.js +0 -7
  49. package/dist/auto-mode-face.d.ts +10 -7
  50. package/dist/auto-mode-face.js +7 -4
  51. package/dist/background-agent-name.d.ts +19 -1
  52. package/dist/background-agent-name.js +12 -2
  53. package/dist/background-session-reap.d.ts +1 -1
  54. package/dist/bake-runner/main.js +9 -6
  55. package/dist/bench/s1/arms.js +6 -5
  56. package/dist/bench/s1/live-deps.js +5 -2
  57. package/dist/bench/s1/run-firm.js +6 -5
  58. package/dist/bind-host.d.ts +25 -0
  59. package/dist/bind-host.js +25 -0
  60. package/dist/boot/adoption.d.ts +3 -0
  61. package/dist/boot/adoption.js +1 -0
  62. package/dist/boot/deployment-mods.d.ts +1 -1
  63. package/dist/boot/execution-env.d.ts +17 -7
  64. package/dist/boot/execution-env.js +37 -31
  65. package/dist/boot/exit-boundary.d.ts +2 -2
  66. package/dist/boot/exit-boundary.js +6 -5
  67. package/dist/boot/fatal-exit.d.ts +3 -5
  68. package/dist/boot/fatal-exit.js +2 -2
  69. package/dist/boot/leader.d.ts +15 -0
  70. package/dist/boot/leader.js +17 -15
  71. package/dist/boot/memory-consolidation.d.ts +37 -29
  72. package/dist/boot/memory-consolidation.js +11 -5
  73. package/dist/boot/org-memory.js +1 -1
  74. package/dist/boot/parked-revive-gate.js +2 -2
  75. package/dist/boot/reapers.d.ts +4 -3
  76. package/dist/boot/reapers.js +19 -16
  77. package/dist/boot/resolve-spec.d.ts +5 -3
  78. package/dist/boot/resolve-spec.js +55 -67
  79. package/dist/boot/retention-lane.d.ts +4 -4
  80. package/dist/boot/retention-lane.js +2 -2
  81. package/dist/boot/runner-deps.d.ts +28 -7
  82. package/dist/boot/runner-deps.js +11 -4
  83. package/dist/boot/runtime-caps.d.ts +2 -2
  84. package/dist/boot/runtime-caps.js +16 -2
  85. package/dist/boot/session-faces.d.ts +16 -7
  86. package/dist/boot/session-faces.js +114 -94
  87. package/dist/boot/shutdown.d.ts +5 -4
  88. package/dist/boot/shutdown.js +6 -4
  89. package/dist/boot/stage-01-config.js +9 -1
  90. package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
  91. package/dist/boot/stage-02-web-admin-pull.js +6 -1
  92. package/dist/boot/stage-03-store-backend.d.ts +3 -0
  93. package/dist/boot/stage-03-store-backend.js +4 -3
  94. package/dist/boot/stage-04-stores.d.ts +2 -0
  95. package/dist/boot/stage-04-stores.js +2 -2
  96. package/dist/boot/stage-05-execution-env.d.ts +7 -3
  97. package/dist/boot/stage-05-execution-env.js +2 -2
  98. package/dist/boot/stage-06-runners.d.ts +10 -12
  99. package/dist/boot/stage-06-runners.js +23 -15
  100. package/dist/boot/stage-07-capability-layer.d.ts +11 -8
  101. package/dist/boot/stage-07-capability-layer.js +5 -3
  102. package/dist/boot/stage-08-reapers.d.ts +11 -8
  103. package/dist/boot/stage-08-reapers.js +3 -3
  104. package/dist/boot/stage-09-leader.d.ts +12 -15
  105. package/dist/boot/stage-09-leader.js +12 -4
  106. package/dist/boot/stage-10-http-server.d.ts +12 -15
  107. package/dist/boot/stage-10-http-server.js +7 -4
  108. package/dist/boot/store-evidence.d.ts +20 -0
  109. package/dist/boot/store-evidence.js +13 -0
  110. package/dist/boot/stores.d.ts +3 -0
  111. package/dist/boot/stores.js +21 -10
  112. package/dist/boot/task-list-lane.d.ts +4 -4
  113. package/dist/boot/web-admin.d.ts +4 -2
  114. package/dist/boot/web-admin.js +55 -35
  115. package/dist/boot/webfetch-summarize-lane.d.ts +1 -1
  116. package/dist/boot-reclaim.d.ts +3 -1
  117. package/dist/boot-reclaim.js +1 -1
  118. package/dist/brain.d.ts +7 -18
  119. package/dist/brain.js +5 -17
  120. package/dist/budget.js +6 -6
  121. package/dist/capabilities/center-plugins.d.ts +7 -1
  122. package/dist/capabilities/center-plugins.js +32 -10
  123. package/dist/capabilities/center-wiring.js +1 -1
  124. package/dist/capabilities/composite-members.d.ts +2 -2
  125. package/dist/capabilities/composite-members.js +2 -2
  126. package/dist/capabilities/repo-tools.d.ts +2 -0
  127. package/dist/capabilities/repo-tools.js +14 -12
  128. package/dist/capabilities/scenarios.d.ts +6 -15
  129. package/dist/capabilities/scenarios.js +11 -16
  130. package/dist/capabilities/skills.d.ts +1 -1
  131. package/dist/capabilities/tool-defer.d.ts +1 -1
  132. package/dist/capability-facts.d.ts +38 -11
  133. package/dist/capability-facts.js +47 -8
  134. package/dist/card-void.d.ts +4 -4
  135. package/dist/card-void.js +1 -1
  136. package/dist/center-credential-renewer.d.ts +6 -2
  137. package/dist/center-credential-renewer.js +7 -3
  138. package/dist/config-catalog.d.ts +16 -1
  139. package/dist/config-catalog.js +62 -56
  140. package/dist/config-dir-trust.d.ts +37 -4
  141. package/dist/config-dir-trust.js +88 -44
  142. package/dist/config-invariants.d.ts +42 -3
  143. package/dist/config-invariants.js +69 -5
  144. package/dist/config-lkg.d.ts +23 -1
  145. package/dist/config-lkg.js +17 -3
  146. package/dist/config-provider.d.ts +9 -9
  147. package/dist/config-provider.js +25 -110
  148. package/dist/config-pull-failure.d.ts +50 -0
  149. package/dist/config-pull-failure.js +48 -0
  150. package/dist/config-types.d.ts +26 -17
  151. package/dist/config.d.ts +8 -16
  152. package/dist/config.js +113 -47
  153. package/dist/delegated-session-owner.d.ts +1 -1
  154. package/dist/deleted-session-ids.d.ts +3 -2
  155. package/dist/deployment-governance.d.ts +3 -3
  156. package/dist/deployment-shape.d.ts +30 -4
  157. package/dist/deployment-shape.js +7 -0
  158. package/dist/egress-redirect.d.ts +25 -7
  159. package/dist/egress-redirect.js +20 -2
  160. package/dist/elicitation.d.ts +6 -5
  161. package/dist/elicitation.js +23 -22
  162. package/dist/engine-identity.d.ts +28 -0
  163. package/dist/engine-identity.js +10 -0
  164. package/dist/entry-problems.d.ts +5 -7
  165. package/dist/entry-problems.js +1 -1
  166. package/dist/env-facts.js +2 -1
  167. package/dist/env-witness.d.ts +7 -0
  168. package/dist/env-witness.js +16 -0
  169. package/dist/execution-lane-caps.d.ts +5 -18
  170. package/dist/execution-lane-caps.js +0 -22
  171. package/dist/execution-placement.d.ts +58 -18
  172. package/dist/execution-placement.js +41 -2
  173. package/dist/field-conflict.d.ts +7 -11
  174. package/dist/field-conflict.js +3 -3
  175. package/dist/file-history-capture.d.ts +3 -3
  176. package/dist/file-history-disclosure.js +1 -0
  177. package/dist/fleet/fleet-bus.d.ts +21 -3
  178. package/dist/fleet/fleet-bus.js +35 -25
  179. package/dist/fleet/fleet-reconciler.js +2 -2
  180. package/dist/fleet/serving-lease.js +3 -3
  181. package/dist/fleet-client.js +3 -3
  182. package/dist/fleet-lease.d.ts +0 -1
  183. package/dist/fleet-lease.js +4 -5
  184. package/dist/history-anchor.d.ts +23 -3
  185. package/dist/history-anchor.js +24 -4
  186. package/dist/hitl-delivery.d.ts +90 -0
  187. package/dist/hitl-delivery.js +98 -0
  188. package/dist/hooks/classic-stations.d.ts +8 -11
  189. package/dist/hooks/classic-stations.js +0 -7
  190. package/dist/hooks/hook-llm.d.ts +5 -1
  191. package/dist/hooks/hook-llm.js +24 -15
  192. package/dist/hooks/hook-runner.d.ts +67 -57
  193. package/dist/hooks/hook-runner.js +260 -186
  194. package/dist/host-lsp-manager.d.ts +22 -8
  195. package/dist/host-lsp-manager.js +4 -1
  196. package/dist/http/active-run-conflict.d.ts +2 -43
  197. package/dist/http/active-run-conflict.js +3 -7
  198. package/dist/http/admission.d.ts +4 -18
  199. package/dist/http/admission.js +75 -78
  200. package/dist/http/approval-sweeps.d.ts +3 -3
  201. package/dist/http/approval-sweeps.js +54 -30
  202. package/dist/http/caller-trust.d.ts +8 -10
  203. package/dist/http/caller-trust.js +1 -2
  204. package/dist/http/claim-heartbeat.d.ts +49 -0
  205. package/dist/http/claim-heartbeat.js +46 -0
  206. package/dist/http/claimed-run.d.ts +4 -3
  207. package/dist/http/dispatch.d.ts +8 -1
  208. package/dist/http/dispatch.js +76 -30
  209. package/dist/http/durable-run-leg.d.ts +3 -3
  210. package/dist/http/durable-run-leg.js +17 -12
  211. package/dist/http/execution-context.d.ts +17 -43
  212. package/dist/http/execution-context.js +7 -5
  213. package/dist/http/health-reader.d.ts +36 -0
  214. package/dist/http/health-reader.js +21 -0
  215. package/dist/http/health-self-report.d.ts +9 -9
  216. package/dist/http/health-self-report.js +4 -4
  217. package/dist/http/idempotency.d.ts +9 -5
  218. package/dist/http/idempotency.js +4 -4
  219. package/dist/http/memory-compliance-failure-reply.d.ts +15 -16
  220. package/dist/http/memory-compliance-failure-reply.js +4 -2
  221. package/dist/http/memory-face-fault-reply.d.ts +67 -0
  222. package/dist/http/memory-face-fault-reply.js +71 -0
  223. package/dist/http/memory-store-refusal-reply.d.ts +1 -1
  224. package/dist/http/memory-store-refusal-reply.js +3 -0
  225. package/dist/http/owner-access.d.ts +391 -67
  226. package/dist/http/owner-access.js +371 -35
  227. package/dist/http/principal-gate.d.ts +24 -81
  228. package/dist/http/principal-gate.js +24 -68
  229. package/dist/http/refusal-body.d.ts +35 -2
  230. package/dist/http/refusal-body.js +34 -0
  231. package/dist/http/request-guards.d.ts +9 -13
  232. package/dist/http/request-guards.js +34 -68
  233. package/dist/http/resume-composition.d.ts +37 -0
  234. package/dist/http/resume-composition.js +18 -0
  235. package/dist/http/resume-ctx-read.d.ts +35 -12
  236. package/dist/http/resume-ctx-read.js +25 -6
  237. package/dist/http/resume-legs.d.ts +21 -18
  238. package/dist/http/resume-legs.js +189 -129
  239. package/dist/http/retired-skill-manifest.d.ts +1 -1
  240. package/dist/http/route-ctx.d.ts +25 -32
  241. package/dist/http/routes/a2a-serve.d.ts +43 -5
  242. package/dist/http/routes/a2a-serve.js +58 -37
  243. package/dist/http/routes/admin-config-refresh.js +2 -2
  244. package/dist/http/routes/admin-drain.js +2 -2
  245. package/dist/http/routes/admin-memory-optout.js +4 -3
  246. package/dist/http/routes/adoption.d.ts +3 -0
  247. package/dist/http/routes/adoption.js +17 -10
  248. package/dist/http/routes/agents-roster.js +13 -7
  249. package/dist/http/routes/approvals-assistant.js +70 -65
  250. package/dist/http/routes/attachments.js +2 -2
  251. package/dist/http/routes/background.d.ts +3 -3
  252. package/dist/http/routes/background.js +9 -17
  253. package/dist/http/routes/capabilities.js +15 -18
  254. package/dist/http/routes/config-catalog.js +2 -2
  255. package/dist/http/routes/devices.d.ts +3 -3
  256. package/dist/http/routes/devices.js +4 -4
  257. package/dist/http/routes/diagnostics.d.ts +27 -3
  258. package/dist/http/routes/diagnostics.js +27 -21
  259. package/dist/http/routes/engine.js +2 -2
  260. package/dist/http/routes/fleet.js +5 -3
  261. package/dist/http/routes/images.js +10 -6
  262. package/dist/http/routes/leader.d.ts +7 -2
  263. package/dist/http/routes/leader.js +12 -3
  264. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  265. package/dist/http/routes/mcp-reconnect.js +7 -15
  266. package/dist/http/routes/memory-bundle.js +4 -7
  267. package/dist/http/routes/memory-compliance.js +4 -4
  268. package/dist/http/routes/memory-consolidation.js +6 -9
  269. package/dist/http/routes/memory-origin.d.ts +2 -0
  270. package/dist/http/routes/memory-origin.js +7 -8
  271. package/dist/http/routes/memory-policy.js +17 -12
  272. package/dist/http/routes/notify-wake.js +10 -19
  273. package/dist/http/routes/observability.js +3 -3
  274. package/dist/http/routes/principal-inbox.d.ts +1 -1
  275. package/dist/http/routes/principal-inbox.js +2 -2
  276. package/dist/http/routes/projects.d.ts +1 -1
  277. package/dist/http/routes/projects.js +3 -2
  278. package/dist/http/routes/retention-ops.js +6 -9
  279. package/dist/http/routes/rules.js +20 -5
  280. package/dist/http/routes/run-memory-capture.d.ts +2 -2
  281. package/dist/http/routes/run-memory-capture.js +6 -12
  282. package/dist/http/routes/run-permission-mode.d.ts +2 -2
  283. package/dist/http/routes/run-permission-mode.js +10 -17
  284. package/dist/http/routes/runs.js +146 -231
  285. package/dist/http/routes/session-memory-sync.d.ts +2 -2
  286. package/dist/http/routes/session-memory-sync.js +7 -13
  287. package/dist/http/routes/session-sync.d.ts +4 -2
  288. package/dist/http/routes/session-sync.js +21 -20
  289. package/dist/http/routes/sessions-list.d.ts +3 -3
  290. package/dist/http/routes/sessions-list.js +9 -9
  291. package/dist/http/routes/sessions.js +87 -124
  292. package/dist/http/routes/shared-memory.js +6 -6
  293. package/dist/http/routes/side-query.js +2 -2
  294. package/dist/http/routes/tasks.js +136 -120
  295. package/dist/http/routes/trace-usage.d.ts +0 -12
  296. package/dist/http/routes/trace-usage.js +40 -46
  297. package/dist/http/routes/workflows.d.ts +39 -4
  298. package/dist/http/routes/workflows.js +42 -14
  299. package/dist/http/run-concurrency-cap.d.ts +20 -12
  300. package/dist/http/run-concurrency-cap.js +39 -26
  301. package/dist/http/run-read-face.d.ts +3 -5
  302. package/dist/http/run-read-face.js +8 -13
  303. package/dist/http/send.d.ts +12 -3
  304. package/dist/http/send.js +42 -6
  305. package/dist/http/server.d.ts +39 -40
  306. package/dist/http/server.js +36 -11
  307. package/dist/http/sse-log.d.ts +17 -10
  308. package/dist/http/sse-log.js +7 -7
  309. package/dist/http/stored-body-replay.d.ts +12 -0
  310. package/dist/http/stored-body-replay.js +2 -2
  311. package/dist/http/submit-ctx.d.ts +16 -8
  312. package/dist/http/submit-ctx.js +6 -2
  313. package/dist/http/submit-replay.d.ts +19 -6
  314. package/dist/http/submit-replay.js +18 -6
  315. package/dist/http/sync-submit-body.d.ts +3 -4
  316. package/dist/http/sync-submit-body.js +4 -5
  317. package/dist/http/wire-types.d.ts +4 -3
  318. package/dist/identity-source.d.ts +36 -5
  319. package/dist/identity-source.js +27 -0
  320. package/dist/index.d.ts +1 -0
  321. package/dist/index.js +1 -0
  322. package/dist/key-resolver.d.ts +32 -0
  323. package/dist/key-resolver.js +23 -9
  324. package/dist/leader/diffup.js +2 -1
  325. package/dist/leader/endpoint.d.ts +26 -5
  326. package/dist/leader/endpoint.js +154 -14
  327. package/dist/leader/fanout.d.ts +3 -0
  328. package/dist/leader/fanout.js +78 -63
  329. package/dist/leader/leader.d.ts +16 -0
  330. package/dist/leader/leader.js +43 -3
  331. package/dist/leader/merge.d.ts +9 -1
  332. package/dist/leader/merge.js +16 -1
  333. package/dist/leader/repair-wire.js +1 -1
  334. package/dist/leader/wire.d.ts +36 -3
  335. package/dist/leader/wire.js +59 -18
  336. package/dist/lsp-evict.d.ts +6 -4
  337. package/dist/lsp-evict.js +2 -3
  338. package/dist/memory-operator-faces.d.ts +5 -4
  339. package/dist/memory-operator-faces.js +1 -1
  340. package/dist/memory-scope.d.ts +29 -2
  341. package/dist/memory-scope.js +64 -15
  342. package/dist/memory-store-refusal.d.ts +5 -2
  343. package/dist/memory-sync-client.d.ts +3 -2
  344. package/dist/memory-sync-client.js +6 -3
  345. package/dist/model-compat.d.ts +17 -8
  346. package/dist/model-compat.js +6 -2
  347. package/dist/model-context-window.d.ts +18 -0
  348. package/dist/model-context-window.js +2 -0
  349. package/dist/model-entry-headers.d.ts +46 -4
  350. package/dist/model-entry-headers.js +2 -2
  351. package/dist/model-entry-refusal.d.ts +35 -16
  352. package/dist/model-entry-refusal.js +40 -27
  353. package/dist/model-plane-face.d.ts +19 -11
  354. package/dist/model-plane-face.js +9 -1
  355. package/dist/model-plane-probe.d.ts +2 -0
  356. package/dist/model-plane-probe.js +17 -0
  357. package/dist/model-provider.d.ts +3 -3
  358. package/dist/model-route-endpoint.d.ts +9 -5
  359. package/dist/model-route-endpoint.js +29 -7
  360. package/dist/model-select.d.ts +16 -0
  361. package/dist/model-select.js +4 -0
  362. package/dist/mountinfo.d.ts +37 -0
  363. package/dist/mountinfo.js +47 -0
  364. package/dist/namespaced-rule-name.d.ts +23 -14
  365. package/dist/namespaced-rule-name.js +8 -11
  366. package/dist/net-address.d.ts +1 -1
  367. package/dist/observability/corrupt-read-seat.d.ts +4 -4
  368. package/dist/observability/corrupt-read-seat.js +5 -3
  369. package/dist/observability/fail-open.d.ts +58 -38
  370. package/dist/observability/fail-open.js +60 -38
  371. package/dist/observability/logger.d.ts +22 -1
  372. package/dist/observability/logger.js +89 -12
  373. package/dist/observability/metrics.js +3 -4
  374. package/dist/observability/otel-exporter.js +2 -1
  375. package/dist/observability/principal-context.d.ts +14 -7
  376. package/dist/observability/principal-context.js +8 -3
  377. package/dist/observability/run-terminal.d.ts +7 -1
  378. package/dist/observability/run-terminal.js +5 -2
  379. package/dist/orchestration/hardened-vm-runner.d.ts +1 -0
  380. package/dist/orchestration/hardened-vm-runner.js +11 -5
  381. package/dist/orchestration/hardened-vm-worker-runner.d.ts +0 -14
  382. package/dist/orchestration/hardened-vm-worker-runner.js +5 -0
  383. package/dist/orchestration/hardened-vm-worker.js +2 -1
  384. package/dist/orchestration/workflow-completion-inbox.d.ts +3 -3
  385. package/dist/orchestration/workflow-completion-inbox.js +3 -2
  386. package/dist/org-delivery-gate.d.ts +5 -4
  387. package/dist/org-delivery-gate.js +7 -6
  388. package/dist/outbound-dispatcher.d.ts +1 -1
  389. package/dist/outbound-dispatcher.js +6 -12
  390. package/dist/owner-brands.d.ts +81 -0
  391. package/dist/owner-brands.js +42 -0
  392. package/dist/owner-faces.d.ts +531 -0
  393. package/dist/owner-faces.js +126 -0
  394. package/dist/parked-decide.d.ts +67 -5
  395. package/dist/parked-decide.js +127 -5
  396. package/dist/parked-revive-surface.d.ts +14 -4
  397. package/dist/parked-revive-surface.js +5 -4
  398. package/dist/peer-directory.d.ts +6 -8
  399. package/dist/peer-directory.js +3 -2
  400. package/dist/permission-rule-vocab.d.ts +53 -8
  401. package/dist/permission-rule-vocab.js +30 -2
  402. package/dist/plugins/adoption-log-sql.d.ts +0 -22
  403. package/dist/plugins/adoption-log-sql.js +5 -3
  404. package/dist/plugins/approval-ask-retired-delete-by-task-m50.d.ts +7 -0
  405. package/dist/plugins/approval-ask-retired-delete-by-task-m50.js +17 -0
  406. package/dist/plugins/approval-ask-store-file.d.ts +18 -7
  407. package/dist/plugins/approval-ask-store-file.js +37 -14
  408. package/dist/plugins/approval-ask-store-memory.d.ts +12 -4
  409. package/dist/plugins/approval-ask-store-memory.js +24 -10
  410. package/dist/plugins/approval-ask-store-sql.d.ts +39 -20
  411. package/dist/plugins/approval-ask-store-sql.js +41 -10
  412. package/dist/plugins/approval-exemption-skill-m46.d.ts +20 -0
  413. package/dist/plugins/approval-exemption-skill-m46.js +25 -0
  414. package/dist/plugins/approval-exemption-store.d.ts +6 -1
  415. package/dist/plugins/approval-exemption-store.js +14 -0
  416. package/dist/plugins/approval-nonce-store.d.ts +39 -12
  417. package/dist/plugins/approval-nonce-store.js +72 -23
  418. package/dist/plugins/blob-backend.d.ts +2 -0
  419. package/dist/plugins/blob-backend.js +9 -6
  420. package/dist/plugins/caching-session-store.d.ts +13 -1
  421. package/dist/plugins/caching-session-store.js +43 -4
  422. package/dist/plugins/checkpoint-index-columns.d.ts +32 -5
  423. package/dist/plugins/checkpoint-index-columns.js +36 -1
  424. package/dist/plugins/checkpoint-store-face.d.ts +83 -10
  425. package/dist/plugins/checkpoint-store-face.js +18 -1
  426. package/dist/plugins/device-store-sql.js +1 -0
  427. package/dist/plugins/ensure-index.d.ts +13 -1
  428. package/dist/plugins/ensure-index.js +154 -21
  429. package/dist/plugins/ensure-schema-lock-policy.d.ts +0 -15
  430. package/dist/plugins/ensure-schema-lock-policy.js +3 -2
  431. package/dist/plugins/file-run-store.d.ts +63 -23
  432. package/dist/plugins/file-run-store.js +138 -83
  433. package/dist/plugins/host-platform.d.ts +24 -3
  434. package/dist/plugins/host-platform.js +15 -1
  435. package/dist/plugins/image-bake-store-sql.js +2 -0
  436. package/dist/plugins/imported-layer-root-retirement.d.ts +2 -2
  437. package/dist/plugins/k8s-pod-reaper.d.ts +1 -3
  438. package/dist/plugins/k8s-pod-reaper.js +0 -1
  439. package/dist/plugins/leader-run-store-sql.d.ts +22 -0
  440. package/dist/plugins/leader-run-store-sql.js +34 -4
  441. package/dist/plugins/local-checkpoint-store.d.ts +58 -23
  442. package/dist/plugins/local-checkpoint-store.js +195 -76
  443. package/dist/plugins/local-data-dir-modes-m39.js +2 -1
  444. package/dist/plugins/local-docker-capacity.d.ts +93 -0
  445. package/dist/plugins/local-docker-capacity.js +194 -0
  446. package/dist/plugins/local-docker-reaper.d.ts +92 -0
  447. package/dist/plugins/local-docker-reaper.js +102 -0
  448. package/dist/plugins/local-engine-high-water.d.ts +4 -2
  449. package/dist/plugins/local-engine-high-water.js +4 -1
  450. package/dist/plugins/local-session-store.d.ts +358 -125
  451. package/dist/plugins/local-session-store.js +824 -251
  452. package/dist/plugins/local-session-window.d.ts +3 -2
  453. package/dist/plugins/local-session-window.js +3 -2
  454. package/dist/plugins/local-sidecar-quarantine.js +3 -2
  455. package/dist/plugins/local-task-attachment-store.d.ts +18 -1
  456. package/dist/plugins/local-task-attachment-store.js +22 -1
  457. package/dist/plugins/memory-embedder.js +9 -7
  458. package/dist/plugins/memory-engine-pg.d.ts +3 -2
  459. package/dist/plugins/memory-engine-pg.js +14 -5
  460. package/dist/plugins/memory-engine-sql-apply.d.ts +8 -4
  461. package/dist/plugins/memory-engine-sql-apply.js +6 -8
  462. package/dist/plugins/memory-engine-tidb.d.ts +4 -2
  463. package/dist/plugins/memory-engine-tidb.js +11 -2
  464. package/dist/plugins/memory-optout-grant-store-sql.d.ts +1 -1
  465. package/dist/plugins/memory-optout-grant-store-sql.js +3 -3
  466. package/dist/plugins/memory-run-store.d.ts +39 -27
  467. package/dist/plugins/memory-run-store.js +72 -70
  468. package/dist/plugins/one-time-migration-marker.d.ts +10 -0
  469. package/dist/plugins/one-time-migration-marker.js +7 -0
  470. package/dist/plugins/one-time-migrations.d.ts +186 -45
  471. package/dist/plugins/one-time-migrations.js +442 -119
  472. package/dist/plugins/org-delivery-quota-store.js +2 -1
  473. package/dist/plugins/permission-rule-store-file.d.ts +3 -3
  474. package/dist/plugins/permission-rule-store-sql.d.ts +4 -63
  475. package/dist/plugins/permission-rule-store-sql.js +6 -86
  476. package/dist/plugins/pg-pool.d.ts +1 -31
  477. package/dist/plugins/pg-pool.js +16 -7
  478. package/dist/plugins/remote-env-e2b.d.ts +7 -25
  479. package/dist/plugins/remote-env-e2b.js +34 -25
  480. package/dist/plugins/remote-env-host.d.ts +2 -9
  481. package/dist/plugins/remote-env-host.js +34 -22
  482. package/dist/plugins/remote-env-k8s.d.ts +40 -45
  483. package/dist/plugins/remote-env-k8s.js +107 -58
  484. package/dist/plugins/remote-env-local-docker.d.ts +148 -14
  485. package/dist/plugins/remote-env-local-docker.js +367 -72
  486. package/dist/plugins/remote-scratchpad.js +4 -0
  487. package/dist/plugins/retention-deployment.d.ts +49 -17
  488. package/dist/plugins/retention-deployment.js +39 -8
  489. package/dist/plugins/run-preview-m45.d.ts +11 -0
  490. package/dist/plugins/run-preview-m45.js +19 -0
  491. package/dist/plugins/run-store-sql.d.ts +56 -68
  492. package/dist/plugins/run-store-sql.js +127 -116
  493. package/dist/plugins/s3-answer.d.ts +2 -1
  494. package/dist/plugins/sandbox-reaper.d.ts +26 -0
  495. package/dist/plugins/sandbox-reaper.js +2 -0
  496. package/dist/plugins/scenario-prefix-switch-m42.d.ts +54 -0
  497. package/dist/plugins/scenario-prefix-switch-m42.js +55 -0
  498. package/dist/plugins/scheduler-support.d.ts +16 -1
  499. package/dist/plugins/scheduler-support.js +22 -2
  500. package/dist/plugins/schema-consistency.d.ts +42 -9
  501. package/dist/plugins/schema-consistency.js +212 -11
  502. package/dist/plugins/schema-drift-sentence.d.ts +4 -1
  503. package/dist/plugins/schema-drift-sentence.js +4 -4
  504. package/dist/plugins/schema-ensure-legs.d.ts +9 -0
  505. package/dist/plugins/schema-ensure-legs.js +1 -1
  506. package/dist/plugins/schema-indexes.js +3 -0
  507. package/dist/plugins/schema-live-columns.d.ts +14 -5
  508. package/dist/plugins/schema-live-columns.js +10 -10
  509. package/dist/plugins/send-user-file.js +2 -1
  510. package/dist/plugins/session-birth.d.ts +37 -0
  511. package/dist/plugins/session-birth.js +38 -0
  512. package/dist/plugins/session-epoch-anchor.d.ts +40 -12
  513. package/dist/plugins/session-epoch-anchor.js +33 -11
  514. package/dist/plugins/session-ext-table.d.ts +27 -3
  515. package/dist/plugins/session-ext-table.js +19 -6
  516. package/dist/plugins/session-fork.d.ts +15 -1
  517. package/dist/plugins/session-fork.js +3 -0
  518. package/dist/plugins/session-ownership.d.ts +1 -1
  519. package/dist/plugins/session-placement.d.ts +22 -16
  520. package/dist/plugins/session-placement.js +15 -12
  521. package/dist/plugins/session-row-sql.d.ts +12 -0
  522. package/dist/plugins/session-row-sql.js +3 -3
  523. package/dist/plugins/session-run-rollup.d.ts +29 -0
  524. package/dist/plugins/session-run-rollup.js +40 -0
  525. package/dist/plugins/session-store-sql.d.ts +38 -12
  526. package/dist/plugins/session-store-sql.js +130 -30
  527. package/dist/plugins/session-withdraw-sql.d.ts +36 -0
  528. package/dist/plugins/session-withdraw-sql.js +42 -0
  529. package/dist/plugins/shared-memory-store-sql.d.ts +0 -69
  530. package/dist/plugins/shared-memory-store-sql.js +2 -1
  531. package/dist/plugins/shell-sentinel-owner-m48.d.ts +20 -0
  532. package/dist/plugins/shell-sentinel-owner-m48.js +3 -0
  533. package/dist/plugins/snapshot-bucket-presence.d.ts +2 -1
  534. package/dist/plugins/sql-driver.d.ts +1 -1
  535. package/dist/plugins/sql-driver.js +2 -1
  536. package/dist/plugins/sql-errors.d.ts +32 -5
  537. package/dist/plugins/sql-errors.js +55 -7
  538. package/dist/plugins/sql-json-column.d.ts +8 -7
  539. package/dist/plugins/sql-json-column.js +10 -6
  540. package/dist/plugins/store-backend.d.ts +84 -15
  541. package/dist/plugins/store-backend.js +186 -55
  542. package/dist/plugins/store-contracts.d.ts +90 -30
  543. package/dist/plugins/store-contracts.js +22 -1
  544. package/dist/plugins/store-fault.d.ts +28 -2
  545. package/dist/plugins/store-fault.js +20 -2
  546. package/dist/plugins/task-attachment-store.d.ts +15 -3
  547. package/dist/plugins/task-attachment-store.js +22 -9
  548. package/dist/plugins/tidb-pool.js +23 -8
  549. package/dist/plugins/web-search.js +5 -3
  550. package/dist/plugins/workflow-run-store-sql.d.ts +6 -1
  551. package/dist/plugins/workflow-run-store-sql.js +11 -5
  552. package/dist/principal-jwt.d.ts +4 -4
  553. package/dist/principal-jwt.js +20 -5
  554. package/dist/principal-shape.d.ts +41 -0
  555. package/dist/principal-shape.js +19 -0
  556. package/dist/question.d.ts +13 -23
  557. package/dist/question.js +21 -39
  558. package/dist/request-declaration-refusal.d.ts +35 -12
  559. package/dist/request-declaration-refusal.js +21 -9
  560. package/dist/request-form.d.ts +58 -0
  561. package/dist/request-form.js +72 -0
  562. package/dist/request-image-urls.d.ts +8 -2
  563. package/dist/request-image-urls.js +2 -1
  564. package/dist/request-images.d.ts +20 -0
  565. package/dist/request-images.js +59 -0
  566. package/dist/request-key-closure.d.ts +6 -7
  567. package/dist/request-key-closure.js +15 -2
  568. package/dist/resource-suspend.d.ts +7 -16
  569. package/dist/resource-suspend.js +1 -1
  570. package/dist/retired-name-host-notice.d.ts +21 -0
  571. package/dist/retired-name-host-notice.js +12 -0
  572. package/dist/rule-entry-list.d.ts +2 -2
  573. package/dist/rule-entry-list.js +3 -4
  574. package/dist/rule-issue-reading.d.ts +58 -0
  575. package/dist/rule-issue-reading.js +14 -0
  576. package/dist/rules-consent.d.ts +5 -3
  577. package/dist/rules-consent.js +1 -0
  578. package/dist/run-acceptance.d.ts +3 -1
  579. package/dist/run-acceptance.js +3 -0
  580. package/dist/run-local.d.ts +14 -6
  581. package/dist/run-local.js +92 -80
  582. package/dist/run-stale-default.d.ts +7 -0
  583. package/dist/run-stale-default.js +2 -0
  584. package/dist/runs.d.ts +26 -15
  585. package/dist/runs.js +39 -27
  586. package/dist/runtime-caps-resolver.d.ts +21 -6
  587. package/dist/runtime-caps-resolver.js +17 -4
  588. package/dist/runtime-governance.d.ts +2 -2
  589. package/dist/runtime-governance.js +5 -3
  590. package/dist/sealed-key-layout.d.ts +12 -5
  591. package/dist/sealed-key-layout.js +5 -0
  592. package/dist/sealed-key.d.ts +12 -2
  593. package/dist/sealed-key.js +115 -27
  594. package/dist/security.d.ts +128 -158
  595. package/dist/security.js +163 -59
  596. package/dist/sema-config-dir.d.ts +20 -0
  597. package/dist/sema-config-dir.js +25 -0
  598. package/dist/server-secret-env.d.ts +21 -5
  599. package/dist/server-secret-env.js +14 -4
  600. package/dist/session-children-retire.d.ts +7 -5
  601. package/dist/session-children-retire.js +7 -2
  602. package/dist/session-deletion.d.ts +88 -0
  603. package/dist/session-deletion.js +8 -0
  604. package/dist/session-erase.d.ts +145 -0
  605. package/dist/session-erase.js +115 -0
  606. package/dist/session-error-wire.d.ts +5 -5
  607. package/dist/session-error-wire.js +1 -1
  608. package/dist/session-incarnation.d.ts +52 -5
  609. package/dist/session-incarnation.js +19 -2
  610. package/dist/session-policy-wire.d.ts +6 -3
  611. package/dist/session-policy-wire.js +11 -1
  612. package/dist/session-resident-background.d.ts +0 -71
  613. package/dist/session-resident-background.js +4 -3
  614. package/dist/session-row.d.ts +2 -1
  615. package/dist/session-rules-seat.d.ts +12 -0
  616. package/dist/session-rules-seat.js +19 -0
  617. package/dist/session-titler.d.ts +7 -15
  618. package/dist/session-titler.js +1 -1
  619. package/dist/spec-fields.d.ts +57 -3
  620. package/dist/spec-fields.js +72 -51
  621. package/dist/store-posture.d.ts +136 -20
  622. package/dist/store-posture.js +188 -3
  623. package/dist/stored-request-hooks-m20.js +2 -2
  624. package/dist/stores-sql/background-agent-store-sql.d.ts +11 -2
  625. package/dist/stores-sql/background-agent-store-sql.js +73 -20
  626. package/dist/stores-sql/checkpoint-store-sql.d.ts +33 -28
  627. package/dist/stores-sql/checkpoint-store-sql.js +75 -44
  628. package/dist/stores-sql/mailbox-store-sql.d.ts +7 -4
  629. package/dist/stores-sql/mailbox-store-sql.js +31 -32
  630. package/dist/stores-sql/pg-session-storage.d.ts +7 -5
  631. package/dist/stores-sql/pg-session-storage.js +54 -46
  632. package/dist/stores-sql/retention-store-sql.d.ts +87 -19
  633. package/dist/stores-sql/retention-store-sql.js +92 -27
  634. package/dist/stores-sql/session-policy-store-sql.d.ts +32 -10
  635. package/dist/stores-sql/session-policy-store-sql.js +44 -36
  636. package/dist/stores-sql/session-write-hooks.d.ts +12 -6
  637. package/dist/stores-sql/tidb-session-storage.d.ts +4 -4
  638. package/dist/stores-sql/tidb-session-storage.js +13 -8
  639. package/dist/stores-sql/tidb-session-store.d.ts +36 -17
  640. package/dist/stores-sql/tidb-session-store.js +69 -39
  641. package/dist/stores-sql/windowed-session-storage.d.ts +5 -0
  642. package/dist/stores-sql/windowed-session-storage.js +9 -0
  643. package/dist/submission-exit.d.ts +50 -0
  644. package/dist/submission-exit.js +108 -0
  645. package/dist/task-a2a.d.ts +1 -1
  646. package/dist/task-a2a.js +3 -3
  647. package/dist/task-cwd.d.ts +20 -0
  648. package/dist/task-cwd.js +8 -0
  649. package/dist/task-mcp.d.ts +1 -1
  650. package/dist/task-mcp.js +3 -3
  651. package/dist/task-settings.d.ts +14 -10
  652. package/dist/task-settings.js +18 -7
  653. package/dist/terminal.d.ts +25 -43
  654. package/dist/terminal.js +31 -11
  655. package/dist/tool-approval.d.ts +131 -129
  656. package/dist/tool-approval.js +189 -193
  657. package/dist/trace/core-keyset-guard.d.ts +13 -6
  658. package/dist/trace/core-vocab-wire.d.ts +95 -0
  659. package/dist/trace/core-vocab-wire.js +15 -0
  660. package/dist/trace/exit-seat.d.ts +30 -4
  661. package/dist/trace/exit-seat.js +40 -36
  662. package/dist/trace/extension-call-face.d.ts +3 -2
  663. package/dist/trace/extension-call-face.js +3 -1
  664. package/dist/trace/ledger-events.d.ts +4 -7
  665. package/dist/trace/ledger-sink.d.ts +1 -30
  666. package/dist/trace/ledger-sink.js +0 -11
  667. package/dist/trace/model-segment.d.ts +5 -5
  668. package/dist/trace/model-segment.js +5 -5
  669. package/dist/trace/project.d.ts +55 -42
  670. package/dist/trace/project.js +52 -19
  671. package/dist/trace/redact.d.ts +123 -27
  672. package/dist/trace/redact.js +880 -260
  673. package/dist/trace/self-minted-wire.d.ts +487 -19
  674. package/dist/trace/self-minted-wire.js +172 -23
  675. package/dist/trace/wire-projection-faces.d.ts +5 -6
  676. package/dist/trace/wire-projection-faces.js +2 -2
  677. package/dist/upstream-body.d.ts +23 -0
  678. package/dist/upstream-body.js +16 -0
  679. package/dist/url-refusal.d.ts +3 -3
  680. package/dist/url-refusal.js +11 -4
  681. package/dist/user-authored-text.d.ts +1 -1
  682. package/dist/user-input-ledger.d.ts +7 -8
  683. package/dist/user-input-ledger.js +1 -1
  684. package/dist/web-admin-client/apply-effective.d.ts +6 -3
  685. package/dist/web-admin-client/apply-effective.js +13 -16
  686. package/dist/web-admin-client/apply-ledger.d.ts +16 -7
  687. package/dist/web-admin-client/apply-ledger.js +5 -2
  688. package/dist/web-admin-client/center-request.d.ts +2 -2
  689. package/dist/web-admin-client/center-request.js +15 -15
  690. package/dist/web-admin-client/effective-keys.d.ts +1 -1
  691. package/dist/web-admin-client/effective-keys.js +1 -1
  692. package/dist/web-admin-client/entry-metadata.d.ts +8 -0
  693. package/dist/web-admin-client/entry-metadata.js +13 -0
  694. package/dist/web-admin-client/http-client.d.ts +1 -1
  695. package/dist/web-admin-client/http-client.js +23 -4
  696. package/dist/web-admin-client/mcp-revocation.d.ts +1 -1
  697. package/dist/web-admin-client/mcp-revocation.js +2 -1
  698. package/dist/web-admin-client/read-warnings.d.ts +1 -0
  699. package/dist/web-admin-client/read-warnings.js +1 -0
  700. package/dist/web-admin-client/restart-signal.js +8 -4
  701. package/dist/web-admin-client/skills-mcp.d.ts +2 -2
  702. package/dist/web-admin-client/types.d.ts +1 -2
  703. package/dist/workspace-space.d.ts +3 -2
  704. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +4 -4
  705. package/package.json +6 -3
  706. package/scripts/drain-check-local.mjs +118 -147
  707. package/scripts/drain-check.mysql.sql +22 -2
  708. package/scripts/drain-check.pg.sql +22 -2
  709. package/wire-changes/server@7.148.0.json +1517 -0
  710. package/dist/http/memory-control-plane-corrupt-reply.d.ts +0 -25
  711. package/dist/http/memory-control-plane-corrupt-reply.js +0 -19
  712. package/dist/http/memory-layer-reply.d.ts +0 -30
  713. package/dist/http/memory-layer-reply.js +0 -24
  714. package/dist/lsp/e2b-bridge.d.ts +0 -57
  715. package/dist/lsp/e2b-bridge.js +0 -139
  716. package/dist/lsp/e2b-manager.d.ts +0 -93
  717. package/dist/lsp/e2b-manager.js +0 -178
  718. package/dist/lsp/lsp-frames.d.ts +0 -14
  719. package/dist/lsp/lsp-frames.js +0 -25
  720. package/dist/lsp/manager.d.ts +0 -129
  721. package/dist/lsp/manager.js +0 -127
  722. package/dist/lsp/types.d.ts +0 -12
  723. package/dist/lsp/types.js +0 -2
  724. package/dist/lsp/ws-transport.d.ts +0 -40
  725. package/dist/lsp/ws-transport.js +0 -210
@@ -1,4 +1,5 @@
1
1
  import { mysqlDriver, pgDriver, dialectJsonEncoder } from "./sql-driver.js";
2
+ import { retentionIdSet } from "./retention-sql.js";
2
3
  import { ASK_TERMINAL, canAskTransition } from "../approval-ask-machine.js";
3
4
  import { DECIDED_VIA } from "@sema-agent/core";
4
5
  import { APPROVAL_ENDING_CAUSES, askRowEndingCause, askRowParkTrigger } from "../approval-deny-reasons.js";
@@ -119,15 +120,26 @@ export function projectAskTerminalClaimTruth(row) {
119
120
  export function askRowOnCall(row, call) {
120
121
  return row.taskId === call.taskId && row.legKey === call.legKey && row.toolCallId === call.toolCallId && row.sourceSessionId === call.sourceSessionId;
121
122
  }
122
- export function askOwnerAdmits(owner, principal) {
123
- return owner === null || owner === principal;
124
- }
125
123
  export function askRowCarriesOwner(row, owner) {
126
124
  return row !== null && row.owner === owner;
127
125
  }
128
126
  export function projectDecideReading(row, owner) {
129
127
  return askRowCarriesOwner(row, owner) ? row : null;
130
128
  }
129
+ export function askAttachedToSession(row, sessionId) {
130
+ return row.taskId !== sessionId && (row.sessionId === sessionId || row.sourceSessionId === sessionId);
131
+ }
132
+ const ASK_SESSION_CELLS = ["session_id", "source_task_id"];
133
+ export async function deleteSessionApprovalRows(exec, dialect, ids) {
134
+ if (ids.length === 0)
135
+ return;
136
+ for (const cell of ASK_SESSION_CELLS) {
137
+ const inAsk = retentionIdSet(dialect, `a.${cell}`, ids, 1);
138
+ await exec.query(`DELETE FROM ${APPROVAL_BATCH_TABLE} WHERE batch_id IN (SELECT a.batch_id FROM ${APPROVAL_ASK_TABLE} a WHERE ${inAsk.sql} AND a.${cell} <> a.task_id)`, inAsk.params);
139
+ const own = retentionIdSet(dialect, cell, ids, 1);
140
+ await exec.query(`DELETE FROM ${APPROVAL_ASK_TABLE} WHERE ${own.sql} AND ${cell} <> task_id`, own.params);
141
+ }
142
+ }
131
143
  export const APPROVAL_ASK_TABLE = "approval_ask";
132
144
  export const APPROVAL_ASK_EXECUTION_LANE_COLUMN = {
133
145
  mysql: "execution_lane VARCHAR(32) NOT NULL DEFAULT ''",
@@ -235,7 +247,9 @@ export const TIDB_APPROVAL_ASK_STATEMENTS = [
235
247
  -- 表尚未进生产 ⇒ 此刻加索引零迁移成本,晚一车加就要动生产表。
236
248
  KEY idx_ask_session_state (session_id, state),
237
249
  KEY idx_ask_batch (batch_id),
238
- KEY idx_ask_state (state)
250
+ KEY idx_ask_state (state),
251
+ -- idx_ask_source_session:删会话的审批腿按发问格选行(deleteSessionApprovalRows);宿主格走上面 idx_ask_session_state 的前缀。
252
+ KEY idx_ask_source_session (source_task_id)
239
253
  ) COLLATE utf8mb4_bin`,
240
254
  ];
241
255
  export async function ensureTiDBApprovalAskSchema(pool) {
@@ -244,10 +258,12 @@ export async function ensureTiDBApprovalAskSchema(pool) {
244
258
  }
245
259
  export const APPROVAL_ASK_INDEXES = [
246
260
  { table: `${APPROVAL_BATCH_TABLE}`, name: "idx_batch_task", columns: ["task_id"] },
261
+ { table: `${APPROVAL_ASK_TABLE}`, name: "uq_approval_ask_idem", columns: ["task_id", "idempotency_key"], unique: true },
247
262
  { table: `${APPROVAL_ASK_TABLE}`, name: "idx_ask_task_state", columns: ["task_id", "state"] },
248
263
  { table: `${APPROVAL_ASK_TABLE}`, name: "idx_ask_session_state", columns: ["session_id", "state"] },
249
264
  { table: `${APPROVAL_ASK_TABLE}`, name: "idx_ask_batch", columns: ["batch_id"] },
250
265
  { table: `${APPROVAL_ASK_TABLE}`, name: "idx_ask_state", columns: ["state"] },
266
+ { table: `${APPROVAL_ASK_TABLE}`, name: "idx_ask_source_session", columns: ["source_task_id"] },
251
267
  ];
252
268
  export async function ensurePgApprovalAskSchema(q) {
253
269
  await q(`CREATE TABLE IF NOT EXISTS ${APPROVAL_BATCH_TABLE} (
@@ -776,9 +792,9 @@ export class SqlApprovalAskStore {
776
792
  const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = ? AND leg_key = ? AND tool_call_id = ? AND source_task_id = ? ORDER BY created_at_ms ASC, ask_id ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = $1 AND leg_key = $2 AND tool_call_id = $3 AND source_task_id = $4 ORDER BY created_at_ms ASC, ask_id ASC`), [call.taskId, call.legKey, call.toolCallId, call.sourceSessionId]);
777
793
  return rows.map(mapAskRow).filter((r) => askRowOnCall(r, call));
778
794
  }
779
- async listParkingBySession(sessionId) {
780
- const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = ? AND state = 'PARKING' ORDER BY created_at_ms ASC, ask_id ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = $1 AND state = 'PARKING' ORDER BY created_at_ms ASC, ask_id ASC`), [sessionId]);
781
- return rows.map(mapAskRow).filter((r) => r.sessionId === sessionId);
795
+ async listParkingBySourceSession(sourceSessionId) {
796
+ const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE source_task_id = ? AND state = 'PARKING' ORDER BY created_at_ms ASC, ask_id ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE source_task_id = $1 AND state = 'PARKING' ORDER BY created_at_ms ASC, ask_id ASC`), [sourceSessionId]);
797
+ return rows.map(mapAskRow).filter((r) => r.sourceSessionId === sourceSessionId);
782
798
  }
783
799
  async getAsk(askId) {
784
800
  const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE ask_id = ?`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE ask_id = $1`), [
@@ -808,9 +824,24 @@ export class SqlApprovalAskStore {
808
824
  const res = await this.db.query(`UPDATE ${APPROVAL_ASK_TABLE} SET ${setSql}, rev = rev + 1 WHERE ask_id = ${askIdPh} AND provisional = ${provPh} AND state = ${fromPh}`, [...vals, askId, 1, from]);
809
825
  return res.affected === 1;
810
826
  }
811
- async deleteByTask(taskId) {
812
- await this.db.query(this.q(`DELETE FROM ${APPROVAL_ASK_TABLE} WHERE task_id = ?`, `DELETE FROM ${APPROVAL_ASK_TABLE} WHERE task_id = $1`), [taskId]);
813
- await this.db.query(this.q(`DELETE FROM ${APPROVAL_BATCH_TABLE} WHERE task_id = ?`, `DELETE FROM ${APPROVAL_BATCH_TABLE} WHERE task_id = $1`), [taskId]);
827
+ async deleteBySession(sessionId) {
828
+ const conn = await this.db.connect();
829
+ try {
830
+ await conn.begin();
831
+ await deleteSessionApprovalRows(conn, this.db.dialect, [sessionId]);
832
+ await conn.commit();
833
+ }
834
+ catch (err) {
835
+ try {
836
+ await conn.rollback();
837
+ }
838
+ catch {
839
+ }
840
+ throw err;
841
+ }
842
+ finally {
843
+ conn.release();
844
+ }
814
845
  }
815
846
  async reapSettledAsks(cutoffMs, limit, keepAnchors) {
816
847
  assertReapBounds(cutoffMs, limit);
@@ -0,0 +1,20 @@
1
+ import type { FileApprovalExemptionStore } from "./approval-exemption-store.js";
2
+ /** 本条在标记表(`one-time-migration-marker.ts`)里的那一行的键。 */
3
+ export declare const LEGACY_SKILL_EXEMPTION_MARKER_ID = "M46";
4
+ /** local 车道的标记文件(数据根下,文件名即本条;正文 = T0 的 ISO 时刻一行,人可直接读)。 */
5
+ export declare const LOCAL_LEGACY_SKILL_EXEMPTION_MARKER_FILE = "one-time-migration-M46.marker";
6
+ /** 被删行的 wire 工具名 —— 引擎 `Skill` 工具的名字,core 导出(core 改名 ⇒ 谓词跟着走,不会静默指向空气)。 */
7
+ export declare const LEGACY_SKILL_EXEMPTION_TOOL_NAME: string;
8
+ /** SQL 腿一页的会话数(键集分批:`session_id` 升序,一页一次读、一句删)。 */
9
+ export declare const LEGACY_SKILL_EXEMPTION_PAGE = 500;
10
+ /**
11
+ * local 腿的 T0:标记文件在 ⇒ 读它(正文 = T0 的 ISO 时刻);不在 ⇒ **先**原子落盘再返回(`required`:标记没落盘就不算开始过 —— 写不进 ⇒ 抛,起服拒,下一次起服重来,一行没删)。
12
+ * 标记文件在而读不出(正文不是时刻 —— 手改过 / 写坏了)⇒ **响亮拒启**,点名文件与出路:不替人猜一个 T0(猜晚了会多删、猜早了会少删)。出路 = 删掉那只文件再起服(本步取新的 T0)。
13
+ */
14
+ export declare function legacySkillExemptionCutoffLocal(markerPath: string, now?: () => number): number;
15
+ /**
16
+ * 🔴 M46 的 local 腿(唯一调用点 `LocalBackend.runOneTimeMigrations`):T0 先落盘,再对 File 店删「首次放行早于 T0 的 `Skill` 行」(墓碑,与按名撤销同形)。返回删了几行。
17
+ * 数据根独占(根锁):同一只根上没有第二个起服者,也没有更早版本的副本与本次并跑。
18
+ */
19
+ export declare function dropLocalLegacySkillExemptionsM46(markerPath: string, store: Pick<FileApprovalExemptionStore, "dropToolRowsCreatedBeforeM46">): number;
20
+ //# sourceMappingURL=approval-exemption-skill-m46.d.ts.map
@@ -0,0 +1,25 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { SKILL_TOOL_NAME } from "@sema-agent/core";
3
+ import { atomicWriteFileSync } from "./owner-only-file-mode.js";
4
+ import { StoreBootRefusalError } from "./store-contracts.js";
5
+ export const LEGACY_SKILL_EXEMPTION_MARKER_ID = "M46";
6
+ export const LOCAL_LEGACY_SKILL_EXEMPTION_MARKER_FILE = "one-time-migration-M46.marker";
7
+ export const LEGACY_SKILL_EXEMPTION_TOOL_NAME = SKILL_TOOL_NAME;
8
+ export const LEGACY_SKILL_EXEMPTION_PAGE = 500;
9
+ export function legacySkillExemptionCutoffLocal(markerPath, now = Date.now) {
10
+ if (existsSync(markerPath)) {
11
+ const marked = Date.parse(readFileSync(markerPath, "utf8").trim());
12
+ if (!Number.isFinite(marked)) {
13
+ throw new StoreBootRefusalError(`one-time migration ${LEGACY_SKILL_EXEMPTION_MARKER_ID}: ${markerPath} exists but does not hold a readable cutoff time (expected one ISO time, e.g. 2026-11-06T09:00:00.000Z); ` +
14
+ `refusing to start rather than guess which stored Skill exemption rows predate the upgrade. Delete the file and restart: the step then records a new cutoff (now) and deletes the stored Skill exemption rows older than it.`);
15
+ }
16
+ return marked;
17
+ }
18
+ const t0 = now();
19
+ atomicWriteFileSync(markerPath, `${new Date(t0).toISOString()}\n`, { durability: "required" });
20
+ return t0;
21
+ }
22
+ export function dropLocalLegacySkillExemptionsM46(markerPath, store) {
23
+ return store.dropToolRowsCreatedBeforeM46(LEGACY_SKILL_EXEMPTION_TOOL_NAME, legacySkillExemptionCutoffLocal(markerPath));
24
+ }
25
+ //# sourceMappingURL=approval-exemption-skill-m46.js.map
@@ -66,7 +66,7 @@ export declare class FileApprovalExemptionStore implements ApprovalExemptionStor
66
66
  /** [ref]: sanitized session key → that session log's gate (only files that replayed a bad record are listed). */
67
67
  private readonly corruptGates;
68
68
  private readonly warn;
69
- /** @param opts.warn corrupt-read disclosure seat (`LocalBackend` wires `discloseWarn`; absent ⇒ the owner falls back to `console.warn`, never to silence). */
69
+ /** @param opts.warn corrupt-read disclosure seat (`LocalBackend` wires `discloseWarn`; absent ⇒ the owner falls back to the log seam's text exit `writeLogText`, never to silence). */
70
70
  constructor(root: string, opts?: {
71
71
  warn?: Logger["warn"];
72
72
  });
@@ -80,6 +80,11 @@ export declare class FileApprovalExemptionStore implements ApprovalExemptionStor
80
80
  has(sessionId: string, toolName: string): Promise<boolean>;
81
81
  list(sessionId: string): Promise<ApprovalExemptionRow[]>;
82
82
  revoke(sessionId: string, toolName: string): Promise<boolean>;
83
+ /**
84
+ * 一次性迁移 M46 的 local 腿(窗关随 M46 删;登记表 `removal` 点名):每只会话上 `toolName` 那一行的**首次放行**早于 `beforeMs` 的,追加一条墓碑(与 {@link revoke} 同形、fsync)并出索引。
85
+ * 返回删了几行。日志已被判坏的会话不碰(它的 `has` / `list` 本来就拒;删会话即清闸)。幂等:删过的行不在索引里,第二跑零命中。
86
+ */
87
+ dropToolRowsCreatedBeforeM46(toolName: string, beforeMs: number): number;
83
88
  deleteBySession(sessionId: string): Promise<number>;
84
89
  /** Release every open append-log fd (LocalBackend.close → graceful-restart re-open). */
85
90
  dispose(): void;
@@ -212,6 +212,20 @@ export class FileApprovalExemptionStore {
212
212
  m.delete(toolName);
213
213
  return true;
214
214
  }
215
+ dropToolRowsCreatedBeforeM46(toolName, beforeMs) {
216
+ let dropped = 0;
217
+ for (const [key, m] of this.bySession) {
218
+ if (this.corruptGates.has(key))
219
+ continue;
220
+ const row = m.get(toolName);
221
+ if (row === undefined || !(row.createdAt < beforeMs))
222
+ continue;
223
+ this.logFor(key).append({ toolName, grantedBy: null, ts: new Date().toISOString(), revoked: true }, true);
224
+ m.delete(toolName);
225
+ dropped += 1;
226
+ }
227
+ return dropped;
228
+ }
215
229
  async deleteBySession(sessionId) {
216
230
  const key = sanitizePathComponent(sessionId);
217
231
  const removed = this.bySession.get(key)?.size ?? 0;
@@ -1,7 +1,7 @@
1
1
  import type { Pool as MysqlPool } from "mysql2/promise";
2
2
  import type { Pool as PgPool } from "pg";
3
3
  import { type SqlDriver } from "./sql-driver.js";
4
- import type { Logger } from "../observability/logger.js";
4
+ import { type Logger } from "../observability/logger.js";
5
5
  /** 表名(单数形;`test/schema-naming-invariants.test.ts` 的闭集词表钉着)。 */
6
6
  export declare const APPROVAL_NONCE_TABLE = "approval_nonce";
7
7
  /**
@@ -10,6 +10,12 @@ export declare const APPROVAL_NONCE_TABLE = "approval_nonce";
10
10
  * 设限是**保守**方向(星平面字符在 JS 里算 2、在两个引擎的 VARCHAR 里算 1),永远不会撞到列宽。
11
11
  */
12
12
  export declare const MAX_APPROVAL_NONCE_CHARS = 190;
13
+ /** 时间地板的表名(单行表,与 `retention_lease` 同形:`singleton` 恒 `'x'`)。判据见头注「时间地板」。 */
14
+ export declare const APPROVAL_NONCE_FLOOR_TABLE = "approval_nonce_floor";
15
+ /** 原始钟低于地板(钟被往回拨)时那一行 warn 的事件名。字段:`rolledBackMs`(地板 − 原始钟)/ `floorMs` / `clockMs`(原始钟读数)/ `store`(哪条腿)。 */
16
+ export declare const APPROVAL_NONCE_CLOCK_ROLLBACK_EVENT = "approval_nonce_clock_rollback";
17
+ /** 回拨 warn 的落点;店没接日志座时退回日志出口接缝的缺省 logger(不退回沉默)。 */
18
+ export type ApprovalNonceWarn = Logger["warn"];
13
19
  export interface ApprovalNonceStore {
14
20
  /**
15
21
  * **这只店为它的记录计时的那口钟**(epoch ms)—— 见头注「到期 —— 一口钟」。
@@ -17,9 +23,8 @@ export interface ApprovalNonceStore {
17
23
  * 它是消费记录这条命上**唯一**的参照:受理窗的判定、落地后的复核、到期清扫三处全读它,于是
18
24
  * 「还受理 ⇒ 记录还在」是结构性的,不靠「两台副本的钟差不多」这条没人声明过的假设。
19
25
  *
20
- * ⚠️ **要求:单调不减**。同源只挡「两只钟各走各的」,挡不住「这一只往回走」—— 钟回拨会让一条已被
21
- * 清扫的记录所对应的证明重新过验签(头注「由构造」那段的残余,🚧 见 `approval-nonce-store.test.ts`)。
22
- * 现役三实现都**不**自己强制这一条(Memory/File = `Date.now()`,SQL = 库钟),登记在案。
26
+ * 🔴 **由构造不低于地板**(头注「时间地板」):答 `max(原始钟, 地板)`。原始钟低于地板 ⇒ 答地板 + 一行
27
+ * {@link APPROVAL_NONCE_CLOCK_ROLLBACK_EVENT} warn(点名回拨量)。于是三处判决都不会读到「已删记录的到期时刻之前」的钟。
23
28
  * 🔴 读不出来 ⇒ **响亮抛**([ref] fail-closed):调用方必须把它当不确定失败,**绝不**掉回本地墙钟。
24
29
  */
25
30
  nowMs(): Promise<number>;
@@ -30,7 +35,8 @@ export interface ApprovalNonceStore {
30
35
  */
31
36
  consume(sessionId: string, nonce: string, expiresAtMs: number): Promise<boolean>;
32
37
  /**
33
- * GC:删掉 `expires_at_ms <= ` **{@link nowMs}** 的记录,返回删除行数(维护 tick 调)。
38
+ * GC:读一次 **{@link nowMs}** → 把地板抬到这一读数(**先落地**)→ 删掉 `expires_at_ms <=` 这一读数的记录,返回删除行数(维护 tick 调)。
39
+ * 地板的唯一写者:行不会在已落地的地板低于它的到期时刻时消失,中途崩溃只留下「地板已抬、行还在」(下一拍再删)。
34
40
  *
35
41
  * 🔴 **一个时钟入参都没有**,而且这不是省事:形参会让删除线由**跑清理的那台副本**说了算,而它跟
36
42
  * 验签那台不是同一口钟 —— 那正是本店要消灭的那条依赖(与票据店 [ref] 删掉 `now: () => number`
@@ -41,24 +47,42 @@ export interface ApprovalNonceStore {
41
47
  }
42
48
  export declare class SqlApprovalNonceStore implements ApprovalNonceStore {
43
49
  private readonly db;
44
- constructor(db: SqlDriver);
50
+ private readonly warn;
51
+ /** @param opts.warn 回拨 warn 的落点(缺席 ⇒ 日志出口接缝的缺省 logger,不退回沉默)。 */
52
+ constructor(db: SqlDriver, opts?: {
53
+ readonly warn?: ApprovalNonceWarn;
54
+ });
45
55
  private q;
46
- /** 库钟({@link sqlDbNowMs})—— 一组无状态副本唯一共享的那口钟。读不出 ⇒ 响亮抛。 */
56
+ /**
57
+ * 店钟 = max(库钟, 地板)。库钟({@link SQL_DB_NOW_MS})是一组无状态副本唯一共享的那口钟;地板与它**同一条语句**读出(两条语句之间
58
+ * 一次清扫会把地板抬到第一读之后,于是一次正常的读也会被报成回拨)。没有地板行 = 这只店从没删过记录。读不出 ⇒ 响亮抛。
59
+ */
47
60
  nowMs(): Promise<number>;
48
61
  consume(sessionId: string, nonce: string, expiresAtMs: number): Promise<boolean>;
49
62
  reapExpired(): Promise<number>;
50
63
  }
51
64
  /** MySQL 协议腿的构造绑定(与兄弟店同形:类名/构造元数不变,消费方不必动)。 */
52
65
  export declare class TiDBApprovalNonceStore extends SqlApprovalNonceStore {
53
- constructor(pool: MysqlPool);
66
+ constructor(pool: MysqlPool, opts?: {
67
+ readonly warn?: ApprovalNonceWarn;
68
+ });
54
69
  }
55
70
  /** PostgreSQL 腿的构造绑定。 */
56
71
  export declare class PgApprovalNonceStore extends SqlApprovalNonceStore {
57
- constructor(pool: PgPool);
72
+ constructor(pool: PgPool, opts?: {
73
+ readonly warn?: ApprovalNonceWarn;
74
+ });
58
75
  }
59
76
  export declare class MemoryApprovalNonceStore implements ApprovalNonceStore {
60
77
  private readonly rows;
61
- /** 单进程腿:店 = 这个进程,所以店钟就是本进程的墙钟(验签、复核、清扫本来就同一只钟,无第二口)。 */
78
+ /** 时间地板(头注「时间地板」):进程内即可 —— 店随进程死,它保护的记录同亡。缺席 = 从没删过。 */
79
+ private floorMs;
80
+ private readonly warn;
81
+ /** @param opts.warn 回拨 warn 的落点(缺席 ⇒ 日志出口接缝的缺省 logger)。 */
82
+ constructor(opts?: {
83
+ readonly warn?: ApprovalNonceWarn;
84
+ });
85
+ /** 单进程腿:店 = 这个进程,所以原始钟就是本进程的墙钟(验签、复核、清扫本来就同一只钟,无第二口);店钟 = 它与地板取大。 */
62
86
  nowMs(): Promise<number>;
63
87
  consume(sessionId: string, nonce: string, expiresAtMs: number): Promise<boolean>;
64
88
  reapExpired(): Promise<number>;
@@ -91,12 +115,15 @@ export declare class FileApprovalNonceStore implements ApprovalNonceStore {
91
115
  private log;
92
116
  /** [ref]:本账的损坏闸(见类注)。 */
93
117
  private readonly gate;
94
- /** @param opts.warn 腐读披露座(`LocalBackend` 接 `discloseWarn`;缺席 ⇒ 属主退回 `console.warn`,不退回沉默)。 */
118
+ /** 时间地板(头注「时间地板」):重放时取账里的地板行,每次压实与幸存行一起写回。缺席 = 这本账从没被清扫过。 */
119
+ private floorMs;
120
+ private readonly warn;
121
+ /** @param opts.warn 腐读披露座与回拨 warn 的落点(`LocalBackend` 接 `discloseWarn`;缺席 ⇒ 日志出口接缝的缺省出口,不退回沉默)。 */
95
122
  constructor(root: string, opts?: {
96
123
  warn?: Logger["warn"];
97
124
  });
98
125
  private logFor;
99
- /** local 车道:店 = 这台机器上的这个数据根,所以店钟就是本进程的墙钟(理由同 Memory 腿)。 */
126
+ /** local 车道:店 = 这台机器上的这个数据根,所以原始钟就是本进程的墙钟(理由同 Memory 腿);店钟 = 它与地板取大(地板活过重启)。 */
100
127
  nowMs(): Promise<number>;
101
128
  consume(sessionId: string, nonce: string, expiresAtMs: number): Promise<boolean>;
102
129
  reapExpired(): Promise<number>;
@@ -1,20 +1,48 @@
1
1
  import { join } from "node:path";
2
2
  import { atomicWriteFile, ensureDir, AppendLog } from "@sema-agent/core";
3
- import { mysqlDriver, pgDriver, sqlDbNowMs, SQL_DB_NOW_MS } from "./sql-driver.js";
3
+ import { mysqlDriver, pgDriver, SQL_DB_NOW_MS } from "./sql-driver.js";
4
4
  import { isDupKeyError } from "./sql-errors.js";
5
5
  import { replayJsonlGuarded } from "../observability/corrupt-read-seat.js";
6
+ import { createLogger } from "../observability/logger.js";
6
7
  export const APPROVAL_NONCE_TABLE = "approval_nonce";
7
8
  export const MAX_APPROVAL_NONCE_CHARS = 190;
9
+ export const APPROVAL_NONCE_FLOOR_TABLE = "approval_nonce_floor";
10
+ export const APPROVAL_NONCE_CLOCK_ROLLBACK_EVENT = "approval_nonce_clock_rollback";
11
+ let seamLogger;
12
+ const warnToLogSeam = (msg, fields) => (seamLogger ??= createLogger()).warn(msg, fields);
13
+ function storeClockOf(rawMs, floorMs, store, warn) {
14
+ if (floorMs === undefined || rawMs >= floorMs)
15
+ return rawMs;
16
+ warn(APPROVAL_NONCE_CLOCK_ROLLBACK_EVENT, {
17
+ store,
18
+ rolledBackMs: floorMs - rawMs,
19
+ floorMs,
20
+ clockMs: rawMs,
21
+ note: "the approval-nonce store's clock reads below the line it already deleted consumption records under (the clock was stepped back: an NTP step, a failover to a lagging host, or another database node answering) — " +
22
+ "the store answers that line instead, so proofs that expired before it stay refused; check time sync on the database host (SQL backends) or on this host (local lane)",
23
+ });
24
+ return floorMs;
25
+ }
8
26
  export class SqlApprovalNonceStore {
9
27
  db;
10
- constructor(db) {
28
+ warn;
29
+ constructor(db, opts) {
11
30
  this.db = db;
31
+ this.warn = opts?.warn ?? warnToLogSeam;
12
32
  }
13
33
  q(mysql, pg) {
14
34
  return this.db.dialect === "mysql" ? mysql : pg;
15
35
  }
16
36
  async nowMs() {
17
- return sqlDbNowMs(this.db, APPROVAL_NONCE_TABLE);
37
+ const { rows } = await this.db.query(this.q(`SELECT ${SQL_DB_NOW_MS.mysql} AS db_now_ms, (SELECT floor_ms FROM ${APPROVAL_NONCE_FLOOR_TABLE} WHERE singleton = 'x') AS floor_ms`, `SELECT ${SQL_DB_NOW_MS.pg} AS db_now_ms, (SELECT floor_ms FROM ${APPROVAL_NONCE_FLOOR_TABLE} WHERE singleton = 'x') AS floor_ms`), []);
38
+ const raw = Number(rows[0]?.["db_now_ms"] ?? Number.NaN);
39
+ if (!Number.isFinite(raw))
40
+ throw new Error(`${APPROVAL_NONCE_TABLE}: the database clock came back unreadable (${String(rows[0]?.["db_now_ms"])})`);
41
+ const floorCell = rows[0]?.["floor_ms"];
42
+ const floor = floorCell === null || floorCell === undefined ? undefined : Number(floorCell);
43
+ if (floor !== undefined && !Number.isFinite(floor))
44
+ throw new Error(`${APPROVAL_NONCE_FLOOR_TABLE}: the time floor came back unreadable (${String(floorCell)})`);
45
+ return storeClockOf(raw, floor, "sql", this.warn);
18
46
  }
19
47
  async consume(sessionId, nonce, expiresAtMs) {
20
48
  try {
@@ -28,25 +56,32 @@ export class SqlApprovalNonceStore {
28
56
  }
29
57
  }
30
58
  async reapExpired() {
31
- const res = await this.db.query(this.q(`DELETE FROM ${APPROVAL_NONCE_TABLE} WHERE expires_at_ms <= ${SQL_DB_NOW_MS.mysql}`, `DELETE FROM ${APPROVAL_NONCE_TABLE} WHERE expires_at_ms <= ${SQL_DB_NOW_MS.pg}`), []);
59
+ const line = await this.nowMs();
60
+ await this.db.query(this.q(`INSERT INTO ${APPROVAL_NONCE_FLOOR_TABLE} (singleton, floor_ms) VALUES ('x', ?) ON DUPLICATE KEY UPDATE floor_ms = GREATEST(floor_ms, VALUES(floor_ms))`, `INSERT INTO ${APPROVAL_NONCE_FLOOR_TABLE} (singleton, floor_ms) VALUES ('x', $1) ON CONFLICT (singleton) DO UPDATE SET floor_ms = GREATEST(${APPROVAL_NONCE_FLOOR_TABLE}.floor_ms, EXCLUDED.floor_ms)`), [line]);
61
+ const res = await this.db.query(this.q(`DELETE FROM ${APPROVAL_NONCE_TABLE} WHERE expires_at_ms <= ?`, `DELETE FROM ${APPROVAL_NONCE_TABLE} WHERE expires_at_ms <= $1`), [line]);
32
62
  return res.affected;
33
63
  }
34
64
  }
35
65
  export class TiDBApprovalNonceStore extends SqlApprovalNonceStore {
36
- constructor(pool) {
37
- super(mysqlDriver(pool));
66
+ constructor(pool, opts) {
67
+ super(mysqlDriver(pool), opts);
38
68
  }
39
69
  }
40
70
  export class PgApprovalNonceStore extends SqlApprovalNonceStore {
41
- constructor(pool) {
42
- super(pgDriver(pool));
71
+ constructor(pool, opts) {
72
+ super(pgDriver(pool), opts);
43
73
  }
44
74
  }
45
75
  const keyOf = (sessionId, nonce) => JSON.stringify([sessionId, nonce]);
46
76
  export class MemoryApprovalNonceStore {
47
77
  rows = new Map();
78
+ floorMs;
79
+ warn;
80
+ constructor(opts) {
81
+ this.warn = opts?.warn ?? warnToLogSeam;
82
+ }
48
83
  async nowMs() {
49
- return Date.now();
84
+ return storeClockOf(Date.now(), this.floorMs, "memory", this.warn);
50
85
  }
51
86
  async consume(sessionId, nonce, expiresAtMs) {
52
87
  const k = keyOf(sessionId, nonce);
@@ -56,10 +91,11 @@ export class MemoryApprovalNonceStore {
56
91
  return true;
57
92
  }
58
93
  async reapExpired() {
59
- const now = await this.nowMs();
94
+ const line = await this.nowMs();
95
+ this.floorMs = this.floorMs === undefined ? line : Math.max(this.floorMs, line);
60
96
  let n = 0;
61
97
  for (const [k, exp] of this.rows) {
62
- if (exp <= now) {
98
+ if (exp <= line) {
63
99
  this.rows.delete(k);
64
100
  n++;
65
101
  }
@@ -67,11 +103,15 @@ export class MemoryApprovalNonceStore {
67
103
  return n;
68
104
  }
69
105
  }
70
- const NONCE_RECORD_SHAPE = {
71
- what: "approval-nonce record without a string s / string n / numeric e",
106
+ const NONCE_LOG_LINE_SHAPE = {
107
+ what: "approval-nonce line that is neither a record (string s / string n / numeric e) nor a time floor (numeric f alone)",
72
108
  read(record) {
73
- const { s, n, e } = record;
74
- return typeof s === "string" && typeof n === "string" && typeof e === "number" ? { s, n, e } : undefined;
109
+ const { s, n, e, f } = record;
110
+ if (typeof s === "string" && typeof n === "string" && typeof e === "number")
111
+ return { s, n, e };
112
+ if (typeof f === "number" && s === undefined && n === undefined && e === undefined)
113
+ return { f };
114
+ return undefined;
75
115
  },
76
116
  };
77
117
  export class FileApprovalNonceStore {
@@ -80,22 +120,29 @@ export class FileApprovalNonceStore {
80
120
  rows = new Map();
81
121
  log;
82
122
  gate;
123
+ floorMs;
124
+ warn;
83
125
  constructor(root, opts) {
126
+ this.warn = opts?.warn ?? warnToLogSeam;
84
127
  const dir = join(root, "approval-nonces");
85
128
  ensureDir(dir);
86
129
  this.tmpDir = join(dir, ".tmp");
87
130
  ensureDir(this.tmpDir);
88
131
  this.path = join(dir, "consumed.jsonl");
89
- const { records, gate } = replayJsonlGuarded(this.path, "approval-nonce", NONCE_RECORD_SHAPE, opts?.warn);
132
+ const { records, gate } = replayJsonlGuarded(this.path, "approval-nonce", NONCE_LOG_LINE_SHAPE, opts?.warn);
90
133
  this.gate = gate;
91
- for (const r of records)
92
- this.rows.set(keyOf(r.s, r.n), r);
134
+ for (const r of records) {
135
+ if ("f" in r)
136
+ this.floorMs = this.floorMs === undefined ? r.f : Math.max(this.floorMs, r.f);
137
+ else
138
+ this.rows.set(keyOf(r.s, r.n), r);
139
+ }
93
140
  }
94
141
  logFor() {
95
142
  return (this.log ??= new AppendLog(this.path));
96
143
  }
97
144
  async nowMs() {
98
- return Date.now();
145
+ return storeClockOf(Date.now(), this.floorMs, "file", this.warn);
99
146
  }
100
147
  async consume(sessionId, nonce, expiresAtMs) {
101
148
  this.gate.assertUsable();
@@ -109,11 +156,11 @@ export class FileApprovalNonceStore {
109
156
  }
110
157
  async reapExpired() {
111
158
  this.gate.assertUsable();
112
- const nowMs = await this.nowMs();
159
+ const line = await this.nowMs();
113
160
  const survivors = [];
114
161
  let removed = 0;
115
162
  for (const record of this.rows.values()) {
116
- if (record.e <= nowMs) {
163
+ if (record.e <= line) {
117
164
  removed++;
118
165
  continue;
119
166
  }
@@ -122,9 +169,11 @@ export class FileApprovalNonceStore {
122
169
  if (removed === 0)
123
170
  return 0;
124
171
  this.log?.closeForSwap();
125
- atomicWriteFile(this.tmpDir, this.path, survivors.map((r) => `${JSON.stringify(r)}\n`).join(""));
172
+ const floor = { f: this.floorMs === undefined ? line : Math.max(this.floorMs, line) };
173
+ atomicWriteFile(this.tmpDir, this.path, [floor, ...survivors].map((r) => `${JSON.stringify(r)}\n`).join(""));
174
+ this.floorMs = floor.f;
126
175
  for (const [k, record] of [...this.rows])
127
- if (record.e <= nowMs)
176
+ if (record.e <= line)
128
177
  this.rows.delete(k);
129
178
  return removed;
130
179
  }
@@ -57,6 +57,8 @@ export declare class MinioBlobBackend implements BlobBackend {
57
57
  private readonly cfg;
58
58
  private readonly keyPrefix;
59
59
  private readonly ttl;
60
+ /** 六个站点(put / get / delete / listObjects / headObject / probeBucket)的唯一出口:端点回重定向 ⇒ 拒,预签名 URL 与对象体不被带去 `Location`。 */
61
+ private readonly egressFetch;
60
62
  constructor(cfg: MinioBlobBackendConfig);
61
63
  private objectKey;
62
64
  private presign;
@@ -1,6 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { presignS3Url, presignS3ListUrl } from "./s3-presign.js";
3
3
  import { isNoSuchBucketAnswer } from "./s3-answer.js";
4
+ import { createEgressFetch } from "../egress-redirect.js";
4
5
  export async function readAtAddress(port, hash) {
5
6
  const bytes = await port.get(hash);
6
7
  if (bytes === undefined)
@@ -23,10 +24,12 @@ export class MinioBlobBackend {
23
24
  cfg;
24
25
  keyPrefix;
25
26
  ttl;
27
+ egressFetch;
26
28
  constructor(cfg) {
27
29
  this.cfg = cfg;
28
30
  this.keyPrefix = cfg.keyPrefix ?? "blobs/";
29
31
  this.ttl = cfg.presignTtlSec ?? 3600;
32
+ this.egressFetch = createEgressFetch("declare the final object-store address as MINIO_ENDPOINT / S3_ENDPOINT", cfg.fetchImpl);
30
33
  }
31
34
  objectKey(key) {
32
35
  return `${this.keyPrefix}${key}`;
@@ -45,7 +48,7 @@ export class MinioBlobBackend {
45
48
  }
46
49
  async put(key, bytes) {
47
50
  const url = this.presign(key, "PUT");
48
- const res = await (this.cfg.fetchImpl ?? fetch)(url, { method: "PUT", body: bytes, signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
51
+ const res = await this.egressFetch(url, { method: "PUT", body: bytes, signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
49
52
  if (!res.ok) {
50
53
  const detail = await res.text().catch(() => "");
51
54
  throw new Error(`MinioBlobBackend.put ${key}: HTTP ${res.status} ${detail.slice(0, 200)}`);
@@ -55,7 +58,7 @@ export class MinioBlobBackend {
55
58
  const url = this.presign(key, "GET");
56
59
  let res;
57
60
  try {
58
- res = await (this.cfg.fetchImpl ?? fetch)(url, { method: "GET", signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
61
+ res = await this.egressFetch(url, { method: "GET", signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
59
62
  }
60
63
  catch (err) {
61
64
  throw new Error(`MinioBlobBackend.get ${key}: transient fetch failure: ${err.message}`);
@@ -74,7 +77,7 @@ export class MinioBlobBackend {
74
77
  let firstFailure;
75
78
  await mapBounded(distinct, MINIO_OP_CONCURRENCY, async (key) => {
76
79
  try {
77
- const res = await (this.cfg.fetchImpl ?? fetch)(this.presign(key, "DELETE"), { method: "DELETE", signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
80
+ const res = await this.egressFetch(this.presign(key, "DELETE"), { method: "DELETE", signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
78
81
  if (res.ok || res.status === 404)
79
82
  return;
80
83
  failed++;
@@ -89,7 +92,7 @@ export class MinioBlobBackend {
89
92
  throw new Error(`MinioBlobBackend.delete: ${failed} of ${distinct.length} object(s) could not be deleted (first: ${firstFailure})`);
90
93
  }
91
94
  async *listObjects() {
92
- const f = this.cfg.fetchImpl ?? fetch;
95
+ const f = this.egressFetch;
93
96
  let token;
94
97
  const MAX_PAGES = 1000;
95
98
  let pages = 0;
@@ -127,7 +130,7 @@ export class MinioBlobBackend {
127
130
  } while (token !== undefined);
128
131
  }
129
132
  async headObject(hash) {
130
- const f = this.cfg.fetchImpl ?? fetch;
133
+ const f = this.egressFetch;
131
134
  const res = await f(this.presign(hash, "HEAD"), { method: "HEAD", signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
132
135
  if (!res.ok)
133
136
  return undefined;
@@ -136,7 +139,7 @@ export class MinioBlobBackend {
136
139
  return { lastModifiedMs: Number.isFinite(ms) ? ms : Date.now() };
137
140
  }
138
141
  async probeBucket(timeoutMs = OBJECT_STORE_IO_TIMEOUT_MS) {
139
- const f = this.cfg.fetchImpl ?? fetch;
142
+ const f = this.egressFetch;
140
143
  const url = presignS3ListUrl({
141
144
  endpoint: this.cfg.endpoint,
142
145
  bucket: this.cfg.bucket,
@@ -1,9 +1,12 @@
1
1
  import { type AcquiredSession, type PlacedSessionRow, type RetentionDeclaration, type SessionPlacementRecord, type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
2
+ import type { LocalSessionDeletionSection } from "../session-erase.js";
2
3
  import type { OwnerAwareSessionStore, SessionListItem } from "../security.js";
3
4
  import type { StagingHandle } from "../session-sync-kernel.js";
5
+ import type { SessionDeletionFace } from "../session-deletion.js";
4
6
  import { type PlacementAcquireOpts } from "./session-placement.js";
5
7
  import type { InstructionSourceStore } from "../instruction-source-notice.js";
6
8
  import type { SessionWorkspaceStore } from "../session-workspace.js";
9
+ import { type SessionBirthFace, type SessionWithdrawFace } from "./session-birth.js";
7
10
  export interface CachingOptions {
8
11
  /** Idle seconds a woken session is kept warm. 0 disables caching (pure passthrough). */
9
12
  ttlSec: number;
@@ -60,7 +63,13 @@ export declare class CachingSessionStore implements SessionStore {
60
63
  * 缓存的会话活得比「另一只店删掉又重建了这一行」长)。内层店必有(本类的暖命中按它核新鲜)。🔴 必须转发:生产默认把真店包进本类,授权口 / 属主门 /
61
64
  * k8s 工作区空间 / SSE 探针 / resume-at 读的都是本类。 */
62
65
  readonly headOf: SessionHeadReader["headOf"];
66
+ /** 删除门的头读(`OwnerAwareSessionStore.deletionHeadOf`;local 店才交):**纯转发、不经暖缓存**(与 `headOf` 同理)。内层店不交 ⇒ 本类也不交(删除门读 `headOf`)。 */
67
+ readonly deletionHeadOf?: OwnerAwareSessionStore["deletionHeadOf"];
63
68
  readonly register?: (sessionId: string, owner: string | null) => Promise<void>;
69
+ /** 出生回执面(`session-birth.ts`;纯转发 —— 写的是持久行)。🔴 必须转发:授权口读的是本类,不转发 = 永远没有候选 = 永不撤回。 */
70
+ readonly registerWithReceipt?: SessionBirthFace["registerWithReceipt"];
71
+ /** 条件撤回面(`session-birth.ts`;转发后逐出暖缓存,与 `deleteSession` 同一条纪律)。 */
72
+ readonly withdrawBirth?: SessionWithdrawFace["withdrawBirth"];
64
73
  /** Delegated SessionRepo seam (§0.5) — list/fork/delete operate on the DURABLE tables directly (they bypass the
65
74
  * warm cache by design; a fork/delete must read/write durable state, not a possibly-stale cached view). */
66
75
  readonly listSessions?: (opts: {
@@ -80,7 +89,10 @@ export declare class CachingSessionStore implements SessionStore {
80
89
  readonly forkTo?: OwnerAwareSessionStore["forkTo"];
81
90
  /** 执行席(原样转发:放置是会话**行**上的一格,缓存只缓存会话日志的暖句柄,不缓存行格 —— 读与写都直达内层店)。 */
82
91
  readonly executionPlacement?: OwnerAwareSessionStore["executionPlacement"];
83
- readonly deleteSession?: (sessionId: string, owner: string | null) => Promise<boolean>;
92
+ /** 删净一只在删会话的 local 执行体锁节(转发后逐出暖缓存)。 */
93
+ readonly deleteSession?: LocalSessionDeletionSection;
94
+ /** 删除面(会话三态的围栏 / 复核 / 收尾输入;`fence` 转发后逐出暖缓存 —— 在删即读作不在,暖条目不许再交出那只会话)。内层店不交 ⇒ 本类也不交。 */
95
+ readonly sessionDeletion?: SessionDeletionFace;
84
96
  /** The session row's list projection for one id + its writable bits (`title` / `pinned`) — DURABLE, pure pass-through
85
97
  * (they read / write `session_meta` / the local sidecars, never the warm cache). 🔴 Must forward (the retention / placements
86
98
  * lesson): the production default wraps the real store in this class, and the route's fact `sessionPatch` reads THIS object. */