@sema-agent/server 7.148.0 → 7.150.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 (360) hide show
  1. package/MIGRATION.md +551 -9
  2. package/README.md +17 -2
  3. package/README.zh-CN.md +5 -1
  4. package/USAGE.md +126 -68
  5. package/dist/adoption/wire.d.ts +3 -3
  6. package/dist/approval-card.d.ts +33 -33
  7. package/dist/approval-gate-currency.d.ts +1 -1
  8. package/dist/approval-leg-origin.d.ts +33 -0
  9. package/dist/approval-leg-origin.js +4 -0
  10. package/dist/audit.d.ts +1 -1
  11. package/dist/audit.js +2 -2
  12. package/dist/auth-bridge.d.ts +9 -1
  13. package/dist/auth-bridge.js +4 -4
  14. package/dist/auth-keys.d.ts +10 -1
  15. package/dist/auth-keys.js +8 -0
  16. package/dist/background-session-reap.d.ts +1 -1
  17. package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
  18. package/dist/boot/deferred-sandbox-path-env.js +1 -2
  19. package/dist/boot/execution-env.js +10 -11
  20. package/dist/boot/execution-lane.d.ts +6 -4
  21. package/dist/boot/execution-lane.js +3 -1
  22. package/dist/boot/org-delivery.d.ts +3 -2
  23. package/dist/boot/parked-revive-gate.d.ts +5 -5
  24. package/dist/boot/parked-revive-gate.js +2 -3
  25. package/dist/boot/resolve-spec.d.ts +4 -5
  26. package/dist/boot/resolve-spec.js +66 -28
  27. package/dist/boot/retention-lane.d.ts +1 -1
  28. package/dist/boot/runner-deps.js +3 -1
  29. package/dist/boot/session-faces.js +21 -21
  30. package/dist/boot/stage-01-config.d.ts +1 -0
  31. package/dist/boot/stage-01-config.js +4 -3
  32. package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
  33. package/dist/boot/stage-02-web-admin-pull.js +10 -2
  34. package/dist/boot/stage-03-store-backend.d.ts +1 -0
  35. package/dist/boot/stage-03-store-backend.js +4 -4
  36. package/dist/boot/stage-04-stores.d.ts +1 -0
  37. package/dist/boot/stage-05-execution-env.d.ts +1 -0
  38. package/dist/boot/stage-06-runners.d.ts +2 -1
  39. package/dist/boot/stage-06-runners.js +1 -2
  40. package/dist/boot/stage-07-capability-layer.d.ts +2 -1
  41. package/dist/boot/stage-07-capability-layer.js +1 -1
  42. package/dist/boot/stage-08-reapers.d.ts +2 -1
  43. package/dist/boot/stage-09-leader.d.ts +2 -1
  44. package/dist/boot/stage-10-http-server.d.ts +35 -2
  45. package/dist/boot/stage-10-http-server.js +9 -4
  46. package/dist/boot/stores.d.ts +3 -0
  47. package/dist/boot/stores.js +22 -19
  48. package/dist/boot/web-admin.d.ts +1 -1
  49. package/dist/capabilities/tool-defer.d.ts +1 -1
  50. package/dist/capability-facts.d.ts +70 -60
  51. package/dist/capability-facts.js +45 -49
  52. package/dist/card-settle-stored-scope.d.ts +56 -0
  53. package/dist/card-settle-stored-scope.js +27 -0
  54. package/dist/card-void.d.ts +7 -12
  55. package/dist/card-void.js +2 -7
  56. package/dist/config-catalog.d.ts +12 -0
  57. package/dist/config-catalog.js +37 -33
  58. package/dist/config-invariants.d.ts +5 -4
  59. package/dist/config-invariants.js +4 -4
  60. package/dist/config-types.d.ts +49 -16
  61. package/dist/config.d.ts +6 -5
  62. package/dist/config.js +35 -24
  63. package/dist/context-window-notice.d.ts +31 -0
  64. package/dist/context-window-notice.js +28 -0
  65. package/dist/deployment-governance.d.ts +7 -28
  66. package/dist/deployment-governance.js +1 -14
  67. package/dist/deployment-shape.d.ts +20 -11
  68. package/dist/deployment-shape.js +1 -0
  69. package/dist/device-ws-hub.d.ts +1 -0
  70. package/dist/device-ws-hub.js +64 -28
  71. package/dist/device-ws-protocol.d.ts +20 -6
  72. package/dist/device-ws-protocol.js +9 -2
  73. package/dist/engine-identity.d.ts +7 -1
  74. package/dist/engine-identity.js +5 -0
  75. package/dist/env-name-allowlist-knobs.d.ts +6 -5
  76. package/dist/env-name-allowlist-knobs.js +5 -0
  77. package/dist/execution-lane-caps.d.ts +20 -5
  78. package/dist/execution-lane-caps.js +18 -4
  79. package/dist/field-conflict.d.ts +2 -2
  80. package/dist/fleet/engine-signal.d.ts +14 -1
  81. package/dist/fleet/engine-signal.js +5 -1
  82. package/dist/fleet/fleet-reconciler.d.ts +1 -1
  83. package/dist/fleet/serving-lease.d.ts +18 -3
  84. package/dist/fleet/serving-lease.js +81 -35
  85. package/dist/fleet-client.d.ts +13 -11
  86. package/dist/fleet-client.js +53 -33
  87. package/dist/history-anchor.js +1 -1
  88. package/dist/hitl-delivery.d.ts +1 -3
  89. package/dist/hitl-delivery.js +1 -1
  90. package/dist/hooks/command-spawn.d.ts +7 -2
  91. package/dist/hooks/command-spawn.js +13 -6
  92. package/dist/hooks/hook-runner.d.ts +5 -0
  93. package/dist/hooks/hook-runner.js +11 -7
  94. package/dist/http/active-run-conflict.d.ts +3 -7
  95. package/dist/http/active-run-conflict.js +2 -2
  96. package/dist/http/admission.js +5 -5
  97. package/dist/http/approval-sweeps.js +5 -3
  98. package/dist/http/caller-trust.d.ts +2 -2
  99. package/dist/http/caller-trust.js +3 -3
  100. package/dist/http/checkpoint-ctx.d.ts +18 -63
  101. package/dist/http/checkpoint-ctx.js +1 -24
  102. package/dist/http/claim-heartbeat.d.ts +6 -6
  103. package/dist/http/claim-heartbeat.js +6 -6
  104. package/dist/http/claimed-run.d.ts +16 -9
  105. package/dist/http/claimed-run.js +8 -0
  106. package/dist/http/dispatch.js +7 -5
  107. package/dist/http/durable-run-leg.d.ts +8 -1
  108. package/dist/http/durable-run-leg.js +34 -15
  109. package/dist/http/execution-context.d.ts +115 -14
  110. package/dist/http/execution-context.js +130 -40
  111. package/dist/http/owner-access.d.ts +246 -21
  112. package/dist/http/owner-access.js +186 -8
  113. package/dist/http/principal-gate.d.ts +18 -11
  114. package/dist/http/principal-gate.js +3 -1
  115. package/dist/http/readiness.d.ts +4 -2
  116. package/dist/http/resume-ctx-read.d.ts +14 -3
  117. package/dist/http/resume-ctx-read.js +24 -3
  118. package/dist/http/resume-legs.d.ts +35 -3
  119. package/dist/http/resume-legs.js +262 -106
  120. package/dist/http/route-ctx.d.ts +29 -11
  121. package/dist/http/routes/a2a-serve.js +17 -14
  122. package/dist/http/routes/approvals-assistant.d.ts +3 -2
  123. package/dist/http/routes/approvals-assistant.js +11 -11
  124. package/dist/http/routes/capabilities.js +5 -4
  125. package/dist/http/routes/config-catalog.d.ts +1 -1
  126. package/dist/http/routes/diagnostics.d.ts +3 -1
  127. package/dist/http/routes/diagnostics.js +30 -5
  128. package/dist/http/routes/mcp-reconnect.js +2 -2
  129. package/dist/http/routes/memory-origin.d.ts +1 -1
  130. package/dist/http/routes/notify-wake.js +2 -3
  131. package/dist/http/routes/principal-inbox.d.ts +3 -1
  132. package/dist/http/routes/principal-inbox.js +3 -2
  133. package/dist/http/routes/projects.d.ts +1 -0
  134. package/dist/http/routes/projects.js +5 -3
  135. package/dist/http/routes/retention-ops.d.ts +1 -1
  136. package/dist/http/routes/run-permission-mode.d.ts +1 -1
  137. package/dist/http/routes/run-permission-mode.js +2 -2
  138. package/dist/http/routes/runs.d.ts +1 -1
  139. package/dist/http/routes/runs.js +33 -37
  140. package/dist/http/routes/session-memory-sync.js +4 -5
  141. package/dist/http/routes/session-sync.d.ts +24 -5
  142. package/dist/http/routes/session-sync.js +45 -37
  143. package/dist/http/routes/sessions-list.d.ts +1 -1
  144. package/dist/http/routes/sessions.d.ts +1 -1
  145. package/dist/http/routes/sessions.js +18 -44
  146. package/dist/http/routes/tasks.js +136 -101
  147. package/dist/http/routes/trace-usage.js +14 -14
  148. package/dist/http/routes/workflows.d.ts +1 -0
  149. package/dist/http/routes/workflows.js +20 -38
  150. package/dist/http/server.d.ts +12 -9
  151. package/dist/http/server.js +35 -6
  152. package/dist/http/stored-body-replay.d.ts +3 -24
  153. package/dist/http/stored-body-replay.js +2 -12
  154. package/dist/http/submit-ctx.d.ts +2 -2
  155. package/dist/http/submit-ctx.js +5 -5
  156. package/dist/http/submit-replay.d.ts +15 -2
  157. package/dist/http/submit-replay.js +10 -4
  158. package/dist/http/wire-types.d.ts +6 -3
  159. package/dist/index.d.ts +3 -1
  160. package/dist/index.js +1 -0
  161. package/dist/leader/endpoint.js +9 -8
  162. package/dist/leg-facts.d.ts +13 -2
  163. package/dist/leg-facts.js +2 -0
  164. package/dist/local-store-declaration.d.ts +54 -0
  165. package/dist/local-store-declaration.js +59 -0
  166. package/dist/mcp-assertion-header.d.ts +1 -1
  167. package/dist/mcp-assertion-header.js +1 -1
  168. package/dist/mcp-authorization-face.d.ts +18 -14
  169. package/dist/mcp-authorization-face.js +3 -2
  170. package/dist/memory-project-layer.js +1 -1
  171. package/dist/memory-scope.d.ts +4 -4
  172. package/dist/memory-scope.js +4 -4
  173. package/dist/memory-store-refusal.d.ts +1 -1
  174. package/dist/memory-sync-client.js +2 -2
  175. package/dist/model-context-window.d.ts +50 -11
  176. package/dist/model-context-window.js +20 -1
  177. package/dist/model-entry-refusal.d.ts +5 -4
  178. package/dist/model-entry-refusal.js +17 -3
  179. package/dist/model-reach-scope.d.ts +2 -1
  180. package/dist/observability/corrupt-read-seat.d.ts +1 -1
  181. package/dist/observability/fail-open.d.ts +19 -7
  182. package/dist/observability/fail-open.js +19 -7
  183. package/dist/observability/logger.d.ts +7 -0
  184. package/dist/observability/logger.js +3 -1
  185. package/dist/observability/metrics.js +1 -1
  186. package/dist/observability/run-terminal.d.ts +1 -1
  187. package/dist/observability/run-terminal.js +1 -0
  188. package/dist/observability/secret-env-scrub.d.ts +1 -1
  189. package/dist/observability/secret-env-scrub.js +1 -1
  190. package/dist/org-delivery-gate.d.ts +31 -6
  191. package/dist/org-delivery-gate.js +7 -4
  192. package/dist/owner-faces.d.ts +30 -5
  193. package/dist/owner-faces.js +2 -0
  194. package/dist/park-row-commit.d.ts +67 -0
  195. package/dist/park-row-commit.js +76 -0
  196. package/dist/parked-decide.d.ts +9 -7
  197. package/dist/parked-decide.js +25 -6
  198. package/dist/peer-directory.d.ts +1 -1
  199. package/dist/peer-seat.d.ts +1 -1
  200. package/dist/peer-seat.js +52 -59
  201. package/dist/plugins/adoption-log-sql.d.ts +3 -3
  202. package/dist/plugins/adoption-log-sql.js +19 -19
  203. package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
  204. package/dist/plugins/approval-ask-store-sql.js +3 -5
  205. package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
  206. package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
  207. package/dist/plugins/approval-exemption-skill-m46.d.ts +0 -6
  208. package/dist/plugins/approval-exemption-skill-m46.js +6 -10
  209. package/dist/plugins/approval-exemption-store.d.ts +26 -1
  210. package/dist/plugins/approval-exemption-store.js +28 -19
  211. package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -3
  212. package/dist/plugins/ensure-schema-lock-policy.js +75 -9
  213. package/dist/plugins/exec-path-law.d.ts +34 -0
  214. package/dist/plugins/exec-path-law.js +13 -0
  215. package/dist/plugins/file-run-store.d.ts +22 -9
  216. package/dist/plugins/file-run-store.js +51 -23
  217. package/dist/plugins/local-checkpoint-store.d.ts +8 -1
  218. package/dist/plugins/local-checkpoint-store.js +5 -1
  219. package/dist/plugins/local-data-root-admission.d.ts +52 -0
  220. package/dist/plugins/local-data-root-admission.js +100 -0
  221. package/dist/plugins/local-engine-high-water.d.ts +28 -7
  222. package/dist/plugins/local-engine-high-water.js +27 -22
  223. package/dist/plugins/local-session-store.d.ts +134 -49
  224. package/dist/plugins/local-session-store.js +149 -108
  225. package/dist/plugins/memory-run-store.d.ts +14 -9
  226. package/dist/plugins/memory-run-store.js +48 -22
  227. package/dist/plugins/one-time-migration-marker.d.ts +19 -3
  228. package/dist/plugins/one-time-migration-marker.js +7 -1
  229. package/dist/plugins/one-time-migrations.d.ts +110 -59
  230. package/dist/plugins/one-time-migrations.js +224 -136
  231. package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
  232. package/dist/plugins/org-delivery-quota-store.js +29 -14
  233. package/dist/plugins/permission-rule-store-sql.d.ts +1 -1
  234. package/dist/plugins/permission-rule-store-sql.js +5 -9
  235. package/dist/plugins/pg-pool.d.ts +1 -1
  236. package/dist/plugins/pg-pool.js +14 -12
  237. package/dist/plugins/posix-shell-fs.js +4 -2
  238. package/dist/plugins/remote-env-adb.js +3 -2
  239. package/dist/plugins/remote-env-device.d.ts +3 -2
  240. package/dist/plugins/remote-env-device.js +8 -6
  241. package/dist/plugins/remote-env-e2b.d.ts +4 -8
  242. package/dist/plugins/remote-env-e2b.js +21 -15
  243. package/dist/plugins/remote-env-host.d.ts +51 -10
  244. package/dist/plugins/remote-env-host.js +97 -31
  245. package/dist/plugins/remote-env-k8s.js +7 -4
  246. package/dist/plugins/remote-env-local-docker.d.ts +6 -3
  247. package/dist/plugins/remote-env-local-docker.js +11 -25
  248. package/dist/plugins/remote-env-ssh.js +4 -3
  249. package/dist/plugins/remote-shell.d.ts +3 -1
  250. package/dist/plugins/remote-shell.js +3 -3
  251. package/dist/plugins/replica-registration.d.ts +35 -0
  252. package/dist/plugins/replica-registration.js +48 -0
  253. package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
  254. package/dist/plugins/run-store-sql.d.ts +27 -8
  255. package/dist/plugins/run-store-sql.js +46 -18
  256. package/dist/plugins/scenario-prefix-switch-m42.d.ts +8 -12
  257. package/dist/plugins/scenario-prefix-switch-m42.js +9 -6
  258. package/dist/plugins/schema-consistency.d.ts +91 -5
  259. package/dist/plugins/schema-consistency.js +189 -7
  260. package/dist/plugins/schema-drift-sentence.d.ts +6 -5
  261. package/dist/plugins/schema-drift-sentence.js +13 -5
  262. package/dist/plugins/serving-requirement.d.ts +49 -0
  263. package/dist/plugins/serving-requirement.js +53 -0
  264. package/dist/plugins/session-placement.d.ts +5 -4
  265. package/dist/plugins/shell-sentinel-owner-m48.d.ts +22 -0
  266. package/dist/plugins/shell-sentinel-owner-m48.js +6 -0
  267. package/dist/plugins/stop-then-start-sentence.d.ts +55 -0
  268. package/dist/plugins/stop-then-start-sentence.js +51 -0
  269. package/dist/plugins/store-backend.d.ts +23 -9
  270. package/dist/plugins/store-backend.js +58 -24
  271. package/dist/plugins/store-contracts.d.ts +45 -5
  272. package/dist/plugins/store-contracts.js +19 -0
  273. package/dist/plugins/tidb-pool.d.ts +11 -6
  274. package/dist/plugins/tidb-pool.js +22 -12
  275. package/dist/plugins/workspace-custody.d.ts +44 -0
  276. package/dist/plugins/workspace-custody.js +47 -0
  277. package/dist/process-instance.d.ts +3 -0
  278. package/dist/process-instance.js +7 -0
  279. package/dist/project-context.d.ts +66 -0
  280. package/dist/project-context.js +70 -0
  281. package/dist/project-identity.d.ts +8 -7
  282. package/dist/project-identity.js +40 -17
  283. package/dist/project-layer-key.d.ts +13 -2
  284. package/dist/project-layer-key.js +9 -1
  285. package/dist/question.d.ts +9 -21
  286. package/dist/question.js +28 -19
  287. package/dist/read-deny-floor-notice.d.ts +36 -0
  288. package/dist/read-deny-floor-notice.js +40 -0
  289. package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
  290. package/dist/request-declaration-disposition.js +39 -0
  291. package/dist/run-cancel-card.d.ts +28 -0
  292. package/dist/run-cancel-card.js +20 -0
  293. package/dist/run-cancel-context.d.ts +10 -0
  294. package/dist/run-cancel-context.js +1 -0
  295. package/dist/run-local.js +28 -13
  296. package/dist/runs.d.ts +31 -7
  297. package/dist/runs.js +34 -16
  298. package/dist/security.d.ts +3 -3
  299. package/dist/server-secret-env.d.ts +34 -20
  300. package/dist/server-secret-env.js +61 -18
  301. package/dist/session-agent.d.ts +4 -12
  302. package/dist/session-agent.js +0 -6
  303. package/dist/session-children-retire.d.ts +6 -3
  304. package/dist/session-children-retire.js +2 -5
  305. package/dist/session-incarnation.d.ts +18 -4
  306. package/dist/session-incarnation.js +4 -1
  307. package/dist/session-notify-door.d.ts +4 -4
  308. package/dist/session-notify-door.js +5 -6
  309. package/dist/session-rules-seat.d.ts +4 -3
  310. package/dist/session-rules-seat.js +3 -11
  311. package/dist/session-sync.js +3 -3
  312. package/dist/session-workspace.d.ts +3 -3
  313. package/dist/store-admission.d.ts +33 -0
  314. package/dist/store-admission.js +49 -0
  315. package/dist/store-posture.d.ts +5 -0
  316. package/dist/store-posture.js +18 -1
  317. package/dist/stores-sql/checkpoint-store-sql.d.ts +22 -3
  318. package/dist/stores-sql/checkpoint-store-sql.js +109 -23
  319. package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
  320. package/dist/stores-sql/file-history-store-sql.js +3 -5
  321. package/dist/stores-sql/retention-store-sql.d.ts +1 -1
  322. package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
  323. package/dist/stores-sql/tool-result-store-sql.js +4 -6
  324. package/dist/task-a2a.d.ts +3 -8
  325. package/dist/task-a2a.js +25 -27
  326. package/dist/task-cwd.d.ts +27 -10
  327. package/dist/task-cwd.js +3 -0
  328. package/dist/task-mcp.d.ts +3 -3
  329. package/dist/task-mcp.js +1 -1
  330. package/dist/task-settings.d.ts +13 -0
  331. package/dist/task-settings.js +14 -7
  332. package/dist/terminal.d.ts +2 -0
  333. package/dist/terminal.js +21 -6
  334. package/dist/tool-approval.d.ts +50 -41
  335. package/dist/tool-approval.js +96 -73
  336. package/dist/trace/engine-notice-wire.d.ts +38 -21
  337. package/dist/trace/engine-notice-wire.js +25 -4
  338. package/dist/trace/ledger-sink.d.ts +3 -1
  339. package/dist/trace/project.d.ts +8 -5
  340. package/dist/trace/project.js +11 -9
  341. package/dist/trace/projection-table.d.ts +33 -2
  342. package/dist/trace/redact.d.ts +12 -0
  343. package/dist/trace/redact.js +5 -1
  344. package/dist/trace/self-minted-wire.d.ts +268 -56
  345. package/dist/trace/self-minted-wire.js +110 -40
  346. package/dist/trace/tool-card.d.ts +3 -0
  347. package/dist/trace/tool-card.js +24 -0
  348. package/dist/trace/tool-output-media.d.ts +2 -1
  349. package/dist/unattended-permission-mode.d.ts +1 -1
  350. package/dist/web-admin-client/apply-effective.d.ts +1 -1
  351. package/dist/web-admin-client/apply-effective.js +22 -9
  352. package/dist/web-admin-client/effective-keys.d.ts +1 -1
  353. package/dist/web-admin-client/skills-mcp.d.ts +1 -1
  354. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -29
  355. package/docs/error-text-lexicon.json +317 -0
  356. package/package.json +4 -2
  357. package/scripts/embed-minimal.mjs +183 -0
  358. package/wire-changes/server@7.149.0.json +372 -0
  359. package/wire-changes/server@7.150.0.json +335 -0
  360. package/dist/plain-string-record.js +0 -70
