@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
@@ -1,5 +1,7 @@
1
1
  import { closeSync, copyFileSync, openSync, readSync, statSync, existsSync } from "node:fs";
2
2
  import { isExecutionLane } from "../execution-lane-caps.js";
3
+ import { RENAMED_EXECUTION_LANE_M40, RETIRED_EXECUTION_LANE_WORD_M40 } from "./execution-lane-rename-m40.js";
4
+ import { ExecutionLaneRenameWriteRefusedError } from "./one-time-migrations.js";
3
5
  import { join } from "node:path";
4
6
  import { AppendLog, atomicWriteFile, ensureDir } from "@sema-agent/core";
5
7
  import { replayJsonlSkipping } from "../observability/corrupt-read-seat.js";
@@ -112,12 +114,20 @@ export class FileApprovalAskStore {
112
114
  this.records = records.length;
113
115
  if (tornTail || this.corruptLineCount > 0) {
114
116
  const quarantine = `${this.path}.corrupt-${Date.now()}`;
115
- copyFileSync(this.path, quarantine);
117
+ try {
118
+ copyFileSync(this.path, quarantine);
119
+ this.compact();
120
+ }
121
+ catch (e) {
122
+ throw new StoreBootRefusalError(`FileApprovalAskStore: approval ask journal ${this.path} has ${tornTail ? "a torn tail" : "no torn tail"} and ${this.corruptLineCount} unparseable line(s) ` +
123
+ `and its recovery rewrite could not land on disk (${e?.code ?? (e instanceof Error ? e.message : String(e))}) — the journal is unchanged. ` +
124
+ "Refusing to start rather than run without the approvals it holds: restore write access to the journal, its directory and that directory's .tmp " +
125
+ "(clear an immutable flag, remount read-write, free disk space), then restart.", { cause: e });
126
+ }
116
127
  this.corruptQuarantinePath = quarantine;
117
128
  console.warn(`FileApprovalAskStore: approval ask journal ${this.path} had ${tornTail ? "a torn tail" : "no torn tail"} and ` +
118
129
  `${this.corruptLineCount} unparseable line(s) — replayed every COMPLETE record, quarantined the original at ${quarantine}, ` +
119
130
  `and rewrote the live journal from the replayed state. A dropped record is a LOST approval-ask transition: inspect the quarantined file.`);
120
- this.compact();
121
131
  }
122
132
  else if (this.removalRecordsOnDisk) {
123
133
  this.compactOrRecord();
@@ -370,15 +380,38 @@ export class FileApprovalAskStore {
370
380
  return upgraded;
371
381
  }
372
382
  backfillExecutionLanes(lanes, refuse) {
373
- const pending = this.core.exportRows().asks.filter((r) => !isExecutionLane(String(r.executionLane ?? ""))).length;
383
+ const asks = this.core.exportRows().asks;
384
+ const unknown = [];
385
+ let pending = 0;
386
+ for (const r of asks) {
387
+ const recorded = r.executionLane;
388
+ if (recorded === undefined)
389
+ pending += 1;
390
+ else if (typeof recorded !== "string" || !isExecutionLane(recorded))
391
+ unknown.push({ askId: r.askId, word: String(recorded) });
392
+ }
393
+ if (unknown.length > 0)
394
+ refuse({ kind: "unknown_lane", asks: unknown });
374
395
  if (pending === 0)
375
396
  return 0;
376
397
  if (lanes.length !== 1)
377
- refuse(pending);
398
+ refuse({ kind: "backfill_ambiguous", pending });
378
399
  const filled = this.core.fillMissingExecutionLanes(lanes[0]);
379
400
  this.compact();
380
401
  return filled;
381
402
  }
403
+ renameRetiredExecutionLaneWordM40() {
404
+ const renamed = this.core.renameExecutionLaneWord(RETIRED_EXECUTION_LANE_WORD_M40, RENAMED_EXECUTION_LANE_M40);
405
+ if (renamed === 0)
406
+ return 0;
407
+ try {
408
+ this.compact();
409
+ }
410
+ catch (e) {
411
+ throw new ExecutionLaneRenameWriteRefusedError(this.path, e);
412
+ }
413
+ return renamed;
414
+ }
382
415
  dispose() {
383
416
  this.log?.close();
384
417
  this.log = undefined;
@@ -30,7 +30,7 @@
30
30
  * - resolveProvisional 故意不经 canAskTransition(同 SQL twin 头注:这是版本化补偿的例外通道)。
31
31
  */
32
32
  import { type AskState, type BatchState } from "../approval-ask-machine.js";
33
- import { type ExecutionLane } from "../execution-lane-caps.js";
33
+ import type { ExecutionLane } from "../execution-lane-caps.js";
34
34
  import type { AskCallCoordinate, AskDecision, AskRow, AskTerminalClaimIntent, AskTerminalClaimOpts, AskTerminalClaimOutcome, AskTransitionPatch, ApprovalAskStore, BatchRow, BindGateInput, BindResult, DecideAskInput, EnsureAskResult, DecideResult, ExpireResult, NewAskRow } from "./approval-ask-store-sql.js";
35
35
  /**
36
36
  * [ref] 的 `updatedInput` **入店编码**——两 twin 共用的那一只(本函数是唯一真源)。
@@ -75,10 +75,12 @@ export declare class InMemoryApprovalAskStore implements ApprovalAskStore {
75
75
  */
76
76
  exportRows(): ApprovalAskRowsSnapshot;
77
77
  /**
78
- * 执行放置切换 ④b 的 local 腿(File 形的内核口;`FileApprovalAskStore.backfillExecutionLanes` 调):出处车道还没记下的行(升级前写下的日志 / 快照行
79
- * 装回后这一格缺席)记成 `lane`(一元车道表的唯一项 —— 调用方判过)。返回改了的行数;只碰缺这一格的行。
78
+ * 执行放置切换 ④b 的 local 腿(File 形的内核口;`FileApprovalAskStore.backfillExecutionLanes` 调):出处车道**缺席**的行(升级前写下的日志 / 快照行
79
+ * 装回后这一格不在)记成 `lane`(一元车道表的唯一项 —— 调用方判过)。返回改了的行数;只碰这一格缺席的行 —— 记下了而不是车道词的行不在这里改(调用方先拒)。
80
80
  */
81
81
  fillMissingExecutionLanes(lane: ExecutionLane): number;
82
+ /** 一次性迁移 M40 的 local 问账腿(File 形的内核口;`FileApprovalAskStore.renameRetiredExecutionLaneWordM40` 调):出处车道记成 `from` 的行改记 `to`。返回改了的行数。 */
83
+ renameExecutionLaneWord(from: string, to: ExecutionLane): number;
82
84
  /** [ref]:一行的**同步**点读(拷贝;纯读,零判定)—— File 形在写口的同步前缀里用它(见类顶注)。 */
83
85
  peekAsk(askId: string): AskRow | null;
84
86
  /** [ref]:把快照里的行**原样**装回两张 Map(同键覆盖)。零谓词、零状态机 —— 它不是一条转移,是重放
@@ -1,5 +1,4 @@
1
1
  import { ASK_TERMINAL, canAskTransition } from "../approval-ask-machine.js";
2
- import { isExecutionLane } from "../execution-lane-caps.js";
3
2
  import { APPROVAL_ENDING_CAUSES } from "../approval-deny-reasons.js";
4
3
  import { askRowCarriesOwner, askRowOnCall, assertDecideSource, assertIdempotencyKeyShape, assertIntegralEpochMs, assertReapBounds, ApprovalAskReadAbortedError, claimTargetState, POLICY_REFUSAL_DECISION, projectAskTerminalClaimTruth, projectDecideReading } from "./approval-ask-store-sql.js";
5
4
  function applyPatch(row, patch) {
@@ -45,13 +44,23 @@ export class InMemoryApprovalAskStore {
45
44
  fillMissingExecutionLanes(lane) {
46
45
  let filled = 0;
47
46
  for (const [askId, row] of this.asks) {
48
- if (isExecutionLane(String(row.executionLane ?? "")))
47
+ if (row.executionLane !== undefined)
49
48
  continue;
50
49
  this.asks.set(askId, { ...row, executionLane: lane });
51
50
  filled += 1;
52
51
  }
53
52
  return filled;
54
53
  }
54
+ renameExecutionLaneWord(from, to) {
55
+ let renamed = 0;
56
+ for (const [askId, row] of this.asks) {
57
+ if (row.executionLane !== from)
58
+ continue;
59
+ this.asks.set(askId, { ...row, executionLane: to });
60
+ renamed += 1;
61
+ }
62
+ return renamed;
63
+ }
55
64
  peekAsk(askId) {
56
65
  const row = this.asks.get(askId);
57
66
  return row ? { ...row } : null;
@@ -406,6 +406,9 @@ export type AskTerminalClaimCurrent = {
406
406
  settledBy: HostSettledBy | null;
407
407
  /** core 7.61.0([ref]):赢家决议的机器座位(语义见 {@link AskRow.decidedVia});必填,理由与 `settledBy` 同。 */
408
408
  decidedVia: DecidedVia | null;
409
+ /** 赢家决议的人写说明(`decision_note` 列,与决议同一条 UPDATE 落;`null` = 没说明);**必填**(可空),理由与 `settledBy` 同:可选会让投影漏挑这一列时静默编译过,
410
+ * 而漏挑的后果恰是 CAS 输家把赢家带说明的拒读成「一个人拒了、没说怎么办」(读回铸点 `outcomeOfDecidedRow` 把拒行上的非空说明铸成交给模型的 `reason`)。 */
411
+ decisionNote: string | null;
409
412
  /** 行上记着的终态成因(`ending_cause` 列,经唯一读口 `askRowEndingCause` 读出)。**只在读得出时在场**(没写 / 与 state 不配 ⇒ 缺席;DECIDED 的败方读数逐字不变)。
410
413
  * CAS 输家据它按**行上那个成因**结算(而不是把别人撤的卡读成一次拒绝);投影的唯一函数是 {@link projectAskTerminalClaimTruth},三 twin 不各自挑列,原始列值不出店层。 */
411
414
  endingCause?: AskRowEndingCause;
@@ -7,6 +7,7 @@ import { describeProbedTableDrift } from "./schema-drift-sentence.js";
7
7
  import { decodeJsonColumn, foldJsonColumn, jsonColumnText, readJsonObjectColumn, readTriStateJsonValueColumn } from "./sql-json-column.js";
8
8
  import { ensureIndexes } from "./ensure-index.js";
9
9
  import { isExecutionLane } from "../execution-lane-caps.js";
10
+ import { retiredExecutionLaneHintM40 } from "./execution-lane-rename-m40.js";
10
11
  export function assertIntegralEpochMs(field, value) {
11
12
  if (!Number.isSafeInteger(value)) {
12
13
  throw new TypeError(`approval-ask store: ${field} must be an integer epoch-ms (BIGINT column), got ${String(value)}`);
@@ -110,6 +111,7 @@ export function projectAskTerminalClaimTruth(row) {
110
111
  ...(row.updatedInput !== undefined ? { updatedInput: row.updatedInput } : {}),
111
112
  settledBy: row.settledBy,
112
113
  decidedVia: row.decidedVia,
114
+ decisionNote: row.decisionNote,
113
115
  ...(endingCause !== undefined ? { endingCause } : {}),
114
116
  ...(parkTrigger !== undefined ? { parkTrigger } : {}),
115
117
  };
@@ -144,7 +146,7 @@ export const APPROVAL_ASK_PARK_TRIGGER_COLUMN = {
144
146
  function executionLaneColumnOf(raw, askId) {
145
147
  const lane = typeof raw === "string" ? raw : "";
146
148
  if (!isExecutionLane(lane)) {
147
- throw new Error(`approval-ask-store: ask ${askId} carries execution_lane ${JSON.stringify(lane)}, which is not an execution lane — the execution placement switch migration backfills every row; refusing rather than guess the lane this ask was raised on`);
149
+ throw new Error(`approval-ask-store: ask ${askId} carries execution_lane ${JSON.stringify(lane)}, which is not an execution lane — the execution placement switch migration backfills every row; refusing rather than guess the lane this ask was raised on${retiredExecutionLaneHintM40(lane)}`);
148
150
  }
149
151
  return lane;
150
152
  }
@@ -1,153 +1,31 @@
1
- import type { Pool as MysqlPool } from "mysql2/promise";
2
- import type { Pool as PgPool } from "pg";
3
- import { type SqlEngineFacts, type SqlEngineReading, type SqlWallSource, type SqlWallsReading, type SqlDialect } from "./sql-driver.js";
4
- import { type Logger } from "../observability/logger.js";
5
1
  /**
6
- * 文本协议的 blob 膨胀律 —— mysql2 `query()` 把 Buffer 参数写成 `X'<hex>'`,一字节两个字符,所以承载一个 blob 的语句至少是它的 2 倍。
7
- * 包墙折成「能装下多大的 blob」只用这一只常量,推导里不手写 `/ 2`。
8
- */
9
- export declare const SQL_TEXT_PROTOCOL_BLOB_INFLATION = 2;
10
- /**
11
- * 包墙下能装多大的 blob:语句里的载荷量({@link packetWallStatementBytes})再按 {@link SQL_TEXT_PROTOCOL_BLOB_INFLATION} 折半。
12
- * blob 以十六进制字面进语句、有 2× —— 膨胀律是 blob 腿自己的,余量不是。
13
- */
14
- export declare function packetWallBlobCap(maxPacketBytes: number): number;
15
- /**
16
- * SQL 快照 blob 的**缺省**帽(运维没设 `SNAPSHOT_BLOB_SQL_MAX_BYTES` 时)的唯一推导 —— 入参是判官 `sqlWallsOf` 给的墙(不读事实、不判缺席、不看方言),**两堵墙取最小**:
17
- * 行墙腿(`SqlEngineFacts.maxRowBytes`,TiDB:{@link rowWallPayloadBytes} 的 `blob` = 行墙 − blob 行的余量 1 KiB —— 按这一行的真实形算,不借 JSON 提交体行的 64 KiB)
18
- * 与包墙腿(`SqlEngineFacts.maxPacketBytes`,InnoDB 与 TiDB 都有:{@link packetWallBlobCap} = ⌊(包墙 − 1 KiB 语句余量) ÷ 2⌋)。余量只在 `sql-driver.ts` 定义一次
19
- * (墙 × 行的形各一只),提交体受理口(`http/request-guards.ts` `refuseSubmitBody`)读同一张表的 `json` 那一只,不各抄。
20
- * 墙的 `null` 只表示「这堵墙不存在」;两堵都不存在(PG —— 扩展协议无这两堵墙 —— 或没有 SQL 后端)⇒ `undefined` 不设帽。
21
- * 「事实本身缺席」不是这里的入参:店的写前判读的是借出连接自己的事实(恒已建立,见 {@link SqlConnectionReading}),缺席的读法只在提交受理口读池级读口时出现(判官 `sqlWallsOf` 给墙)。
22
- * 显式旋钮是运维的策略帽,在本推导之上(见 {@link sqlBlobCapBytes})。
23
- *
24
- * 两堵墙的真库读数(clay 拍 a+c,2026-07-27;k3s8 tidb-test v7.5.1 默认配置探针):7 MiB / 31 MiB = `entry too large`(行墙,默认 6291456)、
25
- * 32 MiB = `max_allowed_packet`(包墙,64 MiB ÷ ~2× 文本协议膨胀)。帽=诚实拒绝:超限 blob 在 query 之前 typed 拒(消费面 HTTP 413 / capture warn
26
- * 拿到可行动信息);帽与墙之间只差这一行自己的几百字节(blob 行余量),帽之下的 blob 在缺省配置下落得进。D-1 附件战役同墙教训:`task-attachment-store.ts` 头注。
27
- */
28
- export declare function sqlBlobDefaultCapBytes(walls: SqlWallsReading): number | undefined;
29
- /**
30
- * 一个 SQL 快照 blob 的帽 + 它**从哪来**。`operator` = 运维显式设的 `SNAPSHOT_BLOB_SQL_MAX_BYTES`(策略帽);`reported` / `assumed` = 缺省推导里**定下这个帽的那条腿**的墙数字出处
31
- * ({@link SqlWallSource}:库自己报的 / 读失败或事实缺席而退的文档缺省)。机读位同 413 拒体的 `wallSource` 词,旋钮形多一个 `operator`。
32
- */
33
- export interface SqlBlobCapReading {
34
- readonly capBytes: number;
35
- readonly source: "operator" | SqlWallSource;
36
- }
37
- /**
38
- * 缺省帽的推导(唯一一处,{@link sqlBlobDefaultCapBytes} 是它的字节投影):两条腿各带自己那堵墙的出处,取最小的那条;两条一样小取行墙腿。两堵墙都不存在 ⇒ `undefined`。
39
- */
40
- export declare function sqlBlobDefaultCapOf(walls: SqlWallsReading): SqlBlobCapReading | undefined;
41
- /**
42
- * 一条**借出连接**的引擎读口:方言(装配事实)+ 它自己那次初始化回读的事实。与 {@link SqlEngineReading} 的差别只有一处 —— `facts` 恒在:连接是借出时才有的,
43
- * 借出即已初始化({@link connectJudged} 交给判决的就是借出连接的 `sqlConnectionFacts`),所以「事实缺席」在这条读法上**不可表示**(编译期拒,不是运行期一个没人走的分支)。
44
- * 事实缺席(池上还没建立过、或最近一次初始化被拒)只出现在读**池级**读口的地方 —— 提交受理口 —— 那一格的墙由判官 `sqlWallsOf` 给,不经过帽的推导。
45
- */
46
- export interface SqlConnectionReading {
47
- readonly dialect: SqlEngineReading["dialect"];
48
- readonly facts: SqlEngineFacts;
49
- }
50
- /**
51
- * 一个 SQL 快照 blob 此刻的帽 —— **显式旋钮 ?? 判官给的墙走缺省推导**的唯一一只函数。唯一读者 = 店的写前判({@link SqlBlobBackend.putBlob}),传的读口({@link SqlConnectionReading})是
52
- * **将要执行写入的那条连接**的(方言 + 它自己那次初始化回读的事实,墙经与提交受理口同一只判官 `sqlWallsOf`):包墙是连接的会话值,所以判决只在写入的那条连接上做,
53
- * HTTP 面不替店另算一份帽。
54
- */
55
- export declare function sqlBlobCapOf(explicitCapBytes: number | undefined, connection: SqlConnectionReading): SqlBlobCapReading | undefined;
56
- /** {@link sqlBlobCapOf} 的字节投影(同一个推导,不另读)。 */
57
- export declare function sqlBlobCapBytes(explicitCapBytes: number | undefined, connection: SqlConnectionReading): number | undefined;
58
- /**
59
- * 这一拒是不是**那条连接的包墙**定的:帽是缺省推导出的(不是运维旋钮)、那条连接有包墙、且包墙腿的折算恰是这个帽(包墙腿是最矮的一腿,或与行墙腿并列)。
60
- * 只有这种拒才值得问「这条连接过时了吗」({@link connectJudged}) —— 旋钮的拒、行墙的拒与连接新旧无关。`walls` = 判出这个帽的那一份墙({@link sqlWallsOf})。
61
- */
62
- export declare function capBoundByPacketWall(cap: SqlBlobCapReading, walls: SqlWallsReading): boolean;
63
- /**
64
- * 一次 blob 超帽的拒句 —— **唯一的组句器**(店的 typed {@link BlobTooLargeError} 调它;`PUT /sync/blobs` 的 413 原样转出它的句子):句子按帽的出处({@link SqlBlobCapReading.source})
65
- * 分三形,不把假定说成库的上限、也不把运维的旋钮说成库的上限。
66
- * · `operator` —— 帽是运维设的 `SNAPSHOT_BLOB_SQL_MAX_BYTES`;
67
- * · `reported` —— 帽由库报的两堵墙推出(单行上限与包墙÷文本协议膨胀的较小者);
68
- * · `assumed` —— 库的上限没读到(事实还没建立,或这一堵读失败),帽按受支持引擎里最保守的缺省墙推出,稍后重试或由运维设旋钮。
69
- */
70
- export declare function sqlBlobCapRefusalText(byteLen: number, cap: SqlBlobCapReading): string;
71
- /** typed 判别错:blob 超过 SQL 店的承载帽。判别码供店侧结果映射/HTTP 面/日志使用——绝不能与
72
- * transient 写失败混在一类(那类是可重试的 502;这类重试永远不会成功)。句子是 {@link sqlBlobCapRefusalText}(带帽的出处)。 */
73
- export declare class BlobTooLargeError extends Error {
74
- readonly cap: SqlBlobCapReading;
75
- readonly code: "blob_too_large_for_sql";
76
- constructor(byteLen: number, cap: SqlBlobCapReading);
77
- }
78
- /**
79
- * The content-addressed byte store. All four methods are keyed on the sha256 `hash` of the bytes:
80
- * - putBlob: store bytes (idempotent — a repeat for the same hash is a no-op-equivalent; the SQL twin refreshes
81
- * created_at so a just-written/re-used blob is GC-grace-protected). MinIO PUTs the object AND upserts the SQL INDEX.
82
- * - getBlob: the bytes for `hash`, or undefined if absent. A TRANSIENT backend fault THROWS (so a restore/import fails
83
- * LOUD, not a silent "missing blob"); only a genuine absence / corruption is undefined.
84
- * - hasBlobs: the subset of `hashes` that already exist — a single SQL `IN(...)` over the index for BOTH backends
85
- * (migration idempotency + reap probing + the §10 import presence pre-check; cheaper than a HEAD-per-hash on MinIO).
86
- * - deleteBlobs: byte-delete the given hashes (called ONLY by the async sweep reaper). Honors the SAME created_at
87
- * grace window as the SQL backend (MinIO reads the index's created_at) — delete-in-use is impossible. Returns the
88
- * count ACTUALLY deleted (the grace-passed subset), so the sweep reports real work, not the pre-grace orphan count.
2
+ * The byte port. Keys are opaque to it (today every index owner keys a blob by its sha256 hash).
3
+ * - `put`: store `bytes` under `key`. Idempotent (a repeat for the same key overwrites with the identical bytes); a rejection is a
4
+ * failed write.
5
+ * - `get`: the bytes under `key`, or `undefined` when nothing is there. A TRANSIENT fault THROWS (so a restore / import fails LOUD,
6
+ * not as a silent "missing blob"). The index owner checks the bytes against the hash ({@link readAtAddress}).
7
+ * - `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).
89
9
  */
90
10
  export interface BlobBackend {
91
- putBlob(hash: string, bytes: Uint8Array): Promise<void>;
92
- getBlob(hash: string): Promise<Uint8Array | undefined>;
93
- hasBlobs(hashes: string[]): Promise<Set<string>>;
94
- deleteBlobs(hashes: string[]): Promise<number>;
11
+ put(key: string, bytes: Uint8Array): Promise<void>;
12
+ get(key: string): Promise<Uint8Array | undefined>;
13
+ delete(keys: readonly string[]): Promise<void>;
95
14
  }
96
15
  /**
97
- * SQL BlobBackend — the `snapshot_blob` table ops EXTRACTED VERBATIM from the tidb/pg file-snapshot stores (the
98
- * created_at-refreshing upsert, the bytes SELECT, the grace-window orphan DELETE→deleteBlobs, a has via SELECT). Two
99
- * dialect twins selected by `dialect`. Keeping the SQL byte-identical means the existing behaviour + the env-gated
100
- * real-DB integration suite are unchanged when MinIO is unset (the DEFAULT backend the file-snapshot stores construct).
101
- *
102
- * NOTE deleteBlobs here is the BYTE delete ONLY — it does NOT do the reference (`not in the manifest`) filter: that
103
- * check stays in the owning store, which computes the orphan hash SET from its own domain's manifest and hands it here. The grace-window `created_at < cutoff` guard is RETAINED on the delete so a just-written blob
104
- * that a concurrent in-flight snapshot still needs is never byte-deleted (delete-in-use is data loss; under-delete is
105
- * harmless — the next sweep collects it).
16
+ * A content-addressed read through a port — the index owner's ONE reading of `get`: the bytes under `hash`, or `undefined` when the
17
+ * port has none OR when the bytes it serves do not hash to `hash` (corruption on the wire, or a POISONED object written under a hash
18
+ * it does not match): fail-closed, never wrong bytes. A content-addressed store's whole safety rests on bytes-match-hash; this is
19
+ * where both index owners judge it (the file-history blob index, the attachment store).
106
20
  */
107
- export declare class SqlBlobBackend implements BlobBackend {
108
- private readonly dialect;
109
- private readonly pool;
110
- /** Explicit per-blob cap (the operator's `SNAPSHOT_BLOB_SQL_MAX_BYTES`); absent ⇒ the derivation in {@link sqlBlobCapOf} over the walls of the connection each write borrows. */
111
- private readonly explicitCapBytes;
112
- /** Blob-domain table ([ref] blob 域隔离:file-history 域用自己的表,reap/GC 不跨域)。代码内字面量,非用户输入。 */
113
- private readonly table;
114
- /** The write path's connection source: every `putBlob` borrows ONE connection from it (through {@link connectJudged}), judges on that connection's walls, writes on it. */
115
- private readonly db;
116
- /** Where a stale connection's replacement is logged ({@link connectJudged}); the boot assembly passes the service logger. */
117
- private readonly log;
118
- constructor(dialect: SqlDialect, pool: MysqlPool | PgPool, maxBytes?: number, table?: string, log?: Pick<Logger, "warn">);
119
- /** The created_at-refreshing content-addressed upsert — VERBATIM the tidb/pg stores' `putBlobRow`. Refreshes
120
- * created_at even on a dedup hit so a re-used/just-written blob is "touched=now" and GC-grace-protected.
121
- * (a): an over-cap blob is REJECTED (typed {@link BlobTooLargeError}) BEFORE the driver ever sees the bytes —
122
- * the alternative is an inscrutable packet-limit error deep in the driver, and on the HTTP face a 502 that
123
- * invites the peer to retry a blob that can never land.
124
- * 🔴 The cap is judged ON THE CONNECTION THAT WRITES ([ref]): `max_allowed_packet` is a session value, fixed per
125
- * connection, so the write borrows one connection through {@link connectJudged}, which reads ITS walls, judges, and — when
126
- * the refusal is that connection's packet wall and the server's global wall is higher — replaces the stale connection and
127
- * judges once more; the INSERT runs on the connection that passed. Never a pool-level reading, never a bare `pool.query`. */
128
- putBlob(hash: string, bytes: Uint8Array): Promise<void>;
129
- /** The bytes for `hash` (undefined if absent) — VERBATIM the tidb/pg stores' getBlob SELECT. A pool/query error
130
- * PROPAGATES (a transient DB fault is loud, not a silent "missing blob" — parity with the MinIO backend's throw). */
131
- getBlob(hash: string): Promise<Uint8Array | undefined>;
132
- /** The subset of `hashes` that exist — a single `blob_hash IN (...)` SELECT (idempotency / reap probe). */
133
- hasBlobs(hashes: string[]): Promise<Set<string>>;
134
- /** Byte-delete the given hashes (the orphan SET is computed by the CALLER from its own domain's manifest). Retains
135
- * the grace-window guard so a just-written blob a concurrent in-flight write needs is never delete-in-use — VERBATIM
136
- * the tidb/pg stores' gcOrphanBlobs delete, minus the reference clause (the caller already excluded referenced
137
- * hashes). Best-effort: a delete error is swallowed (under-delete is harmless). */
138
- deleteBlobs(hashes: string[]): Promise<number>;
139
- }
140
- /** SHARED index op(workspace 浏览面 #3,[ref]②)—— per-blob 字节数,读 SQL INDEX 的 `byte_len`
141
- * 列(sqlHasBlobs 同款单 IN 查询;MinIO 后端的 bytes-NULL 索引行同样带 byte_len,两后端同源)。
142
- * tree/file 面的 size 投影与「超限先拒后拉」都靠它——绝不为拿大小去 getBlob 整块字节。 */
143
- export declare function sqlBlobSizes(dialect: SqlDialect, pool: MysqlPool | PgPool, hashes: string[]): Promise<Map<string, number>>;
21
+ export declare function readAtAddress(port: Pick<BlobBackend, "get">, hash: string): Promise<Uint8Array | undefined>;
144
22
  export interface MinioBlobBackendConfig {
145
23
  endpoint: string;
146
24
  bucket: string;
147
25
  accessKey: string;
148
26
  secretKey: string;
149
27
  region?: string;
150
- /** Key prefix for blob objects, e.g. "blobs/". Object key = keyPrefix + hash. Default "blobs/". */
28
+ /** Key prefix for blob objects, e.g. "blobs/". Object key = keyPrefix + key. Default "blobs/". */
151
29
  keyPrefix?: string;
152
30
  /** Presigned-URL TTL (seconds). Default 3600 (1h) — must comfortably exceed a ~64 MiB single-PUT/GET on a slow link
153
31
  * (a SigV4 X-Amz-Expires bounds the WHOLE transfer from X-Amz-Date; a too-short TTL fails mid-stream). */
@@ -155,22 +33,6 @@ export interface MinioBlobBackendConfig {
155
33
  /** 测试注入口(listObjects 分页钉用);生产缺省 global fetch。 */
156
34
  fetchImpl?: typeof fetch;
157
35
  }
158
- /**
159
- * MinIO BlobBackend — content-addressed bytes in an S3-compatible object store, via the zero-dependency
160
- * {@link presignS3Url} SigV4 generator + `fetch` (NO S3 SDK; the repo's no-SDK posture). The object key is
161
- * `keyPrefix + hash` (content-addressed → idempotent PUT, dedup across snapshots is automatic).
162
- *
163
- * THE SQL INDEX: the bytes go to MinIO, but a `snapshot_blob` INDEX row `(blob_hash, byte_len, created_at)` with bytes
164
- * NULL is kept in SQL (same pool/dialect). This is what makes the orphan-reference computation + the created_at grace
165
- * window + the §10 presence pre-check work identically to the SQL backend (see the file header). hasBlobs reads the
166
- * index; putBlob PUTs then upserts the index (created_at-refresh on conflict); deleteBlobs deletes the grace-passed
167
- * index rows AND the matching MinIO objects (called ONLY from the async sweep reaper).
168
- *
169
- * INTEGRITY (security-critical): getBlob VERIFIES sha256(bytes) === hash before returning. A content-addressed store's
170
- * whole safety rests on bytes-match-hash; a mismatch means corruption (network) or POISONING (a hostile object written
171
- * under a hash it doesn't match) — treated as ABSENT (undefined), NEVER returning wrong bytes. This mirrors the
172
- * importManifest content-address check the SQL stores already do.
173
- */
174
36
  /** 鲁棒性批2 C2/C3/C6(2026-08-03):S3 兼容端点 IO 的统一 abort 上界(fleet-client C1 定常量形
175
37
  * 先例)。半开端点此前各挂 undici 默认 ~300s headersTimeout——blob GET 卡住 restore/session-import
176
38
  * 同步路径,SendUserFile 工具调用永不返回。120s 对慢链路 ~64MiB 单 PUT/GET 仍宽裕(presignTtlSec
@@ -185,45 +47,34 @@ export type BucketProbe = {
185
47
  readonly state: "unknown";
186
48
  readonly detail: string;
187
49
  };
50
+ /**
51
+ * The object-storage port: bytes in an S3-compatible store under `keyPrefix + key` (content-addressed keys ⇒ an idempotent PUT and
52
+ * dedup across writers). Object I/O only — no SQL, no index, no grace window, no content-address check (those are the index
53
+ * owner's). Beyond the port's three members it carries the object store's own reads a deployment needs: `listObjects` / `headObject`
54
+ * (the attachment store's orphan-object sweep) and `probeBucket` (the boot-time bucket check).
55
+ */
188
56
  export declare class MinioBlobBackend implements BlobBackend {
189
57
  private readonly cfg;
190
58
  private readonly keyPrefix;
191
59
  private readonly ttl;
192
- /** The SQL index pool+dialect, or undefined for an index-LESS backend (the migration script + the unit suite, which
193
- * exercise ONLY the object I/O — put/get/has-by-HEAD/delete — with no DB). When undefined, hasBlobs falls back to a
194
- * HEAD-per-hash probe and deleteBlobs ignores the grace window (the script is a stop-the-world copy, not the live GC
195
- * path). The file-snapshot stores ALWAYS pass the pool, so the live reference-tracking always has the index. */
196
- private readonly indexPool?;
197
- private readonly indexDialect?;
198
- /** Blob-domain index table ([ref] 域隔离,SqlBlobBackend.table 同款;默认 = E19 纪元的 snapshot_blob)。 */
199
- private readonly indexTable;
200
- constructor(cfg: MinioBlobBackendConfig, index?: {
201
- dialect: SqlDialect;
202
- pool: MysqlPool | PgPool;
203
- table?: string;
204
- });
60
+ constructor(cfg: MinioBlobBackendConfig);
205
61
  private objectKey;
206
62
  private presign;
207
- /** PUT the bytes under the content-addressed key, THEN upsert the SQL INDEX row (bytes NULL, created_at refresh on
208
- * conflict — the SAME grace discipline as SqlBlobBackend, so a just-PUT blob an in-flight snapshot needs is touched=
209
- * now and protected). Idempotent (same hash ⇒ overwrite-with-identical-bytes + created_at bump). A non-2xx PUT throws
210
- * (an upload failure must surface — a silent drop would later read_failed on restore). The PUT happens BEFORE the
211
- * index upsert so an index row never claims a blob the object store doesn't hold (an index row with no object would
212
- * let hasBlobs report a phantom present; the reverse — an object with no index — is harmless and pruned by a bucket
213
- * lifecycle if it ever happens). NOTE no post-PUT read-back verify on the LIVE path (perf): content-addressing
214
- * catches a corrupted PUT at the next getBlob sha-check (fail-closed); the one-time migration script DOES read-back. */
215
- putBlob(hash: string, bytes: Uint8Array): Promise<void>;
216
- /** GET the bytes for `hash`, then VERIFY content-address (sha256(bytes)===hash). THREE branches (finding 11):
217
- * - 404 → undefined (genuinely ABSENT — the file-snapshot store treats undefined as a missing blob).
218
- * - sha256 MISMATCH → undefined (corruption/poisoning; treat corrupt-as-absent, fail-CLOSED, NEVER wrong bytes).
219
- * - a NON-2xx-NON-404 (5xx/throttle) OR a network/fetch REJECT → THROW (a TRANSIENT fault must fail LOUD so the
220
- * restore/import surfaces an error, NOT silently drop a file as "missing"; the SQL backend likewise propagates a
221
- * pool error). The snapshot store's restore() wraps applyManifest so this throw becomes a {ok:false} restore_failed. */
222
- getBlob(hash: string): Promise<Uint8Array | undefined>;
223
- /** The subset of `hashes` present — reads the SQL INDEX (cheaper than a HEAD-per-hash AND consistent with the SQL
224
- * backend). Falls back to a presigned HEAD per hash ONLY in object-only mode (no index pool: the migration / unit
225
- * path). The caller passes DISTINCT hashes (migration idempotency batch / reap orphan set / §10 presence pre-check). */
226
- hasBlobs(hashes: string[]): Promise<Set<string>>;
63
+ /** PUT the bytes under the key. A non-2xx PUT throws (an upload failure must surface — a silent drop would later read_failed on
64
+ * 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
65
+ * check (fail-closed). */
66
+ put(key: string, bytes: Uint8Array): Promise<void>;
67
+ /** GET the bytes under the key. THREE branches (finding 11):
68
+ * - 404 → undefined (genuinely ABSENT).
69
+ * - 2xx → the bytes, unjudged (the index owner checks them against the hash: {@link readAtAddress}).
70
+ * - a NON-2xx-NON-404 (5xx/throttle) OR a network/fetch REJECT → THROW (a TRANSIENT fault must fail LOUD so the restore/import
71
+ * surfaces an error, NOT silently drop a file as "missing"). */
72
+ get(key: string): Promise<Uint8Array | undefined>;
73
+ /** DELETE every key's object, at most {@link MINIO_OP_CONCURRENCY} in flight (no FD / throttle storm). Each key is independent: a
74
+ * 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
75
+ * failed, the call REJECTS naming how many (🔴 复审 F4 的同一判据:对象存储完全不可写时绝不报「清理成功」—— 失败只在这里说出来,
76
+ * 调用方据此记账,不吞)。 */
77
+ delete(keys: readonly string[]): Promise<void>;
227
78
  /** D-1 孤儿对象 GC(clay 拍 2026-07-28):列举本后端 keyPrefix 下的全部对象(ListObjectsV2 分页,
228
79
  * 零依赖 XML 取 <Key>/<LastModified>/<NextContinuationToken>)。**server 端 sweep 专用**——presign 的
229
80
  * bucket-GET 列举能力绝不外发。响应非 2xx 即 throw(sweep 调用方自 catch:列举失败=本轮跳过,
@@ -241,13 +92,5 @@ export declare class MinioBlobBackend implements BlobBackend {
241
92
  * 🔴 只有「404 且体里是 `NoSuchBucket`」才算缺桶;网络不通 / 403(凭据不能列举 ≠ 桶不在)/ 5xx / 没有 NoSuchBucket 的 404(代理 / 路径错)
242
93
  * 都**证明不了**缺桶 ⇒ `unknown`,调用方不拒启、只报一次。总函数:不抛。`timeoutMs`:boot 期调用方给的单次上界(黑洞端点不许把起服拖到 120s)。 */
243
94
  probeBucket(timeoutMs?: number): Promise<BucketProbe>;
244
- /** Byte-delete the given hashes — called ONLY from the async sweepOrphanBlobs reaper (NEVER the synchronous purge
245
- * path). Honors the SAME created_at grace window as the SQL backend: with an index, DELETE the grace-passed index
246
- * rows first (the index's created_at is the authoritative age — an S3 object carries no service-controlled timestamp
247
- * the backend reads), then delete the MinIO objects ONLY for those grace-passed hashes (so a just-PUT blob an
248
- * in-flight snapshot needs is NOT delete-in-use). ERROR-TOLERANT + BOUNDED: each object delete is independent (a
249
- * failure is skipped → retried next sweep), at most MINIO_OP_CONCURRENCY in flight (no FD/throttle storm). In
250
- * object-only mode (no index pool: the migration/unit cleanup path) it deletes every given hash with no grace. */
251
- deleteBlobs(hashes: string[]): Promise<number>;
252
95
  }
253
96
  //# sourceMappingURL=blob-backend.d.ts.map