@sema-agent/server 7.43.0 → 7.44.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 (345) hide show
  1. package/USAGE.md +18 -0
  2. package/dist/adoption/plan.js +31 -192
  3. package/dist/adoption/quiesce.js +3 -86
  4. package/dist/adoption/runner.js +3 -140
  5. package/dist/adoption/sql.js +0 -74
  6. package/dist/adoption/wire.js +0 -80
  7. package/dist/approval-ask-machine.js +0 -75
  8. package/dist/approval-card.js +0 -323
  9. package/dist/approval-deny-reasons.js +0 -42
  10. package/dist/approval-hmac.js +0 -35
  11. package/dist/approval-reconciler.js +8 -166
  12. package/dist/approval.js +4 -67
  13. package/dist/audit.js +1 -44
  14. package/dist/auth-bridge.js +4 -47
  15. package/dist/auth-keys.js +0 -23
  16. package/dist/bake-runner/main.js +4 -65
  17. package/dist/bake-runner/protocol.js +3 -58
  18. package/dist/bake-runner/runner.js +5 -91
  19. package/dist/bench/l8/artifact.js +2 -61
  20. package/dist/bench/l8/escape.js +0 -25
  21. package/dist/bench/l8/index.js +0 -14
  22. package/dist/bench/l8/probes.js +0 -60
  23. package/dist/bench/l8/run-probes.js +2 -45
  24. package/dist/bench/s1/arms.js +14 -189
  25. package/dist/bench/s1/live-deps.js +11 -253
  26. package/dist/bench/s1/oracle.js +1 -36
  27. package/dist/bench/s1/repair-oracle-adapter.js +0 -30
  28. package/dist/bench/s1/reviewer.js +0 -34
  29. package/dist/bench/s1/row.js +0 -62
  30. package/dist/bench/s1/run-firm.js +4 -70
  31. package/dist/bench/s1/runner-ctx.js +0 -40
  32. package/dist/bench/s1/tasks.js +0 -115
  33. package/dist/boot/adoption.js +0 -20
  34. package/dist/boot/budget-tracing.js +3 -55
  35. package/dist/boot/config-center.js +43 -551
  36. package/dist/boot/coordinators.js +1 -69
  37. package/dist/boot/crash-last.js +0 -18
  38. package/dist/boot/deferred-sandbox-path-env.js +3 -119
  39. package/dist/boot/execution-env.js +5 -171
  40. package/dist/boot/governance-seams.js +0 -92
  41. package/dist/boot/leader.js +0 -69
  42. package/dist/boot/limit-sync.js +0 -2
  43. package/dist/boot/memory-boundary.js +3 -91
  44. package/dist/boot/org-memory.js +1 -25
  45. package/dist/boot/parked-revive-gate.js +0 -150
  46. package/dist/boot/permission-rules-audit.js +1 -56
  47. package/dist/boot/reapers.js +15 -273
  48. package/dist/boot/resolve-spec.js +9 -768
  49. package/dist/boot/retention-lane.js +4 -87
  50. package/dist/boot/runner-deps.js +3 -297
  51. package/dist/boot/runtime-caps.js +0 -40
  52. package/dist/boot/session-faces.js +2 -133
  53. package/dist/boot/shutdown.js +9 -83
  54. package/dist/boot/side-query-lane.js +2 -137
  55. package/dist/boot/stores.js +15 -215
  56. package/dist/boot/task-list-lane.js +0 -18
  57. package/dist/boot/webfetch-summarize-lane.js +0 -47
  58. package/dist/boot/workflow-orchestration.js +3 -99
  59. package/dist/boot-reclaim.js +0 -20
  60. package/dist/bounded-session-map.js +0 -19
  61. package/dist/brain.js +2 -139
  62. package/dist/budget.js +9 -244
  63. package/dist/capabilities/builtin-tools.js +0 -3
  64. package/dist/capabilities/center-plugins.js +6 -51
  65. package/dist/capabilities/center-prompts.js +6 -71
  66. package/dist/capabilities/code-review-council.js +7 -40
  67. package/dist/capabilities/collab-workflows.js +1 -44
  68. package/dist/capabilities/hands-lane.js +0 -65
  69. package/dist/capabilities/memory-notice.js +0 -70
  70. package/dist/capabilities/prompt.js +0 -14
  71. package/dist/capabilities/prompts/code-review.js +0 -14
  72. package/dist/capabilities/prompts/identity.js +0 -6
  73. package/dist/capabilities/prompts/team.js +0 -4
  74. package/dist/capabilities/repo-tools.js +0 -34
  75. package/dist/capabilities/sandbox-file-send.js +3 -92
  76. package/dist/capabilities/scenarios.d.ts +0 -1
  77. package/dist/capabilities/scenarios.js +18 -279
  78. package/dist/capabilities/select-environment-tool.js +0 -32
  79. package/dist/capabilities/send-user-file-tool.js +2 -66
  80. package/dist/capabilities/skills.d.ts +1 -2
  81. package/dist/capabilities/skills.js +3 -21
  82. package/dist/capabilities/team.d.ts +3 -11
  83. package/dist/capabilities/team.js +3 -51
  84. package/dist/capabilities/tool-defer.js +0 -3
  85. package/dist/config-center/apply-effective.js +15 -330
  86. package/dist/config-center/apply-ledger.js +5 -38
  87. package/dist/config-center/facade.js +0 -41
  88. package/dist/config-center/hot-keys-registry.js +0 -20
  89. package/dist/config-center/http-client.js +2 -125
  90. package/dist/config-center/mcp-revocation.js +2 -34
  91. package/dist/config-center/read-face.js +0 -59
  92. package/dist/config-center/restart-signal.js +1 -85
  93. package/dist/config-center/skills-mcp.d.ts +1 -1
  94. package/dist/config-center/skills-mcp.js +9 -76
  95. package/dist/config-center/stage-limits.js +8 -35
  96. package/dist/config-invariants.js +0 -16
  97. package/dist/config-lkg.js +0 -42
  98. package/dist/config-provider.js +3 -186
  99. package/dist/config-types.js +0 -5
  100. package/dist/config.js +107 -1145
  101. package/dist/degenerate-instrument.js +3 -67
  102. package/dist/deployment-governance.js +0 -124
  103. package/dist/digest-form.js +0 -12
  104. package/dist/elicitation.js +3 -86
  105. package/dist/env-facts.js +7 -75
  106. package/dist/fleet/fleet-bus.js +34 -507
  107. package/dist/fleet/fleet-reconciler.js +9 -149
  108. package/dist/fleet/fleet-terminal-window.js +10 -178
  109. package/dist/fleet/subagent-tail-bus.js +3 -72
  110. package/dist/fleet-client.js +10 -70
  111. package/dist/fleet-lease.js +5 -79
  112. package/dist/git-api-kind.js +0 -3
  113. package/dist/governance-ask-marks.js +2 -78
  114. package/dist/hooks/branch-transcript.js +0 -74
  115. package/dist/hooks/cc-agent-hook-prompt.js +0 -29
  116. package/dist/hooks/cc-stop-prompt.js +1 -46
  117. package/dist/hooks/hook-llm.js +1 -53
  118. package/dist/hooks/hook-runner.js +20 -414
  119. package/dist/http/active-run-conflict.js +4 -129
  120. package/dist/http/cursor-fingerprint.d.ts +5 -0
  121. package/dist/http/cursor-fingerprint.js +5 -0
  122. package/dist/http/idempotency.js +0 -37
  123. package/dist/http/principal-gate.js +3 -40
  124. package/dist/http/route-ctx.js +0 -9
  125. package/dist/http/routes/a2a-serve.js +7 -319
  126. package/dist/http/routes/admin-config-refresh.js +0 -4
  127. package/dist/http/routes/admin-drain.js +0 -10
  128. package/dist/http/routes/adoption.js +1 -29
  129. package/dist/http/routes/agents-roster.js +1 -47
  130. package/dist/http/routes/approvals-assistant.js +32 -395
  131. package/dist/http/routes/attachments.js +4 -22
  132. package/dist/http/routes/capabilities.js +3 -420
  133. package/dist/http/routes/diagnostics.js +1 -81
  134. package/dist/http/routes/fleet.js +9 -185
  135. package/dist/http/routes/images.js +14 -239
  136. package/dist/http/routes/leader.js +0 -13
  137. package/dist/http/routes/memory-bundle.js +1 -61
  138. package/dist/http/routes/memory-policy.js +9 -99
  139. package/dist/http/routes/notify-wake.js +3 -37
  140. package/dist/http/routes/observability.js +2 -19
  141. package/dist/http/routes/retention-ops.js +2 -34
  142. package/dist/http/routes/rules.js +1 -93
  143. package/dist/http/routes/runs.js +64 -873
  144. package/dist/http/routes/session-sync.js +19 -258
  145. package/dist/http/routes/sessions-list.js +17 -43
  146. package/dist/http/routes/sessions.js +34 -226
  147. package/dist/http/routes/shared-memory.js +5 -36
  148. package/dist/http/routes/side-query.js +1 -87
  149. package/dist/http/routes/tasks.js +52 -722
  150. package/dist/http/routes/trace-usage.js +32 -195
  151. package/dist/http/routes/workflows.js +19 -195
  152. package/dist/http/run-meta.js +0 -6
  153. package/dist/http/send.js +0 -32
  154. package/dist/http/server.js +92 -1597
  155. package/dist/http/sse-lifecycle.js +2 -13
  156. package/dist/http/sse-log.js +3 -48
  157. package/dist/http/tar.js +5 -21
  158. package/dist/http/verify-rounds.js +0 -5
  159. package/dist/http/wire-gate.js +0 -9
  160. package/dist/http/workspace-content.js +0 -10
  161. package/dist/images/bake-validate.js +1 -70
  162. package/dist/images/manifest.js +1 -6
  163. package/dist/index.js +0 -21
  164. package/dist/key-resolver.js +2 -17
  165. package/dist/leader/diffout.js +1 -20
  166. package/dist/leader/diffup.js +0 -47
  167. package/dist/leader/endpoint.js +2 -57
  168. package/dist/leader/fanout.js +3 -45
  169. package/dist/leader/grader-env-factory.js +3 -72
  170. package/dist/leader/leader.js +5 -156
  171. package/dist/leader/merge.js +8 -115
  172. package/dist/leader/planner.js +3 -54
  173. package/dist/leader/repair-oracle.js +1 -60
  174. package/dist/leader/repair-wire.js +2 -79
  175. package/dist/leader/wire.js +8 -307
  176. package/dist/lsp/e2b-bridge.js +4 -64
  177. package/dist/lsp/e2b-manager.js +6 -94
  178. package/dist/lsp/lsp-frames.js +0 -12
  179. package/dist/lsp/manager.js +4 -96
  180. package/dist/lsp/ws-transport.js +5 -55
  181. package/dist/lsp-evict.js +1 -15
  182. package/dist/main.js +57 -765
  183. package/dist/memory-bundle-engine.js +0 -55
  184. package/dist/memory-export.js +0 -4
  185. package/dist/memory-posture.js +1 -15
  186. package/dist/memory-scope.js +11 -148
  187. package/dist/memory-sync-client.js +2 -44
  188. package/dist/memory-sync.js +1 -80
  189. package/dist/model-select.js +3 -80
  190. package/dist/observability/cost-quota.js +1 -17
  191. package/dist/observability/cost-taxonomy.js +0 -34
  192. package/dist/observability/fail-open.js +7 -86
  193. package/dist/observability/logger.js +0 -6
  194. package/dist/observability/metrics.js +0 -94
  195. package/dist/observability/otel-exporter.js +3 -13
  196. package/dist/observability/principal-context.js +0 -9
  197. package/dist/observability/prompt-manifest.js +1 -37
  198. package/dist/observability/rate-limit.js +0 -4
  199. package/dist/observability/secret-env-scrub.js +2 -56
  200. package/dist/observability/tool-trace.js +1 -70
  201. package/dist/orchestration/hardened-vm-runner.js +4 -118
  202. package/dist/orchestration/hardened-vm-worker-runner.js +1 -26
  203. package/dist/orchestration/hardened-vm-worker.js +0 -27
  204. package/dist/orchestration/subagent-steer.js +1 -45
  205. package/dist/orchestration/workflow-agent-steer.js +1 -80
  206. package/dist/orchestration/workflow-completion-inbox.js +32 -285
  207. package/dist/orchestration/workflow-notify-journal.js +16 -259
  208. package/dist/org-memory-admission.js +3 -47
  209. package/dist/parent-watch.js +2 -48
  210. package/dist/parked-decide.js +1 -109
  211. package/dist/per-task-image.js +0 -57
  212. package/dist/plan-cache-probe.js +3 -27
  213. package/dist/plugins/adoption-log-sql.js +2 -119
  214. package/dist/plugins/approval-ask-store-memory.js +3 -38
  215. package/dist/plugins/approval-ask-store-sql.js +6 -188
  216. package/dist/plugins/approval-exemption-store.js +2 -28
  217. package/dist/plugins/background-agent-store-sql.js +4 -105
  218. package/dist/plugins/background-shell-support.js +14 -122
  219. package/dist/plugins/blob-backend.js +6 -169
  220. package/dist/plugins/breaker-state-sql.js +8 -46
  221. package/dist/plugins/caching-session-store.js +4 -106
  222. package/dist/plugins/checkpoint-store-sql.js +18 -505
  223. package/dist/plugins/e2b-orphan-reclaim.js +0 -45
  224. package/dist/plugins/file-outcome-sink.js +0 -9
  225. package/dist/plugins/file-resume-anchor-store.js +4 -43
  226. package/dist/plugins/file-run-store.js +26 -364
  227. package/dist/plugins/file-snapshot-store-sql.js +10 -181
  228. package/dist/plugins/fork-routing-session-store.js +8 -111
  229. package/dist/plugins/host-platform.js +2 -91
  230. package/dist/plugins/image-bake-store-sql.js +7 -250
  231. package/dist/plugins/image-index-sql.js +4 -123
  232. package/dist/plugins/k8s-bg-scripts.js +4 -88
  233. package/dist/plugins/k8s-exec-protocol.js +0 -41
  234. package/dist/plugins/leader-run-store-sql.js +0 -101
  235. package/dist/plugins/local-checkpoint-store.js +8 -128
  236. package/dist/plugins/local-session-store.js +34 -296
  237. package/dist/plugins/local-task-attachment-store.js +2 -16
  238. package/dist/plugins/mailbox-store-sql.js +8 -65
  239. package/dist/plugins/memory-embedder-fingerprint.js +5 -166
  240. package/dist/plugins/memory-embedder.js +4 -70
  241. package/dist/plugins/memory-engine-pg.js +6 -170
  242. package/dist/plugins/memory-engine-tidb.js +7 -155
  243. package/dist/plugins/memory-engine-vector-util.js +0 -10
  244. package/dist/plugins/memory-key-guards.js +0 -34
  245. package/dist/plugins/memory-origin-law.js +0 -187
  246. package/dist/plugins/memory-resume-anchor-store.js +0 -17
  247. package/dist/plugins/memory-run-store.js +12 -89
  248. package/dist/plugins/memory-session-policy-store.js +0 -17
  249. package/dist/plugins/memory-sync-store-pg.js +4 -49
  250. package/dist/plugins/memory-sync-store-tidb.js +3 -35
  251. package/dist/plugins/outcome-ledger-sql.js +3 -97
  252. package/dist/plugins/permission-rule-store-file.js +5 -133
  253. package/dist/plugins/permission-rule-store-sql.d.ts +3 -0
  254. package/dist/plugins/permission-rule-store-sql.js +50 -307
  255. package/dist/plugins/pg-cost-quota.js +0 -7
  256. package/dist/plugins/pg-pool.js +0 -92
  257. package/dist/plugins/pg-rate-limiter.js +2 -13
  258. package/dist/plugins/pg-safe-json.js +4 -40
  259. package/dist/plugins/pg-session-storage.js +25 -189
  260. package/dist/plugins/posix-shell-fs.js +1 -31
  261. package/dist/plugins/remote-env-adb.js +12 -101
  262. package/dist/plugins/remote-env-e2b.js +40 -371
  263. package/dist/plugins/remote-env-file-error.js +0 -37
  264. package/dist/plugins/remote-env-host.js +63 -483
  265. package/dist/plugins/remote-env-k8s.js +32 -326
  266. package/dist/plugins/remote-env-local-docker.js +24 -157
  267. package/dist/plugins/remote-env-ssh.js +20 -128
  268. package/dist/plugins/remote-scratchpad.js +2 -32
  269. package/dist/plugins/remote-shell.js +1 -32
  270. package/dist/plugins/resume-anchor-store-sql.js +0 -11
  271. package/dist/plugins/retention-lane-store-sql.js +0 -108
  272. package/dist/plugins/retention-store-sql.js +4 -383
  273. package/dist/plugins/roster-store-sql.js +0 -55
  274. package/dist/plugins/run-store-sql.js +14 -251
  275. package/dist/plugins/s3-presign.js +2 -49
  276. package/dist/plugins/scheduler-support.js +3 -80
  277. package/dist/plugins/send-file-ledger.js +4 -53
  278. package/dist/plugins/send-user-file.js +4 -94
  279. package/dist/plugins/session-placement.js +1 -89
  280. package/dist/plugins/session-policy-store-sql.js +3 -81
  281. package/dist/plugins/session-store.js +0 -57
  282. package/dist/plugins/shared-memory-store-sql.js +4 -167
  283. package/dist/plugins/sql-driver.js +0 -17
  284. package/dist/plugins/sql-errors.js +0 -7
  285. package/dist/plugins/sql-escape.js +0 -8
  286. package/dist/plugins/sql-row-helpers.js +0 -25
  287. package/dist/plugins/store-backend.js +42 -222
  288. package/dist/plugins/store-contracts.js +2 -46
  289. package/dist/plugins/task-attachment-store.js +3 -49
  290. package/dist/plugins/task-list-store-sql.js +0 -79
  291. package/dist/plugins/tidb-cost-quota.js +1 -4
  292. package/dist/plugins/tidb-pool.js +1 -207
  293. package/dist/plugins/tidb-rate-limiter.js +3 -9
  294. package/dist/plugins/tidb-session-storage.js +4 -70
  295. package/dist/plugins/tidb-session-store.js +19 -341
  296. package/dist/plugins/tool-result-store-sql.js +4 -179
  297. package/dist/plugins/usage-window-store-sql.js +0 -8
  298. package/dist/plugins/web-search.js +10 -132
  299. package/dist/plugins/workflow-journal-store-sql.js +2 -58
  300. package/dist/plugins/workflow-run-store-sql.js +6 -91
  301. package/dist/plugins/worktree-isolation.js +6 -126
  302. package/dist/plugins/write-behind-counter.js +16 -75
  303. package/dist/principal-jwt.js +5 -60
  304. package/dist/project-memory.js +15 -146
  305. package/dist/prompts-domain-validate.js +1 -51
  306. package/dist/question.js +2 -111
  307. package/dist/resource-suspend.js +0 -18
  308. package/dist/router/route-orchestration.js +0 -77
  309. package/dist/rules-consent.d.ts +44 -5
  310. package/dist/rules-consent.js +75 -215
  311. package/dist/run-local.js +14 -381
  312. package/dist/runs.js +29 -617
  313. package/dist/runtime-caps-resolver.js +6 -132
  314. package/dist/runtime-governance.js +1 -232
  315. package/dist/sandbox-pkg-source.js +0 -37
  316. package/dist/sealed-key.js +3 -68
  317. package/dist/security.js +6 -291
  318. package/dist/session-leaf-bus.js +0 -32
  319. package/dist/session-sync-content.js +1 -69
  320. package/dist/session-sync-kernel.js +3 -60
  321. package/dist/session-sync.js +3 -66
  322. package/dist/session-titler.js +7 -41
  323. package/dist/session-watch.js +9 -73
  324. package/dist/shared-memory-scope-authorizer.js +0 -18
  325. package/dist/sighup-idle.js +1 -12
  326. package/dist/spec-fields.js +4 -143
  327. package/dist/store-live-probe.js +3 -49
  328. package/dist/task-a2a.js +1 -126
  329. package/dist/task-cwd.js +1 -103
  330. package/dist/task-mcp.js +1 -89
  331. package/dist/task-settings.js +10 -300
  332. package/dist/task-workflow.js +8 -75
  333. package/dist/tool-approval.d.ts +28 -1
  334. package/dist/tool-approval.js +70 -1430
  335. package/dist/trace/artifacts.js +5 -20
  336. package/dist/trace/engine-notice-wire.js +6 -138
  337. package/dist/trace/ledger-sink.js +7 -96
  338. package/dist/trace/project.js +4 -448
  339. package/dist/trace/redact.js +9 -77
  340. package/dist/turn-activity.js +1 -27
  341. package/dist/usage-analytics.js +4 -34
  342. package/dist/wall-clock-jump-guard.js +1 -68
  343. package/package.json +3 -3
  344. package/dist/capabilities/scenario-alias.d.ts +0 -27
  345. package/dist/capabilities/scenario-alias.js +0 -61