@@ -1,7 +1,13 @@
1
1
  export const MIGRATION_MARKER_TABLE = "one_time_migration_marker";
2
+ export const SKILL_EXEMPTION_CUTOFF_ID = "M46";
2
3
  export function migrationMarkerDdl(dialect) {
3
4
  return dialect === "mysql"
4
- ? `CREATE TABLE IF NOT EXISTS ${MIGRATION_MARKER_TABLE} (migration_id VARCHAR(16) NOT NULL PRIMARY KEY, marked_at_ms BIGINT NOT NULL)`
5
+ ? `CREATE TABLE IF NOT EXISTS ${MIGRATION_MARKER_TABLE} (migration_id VARCHAR(16) NOT NULL PRIMARY KEY, marked_at_ms BIGINT NOT NULL) COLLATE utf8mb4_bin`
5
6
  : `CREATE TABLE IF NOT EXISTS ${MIGRATION_MARKER_TABLE} (migration_id VARCHAR(16) COLLATE "C" NOT NULL PRIMARY KEY, marked_at_ms BIGINT NOT NULL)`;
6
7
  }
8
+ export function markIfAbsentSql(dialect) {
9
+ return dialect === "mysql"
10
+ ? `INSERT INTO ${MIGRATION_MARKER_TABLE} (migration_id, marked_at_ms) VALUES (?, ?) ON DUPLICATE KEY UPDATE migration_id = migration_id`
11
+ : `INSERT INTO ${MIGRATION_MARKER_TABLE} (migration_id, marked_at_ms) VALUES ($1, $2) ON CONFLICT (migration_id) DO NOTHING`;
12
+ }
7
13
  //# sourceMappingURL=one-time-migration-marker.js.map
