@sema-agent/server 7.146.0 → 7.147.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 (398) hide show
  1. package/MIGRATION.md +384 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +170 -66
  5. package/deploy/facts/lanes.json +7 -0
  6. package/deploy/sema-up/README.md +2 -2
  7. package/deploy/sema-up/chart/templates/_helpers.tpl +22 -0
  8. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -4
  9. package/deploy/sema-up/chart/templates/server.yaml +5 -4
  10. package/deploy/sema-up/chart/values.yaml +1 -1
  11. package/deploy/sema-up/cluster-up.sh +2 -1
  12. package/deploy/sema-up/lib/flagshape.sh +4 -0
  13. package/deploy/sema-up/lib/lanes.json +2 -5
  14. package/deploy/sema-up/sema-up.sh +12 -9
  15. package/deploy/sema-up/stack/compose.yaml +5 -4
  16. package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -3
  17. package/dist/approval-card.d.ts +4 -4
  18. package/dist/approval.d.ts +3 -3
  19. package/dist/audit.js +2 -2
  20. package/dist/bench/s1/live-deps.js +3 -1
  21. package/dist/boot/crash-last.js +2 -1
  22. package/dist/boot/device-lane.js +5 -5
  23. package/dist/boot/engine-lease.d.ts +12 -11
  24. package/dist/boot/execution-env.d.ts +2 -1
  25. package/dist/boot/execution-env.js +45 -33
  26. package/dist/boot/execution-lane.d.ts +37 -9
  27. package/dist/boot/execution-lane.js +74 -20
  28. package/dist/boot/exit-boundary.d.ts +1 -1
  29. package/dist/boot/exit-last.js +2 -1
  30. package/dist/boot/governance-seams.d.ts +2 -2
  31. package/dist/boot/leader.js +1 -1
  32. package/dist/boot/memory-boundary.d.ts +11 -11
  33. package/dist/boot/memory-boundary.js +3 -3
  34. package/dist/boot/memory-consolidation.d.ts +13 -24
  35. package/dist/boot/memory-consolidation.js +0 -13
  36. package/dist/boot/org-memory.js +3 -2
  37. package/dist/boot/parked-revive-gate.d.ts +1 -1
  38. package/dist/boot/parked-revive-gate.js +1 -1
  39. package/dist/boot/reapers.js +1 -1
  40. package/dist/boot/resolve-spec.js +91 -111
  41. package/dist/boot/retention-lane.d.ts +4 -42
  42. package/dist/boot/session-faces.d.ts +1 -0
  43. package/dist/boot/session-faces.js +8 -2
  44. package/dist/boot/stage-01-config.d.ts +1 -1
  45. package/dist/boot/stage-01-config.js +6 -2
  46. package/dist/boot/stage-02-web-admin-pull.d.ts +1 -1
  47. package/dist/boot/stage-02-web-admin-pull.js +10 -8
  48. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  49. package/dist/boot/stage-04-stores.d.ts +1 -1
  50. package/dist/boot/stage-05-execution-env.d.ts +2 -2
  51. package/dist/boot/stage-05-execution-env.js +3 -3
  52. package/dist/boot/stage-06-runners.d.ts +3 -3
  53. package/dist/boot/stage-06-runners.js +1 -3
  54. package/dist/boot/stage-07-capability-layer.d.ts +3 -3
  55. package/dist/boot/stage-07-capability-layer.js +4 -9
  56. package/dist/boot/stage-08-reapers.d.ts +3 -3
  57. package/dist/boot/stage-09-leader.d.ts +4 -3
  58. package/dist/boot/stage-10-http-server.d.ts +4 -3
  59. package/dist/boot/stage-10-http-server.js +2 -1
  60. package/dist/boot/stores.d.ts +9 -0
  61. package/dist/boot/stores.js +18 -7
  62. package/dist/boot/web-admin.js +3 -3
  63. package/dist/capabilities/center-plugins.d.ts +2 -0
  64. package/dist/capabilities/center-plugins.js +6 -2
  65. package/dist/capabilities/composite-members.d.ts +1 -0
  66. package/dist/capabilities/composite-members.js +1 -0
  67. package/dist/capabilities/execution-lane.d.ts +7 -7
  68. package/dist/capabilities/execution-lane.js +2 -2
  69. package/dist/capabilities/hands-lane.d.ts +1 -1
  70. package/dist/capabilities/scenarios.d.ts +32 -18
  71. package/dist/capabilities/scenarios.js +13 -9
  72. package/dist/capabilities/settings-contract.d.ts +29 -0
  73. package/dist/capabilities/settings-contract.js +14 -0
  74. package/dist/capabilities/skills.d.ts +5 -5
  75. package/dist/capability-facts.d.ts +38 -0
  76. package/dist/capability-facts.js +34 -1
  77. package/dist/center-credential-renewer.js +3 -2
  78. package/dist/config-catalog.js +6 -5
  79. package/dist/config-invariants.d.ts +18 -3
  80. package/dist/config-invariants.js +36 -19
  81. package/dist/config-lkg.d.ts +1 -1
  82. package/dist/config-lkg.js +5 -6
  83. package/dist/config-provider.js +2 -0
  84. package/dist/config-types.d.ts +190 -186
  85. package/dist/config.d.ts +68 -5
  86. package/dist/config.js +80 -54
  87. package/dist/degenerate-instrument.js +1 -1
  88. package/dist/deploy-facts.js +3 -2
  89. package/dist/deployment-shape.d.ts +21 -12
  90. package/dist/deployment-shape.js +24 -6
  91. package/dist/env-facts.d.ts +7 -5
  92. package/dist/env-facts.js +10 -6
  93. package/dist/execution-config-root.d.ts +5 -5
  94. package/dist/execution-config-root.js +5 -5
  95. package/dist/execution-env-purpose.d.ts +14 -0
  96. package/dist/execution-env-purpose.js +29 -0
  97. package/dist/execution-lane-caps.d.ts +49 -86
  98. package/dist/execution-lane-caps.js +52 -62
  99. package/dist/execution-placement.d.ts +18 -2
  100. package/dist/execution-placement.js +19 -0
  101. package/dist/file-history-disclosure.d.ts +2 -2
  102. package/dist/fleet/drain-entry.d.ts +17 -10
  103. package/dist/fleet/drain-entry.js +1 -1
  104. package/dist/fleet/serving-lease.js +3 -4
  105. package/dist/history-anchor.d.ts +22 -0
  106. package/dist/history-anchor.js +14 -0
  107. package/dist/hooks/command-spawn.d.ts +1 -4
  108. package/dist/hooks/command-spawn.js +0 -11
  109. package/dist/hooks/hook-runner.d.ts +52 -8
  110. package/dist/hooks/hook-runner.js +160 -36
  111. package/dist/http/approval-sweeps.d.ts +2 -5
  112. package/dist/http/approval-sweeps.js +3 -2
  113. package/dist/http/checkpoint-ctx.d.ts +17 -0
  114. package/dist/http/checkpoint-ctx.js +6 -0
  115. package/dist/http/claim-latency.d.ts +10 -0
  116. package/dist/http/claim-latency.js +12 -0
  117. package/dist/http/dispatch.js +1 -1
  118. package/dist/http/durable-run-leg.js +2 -1
  119. package/dist/http/execution-context.d.ts +3 -1
  120. package/dist/http/execution-context.js +4 -0
  121. package/dist/http/memory-compliance-failure-reply.d.ts +1 -1
  122. package/dist/http/memory-compliance-failure-reply.js +3 -0
  123. package/dist/http/memory-store-refusal-reply.d.ts +3 -3
  124. package/dist/http/memory-store-refusal-reply.js +3 -0
  125. package/dist/http/owner-access.d.ts +11 -0
  126. package/dist/http/owner-access.js +7 -4
  127. package/dist/http/principal-gate.d.ts +3 -14
  128. package/dist/http/principal-gate.js +0 -13
  129. package/dist/http/request-guards.d.ts +1 -1
  130. package/dist/http/resume-legs.d.ts +7 -10
  131. package/dist/http/resume-legs.js +79 -50
  132. package/dist/http/rewind-files-reply.d.ts +34 -0
  133. package/dist/http/rewind-files-reply.js +36 -0
  134. package/dist/http/route-ctx.d.ts +32 -16
  135. package/dist/http/route-table.js +2 -0
  136. package/dist/http/routes/approvals-assistant.js +5 -25
  137. package/dist/http/routes/capabilities.js +8 -2
  138. package/dist/http/routes/devices.js +1 -1
  139. package/dist/http/routes/memory-origin.d.ts +1 -1
  140. package/dist/http/routes/notify-wake.js +2 -1
  141. package/dist/http/routes/projects.d.ts +70 -0
  142. package/dist/http/routes/projects.js +86 -0
  143. package/dist/http/routes/rules.js +30 -2
  144. package/dist/http/routes/runs.js +8 -8
  145. package/dist/http/routes/session-sync.js +27 -10
  146. package/dist/http/routes/sessions.d.ts +7 -1
  147. package/dist/http/routes/sessions.js +104 -2
  148. package/dist/http/routes/tasks.js +9 -3
  149. package/dist/http/server.d.ts +24 -10
  150. package/dist/http/server.js +17 -6
  151. package/dist/http/stored-body-replay.d.ts +5 -3
  152. package/dist/http/stored-body-replay.js +10 -1
  153. package/dist/http/wire-types.d.ts +19 -10
  154. package/dist/index.d.ts +2 -2
  155. package/dist/index.js +1 -1
  156. package/dist/instruction-source-notice.d.ts +1 -1
  157. package/dist/memory-embedder-reembed.d.ts +38 -0
  158. package/dist/memory-embedder-reembed.js +20 -0
  159. package/dist/memory-incident-sink.d.ts +0 -28
  160. package/dist/memory-incident-sink.js +5 -0
  161. package/dist/memory-scope.d.ts +2 -2
  162. package/dist/memory-scope.js +1 -1
  163. package/dist/memory-store-refusal.d.ts +17 -4
  164. package/dist/memory-store-refusal.js +1 -1
  165. package/dist/memory-sync-client.d.ts +2 -0
  166. package/dist/memory-sync-client.js +13 -11
  167. package/dist/memory-sync.js +1 -1
  168. package/dist/model-compat.d.ts +35 -21
  169. package/dist/model-compat.js +49 -21
  170. package/dist/model-entry-refusal.d.ts +11 -1
  171. package/dist/model-entry-refusal.js +7 -0
  172. package/dist/namespaced-rule-name.d.ts +18 -1
  173. package/dist/namespaced-rule-name.js +12 -0
  174. package/dist/observability/fail-open.d.ts +17 -9
  175. package/dist/observability/fail-open.js +17 -9
  176. package/dist/observability/metrics.d.ts +2 -0
  177. package/dist/observability/metrics.js +2 -0
  178. package/dist/observability/secret-env-scrub.d.ts +30 -4
  179. package/dist/observability/secret-env-scrub.js +15 -3
  180. package/dist/orchestration/workflow-agent-session-index.d.ts +7 -12
  181. package/dist/orchestration/workflow-agent-session-index.js +1 -6
  182. package/dist/orchestration/workflow-completion-inbox.d.ts +26 -6
  183. package/dist/orchestration/workflow-completion-inbox.js +63 -45
  184. package/dist/org-memory-admission.d.ts +5 -2
  185. package/dist/org-memory-admission.js +25 -10
  186. package/dist/parked-decide.d.ts +33 -26
  187. package/dist/parked-decide.js +36 -44
  188. package/dist/plugins/approval-ask-store-file.d.ts +10 -2
  189. package/dist/plugins/approval-ask-store-file.js +37 -4
  190. package/dist/plugins/approval-ask-store-memory.d.ts +5 -3
  191. package/dist/plugins/approval-ask-store-memory.js +11 -2
  192. package/dist/plugins/approval-ask-store-sql.d.ts +3 -0
  193. package/dist/plugins/approval-ask-store-sql.js +3 -1
  194. package/dist/plugins/blob-backend.d.ts +38 -195
  195. package/dist/plugins/blob-backend.js +33 -229
  196. package/dist/plugins/caching-session-store.d.ts +9 -4
  197. package/dist/plugins/checkpoint-index-columns.d.ts +1 -1
  198. package/dist/plugins/checkpoint-index-columns.js +3 -2
  199. package/dist/plugins/checkpoint-store-face.d.ts +1 -1
  200. package/dist/plugins/device-store-sql.d.ts +2 -2
  201. package/dist/plugins/device-store-sql.js +5 -10
  202. package/dist/plugins/execution-lane-rename-m40.d.ts +20 -0
  203. package/dist/plugins/execution-lane-rename-m40.js +10 -0
  204. package/dist/plugins/execution-placement-sql.d.ts +63 -88
  205. package/dist/plugins/execution-placement-sql.js +94 -54
  206. package/dist/plugins/file-run-store.d.ts +26 -12
  207. package/dist/plugins/file-run-store.js +63 -63
  208. package/dist/plugins/imported-layer-root-retirement.d.ts +17 -8
  209. package/dist/plugins/imported-layer-root-retirement.js +4 -8
  210. package/dist/plugins/inbox-payload-column.d.ts +14 -0
  211. package/dist/plugins/inbox-payload-column.js +13 -0
  212. package/dist/plugins/local-checkpoint-store.d.ts +5 -0
  213. package/dist/plugins/local-checkpoint-store.js +11 -7
  214. package/dist/plugins/local-data-dir-modes-m39.d.ts +48 -0
  215. package/dist/plugins/local-data-dir-modes-m39.js +182 -0
  216. package/dist/plugins/local-engine-high-water.d.ts +11 -0
  217. package/dist/plugins/local-engine-high-water.js +59 -0
  218. package/dist/plugins/local-session-store.d.ts +91 -25
  219. package/dist/plugins/local-session-store.js +124 -45
  220. package/dist/plugins/local-task-attachment-store.d.ts +2 -0
  221. package/dist/plugins/local-task-attachment-store.js +10 -11
  222. package/dist/plugins/memory-embedder-fingerprint.d.ts +33 -10
  223. package/dist/plugins/memory-embedder-fingerprint.js +52 -12
  224. package/dist/plugins/memory-embedder.d.ts +1 -1
  225. package/dist/plugins/memory-embedder.js +2 -2
  226. package/dist/plugins/memory-engine-pg.d.ts +4 -3
  227. package/dist/plugins/memory-engine-pg.js +4 -4
  228. package/dist/plugins/memory-engine-sql-apply.d.ts +13 -4
  229. package/dist/plugins/memory-engine-sql-apply.js +1 -1
  230. package/dist/plugins/memory-engine-tidb.d.ts +8 -5
  231. package/dist/plugins/memory-engine-tidb.js +7 -8
  232. package/dist/plugins/one-time-migrations.d.ts +145 -35
  233. package/dist/plugins/one-time-migrations.js +272 -120
  234. package/dist/plugins/owner-only-file-mode.d.ts +29 -0
  235. package/dist/plugins/owner-only-file-mode.js +141 -0
  236. package/dist/plugins/permission-rule-store-file.d.ts +8 -8
  237. package/dist/plugins/permission-rule-store-file.js +14 -2
  238. package/dist/plugins/pg-pool.d.ts +2 -1
  239. package/dist/plugins/pg-pool.js +11 -4
  240. package/dist/plugins/release-version.d.ts +20 -0
  241. package/dist/plugins/release-version.js +28 -0
  242. package/dist/plugins/remote-env-adb.d.ts +20 -4
  243. package/dist/plugins/remote-env-adb.js +39 -11
  244. package/dist/plugins/remote-env-e2b.d.ts +12 -3
  245. package/dist/plugins/remote-env-e2b.js +6 -4
  246. package/dist/plugins/remote-env-host.d.ts +9 -1
  247. package/dist/plugins/remote-env-host.js +6 -5
  248. package/dist/plugins/remote-env-k8s.d.ts +5 -2
  249. package/dist/plugins/remote-env-k8s.js +15 -4
  250. package/dist/plugins/remote-env-local-docker.d.ts +4 -1
  251. package/dist/plugins/remote-env-local-docker.js +3 -3
  252. package/dist/plugins/remote-env-ssh.d.ts +8 -2
  253. package/dist/plugins/remote-env-ssh.js +26 -24
  254. package/dist/plugins/remote-shell.d.ts +59 -30
  255. package/dist/plugins/remote-shell.js +175 -62
  256. package/dist/plugins/retention-declaration.d.ts +37 -0
  257. package/dist/plugins/retention-declaration.js +9 -0
  258. package/dist/plugins/retention-deployment.d.ts +126 -0
  259. package/dist/plugins/retention-deployment.js +88 -0
  260. package/dist/plugins/retention-lane-store-sql.d.ts +74 -4
  261. package/dist/plugins/retention-lane-store-sql.js +103 -1
  262. package/dist/plugins/retention-sql.d.ts +29 -0
  263. package/dist/plugins/retention-sql.js +8 -0
  264. package/dist/plugins/schema-consistency.d.ts +0 -6
  265. package/dist/plugins/schema-consistency.js +1 -2
  266. package/dist/plugins/schema-ensure-legs.d.ts +1 -1
  267. package/dist/plugins/schema-ensure-legs.js +11 -1
  268. package/dist/plugins/session-ext-table.d.ts +74 -0
  269. package/dist/plugins/session-ext-table.js +121 -0
  270. package/dist/plugins/session-fork.d.ts +1 -1
  271. package/dist/plugins/session-row-sql.d.ts +8 -7
  272. package/dist/plugins/session-row-sql.js +15 -7
  273. package/dist/plugins/session-store-sql.d.ts +131 -0
  274. package/dist/plugins/session-store-sql.js +298 -0
  275. package/dist/plugins/session-workspace-cell.d.ts +2 -2
  276. package/dist/plugins/session-workspace-cell.js +2 -2
  277. package/dist/plugins/shared-memory-store-sql.d.ts +10 -0
  278. package/dist/plugins/shared-memory-store-sql.js +13 -13
  279. package/dist/plugins/snapshot-bucket-presence.js +1 -1
  280. package/dist/plugins/sql-driver.d.ts +23 -7
  281. package/dist/plugins/sql-driver.js +41 -8
  282. package/dist/plugins/sql-errors.d.ts +5 -2
  283. package/dist/plugins/sql-errors.js +4 -0
  284. package/dist/plugins/store-backend.d.ts +35 -8
  285. package/dist/plugins/store-backend.js +184 -62
  286. package/dist/plugins/store-contracts.d.ts +9 -2
  287. package/dist/plugins/store-contracts.js +1 -0
  288. package/dist/plugins/task-attachment-store.d.ts +6 -8
  289. package/dist/plugins/task-attachment-store.js +15 -10
  290. package/dist/plugins/task-list-store-sql.d.ts +1 -1
  291. package/dist/plugins/text-column-capacity.d.ts +21 -0
  292. package/dist/plugins/text-column-capacity.js +5 -0
  293. package/dist/plugins/tidb-pool.d.ts +3 -2
  294. package/dist/plugins/tidb-pool.js +19 -31
  295. package/dist/plugins/user-input-ledger-sql.d.ts +1 -1
  296. package/dist/read-face-posture.d.ts +6 -6
  297. package/dist/read-face-posture.js +2 -2
  298. package/dist/request-value-closure.d.ts +5 -5
  299. package/dist/request-value-closure.js +1 -1
  300. package/dist/rules-consent.d.ts +41 -13
  301. package/dist/rules-consent.js +101 -53
  302. package/dist/run-local.js +17 -13
  303. package/dist/runs.d.ts +48 -30
  304. package/dist/runs.js +26 -16
  305. package/dist/runtime-caps-resolver.d.ts +15 -8
  306. package/dist/runtime-caps-resolver.js +14 -10
  307. package/dist/sealed-key-layout.d.ts +2 -3
  308. package/dist/sealed-key-layout.js +0 -1
  309. package/dist/sealed-key.js +7 -5
  310. package/dist/security.d.ts +5 -3
  311. package/dist/sema-config-dir.js +2 -2
  312. package/dist/server-secret-env.d.ts +2 -0
  313. package/dist/service-version.d.ts +2 -1
  314. package/dist/service-version.js +2 -2
  315. package/dist/session-error-wire.d.ts +1 -1
  316. package/dist/session-incarnation.d.ts +8 -5
  317. package/dist/session-resident-background.d.ts +85 -32
  318. package/dist/session-resident-background.js +75 -7
  319. package/dist/session-row.d.ts +1 -1
  320. package/dist/session-sync-kernel.d.ts +1 -1
  321. package/dist/session-workspace.d.ts +11 -2
  322. package/dist/session-workspace.js +5 -0
  323. package/dist/sighup-idle.d.ts +1 -1
  324. package/dist/store-posture.d.ts +2 -1
  325. package/dist/stored-request-hooks-m20.d.ts +3 -2
  326. package/dist/stored-request-hooks-m20.js +19 -14
  327. package/dist/stores-sql/blob-index-sql.d.ts +148 -0
  328. package/dist/stores-sql/blob-index-sql.js +154 -0
  329. package/dist/stores-sql/checkpoint-store-sql.d.ts +1 -1
  330. package/dist/stores-sql/checkpoint-store-sql.js +11 -27
  331. package/dist/{plugins → stores-sql}/file-history-store-sql.d.ts +23 -11
  332. package/dist/{plugins → stores-sql}/file-history-store-sql.js +23 -18
  333. package/dist/{plugins → stores-sql}/pg-session-storage.d.ts +23 -76
  334. package/dist/{plugins → stores-sql}/pg-session-storage.js +80 -209
  335. package/dist/{plugins → stores-sql}/retention-store-sql.d.ts +123 -217
  336. package/dist/{plugins → stores-sql}/retention-store-sql.js +66 -190
  337. package/dist/{plugins → stores-sql}/session-event-payload.d.ts +1 -1
  338. package/dist/{plugins → stores-sql}/session-event-payload.js +1 -1
  339. package/dist/stores-sql/session-policy-store-sql.d.ts +1 -1
  340. package/dist/stores-sql/session-write-hooks.d.ts +59 -0
  341. package/dist/stores-sql/session-write-hooks.js +2 -0
  342. package/dist/{plugins → stores-sql}/tidb-session-storage.d.ts +10 -11
  343. package/dist/{plugins → stores-sql}/tidb-session-storage.js +10 -21
  344. package/dist/{plugins → stores-sql}/tidb-session-store.d.ts +32 -122
  345. package/dist/{plugins → stores-sql}/tidb-session-store.js +71 -171
  346. package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
  347. package/dist/stores-sql/tool-result-store-sql.js +1 -1
  348. package/dist/stores-sql/windowed-session-storage.d.ts +56 -0
  349. package/dist/stores-sql/windowed-session-storage.js +61 -0
  350. package/dist/task-a2a.d.ts +7 -1
  351. package/dist/task-a2a.js +15 -14
  352. package/dist/task-cwd.d.ts +11 -3
  353. package/dist/task-cwd.js +17 -1
  354. package/dist/task-mcp.d.ts +10 -2
  355. package/dist/task-mcp.js +13 -16
  356. package/dist/task-settings.d.ts +9 -4
  357. package/dist/task-settings.js +17 -6
  358. package/dist/tool-approval.d.ts +21 -8
  359. package/dist/tool-approval.js +10 -6
  360. package/dist/trace/core-keyset-guard.d.ts +9 -3
  361. package/dist/trace/engine-notice-wire.d.ts +1 -1
  362. package/dist/trace/engine-notice-wire.js +2 -0
  363. package/dist/trace/exit-seat.d.ts +23 -1
  364. package/dist/trace/exit-seat.js +3 -0
  365. package/dist/trace/project.d.ts +33 -16
  366. package/dist/trace/project.js +12 -9
  367. package/dist/trace/redact.d.ts +1 -1
  368. package/dist/trace/redact.js +61 -73
  369. package/dist/trace/self-minted-wire.d.ts +263 -10
  370. package/dist/trace/self-minted-wire.js +90 -2
  371. package/dist/trace/sema-provenance.d.ts +45 -41
  372. package/dist/trace/sema-provenance.js +81 -10
  373. package/dist/trace/task-notification-facets.d.ts +70 -2
  374. package/dist/trace/task-notification-facets.js +71 -1
  375. package/dist/trace/wire-projection-faces.d.ts +38 -2
  376. package/dist/trace/wire-projection-faces.js +26 -1
  377. package/dist/unread-request-members.d.ts +66 -0
  378. package/dist/unread-request-members.js +41 -0
  379. package/dist/user-input-ledger.d.ts +2 -2
  380. package/dist/web-admin-client/apply-effective.js +22 -26
  381. package/dist/web-admin-client/candidate-gate.d.ts +35 -3
  382. package/dist/web-admin-client/candidate-gate.js +53 -5
  383. package/dist/web-admin-client/center-request.d.ts +4 -1
  384. package/dist/web-admin-client/center-request.js +2 -1
  385. package/dist/web-admin-client/effective-keys.js +0 -1
  386. package/dist/web-admin-client/facade.d.ts +1 -1
  387. package/dist/web-admin-client/http-client.d.ts +1 -0
  388. package/dist/web-admin-client/http-client.js +17 -9
  389. package/dist/web-admin-client/restart-signal.js +5 -2
  390. package/dist/web-admin-client/skills-mcp.d.ts +20 -6
  391. package/dist/web-admin-client/skills-mcp.js +26 -21
  392. package/dist/web-admin-client/types.d.ts +34 -49
  393. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +2 -2
  394. package/package.json +13 -12
  395. package/scripts/drain-check-local.mjs +2 -28
  396. package/scripts/drain-check.mysql.sql +2 -18
  397. package/scripts/drain-check.pg.sql +2 -18
  398. package/wire-changes/server@7.147.0.json +813 -0