@@ -4,14 +4,6 @@ import { TIDB_LEADER_RUN_STATEMENTS } from "./leader-run-store-sql.js";
4
4
  import { TIDB_ADOPTION_LOG_STATEMENTS } from "./adoption-log-sql.js";
5
5
  import { TIDB_PERMISSION_RULE_STATEMENTS } from "./permission-rule-store-sql.js";
6
6
  import { TIDB_RETENTION_STATEMENTS } from "./retention-store-sql.js";
7
- /**
8
- * Shared TiDB (MySQL wire-compatible) connection pool for the durable Session center (L1).
9
- * Owned by `main.ts`; closed on shutdown.
10
- *
11
- * Read/write pool — this is the persistence center. (The SQL *tool* given to the model must use a
12
- * separate read-only pool/credential; never hand this pool to a tool.)
13
- */
14
- /** Build the mysql2 pool options from TiDB config (pure → unit-testable apart from the live connection). */
15
7
  export function tidbPoolOptions(tidb) {
16
8
  const { host, port, user, password, database, connectionLimit } = tidb;
17
9
  const limit = connectionLimit ?? 10;
@@ -26,15 +18,7 @@ export function tidbPoolOptions(tidb) {
26
18
  maxIdle: limit,
27
19
  idleTimeout: 60_000,
28
20
  enableKeepAlive: true,
29
- // Bound the acquire backlog. With waitForConnections + the mysql2 default queueLimit:0 (unlimited), a TiDB
30
- // stall makes EVERY db op queue without bound → all serving hangs indefinitely instead of failing fast. A
31
- // finite limit (well above a normal burst) lets a sustained stall surface as errors the HTTP layer can map
32
- // to 5xx, rather than an invisible hang. (Per-query timeouts are the deeper fix: mysql2 has NO pool-level
33
- // knob — `timeout` is per-query `{sql, timeout}` only — so the S9 write-behind counter family carries its
34
- // own per-query timeout (write-behind-counter.ts, DB_QUERY_TIMEOUT_MS overrides); the general query surface
35
- // here keeps relying on this backlog bound. The PG pool DOES have the pool-wide knob — see pgPoolOptions.)
36
21
  queueLimit: limit * 32,
37
- // Persist/return DATETIME in UTC so timestamps are stable across instances/timezones.
38
22
  timezone: "Z",
39
23
  charset: "utf8mb4",
40
24
  };
@@ -46,26 +30,6 @@ export function createTidbPool(config) {
46
30
  }
47
31
  return mysql.createPool(tidbPoolOptions(config.tidb));
48
32
  }