@@ -12,7 +12,9 @@
12
12
  * **≥** 某条未发布形的 `introducedIn` 而两格仍是 `null` ⇒ 红(发布准备提交就是回填时刻,忘了就当场红;版本更低 = 还在开发,不红)。
13
13
  * 最后一条删掉时,整个文件连同 `StoreBackend.runOneTimeMigrations()`(npm 公面上的接口成员)、`NO_SQL_MIGRATIONS`、
14
14
  * `logOneTimeMigrations` / `runAndLogOneTimeMigrations`、三只后端与两只测试夹具上的实现、`boot/stores.ts` 的调用点一起删 —— 零例外:本文件里只有带窗的迁移与它们自己的
15
- * 帮手(两只在场探针、锁腿、方言适配器);没有窗的东西(跳版升级的库的拒启臂)住在起服对账一族(`schema-consistency.ts`),不在这里。
15
+ * 帮手(两只在场探针、锁腿、方言适配器)与迁移段的**段头**两步(副本能力登记、起服准入 —— 常设,码在 `replica-registration.ts` / `serving-requirement.ts`,本文件只在 {@link runSqlOneTimeMigrations}
16
+ * 里排它们的序;最后一条迁移删码时,段头连同锁腿搬进起服序列,不随文件删);没有窗的东西(跳版升级的库的拒启臂)住在起服对账一族(`schema-consistency.ts`、`approval-exemption-skill-cutoff.ts`、local 的
17
+ * `local-data-root-admission.ts`),不在这里 —— 那条迁移还在时臂只判、不拒,读本文件的 {@link migrationCarried}(行随码同删 ⇒ 删码那一版起臂恒判)。
16
18
  * 其余文件一律只写「窗口见本文件登记表」,不各写一个日期或版本 —— [ref] 之前本文件头写死了一个删除版本号(7.75.0),
17
19
  * 连同 11 个文件里的复述共 23 行;那一版过去了 28 个 minor 也没删,7.93.5 反倒往本文件里又加了一条迁移。
18
20
  *
@@ -24,7 +26,7 @@
24
26
  * ⇒ 换成本段:**升一次级把存量字节改完,兼容臂当场删干净**。代价是每一条在它的窗内每次启动都要跑一遍(第二次起全是
25
27
  * 零命中的空转);收益是窗关之后可以把那一条连同它的 SQL 一起删,而读腿从引入那一版起就只有**一种**读法。
26
28
  *
27
- * ## 已退役的 M1–M11 与 M14
29
+ * ## 已退役的 M1–M12 与 M14
28
30
  * 退役的整树快照索引表(M1)、退役的单座 steering 列(M2)、被上游改了名的闭集词 `unresolvable` → `ancestor_marked`(M3)三条的改写、计数与读数
29
31
  * 窗关后已全部删码,登记行一并删。跳过了它们直接升的库由起服对账一族的拒启臂接住(`schema-consistency.ts` 头注「第二道对账」一节:两件退役 schema
30
32
  * 任一在场 ⇒ 拒启、点名出路;先于一切建表)—— 那一道没有窗,所以不在本文件里。本段入口({@link runSqlOneTimeMigrations})不问这一问。
@@ -63,12 +65,13 @@
63
65
  * 那一行不参与任何检查,但撤销口删不动它(引擎的写臂对这种 scope 同样拒)。出路 = 运维在库里把那只桶的那一行删掉(整桶 OCC 回写,指纹按 `buildRuleBucketChecksum` 重算)。
64
66
  * 起服不再逐桶扫描、也不再有逐行 / 逐桶的删除告警;读腿整桶拒的桶照旧整桶拒(出路是人)。local 车道的持久规则在引擎自己的 File 分区里,这一半对它本来就是空转。
65
67
  *
68
+ * M12(停驻行模式词读法记号的拒臂;不写库;7.150.0 删,窗 2026-11-08 关,发版日前已关)同样已删码,登记行一并删:判据、拒臂与答复、两处记号写点与 ctx 上的记号位都没有了,续跑重放不再问「行上有没有记号」。逐条写跳过了它直接升的库由谁接住:
69
+ * ⑦ 停驻行模式词读法记号的拒臂(M12):没有响亮臂 —— 7.121.x 及以前写下、此刻仍停驻的行(把 `APPROVAL_TERMINAL_BACKSTOP_MS` 调长的部署,或跳过了带本条的版本直接升的库)体里是请求原词、没有记号;
70
+ * 在设了 `AUTONOMY=plan` 的部署上不再被拒,续跑按体里的原词重放(运维的 plan 不再被按段重钳;`plan_review` 的驳回仍由引擎留在 plan)。存量行上的那只记号键原样留着、无人读。出路 = 升级前把这些停驻的 run 决掉 / 取消,
71
+ * 或升级窗内设 `AUTONOMY=read-only`(按段的只读围栏)。
72
+ *
66
73
  * ## 窗内的迁移(逐条的失败方向刻意不同)
67
- * · **M12 停驻行模式词读法记号的拒臂**(7.122.0)—— 持久数据「响亮拒」那一半:7.122.0 起一条 run 的模式词只有存储体顶层 `permissionMode`
68
- * 一个源(提交入口盖运维 `AUTONOMY=plan` 的地板一次),更早的行体里是请求原词、运维的 plan 由治理层每段重钳。续跑重放之前:本部署此刻有入口地板 ∧
69
- * ctx 上没有当前记号 `"entry_word"` ∧ 体的生效词被地板钳会变 ⇒ 认领之前 409、行字节不动。规则、拒句与写点在 `http/checkpoint-ctx.ts` 顶注第三问。
70
- * 没有读数键(它不写库)。
71
- * · **M13 盘上 LKG 信封 formatVersion 2 → 3**(7.123.0)—— 不在店里(配置候选的盘上缓存,与 M12 同为非店迁移):被丢目录条目收成一份载体
74
+ * · **M13 盘上 LKG 信封 formatVersion 2 → 3**(7.123.0)—— 不在店里(配置候选的盘上缓存):被丢目录条目收成一份载体
72
75
  * (`models.droppedCatalogEntries`,每条被丢的目录条目一行),7.122.0 及以前写的 2 只记了有名且启用的行、记在旧键 `droppedIdentities`。
73
76
  * `config-lkg.ts` `loadLkg` 读回 2 时在内存里迁一次(旧载体搬成新载体、去掉 etag ⇒ 中心可达后第一拍整拉、重铸完整载体),启动日志
74
77
  * `config_lkg_migrated` 一行;写盘一律写 3。规则与判形在 `config-lkg.ts` 顶注与 `migrateV2Lkg`。没有读数键(它不写库)。
@@ -250,7 +253,7 @@
250
253
  * 每行单独读整只文档(一页里不同时持有两份停驻快照)、问那一只派生,答出词才写(`WHERE … AND approval_card IS NULL` CAS,第二跑零写);文档读不出 / 不是一只
251
254
  * 引擎读得了的检查点 ⇒ 计数、不写(这样的行续不了,`get()` 对同一格拒);答出的卡词放不进列(MySQL 协议 `TEXT` 按 UTF-8 字节 65,535;PG 无上限)⇒ 同一个态度:
252
255
  * 计数 + 一行 warn 点名(会话 id + 字节数)、不写、起服不挡 —— 引擎铸的卡词是闭集短词,超长只会是手改 / 外来写者写下的行,列留 NULL、读面按缺列读(与「无卡」同读;到期 facet 不变 —— 超长的词不可能是 core `CARD_FACET_OVERRIDES` 的键;文档一个字节没动)。排在 M21 之后:M21 给存量问答行补上的卡词由本条落列。**列不在 ⇒ 延后**(与 M36 同一条前置:
253
- * 迁移段先于起服列册对账,缺列表上的扫描会抛裸的「未知列」、盖住随后的拒启句)。到期 facet 的生成谓词与运维队列行的卡读这一列 —— 本条跑完之前它们不运行
256
+ * HTTP 服务起服时列册对账先于迁移段,缺列的库在那里就拒;不经对账的公开序列(嵌入方)上,缺列表上的扫描会抛裸的「未知列」)。到期 facet 的生成谓词与运维队列行的卡读这一列 —— 本条跑完之前它们不运行
254
257
  * (迁移段先于任何路由与收割器装配)。**够不到的一格(如实登记)**:已决 / 已作废的行不扫(没有读者读它们的卡);local 车道没有这一列(停驻行在引擎自己的 File 店,
255
258
  * 卡从文档读)。窗 = 发布日 + 30 天(与 M21 同一条论证:窗关时缺省部署上升级前停驻的行已被终局兜底收走)。