@@ -2,6 +2,30 @@ import { pgSafeJsonStringify, pgProtocolJsonStringify } from "./pg-safe-json.js"
2
2
  import { recordFailOpen } from "../observability/fail-open.js";
3
3
  import { errorKindOf } from "../observability/err-text.js";
4
4
  import { isConnectionUnusableError } from "./sql-errors.js";
5
+ export class SqlStatementDeadlineExceeded extends Error {
6
+ deadlineMs;
7
+ constructor(deadlineMs) {
8
+ super(`SQL statement did not settle within ${deadlineMs}ms — the connection was destroyed (its transaction rolls back when it closes)`);
9
+ this.deadlineMs = deadlineMs;
10
+ this.name = "SqlStatementDeadlineExceeded";
11
+ }
12
+ }
13
+ function withStatementDeadline(run, opts, destroy) {
14
+ const deadlineMs = opts?.deadlineMs;
15
+ if (deadlineMs === undefined)
16
+ return run();
17
+ const running = run();
18
+ running.catch(() => undefined);
19
+ let timer;
20
+ const expired = new Promise((_, reject) => {
21
+ timer = setTimeout(() => {
22
+ destroy();
23
+ reject(new SqlStatementDeadlineExceeded(deadlineMs));
24
+ }, deadlineMs);
25
+ timer.unref?.();
26
+ });
27
+ return Promise.race([running, expired]).finally(() => clearTimeout(timer));
28
+ }
5
29
  export const TIDB_DEFAULT_TXN_ENTRY_SIZE_LIMIT = 6_291_456;
