@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
@@ -9,6 +9,7 @@ import { decodeJsonColumn, foldJsonColumn, jsonColumnText, readJsonObjectColumn,
9
9
  import { ensureIndexes } from "./ensure-index.js";
10
10
  import { isExecutionLane } from "../execution-lane-caps.js";
11
11
  import { retiredExecutionLaneHintM40 } from "./execution-lane-rename-m40.js";
12
+ import { sealStoreClass } from "./store-boundary.js";
12
13
  export function assertIntegralEpochMs(field, value) {
13
14
  if (!Number.isSafeInteger(value)) {
14
15
  throw new TypeError(`approval-ask store: ${field} must be an integer epoch-ms (BIGINT column), got ${String(value)}`);
@@ -120,6 +121,13 @@ export function projectAskTerminalClaimTruth(row) {
120
121
  export function askRowOnCall(row, call) {
121
122
  return row.taskId === call.taskId && row.legKey === call.legKey && row.toolCallId === call.toolCallId && row.sourceSessionId === call.sourceSessionId;
122
123
  }
124
+ export function askAtGate(r, sourceSessionId, binding) {
125
+ if (r.sourceSessionId !== sourceSessionId)
126
+ return false;
127
+ if (r.state === "PARKED")
128
+ return r.gateBoundCallId === binding.boundCallId && r.gateBoundInputHash === binding.boundInputHash;
129
+ return r.state === "PARKING" && r.toolCallId === binding.boundCallId && r.boundInputHash === binding.boundInputHash;
130
+ }
123
131
  export function askRowCarriesOwner(row, owner) {
124
132
  return row !== null && row.owner === owner;
125
133
  }
@@ -565,11 +573,7 @@ export class SqlApprovalAskStore {
565
573
  let askRes;
566
574
  try {
567
575
  askRes = await conn.query(`UPDATE ${APPROVAL_ASK_TABLE} SET state='DECIDED', decision=${ph(dialect, 1)}, decision_actor=${ph(dialect, 2)}, decision_note=${ph(dialect, 3)}, settled_by=${ph(dialect, 4)}, decided_via=${ph(dialect, 5)}, updated_input=${ph(dialect, 6)}, decided_at_ms=${ph(dialect, 7)}, idempotency_key=${ph(dialect, 8)}, rev=rev+1, updated_at_ms=${ph(dialect, 9)} WHERE ${pendingClaimWhere(dialect, 10)} AND ${ownerWhere.sql}`, [
568
- decision.decision,
569
- decision.decisionActor == null ? null : this.json(decision.decisionActor),
570
- decision.decisionNote ?? null,
571
- decision.settledBy ?? null,
572
- decision.decidedVia ?? null,
576
+ ...this.decisionRecordValues(decision),
573
577
  decision.updatedInput === undefined ? null : this.json(decision.updatedInput),
574
578
  now,
575
579
  decision.idempotencyKey ?? null,
@@ -608,6 +612,32 @@ export class SqlApprovalAskStore {
608
612
  throw new Error(`decideAsk: row vanished after commit (askId=${askId})`);
609
613
  return { ok: true, row };
610
614
  }
615
+ decisionRecordValues(record) {
616
+ return [record.decision, record.decisionActor == null ? null : this.json(record.decisionActor), record.decisionNote ?? null, record.settledBy ?? null, record.decidedVia ?? null];
617
+ }
618
+ async recordParkedDecision(askId, owner, record) {
619
+ if (record.idempotencyKey != null)
620
+ assertIdempotencyKeyShape(record.idempotencyKey);
621
+ assertDecideSource(record);
622
+ const now = Date.now();
623
+ const dialect = this.db.dialect;
624
+ const ownerWhere = decideOwnerWhere(dialect, owner, 10);
625
+ let res;
626
+ try {
627
+ res = await this.db.query(`UPDATE ${APPROVAL_ASK_TABLE} SET decision=${ph(dialect, 1)}, decision_actor=${ph(dialect, 2)}, decision_note=${ph(dialect, 3)}, settled_by=${ph(dialect, 4)}, decided_via=${ph(dialect, 5)}, decided_at_ms=${ph(dialect, 6)}, idempotency_key=${ph(dialect, 7)}, rev=rev+1, updated_at_ms=${ph(dialect, 8)} WHERE ask_id = ${ph(dialect, 9)} AND state = 'PARKED' AND ${ownerWhere.sql}`, [...this.decisionRecordValues(record), now, record.idempotencyKey ?? null, now, askId, ...ownerWhere.params]);
628
+ }
629
+ catch (err) {
630
+ if (this.isDupKey(err))
631
+ return { ok: false, reason: "idempotency_conflict", row: projectDecideReading(await this.getAsk(askId), owner) };
632
+ throw err;
633
+ }
634
+ const row = projectDecideReading(await this.getAsk(askId), owner);
635
+ if (res.affected !== 1)
636
+ return { ok: false, reason: "ask_not_parked", row };
637
+ if (row === null)
638
+ throw new Error(`recordParkedDecision: row vanished after write (askId=${askId})`);
639
+ return { ok: true, row };
640
+ }
611
641
  async claimTerminal(askId, batchId, intent, opts) {
612
642
  const to = claimTargetState(intent);
613
643
  if (!canAskTransition("STREAM_PENDING", to)) {
@@ -794,6 +824,10 @@ export class SqlApprovalAskStore {
794
824
  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]);
795
825
  return rows.map(mapAskRow).filter((r) => r.sourceSessionId === sourceSessionId);
796
826
  }
827
+ async listAsksAtGate(sourceSessionId, binding) {
828
+ const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE source_task_id = ? AND ((state = 'PARKED' AND gate_bound_call_id = ? AND gate_bound_input_hash = ?) OR (state = 'PARKING' AND tool_call_id = ? AND bound_input_hash = ?)) ORDER BY created_at_ms ASC, ask_id ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE source_task_id = $1 AND ((state = 'PARKED' AND gate_bound_call_id = $2 AND gate_bound_input_hash = $3) OR (state = 'PARKING' AND tool_call_id = $2 AND bound_input_hash = $3)) ORDER BY created_at_ms ASC, ask_id ASC`), [sourceSessionId, binding.boundCallId, binding.boundInputHash, binding.boundCallId, binding.boundInputHash]);
829
+ return rows.map(mapAskRow).filter((r) => askAtGate(r, sourceSessionId, binding));
830
+ }
797
831
  async getAsk(askId) {
798
832
  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`), [
799
833
  askId,
@@ -877,6 +911,12 @@ export class SqlApprovalAskStore {
877
911
  return rows[0] ? mapBatchRow(rows[0]) : null;
878
912
  }
879
913
  }
914
+ sealStoreClass(SqlApprovalAskStore, "sql-approval-ask-store", {
915
+ ensureAsk: "exit", transitionAsk: "exit", decideAsk: "exit", claimTerminal: "exit", expireAsk: "exit", bindBatch: "exit", abortBatch: "exit",
916
+ listByState: "exit", listPendingByTask: "exit", listPendingBySession: "exit", listByCall: "exit", listParkingBySourceSession: "exit", getAsk: "exit",
917
+ getByIdempotencyKey: "exit", deferReconcile: "exit", resolveProvisional: "exit", deleteBySession: "exit", reapSettledAsks: "exit", reapEmptyBatches: "exit",
918
+ getBatch: "exit", recordParkedDecision: "exit", listAsksAtGate: "exit",
919
+ });
880
920
  export class TiDBApprovalAskStore extends SqlApprovalAskStore {
881
921
  constructor(pool) {
882
922
  super(mysqlDriver(pool));
@@ -2,6 +2,7 @@ import { join } from "node:path";
2
2
  import { existsSync, readdirSync, rmSync } from "node:fs";
3
3
  import { AppendLog, ensureDir, sanitizePathComponent } from "@sema-agent/core";
4
4
  import { replayJsonlGuarded } from "../observability/corrupt-read-seat.js";
5
+ import { sealStoreClass } from "./store-boundary.js";
5
6
  export const APPROVAL_EXEMPTED_EVENT = "approval_exempted";
6
7
  export class TiDBApprovalExemptionStore {
7
8
  pool;
@@ -33,6 +34,7 @@ export class TiDBApprovalExemptionStore {
33
34
  return r.affectedRows;
34
35
  }
35
36
  }
37
+ sealStoreClass(TiDBApprovalExemptionStore, "tidb-approval-exemption-store", { grant: "exit", has: "exit", list: "exit", revoke: "exit", deleteBySession: "exit" });
36
38
  export class PgApprovalExemptionStore {
37
39
  pool;
38
40
  constructor(pool) {
@@ -69,6 +71,7 @@ export class PgApprovalExemptionStore {
69
71
  return res.rowCount ?? 0;
70
72
  }
71
73
  }
74
+ sealStoreClass(PgApprovalExemptionStore, "pg-approval-exemption-store", { grant: "exit", has: "exit", list: "exit", revoke: "exit", deleteBySession: "exit" });
72
75
  export class MemoryApprovalExemptionStore {
73
76
  bySession = new Map();
74
77
  async grant(sessionId, toolName, grantedBy) {
@@ -4,6 +4,7 @@ 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
6
  import { createLogger } from "../observability/logger.js";
7
+ import { sealStoreClass } from "./store-boundary.js";
7
8
  export const APPROVAL_NONCE_TABLE = "approval_nonce";
8
9
  export const MAX_APPROVAL_NONCE_CHARS = 190;
9
10
  export const APPROVAL_NONCE_FLOOR_TABLE = "approval_nonce_floor";
@@ -62,6 +63,7 @@ export class SqlApprovalNonceStore {
62
63
  return res.affected;
63
64
  }
64
65
  }
66
+ sealStoreClass(SqlApprovalNonceStore, "sql-approval-nonce-store", { nowMs: "exit", consume: "exit", reapExpired: "exit" });
65
67
  export class TiDBApprovalNonceStore extends SqlApprovalNonceStore {
66
68
  constructor(pool, opts) {
67
69
  super(mysqlDriver(pool), opts);
@@ -1,3 +1,5 @@
1
+ import { type ObjectStoreOp } from "../object-store-buckets.js";
2
+ import type { SessionBlobNamespace } from "./session-blob-namespace.js";
1
3
  /**
2
4
  * The byte port. Keys are opaque to it (today every index owner keys a blob by its sha256 hash).
3
5
  * - `put`: store `bytes` under `key`. Idempotent (a repeat for the same key overwrites with the identical bytes); a rejection is a
@@ -5,7 +7,10 @@
5
7
  * - `get`: the bytes under `key`, or `undefined` when nothing is there. A TRANSIENT fault THROWS (so a restore / import fails LOUD,
6
8
  * not as a silent "missing blob"). The index owner checks the bytes against the hash ({@link readAtAddress}).
7
9
  * - `delete`: remove the bytes under each key. Idempotent — a key with nothing under it is a success; a key that could not be removed
8
- * makes the call reject (after every key was tried).
10
+ * makes the call reject (after every key was tried). A port whose deletes wait on a precondition (the session blob ports: the namespace's
11
+ * ownership, `session-blob-namespace.ts`) checks it at the start of EVERY call, before any key — so `delete([])` is that precondition alone:
12
+ * it rejects exactly as a real delete would be refused, and removes nothing. An index owner whose own writes come before its byte deletes
13
+ * asks it that way first (`SqlBlobIndex.sweep`).
9
14
  */
10
15
  export interface BlobBackend {
11
16
  put(key: string, bytes: Uint8Array): Promise<void>;
@@ -19,20 +24,47 @@ export interface BlobBackend {
19
24
  * where both index owners judge it (the file-history blob index, the attachment store).
20
25
  */
21
26
  export declare function readAtAddress(port: Pick<BlobBackend, "get">, hash: string): Promise<Uint8Array | undefined>;
22
- export interface MinioBlobBackendConfig {
27
+ /** A name a content-addressed domain could have written: a hex sha256, one key segment. A listed name of any other shape (a nested prefix's object, a
28
+ * hand-placed file) is not the domain's — its sweep leaves it alone. */
29
+ export declare function isContentAddress(name: string): boolean;
30
+ /** The object-store action table rows one blob backend signs, by verb (`object-store-buckets.ts`). A verb with no row is a request this backend never
31
+ * makes: calling it throws before anything is signed (the retired epoch's index only deletes; the boot check only lists). */
32
+ export interface BlobBackendOps {
33
+ readonly put?: ObjectStoreOp;
34
+ readonly get?: ObjectStoreOp;
35
+ readonly head?: ObjectStoreOp;
36
+ readonly delete?: ObjectStoreOp;
37
+ readonly list?: ObjectStoreOp;
38
+ }
39
+ interface MinioBlobBackendBaseConfig {
23
40
  endpoint: string;
24
41
  bucket: string;
25
42
  accessKey: string;
26
43
  secretKey: string;
27
44
  region?: string;
28
- /** Key prefix for blob objects, e.g. "blobs/". Object key = keyPrefix + key. Default "blobs/". */
29
- keyPrefix?: string;
30
- /** Presigned-URL TTL (seconds). Default 3600 (1h) — must comfortably exceed a ~64 MiB single-PUT/GET on a slow link
31
- * (a SigV4 X-Amz-Expires bounds the WHOLE transfer from X-Amz-Date; a too-short TTL fails mid-stream). */
45
+ /** Key prefix for blob objects. Object key = keyPrefix + key. The production domains get theirs from {@link createSessionBlobBackend}. */
46
+ keyPrefix: string;
47
+ /** Presigned-URL TTL (seconds; `SESSION_SNAPSHOT_TTL_SEC`). Unset ⇒ the row's default in the object-store action table (3600 s — it must
48
+ * comfortably exceed a ~64 MiB single-PUT/GET on a slow link: a SigV4 X-Amz-Expires bounds the WHOLE transfer from X-Amz-Date; a too-short TTL
49
+ * fails mid-stream). A row whose TTL is fixed (the boot probe's) refuses a configured one. */
32
50
  presignTtlSec?: number;
33
51
  /** 测试注入口(listObjects 分页钉用);生产缺省 global fetch。 */
34
52
  fetchImpl?: typeof fetch;
35
53
  }
54
+ /** A backend's rows and, for one that signs DELETE, the namespace's ownership every DELETE waits for — required by construction: every delete of a
55
+ * content-addressed domain is judged by one database's references, so a port that can delete is built from that database's proven namespace
56
+ * (`session-blob-namespace.ts`; `createSessionBlobBackend` passes it). A port with no DELETE row (the boot probe) has no owner. */
57
+ export type MinioBlobBackendConfig = MinioBlobBackendBaseConfig & ({
58
+ readonly ops: BlobBackendOps & {
59
+ readonly delete?: undefined;
60
+ };
61
+ readonly owner?: undefined;
62
+ } | {
63
+ readonly ops: BlobBackendOps & {
64
+ readonly delete: ObjectStoreOp;
65
+ };
66
+ readonly owner: Pick<SessionBlobNamespace, "assertOwned">;
67
+ });
36
68
  /** 鲁棒性批2 C2/C3/C6(2026-08-03):S3 兼容端点 IO 的统一 abort 上界(fleet-client C1 定常量形
37
69
  * 先例)。半开端点此前各挂 undici 默认 ~300s headersTimeout——blob GET 卡住 restore/session-import
38
70
  * 同步路径,SendUserFile 工具调用永不返回。120s 对慢链路 ~64MiB 单 PUT/GET 仍宽裕(presignTtlSec
@@ -56,11 +88,14 @@ export type BucketProbe = {
56
88
  export declare class MinioBlobBackend implements BlobBackend {
57
89
  private readonly cfg;
58
90
  private readonly keyPrefix;
91
+ /** The configured TTL, or nothing (the seat then takes the row's own). */
59
92
  private readonly ttl;
60
93
  /** 六个站点(put / get / delete / listObjects / headObject / probeBucket)的唯一出口:端点回重定向 ⇒ 拒,预签名 URL 与对象体不被带去 `Location`。 */
61
94
  private readonly egressFetch;
62
95
  constructor(cfg: MinioBlobBackendConfig);
63
96
  private objectKey;
97
+ /** The table row this backend signs `verb` under; none ⇒ throw (a request this backend's domain never makes). */
98
+ private opFor;
64
99
  private presign;
65
100
  /** PUT the bytes under the key. A non-2xx PUT throws (an upload failure must surface — a silent drop would later read_failed on
66
101
  * restore). NOTE no post-PUT read-back verify on the live path (perf): a corrupted PUT is caught at the next read's content-address
@@ -75,7 +110,8 @@ export declare class MinioBlobBackend implements BlobBackend {
75
110
  /** DELETE every key's object, at most {@link MINIO_OP_CONCURRENCY} in flight (no FD / throttle storm). Each key is independent: a
76
111
  * 2xx or a 404 (already gone) is a success; any other answer or a network failure is a failure. Every key is tried; then, if any
77
112
  * failed, the call REJECTS naming how many (🔴 复审 F4 的同一判据:对象存储完全不可写时绝不报「清理成功」—— 失败只在这里说出来,
78
- * 调用方据此记账,不吞)。 */
113
+ * 调用方据此记账,不吞)。The namespace's ownership is read first on every call, an empty `keys` included (that call is the precondition
114
+ * alone: the port contract, {@link BlobBackend}). */
79
115
  delete(keys: readonly string[]): Promise<void>;
80
116
  /** D-1 孤儿对象 GC(clay 拍 2026-07-28):列举本后端 keyPrefix 下的全部对象(ListObjectsV2 分页,
81
117
  * 零依赖 XML 取 <Key>/<LastModified>/<NextContinuationToken>)。**server 端 sweep 专用**——presign 的
@@ -95,4 +131,44 @@ export declare class MinioBlobBackend implements BlobBackend {
95
131
  * 都**证明不了**缺桶 ⇒ `unknown`,调用方不拒启、只报一次。总函数:不抛。`timeoutMs`:boot 期调用方给的单次上界(黑洞端点不许把起服拖到 120s)。 */
96
132
  probeBucket(timeoutMs?: number): Promise<BucketProbe>;
97
133
  }
134
+ /** The blob domains of the session snapshot bucket (closed set) → the table rows each signs. File history reads, writes and sweeps; attachments also list
135
+ * and HEAD (their orphan sweep); the retired snapshot epoch only deletes (its sweep). */
136
+ export declare const SESSION_BLOB_DOMAIN_OPS: {
137
+ readonly "file-history": {
138
+ readonly put: "file-history/blob:PUT";
139
+ readonly get: "file-history/blob:GET";
140
+ readonly delete: "file-history/blob:DELETE";
141
+ };
142
+ readonly attachments: {
143
+ readonly put: "attachments/blob:PUT";
144
+ readonly get: "attachments/blob:GET";
145
+ readonly head: "attachments/blob:HEAD";
146
+ readonly delete: "attachments/blob:DELETE";
147
+ readonly list: "attachments/prefix:LIST";
148
+ };
149
+ readonly "legacy-blobs": {
150
+ readonly delete: "legacy-blobs/blob:DELETE";
151
+ };
152
+ };
153
+ export type SessionBlobDomain = keyof typeof SESSION_BLOB_DOMAIN_OPS;
154
+ /** The session snapshot bucket's store config (`config.snapshotBlobStore`: `SESSION_SNAPSHOT_BUCKET`, `SESSION_SNAPSHOT_PREFIX`, `SESSION_SNAPSHOT_TTL_SEC`). */
155
+ export interface SessionBlobStoreConfig {
156
+ endpoint: string;
157
+ bucket: string;
158
+ accessKey: string;
159
+ secretKey: string;
160
+ region?: string;
161
+ keyPrefix?: string;
162
+ presignTtlSec?: number;
163
+ }
164
+ /** The key prefix of a session blob domain, or the key of the namespace's claim — the ONE place each composes `SESSION_SNAPSHOT_PREFIX` with its
165
+ * segment (the table's key forms `{sessionPrefix}file-history/…`, `{sessionPrefix}attachments/…`, `{legacyBlobRoot}…`, `{sessionPrefix}blob-namespace-claim`).
166
+ * An empty prefix reads as unset (the env loader's reading of the knob, kept for a hand-built config too): file history, attachments and the claim then
167
+ * sit at the bucket root, the retired epoch at its own root `blobs/` (where its objects were written). */
168
+ export declare function sessionBlobKeyPrefixOf(store: Pick<SessionBlobStoreConfig, "keyPrefix">, part: SessionBlobDomain | "claim"): string;
169
+ /** The byte port of one session blob domain over the session snapshot bucket: its key prefix ({@link sessionBlobKeyPrefixOf}), its table rows
170
+ * ({@link SESSION_BLOB_DOMAIN_OPS}) and the namespace's ownership its deletes wait for — the one construction every production domain uses, and it
171
+ * takes the namespace (one database's), not a bare bucket config. */
172
+ export declare function createSessionBlobBackend(namespace: SessionBlobNamespace, domain: SessionBlobDomain): MinioBlobBackend;
173
+ export {};
98
174
  //# sourceMappingURL=blob-backend.d.ts.map
@@ -2,12 +2,16 @@ import { createHash } from "node:crypto";
2
2
  import { presignS3Url, presignS3ListUrl } from "./s3-presign.js";
3
3
  import { isNoSuchBucketAnswer } from "./s3-answer.js";
4
4
  import { createEgressFetch } from "../egress-redirect.js";
5
+ import { ATTACHMENT_BLOB_SEGMENT, FILE_HISTORY_BLOB_SEGMENT, LEGACY_BLOB_ROOT_DEFAULT, SESSION_BLOB_CLAIM_KEY } from "../object-store-buckets.js";
5
6
  export async function readAtAddress(port, hash) {
6
7
  const bytes = await port.get(hash);
7
8
  if (bytes === undefined)
8
9
  return undefined;
9
10
  return createHash("sha256").update(bytes).digest("hex") === hash ? bytes : undefined;
10
11
  }
12
+ export function isContentAddress(name) {
13
+ return /^[0-9a-f]{64}$/.test(name);
14
+ }
11
15
  const MINIO_OP_CONCURRENCY = 16;
12
16
  async function mapBounded(items, limit, fn) {
13
17
  let i = 0;
@@ -27,23 +31,30 @@ export class MinioBlobBackend {
27
31
  egressFetch;
28
32
  constructor(cfg) {
29
33
  this.cfg = cfg;
30
- this.keyPrefix = cfg.keyPrefix ?? "blobs/";
31
- this.ttl = cfg.presignTtlSec ?? 3600;
34
+ this.keyPrefix = cfg.keyPrefix;
35
+ this.ttl = cfg.presignTtlSec !== undefined ? { expiresSec: cfg.presignTtlSec } : {};
32
36
  this.egressFetch = createEgressFetch("declare the final object-store address as MINIO_ENDPOINT / S3_ENDPOINT", cfg.fetchImpl);
33
37
  }
34
38
  objectKey(key) {
35
39
  return `${this.keyPrefix}${key}`;
36
40
  }
41
+ opFor(verb) {
42
+ const op = this.cfg.ops[verb];
43
+ if (op === undefined)
44
+ throw new Error(`MinioBlobBackend: this blob domain (prefix ${JSON.stringify(this.keyPrefix)}) signs no ${verb.toUpperCase()} — no object-store action row for it`);
45
+ return op;
46
+ }
37
47
  presign(key, method) {
38
48
  return presignS3Url({
49
+ op: this.opFor(method === "GET" ? "get" : method === "PUT" ? "put" : method === "HEAD" ? "head" : "delete"),
39
50
  endpoint: this.cfg.endpoint,
40
51
  bucket: this.cfg.bucket,
41
52
  key: this.objectKey(key),
42
- method: method,
53
+ method,
43
54
  accessKey: this.cfg.accessKey,
44
55
  secretKey: this.cfg.secretKey,
45
56
  ...(this.cfg.region ? { region: this.cfg.region } : {}),
46
- expiresSec: this.ttl,
57
+ ...this.ttl,
47
58
  });
48
59
  }
49
60
  async put(key, bytes) {
@@ -72,7 +83,13 @@ export class MinioBlobBackend {
72
83
  return new Uint8Array(await res.arrayBuffer());
73
84
  }
74
85
  async delete(keys) {
86
+ const owner = this.cfg.owner;
87
+ if (owner === undefined)
88
+ throw new Error(`MinioBlobBackend: this blob domain (prefix ${JSON.stringify(this.keyPrefix)}) has no namespace ownership to delete under — a port that signs DELETE is built from a proven namespace`);
89
+ await owner.assertOwned();
75
90
  const distinct = [...new Set(keys)];
91
+ if (distinct.length === 0)
92
+ return;
76
93
  let failed = 0;
77
94
  let firstFailure;
78
95
  await mapBounded(distinct, MINIO_OP_CONCURRENCY, async (key) => {
@@ -100,6 +117,7 @@ export class MinioBlobBackend {
100
117
  if (++pages > MAX_PAGES)
101
118
  throw new Error(`listObjects: exceeded ${MAX_PAGES} pages (max-keys 1000/page) — the backend is looping its continuation-token or the prefix is unexpectedly large; refusing to report a partial orphan set`);
102
119
  const url = presignS3ListUrl({
120
+ op: this.opFor("list"),
103
121
  endpoint: this.cfg.endpoint,
104
122
  bucket: this.cfg.bucket,
105
123
  prefix: this.keyPrefix,
@@ -108,7 +126,7 @@ export class MinioBlobBackend {
108
126
  accessKey: this.cfg.accessKey,
109
127
  secretKey: this.cfg.secretKey,
110
128
  ...(this.cfg.region ? { region: this.cfg.region } : {}),
111
- expiresSec: this.ttl,
129
+ ...this.ttl,
112
130
  });
113
131
  const res = await f(url, { method: "GET", signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
114
132
  if (!res.ok)
@@ -141,6 +159,7 @@ export class MinioBlobBackend {
141
159
  async probeBucket(timeoutMs = OBJECT_STORE_IO_TIMEOUT_MS) {
142
160
  const f = this.egressFetch;
143
161
  const url = presignS3ListUrl({
162
+ op: this.opFor("list"),
144
163
  endpoint: this.cfg.endpoint,
145
164
  bucket: this.cfg.bucket,
146
165
  prefix: this.keyPrefix,
@@ -148,7 +167,7 @@ export class MinioBlobBackend {
148
167
  accessKey: this.cfg.accessKey,
149
168
  secretKey: this.cfg.secretKey,
150
169
  ...(this.cfg.region ? { region: this.cfg.region } : {}),
151
- expiresSec: this.ttl,
170
+ ...this.ttl,
152
171
  });
153
172
  let res;
154
173
  try {
@@ -165,4 +184,36 @@ export class MinioBlobBackend {
165
184
  return { state: "unknown", detail: `HTTP ${res.status}` };
166
185
  }
167
186
  }
187
+ export const SESSION_BLOB_DOMAIN_OPS = {
188
+ "file-history": { put: "file-history/blob:PUT", get: "file-history/blob:GET", delete: "file-history/blob:DELETE" },
189
+ attachments: { put: "attachments/blob:PUT", get: "attachments/blob:GET", head: "attachments/blob:HEAD", delete: "attachments/blob:DELETE", list: "attachments/prefix:LIST" },
190
+ "legacy-blobs": { delete: "legacy-blobs/blob:DELETE" },
191
+ };
192
+ export function sessionBlobKeyPrefixOf(store, part) {
193
+ const prefix = store.keyPrefix === "" ? undefined : store.keyPrefix;
194
+ switch (part) {
195
+ case "file-history":
196
+ return `${prefix ?? ""}${FILE_HISTORY_BLOB_SEGMENT}`;
197
+ case "attachments":
198
+ return `${prefix ?? ""}${ATTACHMENT_BLOB_SEGMENT}`;
199
+ case "claim":
200
+ return `${prefix ?? ""}${SESSION_BLOB_CLAIM_KEY}`;
201
+ case "legacy-blobs":
202
+ return prefix ?? LEGACY_BLOB_ROOT_DEFAULT;
203
+ }
204
+ }
205
+ export function createSessionBlobBackend(namespace, domain) {
206
+ const store = namespace.store;
207
+ return new MinioBlobBackend({
208
+ endpoint: store.endpoint,
209
+ bucket: store.bucket,
210
+ accessKey: store.accessKey,
211
+ secretKey: store.secretKey,
212
+ ...(store.region ? { region: store.region } : {}),
213
+ keyPrefix: sessionBlobKeyPrefixOf(store, domain),
214
+ ops: SESSION_BLOB_DOMAIN_OPS[domain],
215
+ owner: namespace,
216
+ ...(store.presignTtlSec ? { presignTtlSec: store.presignTtlSec } : {}),
217
+ });
218
+ }
168
219
  //# sourceMappingURL=blob-backend.js.map
@@ -1,4 +1,5 @@
1
1
  import { mysqlDriver, pgDriver } from "./sql-driver.js";
2
+ import { sealStoreClass } from "./store-boundary.js";
2
3
  export const PG_BREAKER_STATE_SCHEMA = [
3
4
  `CREATE TABLE IF NOT EXISTS breaker_state (
4
5
  breaker_key VARCHAR(190) COLLATE "C" NOT NULL,
@@ -91,6 +92,7 @@ export class SqlBreakerState {
91
92
  this.timer = undefined;
92
93
  }
93
94
  }
95
+ sealStoreClass(SqlBreakerState, "sql-breaker-state", { get: "exit", set: "exit", refresh: "exit", startRefresh: "exit", stop: "exit" });
94
96
  export class TiDBBreakerState extends SqlBreakerState {
95
97
  constructor(pool, onWriteFail) {
96
98
  super(mysqlDriver(pool), onWriteFail);
@@ -1,4 +1,5 @@
1
1
  import { type AcquiredSession, type PlacedSessionRow, type RetentionDeclaration, type SessionPlacementRecord, type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
2
+ import type { EntriesStreamOptions } from "../session-sync-kernel.js";
2
3
  import type { LocalSessionDeletionSection } from "../session-erase.js";
3
4
  import type { OwnerAwareSessionStore, SessionListItem } from "../security.js";
4
5
  import type { StagingHandle } from "../session-sync-kernel.js";
@@ -7,6 +8,7 @@ import { type PlacementAcquireOpts } from "./session-placement.js";
7
8
  import type { InstructionSourceStore } from "../instruction-source-notice.js";
8
9
  import type { SessionWorkspaceStore } from "../session-workspace.js";
9
10
  import { type SessionBirthFace, type SessionWithdrawFace } from "./session-birth.js";
11
+ import type { SessionFace } from "../session-incarnation.js";
10
12
  export interface CachingOptions {
11
13
  /** Idle seconds a woken session is kept warm. 0 disables caching (pure passthrough). */
12
14
  ttlSec: number;
@@ -72,18 +74,13 @@ export declare class CachingSessionStore implements SessionStore {
72
74
  readonly withdrawBirth?: SessionWithdrawFace["withdrawBirth"];
73
75
  /** Delegated SessionRepo seam (§0.5) — list/fork/delete operate on the DURABLE tables directly (they bypass the
74
76
  * warm cache by design; a fork/delete must read/write durable state, not a possibly-stale cached view). */
75
- readonly listSessions?: (opts: {
76
- owner?: string;
77
- includeUnowned?: boolean;
78
- cursor?: {
79
- lastActivityAt: string;
80
- sessionId: string;
81
- };
82
- limit: number;
83
- q?: string;
84
- }) => Promise<SessionListItem[]>;
77
+ readonly listSessions?: OwnerAwareSessionStore["listSessions"];
85
78
  /** 带住客的同一只列表面(原样转发;理由同 listSessions)。 */
86
79
  readonly listSessionRows?: OwnerAwareSessionStore["listSessionRows"];
80
+ /** 按 id 的种类读(`session-kind.ts`;纯转发、不经暖缓存 —— 答的是行)。🔴 必须转发:授权口的种类判与能力位读的是本类。 */
81
+ readonly sessionKindOf?: OwnerAwareSessionStore["sessionKindOf"];
82
+ /** 老化候选面(纯转发;读的是持久行)。🔴 必须转发:能力位 `sessionKinds` 与老化腿读的是本类。 */
83
+ readonly listIdleOfKind?: OwnerAwareSessionStore["listIdleOfKind"];
87
84
  readonly fork?: OwnerAwareSessionStore["fork"];
88
85
  /** fork 续写的店契约(原样转发;与 fork 同理绕过暖缓存 —— 读写的是持久行,新 id 本来就不在缓存里)。 */
89
86
  readonly forkTo?: OwnerAwareSessionStore["forkTo"];
@@ -99,7 +96,7 @@ export declare class CachingSessionStore implements SessionStore {
99
96
  readonly sessionSummaryOf?: (sessionId: string) => Promise<SessionListItem | undefined>;
100
97
  readonly writeSessionRowCells?: OwnerAwareSessionStore["writeSessionRowCells"];
101
98
  /** The auto-titler's NULL-only title write (SQL twins + local sidecar carry it; pure pass-through). */
102
- readonly setTitleIfNull?: (sessionId: string, title: string) => Promise<boolean>;
99
+ readonly setTitleIfNull?: (sessionId: string, title: string, landed: SessionFace) => Promise<boolean>;
103
100
  readonly probeTitle?: (sessionId: string) => Promise<"none" | "untitled" | "titled">;
104
101
  /** [ref] —— 换源通告的基线面(`session_ext.instruction_source` / local sidecar),纯转发、不经暖缓存。
105
102
  * 🔴 必须转发(与 retention / placements 同一条教训):默认 `SESSION_CACHE_TTL_SEC=300` 把真店包进本类,
@@ -117,10 +114,7 @@ export declare class CachingSessionStore implements SessionStore {
117
114
  * (read straight from the durable log, bypassing the warm cache, like exportEntries). The stream's per-batch query
118
115
  * discipline (one pooled query per page) lives in the inner store; this wrapper just forwards. */
119
116
  readonly listEntryIds?: (sessionId: string) => Promise<string[] | null>;
120
- readonly exportEntriesStream?: (sessionId: string, opts?: {
121
- afterSeq?: number;
122
- batchSize?: number;
123
- }) => Promise<AsyncIterable<SessionTreeEntry> | null>;
117
+ readonly exportEntriesStream?: (sessionId: string, opts: EntriesStreamOptions) => Promise<AsyncIterable<SessionTreeEntry> | null>;
124
118
  /** 轴A #1(1.254):core B-17 forget 面(evict 本地 + 转发 inner 可选面)。 */
125
119
  forget?: (sessionId: string) => void | Promise<void>;
126
120
  readonly importEntries?: (sessionId: string, owner: string | null, entries: SessionTreeEntry[]) => Promise<void>;
@@ -15,6 +15,8 @@ export class CachingSessionStore {
15
15
  withdrawBirth;
16
16
  listSessions;
17
17
  listSessionRows;
18
+ sessionKindOf;
19
+ listIdleOfKind;
18
20
  fork;
19
21
  forkTo;
20
22
  executionPlacement;
@@ -82,6 +84,10 @@ export class CachingSessionStore {
82
84
  this.listSessions = ownerAware.listSessions.bind(inner);
83
85
  if (ownerAware.listSessionRows)
84
86
  this.listSessionRows = ownerAware.listSessionRows.bind(inner);
87
+ if (ownerAware.sessionKindOf)
88
+ this.sessionKindOf = ownerAware.sessionKindOf.bind(inner);
89
+ if (ownerAware.listIdleOfKind)
90
+ this.listIdleOfKind = ownerAware.listIdleOfKind.bind(inner);
85
91
  if (ownerAware.sessionSummaryOf)
86
92
  this.sessionSummaryOf = ownerAware.sessionSummaryOf.bind(inner);
87
93
  if (ownerAware.writeSessionRowCells)
@@ -4,11 +4,11 @@
4
4
  *
5
5
  * ## 写:一只派生 = core `checkpointIndexFacts(cp)`(core 7.55.0 [ref] P1 阶段二)
6
6
  * 行上「core 铸下、此后不动」的十三个事实(令牌、scope、会话、格式版本、门型、卡、待决工具的名 / 调用 id / 入参摘要、deadline、铸行时刻、风险描述符、
7
- * 双向控制字符在场位),每一个都由 core 那一只函数答;本模块只把它们落到列名下({@link buildCheckpointIndexCells})。修前写口自己从寄存行 / 门上逐格读,
8
- * 对任何寄存臂、任何门都不分臂 —— 与 core 读法在契约外的行上答两样(计划门上的卡、审阅寄存行上的工具位)。键表对 core 的事实键闭合
9
- * ({@link CHECKPOINT_INDEX_COLUMNS} `satisfies Record<keyof CheckpointIndexFacts, …>`):core 加 / 删一个事实 ⇒ 编译红,由人决定它落不落列。
10
- * 不在这里的:CAS 面推动的状态(`status` / `rev` / `reopen_reason` / 执行记录)、部署铸的值(`terminal_at_ms` 兜底)、部署截长脱敏的展示投影(`tool_input` /
11
- * `rule_suggestions`)—— 它们不是行的不变事实,core 也不答。
7
+ * 双向控制字符在场位),每一个都由 core 那一只函数答;本模块只把**有读者找行 / 判到期**的那几个落到列名下({@link buildCheckpointIndexCells})。
8
+ * 键表对 core 的事实键闭合({@link CHECKPOINT_INDEX_COLUMNS} `satisfies Record<keyof CheckpointIndexFacts, string | null>`):core 加 / 删一个事实 ⇒ 编译红,
9
+ * 由人决定它落不落列。**不落列**(`null`)的三个 —— 工具名、风险描述符、bidi 位 —— 只是运维队列的展示材料:队列行在读时从续跑执行的同一份字节、同一次整行解码投影
10
+ * (`checkpoint-store-face.ts` 的 `buildQueueActionFacts`,同调这同一只 core 派生),落一份列就是同一事实的第二份存储(7.151.x 及以前落过,一次性迁移 M54 删)。
11
+ * 不在这里的:CAS 面推动的状态(`status` / `rev` / `reopen_reason` / 执行记录)、部署铸的值(`terminal_at_ms` 兜底)—— 它们不是行的不变事实,core 也不答。
12
12
  *
13
13
  * ## 写之前:一只判官 = {@link judgeCheckpointIndexCells}
14
14
  * 一份文档能不能落进这些列,在写之前由**同一只**判官答 —— 写口 `put` 与 M29 的存量回填都问它,界不抄第二份。三个答案:`cells`(放得下,列格在手);`unreadable`(门或待决动作
@@ -29,9 +29,13 @@
29
29
  * (`boot/stores.ts`,先于任何路由与收割器装配),跑不完就拒启 —— 所以每只副本的收割器只在本次起服的 M29 完成之后才运行。混跑期间旧副本新写的行
30
30
  * 不带卡列(它们不认这一列),由下一次起服的 M29 补上;升级序见 MIGRATION 7.135.0 节(同一只库不混跑两版)。
31
31
  */
32
- import { PAUSE_REGISTRY, type Checkpoint, type CheckpointIndexFacts, type GateKind, type RiskDescriptor } from "@sema-agent/core";
32
+ import { PAUSE_REGISTRY, type Checkpoint, type CheckpointIndexFacts, type GateKind } from "@sema-agent/core";
33
33
  import type { SqlDialect } from "./sql-driver.js";
34
- /** 每个索引事实落在哪一列(键表对 core 的事实键闭合:core 加 / 删一个事实 ⇒ 编译红)。 */
34
+ /**
35
+ * 每个索引事实落在哪一列;`null` = 不落列(键表对 core 的事实键闭合:core 加 / 删一个事实 ⇒ 编译红,由人定落不落)。
36
+ * 落列的判据只有一条:**有读者按它找行或判到期**(决断口的门型绑定、对账与决断回放的调用 id / 绑定摘要、到期 facet 的卡与门型、会话 / scope / 时刻 / 截止)。
37
+ * 只给人看的事实不落列 —— 队列在读时从同一次整行解码投影,一个事实一份存储。
38
+ */
35
39
  export declare const CHECKPOINT_INDEX_COLUMNS: {
36
40
  readonly token: "token";
37
41
  readonly scope: "scope";
@@ -39,21 +43,21 @@ export declare const CHECKPOINT_INDEX_COLUMNS: {
39
43
  readonly version: "version";
40
44
  readonly gateKind: "gate_kind";
41
45
  readonly approvalCard: "approval_card";
42
- readonly toolName: "tool_name";
46
+ readonly toolName: null;
43
47
  readonly toolCallId: "tool_call_id";
44
48
  readonly boundInputHash: "bound_input_hash";
45
49
  readonly deadline: "deadline";
46
50
  readonly createdAt: "created_at_ms";
47
- readonly riskDescriptor: "risk_descriptor";
48
- readonly hasBidiControls: "has_bidi_controls";
51
+ readonly riskDescriptor: null;
52
+ readonly hasBidiControls: null;
49
53
  };
50
- type IndexColumnOf<K extends keyof CheckpointIndexFacts> = (typeof CHECKPOINT_INDEX_COLUMNS)[K];
51
- /**
52
- * 一行的索引列格:core 的事实落在列名下。值逐字是事实本身,只有一处换形:双向控制字符在场位落 `1` 或 NULL(列是 TINYINT / SMALLINT,恒不写 0 —— core 的契约
53
- * 是「`true` 或缺席」,0 会把「没检出」谎成「已确认干净」)。描述符是行自己的对象,写口负责编码(两方言的 JSON 编码器不同)。
54
- */
54
+ /** 落列的那几个事实(键表上列名不是 `null` 的)。 */
55
+ type StoredIndexFact = {
56
+ [K in keyof CheckpointIndexFacts]: (typeof CHECKPOINT_INDEX_COLUMNS)[K] extends string ? K : never;
57
+ }[keyof CheckpointIndexFacts];
58
+ /** 一行的索引列格:落列的 core 事实落在列名下,值逐字是事实本身。 */
55
59
  export type CheckpointIndexCells = {
56
- readonly [K in keyof CheckpointIndexFacts as IndexColumnOf<K>]: K extends "hasBidiControls" ? 1 | null : K extends "riskDescriptor" ? RiskDescriptor | null : CheckpointIndexFacts[K];
60
+ readonly [K in StoredIndexFact as (typeof CHECKPOINT_INDEX_COLUMNS)[K] & string]: CheckpointIndexFacts[K];
57
61
  };
58
62
  /** 一行的索引列格(纯数据;写口与 M29 回填同调这一只 —— 回填不另读门子树自算)。 */
59
63
  export declare function buildCheckpointIndexCells(cp: Checkpoint): CheckpointIndexCells;
@@ -7,13 +7,13 @@ export const CHECKPOINT_INDEX_COLUMNS = {
7
7
  version: "version",
8
8
  gateKind: "gate_kind",
9
9
  approvalCard: "approval_card",
10
- toolName: "tool_name",
10
+ toolName: null,
11
11
  toolCallId: "tool_call_id",
12
12
  boundInputHash: "bound_input_hash",
13
13
  deadline: "deadline",
14
14
  createdAt: "created_at_ms",
15
- riskDescriptor: "risk_descriptor",
16
- hasBidiControls: "has_bidi_controls",
15
+ riskDescriptor: null,
16
+ hasBidiControls: null,
17
17
  };
18
18
  export function buildCheckpointIndexCells(cp) {
19
19
  const f = checkpointIndexFacts(cp);
@@ -24,13 +24,10 @@ export function buildCheckpointIndexCells(cp) {
24
24
  version: f.version,
25
25
  gate_kind: f.gateKind,
26
26
  approval_card: f.approvalCard,
27
- tool_name: f.toolName,
28
27
  tool_call_id: f.toolCallId,
29
28
  bound_input_hash: f.boundInputHash,
30
29
  deadline: f.deadline,
31
30
  created_at_ms: f.createdAt,
32
- risk_descriptor: f.riskDescriptor,
33
- has_bidi_controls: f.hasBidiControls === true ? 1 : null,
34
31
  };
35
32
  }
36
33
  export const APPROVAL_CARD_COLUMN_MAX_BYTES = {