256
259
  * · **M30 停驻行请求体里的退役键 `promptProfile` 原地改写**(7.137.0,引擎 7.56.0)—— 提示词形收成布尔 `promptLean`,双形词 `promptProfile` 整键退役(新提交在键闭集门 400)。
@@ -355,7 +358,7 @@
355
358
  * `approval_ask.execution_lane` 与会话的 `execution_lane`(`session_meta` 上;M41 搬过之后在 `session_ext` 上 —— 三张表逐张读形,列在哪张改哪张)(本段**第一步**,先于任何写:列不在 ⇒ 那一张零动作 —— 跳版升上来的库由 M32 加列、按声明车道回填,不会再铸旧词);
356
359
  * local 的会话元数据边档(`session-incarnations.json` 的 `[会话].execution.lane`,**排在严格边档对账之前** —— `LocalBackend.ensureSchema()` 第一步,否则旧词先撞严格拒)
357
360
  * 与问账日志(排在 M32 的 local 问回填之前,一次压实重写整本)。**版本围栏(停-迁-起)**:旧副本不认 `none`、新读者不认旧词,列形不变 ⇒ 混跑没有列检查拦得住。
358
- * SQL:还有旧词行要改 ∧ 本库上仍有 run 在心跳(`task_run` 的 `running` 行在 `REAP_RUN_STALE_SEC` 之内更新过 —— 收割器判活的同一条谓词)⇒ 拒启
361
+ * SQL:还有旧词行要改 ∧ 有停-迁-起证据(`readOlderReplicaEvidence`:`task_run` 的 `running` 行在 `REAP_RUN_STALE_SEC` 之内更新过 —— 收割器判活的同一条谓词 —— 且持有者没有登记为知道 M40)⇒ 拒启
359
362
  * (`config.execution_lane_rename_refused`,一行没改;拒句给最新心跳时刻与「全停之后何时再起」);没有旧词行 ⇒ 零动作、可滚动。local:数据根的起服锁(core `FileStorageBackend` 的 `LOCK`)
360
363
  * 本来就只许一个进程 ⇒ 不另设守卫。读数 `executionLaneWordsRenamed`(四处合计)。幂等:第二次起服零命中零写。
361
364
  * · **M41 会话的部署格搬出引擎座表**(7.147.0)—— 引擎座表 `session_meta` 只带引擎的列;本服务记在会话上的十二格(标题 / 置顶 / 换源通告基线 / 位置与项目 / 执行放置七列 / fork 键)
@@ -364,7 +367,8 @@
364
367
  * (`ON DUPLICATE KEY UPDATE` / `ON CONFLICT DO UPDATE`:旁表那一行的这几格 = 根行上的值;中断后重跑同一句同一结果);② 逐行核对(每一列 null 安全相等,旁表行不在 = 缺省)——
365
368
  * 有一行不等 ⇒ 拒启 `config.session_ext_move_refused`(`copy_mismatch`,点名那只会话;一列没删,下一次起服重搬);③ **一句** `ALTER TABLE session_meta DROP COLUMN …` 删掉在场的全部部署格列
366
369
  * (按后置条件收敛:那几列都不在)。旁表形的库(本版新建、或已搬过)⇒ 零动作。**版本围栏(停-迁-起)**:旧副本对这十二格的每一笔写在删列之后都撞未知列,
367
- * 搬与删之间落下的写会丢 ⇒ 还有列要搬 ∧ 本库上仍有 run 在心跳(与 M40 同一条判活谓词)⇒ 拒启(`live_runs`,一字节没写;本段第二步,紧随 M40,先于任何别的写)。
370
+ * 搬与删之间落下的写会丢 ⇒ 还有列要搬 ∧ 有停-迁-起证据(与 M40 同一只读法)⇒ 拒启(`older_replica`,一字节没写;本段第二步,紧随 M40,先于任何别的写)。
371
+ * 如实的边(7.147.0 起已披露,不改):① 搬 → ② 核对 → ③ 删列三步之间一只没被看见的旧副本落下的写会丢 —— 删列让旧写在 ③ 之后响亮失败,却挡不住 ② 与 ③ 之间那一笔。
368
372
  * **M32 × M41 的序与读表**:迁移段里 M32 先、M41 后。M32 读两种形 —— 八列在 `session_meta` 上(7.139–7.146 形:M32 全程写根行,随后 M41 连同别的格一起搬进旁表)
369
373
  * 或部署格已在旁表(本条之后 / 新库)。旁表形里 M32 的加列 / 回填 / 收尾标记(② ④ ④b ⑥)都不跑(切换早已收尾;回填前提的拒随之不判),剩 ⓪(旧版副本建回的空退役表删掉)、围栏,
370
374
  * 与围栏拒句「采旧」造出的中途表 ③ ⑤ —— ③ 写执行格当下的家(旁表:先补行、再覆盖,`migrateDeviceBindingsOntoSideTableStatements`)。删码不改语义:本条删码时 M32 若还在,改成恒旁表形(见登记行)。
@@ -372,19 +376,19 @@
372
376
  * · **M42 场景前缀的切换检查**(7.148.0)—— 本版起以 `_scn:` 开头的身份读作「某个人的某个场景」(恢复管线 `owner-brands.ts` 的 `partsOf`);更早的版本不保留这一前缀,
373
377
  * 自称 `_scn:<x>:<y>` 的调用方写下的行在本版会被读成另一个人的场景。**持久数据「响亮拒」那一半,不改写**:库里没有本条的标记 ⇒ 只读扫存量身份(本树建表句里名字以
374
378
  * owner / scope / principal / subject 结尾、且库里在的每一列;local = run / 会话 / 问 / 附件四处 File 店的属主),一处命中 ⇒ 拒启 `config.scenario_prefix_switch_refused`(点名来源与行数,
375
- * 一字节没写);零命中 ⇒ 写标记;有标记 ⇒ 不扫(本版自己写下的合法 `_scn:` 行不让第二次起服拒启)。**停-迁-起(SQL)**:零命中而判活窗内仍有 run 在心跳(与 M40 / M41 同一条
376
- * 判活谓词)⇒ 同码拒启(`live_runs`),标记不写 —— 更早版本的副本不保留前缀,扫描之后它还会收下这类身份。标记随库(SQL:本条自己建的标记表一行;local:数据根里一只文件),
379
+ * 一字节没写);零命中 ⇒ 写标记;有标记 ⇒ 不扫(本版自己写下的合法 `_scn:` 行不让第二次起服拒启)。**停-迁-起(SQL)**:零命中而有停-迁-起证据(与 M40 / M41 同一只
380
+ * 读法)⇒ 同码拒启(`older_replica`),标记不写 —— 更早版本的副本不保留前缀,扫描之后它还会收下这类身份。标记随库(SQL:本条自己建的标记表一行;local:数据根里一只文件),
377
381
  * 不随进程。**第一步**:先于任何写(拒了就是一字节没动)。律、扫描面、拒句的唯一属主 = `scenario-prefix-switch-m42.ts`。读数 `scenarioPrefixSourcesScanned`(0 = 标记在场)。
378
382
  * · **M43 撤回出口的启用标记**(7.148.0)—— 不改任何存量行。提交出口撤回一只「受理之前就被拒」的提交铸下的会话之前,读旁表的客户端写计数 `client_writes`
379
383
  * (四个客户端写者在锁住根行之后同一事务 +1,`plugins/session-ext-table.ts`);更早版本的副本的写者不计数 ⇒ 混跑窗里它刚给这只会话改了标题,撤回却读到 0,会把人写过的会话删掉。
380
384
  * ⇒ 撤回出口只在本库的**标记行**落下之后启用(标记表与 M42 同一张,属主 `one-time-migration-marker.ts`;读者 = 撤回事务里的部署判据 `plugins/session-withdraw-sql.ts`,标记未落 ⇒ 答 `upgrade_pending` = 留,
381
- * 幽灵会话照旧)。标记由本步落:标记不在 ∧ 判活窗内没有 `running` run 更新过(与 M40 同一条谓词)⇒ 落;有 ⇒ 不落、**不拒启**,下一次起服再判(M42 的停-迁-起守卫在同一版里先拒过一次)。
385
+ * 幽灵会话照旧)。标记由本步落:标记不在 ∧ 没有停-迁-起证据(与 M40 同一只读法;登记为知道 M43 的副本持有的 run 不算)⇒ 落;有 ⇒ 不落、**不拒启**,下一次起服再判(M42 的停-迁-起守卫在同一版里先拒过一次)。
382
386
  * 读数 `withdrawMarkWritten`。local 车道:数据根独占、没有混跑窗,版本位在会话元数据格上(`clientWrites`,本版铸的格都带),恒零。
383
387
  * · **M51 会话在删态的切换**(7.148.0)—— 不改任何存量行。本版起删会话按会话三态走(活 → 在删 → 没了,律在 `src/session-deletion.ts`):围栏写旁表 `session_ext.deleting_token`,
384
388
  * 认领点(规则 L)读它、删除路只在围栏判一次认领。更早版本的副本不读在删态 ⇒ 混跑时它会在一只在删的会话上收下提交、建 run,而本版删除路的账本腿已不再判认领 ——
385
- * 比修前更坏。⇒ **停-迁-起**,没有运行期开关:标记表(与 M42 同一张)无 `M51` 行 ∧ 判活窗内有 `running` run 心跳(与 M40 / M41 / M42 同一条谓词 {@link readLiveRunHeartbeat})
386
- * ⇒ 拒启 `config.session_deleting_switch_refused`(`live_runs`,一字节不写,拒句给可再起的时刻);无心跳 ⇒ 落标记(之后本版副本自己的 run 不再挡起服)。
387
- * 看不见的边与 M43 同:空闲的旧副本(零 `running` run)没有心跳 —— MIGRATION 本版节写「全部旧副本停下再起」。读数 `sessionDeletingSwitchMarked`(0 或 1)。
389
+ * 比修前更坏。⇒ **停-迁-起**,没有运行期开关:标记表(与 M42 同一张)无 `M51` 行 ∧ 有停-迁-起证据(与 M40 / M41 / M42 同一只读法 {@link readOlderReplicaEvidence})
390
+ * ⇒ 拒启 `config.session_deleting_switch_refused`(`older_replica`,一字节不写,拒句给可再起的时刻);没有 ⇒ 落标记(之后不再判)。
391
+ * 看不见的边与 M43 同:空闲的、早于副本登记的旧副本(零 `running` run)没有证据 —— MIGRATION 写「全部旧副本停下再起」。读数 `sessionDeletingSwitchMarked`(0 或 1)。
388
392
  * local 车道:数据根独占、没有混跑窗 ⇒ 恒零。