49
- /**
50
- * Idempotent schema. `session_event` is the append-only L1 event log (positional slicing by
51
- * `(session_id, seq)`); `session_meta` holds the branch leaf + the optimistic-lock counter
52
- * (`leaf_seq`) + tenant `owner`.
53
- *
54
- * ── SCHEMA POLICY (clay 裁,2026-07-26) ─────────────────────────────────────────────────────────────
55
- * 本仓 schema 的唯一真源 = **这份代码**(此数组 + `pg-pool.ts` 的 PG 孪生)。口径:
56
- *
57
- * 1. **删库重建,不做增量。** 尚未上生产、单人本地,存量库一律 DROP DATABASE 重建;因此这里**不再保留
58
- * 任何 `ALTER TABLE` 增量 seam**。历史上的 21 条 ADD COLUMN / 3 条 CREATE INDEX / 1 条 MODIFY COLUMN
59
- * 已于 2026-07-26 全部折进下面的 `CREATE TABLE`(它们承载的语义已逐条搬成列上的行内注释 —— 那些注释
60
- * 是 pre-migration 行为契约的**唯一书面记录**,删注释 = 丢语义)。
61
- * 2. **不许再新增 `ALTER TABLE` seam。** 要改列/加列/改可空性 ⇒ 直接改下面的 `CREATE TABLE`,然后重建库。
62
- * (再开增量通道就等于把「代码是真源」变回「代码 + 一串按时间排的补丁才是真源」。)
63
- * 3. 生成的全集 SQL 基线导出到 `docs/schema/baseline-mysql.sql`(由本数组机器生成;它是**产物**,不是真源
64
- * —— 冲突时以本文件为准并重新生成)。
65
- *
66
- * 注意:`ensureSchema` 仍然保留(建表 + advisory lock + image_bake_admit 种子行),只是语句数组现在是纯
67
- * CREATE,不再有 information_schema 探针。
68
- */
69
33
  export const SCHEMA_STATEMENTS = [
70
34
  `CREATE TABLE IF NOT EXISTS session_meta (
71
35
  session_id VARCHAR(64) NOT NULL,
@@ -105,8 +69,6 @@ export const SCHEMA_STATEMENTS = [
105
69
  PRIMARY KEY (session_id, seq),
106
70
  UNIQUE KEY uq_session_event_entry (session_id, entry_id)
107
71
  ) COLLATE utf8mb4_bin`,
108
- // Async run registry (S1) + replayable event log (S2). Any instance can serve a run's status /
109
- // event replay because both live here, not in a single instance's memory.
110
72
  `CREATE TABLE IF NOT EXISTS task_run (
111
73
  -- ⚠️ 表级 COLLATE 的**非键列**影响(#192 A11,codex 复审 2026-08-08 round2 点名——先前"只有
112
74
  -- outcome_ledger 有聚合语义变化"的说法过窄,如实更正):
@@ -169,10 +131,6 @@ export const SCHEMA_STATEMENTS = [
169
131
  -- ever served an operator's ad-hoc WHERE error_code LIKE 'budget.%', while every task_run write paid its
170
132
  -- maintenance cost. If you need that ad-hoc query, build the index temporarily and drop it after.
171
133
  ) COLLATE utf8mb4_bin`,
172
- // Cross-replica circuit-breaker state (1.38). A row per breaker key ("<provider>:<id>"); each
173
- // replica write-through-caches its trips here and periodically refreshes so a provider outage is
174
- // learned fleet-wide instead of every replica re-discovering it. Advisory / eventually consistent
175
- // (last-writer-wins): the breaker is consultative, not a linearizable lock.
176
134
  `CREATE TABLE IF NOT EXISTS circuit_breaker (
177
135
  breaker_key VARCHAR(190) NOT NULL,
178
136
  phase VARCHAR(16) NOT NULL,
@@ -181,9 +139,6 @@ export const SCHEMA_STATEMENTS = [
181
139
  updated_at DATETIME(3) NOT NULL,
182
140
  PRIMARY KEY (breaker_key)
183
141
  ) COLLATE utf8mb4_bin`,
184
- // Cross-replica per-key CUMULATIVE cost quota (design/30 P0-1). One row per (scope_key, aligned window
185
- // bucket); replicas atomically `micro = micro + delta` (write-behind aggregation), so spend is summed
186
- // fleet-wide without losing increments. scope_key is opaque (principal today; team/feature later).
187
142
  `CREATE TABLE IF NOT EXISTS cost_quota (
188
143
  scope_key VARCHAR(190) NOT NULL,
189
144
  window_bucket BIGINT NOT NULL,
@@ -192,8 +147,6 @@ export const SCHEMA_STATEMENTS = [
192
147
  PRIMARY KEY (scope_key, window_bucket),
193
148
  KEY idx_cost_quota_window (window_bucket)
194
149
  ) COLLATE utf8mb4_bin`,
195
- // Cross-replica per-key request rate limit (design/30 P0-2) — same write-behind-counter shape as
196
- // cost_quota (one row per key+aligned-window, atomic n = n + delta). Soft fleet-wide limiting.
197
150
  `CREATE TABLE IF NOT EXISTS rate_limit (
198
151
  limit_key VARCHAR(190) NOT NULL,
199
152
  window_bucket BIGINT NOT NULL,
@@ -202,15 +155,6 @@ export const SCHEMA_STATEMENTS = [
202
155
  PRIMARY KEY (limit_key, window_bucket),
203
156
  KEY idx_rate_limit_window (window_bucket)
204
157
  ) COLLATE utf8mb4_bin`,
205
- // Durable backing for offloaded large tool results (core 1.47/1.49). One row per offload ref
206
- // (`tr_<sessionId>~<toolCallId>~<contentSeg>` since core 5.26.0 #119, globally unique → PK); content is the full tool output moved out of
207
- // context. Write-once (INSERT IGNORE); TTL-reaped by created_at (idx_created). LONGTEXT holds large
208
- // file/diff reads. Lets an async run wake on any replica and still read_tool_result the full text.
209
- // #119(core 5.26.0 提货):`ref` 从 VARCHAR(190) 抬到 518 = core 导出的 `MAX_MINTED_TOOL_RESULT_REF_CHARS`
210
- // (`"tr_"` + 四段 × 128 + 三个 `~` 分隔),并新增 #119 出处两列(NULL = 该行无属主,读面 fail-closed)。
211
- // 抬宽不是保守裕度:core 的 d.ts 逐字点名过旧宽度(「TiDB's was VARCHAR(191), which a long three-segment
212
- // ref overruns — a truncating key aliases distinct refs」)—— 截断的主键会把两枚不同的 ref 折成同一行,
213
- // 于是 A 的产物能从 B 的 ref 读出来。utf8mb4 下 518 字符 = 2072 字节,仍在 InnoDB/TiDB 3072 字节键长内。
214
158
  `CREATE TABLE IF NOT EXISTS tool_result (
215
159
  ref VARCHAR(518) NOT NULL,
216
160
  content LONGTEXT NOT NULL,
@@ -228,9 +172,6 @@ export const SCHEMA_STATEMENTS = [
228
172
  ts DATETIME(3) NOT NULL,
229
173
  PRIMARY KEY (task_id, seq)
230
174
  ) COLLATE utf8mb4_bin`,
231
- // Single-active-run-per-session claim. PRIMARY KEY(session_id) makes the claim a unique-key
232
- // insert: TiDB enforces it even with no prior row (it lacks InnoDB gap locks, so a
233
- // SELECT…FOR UPDATE on an empty match would NOT serialize two concurrent zero-prior createRuns).
234
175
  `CREATE TABLE IF NOT EXISTS task_active (
235
176
  session_id VARCHAR(64) NOT NULL,
236
177
  task_id VARCHAR(64) NOT NULL,
@@ -238,11 +179,6 @@ export const SCHEMA_STATEMENTS = [
238
179
  PRIMARY KEY (session_id),
239
180
  KEY idx_task_active_task (task_id)
240
181
  ) COLLATE utf8mb4_bin`,
241
- // ([2354]/[2356] A-5,5.0.0:F4 轮询车道的 `approval` 表 DDL 已随车道退役——存量库里的旧表留置不动,
242
- // 代码零读写;durable 门只用下面的 checkpoint 表。)
243
- // Durable-checkpoint (core 1.67 / design/45): a policy `ask` persisted as a suspended task so an operator
244
- // can `resume` it from any replica. `checkpoint` = core's blob + CAS status; `outcome` persisted on resolve
245
- // (R20 #1). Timestamps are epoch-ms BIGINT (the core Checkpoint uses ms numbers, not DATETIME).
246
182
  `CREATE TABLE IF NOT EXISTS checkpoint (
247
183
  token VARCHAR(120) NOT NULL,
248
184
  scope VARCHAR(190) NOT NULL,
@@ -325,18 +261,12 @@ export const SCHEMA_STATEMENTS = [
325
261
  KEY idx_checkpoint_status_deadline (status, deadline),
326
262
  KEY idx_checkpoint_session_status (session_id, status)
327
263
  ) COLLATE utf8mb4_bin`,
328
- // Service-side resume rebuild inputs (DURABLE-CHECKPOINT-PLAN §4.4a): sessionId-keyed because core's
329
- // put(token,cp) can't carry service scenario_ctx. GC'd by the reaper once its checkpoint is gone.
330
264
  `CREATE TABLE IF NOT EXISTS checkpoint_ctx (
331
265
  session_id VARCHAR(190) NOT NULL,
332
266
  ctx JSON NOT NULL,
333
267
  updated_at_ms BIGINT NOT NULL,
334
268
  PRIMARY KEY (session_id)
335
269
  ) COLLATE utf8mb4_bin`,
336
- // E18 resume-at anchor map: the shell holds live E2 eventIds (never persisted by core); TaskSpec.resumeAt takes a
337
- // persisted SessionTreeEntry.id. This is the service-owned eventId→entryId translation. Keyed (session_id,event_id)
338
- // so resolve is a PK point-lookup; entry_id is the resolve target. owner = single-DB-fleet defense-in-depth (the
339
- // session is already owner-gated at the route + scoped by session_id). GC'd with the session (E21 delete).
340
270
  `CREATE TABLE IF NOT EXISTS resume_anchor (
341
271
  session_id VARCHAR(64) NOT NULL,
342
272
  event_id VARCHAR(64) NOT NULL,
@@ -346,9 +276,6 @@ export const SCHEMA_STATEMENTS = [
346
276
  PRIMARY KEY (session_id, event_id),
347
277
  KEY idx_resume_anchor_session (session_id)
348
278
  ) COLLATE utf8mb4_bin`,
349
- // Per-session per-toolName approval exemption ("本会话不再询问") — an APPROVAL MEMORY the
350
- // F4 ask-gate consults AFTER deny/neverAuto (both always win). tool_name is CANONICAL space. GC'd with
351
- // the session (E21 delete). See sema-internal server/docs/design/APPROVAL-SESSION-EXEMPTION.md.
352
279
  `CREATE TABLE IF NOT EXISTS approval_exemption (
353
280
  session_id VARCHAR(64) NOT NULL,
354
281
  tool_name VARCHAR(190) NOT NULL,
@@ -356,12 +283,6 @@ export const SCHEMA_STATEMENTS = [
356
283
  created_at DATETIME(3) NOT NULL,
357
284
  PRIMARY KEY (session_id, tool_name)
358
285
  ) COLLATE utf8mb4_bin`,
359
- // SendUserFile server-side ledger (multi-tenant governance, 1.190.0 [768]②a second half): one row per issued
360
- // link — the scope↔object mapping the HASHED key segment deliberately hides from URLs (per-tenant list/revoke
361
- // handle). id = uuidv7 (time-ordered PK = the keyset cursor); scope = VERIFIED principal verbatim ("_" =
362
- // single-user sentinel); object_key ≤ 207 chars by construction (prefix 9 + seg 32 + uuid 36 + name ≤128 + 2 slashes).
363
- // No URL column by design (public track reconstructs from bucket+key; presigned URLs decay). See
364
- // send-file-ledger.ts.
365
286
  `CREATE TABLE IF NOT EXISTS sendfile_link (
366
287
  id VARCHAR(64) NOT NULL,
367
288
  scope VARCHAR(190) NOT NULL,
@@ -377,16 +298,6 @@ export const SCHEMA_STATEMENTS = [
377
298
  PRIMARY KEY (id),
378
299
  KEY idx_sendfile_link_scope (scope, id)
379
300
  ) COLLATE utf8mb4_bin`,
380
- // E6 durable SessionPolicyStore — operator-tightened per-(session,principal) tool-permission rules (CAS-versioned
381
- // tighten-only; core reads them at prepare-time, subtract-only). policy_key = sha256(JSON.stringify([sessionId,
382
- // principal ?? null])) — the SHA of core's exact composite key: a FIXED 64-char PK (an arbitrary-length / JSON-
383
- // escapable principal can't overflow it, and no PK collation/PAD pitfalls); undefined/null principal collapse to one
384
- // row, "" stays distinct. session_id is kept as a column for the E21 deleteBySession purge + index. `principal` is
385
- // stored DENORMALIZED (it is ALSO inside the sha256 policy_key) ONLY so 2c session-sync's listBySession can ENUMERATE
386
- // a session's per-principal rows (the hash is one-way, so the principal can't be recovered from policy_key).
387
- // It is NOT part of any key/uniqueness and does NOT participate in the CAS/tighten logic — putRules just writes it.
388
- // NULL = the session-wide row (principal undefined). VARCHAR(190) bounds it (a longer/escapable principal still keys
389
- // by the fixed-width hash; this column is enumeration-only, so a truncated value here can't corrupt lookups).
390
301
  `CREATE TABLE IF NOT EXISTS session_policy (
391
302
  policy_key CHAR(64) NOT NULL,
392
303
  session_id VARCHAR(64) NOT NULL,
@@ -402,10 +313,6 @@ export const SCHEMA_STATEMENTS = [
402
313
  PRIMARY KEY (policy_key),
403
314
  KEY idx_session_policy_session (session_id)
404
315
  ) COLLATE utf8mb4_bin`,
405
- // E19 rewind-files — durable working-tree snapshots keyed by (scope=sessionId, snap_key=SessionTreeEntry.id; same
406
- // entryId anchor as E18). A per-(scope,key) manifest of relPath→blob_hash + content-addressed blobs (deduped across
407
- // all snapshots). core's captureManifest/applyManifest do the env walk/restore; this is just the durable persistence.
408
- // Bounded by DEFAULT_SNAPSHOT_BOUNDS (≤2000 files / 64 MiB, skips .git/node_modules). GC'd with the session (E21).
409
316
  `CREATE TABLE IF NOT EXISTS snapshot_manifest (
410
317
  scope VARCHAR(64) NOT NULL,
411
318
  snap_key VARCHAR(64) NOT NULL,
@@ -414,11 +321,6 @@ export const SCHEMA_STATEMENTS = [
414
321
  KEY idx_snapshot_manifest_sk (scope, snap_key),
415
322
  KEY idx_snapshot_manifest_blob (blob_hash)
416
323
  ) COLLATE utf8mb4_bin`,
417
- // `bytes` is NULLABLE: a SQL-backend row carries the bytes inline; a MinIO-backend row keeps ONLY the INDEX
418
- // (blob_hash, byte_len, created_at) here with bytes NULL — the bytes live in MinIO. This INDEX row is what
419
- // gcOrphanBlobs / reap / deleteBySession (E21 purge) / sweepOrphanBlobs read to compute the orphan/grace SET, so
420
- // reference-tracking + the created_at grace window work IDENTICALLY for both backends (and an E21 purge can delete
421
- // the MinIO object, not leak it). See blob-backend.ts MinioBlobBackend.
422
324
  `CREATE TABLE IF NOT EXISTS snapshot_blob (
423
325
  blob_hash CHAR(64) NOT NULL,
424
326
  byte_len BIGINT NOT NULL,
@@ -434,12 +336,6 @@ export const SCHEMA_STATEMENTS = [
434
336
  PRIMARY KEY (blob_hash),
435
337
  KEY idx_snapshot_blob_created (created_at)
436
338
  ) COLLATE utf8mb4_bin`,
437
- // SVC-2 (core CORE-7) durable WorkflowJournalStore — the cross-replica resume journal for an LLM-authored workflow.
438
- // One row per (run_id, ordinal): `ordinal` = core's callKeyOrdinal(callKey) (the positional replay index), `result`
439
- // = JSON.stringify(TaskResult). The (run_id, ordinal) PK makes append IDEMPOTENT (ON DUPLICATE KEY = OVERWRITE /
440
- // last-write-wins) so a resumed run re-appending its replayed prefix verbatim leaves no dup — the byte-match of
441
- // core's InMemoryWorkflowJournalStore (byOrdinal.set). LOAD-BEARING (a resume replays it), unlike the best-effort
442
- // task_event observation log. GC'd by the run reaper (deleteByRun). See workflow-journal-store-sql.ts.
443
339
  `CREATE TABLE IF NOT EXISTS workflow_journal (
444
340
  run_id VARCHAR(191) NOT NULL,
445
341
  ordinal INT NOT NULL,
@@ -455,9 +351,6 @@ export const SCHEMA_STATEMENTS = [
455
351
  created_at_ms BIGINT NOT NULL,
456
352
  PRIMARY KEY (run_id, ordinal)
457
353
  ) COLLATE utf8mb4_bin`,
458
- // RB-242 / WF2 ([1981] core 拍板 a 形):cross-replica workflow resume admission lease. PK (source_run_id, scope)
459
- // = the bake-store idem_key precedent — the INSERT either wins the claim or collides with the current holder.
460
- // TTL is the CRASH backstop only (engine releases on terminal via releaseResumeClaim); see workflow-journal-store-sql.ts.
461
354
  `CREATE TABLE IF NOT EXISTS workflow_resume_claim (
462
355
  source_run_id VARCHAR(191) NOT NULL,
463
356
  scope VARCHAR(190) NOT NULL,
@@ -465,9 +358,6 @@ export const SCHEMA_STATEMENTS = [
465
358
  claimed_at_ms BIGINT NOT NULL,
466
359
  PRIMARY KEY (source_run_id, scope)
467
360
  ) COLLATE utf8mb4_bin`,
468
- // P1 (fleet failover, 2026-07-05): durable cross-replica WorkflowRunStore twin — one row per run, the full
469
- // WorkflowRun as a JSON blob + extracted index columns; `rev` column = the OCC authority (blob rev overlaid
470
- // on read). MEDIUMTEXT (16MB) >> the 4MB write guard in the store.
471
361
  `CREATE TABLE IF NOT EXISTS workflow_run (
472
362
  id VARCHAR(191) NOT NULL,
473
363
  scope VARCHAR(190) NOT NULL,
@@ -480,8 +370,6 @@ export const SCHEMA_STATEMENTS = [
480
370
  KEY idx_wfrun_scope_created (scope, created_at_ms),
481
371
  KEY idx_wfrun_scope_status (scope, status)
482
372
  ) COLLATE utf8mb4_bin`,
483
- // P1: cross-replica workflow completion inbox (the push half). seq = insertion order (re-enqueue
484
- // moves to tail via DELETE+INSERT). summary is bounded upstream (core notifier ≤4000).
485
373
  `CREATE TABLE IF NOT EXISTS workflow_completion_inbox (
486
374
  seq BIGINT NOT NULL AUTO_INCREMENT,
487
375
  session_id VARCHAR(190) NOT NULL,
@@ -503,9 +391,6 @@ export const SCHEMA_STATEMENTS = [
503
391
  UNIQUE KEY uq_wfinbox_seq (seq),
504
392
  KEY idx_wfinbox_session_seq (session_id, seq)
505
393
  ) COLLATE utf8mb4_bin`,
506
- // P1: inbox fences AS ROWS — the actual point of the SQL port: a poll served on replica A must fence the
507
- // late notify landing on replica B (cross-replica). kind = served (per-runId) | purge (run_id='',
508
- // session-wide; owner_known=0 → conservative fence-all). Swept opportunistically on every write verb.
509
394
  `CREATE TABLE IF NOT EXISTS workflow_inbox_fence (
510
395
  session_id VARCHAR(190) NOT NULL,
511
396
  kind VARCHAR(8) NOT NULL,
@@ -516,10 +401,6 @@ export const SCHEMA_STATEMENTS = [
516
401
  PRIMARY KEY (session_id, kind, run_id),
517
402
  KEY idx_wffence_until (until_ms)
518
403
  ) COLLATE utf8mb4_bin`,
519
- // 1.108 review fix (lens③ HIGH): the notify JOURNAL twin — under WORKFLOW_RUN_STORE=auto the run store +
520
- // inbox were SQL but the notify journal stayed a replica-LOCAL File ledger, so a replica that died with an
521
- // un-acked notify stranded it forever (at-least-once silently degraded to at-most-once across replica death).
522
- // One row per STARTED run; acked flips on delivery; the recovery sweep on ANY replica walks acked=0.
523
404
  `CREATE TABLE IF NOT EXISTS workflow_notify_journal (
524
405
  run_id VARCHAR(191) NOT NULL,
525
406
  scope VARCHAR(190) NOT NULL,
@@ -531,13 +412,6 @@ export const SCHEMA_STATEMENTS = [
531
412
  PRIMARY KEY (run_id),
532
413
  KEY idx_wfnotify_acked (acked)
533
414
  ) COLLATE utf8mb4_bin`,
534
- // Outcome ledger (design/73 §7) — one row per graded task run, keyed by
535
- // (task_signature, model). v1 is READ-ONLY (dashboard + offline-backtest source); it drives NO
536
- // automatic policy change — that is flag-gated and must first pass an offline-backtest gate
537
- // (council blocker 3 / major 7). The hard-signal split is structural, not a convention: `mechanical`
538
- // columns (oracle/build/merge/cost/turns/route/replan) are the ONLY ones a future self-scheduler may
539
- // read; `llm_assisted` (stuck/verifier) lives in its JSON blob, dashboard-only, never co-weighted.
540
- // `outcome` is DERIVED from mechanical fields only (council blocker 1).
541
415
  `CREATE TABLE IF NOT EXISTS outcome_ledger (
542
416
  id VARCHAR(64) NOT NULL,
543
417
  -- ⚠️ 表级 COLLATE 对本表**不只是钉住隔离键**(#192 A11,codex 复审 2026-08-08 点名):下面两列是
@@ -572,8 +446,6 @@ export const SCHEMA_STATEMENTS = [
572
446
  KEY idx_outcome_ledger_outcome (outcome),
573
447
  KEY idx_outcome_ledger_created (created_at)
574
448
  ) COLLATE utf8mb4_bin`,
575
- // sandbox-image-pool control API (IMAGE-API-DESIGN.md §1 / pool design §8). One row per image DIGEST (the
576
- // immutable runtime ref); a queryable projection of build.sh's replay-sufficient manifest + the publish lifecycle.
577
449
  `CREATE TABLE IF NOT EXISTS sandbox_image_index (
578
450
  id VARCHAR(64) NOT NULL,
579
451
  profile VARCHAR(64) NOT NULL,
@@ -602,12 +474,6 @@ export const SCHEMA_STATEMENTS = [
602
474
  KEY idx_sandbox_image_index_digest (digest),
603
475
  KEY idx_sandbox_image_index_tenant (tenant_id, status)
604
476
  ) COLLATE utf8mb4_bin`,
605
- // sandbox-image-pool BAKE job (IMAGE-API-DESIGN.md §P2.6). A dedicated row table — NOT a reuse of task_run
606
- // (FK-coupled to task_active + the run reaper + /v1/runs list; co-mingling bakes would leak non-task rows into
607
- // reapStale/listRuns). The reader polls the COARSE 4-value `status` (queued|running|done|failed) for SSE
608
- // terminality; build.sh's 8-value `state` is denormalized for the UI progress bar ONLY and must NOT drive
609
- // terminality (P2.3 MUST-FIX — a non-terminal PUSHING/VERIFYING state would truncate the stream before `done`).
610
- // `argv` is the VETTED, normalized build.sh argv the runner runs (operator free-text never reaches the runner).
611
477
  `CREATE TABLE IF NOT EXISTS image_bake (
612
478
  bake_id VARCHAR(64) NOT NULL,
613
479
  profile VARCHAR(128) NOT NULL,
@@ -641,11 +507,6 @@ export const SCHEMA_STATEMENTS = [
641
507
  KEY idx_image_bake_status (status),
642
508
  KEY idx_image_bake_created (created_at)
643
509
  ) COLLATE utf8mb4_bin`,
644
- // Per-bake replayable event log (P2.6) — run-trace event-log mechanics ((id,seq) PK, ++seq, getEvents(after),
645
- // maxSeq, retainedFrom→416, heartbeat-not-persisted) WITHOUT the task_event FK coupling. image-api is the SOLE
646
- // ++seq writer (seq monotonic from 1). `line_ord` is the runner's per-line ordinal — the at-least-once ingest
647
- // dedupe key (uq_image_bake_event_line): a re-sent (bakeId,line_ord) is a no-op (P2.10). `level='raw'` rows are the opt-in
648
- // build.log tail (?logs=1), pruned on a tighter TTL + evicted first (P2.5/P2.9).
649
510
  `CREATE TABLE IF NOT EXISTS image_bake_event (
650
511
  bake_id VARCHAR(64) NOT NULL,
651
512
  seq INT NOT NULL,
@@ -657,9 +518,6 @@ export const SCHEMA_STATEMENTS = [
657
518
  PRIMARY KEY (bake_id, seq),
658
519
  UNIQUE KEY uq_image_bake_event_line (bake_id, line_ord)
659
520
  ) COLLATE utf8mb4_bin`,
660
- // Single-flight build lease (P2.7, §9). ONE row per builder pool — image-api owns the authoritative lease so the
661
- // one docker daemon never has two concurrent builds (a prune-behind-lock could evict layers an in-flight build
662
- // needs). `expires_at` makes a crashed-runner lease stealable (CAS on expiry).
663
521
  `CREATE TABLE IF NOT EXISTS image_bake_lease (
664
522
  pool VARCHAR(32) NOT NULL DEFAULT 'standard',
665
523
  bake_id VARCHAR(64) NOT NULL,
@@ -667,27 +525,12 @@ export const SCHEMA_STATEMENTS = [
667
525
  expires_at DATETIME(3) NOT NULL,
668
526
  PRIMARY KEY (pool)
669
527
  ) COLLATE utf8mb4_bin`,
670
- // Admission sentinel: ONE always-present row per builder pool, `SELECT … FOR UPDATE`-locked to SERIALIZE the
671
- // createBakeIfIdle busy-check+insert. A bare conditional INSERT…SELECT WHERE NOT EXISTS does NOT serialize two
672
- // concurrent admissions under TiDB's REPEATABLE READ (nor PG's READ COMMITTED), so without this lock two keyless
673
- // POSTs can both admit a non-dryRun bake. Dialect-uniform with the PG twin (image-bake-store-sql.ts).
674
528
  `CREATE TABLE IF NOT EXISTS image_bake_admit (
675
529
  pool VARCHAR(32) NOT NULL,
676
530
  PRIMARY KEY (pool)
677
531
  ) COLLATE utf8mb4_bin`,
678
- // #151(design/172)流内审批协议持久层的两张表。真源 = approval-ask-store-sql.ts 的
679
- // `TIDB_APPROVAL_ASK_STATEMENTS`(那里与 PG twin 并排,方言差异一眼可对);展开进这个数组是为了让它们
680
- // 跟着中央 `ensureSchema` 在 **named-lock 的那条 conn** 上建 —— 把 pool 级 ensure 函数塞进执行循环
681
- // 会绕开 DDL 串行化。挂进来同时也是「这张表算生产 schema」的声明(基线导出按定义只收录被执行的语句)。
682
532
  ...TIDB_APPROVAL_ASK_STATEMENTS,
683
- // #193 车4 件1(台账 P1-9):durable leader-run 登记表。真源 = leader-run-store-sql.ts 的
684
- // `TIDB_LEADER_RUN_STATEMENTS`(那里与 PG twin 并排)。展开进这里的理由与上面 approval-ask 一条不差:
685
- // 跟着中央 `ensureSchema` 在 named-lock 的那条 conn 上建,并声明「这张表算生产 schema」(基线导出按
686
- // 定义只收录被执行的语句)。
687
533
  ...TIDB_LEADER_RUN_STATEMENTS,
688
- // design/177 shared-memory store(#192 单数纪律)—— org 盘的三张表。消费面 = shared-memory-store-sql.ts。
689
- // 🔴 与 `agent_memory_engine_*`(design/138 本地记忆链)**零关系**:不 join、不共享 scope 登记、不互写
690
- // (设计 182 §13)。两族同库不同面,合表/建视图会让 harvest 的私人笔记漏进团队库。
691
534
  `CREATE TABLE IF NOT EXISTS shared_memory_scope (
692
535
  -- 一个 org scope 一行。行缺席 = 该 org 从未开通 ⇒ 语义等价于 connected 且零 store(不是故障)。
693
536
  scope_key VARCHAR(190) NOT NULL,
@@ -721,57 +564,27 @@ export const SCHEMA_STATEMENTS = [
721
564
  updated_at_ms BIGINT NOT NULL,
722
565
  PRIMARY KEY (store_id, path)
723
566
  ) COLLATE utf8mb4_bin`,
724
- // design/183 form b(纯身份重绑)的 **SQL 收编日志**。真源 = adoption-log-sql.ts 的
725
- // `TIDB_ADOPTION_LOG_STATEMENTS`(与 PG twin 并排);展开进来的理由与 approval-ask 同款:
726
- // 跟着中央 ensureSchema 在 named-lock 的那条 conn 上建,不绕开 DDL 串行化。
727
- // 🔴 它**必须**与被迁的行同库(183 I2):phase 真源住别处 ⇒ 发起 host 被摧毁时与半迁移状态分家。
728
567
  ...TIDB_ADOPTION_LOG_STATEMENTS,
729
- // #154 车二(core 5.18.0 design/179 + 5.22.0 design/182)持久化权限规则店的三张表。真源 =
730
- // permission-rule-store-sql.ts 的 `TIDB_PERMISSION_RULE_STATEMENTS`(与 PG twin 并排);展开进这个
731
- // 数组的理由与上面那族逐字相同(named-lock 的那条 conn + 「这张表算生产 schema」的声明)。
732
568
  ...TIDB_PERMISSION_RULE_STATEMENTS,
733
- // #270 车1(托管留存执行面)的四张表:审计(§6)/ hold(§5)/ sweep 租约(§3)/ 墓碑(§2)。真源 =
734
- // retention-store-sql.ts 的 `TIDB_RETENTION_STATEMENTS`(与 PG twin 并排);展开进这个数组的理由与
735
- // 上面那几族逐字相同(named-lock 的那条 conn + 「这张表算生产 schema」的声明)。
736
569
  ...TIDB_RETENTION_STATEMENTS,
737
570
  ];
