@sema-agent/server 7.141.0 → 7.143.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 (341) hide show
  1. package/MIGRATION.md +657 -0
  2. package/USAGE.md +102 -30
  3. package/dist/adoption/plan.js +22 -0
  4. package/dist/approval-ask-audit-store.d.ts +61 -43
  5. package/dist/approval-ask-audit-store.js +69 -44
  6. package/dist/approval-ask-machine.d.ts +15 -7
  7. package/dist/approval-ask-machine.js +10 -4
  8. package/dist/approval-card.d.ts +126 -27
  9. package/dist/approval-card.js +103 -23
  10. package/dist/approval-crash-convergence.d.ts +17 -7
  11. package/dist/approval-crash-convergence.js +94 -22
  12. package/dist/approval-deny-reasons.d.ts +34 -30
  13. package/dist/approval-deny-reasons.js +21 -6
  14. package/dist/approval-policy-settlement.d.ts +1 -1
  15. package/dist/approval-queue-kind.d.ts +27 -0
  16. package/dist/approval-queue-kind.js +6 -0
  17. package/dist/approval-reconciler.d.ts +41 -9
  18. package/dist/approval-reconciler.js +45 -42
  19. package/dist/audit.js +4 -2
  20. package/dist/auth-bridge.d.ts +9 -6
  21. package/dist/auth-bridge.js +9 -3
  22. package/dist/boot/adoption.js +2 -1
  23. package/dist/boot/budget-tracing.d.ts +17 -1
  24. package/dist/boot/budget-tracing.js +10 -6
  25. package/dist/boot/device-lane.d.ts +1 -1
  26. package/dist/boot/execution-env.d.ts +24 -4
  27. package/dist/boot/execution-env.js +26 -23
  28. package/dist/boot/execution-lane.js +2 -1
  29. package/dist/boot/exit-boundary.js +5 -4
  30. package/dist/boot/governance-seams.d.ts +26 -41
  31. package/dist/boot/governance-seams.js +61 -28
  32. package/dist/boot/late-binds.d.ts +7 -4
  33. package/dist/boot/late-binds.js +3 -1
  34. package/dist/boot/leader.js +2 -4
  35. package/dist/boot/memory-consolidation.d.ts +0 -8
  36. package/dist/boot/memory-consolidation.js +5 -4
  37. package/dist/boot/parked-revive-gate.js +2 -1
  38. package/dist/boot/permission-rules-audit.d.ts +0 -28
  39. package/dist/boot/permission-rules-audit.js +2 -1
  40. package/dist/boot/read-deny-anchor-audit.js +2 -1
  41. package/dist/boot/reapers.js +9 -7
  42. package/dist/boot/resolve-spec.d.ts +1 -1
  43. package/dist/boot/resolve-spec.js +19 -10
  44. package/dist/boot/retention-lane.js +5 -3
  45. package/dist/boot/runner-deps.d.ts +10 -7
  46. package/dist/boot/runner-deps.js +20 -29
  47. package/dist/boot/runtime-caps.js +3 -2
  48. package/dist/boot/session-faces.js +4 -3
  49. package/dist/boot/shutdown.d.ts +9 -0
  50. package/dist/boot/shutdown.js +19 -4
  51. package/dist/boot/stage-02-web-admin-pull.js +3 -0
  52. package/dist/boot/stage-03-store-backend.d.ts +4 -1
  53. package/dist/boot/stage-03-store-backend.js +1 -2
  54. package/dist/boot/stage-04-stores.d.ts +5 -2
  55. package/dist/boot/stage-04-stores.js +6 -7
  56. package/dist/boot/stage-05-execution-env.d.ts +6 -3
  57. package/dist/boot/stage-05-execution-env.js +8 -6
  58. package/dist/boot/stage-06-runners.d.ts +6 -3
  59. package/dist/boot/stage-06-runners.js +3 -4
  60. package/dist/boot/stage-07-capability-layer.d.ts +6 -3
  61. package/dist/boot/stage-07-capability-layer.js +7 -2
  62. package/dist/boot/stage-08-reapers.d.ts +6 -3
  63. package/dist/boot/stage-08-reapers.js +3 -2
  64. package/dist/boot/stage-09-leader.d.ts +6 -3
  65. package/dist/boot/stage-10-http-server.d.ts +6 -3
  66. package/dist/boot/stage-10-http-server.js +14 -5
  67. package/dist/boot/stores.d.ts +5 -2
  68. package/dist/boot/stores.js +10 -9
  69. package/dist/boot/web-admin.d.ts +5 -1
  70. package/dist/boot/web-admin.js +48 -36
  71. package/dist/boot/webfetch-summarize-lane.js +2 -1
  72. package/dist/boot/workflow-orchestration.js +3 -2
  73. package/dist/capabilities/builtin-tools.d.ts +2 -1
  74. package/dist/capabilities/builtin-tools.js +2 -4
  75. package/dist/capabilities/composite-members.d.ts +2 -1
  76. package/dist/capabilities/composite-members.js +2 -1
  77. package/dist/capabilities/hands-lane.d.ts +9 -39
  78. package/dist/capabilities/hands-lane.js +8 -13
  79. package/dist/capabilities/mcp-probe.d.ts +3 -2
  80. package/dist/capabilities/scenarios.d.ts +11 -1
  81. package/dist/capabilities/scenarios.js +1 -0
  82. package/dist/capabilities/skills.d.ts +1 -17
  83. package/dist/capabilities/skills.js +0 -8
  84. package/dist/capability-facts.d.ts +31 -7
  85. package/dist/capability-facts.js +27 -4
  86. package/dist/card-void.d.ts +6 -9
  87. package/dist/config-catalog.js +2 -1
  88. package/dist/config-dir-trust.js +58 -29
  89. package/dist/config-invariants.d.ts +7 -1
  90. package/dist/config-invariants.js +7 -0
  91. package/dist/config-provider.d.ts +10 -0
  92. package/dist/config-provider.js +15 -4
  93. package/dist/config-root-migration.d.ts +13 -0
  94. package/dist/config-root-migration.js +99 -0
  95. package/dist/config-types.d.ts +19 -8
  96. package/dist/config.d.ts +10 -3
  97. package/dist/config.js +18 -4
  98. package/dist/delegated-session-owner.d.ts +5 -3
  99. package/dist/delegated-session-owner.js +1 -1
  100. package/dist/device-ws-protocol.d.ts +1 -0
  101. package/dist/device-ws-protocol.js +2 -1
  102. package/dist/env-model-table-gate.d.ts +53 -0
  103. package/dist/env-model-table-gate.js +53 -0
  104. package/dist/execution-lane-caps.d.ts +2 -1
  105. package/dist/fleet/fleet-bus.d.ts +34 -55
  106. package/dist/fleet/fleet-bus.js +35 -100
  107. package/dist/fleet/fleet-reconciler.d.ts +4 -4
  108. package/dist/fleet/fleet-reconciler.js +1 -1
  109. package/dist/fleet/subagent-tail-bus.d.ts +14 -11
  110. package/dist/fleet/subagent-tail-bus.js +15 -28
  111. package/dist/hooks/hook-runner.d.ts +6 -0
  112. package/dist/hooks/hook-runner.js +58 -8
  113. package/dist/host-decision.d.ts +54 -20
  114. package/dist/host-decision.js +42 -14
  115. package/dist/http/admission.d.ts +1 -1
  116. package/dist/http/admission.js +7 -3
  117. package/dist/http/approval-sweeps.js +11 -8
  118. package/dist/http/caller-trust.d.ts +1 -1
  119. package/dist/http/dispatch.js +4 -2
  120. package/dist/http/durable-run-leg.js +2 -2
  121. package/dist/http/engine-refusal.d.ts +16 -0
  122. package/dist/http/engine-refusal.js +17 -0
  123. package/dist/http/execution-context.d.ts +2 -2
  124. package/dist/http/idempotency.d.ts +1 -1
  125. package/dist/http/memory-compliance-failure-reply.d.ts +1 -3
  126. package/dist/http/memory-compliance-failure-reply.js +4 -6
  127. package/dist/http/owner-access.d.ts +11 -0
  128. package/dist/http/owner-access.js +13 -0
  129. package/dist/http/principal-gate.d.ts +3 -1
  130. package/dist/http/principal-gate.js +17 -8
  131. package/dist/http/resume-legs.d.ts +21 -7
  132. package/dist/http/resume-legs.js +76 -58
  133. package/dist/http/resume-restatement.d.ts +39 -0
  134. package/dist/http/resume-restatement.js +25 -0
  135. package/dist/http/route-ctx.d.ts +35 -10
  136. package/dist/http/route-ctx.js +1 -1
  137. package/dist/http/route-table.js +2 -0
  138. package/dist/http/routes/approvals-assistant.d.ts +9 -1
  139. package/dist/http/routes/approvals-assistant.js +142 -31
  140. package/dist/http/routes/attachments.js +18 -0
  141. package/dist/http/routes/capabilities.js +16 -4
  142. package/dist/http/routes/memory-policy.d.ts +2 -2
  143. package/dist/http/routes/memory-policy.js +27 -7
  144. package/dist/http/routes/notify-wake.js +23 -25
  145. package/dist/http/routes/rules.js +48 -13
  146. package/dist/http/routes/runs.js +12 -11
  147. package/dist/http/routes/session-memory-sync.d.ts +91 -0
  148. package/dist/http/routes/session-memory-sync.js +174 -0
  149. package/dist/http/routes/session-sync.js +13 -20
  150. package/dist/http/routes/sessions-list.d.ts +2 -1
  151. package/dist/http/routes/sessions.d.ts +2 -2
  152. package/dist/http/routes/sessions.js +22 -23
  153. package/dist/http/routes/tasks.js +34 -54
  154. package/dist/http/run-read-face.d.ts +7 -0
  155. package/dist/http/run-read-face.js +9 -3
  156. package/dist/http/send.d.ts +5 -0
  157. package/dist/http/send.js +9 -2
  158. package/dist/http/server.d.ts +27 -15
  159. package/dist/http/server.js +4 -6
  160. package/dist/http/stored-body-replay.js +15 -4
  161. package/dist/http/submit-replay.d.ts +4 -3
  162. package/dist/http/submit-replay.js +2 -2
  163. package/dist/http/sync-submit-body.d.ts +21 -4
  164. package/dist/http/sync-submit-body.js +13 -0
  165. package/dist/http/wire-types.d.ts +17 -7
  166. package/dist/identity-source.d.ts +21 -2
  167. package/dist/identity-source.js +6 -0
  168. package/dist/leader/leader.js +5 -2
  169. package/dist/leader/wire.d.ts +7 -1
  170. package/dist/leader/wire.js +6 -5
  171. package/dist/leg-facts.d.ts +37 -0
  172. package/dist/leg-facts.js +15 -0
  173. package/dist/memory-bundle-engine.d.ts +1 -4
  174. package/dist/memory-bundle-engine.js +2 -2
  175. package/dist/memory-incident-sink.d.ts +19 -6
  176. package/dist/memory-incident-sink.js +8 -4
  177. package/dist/memory-operator-faces.d.ts +30 -66
  178. package/dist/memory-operator-faces.js +17 -88
  179. package/dist/memory-scope-stores.d.ts +38 -40
  180. package/dist/memory-scope-stores.js +51 -36
  181. package/dist/memory-scope.d.ts +0 -9
  182. package/dist/memory-scope.js +0 -9
  183. package/dist/memory-sync-client.d.ts +21 -21
  184. package/dist/memory-sync-client.js +62 -43
  185. package/dist/memory-sync-identity.d.ts +24 -0
  186. package/dist/memory-sync-identity.js +57 -0
  187. package/dist/memory-sync.d.ts +27 -5
  188. package/dist/memory-sync.js +29 -7
  189. package/dist/model-plane-face.d.ts +13 -7
  190. package/dist/model-plane-face.js +2 -1
  191. package/dist/observability/fail-open.d.ts +47 -14
  192. package/dist/observability/fail-open.js +37 -11
  193. package/dist/observability/run-terminal.d.ts +92 -34
  194. package/dist/observability/run-terminal.js +171 -162
  195. package/dist/orchestration/workflow-completion-inbox.d.ts +5 -19
  196. package/dist/orchestration/workflow-completion-inbox.js +0 -12
  197. package/dist/orchestration/workflow-notify-journal.d.ts +3 -2
  198. package/dist/orchestration/workflow-park-decision.d.ts +8 -3
  199. package/dist/orchestration/workflow-park-decision.js +5 -3
  200. package/dist/org-delivery-gate.d.ts +11 -0
  201. package/dist/org-delivery-gate.js +19 -1
  202. package/dist/parked-decide.d.ts +13 -9
  203. package/dist/parked-decide.js +7 -7
  204. package/dist/parked-revive-surface.js +1 -1
  205. package/dist/peer-inbound-face.d.ts +127 -0
  206. package/dist/peer-inbound-face.js +158 -0
  207. package/dist/permission-rule-list.d.ts +13 -9
  208. package/dist/permission-rule-list.js +7 -3
  209. package/dist/plugins/approval-ask-store-file.d.ts +14 -4
  210. package/dist/plugins/approval-ask-store-file.js +64 -11
  211. package/dist/plugins/approval-ask-store-memory.d.ts +2 -1
  212. package/dist/plugins/approval-ask-store-memory.js +17 -14
  213. package/dist/plugins/approval-ask-store-sql.d.ts +70 -23
  214. package/dist/plugins/approval-ask-store-sql.js +79 -30
  215. package/dist/plugins/checkpoint-store-sql.d.ts +4 -4
  216. package/dist/plugins/checkpoint-store-sql.js +9 -7
  217. package/dist/plugins/file-history-store-sql.d.ts +24 -18
  218. package/dist/plugins/file-history-store-sql.js +24 -19
  219. package/dist/plugins/file-run-store.d.ts +35 -1
  220. package/dist/plugins/file-run-store.js +108 -9
  221. package/dist/plugins/imported-layer-root-retirement.d.ts +82 -0
  222. package/dist/plugins/imported-layer-root-retirement.js +96 -0
  223. package/dist/plugins/local-checkpoint-store.d.ts +1 -1
  224. package/dist/plugins/local-checkpoint-store.js +2 -2
  225. package/dist/plugins/local-session-store.d.ts +42 -9
  226. package/dist/plugins/local-session-store.js +83 -33
  227. package/dist/plugins/local-task-attachment-store.d.ts +12 -2
  228. package/dist/plugins/local-task-attachment-store.js +67 -43
  229. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +9 -31
  230. package/dist/plugins/mailbox-recipient-lifecycle.js +4 -0
  231. package/dist/plugins/mailbox-store-sql.d.ts +12 -8
  232. package/dist/plugins/mailbox-store-sql.js +76 -7
  233. package/dist/plugins/memory-key-guards.d.ts +3 -3
  234. package/dist/plugins/memory-run-store.d.ts +6 -1
  235. package/dist/plugins/memory-run-store.js +11 -1
  236. package/dist/plugins/memory-sync-store-pg.d.ts +15 -0
  237. package/dist/plugins/memory-sync-store-pg.js +21 -0
  238. package/dist/plugins/memory-sync-store-tidb.d.ts +2 -0
  239. package/dist/plugins/memory-sync-store-tidb.js +13 -1
  240. package/dist/plugins/one-time-migrations.d.ts +58 -2
  241. package/dist/plugins/one-time-migrations.js +161 -4
  242. package/dist/plugins/org-delivery-quota-store.d.ts +1 -1
  243. package/dist/plugins/org-delivery-quota-store.js +2 -12
  244. package/dist/plugins/park-commit-watch.d.ts +1 -1
  245. package/dist/plugins/permission-rule-store-file.d.ts +10 -1
  246. package/dist/plugins/permission-rule-store-file.js +15 -2
  247. package/dist/plugins/permission-rule-store-sql.d.ts +31 -1
  248. package/dist/plugins/permission-rule-store-sql.js +35 -2
  249. package/dist/plugins/remote-env-device.d.ts +8 -11
  250. package/dist/plugins/remote-env-device.js +6 -3
  251. package/dist/plugins/remote-env-e2b.d.ts +23 -4
  252. package/dist/plugins/remote-env-e2b.js +111 -28
  253. package/dist/plugins/remote-env-k8s.d.ts +61 -22
  254. package/dist/plugins/remote-env-k8s.js +133 -33
  255. package/dist/plugins/remote-env-local-docker.d.ts +15 -3
  256. package/dist/plugins/remote-env-local-docker.js +40 -12
  257. package/dist/plugins/retention-store-sql.d.ts +2 -2
  258. package/dist/plugins/run-store-sql.d.ts +9 -1
  259. package/dist/plugins/run-store-sql.js +9 -1
  260. package/dist/plugins/sandbox-read-floor.d.ts +5 -7
  261. package/dist/plugins/sandbox-read-floor.js +2 -7
  262. package/dist/plugins/sql-errors.d.ts +10 -1
  263. package/dist/plugins/sql-errors.js +13 -0
  264. package/dist/plugins/store-backend.d.ts +33 -35
  265. package/dist/plugins/store-backend.js +10 -1
  266. package/dist/plugins/store-contracts.d.ts +50 -1
  267. package/dist/plugins/store-contracts.js +6 -0
  268. package/dist/plugins/task-attachment-store.d.ts +112 -14
  269. package/dist/plugins/task-attachment-store.js +207 -29
  270. package/dist/plugins/tool-result-store-sql.d.ts +9 -8
  271. package/dist/plugins/tool-result-store-sql.js +23 -2
  272. package/dist/plugins/wiring-section-codec.d.ts +32 -0
  273. package/dist/plugins/wiring-section-codec.js +55 -0
  274. package/dist/plugins/workspace-fill.d.ts +60 -0
  275. package/dist/plugins/workspace-fill.js +106 -0
  276. package/dist/project-bundle.d.ts +38 -0
  277. package/dist/project-bundle.js +609 -0
  278. package/dist/rule-entry-list.d.ts +3 -2
  279. package/dist/rule-entry-list.js +5 -1
  280. package/dist/rules-consent.d.ts +28 -5
  281. package/dist/rules-consent.js +40 -28
  282. package/dist/run-local.js +11 -13
  283. package/dist/runs.d.ts +12 -8
  284. package/dist/runs.js +6 -8
  285. package/dist/runtime-governance.d.ts +1 -1
  286. package/dist/sandbox-egress-policy.d.ts +4 -1
  287. package/dist/sandbox-egress-policy.js +3 -1
  288. package/dist/sandbox-git-plane.d.ts +31 -12
  289. package/dist/sandbox-git-plane.js +24 -4
  290. package/dist/security.d.ts +9 -0
  291. package/dist/security.js +8 -0
  292. package/dist/server-secret-env.d.ts +4 -0
  293. package/dist/session-error-wire.d.ts +36 -0
  294. package/dist/session-error-wire.js +13 -0
  295. package/dist/session-incarnation.d.ts +1 -1
  296. package/dist/session-notify-door.d.ts +106 -0
  297. package/dist/session-notify-door.js +93 -0
  298. package/dist/session-sync.d.ts +9 -14
  299. package/dist/session-sync.js +5 -5
  300. package/dist/session-workspace.d.ts +3 -13
  301. package/dist/session-workspace.js +0 -9
  302. package/dist/standing-answer-grant.d.ts +5 -0
  303. package/dist/standing-answer-grant.js +10 -0
  304. package/dist/stores-sql/session-policy-store-sql.d.ts +4 -2
  305. package/dist/stores-sql/session-policy-store-sql.js +3 -13
  306. package/dist/task-mcp.d.ts +1 -1
  307. package/dist/task-settings.d.ts +21 -10
  308. package/dist/task-settings.js +46 -13
  309. package/dist/terminal.d.ts +39 -19
  310. package/dist/terminal.js +65 -22
  311. package/dist/tool-approval.d.ts +56 -37
  312. package/dist/tool-approval.js +78 -71
  313. package/dist/trace/core-keyset-guard.d.ts +134 -14
  314. package/dist/trace/engine-notice-wire.d.ts +9 -3
  315. package/dist/trace/engine-notice-wire.js +7 -3
  316. package/dist/trace/exit-seat.d.ts +9 -2
  317. package/dist/trace/exit-seat.js +1 -0
  318. package/dist/trace/ledger-sink.d.ts +10 -6
  319. package/dist/trace/ledger-sink.js +2 -2
  320. package/dist/trace/model-segment.d.ts +55 -25
  321. package/dist/trace/model-segment.js +101 -33
  322. package/dist/trace/project.d.ts +25 -5
  323. package/dist/trace/project.js +22 -0
  324. package/dist/trace/redact.d.ts +61 -9
  325. package/dist/trace/redact.js +1490 -468
  326. package/dist/trace/self-minted-wire.d.ts +745 -24
  327. package/dist/trace/self-minted-wire.js +239 -9
  328. package/dist/trace/wire-projection-faces.d.ts +2 -2
  329. package/dist/trace/wire-projection-faces.js +2 -2
  330. package/dist/verifier-pause-card.d.ts +33 -5
  331. package/dist/verifier-pause-card.js +15 -10
  332. package/dist/web-admin-client/apply-effective.d.ts +12 -16
  333. package/dist/web-admin-client/apply-effective.js +109 -9
  334. package/dist/web-admin-client/effective-keys.js +2 -0
  335. package/dist/web-admin-client/types.d.ts +4 -0
  336. package/dist/workspace-space.d.ts +19 -3
  337. package/dist/workspace-space.js +8 -4
  338. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -1
  339. package/package.json +3 -2
  340. package/wire-changes/server@7.142.0.json +639 -0
  341. package/wire-changes/server@7.143.0.json +1167 -0