389
393
  * · **M44 run 的 `errorCode` 只读列**(7.148.0)—— 码的唯一读法是 `task_run.error_code` 列;写 `result` 的三个写口同写这一列(停驻两口此前不写)。**改写半场**:
390
394
  * 按 `task_id` 键集分批扫 `result IS NOT NULL` 的行,目标 = 「这条行在稳定、非到期时修前 `GET` 会答的码」= 结果投影的码(`persistedPlaneOf`,读盘面认两代形并折码)?? 列原值;
@@ -400,11 +404,13 @@
400
404
  * local 腿 = `FileRunStore.migrateRunObjectivePreviewM45`(数据根独占)。读数 `runObjectivePreviewRewritten`。
401
405
  * · **M46 存量的引擎家 `Skill` 会话豁免行**(7.148.0)—— 会话豁免店的一行只记一件事:某人对这个 wire 工具名放过行、且那一问的应答不授予这次调用之外的东西。7.116.0 之前耐久腿曾为带摘要的 `Skill` 卡
402
406
  * (批准 = 激活某技能 + 它清单上的工具免问)与名单点名 `Skill` 的名单问落过 `(会话, "Skill")`;今天读者对「不绑授予」的同名调用读这一行 —— 而引擎说无技能时不挂 `Skill`、同名调用是另一只工具 ⇒ 存量行代答它是**扩权**。
403
- * **删,不加列、不加读侧的未知臂**:谓词 = `tool_name = <core 导出的引擎 Skill 工具名> ∧ created_at < T0`;**T0 = 本库第一次跑本步的时刻,先于删除落进标记**(SQL:标记表 `M46` 行;local:数据根里的标记文件),
407
+ * **删,不加列、不加读侧的未知臂**:谓词 = `tool_name = <core 导出的引擎 Skill 工具名> ∧ created_at < T0`;**T0 = 本库的 `Skill` 豁免截点,先于删除落下**(SQL:标记表 `M46` 行;local:数据根里的标记文件;
408
+ * 7.149.0 起由常设的一步在本步之前落 —— SQL `ensureSchema()` 的种子行、local 数据根准入的锁内一步;缺席时本步自己落),
404
409
  * 不按日历截(各部署升级日不同,日历截点会漏掉跳版直升的库里升级前几天写下的行)。第一次删升级前就在的全部 `Skill` 行(含 7.138.0–7.147.x 写下的合法行;方向 = 那些会话的人下一次 `Skill` 调用被重问一次),
405
410
  * 之后各跑零命中、不碰本版自己写下的新行。SQL:`session_id` 键集分批,一页一句 `DELETE … IN`;被打断 ⇒ 下一次起服读同一个 T0 接着删。local 腿 = `FileApprovalExemptionStore.dropToolRowsCreatedBeforeM46`
406
411
  * (对命中行逐会话追加墓碑,与按名撤销同形;日志已判坏的会话不碰),T0 在数据根的标记文件(M42 local 腿同形)。无停-迁-起守卫:更早版本的副本窗内写下的 `Skill` 行是它们当时合法的行,`created_at ≥ T0` 不被碰、`< T0` 被删,两个方向都是重问。
407
412
  * 读数 `legacySkillExemptionsDropped`(非零 ⇒ 一行 warn `legacy_skill_exemptions_dropped`)。存量规模上限 = 会话数 × 1。
413
+ * **删码之后**由常设的跳版拒启臂接住(`approval-exemption-skill-cutoff.ts`,同一条谓词):本条还在时它只判不拒;删码那一版起,截点之前的 `Skill` 行在场 ⇒ 先于任何写拒启(登记行 `afterRemoval`)。
408
414
  * · **M47 local 无格存档收进行,化身沿用存档头令牌**(7.148.0;local 独有 —— SQL 孪生没有存档头,住客只在 `session_meta.incarnation` 一格)—— 本版起一个数据根只有一只会话行店:
409
415
  * run-local 与 HTTP 服务的 local 臂经同一只 `openLocalBackend` 打开数据根、读同一格住客(`local-session-store.ts` 的 `occupiedBy` 注)。更早的 run-local 经引擎的文件仓直接建档、续跑,
410
416
  * 从不写会话元数据格,它的记忆引擎按**存档头**上引擎另铸的令牌落记录(采集 opt-out、污染标记)。这种「存档在而格缺」的会话,第一次读会补铸一只新令牌 —— 那些记录从此不绑。
@@ -417,6 +423,9 @@
417
423
  * 哨兵是一位普通的具名属主(只对字面相等的主体可见),改成无主 = 过了凭据门的任何主体都够得着;那里零改写、读数 0,行原样,本条照样记完成。
418
424
  * SQL:三张表各一句 `UPDATE … SET owner = NULL WHERE owner = <哨兵>`(逐字节比:MySQL 协议两边 `CAST(… AS BINARY)`,只差尾空格的另一位属主不动;表不在 ⇒ 跳过);local 腿 = `LocalSessionStore.clearShellSentinelOwnersM48`(会话元数据边档一次提交)
419
425
  * + `FileRunStore.clearShellSentinelOwnersM48`。读数 `shellSentinelOwnersCleared`(三处行数之和)。幂等:写后不再有哨兵值 ⇒ 第二跑零命中。
426
+ * **有身份边界的部署不改写,但数一遍留着的**:部署形读数是起服的那一个进程的配置,而改写落在整只库 / 数据根上、不可逆 —— 同一只库 / 根被身份配置不同的进程打开(`run-local` 不带服务凭据 / 桥、嵌入方的起服序列、连着共享库的临时进程)时,
427
+ * 一样身份键都不带的那个进程先起会替有边界的服务进程改写(边界是任一身份来源在的并)。有边界的那一臂因此对同一批改写面用**同一个比较**(SQL:`shellSentinelOwnerWhereM48` —— 与改写的 `UPDATE` 是同一句 WHERE、同一个绑定参数;local:`isShellSentinelOwnerM48`)只数不写,
428
+ * 读数 `shellSentinelOwnerRowsRetained`(逐面、只列非零)非空 ⇒ 一行 warn `shell_sentinel_rows_retained`(`logReceiptRows`)。窗内每次起服都数、每次起服都报,直到有人处置(出路:MIGRATION 7.148.0 节第 86 条的手工一步)。
420
429
  * 不改规则行(哨兵键下的规则此前也不对无主体任务生效,改键 = 放宽)、收件箱条目 / 问账行 / 检查点 scope(这些读面从没放过那一格)。
421
430
  * · **M49 检查点的归属会话回填**(7.148.0)—— `checkpoint.host_session_id`(一张卡归在哪只会话上 = 兑现它的那条 run 的会话;读法 `checkpoint-index-columns.ts` 的
422
431
  * `hostSessionOf`,写口 `put` 求值)本版新加;按 run 找卡的读口(取消、steer 停放、两条停驻收割、续跑输入回收、运维队列行的 run)此后只读它。存量行一律自 `session_id`
@@ -428,11 +437,11 @@
428
437
  * 已有格的会话不动(行令牌胜:本仓每一个按住客的读已在答它):升级前 run-local 在头令牌下给它们落过的记录升级后不再绑(MIGRATION 披露)。
429
438
  * 窗内「已在盘的旧存档长第一格」只有这一条规则(`local-session-store.ts` 的 `firstCellIncarnationOf`):本条的起服扫是它的急切版,按 id 打开 / 读时的补铸、登记、执行位回填、
430
439
  * M33 的行回填与快照恢复同经它 —— 不调起服对账的嵌入方同一次起服里按 id 打开旧会话,住客也不变。
431
- * **收令牌欠账**:高水位按律判过即抬、先于本条 —— 「谁可能写过这只根」与「这只根还欠不欠本条」是两件事。带本条的构建打开数据根时(高水位判过、**抬之前**),
440
+ * **收令牌欠账**:高水位按律判过即抬、先于本条 —— 「谁可能写过这只根」与「这只根还欠不欠本条」是两件事。带本条的构建打开数据根时(准入判过、锁内**抬之前**),
432
441
  * 打开之前的高水位早于 7.148.0 或缺席 ∧ 存档目录里有存档 ⇒ 原子写数据根顶层的欠账标记 `archive-token-adoption.pending`(`required`;本服务内部、不是公开契约);
433
442
  * 本条在欠账起服里以 `required` 提交、再用常驻臂那一只读法证明收齐(剔除 placed 与存档头读不出两类 = 本条的收取范围)之后才删它 —— 任何一步失败标记留着、起服拒,下一次窗内起服重来。
434
443
  * **跳版拒启臂(常设,不随本条删)**:不带本条的构建打开数据根时,(打开之前的引擎高水位早于 7.148.0 或缺席 ∨ 欠账标记在)∧ 根里有存档在而格缺的会话
435
- * ⇒ `local-session-store.ts` 的 `holdArchiveTokenAdoptionDuty` 拒启(`config.schema_mismatch`,读数种别 `skipped-required-migration`;标记在而无格存档为零 ⇒ 无事可收,销账放行)—— 它在数据根打开的同步段里、引擎高水位**抬之前**判
444
+ * ⇒ `local-session-store.ts` 的 `judgeArchiveTokenAdoptionDuty` 拒启(`config.schema_mismatch`,读数种别 `skipped-required-migration`;标记在而无格存档为零 ⇒ 无事可收,锁内抬之前销账放行)—— 它是数据根准入的一格(只读,本进程第一笔写之前;`local-data-root-admission.ts`)
436
445
  * (拒 ⇒ 不抬,出路那一版仍开得了这只根:不比已记高水位旧、仍带本条);本条在树里时那一判换成记账(登记表里有本行 ⇒ 记、不判)。读数 `localArchiveTokensAdopted` / `localArchiveTokensMinted`;只 local(SQL 恒零)。
437
446
  * · **M50 local 问账日志里退役动词 `deleteByTask` 的记录**(7.148.0)—— 店接口的按 run 删除动词本版退役(删会话的审批腿 `deleteBySession` 取代它),File 账本的动词闭集随之少一个词。
438
447
  * 本服务已发版本没有任何生产路径调过它;嵌入方经导出的店型调过、且进程停在那一次压实之前,账本里才会留一条它的记录。持久面不翻红:与 M38 同形的**窗内才生效的行为臂**
