@sema-agent/server 7.151.0 → 7.152.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. package/MIGRATION.md +266 -0
  2. package/README.md +15 -3
  3. package/README.zh-CN.md +10 -2
  4. package/USAGE.md +93 -64
  5. package/deploy/sema-up/README.md +5 -4
  6. package/deploy/sema-up/cluster-up.sh +6 -6
  7. package/deploy/sema-up/kube-up.sh +5 -5
  8. package/deploy/sema-up/lib/flagshape.sh +36 -8
  9. package/deploy/sema-up/machines.example.yaml +3 -1
  10. package/deploy/sema-up/sema-up.sh +22 -16
  11. package/dist/approval-ask-audit-store.d.ts +1 -1
  12. package/dist/approval-ask-machine.d.ts +4 -10
  13. package/dist/approval-ask-retention.d.ts +1 -1
  14. package/dist/approval-card.d.ts +10 -12
  15. package/dist/approval-gate-currency.d.ts +8 -8
  16. package/dist/approval-gate-currency.js +3 -4
  17. package/dist/approval-hmac.d.ts +17 -1
  18. package/dist/approval-hmac.js +7 -1
  19. package/dist/approval-queue-kind.d.ts +1 -1
  20. package/dist/approval.d.ts +2 -2
  21. package/dist/approval.js +2 -2
  22. package/dist/bind-host.d.ts +1 -3
  23. package/dist/bind-host.js +2 -3
  24. package/dist/boot/coordinators.d.ts +1 -1
  25. package/dist/boot/coordinators.js +9 -10
  26. package/dist/boot/device-lane.js +2 -0
  27. package/dist/boot/execution-env.d.ts +1 -0
  28. package/dist/boot/execution-env.js +31 -5
  29. package/dist/boot/leader.d.ts +31 -30
  30. package/dist/boot/leader.js +38 -28
  31. package/dist/boot/leg-path-adjudication.d.ts +40 -0
  32. package/dist/boot/leg-path-adjudication.js +18 -0
  33. package/dist/boot/parked-revive-gate.js +3 -15
  34. package/dist/boot/reapers.d.ts +1 -1
  35. package/dist/boot/reapers.js +1 -1
  36. package/dist/boot/resolve-spec.js +12 -26
  37. package/dist/boot/runner-deps.d.ts +39 -35
  38. package/dist/boot/runner-deps.js +92 -89
  39. package/dist/boot/shutdown.d.ts +6 -0
  40. package/dist/boot/shutdown.js +10 -4
  41. package/dist/boot/stage-02-web-admin-pull.js +4 -5
  42. package/dist/boot/stage-05-execution-env.js +2 -1
  43. package/dist/boot/stage-06-runners.d.ts +2 -0
  44. package/dist/boot/stage-06-runners.js +10 -4
  45. package/dist/boot/stage-07-capability-layer.d.ts +1 -0
  46. package/dist/boot/stage-07-capability-layer.js +1 -1
  47. package/dist/boot/stage-08-reapers.d.ts +1 -0
  48. package/dist/boot/stage-09-leader.d.ts +1 -0
  49. package/dist/boot/stage-09-leader.js +2 -2
  50. package/dist/boot/stage-10-http-server.d.ts +8 -0
  51. package/dist/boot/stage-10-http-server.js +11 -15
  52. package/dist/boot/stores.js +7 -4
  53. package/dist/boot/web-admin.js +2 -7
  54. package/dist/capabilities/approvals-push.d.ts +3 -3
  55. package/dist/capabilities/scenarios.d.ts +28 -13
  56. package/dist/capabilities/scenarios.js +2 -2
  57. package/dist/capability-facts.d.ts +22 -20
  58. package/dist/capability-facts.js +18 -34
  59. package/dist/card-rule-offers.d.ts +32 -0
  60. package/dist/card-rule-offers.js +130 -0
  61. package/dist/config-catalog.js +12 -11
  62. package/dist/config-dir-trust.js +4 -2
  63. package/dist/config-invariants.d.ts +18 -7
  64. package/dist/config-invariants.js +51 -8
  65. package/dist/config-lkg.d.ts +5 -19
  66. package/dist/config-lkg.js +8 -62
  67. package/dist/config-provider.d.ts +1 -1
  68. package/dist/config-root-migration.d.ts +2 -2
  69. package/dist/config-types.d.ts +28 -38
  70. package/dist/config.d.ts +7 -5
  71. package/dist/config.js +55 -16
  72. package/dist/control-socket.d.ts +51 -0
  73. package/dist/control-socket.js +115 -0
  74. package/dist/deployment-governance.d.ts +2 -1
  75. package/dist/device-ws-hub.d.ts +7 -0
  76. package/dist/device-ws-hub.js +7 -1
  77. package/dist/elicitation.js +2 -2
  78. package/dist/entry-problems.d.ts +40 -3
  79. package/dist/entry-problems.js +3 -1
  80. package/dist/execution-env-refusal.d.ts +8 -2
  81. package/dist/execution-env-refusal.js +3 -0
  82. package/dist/fleet/engine-signal.d.ts +12 -29
  83. package/dist/fleet/engine-signal.js +1 -7
  84. package/dist/fleet-client.js +2 -5
  85. package/dist/gate-settlement.d.ts +1 -8
  86. package/dist/gate-settlement.js +0 -4
  87. package/dist/history-anchor.js +1 -1
  88. package/dist/hitl-delivery.d.ts +2 -3
  89. package/dist/hitl-delivery.js +0 -2
  90. package/dist/hooks/hook-llm.js +4 -2
  91. package/dist/hooks/hook-runner.d.ts +3 -2
  92. package/dist/hooks/hook-runner.js +16 -1
  93. package/dist/host-decision.d.ts +11 -11
  94. package/dist/http/active-run-conflict.d.ts +35 -2
  95. package/dist/http/active-run-conflict.js +48 -19
  96. package/dist/http/approval-sweeps.d.ts +1 -1
  97. package/dist/http/approval-sweeps.js +5 -2
  98. package/dist/http/checkpoint-ctx.d.ts +2 -0
  99. package/dist/http/checkpoint-ctx.js +1 -0
  100. package/dist/http/dispatch.d.ts +6 -2
  101. package/dist/http/dispatch.js +25 -5
  102. package/dist/http/durable-run-leg.js +0 -1
  103. package/dist/http/health-reader.d.ts +16 -9
  104. package/dist/http/health-reader.js +2 -1
  105. package/dist/http/health-self-report.js +1 -1
  106. package/dist/http/owner-access.d.ts +2 -3
  107. package/dist/http/owner-access.js +3 -4
  108. package/dist/http/principal-gate.d.ts +49 -21
  109. package/dist/http/principal-gate.js +61 -11
  110. package/dist/http/request-channel.d.ts +23 -0
  111. package/dist/http/request-channel.js +9 -0
  112. package/dist/http/request-guards.js +17 -2
  113. package/dist/http/resume-ctx-read.js +20 -3
  114. package/dist/http/resume-legs.d.ts +2 -2
  115. package/dist/http/resume-legs.js +111 -41
  116. package/dist/http/route-ctx.d.ts +73 -7
  117. package/dist/http/route-ctx.js +17 -0
  118. package/dist/http/route-table.d.ts +4 -0
  119. package/dist/http/route-table.js +4 -0
  120. package/dist/http/routes/admin-config-refresh.js +3 -3
  121. package/dist/http/routes/admin-drain.d.ts +3 -0
  122. package/dist/http/routes/admin-drain.js +7 -7
  123. package/dist/http/routes/admin-memory-optout.js +3 -3
  124. package/dist/http/routes/adoption.js +3 -5
  125. package/dist/http/routes/approvals-assistant.d.ts +2 -1
  126. package/dist/http/routes/approvals-assistant.js +95 -48
  127. package/dist/http/routes/capabilities.d.ts +4 -0
  128. package/dist/http/routes/capabilities.js +30 -5
  129. package/dist/http/routes/config-catalog.js +2 -2
  130. package/dist/http/routes/devices.js +1 -1
  131. package/dist/http/routes/diagnostics.d.ts +3 -3
  132. package/dist/http/routes/diagnostics.js +19 -7
  133. package/dist/http/routes/images.js +10 -10
  134. package/dist/http/routes/memory-bundle.js +3 -3
  135. package/dist/http/routes/memory-compliance.js +3 -3
  136. package/dist/http/routes/memory-consolidation.js +2 -2
  137. package/dist/http/routes/memory-origin.js +3 -3
  138. package/dist/http/routes/memory-policy.js +2 -2
  139. package/dist/http/routes/observability.js +3 -3
  140. package/dist/http/routes/retention-ops.js +3 -3
  141. package/dist/http/routes/rules.js +5 -5
  142. package/dist/http/routes/run-permission-mode.d.ts +2 -1
  143. package/dist/http/routes/run-permission-mode.js +2 -2
  144. package/dist/http/routes/runs.d.ts +4 -9
  145. package/dist/http/routes/runs.js +73 -33
  146. package/dist/http/routes/session-sync.d.ts +18 -6
  147. package/dist/http/routes/session-sync.js +38 -36
  148. package/dist/http/routes/sessions.js +20 -9
  149. package/dist/http/routes/tasks.js +28 -37
  150. package/dist/http/routes/workflows.js +1 -1
  151. package/dist/http/server.d.ts +9 -3
  152. package/dist/http/server.js +15 -3
  153. package/dist/http/submit-ctx.d.ts +1 -1
  154. package/dist/http/submit-ctx.js +2 -0
  155. package/dist/human-facing-args.d.ts +33 -0
  156. package/dist/human-facing-args.js +33 -0
  157. package/dist/index.d.ts +1 -1
  158. package/dist/k8s-api-credentials.d.ts +29 -0
  159. package/dist/k8s-api-credentials.js +25 -0
  160. package/dist/lane-home-probe.d.ts +1 -1
  161. package/dist/lane-home-probe.js +2 -1
  162. package/dist/leader/diffup.d.ts +19 -0
  163. package/dist/leader/diffup.js +7 -0
  164. package/dist/leader/leader.d.ts +114 -10
  165. package/dist/leader/leader.js +69 -5
  166. package/dist/leader/repair-wire.js +2 -2
  167. package/dist/leader/run-entry.d.ts +2 -1
  168. package/dist/leader/run-entry.js +1 -1
  169. package/dist/leader/wire.d.ts +42 -132
  170. package/dist/leader/wire.js +81 -67
  171. package/dist/memory-scope.d.ts +20 -9
  172. package/dist/memory-scope.js +15 -3
  173. package/dist/model-entry-headers.d.ts +9 -10
  174. package/dist/model-entry-headers.js +0 -4
  175. package/dist/model-entry-refusal.d.ts +7 -4
  176. package/dist/model-entry-refusal.js +11 -5
  177. package/dist/model-plane-face.d.ts +1 -1
  178. package/dist/model-plane-face.js +3 -1
  179. package/dist/model-route-endpoint.d.ts +13 -7
  180. package/dist/model-route-endpoint.js +14 -11
  181. package/dist/model-select.d.ts +22 -0
  182. package/dist/model-select.js +9 -0
  183. package/dist/model-unreachable-notice.d.ts +11 -0
  184. package/dist/model-unreachable-notice.js +4 -4
  185. package/dist/object-store-buckets.d.ts +640 -6
  186. package/dist/object-store-buckets.js +166 -0
  187. package/dist/observability/fail-open.d.ts +20 -16
  188. package/dist/observability/fail-open.js +20 -16
  189. package/dist/observability/logger.js +3 -1
  190. package/dist/operator-roster.d.ts +68 -0
  191. package/dist/operator-roster.js +32 -0
  192. package/dist/orchestration/workflow-park-decision.d.ts +1 -1
  193. package/dist/outbound-dispatcher.d.ts +71 -8
  194. package/dist/outbound-dispatcher.js +48 -7
  195. package/dist/owner-faces.d.ts +1 -1
  196. package/dist/parked-decide.d.ts +2 -2
  197. package/dist/permission-mode-admission.d.ts +59 -26
  198. package/dist/permission-mode-admission.js +37 -10
  199. package/dist/plugins/approval-ask-store-file.d.ts +4 -0
  200. package/dist/plugins/approval-ask-store-file.js +3 -0
  201. package/dist/plugins/approval-ask-store-memory.d.ts +4 -0
  202. package/dist/plugins/approval-ask-store-memory.js +7 -1
  203. package/dist/plugins/approval-ask-store-sql.d.ts +26 -2
  204. package/dist/plugins/approval-ask-store-sql.js +12 -1
  205. package/dist/plugins/blob-backend.d.ts +83 -7
  206. package/dist/plugins/blob-backend.js +57 -6
  207. package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
  208. package/dist/plugins/checkpoint-index-columns.js +3 -6
  209. package/dist/plugins/checkpoint-store-face.d.ts +119 -61
  210. package/dist/plugins/checkpoint-store-face.js +134 -55
  211. package/dist/plugins/landed-attendants.d.ts +2 -2
  212. package/dist/plugins/local-checkpoint-store.d.ts +13 -3
  213. package/dist/plugins/local-checkpoint-store.js +38 -49
  214. package/dist/plugins/one-time-migrations.d.ts +51 -21
  215. package/dist/plugins/one-time-migrations.js +67 -45
  216. package/dist/plugins/pg-pool.js +11 -9
  217. package/dist/plugins/remote-env-host.d.ts +29 -10
  218. package/dist/plugins/remote-env-host.js +99 -19
  219. package/dist/plugins/remote-env-k8s.d.ts +68 -2
  220. package/dist/plugins/remote-env-k8s.js +107 -24
  221. package/dist/plugins/replica-registration.d.ts +1 -1
  222. package/dist/plugins/replica-registration.js +1 -1
  223. package/dist/plugins/s3-presign.d.ts +23 -0
  224. package/dist/plugins/s3-presign.js +37 -3
  225. package/dist/plugins/scheduler-support.d.ts +2 -2
  226. package/dist/plugins/scheduler-support.js +0 -3
  227. package/dist/plugins/schema-indexes.js +2 -0
  228. package/dist/plugins/send-file-ledger.d.ts +2 -2
  229. package/dist/plugins/send-file-ledger.js +2 -2
  230. package/dist/plugins/send-user-file.d.ts +3 -4
  231. package/dist/plugins/send-user-file.js +56 -52
  232. package/dist/plugins/session-blob-claim-token.d.ts +15 -0
  233. package/dist/plugins/session-blob-claim-token.js +20 -0
  234. package/dist/plugins/session-blob-namespace.d.ts +46 -0
  235. package/dist/plugins/session-blob-namespace.js +116 -0
  236. package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
  237. package/dist/plugins/snapshot-bucket-presence.js +8 -2
  238. package/dist/plugins/sql-json-column.d.ts +1 -1
  239. package/dist/plugins/store-backend.d.ts +44 -2
  240. package/dist/plugins/store-backend.js +75 -53
  241. package/dist/plugins/task-attachment-store.d.ts +2 -1
  242. package/dist/plugins/task-attachment-store.js +5 -1
  243. package/dist/plugins/tidb-pool.js +19 -24
  244. package/dist/plugins/workspace-custody.d.ts +4 -3
  245. package/dist/question.d.ts +2 -1
  246. package/dist/question.js +5 -13
  247. package/dist/request-form.d.ts +6 -1
  248. package/dist/request-form.js +4 -1
  249. package/dist/rule-issue-reading.d.ts +1 -1
  250. package/dist/rules-consent.d.ts +1 -1
  251. package/dist/run-local.js +8 -9
  252. package/dist/runs.d.ts +17 -8
  253. package/dist/runs.js +15 -2
  254. package/dist/runtime-governance.d.ts +2 -2
  255. package/dist/sema-config-dir.d.ts +2 -1
  256. package/dist/session-sync.d.ts +27 -11
  257. package/dist/session-sync.js +15 -7
  258. package/dist/stores-sql/blob-index-sql.d.ts +30 -9
  259. package/dist/stores-sql/blob-index-sql.js +40 -21
  260. package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
  261. package/dist/stores-sql/checkpoint-store-sql.js +70 -146
  262. package/dist/stores-sql/file-history-store-sql.d.ts +64 -16
  263. package/dist/stores-sql/file-history-store-sql.js +100 -28
  264. package/dist/stores-sql/retention-store-sql.js +3 -9
  265. package/dist/task-settings.d.ts +6 -5
  266. package/dist/task-settings.js +3 -3
  267. package/dist/tool-approval.d.ts +342 -518
  268. package/dist/tool-approval.js +498 -1207
  269. package/dist/trace/core-keyset-guard.d.ts +1 -1
  270. package/dist/trace/ledger-events.d.ts +3 -3
  271. package/dist/trace/project.d.ts +2 -3
  272. package/dist/trace/redact.js +3 -2
  273. package/dist/trace/self-minted-wire.d.ts +287 -157
  274. package/dist/trace/self-minted-wire.js +93 -48
  275. package/dist/web-admin-client/apply-effective.js +2 -2
  276. package/dist/web-admin-client/read-warnings.d.ts +2 -2
  277. package/dist/web-admin-client/read-warnings.js +1 -1
  278. package/dist/web-admin-client/types.d.ts +1 -1
  279. package/dist/workspace-space.d.ts +10 -4
  280. package/dist/workspace-space.js +4 -1
  281. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +1 -1
  282. package/package.json +6 -2
  283. package/scripts/embed-minimal.mjs +3 -3
  284. package/wire-changes/server@7.152.0.json +900 -0
  285. package/dist/config-d-migration.d.ts +0 -37
  286. package/dist/config-d-migration.js +0 -60