738
- /** Named MySQL/TiDB advisory lock that serializes the whole `ensureSchema` DDL run (see below). */
739
571
  export const ENSURE_SCHEMA_LOCK = "sema_ensure_schema";
740
- /** Acquire {@link ENSURE_SCHEMA_LOCK} on `conn` (the lock is CONNECTION-level, so the caller MUST then run all the
741
- * serialized work on this SAME connection and release with {@link releaseEnsureSchemaLock}). Returns whether it was
742
- * acquired. Exported so test setup that does ad-hoc DDL (e.g. a DROP-then-recreate) can serialize against
743
- * ensureSchema runs using the IDENTICAL lock.
744
- *
745
- * Under heavy concurrency (the integration suite fans ~20 callers at the SAME named lock; or a fleet boots N
746
- * replicas at once) a BLOCKING GET_LOCK(name, 30) would park ~19 sessions in a pessimistic WAIT on TiDB's advisory-
747
- * lock row — which both exhausts TiDB's "pessimistic lock retry limit" (surfacing as a thrown error) AND starves the
748
- * app's OWN `SELECT … FOR UPDATE` paths (image-bake admission/lease) of pessimistic-lock budget. So we acquire
749
- * NON-BLOCKING (GET_LOCK(name, 0) returns 0 immediately if held) and POLL with jittered backoff: one holder, the
750
- * rest sleeping (not blocked in-DB). Return false only after exhausting retries (the caller then DEGRADES to
751
- * unserialized rather than blocking boot forever — the DDL is still individually idempotent). */
752
572
  export async function acquireEnsureSchemaLock(conn, tag = "ensureSchema") {
753
- // Initial jitter so ~20 callers firing at t=0 (the integration fan-out, or a synchronized fleet boot) don't all
754
- // hit the advisory-lock row in the same instant — that synchronized burst is what most provokes TiDB's pessimistic
755
- // retry-limit. Spreading the first attempt over ~0.4s lets one win cleanly while the rest find it held and poll.
756
573
  await new Promise((r) => setTimeout(r, Math.floor(Math.random() * 400)));
757
574
  for (let attempt = 0; attempt < 40; attempt++) {
758
575
  try {
759
576
  const [rows] = await conn.query("SELECT GET_LOCK(?, 0) AS got", [ENSURE_SCHEMA_LOCK]);
760
577
  if (Number(rows[0]?.got) === 1)
761
- return true; // acquired (0 = currently held by someone else → poll again)
578
+ return true;
762
579
  }
763
580
  catch (err) {
764
- // A non-blocking GET_LOCK should not normally throw, but TiDB can still surface transient pessimistic-lock
765
- // contention here — tolerate it (log + keep polling); the DDL is idempotent so a degrade is at worst benign.
766
581
  console.warn(`[${tag}] GET_LOCK('${ENSURE_SCHEMA_LOCK}') attempt ${attempt + 1}/40:`, err?.message ?? err);
767
582
  }
768
- // Jittered backoff (~0.1s..0.4s + up to 0.15s jitter) — capped so total worst-case wait ≈ 40 * 0.4s = 16s.
769
583
  await new Promise((r) => setTimeout(r, 100 + Math.min(attempt, 3) * 100 + Math.floor(Math.random() * 150)));
770
584
  }
771
585
  console.warn(`[${tag}] could not acquire '${ENSURE_SCHEMA_LOCK}' after retries`);
772
586
  return false;
773
587
  }
