@sema-agent/server 7.150.0 → 7.152.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (514) hide show
  1. package/MIGRATION.md +451 -0
  2. package/README.md +15 -3
  3. package/README.zh-CN.md +10 -2
  4. package/USAGE.md +144 -87
  5. package/deploy/sema-up/README.md +11 -4
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
  9. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
  10. package/deploy/sema-up/chart/templates/server.yaml +5 -3
  11. package/deploy/sema-up/chart/values-full-single.yaml +3 -1
  12. package/deploy/sema-up/chart/values.yaml +8 -1
  13. package/deploy/sema-up/cluster-up.sh +7 -6
  14. package/deploy/sema-up/kube-up.sh +6 -6
  15. package/deploy/sema-up/lib/flagshape.sh +36 -8
  16. package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
  17. package/deploy/sema-up/lib/helm-values-kube.py +2 -0
  18. package/deploy/sema-up/machines.example.yaml +3 -1
  19. package/deploy/sema-up/sema-up.sh +22 -16
  20. package/dist/adoption/import.js +3 -3
  21. package/dist/approval-ask-audit-store.d.ts +1 -1
  22. package/dist/approval-ask-machine.d.ts +4 -10
  23. package/dist/approval-ask-retention.d.ts +1 -1
  24. package/dist/approval-card.d.ts +12 -14
  25. package/dist/approval-gate-currency.d.ts +9 -9
  26. package/dist/approval-gate-currency.js +3 -4
  27. package/dist/approval-hmac.d.ts +17 -1
  28. package/dist/approval-hmac.js +7 -1
  29. package/dist/approval-queue-kind.d.ts +1 -1
  30. package/dist/approval.d.ts +2 -2
  31. package/dist/approval.js +2 -2
  32. package/dist/auth-bridge.d.ts +20 -0
  33. package/dist/auth-bridge.js +9 -0
  34. package/dist/background-session-reap.d.ts +1 -1
  35. package/dist/bake-runner/main.d.ts +4 -2
  36. package/dist/bind-host.d.ts +3 -6
  37. package/dist/bind-host.js +4 -7
  38. package/dist/boot/budget-tracing.js +1 -1
  39. package/dist/boot/coordinators.d.ts +1 -1
  40. package/dist/boot/coordinators.js +9 -10
  41. package/dist/boot/device-lane.js +2 -0
  42. package/dist/boot/engine-lease.d.ts +5 -0
  43. package/dist/boot/engine-lease.js +1 -0
  44. package/dist/boot/execution-env.d.ts +9 -14
  45. package/dist/boot/execution-env.js +85 -22
  46. package/dist/boot/execution-lane.js +32 -5
  47. package/dist/boot/late-binds.d.ts +8 -4
  48. package/dist/boot/late-binds.js +7 -1
  49. package/dist/boot/leader.d.ts +31 -30
  50. package/dist/boot/leader.js +38 -28
  51. package/dist/boot/leg-path-adjudication.d.ts +40 -0
  52. package/dist/boot/leg-path-adjudication.js +18 -0
  53. package/dist/boot/memory-consolidation.d.ts +3 -2
  54. package/dist/boot/memory-consolidation.js +6 -6
  55. package/dist/boot/parked-revive-gate.js +3 -15
  56. package/dist/boot/reapers.d.ts +6 -1
  57. package/dist/boot/reapers.js +13 -2
  58. package/dist/boot/resolve-spec.d.ts +3 -3
  59. package/dist/boot/resolve-spec.js +43 -48
  60. package/dist/boot/runner-deps.d.ts +46 -35
  61. package/dist/boot/runner-deps.js +94 -91
  62. package/dist/boot/session-age-out.d.ts +36 -0
  63. package/dist/boot/session-age-out.js +101 -0
  64. package/dist/boot/session-faces.d.ts +5 -14
  65. package/dist/boot/session-faces.js +9 -5
  66. package/dist/boot/shutdown.d.ts +6 -0
  67. package/dist/boot/shutdown.js +10 -4
  68. package/dist/boot/stage-01-config.js +2 -0
  69. package/dist/boot/stage-02-web-admin-pull.js +4 -5
  70. package/dist/boot/stage-05-execution-env.d.ts +5 -3
  71. package/dist/boot/stage-05-execution-env.js +3 -2
  72. package/dist/boot/stage-06-runners.d.ts +9 -4
  73. package/dist/boot/stage-06-runners.js +24 -9
  74. package/dist/boot/stage-07-capability-layer.d.ts +8 -4
  75. package/dist/boot/stage-07-capability-layer.js +3 -2
  76. package/dist/boot/stage-08-reapers.d.ts +8 -4
  77. package/dist/boot/stage-08-reapers.js +4 -2
  78. package/dist/boot/stage-09-leader.d.ts +12 -5
  79. package/dist/boot/stage-09-leader.js +14 -5
  80. package/dist/boot/stage-10-http-server.d.ts +19 -5
  81. package/dist/boot/stage-10-http-server.js +14 -21
  82. package/dist/boot/stores.js +7 -4
  83. package/dist/boot/web-admin.js +5 -8
  84. package/dist/boot/workflow-orchestration.d.ts +7 -2
  85. package/dist/boot/workflow-orchestration.js +24 -7
  86. package/dist/bounded-rotation.d.ts +29 -0
  87. package/dist/bounded-rotation.js +24 -0
  88. package/dist/capabilities/approvals-push.d.ts +3 -3
  89. package/dist/capabilities/scenarios.d.ts +28 -13
  90. package/dist/capabilities/scenarios.js +2 -2
  91. package/dist/capability-facts.d.ts +43 -32
  92. package/dist/capability-facts.js +45 -51
  93. package/dist/card-rule-offers.d.ts +32 -0
  94. package/dist/card-rule-offers.js +130 -0
  95. package/dist/center-credential.d.ts +25 -6
  96. package/dist/center-credential.js +25 -5
  97. package/dist/config-catalog.d.ts +26 -7
  98. package/dist/config-catalog.js +26 -22
  99. package/dist/config-dir-trust.js +4 -2
  100. package/dist/config-invariants.d.ts +20 -8
  101. package/dist/config-invariants.js +55 -12
  102. package/dist/config-lkg.d.ts +5 -19
  103. package/dist/config-lkg.js +8 -62
  104. package/dist/config-provider.d.ts +1 -1
  105. package/dist/config-root-migration.d.ts +2 -2
  106. package/dist/config-types.d.ts +38 -42
  107. package/dist/config.d.ts +58 -7
  108. package/dist/config.js +90 -40
  109. package/dist/control-socket.d.ts +51 -0
  110. package/dist/control-socket.js +115 -0
  111. package/dist/deployment-governance.d.ts +2 -1
  112. package/dist/deployment-shape.d.ts +9 -1
  113. package/dist/deployment-shape.js +2 -1
  114. package/dist/device-protocol.d.ts +5 -4
  115. package/dist/device-protocol.js +1 -1
  116. package/dist/device-ws-hub.d.ts +7 -0
  117. package/dist/device-ws-hub.js +10 -3
  118. package/dist/device-ws-protocol.d.ts +63 -10
  119. package/dist/device-ws-protocol.js +56 -25
  120. package/dist/elicitation.js +2 -2
  121. package/dist/engine-identity.d.ts +19 -7
  122. package/dist/engine-identity.js +10 -2
  123. package/dist/entry-mode-clamp-notice.d.ts +2 -1
  124. package/dist/entry-problems.d.ts +40 -3
  125. package/dist/entry-problems.js +3 -1
  126. package/dist/execution-env-refusal.d.ts +29 -0
  127. package/dist/execution-env-refusal.js +8 -0
  128. package/dist/execution-lane-caps.d.ts +3 -1
  129. package/dist/field-conflict.d.ts +1 -1
  130. package/dist/file-history-capture.d.ts +11 -4
  131. package/dist/file-history-capture.js +9 -6
  132. package/dist/file-history-disclosure.d.ts +7 -5
  133. package/dist/file-history-disclosure.js +7 -5
  134. package/dist/fleet/drain-entry.d.ts +4 -0
  135. package/dist/fleet/engine-signal.d.ts +12 -29
  136. package/dist/fleet/engine-signal.js +1 -7
  137. package/dist/fleet-client.js +2 -5
  138. package/dist/gate-settlement.d.ts +1 -8
  139. package/dist/gate-settlement.js +0 -4
  140. package/dist/history-anchor.js +1 -1
  141. package/dist/hitl-delivery.d.ts +2 -3
  142. package/dist/hitl-delivery.js +0 -2
  143. package/dist/hooks/hook-llm.js +4 -2
  144. package/dist/hooks/hook-runner.d.ts +3 -2
  145. package/dist/hooks/hook-runner.js +18 -3
  146. package/dist/host-decision.d.ts +11 -11
  147. package/dist/host-lsp-manager.d.ts +2 -2
  148. package/dist/http/active-run-conflict.d.ts +35 -2
  149. package/dist/http/active-run-conflict.js +48 -19
  150. package/dist/http/admission.js +17 -2
  151. package/dist/http/approval-sweeps.d.ts +1 -1
  152. package/dist/http/approval-sweeps.js +10 -7
  153. package/dist/http/checkpoint-ctx.d.ts +4 -0
  154. package/dist/http/checkpoint-ctx.js +2 -0
  155. package/dist/http/dispatch.d.ts +8 -3
  156. package/dist/http/dispatch.js +59 -32
  157. package/dist/http/durable-run-leg.js +16 -17
  158. package/dist/http/health-reader.d.ts +16 -9
  159. package/dist/http/health-reader.js +2 -1
  160. package/dist/http/health-self-report.d.ts +9 -1
  161. package/dist/http/health-self-report.js +3 -1
  162. package/dist/http/owner-access.d.ts +33 -14
  163. package/dist/http/owner-access.js +40 -10
  164. package/dist/http/principal-gate.d.ts +49 -21
  165. package/dist/http/principal-gate.js +61 -11
  166. package/dist/http/request-channel.d.ts +23 -0
  167. package/dist/http/request-channel.js +9 -0
  168. package/dist/http/request-guards.js +17 -2
  169. package/dist/http/resume-ctx-read.js +42 -3
  170. package/dist/http/resume-legs.d.ts +4 -3
  171. package/dist/http/resume-legs.js +367 -117
  172. package/dist/http/route-ctx.d.ts +91 -15
  173. package/dist/http/route-ctx.js +17 -0
  174. package/dist/http/route-table.d.ts +5 -1
  175. package/dist/http/route-table.js +4 -0
  176. package/dist/http/routes/admin-config-refresh.js +3 -3
  177. package/dist/http/routes/admin-drain.d.ts +3 -0
  178. package/dist/http/routes/admin-drain.js +7 -7
  179. package/dist/http/routes/admin-memory-optout.d.ts +1 -1
  180. package/dist/http/routes/admin-memory-optout.js +3 -3
  181. package/dist/http/routes/adoption.js +3 -5
  182. package/dist/http/routes/agents-roster.js +2 -3
  183. package/dist/http/routes/approvals-assistant.d.ts +2 -1
  184. package/dist/http/routes/approvals-assistant.js +99 -51
  185. package/dist/http/routes/background.d.ts +3 -3
  186. package/dist/http/routes/capabilities.d.ts +4 -0
  187. package/dist/http/routes/capabilities.js +38 -10
  188. package/dist/http/routes/config-catalog.js +2 -2
  189. package/dist/http/routes/devices.js +1 -1
  190. package/dist/http/routes/diagnostics.d.ts +3 -3
  191. package/dist/http/routes/diagnostics.js +19 -7
  192. package/dist/http/routes/fleet.js +10 -8
  193. package/dist/http/routes/images.js +10 -10
  194. package/dist/http/routes/memory-bundle.js +3 -3
  195. package/dist/http/routes/memory-compliance.js +3 -3
  196. package/dist/http/routes/memory-consolidation.js +2 -2
  197. package/dist/http/routes/memory-origin.js +3 -3
  198. package/dist/http/routes/memory-policy.js +2 -2
  199. package/dist/http/routes/observability.js +3 -3
  200. package/dist/http/routes/projects.d.ts +3 -2
  201. package/dist/http/routes/projects.js +4 -5
  202. package/dist/http/routes/retention-ops.js +3 -3
  203. package/dist/http/routes/rules.js +5 -5
  204. package/dist/http/routes/run-permission-mode.d.ts +2 -1
  205. package/dist/http/routes/run-permission-mode.js +2 -2
  206. package/dist/http/routes/runs.d.ts +4 -9
  207. package/dist/http/routes/runs.js +171 -65
  208. package/dist/http/routes/session-sync.d.ts +22 -9
  209. package/dist/http/routes/session-sync.js +204 -107
  210. package/dist/http/routes/sessions-list.js +13 -7
  211. package/dist/http/routes/sessions.js +30 -15
  212. package/dist/http/routes/tasks.js +46 -41
  213. package/dist/http/routes/trace-usage.js +2 -2
  214. package/dist/http/routes/workflows.js +1 -1
  215. package/dist/http/server.d.ts +30 -30
  216. package/dist/http/server.js +16 -4
  217. package/dist/http/submit-ctx.d.ts +1 -1
  218. package/dist/http/submit-ctx.js +7 -4
  219. package/dist/http/wire-types.d.ts +14 -4
  220. package/dist/human-facing-args.d.ts +33 -0
  221. package/dist/human-facing-args.js +33 -0
  222. package/dist/identity-source.d.ts +20 -3
  223. package/dist/identity-source.js +14 -0
  224. package/dist/index.d.ts +5 -1
  225. package/dist/k8s-api-credentials.d.ts +29 -0
  226. package/dist/k8s-api-credentials.js +25 -0
  227. package/dist/lane-home-probe.d.ts +3 -7
  228. package/dist/lane-home-probe.js +2 -2
  229. package/dist/leader/diffup.d.ts +19 -0
  230. package/dist/leader/diffup.js +7 -0
  231. package/dist/leader/leader.d.ts +116 -11
  232. package/dist/leader/leader.js +69 -5
  233. package/dist/leader/repair-wire.js +2 -2
  234. package/dist/leader/run-entry.d.ts +2 -1
  235. package/dist/leader/run-entry.js +1 -1
  236. package/dist/leader/wire.d.ts +42 -132
  237. package/dist/leader/wire.js +81 -67
  238. package/dist/leg-facts.d.ts +13 -5
  239. package/dist/leg-facts.js +2 -1
  240. package/dist/memory-scope.d.ts +23 -11
  241. package/dist/memory-scope.js +18 -6
  242. package/dist/memory-sync-client.d.ts +30 -2
  243. package/dist/memory-sync-client.js +16 -9
  244. package/dist/model-entry-headers.d.ts +9 -10
  245. package/dist/model-entry-headers.js +0 -4
  246. package/dist/model-entry-refusal.d.ts +7 -4
  247. package/dist/model-entry-refusal.js +11 -5
  248. package/dist/model-plane-face.d.ts +1 -1
  249. package/dist/model-plane-face.js +3 -1
  250. package/dist/model-route-endpoint.d.ts +13 -7
  251. package/dist/model-route-endpoint.js +14 -11
  252. package/dist/model-select.d.ts +22 -0
  253. package/dist/model-select.js +9 -0
  254. package/dist/model-unreachable-notice.d.ts +11 -0
  255. package/dist/model-unreachable-notice.js +4 -4
  256. package/dist/object-store-buckets.d.ts +640 -6
  257. package/dist/object-store-buckets.js +166 -0
  258. package/dist/observability/err-text.d.ts +7 -0
  259. package/dist/observability/err-text.js +5 -0
  260. package/dist/observability/fail-open.d.ts +25 -17
  261. package/dist/observability/fail-open.js +25 -17
  262. package/dist/observability/logger.js +3 -1
  263. package/dist/observability/metrics.js +1 -0
  264. package/dist/operator-roster.d.ts +68 -0
  265. package/dist/operator-roster.js +32 -0
  266. package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
  267. package/dist/orchestration/workflow-notify-journal.js +12 -1
  268. package/dist/orchestration/workflow-park-decision.d.ts +70 -18
  269. package/dist/orchestration/workflow-park-decision.js +49 -10
  270. package/dist/orchestration/workflow-park-holder.d.ts +65 -0
  271. package/dist/orchestration/workflow-park-holder.js +98 -0
  272. package/dist/orchestration/workflow-record-fence.d.ts +36 -0
  273. package/dist/orchestration/workflow-record-fence.js +42 -0
  274. package/dist/outbound-dispatcher.d.ts +71 -8
  275. package/dist/outbound-dispatcher.js +48 -7
  276. package/dist/owner-faces.d.ts +2 -2
  277. package/dist/parked-decide.d.ts +106 -55
  278. package/dist/parked-decide.js +153 -117
  279. package/dist/peer-directory.d.ts +2 -2
  280. package/dist/peer-inbound-face.d.ts +2 -6
  281. package/dist/peer-inbound-face.js +0 -3
  282. package/dist/permission-mode-admission.d.ts +74 -5
  283. package/dist/permission-mode-admission.js +56 -3
  284. package/dist/plugins/adoption-log-sql.d.ts +3 -1
  285. package/dist/plugins/adoption-log-sql.js +7 -1
  286. package/dist/plugins/approval-ask-store-file.d.ts +14 -2
  287. package/dist/plugins/approval-ask-store-file.js +11 -0
  288. package/dist/plugins/approval-ask-store-memory.d.ts +10 -1
  289. package/dist/plugins/approval-ask-store-memory.js +35 -10
  290. package/dist/plugins/approval-ask-store-sql.d.ts +69 -4
  291. package/dist/plugins/approval-ask-store-sql.js +45 -5
  292. package/dist/plugins/approval-exemption-store.js +3 -0
  293. package/dist/plugins/approval-nonce-store.js +2 -0
  294. package/dist/plugins/blob-backend.d.ts +83 -7
  295. package/dist/plugins/blob-backend.js +57 -6
  296. package/dist/plugins/breaker-state-sql.js +2 -0
  297. package/dist/plugins/caching-session-store.d.ts +9 -15
  298. package/dist/plugins/caching-session-store.js +6 -0
  299. package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
  300. package/dist/plugins/checkpoint-index-columns.js +3 -6
  301. package/dist/plugins/checkpoint-store-face.d.ts +119 -61
  302. package/dist/plugins/checkpoint-store-face.js +134 -55
  303. package/dist/plugins/device-store-sql.js +6 -0
  304. package/dist/plugins/error-origin.d.ts +18 -0
  305. package/dist/plugins/error-origin.js +10 -0
  306. package/dist/plugins/execution-placement-sql.js +6 -6
  307. package/dist/plugins/image-bake-store-sql.js +6 -0
  308. package/dist/plugins/image-index-sql.js +4 -0
  309. package/dist/plugins/landed-attendants.d.ts +212 -0
  310. package/dist/plugins/landed-attendants.js +161 -0
  311. package/dist/plugins/leader-run-store-sql.js +4 -0
  312. package/dist/plugins/local-checkpoint-store.d.ts +13 -3
  313. package/dist/plugins/local-checkpoint-store.js +38 -49
  314. package/dist/plugins/local-session-live-reference.d.ts +40 -0
  315. package/dist/plugins/local-session-live-reference.js +39 -0
  316. package/dist/plugins/local-session-store.d.ts +71 -33
  317. package/dist/plugins/local-session-store.js +129 -27
  318. package/dist/plugins/memory-engine-pg.js +4 -0
  319. package/dist/plugins/memory-engine-sql-apply.js +5 -2
  320. package/dist/plugins/memory-engine-tidb.js +4 -0
  321. package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
  322. package/dist/plugins/memory-sync-store-pg.js +5 -0
  323. package/dist/plugins/memory-sync-store-tidb.js +5 -0
  324. package/dist/plugins/one-time-migrations.d.ts +104 -80
  325. package/dist/plugins/one-time-migrations.js +226 -132
  326. package/dist/plugins/org-delivery-quota-store.js +4 -1
  327. package/dist/plugins/outcome-ledger-sql.js +2 -0
  328. package/dist/plugins/permission-rule-store-sql.js +11 -4
  329. package/dist/plugins/pg-cost-quota.js +4 -0
  330. package/dist/plugins/pg-pool.js +35 -10
  331. package/dist/plugins/pg-rate-limiter.js +2 -0
  332. package/dist/plugins/posix-shell-fs.d.ts +6 -1
  333. package/dist/plugins/posix-shell-fs.js +4 -1
  334. package/dist/plugins/remote-env-adb.d.ts +19 -15
  335. package/dist/plugins/remote-env-adb.js +41 -15
  336. package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
  337. package/dist/plugins/remote-env-connect-seat.js +72 -0
  338. package/dist/plugins/remote-env-device.d.ts +22 -5
  339. package/dist/plugins/remote-env-device.js +106 -8
  340. package/dist/plugins/remote-env-e2b.d.ts +15 -6
  341. package/dist/plugins/remote-env-e2b.js +42 -32
  342. package/dist/plugins/remote-env-file-error.js +6 -2
  343. package/dist/plugins/remote-env-host.d.ts +46 -10
  344. package/dist/plugins/remote-env-host.js +124 -52
  345. package/dist/plugins/remote-env-k8s.d.ts +109 -41
  346. package/dist/plugins/remote-env-k8s.js +160 -54
  347. package/dist/plugins/remote-env-local-docker.d.ts +13 -8
  348. package/dist/plugins/remote-env-local-docker.js +34 -41
  349. package/dist/plugins/remote-env-ssh.d.ts +18 -12
  350. package/dist/plugins/remote-env-ssh.js +60 -59
  351. package/dist/plugins/remote-shell.d.ts +98 -1
  352. package/dist/plugins/remote-shell.js +218 -0
  353. package/dist/plugins/replica-registration.d.ts +1 -1
  354. package/dist/plugins/replica-registration.js +1 -1
  355. package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
  356. package/dist/plugins/resume-anchor-store-sql.js +12 -5
  357. package/dist/plugins/retention-lane-store-sql.js +4 -0
  358. package/dist/plugins/retention-sql.d.ts +20 -2
  359. package/dist/plugins/retention-sql.js +11 -0
  360. package/dist/plugins/run-store-sql.d.ts +21 -2
  361. package/dist/plugins/run-store-sql.js +31 -7
  362. package/dist/plugins/s3-presign.d.ts +23 -0
  363. package/dist/plugins/s3-presign.js +37 -3
  364. package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
  365. package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
  366. package/dist/plugins/scheduler-support.d.ts +2 -2
  367. package/dist/plugins/scheduler-support.js +0 -3
  368. package/dist/plugins/schema-consistency.d.ts +4 -2
  369. package/dist/plugins/schema-consistency.js +19 -2
  370. package/dist/plugins/schema-indexes.js +2 -0
  371. package/dist/plugins/send-file-ledger.d.ts +2 -2
  372. package/dist/plugins/send-file-ledger.js +5 -2
  373. package/dist/plugins/send-user-file.d.ts +3 -4
  374. package/dist/plugins/send-user-file.js +56 -52
  375. package/dist/plugins/serving-requirement.d.ts +26 -7
  376. package/dist/plugins/serving-requirement.js +11 -4
  377. package/dist/plugins/session-birth.d.ts +6 -2
  378. package/dist/plugins/session-blob-claim-token.d.ts +15 -0
  379. package/dist/plugins/session-blob-claim-token.js +20 -0
  380. package/dist/plugins/session-blob-namespace.d.ts +46 -0
  381. package/dist/plugins/session-blob-namespace.js +116 -0
  382. package/dist/plugins/session-capture-record-store-sql.js +2 -0
  383. package/dist/plugins/session-ext-table.d.ts +14 -1
  384. package/dist/plugins/session-ext-table.js +5 -1
  385. package/dist/plugins/session-row-sql.d.ts +49 -2
  386. package/dist/plugins/session-row-sql.js +56 -13
  387. package/dist/plugins/session-store-sql.d.ts +34 -18
  388. package/dist/plugins/session-store-sql.js +98 -17
  389. package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
  390. package/dist/plugins/shared-memory-store-sql.js +6 -2
  391. package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
  392. package/dist/plugins/snapshot-bucket-presence.js +8 -2
  393. package/dist/plugins/sql-driver.d.ts +2 -1
  394. package/dist/plugins/sql-driver.js +18 -3
  395. package/dist/plugins/sql-errors.d.ts +11 -6
  396. package/dist/plugins/sql-errors.js +5 -6
  397. package/dist/plugins/sql-json-column.d.ts +1 -1
  398. package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
  399. package/dist/plugins/stop-then-start-sentence.js +14 -10
  400. package/dist/plugins/stop-then-start.d.ts +109 -0
  401. package/dist/plugins/stop-then-start.js +104 -0
  402. package/dist/plugins/store-backend.d.ts +84 -15
  403. package/dist/plugins/store-backend.js +236 -72
  404. package/dist/plugins/store-boundary.d.ts +57 -0
  405. package/dist/plugins/store-boundary.js +139 -0
  406. package/dist/plugins/store-contracts.d.ts +17 -0
  407. package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
  408. package/dist/plugins/store-fault-sentence-m53.js +25 -0
  409. package/dist/plugins/store-fault.d.ts +26 -7
  410. package/dist/plugins/store-fault.js +18 -2
  411. package/dist/plugins/task-attachment-store.d.ts +2 -1
  412. package/dist/plugins/task-attachment-store.js +14 -1
  413. package/dist/plugins/task-list-store-sql.d.ts +2 -2
  414. package/dist/plugins/task-list-store-sql.js +10 -8
  415. package/dist/plugins/tidb-cost-quota.js +4 -0
  416. package/dist/plugins/tidb-pool.js +21 -25
  417. package/dist/plugins/tidb-rate-limiter.js +4 -0
  418. package/dist/plugins/user-input-ledger-sql.js +4 -0
  419. package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
  420. package/dist/plugins/workflow-run-store-sql.js +64 -4
  421. package/dist/plugins/workspace-custody.d.ts +4 -3
  422. package/dist/plugins/workspace-fill.d.ts +4 -7
  423. package/dist/plugins/workspace-fill.js +2 -1
  424. package/dist/plugins/write-behind-counter.js +5 -0
  425. package/dist/project-context.d.ts +0 -2
  426. package/dist/project-context.js +4 -8
  427. package/dist/project-registry.d.ts +46 -0
  428. package/dist/project-registry.js +44 -0
  429. package/dist/question.d.ts +2 -1
  430. package/dist/question.js +5 -13
  431. package/dist/request-form.d.ts +6 -1
  432. package/dist/request-form.js +4 -1
  433. package/dist/request-key-closure.js +1 -1
  434. package/dist/request-value-closure.d.ts +4 -0
  435. package/dist/request-value-closure.js +10 -0
  436. package/dist/rule-issue-reading.d.ts +1 -1
  437. package/dist/rules-consent.d.ts +1 -1
  438. package/dist/run-acceptance.d.ts +3 -2
  439. package/dist/run-acceptance.js +4 -6
  440. package/dist/run-local.js +9 -9
  441. package/dist/runs.d.ts +54 -16
  442. package/dist/runs.js +67 -13
  443. package/dist/runtime-governance.d.ts +5 -4
  444. package/dist/security.d.ts +30 -32
  445. package/dist/security.js +41 -7
  446. package/dist/sema-config-dir.d.ts +2 -1
  447. package/dist/server-secret-env.d.ts +12 -10
  448. package/dist/server-secret-env.js +24 -15
  449. package/dist/session-bindings.d.ts +82 -0
  450. package/dist/session-bindings.js +18 -0
  451. package/dist/session-children-retire.d.ts +2 -2
  452. package/dist/session-children-retire.js +2 -6
  453. package/dist/session-deletion.d.ts +16 -1
  454. package/dist/session-error-wire.d.ts +3 -3
  455. package/dist/session-error-wire.js +3 -3
  456. package/dist/session-incarnation.d.ts +10 -0
  457. package/dist/session-incarnation.js +10 -1
  458. package/dist/session-kind.d.ts +57 -0
  459. package/dist/session-kind.js +22 -0
  460. package/dist/session-row.d.ts +21 -1
  461. package/dist/session-row.js +7 -1
  462. package/dist/session-sync-kernel.d.ts +24 -14
  463. package/dist/session-sync-kernel.js +3 -6
  464. package/dist/session-sync.d.ts +25 -103
  465. package/dist/session-sync.js +14 -76
  466. package/dist/session-titler.d.ts +10 -3
  467. package/dist/session-titler.js +19 -6
  468. package/dist/ssh-host-key.d.ts +5 -0
  469. package/dist/ssh-host-key.js +3 -0
  470. package/dist/stores-sql/blob-index-sql.d.ts +30 -9
  471. package/dist/stores-sql/blob-index-sql.js +40 -21
  472. package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
  473. package/dist/stores-sql/checkpoint-store-sql.js +70 -146
  474. package/dist/stores-sql/file-history-store-sql.d.ts +113 -15
  475. package/dist/stores-sql/file-history-store-sql.js +205 -95
  476. package/dist/stores-sql/pg-session-storage.d.ts +34 -7
  477. package/dist/stores-sql/pg-session-storage.js +37 -13
  478. package/dist/stores-sql/retention-store-sql.d.ts +1 -9
  479. package/dist/stores-sql/retention-store-sql.js +5 -19
  480. package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
  481. package/dist/stores-sql/session-policy-store-sql.js +61 -44
  482. package/dist/stores-sql/session-write-hooks.d.ts +11 -0
  483. package/dist/stores-sql/tidb-session-store.d.ts +58 -7
  484. package/dist/stores-sql/tidb-session-store.js +37 -13
  485. package/dist/submission-exit.d.ts +3 -2
  486. package/dist/submission-exit.js +9 -1
  487. package/dist/task-cwd.d.ts +2 -2
  488. package/dist/task-settings.d.ts +7 -5
  489. package/dist/task-settings.js +3 -3
  490. package/dist/terminal.d.ts +33 -2
  491. package/dist/terminal.js +139 -9
  492. package/dist/tool-approval.d.ts +465 -507
  493. package/dist/tool-approval.js +606 -1222
  494. package/dist/trace/core-keyset-guard.d.ts +1 -1
  495. package/dist/trace/ledger-events.d.ts +3 -3
  496. package/dist/trace/project.d.ts +2 -3
  497. package/dist/trace/redact.js +3 -2
  498. package/dist/trace/self-minted-wire.d.ts +571 -178
  499. package/dist/trace/self-minted-wire.js +189 -56
  500. package/dist/web-admin-client/apply-effective.js +2 -2
  501. package/dist/web-admin-client/read-warnings.d.ts +2 -2
  502. package/dist/web-admin-client/read-warnings.js +1 -1
  503. package/dist/web-admin-client/types.d.ts +1 -1
  504. package/dist/workspace-space.d.ts +10 -4
  505. package/dist/workspace-space.js +4 -1
  506. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +79 -28
  507. package/package.json +7 -3
  508. package/scripts/embed-minimal.mjs +3 -3
  509. package/wire-changes/server@7.151.0.json +762 -0
  510. package/wire-changes/server@7.152.0.json +900 -0
  511. package/dist/config-d-migration.d.ts +0 -37
  512. package/dist/config-d-migration.js +0 -60
  513. package/dist/http/session-inherit-env.d.ts +0 -36
  514. package/dist/http/session-inherit-env.js +0 -6