@@ -440,6 +449,11 @@
440
449
  * (删 `taskId` 名下的问与批 —— 今天删会话级联的一个子集,语义不丢,`InMemoryApprovalAskStore.deleteByTaskM50`)并算删行记录,构造器末段的起服压实把整本重写成存活行的快照、记录离盘
441
450
  * (压实失败 ⇒ 位留着,下一次写或下一次窗内起服再压;重放幂等),恰一行 stderr 点名条数与账本;窗关之后 ⇒ 同一条记录拒启(`StoreBootRefusalError`,拒因点名本条、
442
451
  * 窗的最后一天与出路:用早于本条的版本起服一次 —— 它认得这只词,起服即压实删行记录),删码因此是零行为变化。没有起服读数键(它不经迁移段跑,读数是那一行 stderr)。只 local(SQL 两方言从来没有这只词)。
452
+ * · **M52 停-迁-起证据的心跳一半**(7.150.0)—— 不改库。停-迁-起守卫(M40 · M41 · M42 · M51)与 M43 的标记判「库上还有不知道这条迁移的副本在服务吗」只经一只读法
453
+ * `readOlderReplicaEvidence`:判活窗内心跳过的 `running` run,按持有者分组,减去登记为知道这条迁移的持有者(副本能力登记 `replica-registration.ts`,常设;本版起每只进程在
454
+ * 迁移段头登记一行)。早于副本登记的副本不登记,只经它们持有的 run 心跳可见 —— 这一半(与它的判活窗输入 `liveRunWindowMs`)就是本行,窗内才在;
455
+ * 登记一半本版**不判活**,只作归因(点名持有者)。看不见的边如实:空闲的、早于副本登记的副本没有任何证据(终局边界,运维停光旧副本是第一道);
456
+ * 登记行不续期、不观察,**不是围栏**。没有读数键(它不写库)。local 车道:数据根独占 ⇒ 守卫没有判活腿,恒不读。
443
457
  *
444
458
  * ## 收据账(一次起服一只,每一条迁移同一只)
445
459
  * 每一步把它**已提交**的改写 / 删除与点名读数当场记进同一只收据账({@link MigrationReceipts}):计数随每次提交累加、行随每次提交追加、形读数在那一步落定时写。走完 ⇒
@@ -458,11 +472,15 @@ import type { Pool as PgPool } from "pg";
458
472
  import { type AllowEntryInertReason, type GateKind } from "@sema-agent/core";
459
473
  import { type SqlDialect } from "./sql-driver.js";
460
474
  import { StoreBootRefusalError } from "./store-contracts.js";
475
+ import { type ShellSentinelOwnerRowsRetained } from "./shell-sentinel-owner-m48.js";
461
476
  import { listRuleBucketOwners } from "./permission-rule-store-sql.js";
462
477
  import type { SchemaProbeRead } from "./schema-live-columns.js";
463
478
  import type { ExecutionLane } from "../execution-lane-caps.js";
464
479
  import { type ImportedLayerRootAllowRetired, type ImportedLayerRootBucketSkipped, type ImportedLayerRootRetirementSource } from "./imported-layer-root-retirement.js";
465
480
  import { type LocalPlacementBackfillSeat, type UnusableArchiveWord } from "../execution-placement.js";
481
+ import type { PendingShapeChange } from "./schema-consistency.js";
482
+ import { type OlderReplicaEvidence } from "./stop-then-start-sentence.js";
483
+ import { type ReplicaCapability, type ReplicaRegistration } from "./replica-registration.js";
466
484
  /** 迁移读数(启动日志一行写全;测试按它断言,不靠日志文本)。 */