774
- /** Release {@link ENSURE_SCHEMA_LOCK} on `conn` (best-effort — the lock also auto-frees when the connection closes). */
775
588
  export async function releaseEnsureSchemaLock(conn, tag = "ensureSchema") {
776
589
  try {
777
590
  await conn.query("SELECT RELEASE_LOCK(?)", [ENSURE_SCHEMA_LOCK]);
@@ -780,32 +593,13 @@ export async function releaseEnsureSchemaLock(conn, tag = "ensureSchema") {
780
593
  console.warn(`[${tag}] RELEASE_LOCK('${ENSURE_SCHEMA_LOCK}') failed (lock auto-frees on connection close):`, err);
781
594
  }
782
595
  }
783
- /** Create tables if absent (+ seed the image-bake admission sentinel). Safe to call on every startup.
784
- *
785
- * Per the SCHEMA POLICY on {@link SCHEMA_STATEMENTS} this is a pure CREATE run — there are NO additive
786
- * ALTER/CREATE-INDEX seams and no information_schema probes any more (2026-07-26): the schema contract is
787
- * drop-and-recreate, so every column / index / nullability lives in its `CREATE TABLE`. Do not reintroduce a
788
- * migration loop here; change the CREATE and rebuild the database.
789
- *
790
- * Concurrency: callers run this concurrently — tests fan ALL integration suites out in parallel (each
791
- * beforeAll calls ensureSchema), and in production every replica calls it at boot (`--scale service=4`).
792
- * Concurrent DDL on the SAME table makes TiDB race in its schema catalog. We serialize the entire run
793
- * behind {@link ENSURE_SCHEMA_LOCK} (a named GET_LOCK), which is CONNECTION-level — so the lock AND every
794
- * DDL statement run on the one connection we hold here (pooled `pool.query` could land on a different
795
- * connection and silently void the lock). The DDL semantics are unchanged; only the timing is serialized.
796
- */
797
596
  export async function ensureSchema(pool) {
798
597
  const conn = await pool.getConnection();
799
- // Serialize the whole DDL run behind the named connection-level lock (see acquireEnsureSchemaLock). The first
800
- // caller does the real CREATEs, the rest wait then find every statement already satisfied (IF NOT EXISTS ⇒ no-op)
801
- // → no catalog race. On a degrade (lock unavailable after retries) the DDL runs unserialized but every statement
802
- // is still individually idempotent.
803
598
  const locked = await acquireEnsureSchemaLock(conn);
804
599
  try {
805
600
  for (const stmt of SCHEMA_STATEMENTS) {
806
601
  await conn.query(stmt);
807
602
  }
808
- // Seed the always-present image-bake admission sentinel (idempotent) so createBakeIfIdle can FOR UPDATE-lock it.
809
603
  await conn.query("INSERT IGNORE INTO image_bake_admit (pool) VALUES ('standard')");
810
604
  }
811
605
  finally {
@@ -1,9 +1,7 @@
1
1
  import { WriteBehindCounter } from "./write-behind-counter.js";
2
2
  export class TiDBRateLimiter {
3
3
  counter;
4
- /** 🔴 #322:限额是比较参数、不是行状态(SQL 腿的行里只有计数),所以换代只动它,库里一行都不用碰。 */
5
4
  limit;
6
- /** 装配点表达过的运维意图(「这条腿该有刷新环」)。关断哨兵靠它把环真正停掉/重开 —— 0 态零 SQL。 */
7
5
  refreshRequested = false;
8
6
  refreshIntervalMs;
9
7
  constructor(pool, limit, windowMs = 60_000, now, onDegraded, queryTimeoutMs) {
@@ -14,7 +12,6 @@ export class TiDBRateLimiter {
14
12
  this.limit = next.rateLimitPerMin;
15
13
  this.syncRefresh();
16
14
  }
17
- /** off ⇒ 停环(零 SQL);on 且装配点要过环 ⇒ 起环(幂等,counter 内部 `??=`)。 */
18
15
  syncRefresh() {
19
16
  if (!this.refreshRequested)
20
17
  return;
@@ -26,17 +23,14 @@ export class TiDBRateLimiter {
26
23
  check(key) {
27
24
  if (this.limit <= 0)
28
25
  return { allowed: true, retryAfterSec: 0, remaining: Number.POSITIVE_INFINITY };
29
- const usedBefore = this.counter.used(key); // fleet (last refresh) + local pending — soft/eventually consistent
30
- this.counter.addLocal(key, 1); // count every request, like the in-memory limiter
26
+ const usedBefore = this.counter.used(key);
27
+ this.counter.addLocal(key, 1);
31
28
  return usedBefore < this.limit
32
29
  ? { allowed: true, retryAfterSec: 0, remaining: this.limit - usedBefore - 1 }
33
30
  : { allowed: false, retryAfterSec: Math.max(1, this.counter.retryAfterSec()), remaining: 0 };
34
31
  }
35
- /** The flush loop self-reaps old windows; the periodic sweeper has nothing to do for this backend. */
36
32
  sweep() {
37
- /* no-op */
38
33
  }
39
- // write-behind lifecycle (delegated; exposed for tests/parity)
40
34
  flush() {
41
35
  return this.counter.flush();
42
36
  }
@@ -46,7 +40,7 @@ export class TiDBRateLimiter {
46
40
  startRefresh(intervalMs) {
47
41
  this.refreshRequested = true;
48
42
  this.refreshIntervalMs = intervalMs;
49
- this.syncRefresh(); // 关断态下**不起环**:恒构造的代价必须是零 SQL,否则「默认部署」白付一条后台环
43
+ this.syncRefresh();
50
44
  return this;
51
45
  }
52
46
  stop() {