6
30
  export const ROW_WALL_ALLOWANCE_BYTES = { json: 64 * 1024, blob: 1024 };
7
31
  export const STATEMENT_ALLOWANCE_BYTES = 1024;
@@ -299,15 +323,20 @@ function leaseOf(raw) {
299
323
  if (GUARDED_LEASES.has(raw))
300
324
  return raw;
301
325
  let destroyed = false;
326
+ let leaveQueue = () => undefined;
327
+ const gone = new Promise((resolve) => {
328
+ leaveQueue = resolve;
329
+ });
302
330
  const destroy = () => {
303
331
  if (destroyed)
304
332
  return;
305
333
  destroyed = true;
334
+ leaveQueue();
306
335
  raw.destroy();
307
336
  };
308
337
  let turn = Promise.resolve();
309
338
  const guard = (run) => {
310
- const result = turn.then(async () => {
339
+ const result = Promise.race([turn, gone]).then(async () => {
311
340
  try {
312
341
  return await run();
313
342
  }
@@ -388,7 +417,7 @@ export function mysqlDriver(pool) {
388
417
  if (broken !== undefined)
389
418
  throw broken.error;
390
419
  const conn = {
391
- query: (sql, params) => mysqlQuery(c, sql, params),
420
+ query: (sql, params, opts) => withStatementDeadline(() => mysqlQuery(c, sql, params), opts, () => c.destroy()),
392
421
  begin: () => c.beginTransaction(),
393
422
  commit: () => c.commit(),
394
423
  rollback: () => c.rollback(),
@@ -440,8 +469,14 @@ export function pgDriver(pool) {
440
469
  const c = await pool.connect();
441
470
  const { facts, initOrdinal } = await establishSession(session, c, c, initPgSession);
442
471
  let destroyed = false;
472
+ const destroy = () => {
473
+ if (destroyed)
474
+ return;
475
+ destroyed = true;
476
+ c.release(true);
477
+ };
443
478
  const conn = {
444
- query: (sql, params) => pgQuery(c, sql, params),
479
+ query: (sql, params, opts) => withStatementDeadline(() => pgQuery(c, sql, params), opts, destroy),
445
480
  begin: async () => {
446
481
  await c.query("BEGIN");
447
482
  },
@@ -449,7 +484,8 @@ export function pgDriver(pool) {
449
484
  await c.query("COMMIT");
450
485
  },
451
486
  rollback: async () => {
452
- await c.query("ROLLBACK");
487
+ if (!destroyed)
488
+ await c.query("ROLLBACK");
453
489
  },
454
490
  release: () => {
455
491
  if (!destroyed)
@@ -461,10 +497,7 @@ export function pgDriver(pool) {
461
497
  facts,
462
498
  initOrdinal,
463
499
  id: typeof pid === "number" ? pid : null,
464
- destroy: () => {
465
- destroyed = true;
466
- c.release(true);
467
- },
500
+ destroy,
468
501
  readGlobalPacketWall: async () => null,
469
502
  });
470
503
  return conn;
@@ -193,12 +193,15 @@ export declare function isConnectionFaultError(err: unknown): boolean;
193
193
  * **部署错配类故障**的识别表(闭集;逐行登记「为什么」)—— 到库的连接是好的、语句也是对的,是这套库的形与本部署的要求不符:**重试注定失败**,修表 / 授权之前什么都不会变
194
194
  * (与连接类互为反面:那一类是「什么都不改稍后再试可能成」)。读者:整仓一只判官 `plugins/store-fault.ts` 的 `storeFaultClassOf` 的 `deployment` 一词 ——
195
195
  * 文件历史店的折点与会话同步拉取口(`503 state.file_history_unreadable`)据它判 `permanence: "terminal"`;审批队列读口并入「此刻读不出」的 503;各读者各自表态,**不在自己那里写码**。
196
+ * 起服建表(`session-ext-table.ts` 的 `ensureSessionExtTableMysql`)问的也是这一只:「库确定拒了这条 DDL」= 本表认得 ⇒ 当场拒启;认不出 ⇒ 原样上抛、开库等待窗重试 —— 不自带第二份分类。
197
+ * 外键四码(3780 / 1215 / 1822 / 1005)只可能出在建表 / 改表上,读写路径上的读者见不到它们 —— 加进本表对那几处零变化。
196
198
  *
197
199
  * 识别集 = 本表一张,按归因键登记:`code`(字符串)与 MySQL 协议的数字 `errno`(两键是同一件事的两种写法,代理 / 序列化往返可能只留一个;同本文件其余谓词的姿势)。
198
200
  * **与连接类互斥**:本表的任何一码都不在 {@link CONNECTION_FAULT_ERRORS} / {@link MYSQL_CONNECTION_UNUSABLE_ERRORS} 的识别集里,反之亦然(`test/store-fault-judge.test.ts` 钉两个方向)—— 同一只错只落一个词。
199
201
  *
200
- * **不在表里**(认不出一律不是;本批只收缺表与权限拒两形,其余是登记在案的未收项,不是「已裁定不判」):缺列(1054 / `42703`:升级前置断言 `assert*Schema` 族有自己的判据与出路)、
201
- * 认证类拒连(MySQL 1045、PG `28xxx`:凭据 / 白名单)、库级与列级的权限拒(MySQL 1044 / 1143)、TiDB 自己的忙 / 区域不可用一族(同连接类表的登记)。
202
+ * **不在表里**(认不出一律不是;今天收缺表、权限拒与外键建不成三形,其余是登记在案的未收项,不是「已裁定不判」):缺列(1054 / `42703`:升级前置断言 `assert*Schema` 族有自己的判据与出路)、
203
+ * 认证类拒连(MySQL 1045、PG `28xxx`:凭据 / 白名单)、库级与列级的权限拒(MySQL 1044 / 1143)、语法错(1064:多半是我方的语句,不是库的形)、
204
+ * TiDB 自己的忙 / 区域不可用 / 结构变更冲突一族(9001 / 9005 / 8028,同连接类表的登记)、锁等待超时(1205)。
202
205
  */
203
206
  export declare const DEPLOYMENT_FAULT_ERRORS: ReadonlyArray<{
204
207
  readonly code: string;
@@ -148,6 +148,10 @@ export const DEPLOYMENT_FAULT_ERRORS = [
148
148
  { code: "42501", why: "PG insufficient_privilege(权限拒:库账号缺这张表 / 这类语句的授权 —— 授权之前重试注定失败)" },
149
149
  { code: "ER_NO_SUCH_TABLE", errno: 1146, why: "MySQL 协议(MySQL / MariaDB / TiDB)缺表:同 PG `42P01`" },
150
150
  { code: "ER_TABLEACCESS_DENIED_ERROR", errno: 1142, why: "MySQL 协议表级权限拒:库账号对这张表缺这类语句的授权,同 PG `42501`" },
151
+ { code: "ER_FK_INCOMPATIBLE_COLUMNS", errno: 3780, why: "MySQL 协议外键两侧列不相容(类型 / 字符集 / 排序规则对不上):被引表的形与外键要求不符,重试同一句仍不相容" },
152
+ { code: "ER_CANNOT_ADD_FOREIGN", errno: 1215, why: "MySQL 协议加不上外键(如被引表不是 InnoDB):库的形不收这条约束,改表之前重试注定失败" },
153
+ { code: "ER_FK_NO_INDEX_PARENT", errno: 1822, why: "MySQL 协议外键的被引列上缺索引:被引表的形不符,建索引之前重试注定失败" },
154
+ { code: "ER_CANT_CREATE_TABLE", errno: 1005, why: "MySQL 协议建表被存储引擎拒(errno 150 外键形不成 / 121 约束名已占 / 28 盘满):修库之前重试同一句仍被拒" },
151
155
  ];
152
156
  const DEPLOYMENT_FAULT_CODES = new Set(DEPLOYMENT_FAULT_ERRORS.map((r) => r.code));
153
157
  const DEPLOYMENT_FAULT_ERRNOS = new Set(DEPLOYMENT_FAULT_ERRORS.flatMap((r) => (r.errno === undefined ? [] : [r.errno])));
@@ -33,9 +33,12 @@ import type { CounterDegradeHook } from "./write-behind-counter.js";
33
33
  import { PgRateLimiter } from "./pg-rate-limiter.js";
34
34
  import { type SqlSharedMemoryStore, type SharedMemoryScopeAuthorizer } from "./shared-memory-store-sql.js";
35
35
  import { type AdoptionLogStore } from "./adoption-log-sql.js";
36
- import { type SqlRetentionStore, type SqlRetentionStoreOptions } from "./retention-store-sql.js";
36
+ import { type SqlTransactionHooks } from "../stores-sql/retention-store-sql.js";
37
+ import type { EndedSpace } from "../workspace-space.js";
38
+ import { type RetentionDestructiveInput, type RetentionExecutor, type RetentionExecutorOptions } from "./retention-deployment.js";
37
39
  import { type RetentionLaneStore } from "./retention-lane-store-sql.js";
38
40
  import type { PermissionRuleStoreBundle } from "../rules-consent.js";
41
+ import { type SqlDriver } from "./sql-driver.js";
39
42
  import { type StoreDegradedReason } from "../store-posture.js";
40
43
  /** boot 期的一条日志座(级别由**座位**决定,不由参数携带):`createStoreBackend` 的 `onWarn` / `onError`
41
44
  * 两参与 `LocalBackend` 的同名字段共用此形。装配层把它们分别接到 `logger.warn` / `logger.error` 上。 */
@@ -65,7 +68,7 @@ export type ServiceSessionPolicyStore = SessionPolicyStore;
65
68
  * The SQL twins' blob exchange — core's {@link FileHistoryBlobExchange} group (`put` / `get` / `has`, all three or none, read only
66
69
  * through `blobExchangeOf` in `session-sync.ts`, which defers to core's judge) with ONE narrowing: a `put` refusal may carry
67
70
  * `blobCap`, the SQL blob judge's refusal on the connection that would have written the blob
68
- * ({@link import("./blob-backend.js").BlobTooLargeError}). Present ⟺ that refusal; `PUT /sync/blobs` answers it 413
71
+ * ({@link import("../stores-sql/blob-index-sql.js").BlobTooLargeError}). Present ⟺ that refusal; `PUT /sync/blobs` answers it 413
69
72
  * `blob_too_large_for_sql` (the judge's sentence, plus the machine-readable `wallSource` = where the cap came from). The content-address
70
73
  * refusal is core's own (`adopt_failed`, `permanence: "terminal"`, nothing stored); every other failure is a write fault the route answers 502.
71
74
  */
@@ -75,7 +78,7 @@ export type SqlBlobPutResult = {
75
78
  readonly ok: false;
76
79
  readonly error: FileHistoryError & {
77
80
  readonly blobCap?: {
78
- readonly wallSource: import("./blob-backend.js").SqlBlobCapReading["source"];
81
+ readonly wallSource: import("../stores-sql/blob-index-sql.js").SqlBlobCapReading["source"];
79
82
  };
80
83
  };
81
84
  };
@@ -163,7 +166,8 @@ export interface StoreBackend {
163
166
  * schema that the one-time migrations of server 7.74.0–7.125.x retired and **refuses** with `RetiredSchemaPresentError`
164
167
  * (code `config.schema_mismatch`, exported from the package root) before it issues the first CREATE; only then does it create.
165
168
  * The check lives in this method itself, so the public sequence `createStoreBackend()` → `ensureSchema()` → `runOneTimeMigrations()`
166
- * needs no step of its own. The LOCAL backend has no SQL pool and nothing to probe. */
169
+ * needs no step of its own. The LOCAL backend has no SQL pool: its data root's engine high-water is judged when the backend is opened (before any store is built),
170
+ * and a data root refused there surfaces here, as that refusal; otherwise this runs the local reconciliation (strict sidecars, archive snapshots). */
167
171
  ensureSchema(): Promise<void>;
168
172
  close(): Promise<void>;
169
173
  run(): RunStore;
@@ -354,7 +358,7 @@ export interface StoreBackend {
354
358
  * `local` 刻意省略 —— 与 {@link leaderRun} 逐字同一条理由:config 层已经把「`REMOTE_EXEC=device` 且
355
359
  * 无外部 SQL 店」整个组合拒启了(`device-durable-store` 不变量),所以 local 车道上根本不存在一个需要
356
360
  * 这四张表的 device worker。消费点按 `backend?.device?.()` 取,缺席 ⇒ `boot/device-lane.ts` 的
357
- * `assertDeviceLaneWired` 响亮拒启(**不是**静默落进程内 stub)。
361
+ * `assertDeviceLaneWired` 响亮拒启(**不是**静默跑成无手)。
358
362
  */
359
363
  device?(): DeviceStore;
360
364
  /**
@@ -364,9 +368,9 @@ export interface StoreBackend {
364
368
  *
365
369
  * `taskAttachmentTable` 必填、无默认值 —— boot 只在配了对象存储时才 ensure 那张表,一条盲发的
366
370
  * DELETE 在无 MinIO 的部署上会以 unknown-table 打红整轮 sweep(理由逐字见
367
- * `retention-store-sql.ts` 的 `SqlRetentionStoreOptions`)。
371
+ * `retention-deployment.ts` 的 `RetentionExecutorOptions`)。组合形见 {@link createSqlRetentionExecutor}。
368
372
  */
369
- retention?(opts: SqlRetentionStoreOptions): SqlRetentionStore;
373
+ retention?(opts: RetentionExecutorOptions): RetentionExecutor;
370
374
  /**
371
375
  * [ref] 车2 —— 留存执行面的**非破坏性**半场:sweep 租约、legal-hold 的放置/解除、审计表的读与
372
376
  * 非破坏行的写。同样 SQL 专有(它写的三张表只在 SQL schema 里)。
@@ -403,6 +407,23 @@ export interface StoreBackend {
403
407
  * `new FileUsageWindowStore(root)` 第二只实例、不接座 ⇒ 坏值只拒不披露,运维找不到是哪只文件。SQL 后端省略(它们有自己的 usage-window 双方言店)。 */
404
408
  fileUsageWindowStore?(): UsageWindowStore;
405
409
  }
410
+ /**
411
+ * 托管留存执行器的**组合**:引擎座表那一半(`SqlRetentionStore`,事务属主)+ 部署那一半(hold / 审计 / 认领判 / 十一张部署表,
412
+ * `plugins/retention-deployment.ts`,经 K4 事务内钩参与同一事务)。
413
+ *
414
+ * 破坏性三方法**每次调用**铸一只执行器、钩表绑这一次调用(`createRetentionDeploymentHooks` 的头注:审计行的判定时点三格与
415
+ * `checkpoint_ctx` 属主门的域是这一次调用的事实)。会话树删除的 `endedSpaces` 由部署从 `beforeDelete` 收到的行自算,
416
+ * 只在执行器**提交成功返回之后**挂上回执(回滚 ⇒ 执行器抛,不挂)。非破坏两口(域枚举 / 预览)不经钩。
417
+ */
418
+ /**
419
+ * 一次破坏性调用的整张事务内钩表:部署的 `retention` 组(按这一次调用铸,`createRetentionDeploymentHooks`)+ 会话座的钩
420
+ * (`createSqlSessionWriteHooks`,会话店用的同一只工厂;留存删除走它的 `retention-delete` 臂)。`endedSpaces` 读部署那一半收到的行。
421
+ */
422
+ export declare function createSqlRetentionCallHooks(db: SqlDriver, opts: RetentionExecutorOptions, input: RetentionDestructiveInput): {
423
+ readonly hooks: SqlTransactionHooks;
424
+ endedSpaces(): readonly EndedSpace[];
425
+ };
426
+ export declare function createSqlRetentionExecutor(db: SqlDriver, opts: RetentionExecutorOptions): RetentionExecutor;
406
427
  /** (c)(clay 拍 a+c,2026-07-27;[ref] 换店后域=file_history_blob,门与旋钮名不变)云形 blob 姿势门——
407
428
  * boot 时调用(boot/stores.ts),纯函数可单测。SQL 后端(mysql|pg)把 blob 字节落单行的形已被两役
408
429
  * 实证撞 mysql-协议包墙(D-1 附件 → 对象存储裁定):大字节归对象存储。per-file 历史的 blob=单文件
@@ -471,7 +492,13 @@ export declare function createStoreBackend(config: ServiceConfig, onWarn?: BootL
471
492
  * 而 LocalBackend 的 `ensureSchema` 是**空实现**,真正会抛的 mkdir + 数据根 BootLock 在构造函数里、
472
493
  * 落在 try 之外。于是那条降级臂对 local 形从来没生效过,注释宣称的行为与代码真做的事撕裂。
473
494
  *
474
- * **降级臂只有一条:缺省推导的 local**(`dbBackend=local && !dbBackendExplicit`)。🔴 **SQL 族没有降级臂** —— 配了 DSN 就是要这只库:
495
+ * **降级臂只有一条:缺省推导的 local 且数据根上什么都没有**(`dbBackend=local && !dbBackendExplicit`,数据根不存在或是空目录 —— 开店之前判)。
496
+ * 判据看的是**数据根的状态**,不是错误的种类:数据根上已有东西 ⇒ 这台部署有过持久面,开它时的**任何**失败(权限 / 只读挂载 / 子目录建不出 /
497
+ * 另一实例持锁 / adoption 在飞 / 账本重放不了 …)都按显式 `DB_BACKEND=local` 同待遇 —— 原样抛、拒启,不退内存(退了 = 已有的会话 / run 账本 /
498
+ * 问账整片看不见、新写只进内存,而 `/health` 照样 200)。只有「数据根不存在 / 空」那一形是「这台机器存不了盘」的诚实等价物,才许退内存 + 一行 warn。
499
+ * 修前按错误种类逐个豁免(adoption 一条、File 店族拒启一条、再往各店构造器里逐处包),漏一处就是一条 fail-open;按状态判之后,新店的新失败默认落在拒启一侧。
500
+ * 1.292 的口径据此收窄:只读挂载 / 建不出的根**在空 / 不存在时**仍退内存;已有数据的根拒启(出路:修好权限 / 挂载 / 停掉持锁的另一实例;要内存就显式写
501
+ * `DB_BACKEND=memory`;要另起一个空根就把 `LOCAL_DATA_ROOT` 指过去)。🔴 **SQL 族没有降级臂** —— 配了 DSN 就是要这只库:
475
502
  * `SESSION_BACKEND=auto` 与显式 `DB_BACKEND=mysql|pg` 同一待遇,库当下打不开 ⇒ 在 `STORE_LOCK_WAIT_MS` 的窗内重试
476
503
  * ({@link openWithinWait}),到窗仍打不开 ⇒ 拒启(拒句 {@link buildSqlStoreOpenRefusal} 点名后端与库的显示安全形)。修前 `auto` 在这里
477
504
  * 静默落内存(只留一行 warn):会话 / 停驻 / run 账本进进程内存、重启即丢,而 `/health` 照样 200 —— [ref] P 类 fail-open。
@@ -2,7 +2,7 @@ import { homedir } from "node:os";
2
2
  import { createCorruptReadSeat, createDurableAbsenceSeat } from "../observability/corrupt-read-seat.js";
3
3
  import { createLogger } from "../observability/logger.js";
4
4
  import { join } from "node:path";
5
- import { existsSync } from "node:fs";
5
+ import { existsSync, readdirSync } from "node:fs";
6
6
  import { AdoptionError, FileStorageBackend } from "@sema-agent/core";
7
7
  import { FileWorkflowJournalStore } from "@sema-agent/core";
8
8
  import { fileSessionCaptureRecordStore } from "@sema-agent/core";
@@ -34,10 +34,11 @@ import { TiDBUserInputLedgerStore, PgUserInputLedgerStore } from "./user-input-l
34
34
  import { TiDBResumeAnchorStore, PgResumeAnchorStore } from "./resume-anchor-store-sql.js";
35
35
  import { TiDBSessionPolicyStore, PgSessionPolicyStore } from "../stores-sql/session-policy-store-sql.js";
36
36
  import { TiDBWorkflowJournalStore, PgWorkflowJournalStore } from "../stores-sql/workflow-journal-store-sql.js";
37
- import { TiDBFileHistoryStore, PgFileHistoryStore, FILE_HISTORY_BLOB_TABLE, FILE_HISTORY_BLOB_KEY_PREFIX } from "./file-history-store-sql.js";
38
- import { MinioBlobBackend, SqlBlobBackend } from "./blob-backend.js";
37
+ import { TiDBFileHistoryStore, PgFileHistoryStore, FILE_HISTORY_BLOB_KEY_PREFIX } from "../stores-sql/file-history-store-sql.js";
38
+ import { SqlBlobIndex } from "../stores-sql/blob-index-sql.js";
39
+ import { MinioBlobBackend } from "./blob-backend.js";
39
40
  import { buildDisplaySafeUrl } from "../trace/redact.js";
40
- import { fileMemoryControlDirFor } from "../memory-scope.js";
41
+ import { fileMemoryControlDirFor, memoryEngineRootFor } from "../memory-scope.js";
41
42
  import { createTidbPool, ensureSchema as ensureTidbSchema } from "./tidb-pool.js";
42
43
  import { createPgPool, ensurePgSchema, pgPoolOptions } from "./pg-pool.js";
43
44
  import { TiDBRunStore, PgRunStore } from "./run-store-sql.js";
@@ -52,48 +53,62 @@ import { TiDBCostQuota } from "./tidb-cost-quota.js";
52
53
  import { PgCostQuota } from "./pg-cost-quota.js";
53
54
  import { TiDBRateLimiter } from "./tidb-rate-limiter.js";
54
55
  import { PgRateLimiter } from "./pg-rate-limiter.js";
55
- import { TiDBSessionStore } from "./tidb-session-store.js";
56
- import { PgSessionStore } from "./pg-session-storage.js";
56
+ import { TiDBSessionStore } from "../stores-sql/tidb-session-store.js";
57
+ import { PgSessionStore } from "../stores-sql/pg-session-storage.js";
58
+ import { SqlSessionStore } from "./session-store-sql.js";
57
59
  import { TiDBSharedMemoryStore, PgSharedMemoryStore } from "./shared-memory-store-sql.js";
58
60
  import { TiDBAdoptionLogStore, PgAdoptionLogStore } from "./adoption-log-sql.js";
59
- import { TiDBRetentionStore, PgRetentionStore, sqlStoreRetention } from "./retention-store-sql.js";
61
+ import { SqlRetentionStore } from "../stores-sql/retention-store-sql.js";
62
+ import { sqlStoreRetention } from "./retention-declaration.js";
63
+ import { createRetentionDeploymentHooks } from "./retention-deployment.js";
64
+ import { createSqlSessionWriteHooks } from "./session-store-sql.js";
60
65
  import { TiDBRetentionLaneStore, PgRetentionLaneStore } from "./retention-lane-store-sql.js";
61
66
  import { createSqlPermissionRuleStores } from "./permission-rule-store-sql.js";
62
67
  import { FILE_PERMISSION_RULE_DIR, createFilePermissionRuleStores, fileRuleBucketOwners, isFileBucketDamaged } from "./permission-rule-store-file.js";
63
68
  import { retireImportedLayerRootAllows } from "./imported-layer-root-retirement.js";
69
+ import { buildDataDirLayout, tightenLocalDataDirModes } from "./local-data-dir-modes-m39.js";
70
+ import { holdEngineHighWater } from "./local-engine-high-water.js";
71
+ import { serviceVersion } from "../service-version.js";
64
72
  import { mysqlDriver, pgDriver } from "./sql-driver.js";
65
73
  import { storeDegradedReasonFor } from "../store-posture.js";
66
74
  import { openWithinWait } from "./store-open-wait.js";
67
75
  export function workflowJournalOf(config, backend) {
68
76
  return config.selfOrchestrationEnabled && backend ? backend.workflowJournal() : undefined;
69
77
  }
70
- function historyBlobBackend(config, dialect, pool) {
78
+ function fileHistoryOptions(config) {
71
79
  const s = config.snapshotBlobStore;
72
- if (!s)
73
- return new SqlBlobBackend(dialect, pool, config.snapshotBlobSqlMaxBytes, FILE_HISTORY_BLOB_TABLE, createLogger(config.logLevel));
74
- return new MinioBlobBackend({
75
- endpoint: s.endpoint,
76
- bucket: s.bucket,
77
- accessKey: s.accessKey,
78
- secretKey: s.secretKey,
79
- ...(s.region ? { region: s.region } : {}),
80
- keyPrefix: `${s.keyPrefix ?? ""}${FILE_HISTORY_BLOB_KEY_PREFIX}`,
81
- ...(s.presignTtlSec ? { presignTtlSec: s.presignTtlSec } : {}),
82
- }, { dialect, pool, table: FILE_HISTORY_BLOB_TABLE });
80
+ const placement = s
81
+ ? {
82
+ blobs: new MinioBlobBackend({
83
+ endpoint: s.endpoint,
84
+ bucket: s.bucket,
85
+ accessKey: s.accessKey,
86
+ secretKey: s.secretKey,
87
+ ...(s.region ? { region: s.region } : {}),
88
+ keyPrefix: `${s.keyPrefix ?? ""}${FILE_HISTORY_BLOB_KEY_PREFIX}`,
89
+ ...(s.presignTtlSec ? { presignTtlSec: s.presignTtlSec } : {}),
90
+ }),
91
+ }
92
+ : {
93
+ ...(config.snapshotBlobSqlMaxBytes !== undefined ? { blobSqlMaxBytes: config.snapshotBlobSqlMaxBytes } : {}),
94
+ log: createLogger(config.logLevel),
95
+ };
96
+ return { ...config.fileHistory, ...placement };
83
97
  }
84
- function legacyBlobBackend(config, dialect, pool) {
98
+ function legacyBlobIndex(config, dialect, pool) {
85
99
  const s = config.snapshotBlobStore;
86
- if (!s)
87
- return new SqlBlobBackend(dialect, pool, config.snapshotBlobSqlMaxBytes, undefined, createLogger(config.logLevel));
88
- return new MinioBlobBackend({
89
- endpoint: s.endpoint,
90
- bucket: s.bucket,
91
- accessKey: s.accessKey,
92
- secretKey: s.secretKey,
93
- ...(s.region ? { region: s.region } : {}),
94
- ...(s.keyPrefix ? { keyPrefix: s.keyPrefix } : {}),
95
- ...(s.presignTtlSec ? { presignTtlSec: s.presignTtlSec } : {}),
96
- }, { dialect, pool });
100
+ const bytes = s
101
+ ? new MinioBlobBackend({
102
+ endpoint: s.endpoint,
103
+ bucket: s.bucket,
104
+ accessKey: s.accessKey,
105
+ secretKey: s.secretKey,
106
+ ...(s.region ? { region: s.region } : {}),
107
+ ...(s.keyPrefix ? { keyPrefix: s.keyPrefix } : {}),
108
+ ...(s.presignTtlSec ? { presignTtlSec: s.presignTtlSec } : {}),
109
+ })
110
+ : undefined;
111
+ return new SqlBlobIndex(dialect, pool, { table: "snapshot_blob", ...(bytes !== undefined ? { bytes } : {}), log: createLogger(config.logLevel) });
97
112
  }
98
113
  async function legacySweepImpl(config, dialect, pool) {
99
114
  const sql = "SELECT blob_hash FROM snapshot_blob";
@@ -108,7 +123,38 @@ async function legacySweepImpl(config, dialect, pool) {
108
123
  }
109
124
  if (orphans.length === 0)
110
125
  return 0;
111
- return legacyBlobBackend(config, dialect, pool).deleteBlobs(orphans);
126
+ return legacyBlobIndex(config, dialect, pool).sweep(orphans);
127
+ }
128
+ export function createSqlRetentionCallHooks(db, opts, input) {
129
+ const deployment = createRetentionDeploymentHooks(db.dialect, opts, input);
130
+ return { hooks: { retention: deployment.hooks.retention, session: createSqlSessionWriteHooks(db) }, endedSpaces: deployment.endedSpaces };
131
+ }
132
+ export function createSqlRetentionExecutor(db, opts) {
133
+ const logged = opts.logger !== undefined ? { logger: opts.logger } : {};
134
+ const reads = new SqlRetentionStore(db, logged);
135
+ const forCall = (input) => {
136
+ const hooks = createSqlRetentionCallHooks(db, opts, input);
137
+ return { store: new SqlRetentionStore(db, { ...logged, transactionHooks: hooks.hooks }), hooks, call: { domain: input.domain, cutoffMs: input.cutoffMs } };
138
+ };
139
+ return {
140
+ retention: reads.retention,
141
+ listRetentionDomains: () => reads.listRetentionDomains(),
142
+ previewRetention: (input) => reads.previewRetention(input),
143
+ expireCheckpoints: async (input) => {
144
+ const one = forCall(input);
145
+ return one.store.expireCheckpoints(one.call);
146
+ },
147
+ deleteExpiredSessions: async (input) => {
148
+ const one = forCall(input);
149
+ const receipt = await one.store.deleteExpiredSessions(one.call);
150
+ const endedSpaces = one.hooks.endedSpaces();
151
+ return endedSpaces.length > 0 ? { ...receipt, endedSpaces } : receipt;
152
+ },
153
+ deleteOrphanToolResults: async (input) => {
154
+ const one = forCall(input);
155
+ return one.store.deleteOrphanToolResults(one.call);
156
+ },
157
+ };
112
158
  }
113
159
  export function assertCloudSnapshotBlobPosture(kind, config) {
114
160
  if (kind === "local" || config.snapshotBlobStore || config.snapshotBlobAllowSql)
@@ -141,12 +187,12 @@ class TiDBBackend {
141
187
  sendFileLedger() { return new TiDBSendFileLedger(this.pool); }
142
188
  userInputLedger() { return new TiDBUserInputLedgerStore(this.pool); }
143
189
  sessionPolicy(logger) { return new TiDBSessionPolicyStore(this.pool, logger); }
144
- fileHistory() { return new TiDBFileHistoryStore(this.pool, historyBlobBackend(this.config, "mysql", this.pool), this.config.fileHistory); }
190
+ fileHistory() { return new TiDBFileHistoryStore(this.pool, fileHistoryOptions(this.config)); }
145
191
  memoryOptOutGrant() { return new TiDBMemoryOptOutGrantStore(this.pool); }
146
192
  sessionCaptureRecords() { return () => (this.captureRecordsInst ??= new TiDBSessionCaptureRecordStore(this.pool)); }
147
193
  captureRecordsInst;
148
194
  legacySnapshotBlobSweep() { return legacySweepImpl(this.config, "mysql", this.pool); }
149
- runOneTimeMigrations() { return runSqlOneTimeMigrations("mysql", this.pool, { lanes: deployedExecutionLanes(this.config) }); }
195
+ runOneTimeMigrations() { return runSqlOneTimeMigrations("mysql", this.pool, { lanes: deployedExecutionLanes(this.config), liveRunWindowMs: this.config.runStaleSec * 1000 }); }
150
196
  workflowJournal() { return new TiDBWorkflowJournalStore(this.pool); }
151
197
  outcomeSink() { return new TiDBOutcomeLedger(this.pool); }
152
198
  workflowRun(onWarn) { return new TiDBWorkflowRunStore(this.pool, onWarn); }
@@ -163,12 +209,12 @@ class TiDBBackend {
163
209
  imageBake() { return new TiDBImageBake(this.pool); }
164
210
  leaderRun() { return new TiDBLeaderRunStore(this.pool); }
165
211
  device() { return new TiDBDeviceStore(this.pool); }
166
- retention(opts) { return new TiDBRetentionStore(this.pool, opts); }
212
+ retention(opts) { return createSqlRetentionExecutor(mysqlDriver(this.pool), opts); }
167
213
  retentionLane() { return new TiDBRetentionLaneStore(this.pool); }
168
214
  breaker(onWriteFail) { return new TiDBBreakerState(this.pool, onWriteFail); }
169
215
  costQuota(limitMicroUsd, windowMs, onDegraded) { return new TiDBCostQuota(this.pool, limitMicroUsd, windowMs, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
170
216
  rateLimiter(limit, onDegraded) { return new TiDBRateLimiter(this.pool, limit, undefined, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
171
- session() { return new TiDBSessionStore(this.pool, { retention: sqlStoreRetention(this.config.retentionSweep) }); }
217
+ session() { return new SqlSessionStore(mysqlDriver(this.pool), (hooks) => new TiDBSessionStore(this.pool, { retention: sqlStoreRetention(this.config.retentionSweep), hooks })); }
172
218
  adoptionLog() { return new TiDBAdoptionLogStore(this.pool); }
173
219
  mysqlPool() { return this.pool; }
174
220
  pgPool() { return undefined; }
@@ -195,12 +241,12 @@ class PgBackend {
195
241
  sendFileLedger() { return new PgSendFileLedger(this.pool); }
196
242
  userInputLedger() { return new PgUserInputLedgerStore(this.pool); }
197
243
  sessionPolicy(logger) { return new PgSessionPolicyStore(this.pool, logger); }
198
- fileHistory() { return new PgFileHistoryStore(this.pool, historyBlobBackend(this.config, "pg", this.pool), this.config.fileHistory); }
244
+ fileHistory() { return new PgFileHistoryStore(this.pool, fileHistoryOptions(this.config)); }
199
245
  memoryOptOutGrant() { return new PgMemoryOptOutGrantStore(this.pool); }
200
246
  sessionCaptureRecords() { return () => (this.captureRecordsInst ??= new PgSessionCaptureRecordStore(this.pool)); }
201
247
  captureRecordsInst;
202
248
  legacySnapshotBlobSweep() { return legacySweepImpl(this.config, "pg", this.pool); }
203
- runOneTimeMigrations() { return runSqlOneTimeMigrations("pg", this.pool, { lanes: deployedExecutionLanes(this.config) }); }
249
+ runOneTimeMigrations() { return runSqlOneTimeMigrations("pg", this.pool, { lanes: deployedExecutionLanes(this.config), liveRunWindowMs: this.config.runStaleSec * 1000 }); }
204
250
  workflowJournal() { return new PgWorkflowJournalStore(this.pool); }
205
251
  outcomeSink() { return new PgOutcomeLedger(this.pool); }
206
252
  workflowRun(onWarn) { return new PgWorkflowRunStore(this.pool, onWarn); }
@@ -217,12 +263,12 @@ class PgBackend {
217
263
  imageBake() { return new PgImageBake(this.pool); }
218
264
  leaderRun() { return new PgLeaderRunStore(this.pool); }
219
265
  device() { return new PgDeviceStore(this.pool); }
220
- retention(opts) { return new PgRetentionStore(this.pool, opts); }
266
+ retention(opts) { return createSqlRetentionExecutor(pgDriver(this.pool), opts); }
221
267
  retentionLane() { return new PgRetentionLaneStore(this.pool); }
222
268
  breaker(onWriteFail) { return new PgBreakerState(this.pool, onWriteFail); }
223
269
  costQuota(limitMicroUsd, windowMs, onDegraded) { return new PgCostQuota(this.pool, limitMicroUsd, windowMs, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
224
270
  rateLimiter(limit, onDegraded) { return new PgRateLimiter(this.pool, limit, undefined, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
225
- session() { return new PgSessionStore(this.pool, { retention: sqlStoreRetention(this.config.retentionSweep) }); }
271
+ session() { return new SqlSessionStore(pgDriver(this.pool), (hooks) => new PgSessionStore(this.pool, { retention: sqlStoreRetention(this.config.retentionSweep), hooks })); }
226
272
  adoptionLog() { return new PgAdoptionLogStore(this.pool); }
227
273
  mysqlPool() { return undefined; }
228
274
  pgPool() { return this.pool; }
@@ -250,26 +296,16 @@ class LocalBackend {
250
296
  discloseWarn;
251
297
  parkDecisionLedgerRoot;
252
298
  executionLanes;
253
- constructor(root, config, onWarn, onError) {
299
+ dataDirLayout;
300
+ constructor(fileBackend, config, discloseWarn, onWarn, onError) {
254
301
  this.executionLanes = deployedExecutionLanes(config);
255
302
  this.onWarn = onWarn;
256
- this.discloseWarn = onWarn ?? ((msg, meta) => console.warn(msg, meta));
303
+ this.discloseWarn = discloseWarn;
257
304
  this.onError = onError;
258
- try {
259
- this.fileBackend = acquireLocalBackendWithWait(() => new FileStorageBackend({
260
- root,
261
- ...(config.fileHistory !== undefined ? { fileHistory: config.fileHistory } : {}),
262
- onCorruptRead: createDurableAbsenceSeat((msg, fields) => this.discloseWarn(msg, fields), root, "file-history = a rewind boundary or scope read as missing"),
263
- }), config.storeLockWaitMs, (fields) => this.onWarn?.("store_dir_lock_wait", { ...fields }));
264
- }
265
- catch (e) {
266
- if (e instanceof AdoptionError)
267
- throw e;
268
- const tail = buildStoreOpenRefusalTail(e, "http");
269
- throw new Error(`DB_BACKEND=local cannot open data dir ${root}: ${e instanceof Error ? e.message : String(e)}` +
270
- (tail === undefined ? "" : ` ${tail}`));
271
- }
305
+ this.fileBackend = fileBackend;
306
+ const root = localBackendRootOf(config);
272
307
  const corruptReadWarn = (msg, fields) => this.discloseWarn(msg, fields);
308
+ this.dataDirLayout = buildDataDirLayout({ configuredRoot: root, physicalRoot: this.fileBackend.root, memoryEngineRoot: memoryEngineRootFor(config, root) });
273
309
  this.runStore = new FileRunStore(this.fileBackend.root, {
274
310
  error: (msg, fields) => void (this.onError ?? this.onWarn)?.(msg, fields),
275
311
  strictHydrate: config.runStoreStrictHydrate,
@@ -297,22 +333,32 @@ class LocalBackend {
297
333
  : (plane) => fileSessionCaptureRecordStore(plane?.controlDir ?? ownControlDir);
298
334
  }
299
335
  async ensureSchema() {
336
+ this.executionLaneWordsRenamed += await this.sessionStore.renameRetiredExecutionLaneWordM40();
300
337
  await this.sessionStore.assertStrictSidecarsReadable();
301
338
  await this.sessionStore.settleArchiveSnapshots();
302
339
  }
340
+ executionLaneWordsRenamed = 0;
303
341
  async runOneTimeMigrations() {
342
+ tightenLocalDataDirModes(this.dataDirLayout, {
343
+ tightened: (msg, meta) => this.onWarn?.(msg, meta),
344
+ refused: (msg, meta) => this.discloseWarn(msg, meta),
345
+ });
304
346
  const archives = await this.sessionStore.migrateLocalArchives();
305
347
  const placements = await backfillLocalExecutionPlacements(this.runStore.sessionIdsWithRuns(), this.sessionStore.executionPlacementBackfill, { lanes: this.executionLanes });
306
- const importedLayerRoot = { importedLayerRootAllowsRetired: [], importedLayerRootBucketsSkipped: [] };
348
+ const importedLayerRoot = { importedLayerRootAllowsRetired: [], importedLayerRootBucketsSkipped: [], importedLayerRootBucketsUnnamed: 0 };
307
349
  if (existsSync(join(this.fileBackend.root, FILE_PERMISSION_RULE_DIR))) {
308
350
  const rules = this.permissionRule();
309
351
  await retireImportedLayerRootAllows({ candidateOwners: () => fileRuleBucketOwners(rules), durable: rules.durable, isWholeBucketRefusal: isFileBucketDamaged, isVanishedBucket: () => false }, importedLayerRoot);
310
352
  }
353
+ const executionLaneWordsRenamed = this.executionLaneWordsRenamed + this.approvalAskStore.renameRetiredExecutionLaneWordM40();
354
+ this.executionLaneWordsRenamed = 0;
355
+ const askExecutionLanesBackfilled = backfillLocalAskExecutionLanes(this.approvalAskStore, { lanes: this.executionLanes });
311
356
  return {
312
357
  ...NO_SQL_MIGRATIONS,
313
358
  executionPlacementsBackfilled: placements.backfilled,
314
359
  executionPlacementSessionsUnreadable: placements.unreadable,
315
- askExecutionLanesBackfilled: backfillLocalAskExecutionLanes(this.approvalAskStore, { lanes: this.executionLanes }),
360
+ askExecutionLanesBackfilled,
361
+ executionLaneWordsRenamed,
316
362
  askJournalRecordsUpgraded: this.approvalAskStore.upgradeJournalEnvelope(),
317
363
  localArchiveRowFactsBackfilled: archives.rowFactsBackfilled,
318
364
  localArchivesAnonymized: archives.anonymized,
@@ -396,9 +442,75 @@ class LocalBackend {
396
442
  export function counterStoreLabel(store, kind) {
397
443
  return store ? `shared(${kind ?? "unknown"})` : "in-process";
398
444
  }
445
+ function openLocalBackend(config, onWarn, onError) {
446
+ const root = localBackendRootOf(config);
447
+ const discloseWarn = onWarn ?? ((msg, meta) => console.warn(msg, meta));
448
+ let fileBackend;
449
+ try {
450
+ fileBackend = acquireLocalBackendWithWait(() => new FileStorageBackend({
451
+ root,
452
+ ...(config.fileHistory !== undefined ? { fileHistory: config.fileHistory } : {}),
453
+ onCorruptRead: createDurableAbsenceSeat(discloseWarn, root, "file-history = a rewind boundary or scope read as missing"),
454
+ }), config.storeLockWaitMs, (fields) => onWarn?.("store_dir_lock_wait", { ...fields }));
455
+ }
456
+ catch (e) {
457
+ if (e instanceof AdoptionError)
458
+ throw e;
459
+ const tail = buildStoreOpenRefusalTail(e, "http");
460
+ throw new Error(`DB_BACKEND=local cannot open data dir ${root}: ${e instanceof Error ? e.message : String(e)}` +
461
+ (tail === undefined ? "" : ` ${tail}`));
462
+ }
463
+ try {
464
+ holdEngineHighWater(fileBackend.root, serviceVersion());
465
+ }
466
+ catch (refusal) {
467
+ return new RefusedLocalBackend(fileBackend, refusal instanceof Error ? refusal : new Error(String(refusal)));
468
+ }
469
+ return new LocalBackend(fileBackend, config, discloseWarn, onWarn, onError);
470
+ }
471
+ class RefusedLocalBackend {
472
+ fileBackend;
473
+ refusal;
474
+ kind = "local";
475
+ constructor(fileBackend, refusal) {
476
+ this.fileBackend = fileBackend;
477
+ this.refusal = refusal;
478
+ }
479
+ refused() {
480
+ throw this.refusal;
481
+ }
482
+ async ensureSchema() {
483
+ return this.refused();
484
+ }
485
+ async runOneTimeMigrations() {
486
+ return this.refused();
487
+ }
488
+ async close() {
489
+ await this.fileBackend.dispose();
490
+ }
491
+ run() { return this.refused(); }
492
+ resumeAnchor() { return this.refused(); }
493
+ approvalExemption() { return this.refused(); }
494
+ approvalNonce() { return this.refused(); }
495
+ orgDeliveryQuota() { return this.refused(); }
496
+ approvalAsk() { return this.refused(); }
497
+ permissionRule() { return this.refused(); }
498
+ sendFileLedger() { return this.refused(); }
499
+ userInputLedger() { return this.refused(); }
500
+ sessionPolicy() { return this.refused(); }
501
+ fileHistory() { return this.refused(); }
502
+ memoryOptOutGrant() { return this.refused(); }
503
+ sessionCaptureRecords() { return this.refused(); }
504
+ workflowJournal() { return this.refused(); }
505
+ outcomeSink() { return this.refused(); }
506
+ checkpointReadView() { return this.refused(); }
507
+ session() { return this.refused(); }
508
+ mysqlPool() { return undefined; }
509
+ pgPool() { return undefined; }
510
+ }
399
511
  export function createStoreBackend(config, onWarn, onError) {
400
512
  if (config.dbBackend === "local")
401
- return new LocalBackend(config.localDataRoot ?? join(homedir(), ".ai-agent"), config, onWarn, onError);
513
+ return openLocalBackend(config, onWarn, onError);
402
514
  if (config.dbBackend === "pg") {
403
515
  if (!config.pg)
404
516
  return undefined;
@@ -419,9 +531,21 @@ function withRetiredSchemaProbe(inner, target, executionPlacementSwitch) {
419
531
  };
420
532
  return guarded;
421
533
  }
534
+ function localBackendRootOf(config) {
535
+ return config.localDataRoot ?? join(homedir(), ".ai-agent");
536
+ }
537
+ function localDataRootHoldsData(root) {
538
+ try {
539
+ return readdirSync(root).length > 0;
540
+ }
541
+ catch (e) {
542
+ const code = e.code;
543
+ return code !== "ENOENT" && code !== "ENOTDIR";
544
+ }
545
+ }
422
546
  export async function openStoreBackendWithFallback(config, logger) {
423
547
  const sqlEngine = config.dbBackend === "mysql" || config.dbBackend === "pg" ? config.dbBackend : undefined;
424
- const mayFallback = config.dbBackend === "local" && !config.dbBackendExplicit;
548
+ const mayFallback = config.dbBackend === "local" && !config.dbBackendExplicit && !localDataRootHoldsData(localBackendRootOf(config));
425
549
  let backend;
426
550
  let inFlight;
427
551
  try {
@@ -448,8 +572,6 @@ export async function openStoreBackendWithFallback(config, logger) {
448
572
  }
449
573
  catch (err) {
450
574
  void inFlight?.close().catch(() => undefined);
451
- if (err instanceof AdoptionError)
452
- throw err;
453
575
  if (err instanceof StoreBootRefusalError)
454
576
  throw err;
455
577
  if (!mayFallback) {