467
485
  export interface OneTimeMigrationReport {
468
486
  /** M17:`session_policy` 装规则的那一列 —— `renamed` = 本次把 `rules` 改名成 `rule_entries`;`current` = 早已是新名(新库 / 第二跑);
@@ -545,6 +563,8 @@ export interface OneTimeMigrationReport {
545
563
  readonly runObjectivePreviewRewritten: number;
546
564
  /** M48:本次把 cli 哨兵属主改写成无主的行数(SQL `session_meta` + `task_run` + `leader_run`;local 会话元数据格 + `run.json`)。SQL 与 local 都有。非零 = 真写了存量行;有身份边界的部署恒 0(那里不改写)。 */
547
565
  readonly shellSentinelOwnersCleared: number;
566
+ /** M48:有身份边界的部署上,留着没改的哨兵属主行数(逐面、只列非零的面;SQL = 表,local = 会话元数据格 / run 行)。只数不写。SQL 与 local 都有。非空 = 库 / 数据根里还有行被别的(一样身份键都不带的)进程改写的风险 —— 一行 warn `shell_sentinel_rows_retained`。 */
567
+ readonly shellSentinelOwnerRowsRetained: readonly ShellSentinelOwnerRowsRetained[];
548
568
  /** M49:本次自 `session_id` 回填了归属会话的检查点行数(SQL `checkpoint.host_session_id` / local 归属索引)。SQL 与 local 都有。非零 = 真写了存量行。 */
549
569
  readonly checkpointHostSessionsBackfilled: number;
550
570
  /** M46:本次删掉的存量引擎家 `Skill` 会话豁免行数(SQL `approval_exemption` / local 豁免日志墓碑;首次放行早于本库第一次跑本步的时刻 T0)。非零 = 真删了存量行 —— 那些会话的人下一次 `Skill` 调用被重问一次。 */
@@ -683,7 +703,7 @@ export declare class OneTimeMigrationInterruptedError extends Error {
683
703
  * 规则(窗长 30 天、窗关后的第一个 minor 删码、门怎么判)在本文件头注「窗」一节,只写那一次。
684
704
  */
685
705
  export interface OneTimeMigrationWindow {
686
- /** 本文件里的条目名(头注「窗内的迁移」的 M12…)。 */
706
+ /** 本文件里的条目名(头注「窗内的迁移」的 M13…)。 */
687
707
  readonly id: string;
688
708
  /** 引入这条迁移的版本 = 第一只含其代码的发布 tag(取证:`git log -S '<该条的常量名>' -- src/plugins/one-time-migrations.ts`
689
709
  * 找引入提交 → `git tag --contains <提交> --sort=creatordate` 取最早)。 */
@@ -701,11 +721,30 @@ export interface OneTimeMigrationWindow {
701
721
  /** 本条在 {@link OneTimeMigrationReport} 里的读数键 —— 报告的每个键恰属一条(到期门核:新迁移不登记 ⇒ 红)。 */
702
722
  readonly reportKeys: readonly (keyof OneTimeMigrationReport)[];
703
723
  /**
704
- * 本条起服时从存量表上**删掉**的列(表名 → 列名)。只有会发 `DROP COLUMN` 的迁移写它;列名取自删列句读的那一份常量(不手抄)。读者 = 发车门 1.10 第三档
705
- * ({@link columnsRemovedByPendingMigrations} → `scripts/schema-reconcile.mjs`):共享测试库还是升级前的旧形、带着这些列时,读成「待跑迁移要删的旧列」,不读成「库比本树新」。
706
- * 删码时随本行一起走 —— 行没了,这些列重新读作多余列(= 本条 `afterRemoval` 写的起服拒启)。
724
+ * 本条起服时对**存量表形**做的事(闭集四种,`schema-consistency.ts` 的 {@link PendingShapeChange}:删列 / 改名 / 补列 / 按建表语句重建)。只有会改表形的迁移写它;
725
+ * 列名取自迁移语句读的那一份常量(不手抄),条件与迁移步自己的判据同一个事实(列在不在)。读者 = 列册对账的投影 `projectPendingShape`(唯一一只;「待跑迁移要建 / 要删哪些列」只有这一格在写):
726
+ * 起服对账在迁移**之前**跑,比的是「这些迁移跑完之后」的形 —— 迁移要删 / 改名 / 补的列不让起服拒,别的不符照拒;迁移段之前 / 之中读列册的拒句(单表探针的拒因、判活守卫的句尾 ——
727
+ * `schema-consistency.ts` 的 `statementBearing`)同读这只投影,迁移自己要建的列不列成部署者的 `ALTER`;发车门 1.10 第三档(`scripts/schema-reconcile.mjs`)读同一只投影,
728
+ * 共享测试库的升级前旧形读成 `migration-pending`,不读成「库比本树新 / 旧」。删码时随本行一起走 —— 行没了,旧形重新读作不符(= 本条 `afterRemoval` 写的起服拒启)。
729
+ */
730
+ readonly shapeChanges?: readonly PendingShapeChange[];
731
+ /**
732
+ * 本条是**停-迁-起**迁移:起服时的守卫在有停-迁-起证据时拒启、一字节不写(动作段的唯一属主 = `stop-then-start-sentence.ts`)。两格见 {@link StopThenStartRow}:
733
+ * 缘由句与「这只库还欠不欠本条」的唯一读法 —— 起服列册对账的升级清单(`schema-consistency.ts` 的 `describeUpgradeChecklist`)只列这只库还欠的行、把缘由句原样列给运维,
734
+ * 于是「本构建有哪几条要先停光旧副本」只有这一处在写、随行删码一起没。读者 = {@link stopThenStartMigrations}。
707
735
  */
708
- readonly dropsColumns?: Readonly<Record<string, readonly string[]>>;
736
+ readonly stopThenStart?: StopThenStartRow;
737
+ }
738
+ /**
739
+ * 一条停-迁-起迁移的登记格(一句话 + 一只只读判据的引用;登记表里只写引用,判据的码在本条的迁移步旁边):
740
+ * · `reason` —— 一句英文:更早版本的副本在迁移之后还会写什么、写了会怎样(升级清单原样列给运维);
741
+ * · `owedOn` —— **这只库还欠不欠本条**的唯一读法(只读,一字节不写):本条的守卫先问它(不欠 ⇒ 零动作、不读证据),升级清单第 2 步只列它答「欠」的行 ——
742
+ * 清单不另判(修前清单按登记表全列、不判欠不欠,对走过这几条的库说「不可滚动」,与守卫的放行是一事两说)。读口是列册对账同一只无参读口
743
+ * {@link SchemaProbeRead}:判据的语句只内联本文件的常量(标记键 / 退役词 / 表名列名,与 `tableExists` / `columnExists` 同形),不带参数。
744
+ */
745
+ export interface StopThenStartRow {
746
+ readonly reason: string;
747
+ readonly owedOn: (read: SchemaProbeRead, dialect: SqlDialect) => Promise<boolean>;
709
748
  }
710
749
  /**
711
750
  * 🔴 [ref] —— 一次性迁移登记表,本文件各条的窗的**唯一属主**。别处(接口 JSDoc、调用点、DDL 注、部署文档)只写「窗口见
@@ -724,16 +763,21 @@ export declare function migrationWindowOpen(window: Pick<OneTimeMigrationWindow,
724
763
  * 还没有日期可写)⇒ 响亮抛,不铸一句带空日期的句子。
725
764
  */
726
765
  export declare function migrationWindowEnd(id: string): string;
727
- /** 待删列:表 → 列 → 认领它的迁移 id。 */
728
- export type PendingColumnRemovals = ReadonlyMap<string, ReadonlyMap<string, string>>;
729
766
  /**
730
- * 登记表里**待跑的**一次性迁移要删的存量列(表 → 列 → 迁移 id)—— 发车门 1.10 第三档读它,把共享测试库上「本树没有的列」分成两类:这里点名的 = 待跑迁移起服时要删的升级前旧形(不是库太新);
731
- * 别的 = 库比本树新(起服同样拒)。登记行在 ⇔ 这条迁移的代码还在、起服会跑它 ⇒ 「待跑」的判据就是行在场,不另设标记;行随删码一起没了,集合随之变空。「待跑」只说起服会**去跑**它,不说一定跑得成(迁移自己的前提 —— 如 M41 的判活窗内无 run 在心跳 —— 是起服时的动态条件,读者不据此判)。
732
- * 同一(表 × 列)被两行认领 ⇒ 响亮抛(一件事一个属主,不挑一个)。`registry` 是测试缝,生产只用登记表本身。
767
+ * 本构建带不带这一条迁移:登记表里有没有那一行(行随码同删 —— 删码那一版起答 `false`)。给**常设的跳版拒启臂**读:那条迁移还在时,存量旧形归它处置(臂只判、不拒);
768
+ * 删码之后臂接住(`Skill` 豁免截点:SQL 探针口与 local 数据根准入各传一次 `migrationCarried(SKILL_EXEMPTION_CUTOFF_ID)`;收令牌欠账:数据根准入与窗内长第一格的规则读 `migrationCarried("M47")`)。
769
+ * 「本构建带不带某条迁移」只有这一只读者(测试摘行模拟删码那一版:就地改登记表,本函数读同一只数组)。
770
+ */
771
+ export declare function migrationCarried(id: string): boolean;
772
+ /**
773
+ * 本构建带的**停-迁-起**迁移(登记行的 `stopThenStart` 一格;行在 ⇔ 码在 ⇒ 起服会在这一条上判活),按登记表顺序。读者 = 起服列册对账的升级清单:
774
+ * 逐行问 `owedOn`,只把这只库还欠的列给运维。登记表里再没有这样的行时返回空数组 —— 清单的这一步随之不出。
733
775
  */
734
- export declare function columnsRemovedByPendingMigrations(registry?: readonly Pick<OneTimeMigrationWindow, "id" | "dropsColumns">[]): PendingColumnRemovals;
776
+ export declare function stopThenStartMigrations(registry?: readonly Pick<OneTimeMigrationWindow, "id" | "stopThenStart">[]): readonly ({
777
+ readonly id: string;
778
+ } & StopThenStartRow)[];
735
779
  /** local 车道上 SQL 独有的几条(M17 / M18 / M21 / M23 / M24 / M26 / M27 / M29)的读数(M32 的回填两车道都有、M33 只在 local,local 腿的读数由 `LocalBackend.runOneTimeMigrations` 现算):那几张表 / 列在文件底座上从来不存在 ⇒ 如实答 absent / 0。 */
736
- export declare const NO_SQL_MIGRATIONS: Omit<OneTimeMigrationReport, "runErrorCodeColumnRewritten" | "runObjectivePreviewRewritten" | "shellSentinelOwnersCleared" | "checkpointHostSessionsBackfilled" | "legacySkillExemptionsDropped" | "executionPlacementsBackfilled" | "askExecutionLanesBackfilled" | "executionLaneWordsRenamed" | "scenarioPrefixSourcesScanned" | "executionPlacementSessionsUnreadable" | "localArchiveRowFactsBackfilled" | "localArchivesAnonymized" | "localArchivesKeptStamped" | "localArchivesUnreadable" | "localArchiveSnapshotsRecovered" | "localArchiveTokensAdopted" | "localArchiveTokensMinted" | "askJournalRecordsUpgraded" | "importedLayerRootAllowsRetired" | "importedLayerRootBucketsSkipped" | "importedLayerRootBucketsUnnamed">;
780
+ export declare const NO_SQL_MIGRATIONS: Omit<OneTimeMigrationReport, "runErrorCodeColumnRewritten" | "runObjectivePreviewRewritten" | "shellSentinelOwnersCleared" | "shellSentinelOwnerRowsRetained" | "checkpointHostSessionsBackfilled" | "legacySkillExemptionsDropped" | "executionPlacementsBackfilled" | "askExecutionLanesBackfilled" | "executionLaneWordsRenamed" | "scenarioPrefixSourcesScanned" | "executionPlacementSessionsUnreadable" | "localArchiveRowFactsBackfilled" | "localArchivesAnonymized" | "localArchivesKeptStamped" | "localArchivesUnreadable" | "localArchiveSnapshotsRecovered" | "localArchiveTokensAdopted" | "localArchiveTokensMinted" | "askJournalRecordsUpgraded" | "importedLayerRootAllowsRetired" | "importedLayerRootBucketsSkipped" | "importedLayerRootBucketsUnnamed">;
737
781
  /** 启动期的日志口(logger 的子集)。两级各有其用,见 {@link logOneTimeMigrations}。 */
738
782
  export interface MigrationLogSink {
739
783
  warn(msg: string, meta?: Record<string, unknown>): void;
@@ -771,12 +815,18 @@ export interface MigrationDb {
771
815
  * 判官不在两处各写一份。
772
816
  */
773
817
  export declare function createSqlImportedLayerRootSource(exec: Parameters<typeof listRuleBucketOwners>[0]): ImportedLayerRootRetirementSource;
774
- export declare function runSqlOneTimeMigrations(dialect: SqlDialect, pool: MysqlPool | PgPool, input: SqlOneTimeMigrationInput): Promise<OneTimeMigrationReport>;
775
- /** M48 的那一步(见头注 M48 段):只在输入显式说「没有身份边界」时改写 —— 有身份边界的部署上零改写(哨兵在那里是一位普通的具名属主);改写面里的每张表一句按值的 `UPDATE`(表不在 ⇒ 跳过);写后不再有哨兵值 ⇒ 第二跑零命中。
776
- * 值**逐字节**比:MySQL 协议的 `utf8mb4_bin` 是 PAD SPACE(`'a' = 'a '`),普通等值会把只差尾空格的另一位属主(合法主体名)也改成无主 ——
777
- * 与 M17 / M18 的 CAS 同一写法 `CAST(… AS BINARY)`;PG `text` 等值本就逐字节。 */
818
+ /**
819
+ * **段头**(常设两步,不带窗;只在这里排序;与迁移步同一条连接):两张表在(不在 ⇒ 拒,点名公开序列)→ 本进程登记(`replica-registration.ts`)→ 起服准入**锁外预读**(`serving-requirement.ts`)
820
+ * → 取迁移锁 → **锁内复核**(同一判据;本进程等锁期间握锁的那一只写下的要求在这里读得到)→ 各迁移步。准入拒 ⇒ 一步迁移都不跑。
821
+ * 登记在任何守卫读证据之前、本进程能持有任何 run 之前落下;跳过 `ensureSchema()` 的嵌入方走同一段。`me` 缺省 = 本进程的登记行;真库钉传别的构建(能力名单不同的起服者)。
822
+ */
823
+ export declare function runSqlOneTimeMigrations(dialect: SqlDialect, pool: MysqlPool | PgPool, input: SqlOneTimeMigrationInput, me?: ReplicaRegistration): Promise<OneTimeMigrationReport>;
824
+ /** M48 的那一步(见头注 M48 段):输入显式说「没有身份边界」⇒ 改写 —— 改写面里的每张表一句按值的 `UPDATE`(表不在 ⇒ 跳过);写后不再有哨兵值 ⇒ 第二跑零命中。
825
+ * 其余一切(有身份边界,或绕过类型缺这一格 / 不是布尔 ⇒ fail-closed,不静默放宽)零改写,但对同一批表用**同一句 WHERE**({@link shellSentinelOwnerWhereM48})数一遍留着的行,
826
+ * 非零的面记进 `shellSentinelOwnerRowsRetained`(起服日志一行 warn;见头注)。值**逐字节**比的理由在 {@link shellSentinelOwnerWhereM48}。 */
778
827
  export declare function clearShellSentinelOwnersM48(db: MigrationDb, dialect: SqlDialect, receipts: {
779
828
  shellSentinelOwnersCleared: number;
829
+ shellSentinelOwnerRowsRetained: ShellSentinelOwnerRowsRetained[];
780
830
  }, input: ShellSentinelOwnerInput): Promise<void>;
781
831
  /**
782
832
  * M46 的 SQL 腿(判据与形见头注 M46 段):标记表不在才建(与 M42 / M43 同一张);**T0 先落**(标记行 `M46`:不在 ⇒ 写下此刻、再读回来用;并发起服收敛到先落的那一只);
@@ -790,11 +840,12 @@ export declare function dropLegacySkillExemptionsM46(db: MigrationDb, dialect: S
790
840
  export declare const SESSION_DELETING_MARK_ID = "M51";
791
841
  /** M51 起服拒的机读码(确定的拒启表态:全停之后再起才有另一个答案)。 */
792
842
  export declare const SESSION_DELETING_SWITCH_REFUSED_CODE = "config.session_deleting_switch_refused";
793
- /** M51 起服拒:标记还没落,而判活窗内仍有 run 在心跳(拒因闭集只有 `live_runs`)。 */
843
+ /** M51 起服拒:标记还没落,而有停-迁-起证据(拒因闭集只有 `older_replica`)。 */
794
844
  export declare class SessionDeletingSwitchRefusedError extends StoreBootRefusalError {
795
845
  readonly code = "config.session_deleting_switch_refused";
796
- readonly reason: "live_runs";
797
- constructor(live: LiveRunHeartbeat);
846
+ readonly reason: "older_replica";
847
+ /** `tail` = 库此刻还差的列(`describeUpgradeDriftTail`;列齐 ⇒ 空串):一次起服读全,不必补一句再试。 */
848
+ constructor(evidence: OlderReplicaEvidence, tail?: string);
798
849
  }
799
850
  /**
800
851
  * M42 的扫描面:本树建表句(两方言各自的录制,与起服列册对账同一份)里名字合 {@link IDENTITY_COLUMN_NAME}、类型是字符 / 字节串的列,与库里实际在的列取交(条件建的表不在库里 ⇒ 不扫)。
@@ -806,12 +857,12 @@ export declare function scannedIdentityColumnsM42(db: Pick<MigrationDb, "rows">,
806
857
  }[]>;
807
858
  /**
808
859
  * 🔴 M42 的 SQL 腿:标记在场 ⇒ 返回(零扫描);否则逐列只读计数 `LIKE '<前缀>%'`,一处命中 ⇒ {@link ScenarioPrefixSwitchRefusedError}(`stored_prefix`;一字节没写,标记不写);
809
- * 零命中而判活窗内仍有 run 在心跳 ⇒ 同一只拒(`live_runs`,停-迁-起;标记不写);否则写标记。
860
+ * 零命中而有停-迁-起证据({@link readOlderReplicaEvidence})⇒ 同一只拒(`older_replica`;标记不写);否则写标记。
810
861
  * 握着迁移段的那一把锁、在那一条连接上:两只副本同时起服时第二只读到第一只写下的标记(写标记用 `INSERT IGNORE` / `ON CONFLICT DO NOTHING`,收敛)。
811
862
  */
812
863
  export declare function switchScenarioPrefixM42(db: MigrationDb, dialect: SqlDialect, receipts: {
813
864
  scenarioPrefixSourcesScanned: number;
814
- }, input: ExecutionLaneRenameInput): Promise<void>;
865
+ }, input: LiveRunWindowInput): Promise<void>;
815
866
  /** M40 的拒启码(停-迁-起守卫)。 */
816
867
  export declare const EXECUTION_LANE_RENAME_REFUSED_CODE = "config.execution_lane_rename_refused";
817
868
  /**
@@ -821,7 +872,7 @@ export declare const EXECUTION_LANE_RENAME_REFUSED_CODE = "config.execution_lane
821
872
  export declare class ExecutionLaneRenameRefusedError extends StoreBootRefusalError {
822
873
  /** 带旧词的行数(两张表合计)。 */
823
874
  readonly pendingRows: number;
824
- /** 判活窗内心跳过的 `running` run 数。 */
875
+ /** 停-迁-起证据里的 `running` run 数(持有者没有登记为知道 M40)。 */
825
876
  readonly liveRuns: number;
826
877
  /** 全停之后可以再起的最早时刻(ISO;= 最新心跳 + 判活窗 —— 那时收割谓词也判它们为死)。 */
827
878
  readonly restartAfter: string;
@@ -829,7 +880,7 @@ export declare class ExecutionLaneRenameRefusedError extends StoreBootRefusalErr
829
880
  constructor(
830
881
  /** 带旧词的行数(两张表合计)。 */
831
882
  pendingRows: number,
832
- /** 判活窗内心跳过的 `running` run 数。 */
883
+ /** 停-迁-起证据里的 `running` run 数(持有者没有登记为知道 M40)。 */
833
884
  liveRuns: number,
834
885
  /** 全停之后可以再起的最早时刻(ISO;= 最新心跳 + 判活窗 —— 那时收割谓词也判它们为死)。 */
835
886
  restartAfter: string, detail: string);
@@ -849,8 +900,8 @@ export declare class ExecutionLaneRenameWriteRefusedError extends StoreBootRefus
849
900
  /** 落不了盘的那只文件(绝对路径)。 */
850
901
  file: string, cause: unknown);
851
902
  }
852
- /** M40 的输入:判活窗(毫秒)= 本部署的 `REAP_RUN_STALE_SEC` —— 收割器判「这条 run 的持有者还活着」用的同一个窗。 */
853
- export interface ExecutionLaneRenameInput {
903
+ /** 停-迁-起证据读法心跳一半的输入(归 M52 行):判活窗(毫秒)= 本部署的 `REAP_RUN_STALE_SEC` —— 收割器判「这条 run 的持有者还活着」用的同一个窗。 */
904
+ export interface LiveRunWindowInput {
854
905
  readonly liveRunWindowMs: number;
855
906
  }
856
907
  /** M48 的输入:本部署有没有身份边界 = 部署形表 `DEPLOYMENT_SHAPE_PREDICATES.identityBoundary` 那一行的读数(只读配置;调用方读表交来,迁移步不另读配置)。
@@ -859,27 +910,27 @@ export interface ShellSentinelOwnerInput {
859
910
  readonly identityBoundary: boolean;
860
911
  }
861
912
  /** SQL 一次性迁移段的输入(各条目自己的那一半;删码车删掉它那一半)。 */
862
- export type SqlOneTimeMigrationInput = ExecutionPlacementSwitchInput & ExecutionLaneRenameInput & ShellSentinelOwnerInput;
913
+ export type SqlOneTimeMigrationInput = ExecutionPlacementSwitchInput & LiveRunWindowInput & ShellSentinelOwnerInput;
863
914
  /**
864
915
  * M40 ⓪ —— 带 `execution_lane` 列的表上的旧词改成新名(问行表 + 会话的那一列所在的表:M41 搬之前在 `session_meta`、之后在 `session_ext`;一句 UPDATE 一张表;幂等:第二跑零命中)。列不在的表零动作(跳版升上来的库:M32 稍后加列、按声明车道回填,不会再铸旧词)。
865
916
  * 还有旧词行 ⇒ 先过停-迁-起守卫({@link refuseWhileRunsHeartbeat});没有 ⇒ 不读 run 表、零写(没跑过无车道部署的库可滚动升级)。
866
917
  */
867
918
  export declare function renameRetiredExecutionLaneWordsM40(db: MigrationDb, dialect: SqlDialect, receipts: {
868
919
  executionLaneWordsRenamed: number;
869
- }, input: ExecutionLaneRenameInput): Promise<void>;
870
- /** 判活窗内的 `running` run 心跳(停-迁-起守卫的读数;M40 / M41 同读):没有 ⇒ `undefined`。 */
871
- interface LiveRunHeartbeat {
872
- readonly liveRuns: number;
873
- readonly windowSec: number;
874
- /** 全停之后可以再起的最早时刻(ISO;= 最新心跳 + 判活窗;读不出最新心跳 ⇒ 现在 + 窗,上界)。 */
875
- readonly restartAfter: string;
876
- /** 同一时刻的人读形(带「离现在还有几秒」)。 */
877
- readonly after: string;
878
- }
920
+ }, input: LiveRunWindowInput): Promise<void>;
921
+ /**
922
+ * **停-迁-起证据的唯一读法**(M40 / M41 / M42 / M43 / M51 同读;拒句与读数的句子属主 = `stop-then-start-sentence.ts`):判活窗内心跳过的 `running` run
923
+ * (收割器 `reapStale` 判活的同一条谓词:`status = 'running'` ∧ `updated_at` 在 `REAP_RUN_STALE_SEC` 窗内),按持有者(`task_run.instance_id`,建行铸、认领接管)分组,
924
+ * **减去登记为知道 `migrationId` 的持有者**(`replica-registration.ts`;`knows` 与起服准入同一只判据)—— 剩下的 run 就是证据:持有者没有登记行(早于副本登记的副本、`NULL` 身份、
925
+ * 自传身份的嵌入方)或登记了而能力名单里没有这条迁移,照算(保守)。登记一半只作归因(点名持有者),**不判活**。
926
+ * 本进程此刻还在迁移段里、一条 run 都没起过 ⇒ 证据里只有别的进程。`task_run` 不在 ⇒ `undefined`。心跳一半随 M52 行删(那一行的 `removal`)。
927
+ * `migrationId` 在型上就要在能力名单里(`ReplicaCapability`):一条迁移读证据 ⇔ 它的名在名单里。
928
+ */
929
+ export declare function readOlderReplicaEvidence(db: MigrationDb, dialect: SqlDialect, input: LiveRunWindowInput, migrationId: ReplicaCapability): Promise<OlderReplicaEvidence | undefined>;
879
930
  /** M41 的拒启码(确定的拒启表态;与 `config.schema_mismatch` 同一族)。 */