@@ -1,22 +1,19 @@
1
1
  import { writeLogText } from "../observability/logger.js";
2
2
  import { z } from "zod";
3
- import { denySweepOwns, parkedApprovalCard } from "../approval-content-kind.js";
4
- import { parkRowFacts, skillCardFacts } from "../approval-card.js";
5
- import { durableRowIdentity } from "../checkpoint-identity.js";
3
+ import { denySweepOwns } from "../approval-content-kind.js";
6
4
  import { createHash } from "node:crypto";
7
5
  import { closeSync, existsSync, fsyncSync, openSync, readFileSync, readdirSync, rmSync, unlinkSync } from "node:fs";
8
6
  import { IS_WIN32 } from "./host-platform.js";
9
7
  import { join } from "node:path";
10
- import { CHECKPOINT_LIST_LIMITS, FileCheckpointStore, atomicWriteFile, checkpointDeadlinePassed, ensureDir, executionVerdict, sanitizePathComponent, } from "@sema-agent/core";
8
+ import { CHECKPOINT_LIST_LIMITS, FileCheckpointStore, judgeCheckpointRow, summarizeCheckpoint, atomicWriteFile, checkpointDeadlinePassed, ensureDir, executionVerdict, sanitizePathComponent, } from "@sema-agent/core";
11
9
  import { approvalPayloadFingerprint } from "./approval-payload-fingerprint.js";