@@ -4,7 +4,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
4
4
  import { isDeepStrictEqual } from "node:util";
5
5
  import { dirname, join, resolve } from "node:path";
6
6
  import { assertFirstOwnerWritable, forkOwnerOf, importerOwnerOf } from "./session-ownership.js";
7
- import { StampedSessionArchiveError } from "../session-error-wire.js";
7
+ import { SessionOwnerUnreadableError, StampedSessionArchiveError, sessionUnreadableOf } from "../session-error-wire.js";
8
8
  import { FileSessionRepo, SessionError, StoredSession, admitSessionPlacement, atomicWriteFile, sessionLogMarkOf, settledForkOptions, uuidv7, validateEntriesForImport } from "@sema-agent/core";
9
9
  import { createPlacedSessionRow, sourceFacesVia } from "../delegated-session-owner.js";
10
10
  import { placementCapabilityOf } from "./session-placement.js";
@@ -54,6 +54,12 @@ function unusableArchiveOf(word, fault) {
54
54
  const code = fault instanceof SessionError ? undefined : fault?.code;
55
55
  return { state: "unusable", word, fault, ...(word === "storage" && typeof code === "string" ? { errno: code } : {}) };
56
56
  }
57
+ function ownerUnreadableArchive(probe) {
58
+ const { fault } = probe;
59
+ if (probe.word === "storage" || !(fault instanceof SessionError))
60
+ return probe;
61
+ return { ...probe, fault: new SessionOwnerUnreadableError(probe.word, fault) };
62
+ }
57
63
  function importRowRefused(sessionId, landing) {
58
64
  return new SessionError("conflict", landing === "create"
59
65
  ? `session ${sessionId} already exists — importEntries only creates a session (replaceEntries rewrites one); nothing was written`
@@ -597,7 +603,7 @@ export class LocalSessionStore {
597
603
  return { state: "found", meta: readSessionMetaCell(cell) };
598
604
  const probe = await this.probeArchive(sessionId);
599
605
  if (probe.state === "unusable")
600
- return probe;
606
+ return ownerUnreadableArchive(probe);
601
607
  if (probe.state === "absent")
602
608
  return { state: "absent" };
603
609
  const meta = await this.cellOfPresent(sessionId);
@@ -677,7 +683,7 @@ export class LocalSessionStore {
677
683
  }
678
684
  async lockedRowOf(sessionId) {
679
685
  const meta = this.metaCellOf(sessionId);
680
- if (meta === undefined || (await this.listedMeta(sessionId)) === undefined)
686
+ if (meta === undefined || (await this.rowHeaderOf(sessionId)) === undefined)
681
687
  return undefined;
682
688
  return { owner: meta.owner ?? null, incarnation: incarnationFromCell(sessionId, meta.incarnation, "absent"), placed: false, mirror: meta.execution?.role === "mirror", cells: this.rowCellsOf(sessionId) };
683
689
  }
@@ -713,19 +719,62 @@ export class LocalSessionStore {
713
719
  }
714
720
  async listRowOf(sessionId) {
715
721
  await this.loadRowSidecars();
716
- const listed = await this.listedMeta(sessionId);
722
+ const header = await this.rowHeaderOf(sessionId);
717
723
  const meta = this.metaCellOf(sessionId);
718
- if (listed === undefined || meta === undefined)
724
+ if (header === undefined || meta === undefined)
719
725
  return undefined;
720
- return { row: await this.summaryOf(listed, await this.runRollups()), occupant: { owner: meta.owner ?? null, incarnation: incarnationFromCell(sessionId, meta.incarnation, "absent") } };
726
+ return { row: await this.summaryOf(await this.listedRowOf(header), await this.runRollups()), occupant: { owner: meta.owner ?? null, incarnation: incarnationFromCell(sessionId, meta.incarnation, "absent") } };
721
727
  }
722
728
  async sessionSummaryOf(sessionId) {
723
729
  await this.loadRowSidecars();
724
- const meta = await this.listedMeta(sessionId);
725
- return meta === undefined ? undefined : this.summaryOf(meta, await this.runRollups());
730
+ const header = await this.rowHeaderOf(sessionId);
731
+ return header === undefined ? undefined : this.summaryOf(await this.listedRowOf(header), await this.runRollups());
732
+ }
733
+ async rowHeaders() {
734
+ await this.meta.ensureLoaded();
735
+ const listed = await this.repo.list();
736
+ const listedIds = new Set(listed.map((row) => row.id));
737
+ const placed = this.createPlacedIdsReader();
738
+ const rows = listed.map((header) => ({ sessionId: header.id, header }));
739
+ for (const id of [...this.meta.state.entries.keys()].sort()) {
740
+ if (listedIds.has(id))
741
+ continue;
742
+ const row = await this.headerUnreadableRowOf(id, placed);
743
+ if (row !== undefined)
744
+ rows.push(row);
745
+ }
746
+ return rows;
747
+ }
748
+ async rowHeaderOf(sessionId) {
749
+ await this.meta.ensureLoaded();
750
+ const header = (await this.repo.list()).find((m) => m.id === sessionId);
751
+ if (header !== undefined)
752
+ return { sessionId, header };
753
+ return this.meta.state.entries.has(sessionId) ? this.headerUnreadableRowOf(sessionId, this.createPlacedIdsReader()) : undefined;
754
+ }
755
+ async headerUnreadableRowOf(sessionId, placed) {
756
+ try {
757
+ await this.archiveHeadOf(sessionId);
758
+ return undefined;
759
+ }
760
+ catch (fault) {
761
+ return (await placed()).has(sessionId) ? undefined : { sessionId, headerFault: fault };
762
+ }
763
+ }
764
+ createPlacedIdsReader() {
765
+ let ids;
766
+ return () => (ids ??= (async () => new Set((await this.listPlaced?.("subagent"))?.map((row) => row.sessionId) ?? []))());
726
767
  }
727
- async listedMeta(sessionId) {
728
- return (await this.repo.list()).find((m) => m.id === sessionId);
768
+ async listedRowOf(row) {
769
+ if ("headerFault" in row)
770
+ return { sessionId: row.sessionId, unreadable: row.headerFault };
771
+ try {
772
+ await this.archiveHeadOf(row.sessionId);
773
+ return { sessionId: row.sessionId, readable: row.header };
774
+ }
775
+ catch (fault) {
776
+ return { sessionId: row.sessionId, unreadable: fault };
777
+ }
729
778
  }
730
779
  async readInstructionSource(sessionId) {
731
780
  await this.instructionSources.ensureLoaded();
@@ -953,14 +1002,16 @@ export class LocalSessionStore {
953
1002
  }
954
1003
  async listSessions(opts) {
955
1004
  await this.loadRowSidecars();
956
- const metas = await this.repo.list();
1005
+ const rows = [];
1006
+ for (const header of await this.rowHeaders())
1007
+ rows.push(await this.listedRowOf(header));
957
1008
  const rollups = await this.runRollups();
958
1009
  const all = [];
959
- for (const meta of metas) {
960
- const owner = this.ownerCellOf(meta.id);
1010
+ for (const row of rows) {
1011
+ const owner = this.ownerCellOf(row.sessionId);
961
1012
  if (opts.owner !== undefined && owner !== opts.owner && !(opts.includeUnowned === true && owner === null))
962
1013
  continue;
963
- all.push(await this.summaryOf(meta, rollups));
1014
+ all.push(await this.summaryOf(row, rollups));
964
1015
  }
965
1016
  const qlc = opts.q?.toLowerCase();
966
1017
  const filtered = qlc ? all.filter((r) => r.objectivePreview?.toLowerCase().includes(qlc)) : all;
@@ -983,23 +1034,25 @@ export class LocalSessionStore {
983
1034
  const cell = this.meta.state.entries.get(sessionId);
984
1035
  return cell === undefined ? null : (readSessionMetaCell(cell).owner ?? null);
985
1036
  }
986
- async summaryOf(meta, rollups) {
987
- const firstActivityAt = rowCreatedAtOf(meta.id, this.metaCellOf(meta.id));
988
- const owner = this.ownerCellOf(meta.id);
989
- const cells = this.rowCellsOf(meta.id);
990
- const rowTag = this.rowTagKeyOf(meta.id, owner, cells);
991
- const lastActivityAt = this.lastActivity.get(meta.id) ?? firstActivityAt;
992
- const objectivePreview = await this.previewOf(meta);
1037
+ async summaryOf(listed, rollups) {
1038
+ const { sessionId } = listed;
1039
+ const firstActivityAt = rowCreatedAtOf(sessionId, this.metaCellOf(sessionId));
1040
+ const owner = this.ownerCellOf(sessionId);
1041
+ const cells = this.rowCellsOf(sessionId);
1042
+ const rowTag = this.rowTagKeyOf(sessionId, owner, cells);
1043
+ const lastActivityAt = this.lastActivity.get(sessionId) ?? firstActivityAt;
1044
+ const objectivePreview = "readable" in listed ? await this.previewOf(listed.readable) : null;
993
1045
  return {
994
- sessionId: meta.id,
1046
+ sessionId,
995
1047
  owner,
996
1048
  lastActivityAt,
997
1049
  firstActivityAt,
998
1050
  objectivePreview,
999
- ...this.runProjectionOf(meta.id, rollups),
1051
+ ...this.runProjectionOf(sessionId, rollups),
1000
1052
  title: cells.title,
1001
1053
  pinned: cells.pinned,
1002
1054
  ...rowTag,
1055
+ ...("unreadable" in listed ? { unreadable: sessionUnreadableOf(listed.unreadable) } : {}),
1003
1056
  };
1004
1057
  }
1005
1058
  rowTagKeyOf(sessionId, owner, cells) {
@@ -1381,19 +1434,16 @@ export class LocalSessionStore {
1381
1434
  if (!this.repo.readRow || !this.repo.importEntries)
1382
1435
  throw new SessionError("storage", "LocalSessionStore: the one-time migration M33 needs a session repo that reads a whole row and imports a log (readRow / importEntries)");
1383
1436
  await this.meta.ensureLoaded();
1384
- const listed = await this.repo.list();
1385
- const listedIds = new Set(listed.map((row) => row.id));
1437
+ const rowHeaders = await this.rowHeaders();
1438
+ const listed = [];
1386
1439
  const unreadable = [];
1387
- for (const id of [...this.meta.state.entries.keys()].sort()) {
1388
- if (listedIds.has(id))
1440
+ for (const row of rowHeaders) {
1441
+ if ("header" in row) {
1442
+ listed.push(row.header);
1389
1443
  continue;
1390
- try {
1391
- await this.archiveHeadOf(id);
1392
- }
1393
- catch (e) {
1394
- const errno = errnoOf(e);
1395
- unreadable.push({ sessionId: id, ...(errno !== undefined ? { errno } : {}) });
1396
1444
  }
1445
+ const errno = errnoOf(row.headerFault);
1446
+ unreadable.push({ sessionId: row.sessionId, ...(errno !== undefined ? { errno } : {}) });
1397
1447
  }
1398
1448
  let rowFactsBackfilled = 0;
1399
1449
  const committed = await this.meta.commit((draft) => {
@@ -1,18 +1,28 @@
1
- import { type TaskAttachmentStore, type TaskAttachmentRecord } from "./task-attachment-store.js";
1
+ import { type AttachmentStoreBindOutcome, type TaskAttachmentStore, type TaskAttachmentRecord } from "./task-attachment-store.js";
2
2
  export declare class LocalTaskAttachmentStore implements TaskAttachmentStore {
3
3
  private readonly dir;
4
4
  private metas;
5
5
  private hydration;
6
+ /** 变更串行段的尾(见 `serialized`):每只变更口排在上一只的落盘与合回之后。本店唯一一只。 */
7
+ private mutationTail;
6
8
  constructor(rootDir: string);
7
9
  private hydrate;
10
+ /**
11
+ * 本店**唯一**的变更串行段:凡改 `this.metas` 或删盘上行的口(put / bind / delete / deleteBySession / reapUnbound)把**整条操作**
12
+ * (判 + 落盘 + 合回内存)交进来,于是任何一只变更口都观察不到别的变更口做到一半的中间态 —— bind 落盘期间「副本已判、内存未合」
13
+ * 的那一段,收割 / 删除既不会判到旧内存、也不会把盘上正在落的行删掉。读口不进来:它们只读内存,不排队。
14
+ * 一只变更失败不堵后面的(尾巴吞掉失败,错原样上抛给它自己的调用方)。操作体里不得再调 `serialized`(会排在自己后面)。
15
+ */
16
+ private serialized;
8
17
  put(rec: TaskAttachmentRecord & {
9
18
  content: Uint8Array;
10
19
  }): Promise<void>;
11
20
  get(owner: string, id: string): Promise<TaskAttachmentRecord | null>;
12
21
  getContent(owner: string, id: string): Promise<Uint8Array | null>;
13
22
  private persistMeta;
14
- bind(owner: string, ids: string[], sessionId: string, boundAtMs: number): Promise<number>;
23
+ bind(owner: string, ids: readonly string[], sessionId: string, boundAtMs: number): Promise<AttachmentStoreBindOutcome>;
15
24
  listBySession(sessionId: string): Promise<TaskAttachmentRecord[]>;
25
+ /** 删一行(meta + bytes + 内存索引)。只在 `serialized` 的操作体里调用。 */
16
26
  private removeRow;
17
27
  delete(owner: string, id: string): Promise<boolean>;
18
28
  deleteBySession(sessionId: string): Promise<number>;
@@ -1,6 +1,6 @@
1
1
  import { promises as fsp } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { TaskAttachmentRecordSchema } from "./task-attachment-store.js";
3
+ import { bindRowsInProcess, TaskAttachmentRecordSchema } from "./task-attachment-store.js";
4
4
  import { createZodColumnReader, decodeJsonColumn } from "./sql-json-column.js";
5
5
  const ID_RE = /^[0-9a-f-]{16,64}$/i;
6
6
  const readAttachmentMeta = createZodColumnReader(TaskAttachmentRecordSchema);
@@ -8,6 +8,7 @@ export class LocalTaskAttachmentStore {
8
8
  dir;
9
9
  metas;
10
10
  hydration;
11
+ mutationTail = Promise.resolve();
11
12
  constructor(rootDir) {
12
13
  this.dir = join(rootDir, "attachments");
13
14
  }
@@ -37,17 +38,24 @@ export class LocalTaskAttachmentStore {
37
38
  })();
38
39
  return this.hydration;
39
40
  }
40
- async put(rec) {
41
- const metas = await this.hydrate();
42
- await fsp.mkdir(this.dir, { recursive: true });
43
- const { content, ...meta } = rec;
44
- const binTmp = join(this.dir, `${rec.id}.bin.tmp`);
45
- const metaTmp = join(this.dir, `${rec.id}.json.tmp`);
46
- await fsp.writeFile(binTmp, Buffer.from(content));
47
- await fsp.rename(binTmp, join(this.dir, `${rec.id}.bin`));
48
- await fsp.writeFile(metaTmp, JSON.stringify(meta));
49
- await fsp.rename(metaTmp, join(this.dir, `${rec.id}.json`));
50
- metas.set(rec.id, { ...meta });
41
+ serialized(op) {
42
+ const run = this.mutationTail.then(op);
43
+ this.mutationTail = run.then(() => undefined, () => undefined);
44
+ return run;
45
+ }
46
+ put(rec) {
47
+ return this.serialized(async () => {
48
+ const metas = await this.hydrate();
49
+ await fsp.mkdir(this.dir, { recursive: true });
50
+ const { content, ...meta } = rec;
51
+ const binTmp = join(this.dir, `${rec.id}.bin.tmp`);
52
+ const metaTmp = join(this.dir, `${rec.id}.json.tmp`);
53
+ await fsp.writeFile(binTmp, Buffer.from(content));
54
+ await fsp.rename(binTmp, join(this.dir, `${rec.id}.bin`));
55
+ await fsp.writeFile(metaTmp, JSON.stringify(meta));
56
+ await fsp.rename(metaTmp, join(this.dir, `${rec.id}.json`));
57
+ metas.set(rec.id, { ...meta });
58
+ });
51
59
  }
52
60
  async get(owner, id) {
53
61
  const m = (await this.hydrate()).get(id);
@@ -69,19 +77,29 @@ export class LocalTaskAttachmentStore {
69
77
  await fsp.writeFile(tmp, JSON.stringify(m));
70
78
  await fsp.rename(tmp, join(this.dir, `${m.id}.json`));
71
79
  }
72
- async bind(owner, ids, sessionId, boundAtMs) {
73
- const metas = await this.hydrate();
74
- let bound = 0;
75
- for (const id of ids) {
76
- const m = metas.get(id);
77
- if (!m || m.owner !== owner)
78
- continue;
79
- m.sessionId = sessionId;
80
- m.boundAtMs = boundAtMs;
81
- await this.persistMeta(m);
82
- bound++;
83
- }
84
- return bound;
80
+ bind(owner, ids, sessionId, boundAtMs) {
81
+ return this.serialized(async () => {
82
+ const metas = await this.hydrate();
83
+ const draft = new Map(metas);
84
+ for (const id of new Set(ids)) {
85
+ const row = metas.get(id);
86
+ if (row !== undefined)
87
+ draft.set(id, { ...row });
88
+ }
89
+ const { outcome, claimed } = bindRowsInProcess(draft, owner, ids, sessionId, boundAtMs);
90
+ const landed = [];
91
+ try {
92
+ for (const m of claimed) {
93
+ await this.persistMeta(m);
94
+ landed.push(m);
95
+ }
96
+ }
97
+ finally {
98
+ for (const m of landed)
99
+ metas.set(m.id, m);
100
+ }
101
+ return outcome;
102
+ });
85
103
  }
86
104
  async listBySession(sessionId) {
87
105
  const metas = await this.hydrate();
@@ -95,26 +113,32 @@ export class LocalTaskAttachmentStore {
95
113
  await fsp.rm(join(this.dir, `${id}.bin`), { force: true });
96
114
  this.metas?.delete(id);
97
115
  }
98
- async delete(owner, id) {
99
- const m = (await this.hydrate()).get(id);
100
- if (!m || m.owner !== owner)
101
- return false;
102
- await this.removeRow(id);
103
- return true;
116
+ delete(owner, id) {
117
+ return this.serialized(async () => {
118
+ const m = (await this.hydrate()).get(id);
119
+ if (!m || m.owner !== owner)
120
+ return false;
121
+ await this.removeRow(id);
122
+ return true;
123
+ });
104
124
  }
105
- async deleteBySession(sessionId) {
106
- const metas = await this.hydrate();
107
- const hit = [...metas.values()].filter((m) => m.sessionId === sessionId);
108
- for (const m of hit)
109
- await this.removeRow(m.id);
110
- return hit.length;
125
+ deleteBySession(sessionId) {
126
+ return this.serialized(async () => {
127
+ const metas = await this.hydrate();
128
+ const hit = [...metas.values()].filter((m) => m.sessionId === sessionId);
129
+ for (const m of hit)
130
+ await this.removeRow(m.id);
131
+ return hit.length;
132
+ });
111
133
  }
112
- async reapUnbound(olderThanMs) {
113
- const metas = await this.hydrate();
114
- const hit = [...metas.values()].filter((m) => m.sessionId === undefined && m.createdAtMs < olderThanMs);
115
- for (const m of hit)
116
- await this.removeRow(m.id);
117
- return hit.length;
134
+ reapUnbound(olderThanMs) {
135
+ return this.serialized(async () => {
136
+ const metas = await this.hydrate();
137
+ const hit = [...metas.values()].filter((m) => m.sessionId === undefined && m.createdAtMs < olderThanMs);
138
+ for (const m of hit)
139
+ await this.removeRow(m.id);
140
+ return hit.length;
141
+ });
118
142
  }
119
143
  }
120
144
  //# sourceMappingURL=local-task-attachment-store.js.map
@@ -1,11 +1,8 @@
1
1
  /**
2
- * 信箱**收件人生命周期面**([ref])—— core `MailboxStore` 契约里被点名、但机制**刻意不由 core 命名**的
3
- * 那一半:「这个收件人正在被部署删掉」。
4
- *
5
- * core 的原话(`core/store-contracts/mailbox-store-contract.ts` 的 `MailboxTombstonedRecipientContractHooks`
6
- * 逐字):「Put `(scope, handle)` into the deployment's PRE-DELETE state — whatever that is for this backend
7
- * (a cascade marking the session row, a `deleting` column, a tombstone table). Core does not name the
8
- * mechanism, only what `append` must then do.」 ⇒ 本文件就是 server 侧那个 "whatever"。
2
+ * 信箱**收件人生命周期面**([ref])—— 「这个收件人正在被部署删掉」。core 7.61.0 起它是 `MailboxStore` 契约里的一对可选成员
3
+ * (`retireRecipient` / `listRetiredRecipients`,一个能力:两个都在或都不在),经 core 的唯一判官 `mailboxRecipientLifecycleOf` 读
4
+ * (缺一半 ⇒ 判官拒)。本仓不另立型:{@link MailboxRecipientLifecycle} 就是那只判官答的形,{@link recipientLifecycleOf} 是本仓唯一的读法 ——
5
+ * 店带那一对 ⇒ 判官的答;不带 ⇒ {@link createDropOnlyRecipientLifecycle}(见文末「缺席形」)。
9
6
  *
10
7
  * ## 两个动词,各答一个问题
11
8
  *
@@ -50,30 +47,11 @@
50
47
  * 后端选择点(`boot/stores.ts` 的 `mailbox_store_enabled` 行)逐次落 `recipientTombstones` 读数,
51
48
  * 披露在 `docs/DEPLOY-PREREQS.md`。方向上它也不放宽任何东西 —— 两种形都**不收**给已删会话的信。
52
49
  */
53
- import type { MailboxStore } from "@sema-agent/core";
54
- /** 一条墓碑(= 一个已退役的收件人)。 */
55
- export interface MailboxRecipientTombstone {
56
- /** 盒句柄(会话盒 = `session.<小写 id>`)。 */
57
- readonly handle: string;
58
- /** 退役时刻(epoch ms)——目录据此铸 `diedAt`。 */
59
- readonly retiredAt: number;
60
- /** 退役前的显示名(会话的删前 `title`);缺席 = 当时没有可用的名字。 */
61
- readonly label?: string;
62
- }
63
- export interface MailboxRecipientLifecycle {
64
- /**
65
- * 把 `(scope, handle)` 置入**预删除态**:此后 `append` 一律以 `MAILBOX_TOMBSTONED_RECIPIENT_CODE` 拒。
66
- * **只打标**——不删消息、不动租约、不碰盒行的高水位(理由 = core T2 试剂盒的两格副作用判据,见模块头)。
67
- * 幂等(重复 retire 只更新时刻/名字)。
68
- *
69
- * @returns 是否真的落了一张耐久墓碑。`false` 有两种,都是「没落」:① 本后端没有预删除态,箱已被直接 `drop`
70
- * (拒的方向不变,退化的只有拒绝措辞与「正在删除中」那一行的可见性);② 这只键收件箱的键判官不收(SQL 两孪生:没有箱可打标,
71
- * 这只键的 `append` 本来就以判官那一句拒,不带墓碑码)。
72
- */
73
- retireRecipient(scope: string, handle: string, at: number, label?: string): Promise<boolean>;
74
- /** 本 scope 下句柄以 `handlePrefix` 开头的墓碑。无预删除态的后端恒返回空。 */
75
- listRetiredRecipients(scope: string, handlePrefix: string): Promise<readonly MailboxRecipientTombstone[]>;
76
- }
50
+ import { mailboxRecipientLifecycleOf, type MailboxStore } from "@sema-agent/core";
51
+ /** 收件人生命周期面 = core 判官 `mailboxRecipientLifecycleOf` 答的那一对(本仓零份第二型;墓碑行型直接用 core 的 `MailboxRecipientTombstone`)。 */
52
+ export type MailboxRecipientLifecycle = NonNullable<ReturnType<typeof mailboxRecipientLifecycleOf>>;
53
+ /** 一只店的收件人生命周期面 —— 本仓唯一的读法:店带那一对 ⇒ core 判官的答(缺一半判官就拒,`config.invalid_argument`);不带 ⇒ drop-only 形。 */
54
+ export declare function recipientLifecycleOf(store: MailboxStore): MailboxRecipientLifecycle;
77
55
  /**
78
56
  * 看不见收件人生命周期的后端的诚实形:retire = 直接把箱 `drop` 掉(**不**打标,因为没有可打标的地方),
79
57
  * 墓碑清单恒空。
@@ -1,3 +1,7 @@
1
+ import { mailboxRecipientLifecycleOf } from "@sema-agent/core";
2
+ export function recipientLifecycleOf(store) {
3
+ return mailboxRecipientLifecycleOf(store) ?? createDropOnlyRecipientLifecycle(store);
4
+ }
1
5
  export function createDropOnlyRecipientLifecycle(store) {
2
6
  return {
3
7
  retireRecipient: async (scope, handle) => {
@@ -1,8 +1,7 @@
1
1
  import type { Pool as MySqlPool } from "mysql2/promise";
2
2
  import type { Pool as PgPool } from "pg";
3
- import type { MailboxAckResult, MailboxAppendMessage, MailboxDecision, MailboxDecisionOutcome, MailboxLease, MailboxStore } from "@sema-agent/core";
3
+ import type { MailboxAckResult, MailboxAppendMessage, MailboxDecision, MailboxDecisionOutcome, MailboxLease, MailboxRecipientTombstone, MailboxStore } from "@sema-agent/core";
4
4
  import { type IndexSpec } from "./ensure-index.js";
5
- import type { MailboxRecipientLifecycle, MailboxRecipientTombstone } from "./mailbox-recipient-lifecycle.js";
6
5
  import type { SqlDialect } from "./sql-driver.js";
7
6
  export declare const MAILBOX_TABLE = "mailbox";
8
7
  export declare const MAILBOX_MSG_TABLE = "mailbox_message";
@@ -12,6 +11,11 @@ export declare const MAILBOX_MSG_TABLE = "mailbox_message";
12
11
  * —— `mailbox` 行是**盒**事实(next_seq / lease),墓碑是**收件人**事实,两者的生命周期本来就不同
13
12
  * (`drop` 同时终结两者 —— 墓碑随箱亡,理由全文见 `mailbox-recipient-lifecycle.ts` 模块头)。 */
14
13
  export declare const MAILBOX_TOMBSTONE_TABLE = "mailbox_tombstone";
14
+ /** 盒的**已收窗**(core 7.61.0):`ack` 删掉的带身份记录各留一行 `{ record_id, seq, digests }`,每盒恰留按 `seq` 最新的 `MAILBOX_CONSUMED_ID_WINDOW` 行;
15
+ * `append` 在盒行锁之内连同持有行一起交引擎的 `judgeMailboxAppendById` 判(同记录 ⇒ 答它当时的 `seq`、零写;不同 ⇒ `mailbox.duplicate_record_id`)。
16
+ * 是**盒**事实(与 `next_seq` 同生命周期):`drop` 随盒删、`reap` 留着(它清掉的东西从没被收过)。新表而不是 `mailbox` 加列,理由同墓碑表(存量库零运维动作)。
17
+ * `digests` = 引擎 `mailboxReplayDigests` 的四面摘要 JSON(只读那一只函数,不另算)。 */
18
+ export declare const MAILBOX_CONSUMED_TABLE = "mailbox_consumed";
15
19
  /**
16
20
  * 身份键(`scope` / `handle` / lease `owner`)的 UTF-8 字节上界 = 键列宽(TiDB `VARBINARY(190)`;PG 列按字符,本判官在两方言上都按字节拒)。
17
21
  */
@@ -35,10 +39,10 @@ export type MailboxKeyColumn = "scope" | "handle" | "owner";
35
39
  /** 库里读回的一对键列判官拒不拒(与入口同一只判官;字节先无损读成串,读不成 = 不良构)。`reap` 的候选句柄与一次性迁移 M27 都按它判。 */
36
40
  export declare function storedMailboxKeyless(scopeKey: unknown, handle: unknown): boolean;
37
41
  /**
38
- * 收件箱表族:三张表的键都是 `(scope_key, handle)`。次序 = 锁序(盒行 → 消息行 → 墓碑行;盒行先删的理由见 `drop`)。
42
+ * 收件箱表族:四张表的键都是 `(scope_key, handle)`。次序 = 锁序(盒行 → 消息行 → 已收窗行 → 墓碑行;盒行先删的理由见 `drop`)。
39
43
  * 「丢掉一只箱」= 按这个次序逐表按键删 —— `drop` 与一次性迁移 M27 是同一组语句({@link mailboxKeyDeleteSql})。
40
44
  */
41
- export declare const MAILBOX_KEYED_TABLES: readonly ["mailbox", "mailbox_message", "mailbox_tombstone"];
45
+ export declare const MAILBOX_KEYED_TABLES: readonly ["mailbox", "mailbox_message", "mailbox_consumed", "mailbox_tombstone"];
42
46
  export type MailboxKeyedTable = (typeof MAILBOX_KEYED_TABLES)[number];
43
47
  /** 按键删收件箱表族的一张表(两方言;参数 = [scope_key, handle])。 */
44
48
  export declare function mailboxKeyDeleteSql(dialect: SqlDialect, table: MailboxKeyedTable): string;
@@ -55,7 +59,7 @@ export declare function ensureTiDBMailboxSchema(pool: MySqlPool): Promise<void>;
55
59
  /** [ref]:本 store 的索引**声明**(两方言共用一份)。PG 侧由下面的 `ensurePgMailboxSchema` 应用,MySQL 侧由 `tidb-pool.ts` 的中央 `ensureSchema` 应用(那里内联 `KEY` 已在 `CREATE TABLE` 里 ⇒ 新建库探到即零 DDL,存量库缺谁补谁)。加索引以外的 schema 变更仍归运维,见 `plugins/ensure-index.ts` 头注。 */
56
60
  export declare const MAILBOX_INDEXES: readonly IndexSpec[];
57
61
  export declare function ensurePgMailboxSchema(q: (text: string, params?: unknown[]) => Promise<unknown>): Promise<void>;
58
- export declare class TiDBMailboxStore implements MailboxStore, MailboxRecipientLifecycle {
62
+ export declare class TiDBMailboxStore implements MailboxStore {
59
63
  private readonly pool;
60
64
  private readonly logger?;
61
65
  /** [ref]([ref] §1.2⑥):跨进程安全**显式**声明 —— core 的 `mailboxCrossProcessMountVerdict` 只对字面 `true` 放行
@@ -82,15 +86,15 @@ export declare class TiDBMailboxStore implements MailboxStore, MailboxRecipientL
82
86
  reap(scope: string, now: number, opts?: {
83
87
  maxAgeMs?: number;
84
88
  }): Promise<number>;
85
- /** 见 {@link MailboxRecipientLifecycle.retireRecipient}。**只打标**:不删消息、不动租约、不碰 next_seq。
89
+ /** 见 core `MailboxStore.retireRecipient`。**只打标**:不删消息、不动租约、不碰 next_seq。
86
90
  * 锁序 = 盒行先(与 append / claim / ack / drop / reap 五面统一 —— ABBA 死锁形不许在这里重开),
87
91
  * 于是 retire 与并发 append 在同一把行锁上串行:要么 append 先拿到 seq、要么它读到墓碑被拒,没有中间态。 */
88
92
  retireRecipient(scope: string, handle: string, at: number, label?: string): Promise<boolean>;
89
- /** 见 {@link MailboxRecipientLifecycle.listRetiredRecipients}。前缀查带 `ESCAPE`(句柄是开集串,
93
+ /** 见 core `MailboxStore.listRetiredRecipients`。前缀查带 `ESCAPE`(句柄是开集串,
90
94
  * `_`/`%` 若被当通配会把**别的**收件人一起列出来 —— 与本仓 `?q=` 面同一条 escapeLike 纪律)。 */
91
95
  listRetiredRecipients(scope: string, handlePrefix: string): Promise<readonly MailboxRecipientTombstone[]>;
92
96
  }
93
- export declare class PgMailboxStore implements MailboxStore, MailboxRecipientLifecycle {
97
+ export declare class PgMailboxStore implements MailboxStore {
94
98
  private readonly pool;
95
99
  private readonly logger?;
96
100
  /** [ref] 跨进程安全显式声明(TiDB 孪生同注:事务 + 盒行 FOR UPDATE 锁序是真值前提;终验 = test/mailbox-cross-process-kit.test.ts pg 腿)。 */