@@ -5,6 +5,7 @@ import { mysqlDriver, pgDriver } from "./sql-driver.js";
5
5
  import { createObjectColumnReader, decodeNullableJsonColumn, foldJsonColumn, jsonColumnText, readJsonArrayColumn, readJsonObjectColumn } from "./sql-json-column.js";
6
6
  import { normalizeIsoOrNull as isoOrNull } from "./sql-row-helpers.js";
7
7
  import { ensureIndexes } from "./ensure-index.js";
8
+ import { sealStoreClass } from "./store-boundary.js";
8
9
  export const PG_IMAGE_INDEX_SCHEMA = [
9
10
  `CREATE TABLE IF NOT EXISTS sandbox_image_index (
10
11
  id VARCHAR(64) COLLATE "C" NOT NULL,
@@ -381,6 +382,9 @@ export class SqlImageIndex {
381
382
  await this.db.query(`UPDATE sandbox_image_index SET ${sets.join(", ")} WHERE id = $${idx}`, params);
382
383
  }
383
384
  }
385
+ sealStoreClass(SqlImageIndex, "sql-image-index", {
386
+ upsert: "exit", registerBuilding: "exit", getById: "exit", getByDigest: "exit", latestPublished: "exit", list: "exit", setStatus: "exit",
387
+ });
384
388
  export class TiDBImageIndex extends SqlImageIndex {
385
389
  constructor(pool) {
386
390
  super(mysqlDriver(pool));
@@ -0,0 +1,212 @@
1
+ /**
2
+ * **会话的附随物只写在判过的那一位住客上** —— 落定席位(`StoreBackend.landedAttendants()`;SQL 两只后端与 local 后端各组一只)。
3
+ *
4
+ * ## 律(一句)
5
+ * 一只会话的附随物(文件历史图 · 会话规则行 · 回退锚;会话行的两位与自动标题另经会话店自己的行格写口,判官同一只)只写在一位**判过的**住客上:
6
+ * 每一笔写在一只**落定段**里 —— 段的第一步锁会话根行,用**同一只**判官(`session-row.ts` 的 `judgeLandedRow` = 行格写原语的判官以 `replay` 写者问:
7
+ * 行在 ∧ 非在删 ∧ 非委派分区 ∧ 属主与化身整对同,core `sessionRowMatches`)比住客;不是那一位 ⇒ 一个字节不写,席位答 `{ landed: false }`。
8
+ * 段的物理形:SQL = `plugins/session-row-sql.ts` 的 `withLandedRow`(一只事务:锁根行 → 判 → 各店的**语句片**(出口表的 `in-store`)在同一连接上跑 → 提交;死锁 / 仲裁输了从段首重来);
9
+ * local = `LocalSessionStore.withLanded`(这只会话的写锁一节,与删净段 `deleteSession` 同锁)。
10
+ *
11
+ * ## 住客从哪来(`landed` 的来源只有这几处)
12
+ * · 会话同步提交臂 = 暂存提交在同一事务 / 写锁里读出、原子交回的 `committed.face`;identical 臂 = 门读的那一位;
13
+ * · 运行腿的每轮回退锚 = 这条腿受理时见证的那一位(`LegFacts.sessionWitness`;新会话的第一条腿在 run 还在跑、认领还在手时读一次头钉住 —— `runs.ts` 的 `createRunAnchorWriter`);
14
+ * · `PUT /v1/sessions/:id/policy` = 门读的那一位;自动标题器 = 起标题时读到的那一位(会话店的 `setTitleIfNull` 自己收行期望)。
15
+ * 所以「提交 / 门读 / 受理之后会话被删、同 id 被任何人(包括同一属主)重建」时,迟到的写落不进新住客;只删不重建时,落不进空闲 id。
16
+ *
17
+ * ## 腿(`SESSION_TREE_LEGS` 的三员子集 —— 「附随物」一词只有删净段那一张腿表)
18
+ * · `wipe` —— overwrite-dst 的擦除:文件历史整 scope · 规则行(抹除语义同店的 `deleteBySession`,封键照封)· 锚,一段一事务(SQL)/ 一节(local);
19
+ * · `replayHistory` —— 段外做门判与取值校验(SQL 店的 `prepareImport`:同图只校验、首推 / 替换续租),段内做空目标 / 同图 / 异图判与发布;异图 ∧ `allowReplace` ⇒ 段内删整 scope 再插
20
+ * (SQL 一事务;local 两步在一节里串行 —— local 的「替换后目标留空」残余只在 local 上);
21
+ * · `replayPolicy` —— **逐条一段**(与修前每条 `putRules` 一事务同粒度):段内锁读 prior、等内容跳过、收紧门、计客户端写、写;某条拒 ⇒ 抛 `SessionPolicyError`(之前各条已提交);
22
+ * 某条段判住客没了 ⇒ `{ landed: false }`,后续条不跑;
23
+ * · `putPolicy` —— `PUT …/policy` 的一笔写(同一只语句源,一段);
24
+ * · `putAnchors` —— 锚的**唯一**生产写口(会话同步两臂 · 四条运行腿的每轮捕获);一段内逐条 upsert。
25
+ *
26
+ * ## 不在这里的(如实)
27
+ * · 运行期仍不进段的写者:文件历史捕获(`trackEdit` / `snapshot`)、条目追加、引擎经会话规则席的规则写 —— 它们在整笔写期间持有 run 认领(认领律令删除与在跑 run 互斥)。
28
+ * · fork 子会话的文件历史由引擎在子会话首个 run 里懒承接(`adoptScope`),承接不比源会话的世代 —— 那一形的座在引擎,本席位不补。
29
+ */
30
+ import { type FileHistoryError, type FileHistoryExport, type FileHistoryResult, type PutRulesOptions, type SessionPermissionRules, type SessionPolicyStore, type SessionRulesRecord, type StoredSessionRules } from "@sema-agent/core";
31
+ import type { SqlDriver, SqlTxConn } from "./sql-driver.js";
32
+ import type { LandedOutcome } from "../session-row.js";
33
+ import type { SessionFace } from "../session-incarnation.js";
34
+ import type { BlobGetter } from "../session-sync.js";
35
+ import type { ServiceFileHistoryStore, ServiceSessionPolicyStore } from "./store-backend.js";
36
+ /** 一条要落的锚(已判过的:`entryId` 在这次导入声明的条目里 / 是这条 run 的提交)。 */
37
+ export interface LandedAnchor {
38
+ readonly eventId: string;
39
+ readonly entryId: string;
40
+ }
41
+ /** 落定席位(头注)。每个方法的 `landed` = 这一笔要落在的那一位住客(来源见头注)。 */
42
+ export interface LandedAttendantSeat {
43
+ wipe(sessionId: string, landed: SessionFace): Promise<LandedOutcome<void>>;
44
+ replayHistory(sessionId: string, landed: SessionFace, envelope: FileHistoryExport, getter: BlobGetter, opts: {
45
+ readonly allowReplace: boolean;
46
+ }): Promise<LandedOutcome<FileHistoryReplayResult>>;
47
+ replayPolicy(sessionId: string, landed: SessionFace, records: readonly SessionRulesRecord[], operator: boolean): Promise<LandedOutcome<void>>;
48
+ putPolicy(sessionId: string, landed: SessionFace, principal: string | undefined, rules: SessionPermissionRules, opts: PutRulesOptions): Promise<LandedOutcome<StoredSessionRules>>;
49
+ putAnchors(sessionId: string, landed: SessionFace, anchors: readonly LandedAnchor[], owner: string | null): Promise<LandedOutcome<void>>;
50
+ }
51
+ /**
52
+ * SQL 席位写经的两只店(组合座 `store-backend.ts` 交入:后端交它自己的那一只 —— 读者读的同一只实例;本目录不 import `stores-sql/**`,所以这里按形写)。席位只调这几员:
53
+ * 文件历史的段外半(`prepareImport`,自己借连接,出口)与唯一折法 `importFailureOf`;两只店的**语句片**(出口表的 `in-store`:`publishImportOn` / `deleteScopeOn` /
54
+ * `putRulesOn` / `eraseOn`,只在落定段借给它们的事务连接上跑,错交回段的主人 = 本席位);撞键判官 `isDupKeyError`;抹除提交之后的响亮面 `discloseErased`
55
+ * (`eraseOn` 交回的封键交给它 —— 封键那一条 warn,只在段提交之后调)。`K` = 规则店的封键形(本席位只转交,不读)。
56
+ */
57
+ export interface SqlAttendantStatements<K> {
58
+ readonly history: {
59
+ prepareImport(scope: string, data: FileHistoryExport, getter: BlobGetter, opts: {
60
+ readonly replace: boolean;
61
+ }): Promise<{
62
+ readonly ok: false;
63
+ readonly error: FileHistoryError;
64
+ } | {
65
+ readonly ok: true;
66
+ readonly mode: "same" | "publish";
67
+ }>;
68
+ publishImportOn(conn: SqlTxConn, scope: string, data: FileHistoryExport, plan: {
69
+ readonly ok: true;
70
+ readonly mode: "same" | "publish";
71
+ }, opts: {
72
+ readonly replace: boolean;
73
+ }): Promise<FileHistoryResult>;
74
+ deleteScopeOn(conn: SqlTxConn, scope: string): Promise<number>;
75
+ /** 导入接住的一只故障的唯一折法(店的图事务与本席位的发布步同读;`adopt_failed` + 判得出的 `permanence`)。 */
76
+ importFailureOf(err: unknown): FileHistoryError;
77
+ };
78
+ readonly policy: {
79
+ putRulesOn(conn: SqlTxConn, sessionId: string, principal: string | undefined, rules: SessionPermissionRules, opts: PutRulesOptions | undefined, how: {
80
+ readonly count: boolean;
81
+ readonly skip?: (prior: StoredSessionRules | null) => boolean;
82
+ }): Promise<StoredSessionRules | {
83
+ readonly skipped: true;
84
+ }>;
85
+ eraseOn(conn: SqlTxConn, sessionId: string): Promise<K>;
86
+ discloseErased(sessionId: string, sealed: K): void;
87
+ isDupKeyError(e: unknown): boolean;
88
+ };
89
+ }
90
+ /**
91
+ * SQL 落定席位:`db` = 这台后端的池包成的 `SqlDriver`(与会话店、三只附随店同一只池)。
92
+ * **席位是店的出口**(店边界律:`store-boundary.ts` 头注):每个方法自己借连接、开事务(`withLandedRow`),段里跑的锁根行句、各店的语句片、锚的语句片、
93
+ * 提交都在这一只事务里 —— 它们都不是出口(出口表记 `in-store`,不封),席位的方法才是。所以封口只在这里一处(`sealStoreObject`):段里任何一句抛的驱动错
94
+ * 原样回到段的重来环(死锁 / 撞键读原码照判;重来成功 ⇒ 什么都不记),只在离开席位时换成「原码 + 稳定句」(原句只进 `at=store` 运维行,恰一次),
95
+ * 调用方(会话同步两臂 · `PUT …/policy` · 运行腿的锚写)读到的一律是边界形。
96
+ */
97
+ export declare function createSqlLandedAttendantSeat<K>(db: Pick<SqlDriver, "dialect" | "connect">, statements: SqlAttendantStatements<K>): LandedAttendantSeat;
98
+ /** local 席位要的:会话店的落定段 + 三只附随店的动词(规则店是**不计数**的内层店 —— 计数口由段交出,计数外包会回到会话店的锁,锁不可重入)。 */
99
+ export interface LocalAttendantStores {
100
+ readonly sessions: {
101
+ withLanded<T>(sessionId: string, landed: SessionFace, body: (count: () => Promise<void>) => Promise<T>): Promise<LandedOutcome<T>>;
102
+ };
103
+ readonly history: ServiceFileHistoryStore;
104
+ readonly policy: ServiceSessionPolicyStore;
105
+ readonly anchors: {
106
+ put(sessionId: string, eventId: string, entryId: string, owner: string | null): Promise<void>;
107
+ deleteBySession(sessionId: string): Promise<unknown>;
108
+ };
109
+ }
110
+ /** local 落定席位(本地后端与进程内夹具同一只组装)。 */
111
+ export declare function createLocalLandedAttendantSeat(stores: LocalAttendantStores): LandedAttendantSeat;
112
+ /** The history-import capability face of a `FileHistoryStore` (`importHistory` is OPTIONAL on the core
113
+ * contract — a store without it cannot be a 2c history sink). */
114
+ export interface FileHistoryImportFace {
115
+ importHistory(scope: string, data: FileHistoryExport, srcGetBlob: BlobGetter): Promise<FileHistoryResult>;
116
+ }
117
+ /** Single-point capability probe ([ref] R7): does `fs` carry the optional `importHistory` seam?
118
+ * Returns the bound method (never a naked function reference — `this` inside must resolve to `fs`) or
119
+ * `undefined` when absent. Callers gate on the RETURN VALUE, not a separate `typeof` check, so there is
120
+ * exactly one place that knows the shape of the probe. */
121
+ export declare function fileHistoryImportFace(fs: unknown): FileHistoryImportFace | undefined;
122
+ /**
123
+ * {@link replayFileHistory} 的结果 = 店的 {@link FileHistoryResult};失败臂可再带 `missingBlob` —— 这一次尝试里**重放自己交给店的 getter 亲口答过 `undefined`** 的那枚 hash
124
+ * (「这枚 blob 不在」是 getter 观察到的事实,不是从店码里猜的:同一个 `adopt_failed` 也可能是取值抛了 / 发布步撞上库的故障,那两形 `missingBlob` 缺席)。
125
+ * 下发口({@link sendFileHistoryReplayFailure} 在路由里)据它铸 wire `missing_blob`,否则原样送店的码。
126
+ */
127
+ export type FileHistoryReplayResult = {
128
+ readonly ok: true;
129
+ } | {
130
+ readonly ok: false;
131
+ readonly error: FileHistoryError;
132
+ readonly missingBlob?: string;
133
+ };
134
+ export type FileHistoryReplayFailure = Extract<FileHistoryReplayResult, {
135
+ ok: false;
136
+ }>;
137
+ /**
138
+ * **The local seat's history leg** (it runs inside `LocalSessionStore.withLanded`, so the two steps below are serial under the session's
139
+ * write lock; the SQL seat publishes in one transaction instead — `prepareImport` + `publishImportOn`, so the "target left empty" residual
140
+ * below holds on the local backend only). The 2c PUSH replay of a session's file-history graph — keep-SOURCE convergence over core's
141
+ * non-destructive-target law. `importHistory` refuses a target that already holds a DIFFERENT graph
142
+ * (typed `conflict`; the identical envelope re-publishes idempotently). On that arm, when the store has
143
+ * the purge seam, the sync's documented semantic (the destination converges to the source's state, same
144
+ * posture as the policy/anchor replays) is applied: wipe the scope, then import once more. Every bundled
145
+ * store carries the verb (the SQL twins, and core's local File store from core 7.64.0), so the three backends
146
+ * read one rule; a store WITHOUT `deleteBySession` (an embedder's) surfaces the typed conflict unchanged —
147
+ * an honest capability limit, never a silent half-state. The wipe throws on a store fault (and core's stores
148
+ * refuse it while they run a write of the scope): the throw propagates, nothing is re-imported.
149
+ *
150
+ * Honest residual (recorded, not hidden): if the RE-import after the wipe fails (a blob corrupted in
151
+ * transit past the Phase-A presence check), the destination's old graph is already gone and the target
152
+ * is left EMPTY — worse than the moment before this call, but strictly self-healing: the client re-PUTs
153
+ * the blob and re-POSTs, and the retry lands on an empty target (importHistory's first-import arm).
154
+ * The alternative (keeping the old graph) would wedge every retry on the same typed conflict forever.
155
+ *
156
+ * 缺 blob 的事实只在这里读一次:每次尝试给店的 getter 都包一层观察,店取到 `undefined` 就记下那枚 hash(按次计,替换臂的第二次尝试从空白起),
157
+ * 失败时随结果交出({@link FileHistoryReplayResult.missingBlob})。预检(按落点的可见性读 `LandingBlobFaces.visible`,`session-sync.ts`)管「这台部署根本收不到 / 这个落点看不见」,
158
+ * `srcGetBlob` 就是那一次可见性读的取值口(集外答 `undefined`);这里管「预检过了而这一枚取不到」(对象存储里已丢 / 校验和不符按缺席读 / 预检与重放之间被孤儿回收清走)—— 同一只不变量的两端,wire 上同一个词。
159
+ */
160
+ export declare function replayFileHistory(store: ServiceFileHistoryStore, scope: string, envelope: FileHistoryExport, srcGetBlob: BlobGetter, opts: {
161
+ allowReplace: boolean;
162
+ }): Promise<FileHistoryReplayResult>;
163
+ /** [ref] ①(死码 A6 修的移植):同内容判据 —— 比较「归一化、去 rev」后的字节形。putRules 每次
164
+ * 无条件写都 rev+1,而 rev 是 operator 乐观锁的 CAS 令牌(`PutRulesOptions.expectedRev`),
165
+ * 幂等重试/无害重复同步不该把在途 CAS 打失败。归一化用 core 的 `normalizeRules`(store 落盘
166
+ * 前走同一函数 ⇒ 两侧同坐标);它略过店的戳 `rev` / `gen`(`listBySession` 的 rules 含 rev,
167
+ * 它不是内容;core 7.51.0 [ref] 起 `normalizeRules` 自己略过,修前的 `stripRev` 包裹随之退役)。
168
+ * 两侧过的是同一只形读法(core 7.51.0 `readSessionRulesShape`):`incoming` 由写口读者(引擎的写口判官)交出,`stored` 由店的读回交出 ——
169
+ * 店读回读不出形的行答 `corrupt`、根本到不了这里,所以 `normalizeRules` 对两侧都不抛(修前本仓的读回比引擎宽,另有一只判官先挡一次)。
170
+ * 🔴 字节同 ≠ 意思同(core 7.51.2 行自带文法戳;codex r1 [high] 验真):`normalizeRules` 把店的戳 `rev` / `gen` / `grammar` 都略过,而同一串桶字节在两种文法里是两句话 ——
171
+ * 目的行无戳(文法 0:`toolAllow` 里的 `Bash(rm:*)` 什么都不放行)、导入记录带 `grammar: 1`(放行 rm),只比字节会判「同内容」、零次 putRules、同步答 200 而目的行仍是旧意思。
172
+ * 所以字节同之外还问引擎的收紧比对 `loosenReasons` **双向**(两侧各在自己的文法里读:`stored` 带 `rev`,`incoming` 带 `grammar`):两个方向都「没放宽」才是同一句话;
173
+ * 意思不同就交给 `putRules` 的判官(非 operator ⇒ `loosen_forbidden`;operator ⇒ 改写成当前文法、盖戳)。本仓仍零处读 / 比戳值;意思由引擎说。
174
+ * 🔴 core 7.55.0 [ref]:行还有一格 **operator 部分**(`StoredSessionRules.operatorRules`:非 operator 的写只能收回非 operator 写加上去的东西;缺席 = 整行归 operator)。
175
+ * 桶同、意思同,这一次写仍可能挪动它 —— operator 重放把整行变成 operator 的(引擎写口判官的答:operator 写的值整只归 operator)。只比桶会判「同内容」⇒ 零次 putRules ⇒
176
+ * 属主盖过戳的目的行保持「属主收得回」,源端 operator 断言过的条目在目的端被属主一条非 operator 的写收回(安全轴的静默放宽)。所以第三问:这一次写之后的部分
177
+ * = 引擎写口判官对(目的行, 记录, 这次重放的态度)的答,与目的行现有的部分按同一读法(缺席 = 整行)比;不同就交给 `putRules`。判官拒 ⇒ 原样上抛(`putRules` 会拒同一句)。
178
+ * `operator` 必填:同一份记录在 operator 与非 operator 的重放下是两种写(漏传是编译错,不是一条静默的读法)。 */
179
+ export declare function sameRulesContent(stored: StoredSessionRules | null, incoming: SessionPermissionRules, operator: boolean): boolean;
180
+ /** [ref] ① 的重放腿共享实现:PUSH 路由的两条 policy 重放腿(Phase A identical 短路支 / Phase B
181
+ * commit 后支)都从这里走 —— 等内容跳过(rev 零漂移),真变更照常落地(E6 tighten-only 门在
182
+ * putRules 内部,此处不重述)。 */
183
+ export declare function replayPolicyRecords(store: Pick<SessionPolicyStore, "getRules" | "putRules">, sessionId: string, records: readonly SessionRulesRecord[], operatorOk: boolean): Promise<void>;
184
+ /** [ref] ② 能力预检(fail-loud 方向,[ref] 判据:保护型能力缺席=fail-closed):consented
185
+ * overwrite-dst 需要 policy 店的 `deleteBySession` purge seam 才能不留混合态;缺席=true,路由在
186
+ * commit **之前**用它干净中止(此时零写入落地),wire 拒因字面量归路由所有(api-error-text-freeze
187
+ * 锚字面站点)。anchor 店的 deleteBySession 是类型必填、history 店有 core 必填的 `reap` 兜底(+
188
+ * {@link replayFileHistory} 的 conflict 收敛臂),都不构成缺席面;唯一可缺的就是 policy 这条
189
+ * (core 接口上是可选方法)。 */
190
+ export declare function overwriteWipeIncapable(policyStore: ServiceSessionPolicyStore | undefined): boolean;
191
+ /** [ref] ②(死码 ⓪ 擦除步的移植):consented overwrite-dst = keep-source,结果必须是**源端那
192
+ * 一份**,不得混成「源端对话 + 目的端遗留 policy/anchor/历史」(混合态比丢历史更危险:悬空
193
+ * anchor 指向已 purge 的 entry、被放弃分支的 policy 行继续 gating、目的端旧历史图挡住源端图的
194
+ * importHistory 空目标法则)。调用时点=commit(原子 swap)成功**之后**、附随物重放**之前**:
195
+ * 死码在任何写入前擦(其 entries 写本身非原子);活路由有真 commit point,擦在 commit 前会在
196
+ * 「commit 失败」时留下反向混合态(目的端对话完好、附随物已毁)——方向更坏。
197
+ * 诚实残余:进程在 commit 与本函数之间崩溃时,重试落 Phase A identical 支(无 wipe)⇒ 遗留行
198
+ * 可存活;该窗口窄于修前世界(修前=遗留行**恒**存活),与 §8「历史重放失败 ⇒ 422 重试自愈」
199
+ * 同款接受,记录于此不装没有。
200
+ * 各店姿势:file history=deleteBySession(整 scope 清空;blob 走异步孤儿 GC)缺席则 core 必填
201
+ * `reap(scope, [])`(丢全部 boundary;v1 基线按 core 契约留存 —— 随后 {@link replayFileHistory}
202
+ * 的 conflict 臂在有 purge 缝的店上收敛,无缝的店如实 422);anchor=直调(类型必填);
203
+ * policy=deleteBySession(路由已用 {@link overwriteWipeIncapable} 预检过,此处缺席=类型外的
204
+ * JS 层残缺实现,直调抛 TypeError 即 fail-loud)。 */
205
+ export declare function wipeSessionAttendants(stores: {
206
+ fileHistoryStore?: ServiceFileHistoryStore | undefined;
207
+ sessionPolicyStore?: ServiceSessionPolicyStore | undefined;
208
+ resumeAnchorStore?: {
209
+ deleteBySession(sessionId: string): Promise<unknown>;
210
+ } | undefined;
211
+ }, sessionId: string): Promise<void>;
212
+ //# sourceMappingURL=landed-attendants.d.ts.map
@@ -0,0 +1,161 @@
1
+ import { judgeSessionRulesWrite, loosenReasons, normalizeRules } from "@sema-agent/core";
2
+ import { withLandedRow } from "./session-row-sql.js";
3
+ import { putAnchorOn, deleteAnchorsOn } from "./resume-anchor-store-sql.js";
4
+ import { sealStoreObject } from "./store-boundary.js";
5
+ function observedGetter(getter) {
6
+ let missing;
7
+ return {
8
+ get: async (hash) => {
9
+ const bytes = await getter(hash);
10
+ if (bytes === undefined && missing === undefined)
11
+ missing = hash;
12
+ return bytes;
13
+ },
14
+ missing: () => missing,
15
+ };
16
+ }
17
+ function withMissing(r, missing) {
18
+ return r.ok || missing === undefined ? r : { ok: false, error: r.error, missingBlob: missing };
19
+ }
20
+ function dupKeyRetry(policy) {
21
+ return { alsoRetry: (err) => policy.isDupKeyError(err) };
22
+ }
23
+ function countedUnlessSame(rules, operator) {
24
+ return { count: true, skip: (prior) => sameRulesContent(prior, rules, operator) };
25
+ }
26
+ export function createSqlLandedAttendantSeat(db, statements) {
27
+ const { history, policy } = statements;
28
+ return sealStoreObject({
29
+ async wipe(sessionId, landed) {
30
+ const out = await withLandedRow(db, sessionId, landed, async (tx) => {
31
+ await history.deleteScopeOn(tx, sessionId);
32
+ await deleteAnchorsOn(tx, db.dialect, sessionId);
33
+ return policy.eraseOn(tx, sessionId);
34
+ });
35
+ if (!out.landed)
36
+ return out;
37
+ policy.discloseErased(sessionId, out.value);
38
+ return { landed: true, value: undefined };
39
+ },
40
+ async replayHistory(sessionId, landed, envelope, getter, opts) {
41
+ const observed = observedGetter(getter);
42
+ const plan = await history.prepareImport(sessionId, envelope, observed.get, { replace: opts.allowReplace });
43
+ if (!plan.ok) {
44
+ const still = await withLandedRow(db, sessionId, landed, async () => undefined);
45
+ return still.landed ? { landed: true, value: withMissing(plan, observed.missing()) } : still;
46
+ }
47
+ try {
48
+ return await withLandedRow(db, sessionId, landed, async (tx) => withMissing(await history.publishImportOn(tx, sessionId, envelope, plan, { replace: opts.allowReplace }), observed.missing()));
49
+ }
50
+ catch (err) {
51
+ return { landed: true, value: withMissing({ ok: false, error: history.importFailureOf(err) }, observed.missing()) };
52
+ }
53
+ },
54
+ async replayPolicy(sessionId, landed, records, operator) {
55
+ for (const rec of records) {
56
+ const one = await withLandedRow(db, sessionId, landed, (tx) => policy.putRulesOn(tx, sessionId, rec.principal, rec.rules, { operator }, countedUnlessSame(rec.rules, operator)), dupKeyRetry(policy));
57
+ if (!one.landed)
58
+ return one;
59
+ }
60
+ return { landed: true, value: undefined };
61
+ },
62
+ async putPolicy(sessionId, landed, principal, rules, opts) {
63
+ const out = await withLandedRow(db, sessionId, landed, (tx) => policy.putRulesOn(tx, sessionId, principal, rules, opts, { count: true }), dupKeyRetry(policy));
64
+ if (!out.landed)
65
+ return out;
66
+ if ("skipped" in out.value)
67
+ throw new Error("createSqlLandedAttendantSeat.putPolicy: no skip predicate was given, yet the write was skipped");
68
+ return { landed: true, value: out.value };
69
+ },
70
+ async putAnchors(sessionId, landed, anchors, owner) {
71
+ const out = await withLandedRow(db, sessionId, landed, async (tx) => {
72
+ for (const a of anchors)
73
+ await putAnchorOn(tx, db.dialect, sessionId, a.eventId, a.entryId, owner);
74
+ });
75
+ return out.landed ? { landed: true, value: undefined } : out;
76
+ },
77
+ }, "sql-landed-attendants", { wipe: "exit", replayHistory: "exit", replayPolicy: "exit", putPolicy: "exit", putAnchors: "exit" });
78
+ }
79
+ export function createLocalLandedAttendantSeat(stores) {
80
+ const { sessions, history, policy, anchors } = stores;
81
+ const counted = (count) => ({
82
+ getRules: (sessionId, principal) => policy.getRules(sessionId, principal),
83
+ putRules: async (sessionId, principal, rules, opts) => {
84
+ await count();
85
+ return policy.putRules(sessionId, principal, rules, opts);
86
+ },
87
+ });
88
+ return {
89
+ wipe: (sessionId, landed) => sessions.withLanded(sessionId, landed, () => wipeSessionAttendants({ fileHistoryStore: history, sessionPolicyStore: policy, resumeAnchorStore: anchors }, sessionId)),
90
+ replayHistory: (sessionId, landed, envelope, getter, opts) => sessions.withLanded(sessionId, landed, () => replayFileHistory(history, sessionId, envelope, getter, opts)),
91
+ replayPolicy: (sessionId, landed, records, operator) => sessions.withLanded(sessionId, landed, (count) => replayPolicyRecords(counted(count), sessionId, records, operator)),
92
+ putPolicy: (sessionId, landed, principal, rules, opts) => sessions.withLanded(sessionId, landed, (count) => counted(count).putRules(sessionId, principal, rules, opts)),
93
+ putAnchors: (sessionId, landed, list, owner) => sessions.withLanded(sessionId, landed, async () => {
94
+ for (const a of list)
95
+ await anchors.put(sessionId, a.eventId, a.entryId, owner);
96
+ }),
97
+ };
98
+ }
99
+ export function fileHistoryImportFace(fs) {
100
+ const candidate = fs?.importHistory;
101
+ if (typeof candidate !== "function")
102
+ return undefined;
103
+ return { importHistory: candidate.bind(fs) };
104
+ }
105
+ export async function replayFileHistory(store, scope, envelope, srcGetBlob, opts) {
106
+ const face = fileHistoryImportFace(store);
107
+ if (face === undefined) {
108
+ return { ok: false, error: { code: "unsupported_format", message: "this deployment's file-history store has no importHistory seam" } };
109
+ }
110
+ const attempt = async () => {
111
+ const observed = observedGetter(srcGetBlob);
112
+ return withMissing(await face.importHistory(scope, envelope, observed.get), observed.missing());
113
+ };
114
+ let r = await attempt();
115
+ if (!r.ok && r.error.code === "conflict" && opts.allowReplace && typeof store.deleteBySession === "function") {
116
+ await store.deleteBySession(scope);
117
+ r = await attempt();
118
+ }
119
+ return r;
120
+ }
121
+ export function sameRulesContent(stored, incoming, operator) {
122
+ if (stored === null)
123
+ return false;
124
+ const norm = (r) => JSON.stringify(normalizeRules(r));
125
+ if (norm(stored) !== norm(incoming))
126
+ return false;
127
+ if (loosenReasons(stored, incoming).length !== 0 || loosenReasons(incoming, stored).length !== 0)
128
+ return false;
129
+ return operatorPartUnmoved(stored, incoming, operator);
130
+ }
131
+ function operatorPartUnmoved(stored, incoming, operator) {
132
+ const next = judgeSessionRulesWrite(stored, incoming, { operator });
133
+ const partOf = (row) => JSON.stringify(normalizeRules(row.operatorRules ?? row));
134
+ return partOf(next) === partOf(stored);
135
+ }
136
+ export async function replayPolicyRecords(store, sessionId, records, operatorOk) {
137
+ for (const rec of records) {
138
+ const cur = await store.getRules(sessionId, rec.principal);
139
+ if (sameRulesContent(cur, rec.rules, operatorOk))
140
+ continue;
141
+ await store.putRules(sessionId, rec.principal, rec.rules, { operator: operatorOk });
142
+ }
143
+ }
144
+ export function overwriteWipeIncapable(policyStore) {
145
+ return policyStore !== undefined && typeof policyStore.deleteBySession !== "function";
146
+ }
147
+ export async function wipeSessionAttendants(stores, sessionId) {
148
+ const fs = stores.fileHistoryStore;
149
+ if (fs !== undefined) {
150
+ if (typeof fs.deleteBySession === "function")
151
+ await fs.deleteBySession(sessionId);
152
+ else
153
+ await fs.reap(sessionId, []);
154
+ }
155
+ if (stores.resumeAnchorStore !== undefined)
156
+ await stores.resumeAnchorStore.deleteBySession(sessionId);
157
+ const policy = stores.sessionPolicyStore;
158
+ if (policy !== undefined)
159
+ await policy.deleteBySession(sessionId);
160
+ }
161
+ //# sourceMappingURL=landed-attendants.js.map
@@ -5,6 +5,7 @@ import { decodeNullableJsonColumn, foldJsonColumn, jsonColumnText, readNonNullJs
5
5
  import { ensureIndexes } from "./ensure-index.js";
6
6
  import { buildObjectivePreview } from "../user-authored-text.js";
7
7
  import { RUN_IDENTITY_COLUMNS, readRunIdentityCells, runIdentityCells } from "../identity-source.js";
8
+ import { sealStoreClass } from "./store-boundary.js";
8
9
  export const LEADER_RUN_TABLE = "leader_run";
9
10
  const LEADER_RUN_STATUSES = new Set(["running", "completed", "failed", "needs_human"]);
10
11
  const LEADER_RUN_ERROR_CODES = new Set(["cancelled"]);
@@ -173,6 +174,9 @@ export class SqlLeaderRunStore {
173
174
  return res.affected > 0;
174
175
  }
175
176
  }
177
+ sealStoreClass(SqlLeaderRunStore, "sql-leader-run-store", {
178
+ createRun: "exit", getRun: "exit", getByIdem: "exit", requestCancel: "exit", reapStaleRunning: "exit", backdateStartedAtForTest: "exit", finishRun: "exit",
179
+ });
176
180
  export class TiDBLeaderRunStore extends SqlLeaderRunStore {
177
181
  constructor(pool) {
178
182
  super(mysqlDriver(pool));
@@ -1,5 +1,5 @@
1
1
  import { type Checkpoint, type CheckpointPage, type CheckpointRowRead, type CheckpointSessionCursor, type CheckpointSessionQuery, type CheckpointSummary, type CheckpointToken, type PendingSteerInput, type ReopenReason, type ResolveExpectation, type ExecutionOutcomeRecordWord, type GateOutcome, type ResumeOutcome, type StoreDurability, type StoreFidelity } from "@sema-agent/core";
2
- import { type CheckpointAskCandidate, type CtxClaimPut, type CtxClaimRewrite, type CtxRowRewrite, type CtxRowsRewrite, type DecidedApprovalRecord, type ExpiredApprovalGate, type ExpiredGatePosition, type PendingCheckpoint, type PendingRowBinding } from "./checkpoint-store-face.js";
2
+ import { type CheckpointAskCandidate, type CtxClaimPut, type CtxClaimRewrite, type CtxRowRewrite, type CtxRowsRewrite, type DecidedApprovalRecord, type ExpiredApprovalGate, type ExpiredGatePosition, type PendingCheckpoint, type PendingRowBinding, type CardScopeRootSeat } from "./checkpoint-store-face.js";
3
3
  import { type CtxWriteClaim } from "./store-contracts.js";
4
4
  import type { SealedCheckpointCtx } from "../http/checkpoint-ctx.js";
5
5
  /**
@@ -16,6 +16,8 @@ export interface LocalCheckpointStoreOptions {
16
16
  /** E21 owner guard (the LocalSessionStore's owner read, `headOf(id)?.owner`: `undefined` = no session row). Absent ⇒ owner guard degrades
17
17
  * to null-owner-only (a non-null owner with no owner source purges NOTHING — fail-closed, mirrors the SQL EXISTS guard). */
18
18
  readSessionOwner?: (sessionId: string) => Promise<string | null | undefined>;
19
+ /** 「不再询问」规则 project root 的铸卡快照席(SQL 孪生同一只;缺席 = 永不绑 ⇒ 不记快照)。 */
20
+ cardScopeRoot?: CardScopeRootSeat;
19
21
  }
20
22
  /** checkpoint 店在数据根下自己铸的目录(构造器与一次性迁移 M39 的名册同读这一只)。 */
21
23
  export declare function localCheckpointStoreDirsFor(root: string): {
@@ -85,6 +87,12 @@ export declare class LocalCheckpointStore {
85
87
  private readonly hostTokens;
86
88
  private readonly hostOfToken;
87
89
  private readonly hostSessionsPath;
90
+ /**
91
+ * **铸卡快照索引**:每张卡上「不再询问」规则的 project root(SQL 孪生 `checkpoint.card_scope_root` 列在本店的同一个事实;`put` 读席一次)。不可知 ⇒ 不登记
92
+ * (读作 `null`,兑付不铸 scope)。与归属索引同一条落盘纪律(先登记、后内核 put;整文件原子替换)。
93
+ */
94
+ private readonly cardScopeRoots;
95
+ private readonly cardScopeRootsPath;
88
96
  private readonly opts;
89
97
  constructor(root: string, opts?: LocalCheckpointStoreOptions);
90
98
  /**
@@ -180,8 +188,8 @@ export declare class LocalCheckpointStore {
180
188
  *
181
189
  * 🔴 **为什么必须有这一口**(不是锦上添花):[ref] 让 local 车道有了持久 ask 账,于是收敛器在这条车道上
182
190
  * 第一次真的有行可扫。缺这一口 ⇒ 判据 1 结构性不命中 ⇒ **窗到期 park 的 ask 行永远停在 `PARKING`**,
183
- * 而那个态在 wire 上是有后果的:`POST /v1/tool-approvals/:id/respond` 的 `PARKING` 臂答的是
184
- * `202 parking_in_progress + retryAfterMs`(它的前提是「`bindBatch` 毫秒级就到」),在一台绑不了的机器上
191
+ * 而那个态在 wire 上是有后果的:决断口 `POST /v1/tasks/:taskId/asks/:askId/decision` 命中 `PARKING` 行答的是
192
+ * 一次带退避的「稍后再试」(它的前提是「`bindBatch` 毫秒级就到」),在一台绑不了的机器上
185
193
  * 那句「再试一次」**永远不会兑现**;run 跑到终局后判据 2 还会把它收成
186
194
  * `DENIED(routing_failure_fail_closed)` ⇒ 迟到答拿到的判别位是 `denied` —— 对一条**人真的批准过**的 ask
187
195
  * 撒谎。两条都是相对 7.80.2 的回归,根因同一个:**判据 1 的读口只有 SQL 孪生有**。修在源头 = 把这一口
@@ -216,6 +224,8 @@ export declare class LocalCheckpointStore {
216
224
  peekPendingScope(sessionId: string, binding?: PendingRowBinding): Promise<string | null | undefined>;
217
225
  /** 归在这只 run 会话上的待决卡(归属索引 → 逐张 `get`;只认 pending,scope 给了就再判一次)。 */
218
226
  private runPendings;
227
+ /** SQL 孪生 `cardScopeRootOf` 的本地形(铸卡快照索引;不在 ⇒ `null`)。 */
228
+ cardScopeRootOf(token: CheckpointToken): Promise<string | null>;
219
229
  /** SQL 孪生 `hostSessionOfCard` 的本地形:`undefined` = 没有这一行;`null` = 行在、归属索引里没有它(M49 还没回填到的存量卡)。 */
220
230
  hostSessionOfCard(token: CheckpointToken): Promise<string | null | undefined>;
221
231
  /**
@@ -1,22 +1,19 @@
1
1
  import { writeLogText } from "../observability/logger.js";
2
2
  import { z } from "zod";
3
- import { denySweepOwns, parkedApprovalCard } from "../approval-content-kind.js";
4
- import { parkRowFacts, skillCardFacts } from "../approval-card.js";
5
- import { durableRowIdentity } from "../checkpoint-identity.js";
3
+ import { denySweepOwns } from "../approval-content-kind.js";
6
4
  import { createHash } from "node:crypto";
7
5
  import { closeSync, existsSync, fsyncSync, openSync, readFileSync, readdirSync, rmSync, unlinkSync } from "node:fs";
8
6
  import { IS_WIN32 } from "./host-platform.js";
9
7
  import { join } from "node:path";
10
- import { CHECKPOINT_LIST_LIMITS, FileCheckpointStore, atomicWriteFile, checkpointDeadlinePassed, ensureDir, executionVerdict, sanitizePathComponent, } from "@sema-agent/core";
8
+ import { CHECKPOINT_LIST_LIMITS, FileCheckpointStore, judgeCheckpointRow, summarizeCheckpoint, atomicWriteFile, checkpointDeadlinePassed, ensureDir, executionVerdict, sanitizePathComponent, } from "@sema-agent/core";
11
9
  import { approvalPayloadFingerprint } from "./approval-payload-fingerprint.js";
12
- import { approvalDecisionOfWinner, boundedRuleOffers, boundedToolInput, candidateIdentityOf, DENY_SWEEP_PAGE_ROWS, isUnreadableSummaryForm, parkedLegTaskId, pendingRowPrecedes, queueRowGateKind, queueTriageOrder, readRiskDescriptorBody, TERMINAL_BACKSTOP_MS, TERMINAL_GRACE_MS, } from "./checkpoint-store-face.js";
10
+ import { approvalDecisionOfWinner, buildQueueActionFacts, buildQueueRow, candidateIdentityOf, DENY_SWEEP_PAGE_ROWS, pendingRowPrecedes, queueRowGateKind, queueTriageOrder, TERMINAL_BACKSTOP_MS, TERMINAL_GRACE_MS, } from "./checkpoint-store-face.js";
13
11
  import { quarantineUnreadableSidecar } from "./local-sidecar-quarantine.js";
14
12
  import { hostSessionOf } from "./checkpoint-index-columns.js";
15
- import { createZodColumnReader, decodeJsonColumn, foldJsonColumn, isJsonObject, readStringArrayColumn } from "./sql-json-column.js";
13
+ import { createZodColumnReader, decodeJsonColumn, foldJsonColumn, readStringArrayColumn } from "./sql-json-column.js";
16
14
  import { UNMANAGED_RETENTION } from "./retention-declaration.js";
17
15
  import { assertJsonColumnWritable, createObjectColumnReader } from "./sql-json-column.js";
18
16
  import { FENCE_LANDED } from "./store-contracts.js";
19
- import { recordFailOpen } from "../observability/fail-open.js";
20
17
  const isFiniteNumber = (v) => typeof v === "number" && Number.isFinite(v);
21
18
  function terminalAtOf(cp) {
22
19
  const createdAt = cp.createdAt;
@@ -32,16 +29,6 @@ function sweepDeadlineKey(deadline) {
32
29
  function sweepPositionPrecedes(a, b) {
33
30
  return a.deadline < b.deadline || (a.deadline === b.deadline && a.token < b.token);
34
31
  }
35
- function queueRiskDescriptorOf(gate) {
36
- const raw = isJsonObject(gate) ? gate.riskDescriptor : undefined;
37
- if (raw === undefined || raw === null)
38
- return null;
39
- const shape = readRiskDescriptorBody(raw);
40
- if (shape.problem === undefined)
41
- return shape.value;
42
- recordFailOpen("server.approvals.risk-descriptor-cell-unreadable");
43
- return null;
44
- }
45
32
  function ctxFileOf(sessionId) {
46
33
  return `${sanitizePathComponent(sessionId).slice(0, 48)}-${createHash("sha256").update(sessionId).digest("hex").slice(0, 12)}.json`;
47
34
  }
@@ -69,6 +56,7 @@ const CtxRecordSchema = z.object({
69
56
  const readCtxRecord = createZodColumnReader(CtxRecordSchema);
70
57
  const readScopeRegistry = readStringArrayColumn;
71
58
  const readSessionTokenIndex = createZodColumnReader(z.record(z.string(), z.array(z.string())));
59
+ const readCardScopeRootIndex = createZodColumnReader(z.record(z.string(), z.string()));
72
60
  function createCtxRecordReader() {
73
61
  const readPayload = createObjectColumnReader();
74
62
  return (body) => {
@@ -107,6 +95,8 @@ export class LocalCheckpointStore {
107
95
  hostTokens = new Map();
108
96
  hostOfToken = new Map();
109
97
  hostSessionsPath;
98
+ cardScopeRoots = new Map();
99
+ cardScopeRootsPath;
110
100
  opts;
111
101
  constructor(root, opts = {}) {
112
102
  this.inner = new FileCheckpointStore(root);
@@ -115,6 +105,7 @@ export class LocalCheckpointStore {
115
105
  this.scopesPath = join(root, "checkpoint-scopes.json");
116
106
  this.sessionTokensPath = join(root, "checkpoint-session-tokens.json");
117
107
  this.hostSessionsPath = join(root, "checkpoint-host-sessions.json");
108
+ this.cardScopeRootsPath = join(root, "checkpoint-card-scope-roots.json");
118
109
  const dirs = localCheckpointStoreDirsFor(root);
119
110
  this.ctxDir = dirs.ctx;
120
111
  this.tmpDir = dirs.tmp;
@@ -146,6 +137,11 @@ export class LocalCheckpointStore {
146
137
  this.indexHost(host, toks);
147
138
  }
148
139
  }
140
+ if (existsSync(this.cardScopeRootsPath)) {
141
+ for (const [tok, root] of Object.entries(decodeJsonColumn(readFileSync(this.cardScopeRootsPath, "utf8"), readCardScopeRootIndex, "checkpoint-card-scope-roots.json (the local card→rule-scope-root snapshot index)"))) {
142
+ this.cardScopeRoots.set(tok, root);
143
+ }
144
+ }
149
145
  }
150
146
  registerDurably(record, undo, persist) {
151
147
  if (!record())
@@ -188,6 +184,10 @@ export class LocalCheckpointStore {
188
184
  const host = hostSessionOf(cp);
189
185
  this.registerDurably(() => !this.scopes.has(cp.scope) && (this.scopes.add(cp.scope), true), () => this.scopes.delete(cp.scope), () => atomicWriteFile(this.tmpDir, this.scopesPath, JSON.stringify([...this.scopes])));
190
186
  this.registerDurably(() => this.indexHost(host, [token]) > 0, () => this.unindexHost(host, token), () => this.persistHostSessions());
187
+ const scopeRoot = this.opts.cardScopeRoot?.of(cp.sessionId);
188
+ if (scopeRoot !== undefined) {
189
+ this.registerDurably(() => !this.cardScopeRoots.has(token) && (this.cardScopeRoots.set(token, scopeRoot), true), () => this.cardScopeRoots.delete(token), () => atomicWriteFile(this.tmpDir, this.cardScopeRootsPath, JSON.stringify(Object.fromEntries(this.cardScopeRoots))));
190
+ }
191
191
  this.registerDurably(() => {
192
192
  if (this.sessionTokens.get(cp.sessionId)?.has(token))
193
193
  return false;
@@ -283,45 +283,31 @@ export class LocalCheckpointStore {
283
283
  }
284
284
  async listPending(scope) {
285
285
  const rows = [];
286
- for (const { token, cp, summary } of await this.pendings(scope)) {
286
+ for (const { token, cp, summary: listed } of await this.pendings(scope)) {
287
+ let summary = listed;
288
+ let reading;
289
+ try {
290
+ summary = summarizeCheckpoint(cp, () => { });
291
+ reading = { rowVerdict: summary.rowVerdict, cp, summary };
292
+ }
293
+ catch {
294
+ reading = { rowVerdict: judgeCheckpointRow(cp), cp };
295
+ }
287
296
  const gateKind = queueRowGateKind(summary.gateKind);
288
297
  if (gateKind === undefined)
289
298
  continue;
290
- const joinKey = durableRowIdentity("approvals-queue", summary.checkpointId, token);
291
299
  const host = this.hostOfToken.get(token);
292
- const taskId = parkedLegTaskId(cp.state?.rowTaskId, host === undefined ? null : ((await this.opts.getActiveTaskId?.(host)) ?? null));
293
- const createdAt = summary.createdAt !== undefined ? { createdAt: summary.createdAt } : {};
294
- const deadline = summary.deadline ?? null;
295
- if (isUnreadableSummaryForm(summary)) {
296
- rows.push({ sessionId: summary.sessionId, ...joinKey, scope: summary.scope, toolName: null, toolCallId: null, gateKind, taskId, input: null, ...createdAt, deadline, riskDescriptor: null, rowVerdict: summary.rowVerdict });
297
- continue;
298
- }
299
- const pa = cp.pendingAction;
300
- const toolCallId = pa?.toolCallId ?? null;
301
- rows.push({
300
+ const claimHolder = host === undefined ? null : ((await this.opts.getActiveTaskId?.(host)) ?? null);
301
+ const address = {
302
+ token,
302
303
  sessionId: summary.sessionId,
303
- ...joinKey,
304
304
  scope: summary.scope,
305
- toolName: pa?.toolName ?? null,
306
- toolCallId,
307
- ...(toolCallId !== null ? { boundCallId: toolCallId } : {}),
308
- ...(pa?.boundInputHash !== undefined ? { boundInputHash: pa.boundInputHash } : {}),
309
305
  gateKind,
310
- taskId,
311
- input: boundedToolInput(pa?.args),
312
- ...createdAt,
313
- deadline,
314
- riskDescriptor: queueRiskDescriptorOf(cp.gate),
315
- ...(() => {
316
- const rs = boundedRuleOffers(pa?.ruleOffers);
317
- return rs !== undefined ? { ruleOffers: rs } : {};
318
- })(),
319
- ...(pa?.hasBidiControls === true ? { hasBidiControls: true } : {}),
320
- ...((card) => (card !== undefined ? { approvalCard: card } : {}))(parkedApprovalCard(cp.gate)),
321
- ...parkRowFacts(cp.pendingAction),
322
- ...skillCardFacts(summary),
323
- rowVerdict: summary.rowVerdict,
324
- });
306
+ ...(summary.createdAt !== undefined ? { createdAt: summary.createdAt } : {}),
307
+ deadline: summary.deadline ?? null,
308
+ claimHolder,
309
+ };
310
+ rows.push(buildQueueRow(address, buildQueueActionFacts(reading)));
325
311
  }
326
312
  return rows.sort(queueTriageOrder);
327
313
  }
@@ -414,6 +400,9 @@ export class LocalCheckpointStore {
414
400
  }
415
401
  return out;
416
402
  }
403
+ async cardScopeRootOf(token) {
404
+ return this.cardScopeRoots.get(token) ?? null;
405
+ }
417
406
  async hostSessionOfCard(token) {
418
407
  const host = this.hostOfToken.get(token);
419
408
  if (host !== undefined)