12
- import { approvalDecisionOfWinner, boundedRuleOffers, boundedToolInput, candidateIdentityOf, DENY_SWEEP_PAGE_ROWS, isUnreadableSummaryForm, parkedLegTaskId, pendingRowPrecedes, queueRowGateKind, queueTriageOrder, readRiskDescriptorBody, TERMINAL_BACKSTOP_MS, TERMINAL_GRACE_MS, } from "./checkpoint-store-face.js";
10
+ import { approvalDecisionOfWinner, buildQueueActionFacts, buildQueueRow, candidateIdentityOf, DENY_SWEEP_PAGE_ROWS, pendingRowPrecedes, queueRowGateKind, queueTriageOrder, TERMINAL_BACKSTOP_MS, TERMINAL_GRACE_MS, } from "./checkpoint-store-face.js";
13
11
  import { quarantineUnreadableSidecar } from "./local-sidecar-quarantine.js";
14
12
  import { hostSessionOf } from "./checkpoint-index-columns.js";
15
- import { createZodColumnReader, decodeJsonColumn, foldJsonColumn, isJsonObject, readStringArrayColumn } from "./sql-json-column.js";
13
+ import { createZodColumnReader, decodeJsonColumn, foldJsonColumn, readStringArrayColumn } from "./sql-json-column.js";
16
14
  import { UNMANAGED_RETENTION } from "./retention-declaration.js";
17
15
  import { assertJsonColumnWritable, createObjectColumnReader } from "./sql-json-column.js";
18
16
  import { FENCE_LANDED } from "./store-contracts.js";
19
- import { recordFailOpen } from "../observability/fail-open.js";
20
17
  const isFiniteNumber = (v) => typeof v === "number" && Number.isFinite(v);