880
931
  export declare const SESSION_EXT_MOVE_REFUSED_CODE = "config.session_ext_move_refused";
881
- /** 拒因闭集:`live_runs` = 还有列要搬而本库上仍有 run 在心跳(停-迁-起);`copy_mismatch` = 搬完核对有一行不等(一列没删)。 */
882
- export type SessionExtMoveRefusalReason = "live_runs" | "copy_mismatch";
932
+ /** 拒因闭集:`older_replica` = 还有列要搬而有停-迁-起证据;`copy_mismatch` = 搬完核对有一行不等(一列没删)。 */
933
+ export type SessionExtMoveRefusalReason = "older_replica" | "copy_mismatch";
883
934
  /** M41 的起服拒。具名类型 + 机读码 + 拒因;继承 {@link StoreBootRefusalError}:SQL 开库的等待窗不重试它。 */
884
935
  export declare class SessionExtMoveRefusedError extends StoreBootRefusalError {
885
936
  readonly reason: SessionExtMoveRefusalReason;
@@ -887,10 +938,10 @@ export declare class SessionExtMoveRefusedError extends StoreBootRefusalError {
887
938
  constructor(reason: SessionExtMoveRefusalReason, detail: string);
888
939
  }
889
940
  /**
890
- * M41 ⓪′ —— 停-迁-起守卫(紧随 M40 的守卫,先于任何别的写):还有部署格列要搬 ∧ 本库上仍有 run 在心跳 ⇒ 拒 `live_runs`,一字节没写。
941
+ * M41 ⓪′ —— 停-迁-起守卫(紧随 M40 的守卫,先于任何别的写):还有部署格列要搬 ∧ 有停-迁-起证据({@link readOlderReplicaEvidence})⇒ 拒 `older_replica`,一字节没写。
891
942
  * 旁表形 ⇒ 零动作(不读 run 表)。
892
943
  */
893
- export declare function refuseSessionExtMoveWhileRunsHeartbeat(db: MigrationDb, dialect: SqlDialect, input: ExecutionLaneRenameInput): Promise<void>;
944
+ export declare function refuseSessionExtMoveWhileRunsHeartbeat(db: MigrationDb, dialect: SqlDialect, input: LiveRunWindowInput): Promise<void>;
894
945
  /**
895
946
  * M41(规则与理由见头注 M41 段):① 搬(键集分页 upsert)→ ② 逐行核对 → ③ 一句删列。旁表形 ⇒ 零动作。中断 ⇒ 下一次起服从头重跑:① 的 upsert 是「旁表这几格 = 根行上的值」,
896
947
  * 重跑同一结果;② 只读;③ 按后置条件收敛(那几列都不在)。排在迁移段最后(M32 之后:M32 读 / 写 `session_meta` 上的八列;M23 改的是引擎列)。导出给真库钉驱动「中断后续跑」。