21
18
  function terminalAtOf(cp) {
22
19
  const createdAt = cp.createdAt;
@@ -32,16 +29,6 @@ function sweepDeadlineKey(deadline) {
32
29
  function sweepPositionPrecedes(a, b) {
33
30
  return a.deadline < b.deadline || (a.deadline === b.deadline && a.token < b.token);
34
31
  }
35
- function queueRiskDescriptorOf(gate) {
36
- const raw = isJsonObject(gate) ? gate.riskDescriptor : undefined;
37
- if (raw === undefined || raw === null)
38
- return null;
39
- const shape = readRiskDescriptorBody(raw);
40
- if (shape.problem === undefined)
41
- return shape.value;
42
- recordFailOpen("server.approvals.risk-descriptor-cell-unreadable");
43
- return null;
44
- }
45
32
  function ctxFileOf(sessionId) {
46
33
  return `${sanitizePathComponent(sessionId).slice(0, 48)}-${createHash("sha256").update(sessionId).digest("hex").slice(0, 12)}.json`;
47
34
  }
@@ -69,6 +56,7 @@ const CtxRecordSchema = z.object({
69
56
  const readCtxRecord = createZodColumnReader(CtxRecordSchema);
70
57
  const readScopeRegistry = readStringArrayColumn;
71
58
  const readSessionTokenIndex = createZodColumnReader(z.record(z.string(), z.array(z.string())));
59
+ const readCardScopeRootIndex = createZodColumnReader(z.record(z.string(), z.string()));
72
60
  function createCtxRecordReader() {
73
61
  const readPayload = createObjectColumnReader();
74
62
  return (body) => {
@@ -107,6 +95,8 @@ export class LocalCheckpointStore {
107
95
  hostTokens = new Map();
108
96
  hostOfToken = new Map();
109
97
  hostSessionsPath;
98
+ cardScopeRoots = new Map();
99
+ cardScopeRootsPath;
110
100
  opts;
111
101
  constructor(root, opts = {}) {
112
102
  this.inner = new FileCheckpointStore(root);
@@ -115,6 +105,7 @@ export class LocalCheckpointStore {
115
105
  this.scopesPath = join(root, "checkpoint-scopes.json");
116
106
  this.sessionTokensPath = join(root, "checkpoint-session-tokens.json");
117
107
  this.hostSessionsPath = join(root, "checkpoint-host-sessions.json");
108
+ this.cardScopeRootsPath = join(root, "checkpoint-card-scope-roots.json");
118
109
  const dirs = localCheckpointStoreDirsFor(root);
119
110
  this.ctxDir = dirs.ctx;
120
111
  this.tmpDir = dirs.tmp;
@@ -146,6 +137,11 @@ export class LocalCheckpointStore {
146
137
  this.indexHost(host, toks);
147
138
  }
148
139
  }
140
+ if (existsSync(this.cardScopeRootsPath)) {
141
+ for (const [tok, root] of Object.entries(decodeJsonColumn(readFileSync(this.cardScopeRootsPath, "utf8"), readCardScopeRootIndex, "checkpoint-card-scope-roots.json (the local card→rule-scope-root snapshot index)"))) {
142
+ this.cardScopeRoots.set(tok, root);
143
+ }
144
+ }
149
145
  }
150
146
  registerDurably(record, undo, persist) {
151
147
  if (!record())
@@ -188,6 +184,10 @@ export class LocalCheckpointStore {
188
184
  const host = hostSessionOf(cp);
189
185
  this.registerDurably(() => !this.scopes.has(cp.scope) && (this.scopes.add(cp.scope), true), () => this.scopes.delete(cp.scope), () => atomicWriteFile(this.tmpDir, this.scopesPath, JSON.stringify([...this.scopes])));
190
186
  this.registerDurably(() => this.indexHost(host, [token]) > 0, () => this.unindexHost(host, token), () => this.persistHostSessions());
187
+ const scopeRoot = this.opts.cardScopeRoot?.of(cp.sessionId);
188
+ if (scopeRoot !== undefined) {
189
+ this.registerDurably(() => !this.cardScopeRoots.has(token) && (this.cardScopeRoots.set(token, scopeRoot), true), () => this.cardScopeRoots.delete(token), () => atomicWriteFile(this.tmpDir, this.cardScopeRootsPath, JSON.stringify(Object.fromEntries(this.cardScopeRoots))));
190
+ }
191
191
  this.registerDurably(() => {
192
192
  if (this.sessionTokens.get(cp.sessionId)?.has(token))
193
193
  return false;
@@ -283,45 +283,31 @@ export class LocalCheckpointStore {
283
283
  }
284
284
  async listPending(scope) {
285
285
  const rows = [];
286
- for (const { token, cp, summary } of await this.pendings(scope)) {
286
+ for (const { token, cp, summary: listed } of await this.pendings(scope)) {
287
+ let summary = listed;
288
+ let reading;
289
+ try {
290
+ summary = summarizeCheckpoint(cp, () => { });
291
+ reading = { rowVerdict: summary.rowVerdict, cp, summary };
292
+ }
293
+ catch {
294
+ reading = { rowVerdict: judgeCheckpointRow(cp), cp };
295
+ }
287
296
  const gateKind = queueRowGateKind(summary.gateKind);
288
297
  if (gateKind === undefined)
289
298
  continue;
290
- const joinKey = durableRowIdentity("approvals-queue", summary.checkpointId, token);
291
299
  const host = this.hostOfToken.get(token);
292
- const taskId = parkedLegTaskId(cp.state?.rowTaskId, host === undefined ? null : ((await this.opts.getActiveTaskId?.(host)) ?? null));
293
- const createdAt = summary.createdAt !== undefined ? { createdAt: summary.createdAt } : {};
294
- const deadline = summary.deadline ?? null;
295
- if (isUnreadableSummaryForm(summary)) {
296
- rows.push({ sessionId: summary.sessionId, ...joinKey, scope: summary.scope, toolName: null, toolCallId: null, gateKind, taskId, input: null, ...createdAt, deadline, riskDescriptor: null, rowVerdict: summary.rowVerdict });
297
- continue;
298
- }
299
- const pa = cp.pendingAction;
300
- const toolCallId = pa?.toolCallId ?? null;
301
- rows.push({
300
+ const claimHolder = host === undefined ? null : ((await this.opts.getActiveTaskId?.(host)) ?? null);
301
+ const address = {
302
+ token,
302
303
  sessionId: summary.sessionId,
303
- ...joinKey,
304
304
  scope: summary.scope,
305
- toolName: pa?.toolName ?? null,
306
- toolCallId,
307
- ...(toolCallId !== null ? { boundCallId: toolCallId } : {}),
308
- ...(pa?.boundInputHash !== undefined ? { boundInputHash: pa.boundInputHash } : {}),
309
305
  gateKind,
310
- taskId,
311
- input: boundedToolInput(pa?.args),
312
- ...createdAt,
313
- deadline,
314
- riskDescriptor: queueRiskDescriptorOf(cp.gate),
315
- ...(() => {
316
- const rs = boundedRuleOffers(pa?.ruleOffers);
317
- return rs !== undefined ? { ruleOffers: rs } : {};
318
- })(),
319
- ...(pa?.hasBidiControls === true ? { hasBidiControls: true } : {}),
320
- ...((card) => (card !== undefined ? { approvalCard: card } : {}))(parkedApprovalCard(cp.gate)),
321
- ...parkRowFacts(cp.pendingAction),
322
- ...skillCardFacts(summary),
323
- rowVerdict: summary.rowVerdict,
324
- });
306
+ ...(summary.createdAt !== undefined ? { createdAt: summary.createdAt } : {}),
307
+ deadline: summary.deadline ?? null,
308
+ claimHolder,
309
+ };
310
+ rows.push(buildQueueRow(address, buildQueueActionFacts(reading)));
325
311
  }
326
312
  return rows.sort(queueTriageOrder);
327
313
  }
@@ -414,6 +400,9 @@ export class LocalCheckpointStore {
414
400
  }
415
401
  return out;
416
402
  }
403
+ async cardScopeRootOf(token) {
404
+ return this.cardScopeRoots.get(token) ?? null;
405
+ }
417
406
  async hostSessionOfCard(token) {
418
407
  const host = this.hostOfToken.get(token);
419
408
  if (host !== undefined)
@@ -26,7 +26,7 @@
26
26
  * ⇒ 换成本段:**升一次级把存量字节改完,兼容臂当场删干净**。代价是每一条在它的窗内每次启动都要跑一遍(第二次起全是
27
27
  * 零命中的空转);收益是窗关之后可以把那一条连同它的 SQL 一起删,而读腿从引入那一版起就只有**一种**读法。
28
28
  *
29
- * ## 已退役的 M1–M12 与 M14
29
+ * ## 已退役的 M1–M16
30
30
  * 退役的整树快照索引表(M1)、退役的单座 steering 列(M2)、被上游改了名的闭集词 `unresolvable` → `ancestor_marked`(M3)三条的改写、计数与读数
31
31
  * 窗关后已全部删码,登记行一并删。跳过了它们直接升的库由起服对账一族的拒启臂接住(`schema-consistency.ts` 头注「第二道对账」一节:两件退役 schema
32
32
  * 任一在场 ⇒ 拒启、点名出路;先于一切建表)—— 那一道没有窗,所以不在本文件里。本段入口({@link runSqlOneTimeMigrations})不问这一问。
@@ -68,22 +68,28 @@
68
68
  * M12(停驻行模式词读法记号的拒臂;不写库;7.150.0 删,窗 2026-11-08 关,发版日前已关)同样已删码,登记行一并删:判据、拒臂与答复、两处记号写点与 ctx 上的记号位都没有了,续跑重放不再问「行上有没有记号」。逐条写跳过了它直接升的库由谁接住:
69
69
  * ⑦ 停驻行模式词读法记号的拒臂(M12):没有响亮臂 —— 7.121.x 及以前写下、此刻仍停驻的行(把 `APPROVAL_TERMINAL_BACKSTOP_MS` 调长的部署,或跳过了带本条的版本直接升的库)体里是请求原词、没有记号;
70
70
  * 在设了 `AUTONOMY=plan` 的部署上不再被拒,由续跑口接住:重放之前体的词过**现**入口地板(`permission-mode-admission.ts` `stampReplayEntryMode`,与提交口同一只入口一步)——
71
- * `bypassPermissions` / `auto` / `dontAsk` / 无词钳成 `plan`;`default` / `acceptEdits` 与 plan 地板的出口词(`plan_review` 批准写下的词)同字、读不出是谁写的,原样重放。
72
- * 存量行上的那只记号键原样留着、无人读。出路(要那两个词也不按原词续跑)= 升级前把这些停驻的 run 决掉 / 取消,或升级窗内设 `AUTONOMY=read-only`(按段的只读围栏)。
71
+ * 这些行没有写据(体顶层模式词那一格的写者,7.152.0 起才记)⇒ 不是地板的出口写下的,每个词(含 `default` / `acceptEdits`)都照钳成 `plan`。
72
+ * 存量行上的那只记号键原样留着、无人读。出路(要按原词走完)= 升级前把这些停驻的 run 决掉 / 取消。
73
+ *
74
+ * M13(盘上 LKG 信封 formatVersion 2 → 3;不写库;7.152.0 删,窗 2026-11-09 关,发版日前已关)同样已删码,登记行一并删:`loadLkg` 读回 2 时的内存迁移(旧载体 `droppedIdentities` 搬成 `droppedCatalogEntries`、去掉 etag)与它的两只帮手都没有了。
75
+ * 逐条写跳过了它直接升的库(从 < 7.123.0 直接升到本版、中间没在 7.123.0–7.151.x 任一版起过服)由谁接住:
76
+ * ⑧ 盘上 LKG 信封 formatVersion 2 的读回迁移(M13):由既有的响亮臂接住 —— `loadLkg` 对 2 答「unknown formatVersion 2」(拒因点名版本),调用方一行 `config_lkg_unusable` + env 兜底;中心可达照拉
77
+ * (整拉,读腿铸出完整载体,新 LKG 按当期版本覆盖),断着则 env 兜底,下一份干净候选重写 —— 与回滚到 7.122.0 读 3 同一种处置。那是缓存文件、不是数据:不采纳载荷、不迁、不改写文件。
78
+ *
79
+ * M15(盘上 LKG 的载荷换代,settings-schema 10.x → 11 的形;不写库;7.152.0 删,窗 2026-11-10 关,发版日前已关)同样已删码,登记行一并删:`loadLkg` 读回时过契约的一次性迁移的那一段、读回的收据与对契约包迁移子路径的 import 都没有了。
80
+ * 逐条写跳过了它直接升的库(从 < 7.124.0 直接升到本版、中间没在 7.124.0–7.151.x 任一版起过服)由谁接住:
81
+ * ⑨ 盘上 LKG 的载荷换代(M15):由既有的响亮臂接住 —— 信封仍是 3 的 LKG(载荷是 settings-schema 10.x 的形)⇒ `loadLkg` 对 3 答「unknown formatVersion 3」,调用方一行 `config_lkg_unusable` + env 兜底;
82
+ * 中心可达照拉(整拉,新 LKG 按当期版本覆盖),断着则 env 兜底,下一份干净候选重写 —— 与回滚到 7.123.0 读 4 同一种处置。整份文件不读回(缓存、不是数据;不采纳载荷、不迁、不改写文件),
83
+ * 所以「旧键留在载荷里被下游当作缺席静默略过」这条路不存在。
84
+ *
85
+ * M16(本地 `config.d` 的起服一次性迁移;不写库;7.152.0 删,窗 2026-11-10 关,发版日前已关)同样已删码,登记行一并删:起服不再改写 `config.d` —— 接线文件、两个入口(HTTP 服务第 2 段 / `run-local`)的调用与三种迁移日志都没有了;
86
+ * 目录信任判官的文档名单(`config-dir-trust.ts` 的 `LOCAL_READER_DOCUMENTS`)本是判官自己的名单、不是迁移的,搬进了判官的文件。逐条写跳过了它直接升的库(从 < 7.124.0 直接升到本版、中间没在 7.124.0–7.151.x 任一版起过服)由谁接住:
87
+ * ⑩ 本地 `config.d` 的起服迁移(M16):由既有的、常设的契约读腿墓碑与车道合成接住 —— 目录里还带迁移前写法的文档不再被起服改写、一个字节不动:`runtime.json` 带事实 ⇒ 读腿对退役域答 `RetiredDomainError`(整份读不出);
88
+ * `models.atModelAllowlist` / `models.default` ⇒ models 域降级、rosters 整份读不出;`remote-exec.json` 的 `apiUrl` 带 `#`(SS-M7)⇒ 车道合成读它时拒启(`run-local` 退 2);同设两种钥匙的模型条目(SS-M5)⇒ 读腿能抢救就逐条丢弃那一条,没有幸存条目时 models 域降级、整份候选被拒回落 env。
89
+ * 拒句 / 告警止于今天的位 / 规则本身(settings-schema 26.0.0 删了这几步,不再点名迁移 id;它的 `migrate` 也不再改写这几形)—— 出路 = 手写到今天的位,
90
+ * 或升级前用上一个契约 major 跑一次 `npx @sema-agent/settings-schema@25 migrate <config.d 目录>`。
73
91
  *
74
92
  * ## 窗内的迁移(逐条的失败方向刻意不同)
75
- * · **M13 盘上 LKG 信封 formatVersion 2 → 3**(7.123.0)—— 不在店里(配置候选的盘上缓存):被丢目录条目收成一份载体
76
- * (`models.droppedCatalogEntries`,每条被丢的目录条目一行),7.122.0 及以前写的 2 只记了有名且启用的行、记在旧键 `droppedIdentities`。
77
- * `config-lkg.ts` `loadLkg` 读回 2 时在内存里迁一次(旧载体搬成新载体、去掉 etag ⇒ 中心可达后第一拍整拉、重铸完整载体),启动日志
78
- * `config_lkg_migrated` 一行;写盘一律写 3。规则与判形在 `config-lkg.ts` 顶注与 `migrateV2Lkg`。没有读数键(它不写库)。
79
- * · **M15 盘上 LKG 的载荷换代(settings-schema 11)**(7.124.0)—— 不在店里(与 M13 同为非店迁移):3 及更早的 LKG 载荷是 settings-schema 10.x
80
- * 的形(`models.atModelAllowlist` / `models.default` / `runtime` 域 …)。`config-lkg.ts` `loadLkg` 每次读回都过契约的一次性迁移
81
- * `migrateEffectiveSnapshot`(本仓不写任何一条改写规则;只认形、幂等),迁不动(收据 `refused`)⇒ 不读回(拒因点名迁移 id);迁过的由读回方
82
- * 按信封 formatVersion 4 写回原位,启动日志 `config_lkg_migrated` 一行(带收据)。没有读数键(它不写库)。
83
- * · **M16 本地 config.d 的一次性迁移(settings-schema 11)**(7.124.0)—— 不在店里:起服时本地配置源第一次读之前,`config-d-migration.ts`
84
- * 调契约的目录迁移 `migrateConfigDirectory`(覆盖面 = 本地读腿会读的那几份:便携域 + 退役域 `runtime`),整域终判通过才原子写回、搬空的
85
- * `runtime.json` 删;读腿不读的域文件(`hosts` / `workers` …)不碰;
86
- * 迁不动 ⇒ 一字不写、`config_dir_migration_refused` 一行。没有读数键(它不写库)。
87
93
  * · **M17 会话规则一列一文法**(7.129.0,引擎 7.51.0 [ref])—— 引擎把会话规则的 `toolDeny` / `toolAllow` 换成规则条目文法(`Bash(rm:*)` 是一条拒 `rm`
88
94
  * 的规则),退役 `commandAllow` / `commandDeny` 两只命令桶。持久面三件事,同一步做:
89
95
  * ① **列改名** `session_policy.rules` → `rule_entries`(列定义唯一属主 `session-rules-column.ts`):7.128.x 及以前的副本按整串工具名读 `rules`,
@@ -171,8 +177,8 @@
171
177
  * 改写按原文 CAS(MySQL 协议两边 `CAST(… AS BINARY)`,PG `text` 等值)+ `status = 'pending'`,第二跑零命中。**够不到的一格(如实登记)**:local 车道的停驻行在
172
178
  * 引擎自己的 File 店里(盘上格式归引擎,本仓没有合法缝改写)⇒ 那里的存量问答行照旧按「无卡」读(显示通用卡、到期 SLA 拒扫、决断口按工具名要 `answer`);
173
179
  * 那一车道的队列行门型从文档读(引擎恒写),没有可回填的列。窗 = 发布日 + 30 天 = 停驻行的终局兜底窗缺省(与 M19 同一条论证与同三类逃出窗的部署)。
174
- * · **M22 盘上 LKG 信封 formatVersion 4 → 5**(7.132.0)—— 不在店里(与 M13 / M15 同为非店迁移):中心提示层收成一种 wire 形(`{ schemaVersion: 2, artifact }`),
175
- * 4 及更早的载荷若带 prompts,那是 13.x 的两轴 wire(引擎当期不读)。`config-lkg.ts` `loadLkg` 读回 4(及迁到 4 的 2 / 3)时:载荷带 prompts ⇒ 不读回
180
+ * · **M22 盘上 LKG 信封 formatVersion 4 → 5**(7.132.0)—— 不在店里(非店迁移):中心提示层收成一种 wire 形(`{ schemaVersion: 2, artifact }`),
181
+ * 4 及更早的载荷若带 prompts,那是 13.x 的两轴 wire(引擎当期不读)。`config-lkg.ts` `loadLkg` 读回 4 时:载荷带 prompts ⇒ 不读回
176
182
  * (拒因点名版本与键);不带 ⇒ 载荷零改动读回,读回方按 5 写回原位,启动日志 `config_lkg_migrated` 一行。规则在 `config-lkg.ts` 顶注 formatVersion 5 一段与
177
183
  * `migrateV4Lkg`。没有读数键(它不写库)。
178
184
  * · **M23 存量 placed 子代行的属主**(7.133.0)—— 7.132.x 及以前两只 SQL 店建委派子代的 placed 行时属主恒 NULL,会话面的属主谓词对 NULL 放行 ⇒ 谁拿到子代的会话 id
@@ -320,7 +326,7 @@
320
326
  * 起服迁移的 local 腿(`FileApprovalAskStore.upgradeJournalEnvelope`)一次压实把整本重写成 v2。
321
327
  * **回滚**:7.141.x 对改名后的表每一条读写都响亮失败、对 v2 日志拒启 —— 回滚的唯一支持形 = 恢复升级前的备份,或手工把列改回(MIGRATION 写了语句)。
322
328
  * 读数:`askCauseColumnsChanged`(0–2 处表形改动)/ `askParkTriggersMoved`(SQL;local 恒 0)/ `askJournalRecordsUpgraded`(local;SQL 恒 0)。
323
- * · **M35 配置根上 env 模型表的决定(settings-schema SS-M11)**(7.143.0)—— 不在店里(与 M16 同为本地配置根上的起服迁移):本版起本地配置腿上,一份管模型面的
329
+ * · **M35 配置根上 env 模型表的决定(settings-schema SS-M11)**(7.143.0)—— 不在店里(本地配置根上的起服迁移):本版起本地配置腿上,一份管模型面的
324
330
  * `config.d/models.json` 在 env 模型表已声明时,只有配置根上的决定文档 `config.env-models.json` 读作 `replaced` 才被采纳(否则模型面组拒
325
331
  * `config.catalog_replaces_env_models`,`env-model-table-gate.ts`);升级前这种目录静默顶替 env 表。本条保住升级前的读法:起服、本地配置第一次读之前
326
332
  * (`config-root-migration.ts`,两个入口同调),调契约的 `migrateEnvModelsDecision` —— 先读决定与目录,再独占创建运行记录 `config.migration.SS-M11.json`
@@ -455,6 +461,13 @@
455
461
  * `background_agent.record_json` 的 `error`(`errorCode` 出了本仓词法;`summary` 里逐字含旧句的那一段同换)与 `task_event` 里 `tool_end` 卡的 `structured.errorMessage`
456
462
  * (卡 `errorCode` 出了词法)。自由文本面(父转录、卡外的 `output` 报告行、workflow 节点句)没有结构标记 —— 不改,MIGRATION 披露。键集分批读、逐行写(后台行按 `rev` CAS、照本表写律把 `rev` 抬 1 —— 拿着改写之前那一读的写者 CAS 落空、重读,不会把旧句写回;
457
463
  * 打空留给下一次起服);幂等:改过的格已是对外句。不是停-迁-起:旧副本写下的新行仍是旧句,窗内每次起服再扫。读数 `storeFaultSentencesRewritten`;local 恒 0(本地数据根上没有 SQL 驱动)。
464
+ * · **M54 退役 `checkpoint` 的展示拷贝列**(7.152.0)—— 运维队列行的动作事实(工具名、入参、风险描述、规则候选、bidi 位 ……)改为读时从续跑执行的同一份字节、同一次整行解码
465
+ * 投影(两孪生同调 `checkpoint-store-face.ts` 的 `buildQueueActionFacts`)⇒ `tool_name` / `tool_input` / `risk_descriptor` / `rule_suggestions` / `has_bidi_controls` 五列是同一事实的
466
+ * 第二份存储,再无读者、再无写者(留下的 `tool_call_id` / `bound_input_hash` / `approval_card` / `gate_kind` 有找行 / 到期谓词的读者)。任一列在 ⇒ 记起服要求 `(M54, in_force)`、
467
+ * 再一句 `ALTER TABLE checkpoint DROP COLUMN …` 删掉在场的那几列(按后置条件收敛:一列都不在);都不在 ⇒ 零动作。没有搬运:值从快照读,删列不丢信息(升级前停驻的行同样按本版读法投影)。
468
+ * 停-迁-起 `structural`(书写序 ③ 的第一形):第一笔改动就是删列 DDL,删之后更早版本副本点名这些列的每一句当场失败 —— 它的每一次停驻写(INSERT 带这些列)与每一次运维队列读。
469
+ * 这不是滚动形 ②(a):更早副本写不出的不是「旧形的一格值」,而是它的全部停驻与队列读,两版混跑不成立 ⇒ 守卫段有证据(判活窗内有不知道 M54 的持有者在跑 run)即拒启、一字节不写;
470
+ * 放行之后缺 M54 的构建起服即被准入拒(回滚形)。读数 `checkpointDisplayColumnsDropped`(本次删掉的列数,0–5);local 恒 0(LOCAL 孪生从来没有这些列)。
458
471
  *
459
472
  * ## 停-迁-起(常设,码不在本文件)
460
473
  * 登记行的 `stopThenStart` 一格是声明(围栏类 · 欠不欠 · 有证据时的拒;每一行显式写,`null` = 不声明),律、型、唯一判官、守卫段与证据读法住 `stop-then-start.ts`(常设,不带窗)。
@@ -577,6 +590,8 @@ export interface OneTimeMigrationReport {
577
590
  /** M53:本次把存量子代失败句换成对外句的格数(SQL `background_agent.record_json` 的 `error` / `summary` 一行算一格 + `task_event` 的 `tool_end` 卡 `errorMessage` 一行算一格)。
578
591
  * local 恒 0(本地数据根上没有 SQL 驱动,存量行不可能带驱动原句)。非零 = 真写了存量行。 */
579
592
  readonly storeFaultSentencesRewritten: number;
593
+ /** M54:本次从 `checkpoint` 删掉的退役展示列数(0–5:在场几列删几列)。SQL 独有;local 恒 0(LOCAL 孪生从来没有这些列)。非零 = 真改了表形。 */
594
+ readonly checkpointDisplayColumnsDropped: number;
580
595
  /** M44:本次改写了 `errorCode` 码列的 run 行数(SQL `task_run` / local `run.json`;结果投影的码 ≠ 列,或 `running` 行带码)。非零 = 真写了存量行。 */
581
596
  readonly runErrorCodeColumnRewritten: number;
582
597
  /** M45:本次改写了预览列的 run 行数(SQL `task_run` / local `run.json`;以闭集注入块开标签起头的旧形剥到不动点)。非零 = 真写了存量行。 */
@@ -723,7 +738,7 @@ export declare class OneTimeMigrationInterruptedError extends Error {
723
738
  * 规则(窗长 30 天、窗关后的第一个 minor 删码、门怎么判)在本文件头注「窗」一节,只写那一次。
724
739
  */
725
740
  export interface OneTimeMigrationWindow {
726
- /** 本文件里的条目名(头注「窗内的迁移」的 M13…)。 */
741
+ /** 本文件里的条目名(头注「窗内的迁移」的 M17…)。 */
727
742
  readonly id: string;
728
743
  /** 引入这条迁移的版本 = 第一只含其代码的发布 tag(取证:`git log -S '<该条的常量名>' -- src/plugins/one-time-migrations.ts`
729
744
  * 找引入提交 → `git tag --contains <提交> --sort=creatordate` 取最早)。 */
@@ -926,6 +941,21 @@ export type SqlOneTimeMigrationInput = ExecutionPlacementSwitchInput & LiveRunWi
926
941
  export declare function renameRetiredExecutionLaneWordsM40(db: MigrationDb, dialect: SqlDialect, receipts: {
927
942
  executionLaneWordsRenamed: number;
928
943
  }): Promise<void>;
944
+ /** M54 的拒启码(确定的拒启表态:全停之后再起才有另一个答案)。 */
945
+ export declare const CHECKPOINT_DISPLAY_COLUMNS_DROP_REFUSED_CODE = "config.checkpoint_display_columns_drop_refused";
946
+ /** M54 起服拒:退役列还在,而有停-迁-起证据(拒因闭集只有 `older_replica`)。 */
947
+ export declare class CheckpointDisplayColumnsDropRefusedError extends StoreBootRefusalError {
948
+ readonly code = "config.checkpoint_display_columns_drop_refused";
949
+ readonly reason: "older_replica";
950
+ /** `tail` = 库此刻还差的列(`describeUpgradeDriftTail`;列齐 ⇒ 空串):一次起服读全,不必补一句再试。 */
951
+ constructor(evidence: OlderReplicaEvidence, tail?: string);
952
+ }
953
+ /**
954
+ * M54(规则与理由见头注 M54 段):退役列一列都不在 ⇒ 零动作;否则(守卫段已判过证据、放行)记起服要求 `(M54, in_force)`、再**一句**删掉在场的那几列
955
+ * (两方言都收多个 `DROP COLUMN`;按后置条件收敛:一列都不在)。没有第二步:删列是本条唯一的改动,也是它的围栏(`structural`)。
956
+ * 中断 ⇒ 要求行留着(保守:缺 M54 的构建拒启),下一次起服还在的列重删。读数 = 本次删掉的列数(0–5)。导出给真库钉驱动。
957
+ */
958
+ export declare function dropCheckpointDisplayColumnsM54(db: MigrationDb, dialect: SqlDialect, receipts: MigrationReceipts): Promise<void>;
929
959
  /** M41 的拒启码(确定的拒启表态;与 `config.schema_mismatch` 同一族)。 */
930
960
  export declare const SESSION_EXT_MOVE_REFUSED_CODE = "config.session_ext_move_refused";
931
961
  /** 拒因闭集:`older_replica` = 还有列要搬而有停-迁-起证据;`copy_mismatch` = 搬完核对有一行不等(一列没删)。 */
@@ -1099,8 +1129,8 @@ export interface ParkedRowRepair {
1099
1129
  */
1100
1130
  export declare function parkedRowRepairOf(gateKindCell: unknown, gate: unknown, pendingAction: unknown): ParkedRowRepair;
1101
1131
  /**
1102
- * M21 —— 停驻行补齐引擎今天在铸点写的两格(规则、为什么、够不到的一格见头注 M21 段)。只扫 `status = 'pending'` 的候选行(`gate_kind` 为 NULL,或审批门型且
1103
- * 待决工具列是问答工具 —— 两列都是写入时从同一份文档反范式下来的;列只做预筛,判读读文档的子树),按 `token` 键集分页,每行只看一次:
1132
+ * M21 —— 停驻行补齐引擎今天在铸点写的两格(规则、为什么、够不到的一格见头注 M21 段)。只扫 `status = 'pending'` 的候选行(`gate_kind` 为 NULL,或审批门型 ——
1133
+ * 列只做预筛,「待决工具是不是问答工具」由判读读文档的子树答;7.152.0 起工具名不再落列,M54 删那一列),按 `token` 键集分页,每行只看一次:
1104
1134
  * · 回填门型:`UPDATE … SET gate_kind = ? WHERE token = ? AND status = 'pending' AND gate_kind IS NULL`(第二跑零命中);
1105
1135
  * · 续不了(列 NULL ∧ 门子树里读不出登记门型):`UPDATE … SET status = 'expired', decided_at_ms = ?`,同一守卫 —— 与到期收割同一个终态(停驻的 run 行由既有收割腿收);
1106
1136
  * · 补卡词:读整只文档一次 —— 带 `requirementsDigest`(引擎行摘要封过,`gate.approvalCard` 是它覆盖的成员)或读不懂 ⇒ 一个字节不动、计进 `parkedQuestionRowsLeftAsWritten`;
@@ -71,6 +71,7 @@ export function buildMigrationReceipts() {
71
71
  withdrawMarkWritten: 0,
72
72
  sessionDeletingSwitchMarked: 0,
73
73
  storeFaultSentencesRewritten: 0,
74
+ checkpointDisplayColumnsDropped: 0,
74
75
  runErrorCodeColumnRewritten: 0,
75
76
  runObjectivePreviewRewritten: 0,
76
77
  shellSentinelOwnersCleared: 0,
@@ -134,6 +135,7 @@ function changedAnything(r) {
134
135
  r.withdrawMarkWritten > 0 ||
135
136
  r.sessionDeletingSwitchMarked > 0 ||
136
137
  r.storeFaultSentencesRewritten > 0 ||
138
+ r.checkpointDisplayColumnsDropped > 0 ||
137
139
  r.runErrorCodeColumnRewritten > 0 ||
138
140
  r.runObjectivePreviewRewritten > 0 ||
139
141
  r.shellSentinelOwnersCleared > 0 ||
@@ -203,48 +205,9 @@ const RETIRED_SESSION_RULES_COLUMN = "rules";
203
205
  const OLD_GRAMMAR_SESSION_RULES_COLUMN = "rule_entries_old_grammar";
204
206
  const RETIRED_ASK_CAUSE_COLUMN = "denied_reason";
205
207
  const ASK_EXECUTION_LANE_COLUMN = "execution_lane";
208
+ const RETIRED_CHECKPOINT_DISPLAY_COLUMNS = ["tool_name", "tool_input", "risk_descriptor", "rule_suggestions", "has_bidi_controls"];
209
+ const CHECKPOINT_DISPLAY_COLUMNS_DROP_M54 = { kind: "drop", table: "checkpoint", columns: RETIRED_CHECKPOINT_DISPLAY_COLUMNS };
206
210
  export const ONE_TIME_MIGRATIONS = [
207
- {
208
- id: "M13",
209
- introducedIn: "7.123.0",
210
- releasedOn: "2026-10-10",
211
- removableAfter: "2026-11-09",
212
- removal: "删 `config-lkg.ts` 的 formatVersion 2 读回迁移:`migrateV2Lkg` / `migrateDroppedIdentityRow` / `RETIRED_CATALOG_COORDINATE` 与其上的窗注;`loadLkg` 的 2 臂" +
213
- "(版本判据里的 `2` 与 `formatVersion === 2 ? migrateV2Lkg(…)` 那一支 —— 2 回到「unknown formatVersion」拒)、返回型的 `migrated` 位与 JSDoc 里说它的那一行、" +
214
- "文件头注「2 读回时一次性迁移」那一句;`boot/web-admin.ts` 读 `read.migrated` 打 `config_lkg_migrated` 的那一行(这一行与 M15 / M22 的读回迁移共用 —— 三条都删完才整段删,先删 M13 时只去掉信封 2 → 3 那一路的 `migrated` 来源);契约 §A.1d " +
215
- "`droppedEntries` 一节「升级窗(如实)」那一条与 §A.1d `[config.model_refused_name_minted]` 那一条里「LKG 载体 `droppedIdentities` 读回时一次性迁移」那半句;手写 formatVersion 2 信封的测试夹具" +
216
- "(`test/config-lkg.test.ts`、`test/config-hot/batch1-version-ordinal.test.ts` 改写成 3;`test/models-dropped-entries-s1295.test.ts` 的旧 LKG 迁移格改钉 2 读回不可用)",
217
- afterRemoval: "既有响亮臂 `config_lkg_unusable`(`loadLkg` 对 2 答「unknown formatVersion 2」):2 读回 ⇒ 不可用,中心可达照拉(整拉,读腿铸出完整载体,新 LKG 按 3 覆盖)、" +
218
- "断着则 env 兜底,下一份干净候选重写 —— 与回滚到 7.122.0 读 3 同一种处置",
219
- stopThenStart: null,
220
- reportKeys: [],
221
- },
222
- {
223
- id: "M15",
224
- introducedIn: "7.124.0",
225
- releasedOn: "2026-10-11",
226
- removableAfter: "2026-11-10",
227
- removal: "删 `config-lkg.ts` 的载荷迁移:`migrateLkgPayload` 与其上的窗注、`loadLkg` 里调它的那一段(载荷照旧过 `lkgPayloadJudged`)、`LkgReadMigration.receipts`" +
228
- "(信封 2 → 3 的 M13 若已先删,`LkgReadMigration` 与 `migrated` 位一并删)、对 `@sema-agent/settings-schema/one-time-migrations` 的 import;`loadLkg` 的版本判据收成" +
229
- "只认 4(3 回到「unknown formatVersion」拒);`boot/web-admin.ts` 读回后按 4 写回的那一段;文件头注 formatVersion 4 一段里「每次读回都过迁移」那一句;" +
230
- "`test/ss11-stored-migrations.test.ts` 的 M15 组(4 原样读回那一格留)",
231
- afterRemoval: "既有响亮臂 `config_lkg_unusable`(`loadLkg` 对 3 答「unknown formatVersion 3」):旧载荷的 LKG 读回 ⇒ 不可用,中心可达照拉(整拉,新 LKG 按 4 覆盖)、" +
232
- "断着则 env 兜底 —— 与回滚到 7.123.0 读 4 同一种处置",
233
- stopThenStart: null,
234
- reportKeys: [],
235
- },
236
- {
237
- id: "M16",
238
- introducedIn: "7.124.0",
239
- releasedOn: "2026-10-11",
240
- removableAfter: "2026-11-10",
241
- removal: "删 `config-d-migration.ts` 整只文件与两个入口的调用(`boot/web-admin.ts` 建本地配置源之后、`run-local.ts` 建配置源之后各一行 + import);" +
242
- "`test/ss11-stored-migrations.test.ts` 的 M16 组;部署文档里「起服自动迁 config.d」那一句(运维仍可手跑契约命令行,直到契约删族)",
243
- afterRemoval: "契约读腿的墓碑(永久):config.d 里还带旧形的域文档 —— `runtime.json` 带事实 ⇒ `RetiredDomainError` 整份读不出;`atModelAllowlist` / `models.default` ⇒ " +
244
- "models 域降级、rosters 整份读不出 —— 拒句点名迁移 id;出路是运维手跑契约命令行(契约删族之后只剩手改)",
245
- stopThenStart: null,
246
- reportKeys: [],
247
- },
248
211
  {
249
212
  id: "M17",
250
213
  introducedIn: "7.129.0",
@@ -350,8 +313,8 @@ export const ONE_TIME_MIGRATIONS = [
350
313
  introducedIn: "7.132.0",
351
314
  releasedOn: "2026-10-18",
352
315
  removableAfter: "2026-11-17",
353
- removal: "删 `config-lkg.ts` 的 formatVersion 4 读回迁移:`migrateV4Lkg` 与其上的窗注;`loadLkg` 里调它的那一支(`formatVersion !== 5` 那一段)与版本判据里的 `4`" +
354
- "(4 回到「unknown formatVersion」拒;若 M13 / M15 仍在窗内,先删到期的那几条再删本条,版本判据收成只认 5)、`LkgReadMigration.fromFormat` 的 `4`;" +
316
+ removal: "删 `config-lkg.ts` 的 formatVersion 4 读回迁移:`migrateV4Lkg` 与其上的窗注;`loadLkg` 里调它的那一支(`formatVersion === 4` 那一段)与版本判据里的 `4`" +
317
+ "(4 回到「unknown formatVersion」拒,版本判据收成只认 5)、`LkgReadMigration` 与 `loadLkg` 返回型的 `migrated` 位(它只服务这一条)、`boot/web-admin.ts` 打 `config_lkg_migrated` 并按当期信封写回的那一段;" +
355
318
  "文件头注 formatVersion 5 一段里「4 的载荷 …」那两句;`test/center-artifact-v3-lane.test.ts` 的两格 4 读回(5 原样读回那一格留)",
356
319
  afterRemoval: "既有响亮臂 `config_lkg_unusable`(`loadLkg` 对 4 答「unknown formatVersion 4」):4 读回 ⇒ 不可用,中心可达照拉(整拉,新 LKG 按 5 覆盖)、断着则 env 兜底 —— " +
357
320
  "与回滚到 7.131.x 读 5 同一种处置",
@@ -851,6 +814,26 @@ export const ONE_TIME_MIGRATIONS = [
851
814
  stopThenStart: null,
852
815
  reportKeys: ["storeFaultSentencesRewritten"],
853
816
  },
817
+ {
818
+ id: "M54",
819
+ introducedIn: "7.152.0",
820
+ releasedOn: "2026-11-11",
821
+ removableAfter: "2026-12-11",
822
+ removal: "删本文件的 M54 步(`dropCheckpointDisplayColumnsM54` / `owesCheckpointDisplayColumnsDropM54` / `refuseCheckpointDisplayColumnsDropM54`〔本行 `stopThenStart.owedOn` / `refuse`〕/ `CheckpointDisplayColumnsDropRefusedError` / " +
823
+ "`CHECKPOINT_DISPLAY_COLUMNS_DROP_REFUSED_CODE` / `RETIRED_CHECKPOINT_DISPLAY_COLUMNS` / `CHECKPOINT_DISPLAY_COLUMNS_DROP_M54`,`migrateStepsOn` 里那一行)、报告 / 收据 / `changedAnything` / `readingFields` / `NO_SQL_MIGRATIONS` 的 " +
824
+ "`checkpointDisplayColumnsDropped`、头注 M54 段;`test/checkpoint-display-columns-drop-m54.test.ts` 与 `test/checkpoint-display-columns-drop-m54-db-integration.test.ts`(`scripts/db-integration-files.json` 里它那一行同删)。" +
825
+ "能力名单 `REPLICA_CAPABILITIES` 里的 `M54` 不删(只增)。**不随本条删**:读时投影 `buildQueueActionFacts` / `boundedToolInput` 与给人看的入参的读法 `src/human-facing-args.ts`(常设)",
826
+ afterRemoval: "跳过了带本条的版本直接升上来的库:`checkpoint` 上仍带那几列 ⇒ 起服列册对账拒启(`config.schema_mismatch`,它们是本树之外的多余列,拒句不给 ALTER —— 出路是带本条的版本);" +
827
+ "列上的值不被任何读者读。出路 = 升级时先过一次带本条的版本并起服",
828
+ stopThenStart: {
829
+ reason: "retires the checkpoint display-copy columns (the approval queue reads a pending call's tool name, input, risk descriptor, rule offers and bidi bit from the suspended checkpoint itself); after the retirement every approval an earlier replica parks and every approval-queue read it serves fails",
830
+ owedOn: owesCheckpointDisplayColumnsDropM54,
831
+ refuse: refuseCheckpointDisplayColumnsDropM54,
832
+ fence: { kind: "structural", fencedBy: CHECKPOINT_DISPLAY_COLUMNS_DROP_M54 },
833
+ },
834
+ reportKeys: ["checkpointDisplayColumnsDropped"],
835
+ shapeChanges: [CHECKPOINT_DISPLAY_COLUMNS_DROP_M54],
836
+ },
854
837
  ];
855
838
  export function migrationWindowOpen(window, today) {
856
839
  return window.removableAfter === null || today <= window.removableAfter;
@@ -900,6 +883,7 @@ export const NO_SQL_MIGRATIONS = {
900
883
  withdrawMarkWritten: 0,
901
884
  sessionDeletingSwitchMarked: 0,
902
885
  storeFaultSentencesRewritten: 0,
886
+ checkpointDisplayColumnsDropped: 0,
903
887
  askCauseColumnsChanged: 0,
904
888
  askParkTriggersMoved: 0,
905
889
  };
@@ -1028,6 +1012,7 @@ async function migrateStepsOn(db, dialect, receipts, input) {
1028
1012
  await migrateSessionRuleGrammar(db, dialect, receipts);
1029
1013
  await repairParkedRows(db, dialect, receipts);
1030
1014
  await backfillParkedApprovalCards(db, dialect, receipts);
1015
+ await dropCheckpointDisplayColumnsM54(db, dialect, receipts);
1031
1016
  if (await tableExists(db, dialect, "session_meta"))
1032
1017
  await inheritPlacedSessionOwners(db, dialect, receipts);
1033
1018
  if ((await tableExists(db, dialect, PERMISSION_RULE_TABLE)) && (await columnExists(db, dialect, PERMISSION_RULE_TABLE, "grammar"))) {
@@ -1255,6 +1240,18 @@ async function owesSessionExtMoveM41(read, dialect) {
1255
1240
  async function owesScenarioPrefixSwitchM42(read, dialect) {
1256
1241
  return !(await migrationMarked(read, dialect, SCENARIO_PREFIX_MARKER_ID));
1257
1242
  }
1243
+ async function owesCheckpointDisplayColumnsDropM54(read, dialect) {
1244
+ return (await retiredDisplayColumnsPresent({ rows: read }, dialect)).length > 0;
1245
+ }
1246
+ async function retiredDisplayColumnsPresent(db, dialect) {
1247
+ if (!(await tableExists(db, dialect, "checkpoint")))
1248
+ return [];
1249
+ const present = [];
1250
+ for (const column of RETIRED_CHECKPOINT_DISPLAY_COLUMNS)
1251
+ if (await columnExists(db, dialect, "checkpoint", column))
1252
+ present.push(column);
1253
+ return present;
1254
+ }
1258
1255
  async function owesSessionDeletingSwitchM51(read, dialect) {
1259
1256
  return !(await migrationMarked(read, dialect, SESSION_DELETING_MARK_ID));
1260
1257
  }
@@ -1378,6 +1375,30 @@ async function refuseExecutionLaneRenameM40(evidence, read, dialect) {
1378
1375
  stopThenStartAction(evidence.after) +
1379
1376
  (await describeUpgradeDriftTail(read, dialect)));
1380
1377
  }
1378
+ export const CHECKPOINT_DISPLAY_COLUMNS_DROP_REFUSED_CODE = "config.checkpoint_display_columns_drop_refused";
1379
+ export class CheckpointDisplayColumnsDropRefusedError extends StoreBootRefusalError {
1380
+ code = CHECKPOINT_DISPLAY_COLUMNS_DROP_REFUSED_CODE;
1381
+ reason = "older_replica";
1382
+ constructor(evidence, tail = "") {
1383
+ super(`${CHECKPOINT_DISPLAY_COLUMNS_DROP_REFUSED_CODE} (reason: older_replica): this version reads a suspended approval's tool name, input, risk descriptor, rule offers and ` +
1384
+ `bidi bit from the checkpoint itself and drops the checkpoint columns ${RETIRED_CHECKPOINT_DISPLAY_COLUMNS.join(", ")} on this boot (one-time migration M54), but ${olderReplicaEvidenceSentence(evidence)} — ` +
1385
+ "a replica of an earlier version may still be serving; after the drop every approval it parks and every approval-queue read it serves fails. Nothing was changed. " +
1386
+ stopThenStartAction(evidence.after) +
1387
+ tail);
1388
+ this.name = "CheckpointDisplayColumnsDropRefusedError";
1389
+ }
1390
+ }
1391
+ async function refuseCheckpointDisplayColumnsDropM54(evidence, read, dialect) {
1392
+ return new CheckpointDisplayColumnsDropRefusedError(evidence, await describeUpgradeDriftTail(read, dialect));
1393
+ }
1394
+ export async function dropCheckpointDisplayColumnsM54(db, dialect, receipts) {
1395
+ const present = await retiredDisplayColumnsPresent(db, dialect);
1396
+ if (present.length === 0)
1397
+ return;
1398
+ await recordServingRequirement(db, dialect, "M54", Date.now());
1399
+ await execUntil(db, `ALTER TABLE checkpoint ${present.map((c) => `DROP COLUMN ${c}`).join(", ")}`, async () => (await retiredDisplayColumnsPresent(db, dialect)).length === 0);
1400
+ receipts.checkpointDisplayColumnsDropped += present.length;
1401
+ }
1381
1402
  export const SESSION_EXT_MOVE_REFUSED_CODE = "config.session_ext_move_refused";
1382
1403
  export class SessionExtMoveRefusedError extends StoreBootRefusalError {
1383
1404
  reason;
@@ -2088,13 +2109,13 @@ export async function repairParkedRows(db, dialect, receipts) {
2088
2109
  const kinds = APPROVAL_GATE_KINDS;
2089
2110
  const kindSlots = kinds.map((_, i) => ph(i + 1)).join(", ");
2090
2111
  const scan = `SELECT token, session_id, gate_kind, ${jsonColumnText(dialect, "checkpoint", M21_GATE)}, ${jsonColumnText(dialect, "checkpoint", M21_PENDING_ACTION)} FROM checkpoint ` +
2091
- `WHERE status = 'pending' AND (gate_kind IS NULL OR (gate_kind IN (${kindSlots}) AND tool_name = ${ph(kinds.length + 1)})) AND token > ${ph(kinds.length + 2)} ` +
2112
+ `WHERE status = 'pending' AND (gate_kind IS NULL OR gate_kind IN (${kindSlots})) AND token > ${ph(kinds.length + 1)} ` +
2092
2113
  `ORDER BY token LIMIT ${PARKED_ROW_REPAIR_PAGE}`;
2093
2114
  const docText = jsonColumnTextExpr(dialect, "checkpoint");
2094
2115
  const encode = dialectProtocolJsonEncoder(dialect);
2095
2116
  let after = "";
2096
2117
  for (;;) {
2097
- const page = await db.rows(scan, [...kinds, ASK_USER_QUESTION_TOOL_NAME, after]);
2118
+ const page = await db.rows(scan, [...kinds, after]);
2098
2119
  for (const r of page) {
2099
2120
  const token = String(r.token);
2100
2121
  after = token;
@@ -2286,6 +2307,7 @@ function readingFields(r) {
2286
2307
  withdrawMarkWritten: r.withdrawMarkWritten,
2287
2308
  sessionDeletingSwitchMarked: r.sessionDeletingSwitchMarked,
2288
2309
  storeFaultSentencesRewritten: r.storeFaultSentencesRewritten,
2310
+ checkpointDisplayColumnsDropped: r.checkpointDisplayColumnsDropped,
2289
2311
  runErrorCodeColumnRewritten: r.runErrorCodeColumnRewritten,
2290
2312
  runObjectivePreviewRewritten: r.runObjectivePreviewRewritten,
2291
2313
  shellSentinelOwnersCleared: r.shellSentinelOwnersCleared,
@@ -30,6 +30,7 @@ import { PRINCIPAL_MAX_BYTES } from "../principal-shape.js";
30
30
  import { SKILL_EXEMPTION_CUTOFF_ID, markIfAbsentSql, migrationMarkerDdl } from "./one-time-migration-marker.js";
31
31
  import { replicaRegistrationDdl } from "./replica-registration.js";
32
32
  import { servingRequirementDdl } from "./serving-requirement.js";
33
+ import { sessionBlobNamespaceClaimDdl } from "./session-blob-claim-token.js";
33
34
  export const PG_SCHEMA_STATEMENTS = [
34
35
  `CREATE TABLE IF NOT EXISTS task_run (
35
36
  task_id VARCHAR(64) COLLATE "C" NOT NULL,
@@ -96,9 +97,7 @@ export const PG_SCHEMA_STATEMENTS = [
96
97
  session_id VARCHAR(190) COLLATE "C" NOT NULL,
97
98
  version INT NOT NULL DEFAULT 1,
98
99
  status VARCHAR(16) COLLATE "C" NOT NULL DEFAULT 'pending',
99
- tool_name VARCHAR(190) COLLATE "C",
100
100
  tool_call_id VARCHAR(190) COLLATE "C",
101
- tool_input JSONB,
102
101
  checkpoint JSONB NOT NULL,
103
102
  outcome JSONB,
104
103
  deadline BIGINT,
@@ -117,13 +116,6 @@ export const PG_SCHEMA_STATEMENTS = [
117
116
  -- (tidb-pool.ts 同两列的行内注)。PG text 无长度上限,预算由 core 侧统一执法。
118
117
  pending_steer_queue TEXT COLLATE "C",
119
118
  pending_steer_rev BIGINT NOT NULL DEFAULT 0,
120
- risk_descriptor TEXT COLLATE "C",
121
- -- rule_suggestions:语义、铸行侧的窄读/脱敏/截断纪律、以及「NULL = 无供给 ⇒ 读口省键」的完整由来见
122
- -- MySQL 孪生(tidb-pool.ts 同名列的行内注)。
123
- rule_suggestions TEXT COLLATE "C",
124
- -- has_bidi_controls(S-30① / #356②):bidi 在场位,语义与「1 或 NULL、恒不写 0」见 MySQL 孪生同名列的
125
- -- 行内注。clay 批 TINYINT(1) 归一先例:PG 侧统一 SMALLINT。
126
- has_bidi_controls SMALLINT,
127
119
  -- execution_outcome / execution_at_ms(S-160;core 7.7.0 #602):语义、两轴的分工、CAS 与冲突的
128
120
  -- 「记录物理不可变」由来见 MySQL 孪生(tidb-pool.ts 同两列的行内注)。载荷是 core 的 GateOutcome
129
121
  -- JSON ⇒ 与同表 outcome 列同取 JSONB(协议信封无损,IS NULL 谓词两方言同义)。
@@ -131,6 +123,8 @@ export const PG_SCHEMA_STATEMENTS = [
131
123
  execution_at_ms BIGINT,
132
124
  -- host_session_id:这张卡归在哪只会话上(MySQL 孪生同名同义;语义、写口与 M49 回填见 tidb-pool.ts 同名列的行内注)。
133
125
  ${CHECKPOINT_HOST_SESSION_COLUMN.pg},
126
+ -- card_scope_root:「不再询问」规则的 project root 铸卡快照(MySQL 孪生同名同义;语义见 tidb-pool.ts 同名列的行内注)。
127
+ card_scope_root VARCHAR(4096) COLLATE "C",
134
128
  PRIMARY KEY (token)
135
129
  )`,
136
130
  `CREATE TABLE IF NOT EXISTS checkpoint_ctx (
@@ -304,6 +298,13 @@ export const PG_SCHEMA_STATEMENTS = [
304
298
  -- bytes NULLABLE = the same two-backend (SQL inline / MinIO index-only) contract as snapshot_blob above.
305
299
  bytes BYTEA NULL,
306
300
  created_at TIMESTAMPTZ(3) NOT NULL
301
+ )`,
302
+ `CREATE TABLE IF NOT EXISTS file_history_blob_grant (
303
+ scope VARCHAR(64) COLLATE "C" NOT NULL,
304
+ landing_owner VARCHAR(${PRINCIPAL_MAX_BYTES}) COLLATE "C" NOT NULL,
305
+ blob_hash CHAR(64) COLLATE "C" NOT NULL,
306
+ granted_at TIMESTAMPTZ(3) NOT NULL,
307
+ PRIMARY KEY (scope, landing_owner, blob_hash)
307
308
  )`,
308
309
  `CREATE TABLE IF NOT EXISTS workflow_journal (
309
310
  run_id VARCHAR(191) COLLATE "C" NOT NULL,
@@ -426,6 +427,7 @@ export const PG_SCHEMA_STATEMENTS = [
426
427
  migrationMarkerDdl("pg"),
427
428
  replicaRegistrationDdl("pg"),
428
429
  servingRequirementDdl("pg"),
430
+ sessionBlobNamespaceClaimDdl("pg"),
429
431
  ];
430
432
  export function pgPoolOptions(pgCfg, dbQueryTimeoutMs) {
431
433
  return {