@sema-agent/server 7.136.0 → 7.138.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 (327) hide show
  1. package/MIGRATION.md +501 -139
  2. package/README.md +1 -0
  3. package/README.zh-CN.md +1 -0
  4. package/USAGE.md +149 -34
  5. package/deploy/sema-up/README.md +14 -0
  6. package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +7 -1
  7. package/deploy/sema-up/stack/sema-stack-cluster.yaml +7 -1
  8. package/dist/approval-card.d.ts +21 -14
  9. package/dist/approval-card.js +1 -0
  10. package/dist/approval-content-kind.d.ts +6 -0
  11. package/dist/approval-content-kind.js +7 -0
  12. package/dist/approval-gate-currency.d.ts +48 -6
  13. package/dist/approval-gate-currency.js +16 -9
  14. package/dist/approval-hmac.d.ts +13 -1
  15. package/dist/approval-hmac.js +1 -1
  16. package/dist/approval.js +3 -3
  17. package/dist/audit.js +1 -0
  18. package/dist/auth-bridge.js +2 -2
  19. package/dist/background-agent-name.d.ts +5 -0
  20. package/dist/background-agent-name.js +5 -0
  21. package/dist/boot/budget-tracing.d.ts +1 -12
  22. package/dist/boot/deployment-mods.d.ts +46 -16
  23. package/dist/boot/deployment-mods.js +82 -6
  24. package/dist/boot/execution-env.d.ts +24 -1
  25. package/dist/boot/execution-env.js +69 -6
  26. package/dist/boot/governance-seams.d.ts +10 -17
  27. package/dist/boot/governance-seams.js +5 -17
  28. package/dist/boot/leader.d.ts +3 -0
  29. package/dist/boot/leader.js +1 -0
  30. package/dist/boot/org-delivery.js +15 -2
  31. package/dist/boot/reapers.d.ts +3 -0
  32. package/dist/boot/reapers.js +15 -1
  33. package/dist/boot/resolve-spec.d.ts +7 -0
  34. package/dist/boot/resolve-spec.js +36 -26
  35. package/dist/boot/retention-lane.d.ts +11 -5
  36. package/dist/boot/retention-lane.js +2 -2
  37. package/dist/boot/runner-deps.d.ts +7 -3
  38. package/dist/boot/runner-deps.js +1 -0
  39. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  40. package/dist/boot/stage-04-stores.d.ts +2 -13
  41. package/dist/boot/stage-05-execution-env.d.ts +6 -13
  42. package/dist/boot/stage-05-execution-env.js +17 -5
  43. package/dist/boot/stage-06-runners.d.ts +6 -13
  44. package/dist/boot/stage-06-runners.js +10 -3
  45. package/dist/boot/stage-07-capability-layer.d.ts +7 -13
  46. package/dist/boot/stage-07-capability-layer.js +3 -3
  47. package/dist/boot/stage-08-reapers.d.ts +7 -13
  48. package/dist/boot/stage-08-reapers.js +2 -1
  49. package/dist/boot/stage-09-leader.d.ts +7 -13
  50. package/dist/boot/stage-09-leader.js +2 -2
  51. package/dist/boot/stage-10-http-server.d.ts +7 -13
  52. package/dist/boot/stage-10-http-server.js +6 -3
  53. package/dist/boot/stores.d.ts +1 -1
  54. package/dist/boot/web-admin.d.ts +5 -2
  55. package/dist/boot/web-admin.js +3 -3
  56. package/dist/brain.js +5 -5
  57. package/dist/broker/broker.d.ts +89 -0
  58. package/dist/broker/broker.js +287 -0
  59. package/dist/broker/constants.d.ts +39 -0
  60. package/dist/broker/constants.js +15 -0
  61. package/dist/broker/http1.d.ts +111 -0
  62. package/dist/broker/http1.js +256 -0
  63. package/dist/broker/lease-book.d.ts +87 -0
  64. package/dist/broker/lease-book.js +142 -0
  65. package/dist/broker/lease-file.d.ts +60 -0
  66. package/dist/broker/lease-file.js +127 -0
  67. package/dist/broker/main.d.ts +2 -0
  68. package/dist/broker/main.js +20 -0
  69. package/dist/budget.d.ts +17 -15
  70. package/dist/budget.js +2 -2
  71. package/dist/capabilities/composite-members.d.ts +2 -1
  72. package/dist/capabilities/composite-members.js +2 -1
  73. package/dist/capabilities/engine-capabilities.js +1 -0
  74. package/dist/capabilities/mcp-probe.d.ts +36 -11
  75. package/dist/capabilities/mcp-probe.js +44 -5
  76. package/dist/capabilities/scenarios.d.ts +23 -8
  77. package/dist/capabilities/scenarios.js +13 -8
  78. package/dist/capabilities/skills.d.ts +28 -5
  79. package/dist/capabilities/skills.js +8 -0
  80. package/dist/capability-facts.d.ts +6 -0
  81. package/dist/capability-facts.js +5 -0
  82. package/dist/center-credential-renewer.js +5 -1
  83. package/dist/checkpoint-ctx-seal-m28.d.ts +3 -10
  84. package/dist/checkpoint-ctx-seal-m28.js +1 -1
  85. package/dist/checkpoint-identity.d.ts +13 -6
  86. package/dist/config-catalog.js +16 -7
  87. package/dist/config-types.d.ts +24 -7
  88. package/dist/config.d.ts +1 -1
  89. package/dist/config.js +42 -13
  90. package/dist/deployment-governance.d.ts +2 -2
  91. package/dist/deployment-governance.js +7 -9
  92. package/dist/deployment-shape.d.ts +6 -6
  93. package/dist/device-ws-protocol.d.ts +1 -0
  94. package/dist/device-ws-protocol.js +2 -1
  95. package/dist/file-history-disclosure.d.ts +4 -2
  96. package/dist/file-history-disclosure.js +2 -0
  97. package/dist/gate-settlement.d.ts +71 -0
  98. package/dist/gate-settlement.js +40 -0
  99. package/dist/hooks/classic-stations.d.ts +12 -54
  100. package/dist/hooks/classic-stations.js +1 -0
  101. package/dist/hooks/command-spawn.d.ts +2 -2
  102. package/dist/hooks/hook-runner.js +14 -14
  103. package/dist/http/admission.js +14 -9
  104. package/dist/http/approval-sweeps.js +4 -3
  105. package/dist/http/caller-trust.d.ts +2 -1
  106. package/dist/http/caller-trust.js +1 -3
  107. package/dist/http/checkpoint-ctx.d.ts +48 -7
  108. package/dist/http/checkpoint-ctx.js +40 -0
  109. package/dist/http/dispatch.d.ts +4 -0
  110. package/dist/http/dispatch.js +18 -10
  111. package/dist/http/durable-run-leg.d.ts +5 -1
  112. package/dist/http/durable-run-leg.js +5 -3
  113. package/dist/http/health-self-report.d.ts +2 -2
  114. package/dist/http/memory-compliance-failure-reply.js +3 -0
  115. package/dist/http/principal-gate.d.ts +15 -10
  116. package/dist/http/principal-gate.js +48 -9
  117. package/dist/http/resume-legs.d.ts +7 -31
  118. package/dist/http/resume-legs.js +185 -126
  119. package/dist/http/route-ctx.d.ts +38 -53
  120. package/dist/http/route-ctx.js +2 -5
  121. package/dist/http/routes/a2a-serve.js +10 -4
  122. package/dist/http/routes/agents-roster.d.ts +1 -1
  123. package/dist/http/routes/agents-roster.js +5 -1
  124. package/dist/http/routes/approvals-assistant.js +24 -10
  125. package/dist/http/routes/capabilities.js +23 -11
  126. package/dist/http/routes/mcp-reconnect.d.ts +3 -2
  127. package/dist/http/routes/mcp-reconnect.js +7 -7
  128. package/dist/http/routes/memory-consolidation.d.ts +1 -1
  129. package/dist/http/routes/memory-origin.d.ts +1 -1
  130. package/dist/http/routes/rules.js +3 -3
  131. package/dist/http/routes/runs.js +13 -8
  132. package/dist/http/routes/session-sync.js +42 -6
  133. package/dist/http/routes/sessions.js +6 -3
  134. package/dist/http/routes/side-query.js +2 -3
  135. package/dist/http/routes/tasks.js +794 -780
  136. package/dist/http/server.d.ts +35 -25
  137. package/dist/http/stored-body-replay.d.ts +3 -3
  138. package/dist/http/stored-body-replay.js +6 -1
  139. package/dist/http/wire-types.d.ts +66 -33
  140. package/dist/identity-source.d.ts +65 -0
  141. package/dist/identity-source.js +45 -0
  142. package/dist/index.d.ts +2 -0
  143. package/dist/index.js +1 -0
  144. package/dist/leader/wire.d.ts +7 -0
  145. package/dist/leader/wire.js +5 -4
  146. package/dist/mcp-assertion-header.d.ts +51 -40
  147. package/dist/mcp-assertion-header.js +10 -11
  148. package/dist/mcp-authorization-face.d.ts +27 -0
  149. package/dist/mcp-authorization-face.js +15 -0
  150. package/dist/memory-operator-faces.d.ts +13 -4
  151. package/dist/memory-operator-faces.js +1 -17
  152. package/dist/memory-store-refusal.d.ts +3 -3
  153. package/dist/memory-sync-client.js +72 -57
  154. package/dist/memory-sync.d.ts +1 -1
  155. package/dist/model-entry-refusal.d.ts +2 -0
  156. package/dist/model-entry-refusal.js +11 -0
  157. package/dist/model-route-gap.d.ts +6 -22
  158. package/dist/model-route-gap.js +7 -5
  159. package/dist/model-select.d.ts +6 -17
  160. package/dist/model-select.js +0 -3
  161. package/dist/mods-declaration.d.ts +110 -0
  162. package/dist/mods-declaration.js +109 -0
  163. package/dist/namespaced-rule-name.d.ts +1 -1
  164. package/dist/observability/err-text.d.ts +5 -0
  165. package/dist/observability/err-text.js +9 -0
  166. package/dist/observability/fail-open.d.ts +17 -1
  167. package/dist/observability/fail-open.js +17 -1
  168. package/dist/observability/metrics.js +1 -1
  169. package/dist/observability/run-terminal.js +1 -0
  170. package/dist/observability/secret-env-scrub.d.ts +1 -1
  171. package/dist/observability/secret-env-scrub.js +1 -1
  172. package/dist/operator-ask.d.ts +2 -2
  173. package/dist/org-delivery-gate.js +1 -1
  174. package/dist/org-memory-admission.d.ts +2 -2
  175. package/dist/org-memory-admission.js +39 -2
  176. package/dist/parked-decide.d.ts +15 -2
  177. package/dist/parked-decide.js +17 -10
  178. package/dist/peer-directory.js +2 -0
  179. package/dist/peer-seat.d.ts +150 -0
  180. package/dist/peer-seat.js +239 -0
  181. package/dist/permission-rule-list.d.ts +2 -2
  182. package/dist/permission-rule-vocab.d.ts +7 -7
  183. package/dist/permission-rule-vocab.js +3 -3
  184. package/dist/plain-string-record.d.ts +38 -0
  185. package/dist/plain-string-record.js +38 -0
  186. package/dist/plugins/background-agent-store-sql.js +6 -3
  187. package/dist/plugins/caching-session-store.d.ts +5 -0
  188. package/dist/plugins/caching-session-store.js +6 -0
  189. package/dist/plugins/checkpoint-store-sql.d.ts +34 -29
  190. package/dist/plugins/checkpoint-store-sql.js +14 -14
  191. package/dist/plugins/file-history-store-sql.js +10 -16
  192. package/dist/plugins/file-run-store.js +8 -2
  193. package/dist/plugins/k8s-exec-protocol.d.ts +69 -13
  194. package/dist/plugins/k8s-exec-protocol.js +116 -28
  195. package/dist/plugins/k8s-pod-delete-failure.d.ts +25 -0
  196. package/dist/plugins/k8s-pod-delete-failure.js +17 -0
  197. package/dist/plugins/k8s-pod-reaper.d.ts +106 -0
  198. package/dist/plugins/k8s-pod-reaper.js +122 -0
  199. package/dist/plugins/local-checkpoint-store.d.ts +4 -17
  200. package/dist/plugins/local-checkpoint-store.js +3 -4
  201. package/dist/plugins/local-session-store.d.ts +66 -27
  202. package/dist/plugins/local-session-store.js +60 -28
  203. package/dist/plugins/mailbox-store-sql.d.ts +11 -3
  204. package/dist/plugins/mailbox-store-sql.js +103 -15
  205. package/dist/plugins/memory-run-store.js +2 -0
  206. package/dist/plugins/memory-sync-store-pg.d.ts +16 -5
  207. package/dist/plugins/memory-sync-store-tidb.d.ts +3 -3
  208. package/dist/plugins/one-time-migrations.d.ts +34 -12
  209. package/dist/plugins/one-time-migrations.js +51 -9
  210. package/dist/plugins/permission-rule-store-file.js +2 -2
  211. package/dist/plugins/permission-rule-store-sql.d.ts +17 -17
  212. package/dist/plugins/permission-rule-store-sql.js +37 -30
  213. package/dist/plugins/pg-pool.js +4 -0
  214. package/dist/plugins/pg-session-storage.d.ts +10 -2
  215. package/dist/plugins/pg-session-storage.js +20 -7
  216. package/dist/plugins/remote-env-adb.d.ts +6 -1
  217. package/dist/plugins/remote-env-adb.js +2 -1
  218. package/dist/plugins/remote-env-device.d.ts +6 -1
  219. package/dist/plugins/remote-env-device.js +5 -1
  220. package/dist/plugins/remote-env-e2b.d.ts +5 -0
  221. package/dist/plugins/remote-env-e2b.js +2 -1
  222. package/dist/plugins/remote-env-file-error.d.ts +8 -1
  223. package/dist/plugins/remote-env-file-error.js +7 -1
  224. package/dist/plugins/remote-env-host.d.ts +10 -2
  225. package/dist/plugins/remote-env-host.js +8 -2
  226. package/dist/plugins/remote-env-k8s.d.ts +140 -11
  227. package/dist/plugins/remote-env-k8s.js +277 -15
  228. package/dist/plugins/remote-env-local-docker.d.ts +5 -0
  229. package/dist/plugins/remote-env-local-docker.js +2 -1
  230. package/dist/plugins/remote-env-ssh.d.ts +6 -1
  231. package/dist/plugins/remote-env-ssh.js +2 -1
  232. package/dist/plugins/retention-store-sql.d.ts +14 -2
  233. package/dist/plugins/retention-store-sql.js +6 -0
  234. package/dist/plugins/run-store-sql.js +10 -4
  235. package/dist/plugins/session-fork.d.ts +10 -13
  236. package/dist/plugins/session-fork.js +5 -25
  237. package/dist/plugins/session-ownership.d.ts +24 -3
  238. package/dist/plugins/session-ownership.js +24 -5
  239. package/dist/plugins/session-workspace-cell.d.ts +17 -0
  240. package/dist/plugins/session-workspace-cell.js +38 -0
  241. package/dist/plugins/sql-errors.d.ts +23 -2
  242. package/dist/plugins/sql-errors.js +15 -0
  243. package/dist/plugins/store-backend.js +7 -7
  244. package/dist/plugins/store-contracts.d.ts +10 -1
  245. package/dist/plugins/store-fault.d.ts +2 -2
  246. package/dist/plugins/store-fault.js +4 -2
  247. package/dist/plugins/tidb-pool.js +13 -0
  248. package/dist/plugins/tidb-session-store.d.ts +17 -2
  249. package/dist/plugins/tidb-session-store.js +18 -7
  250. package/dist/plugins/tool-result-store-sql.d.ts +13 -6
  251. package/dist/plugins/tool-result-store-sql.js +8 -7
  252. package/dist/plugins/worktree-isolation.d.ts +3 -2
  253. package/dist/plugins/worktree-isolation.js +1 -7
  254. package/dist/project-identity.d.ts +1 -14
  255. package/dist/project-identity.js +0 -4
  256. package/dist/request-key-closure.js +1 -1
  257. package/dist/request-value-closure.d.ts +31 -2
  258. package/dist/request-value-closure.js +7 -1
  259. package/dist/rule-entry-list.d.ts +3 -2
  260. package/dist/rule-entry-list.js +2 -2
  261. package/dist/rules-consent.js +12 -7
  262. package/dist/run-local.d.ts +2 -2
  263. package/dist/run-local.js +12 -6
  264. package/dist/runs.d.ts +7 -1
  265. package/dist/runs.js +8 -2
  266. package/dist/runtime-governance.d.ts +5 -5
  267. package/dist/sandbox-git-lease.d.ts +49 -0
  268. package/dist/sandbox-git-lease.js +60 -0
  269. package/dist/sandbox-git-plane.d.ts +84 -0
  270. package/dist/sandbox-git-plane.js +105 -0
  271. package/dist/security.d.ts +16 -4
  272. package/dist/security.js +8 -3
  273. package/dist/server-secret-env.d.ts +12 -3
  274. package/dist/server-secret-env.js +18 -2
  275. package/dist/session-error-wire.d.ts +14 -6
  276. package/dist/session-error-wire.js +2 -1
  277. package/dist/session-incarnation.d.ts +4 -5
  278. package/dist/session-incarnation.js +2 -2
  279. package/dist/session-policy-wire.d.ts +1 -1
  280. package/dist/session-policy-wire.js +2 -2
  281. package/dist/session-sync.d.ts +1 -1
  282. package/dist/session-workspace.d.ts +130 -0
  283. package/dist/session-workspace.js +83 -0
  284. package/dist/spec-fields.d.ts +44 -14
  285. package/dist/spec-fields.js +33 -12
  286. package/dist/standing-answer-grant.d.ts +2 -13
  287. package/dist/standing-answer-grant.js +0 -7
  288. package/dist/stored-request-prompt-profile-m30.d.ts +49 -0
  289. package/dist/stored-request-prompt-profile-m30.js +25 -0
  290. package/dist/task-a2a.d.ts +44 -14
  291. package/dist/task-a2a.js +46 -20
  292. package/dist/task-mcp.d.ts +34 -21
  293. package/dist/task-mcp.js +46 -22
  294. package/dist/task-settings.d.ts +2 -2
  295. package/dist/tool-approval.d.ts +43 -9
  296. package/dist/tool-approval.js +57 -15
  297. package/dist/tool-rule-names.d.ts +5 -0
  298. package/dist/trace/core-keyset-guard.d.ts +34 -19
  299. package/dist/trace/engine-notice-wire.d.ts +1 -1
  300. package/dist/trace/engine-notice-wire.js +4 -0
  301. package/dist/trace/exit-seat.d.ts +20 -1
  302. package/dist/trace/exit-seat.js +5 -2
  303. package/dist/trace/extension-call-face.d.ts +33 -0
  304. package/dist/trace/extension-call-face.js +39 -0
  305. package/dist/trace/ledger-sink.d.ts +4 -5
  306. package/dist/trace/ledger-sink.js +3 -7
  307. package/dist/trace/project.d.ts +62 -10
  308. package/dist/trace/project.js +49 -9
  309. package/dist/trace/redact.d.ts +18 -6
  310. package/dist/trace/redact.js +154 -60
  311. package/dist/trace/self-minted-wire.d.ts +500 -7
  312. package/dist/trace/self-minted-wire.js +182 -1
  313. package/dist/trace/wire-projection-faces.d.ts +7 -5
  314. package/dist/trace/wire-projection-faces.js +9 -4
  315. package/dist/user-authored-text.d.ts +2 -2
  316. package/dist/user-authored-text.js +16 -1
  317. package/dist/web-admin-client/apply-effective.js +0 -1
  318. package/dist/web-admin-client/center-request.d.ts +23 -4
  319. package/dist/web-admin-client/center-request.js +42 -8
  320. package/dist/web-admin-client/http-client.js +6 -6
  321. package/dist/web-admin-client/skills-mcp.d.ts +8 -4
  322. package/dist/web-admin-client/skills-mcp.js +31 -18
  323. package/dist/web-admin-client/types.d.ts +10 -5
  324. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +11 -5
  325. package/package.json +3 -3
  326. package/wire-changes/server@7.137.0.json +825 -0
  327. package/wire-changes/server@7.138.0.json +446 -0
@@ -3,7 +3,8 @@
3
3
  *
4
4
  * ## 规则(一句)
5
5
  * 「fork 拷到哪一条」只有引擎一只判官:`settledForkOptions(源会话)` 答 `{}`(整份日志)或 `{ entryId: <在飞轮的父>, position: "at" }`(拷到那一条为止)。
6
- * 本仓的店不写第二份「什么算在飞」—— local 店把它的答案原样交给引擎自己的 `repo.fork`;两只 SQL 孪生没有 `repo.fork`(它们按行搬字节),所以这里只管**按答案拷**:
6
+ * 本仓的店不写第二份「什么算在飞」—— local 店把它的答案原样交给引擎自己的 `repo.fork`;两只 SQL 孪生没有 `repo.fork`(它们按行搬字节),按答案挑行也是引擎的一只
7
+ * (`selectForkRows`,引擎 7.59.0 包根导出:同一条父链走法、同一组拒词);本文件只给它这两只孪生的行形(`entry_id` / `parent_id` 两列):
7
8
  * · `{}` ⇒ 整份日志(含别的分支),叶 = 源会话的叶(与引擎 `getEntriesToFork` 的无 `entryId` 臂同);
8
9
  * · `at` 点 ⇒ 根到分叉点那一条**路径**上的条目(与引擎 `getPathToRoot(entryId)` 同:路径,不是日志前缀,别的分支不随),叶 = 分叉点。
9
10
  *
@@ -11,24 +12,20 @@
11
12
  * 拷贝要的是**整份**持久日志(压缩地板绕过 —— 唤醒只装 `[地板..叶]`,从唤醒里拷会丢地板之前的全部历史);判官要的只是叶链上最近几条(它是引擎的一份纯函数,
12
13
  * 吃一只 `Session`):唤醒出来的会话 `getEntry` 在地板之下会回读持久日志,所以判官在压缩过的会话上也看得见整条叶链。
13
14
  */
14
- import { settledForkOptions, type SessionStorage } from "@sema-agent/core";
15
- /** 引擎答的分叉点(`{}` = 整份;`entryId` + `position: "at"` = 拷到这一条为止)。 */
16
- export type ForkPoint = Awaited<ReturnType<typeof settledForkOptions>>;
15
+ import { type ForkPoint, type ForkRowShape, type SessionStorage } from "@sema-agent/core";
17
16
  /** 问引擎:这只(已唤醒的)源会话从哪里拷。SQL 孪生用它;local 店手里就是引擎的 `Session`,直接调 `settledForkOptions`。 */
18
17
  export declare function forkPointOf(storage: SessionStorage): Promise<ForkPoint>;
19
- /** 整份日志里一行的父链两键(其余列原样搬,不读内容)。 */
18
+ /** 两只 SQL 孪生整份日志里的一行(两孪生选同一组列):父链两键交引擎挑行,其余三列原样搬进新会话、不读内容。 */
20
19
  export interface ForkLogRow {
21
20
  readonly entry_id: string;
22
21
  readonly parent_id: string | null;
22
+ readonly type: string;
23
+ readonly payload: unknown;
24
+ readonly ts: unknown;
23
25
  }
24
26
  /**
25
- * 按引擎的分叉点从整份日志(oldest-first)里挑出要拷的行,与新会话的叶。行的相对顺序保留(调用方按顺序重铸 seq)。
26
- *
27
- * 分叉点不在日志里 ⇒ `invalid_fork_target`、路径中途的父不在日志里 ⇒ `invalid_session`(引擎 `getEntriesToFork` / `getPathToRoot` 同词同句);分叉点之上的父链成环 ⇒ `invalid_session`、
28
- * 句子与引擎的父链守卫同(守卫类不在包根,走法是同一个意思:走过的条目再踩一次 = 环;沿用它的句子,让同一件事在三种后端上说同一句话);`position` 不是 `at` ⇒ 响亮拒(本函数只认引擎今天答的两形)。
27
+ * 两只 SQL 孪生的行怎么交给引擎的 `selectForkRows`(按答案挑行 + 新会话的叶;分叉点不在日志里 ⇒ `invalid_fork_target`、路径中途悬空父 / 父链成环 ⇒ `invalid_session`,
28
+ * 引擎的原词原句)。本仓不再自写父链走法 —— 那曾是与引擎 `getPathToRoot` 同义的第二份。
29
29
  */
30
- export declare function forkCopyOf<R extends ForkLogRow>(rows: readonly R[], sourceLeafId: string | null, point: ForkPoint): {
31
- rows: R[];
32
- leafId: string | null;
33
- };
30
+ export declare const FORK_LOG_ROW_SHAPE: ForkRowShape<ForkLogRow>;
34
31
  //# sourceMappingURL=session-fork.d.ts.map
@@ -1,29 +1,9 @@
1
- import { SessionError, StoredSession, settledForkOptions } from "@sema-agent/core";
1
+ import { StoredSession, settledForkOptions } from "@sema-agent/core";
2
2
  export async function forkPointOf(storage) {
3
3
  return settledForkOptions(new StoredSession(storage));
4
4
  }
5
- export function forkCopyOf(rows, sourceLeafId, point) {
6
- if (point.entryId === undefined)
7
- return { rows: [...rows], leafId: sourceLeafId };
8
- if (point.position !== "at") {
9
- throw new SessionError("invalid_fork_target", `fork point ${point.entryId} comes with a position this store does not copy (${String(point.position)}) — only the engine's "at" point is read here`);
10
- }
11
- const byId = new Map();
12
- for (const r of rows)
13
- byId.set(r.entry_id, r);
14
- const onPath = new Set();
15
- let cursor = point.entryId;
16
- while (cursor !== null) {
17
- if (onPath.has(cursor)) {
18
- throw new SessionError("invalid_session", `Entry ${cursor} is its own ancestor (parent chain cycles at ${cursor}) — start a new session, or fork from an entry above the loop`);
19
- }
20
- const row = byId.get(cursor);
21
- if (row === undefined) {
22
- throw new SessionError(cursor === point.entryId ? "invalid_fork_target" : "invalid_session", `Entry ${cursor} not found`);
23
- }
24
- onPath.add(cursor);
25
- cursor = row.parent_id;
26
- }
27
- return { rows: rows.filter((r) => onPath.has(r.entry_id)), leafId: point.entryId };
28
- }
5
+ export const FORK_LOG_ROW_SHAPE = {
6
+ idOf: (row) => row.entry_id,
7
+ parentOf: (row) => row.parent_id,
8
+ };
29
9
  //# sourceMappingURL=session-fork.js.map
@@ -1,11 +1,32 @@
1
+ /**
2
+ * 「谁也不指的串」的描述句 —— 拒句里「给的是什么」那一格的串形(从不回显值:一个谁也不指的串可能就是一段被粘进来的凭据)。
3
+ * 本模块的属主拒与鉴权边界的主体拒(`security.ts` `assertPrincipalShape` 的 `principal_not_a_name`)读这同一句:判官同一只,描述也同一句。
4
+ */
5
+ export declare const NOT_A_PRINCIPAL_NAME = "a string that names nobody (empty, blank, or holding a control, separator or invisible format character)";
6
+ /**
7
+ * 「这个值能不能作一只会话行的属主格」—— core 7.56.0 [ref] 起只有一只判官 `principalNameOf`:主体名(有可见内容、不含控制 / 分隔 / 非连接符格式字符,
8
+ * 原样保存不规整)或 `null`(匿名)。空串、空白串、带不可见字符的串与一切非串都不是属主(它们谁也不指 —— 读成匿名会放行每一位主体)。
9
+ *
10
+ * 边界同判官:HTTP 请求带来的主体在鉴权边界已经过同一只 `principalNameOf`(`security.ts` `principalShapeProblem` 的 `not_a_name`,7.137.0)⇒
11
+ * 经过边界的请求到不了这里的拒臂;这里是纵深(嵌入方直调店、别的写者),规则只有引擎那一只,不在本仓另写。
12
+ */
13
+ export declare function isSessionOwnerValue(owner: unknown): owner is string | null;
1
14
  /**
2
15
  * fork 拷贝的属主 —— core `SessionStore.fork` 契约的唯一读法:
3
- * 显式串 ⇒ 该串;无参 / 显式 `null` ⇒ 源会话记下的属主(`undefined` = 源会话没记,拷贝也不记)。
16
+ * 显式主体名 ⇒ 该名;无参 / 显式 `null` ⇒ 源会话记下的属主(`undefined` = 源会话没记,拷贝也不记)。
17
+ * 显式给了却不是主体名(空串 / 空白 / 带不可见字符,core 7.56.0 [ref])⇒ 响亮拒(`SessionError("storage")`,不留行)—— 与 `register` 首写同一只判官。
4
18
  */
5
19
  export declare function forkOwnerOf(requested: string | null | undefined, sourceOwner: string | null | undefined): string | null | undefined;
6
20
  /**
7
- * `register` 首写的 owner 守卫 —— core `SessionStore.register` 契约的唯一读法(三只店同调):首写的 owner 既不是串也不是 `null` ⇒ 响亮拒(不留行);
8
- * 「首写」由调用方判(已记下属主的会话上的调用照旧静默不改,不经这里)。
21
+ * `register` 首写的 owner 守卫 —— core `SessionStore.register` 契约的唯一读法(三只店同调):首写的 owner 既不是主体名也不是 `null` ⇒ 响亮拒(不留行);
22
+ * 「首写」由调用方判(已记下属主的会话上的调用照旧静默不改,不经这里)。判官 = {@link isSessionOwnerValue}(core 7.56.0 [ref] `principalNameOf`)。
9
23
  */
10
24
  export declare function assertFirstOwnerWritable(sessionId: string, owner: unknown): asserts owner is string | null;
25
+ /**
26
+ * 导入者的属主 —— 换装的写腿(公开 `importEntries` / `replaceEntries` 与暂存提交)把调用方给的属主重戳进会话行之前的唯一读法:
27
+ * 主体名或 `null`(匿名)⇒ 原样交回;别的一切(空串、空白串、带控制 / 分隔 / 非连接符格式字符的串、非串)⇒ `TypeError` 响亮拒 ——
28
+ * 与引擎导入口拒同一类值时同一类错、同一句开头(引擎那一判只作用于交给它的属主,而换装交给引擎的是存档自己的戳,所以这一判在本仓)。
29
+ * 调用方在读写任何东西之前判,拒了就一个字节没写。判官 = {@link isSessionOwnerValue}(core `principalNameOf`),不在本仓另写规则。
30
+ */
31
+ export declare function importerOwnerOf(owner: unknown): string | null;
11
32
  //# sourceMappingURL=session-ownership.d.ts.map
@@ -1,11 +1,30 @@
1
- import { SessionError } from "@sema-agent/core";
1
+ import { SessionError, principalNameOf } from "@sema-agent/core";
2
+ export const NOT_A_PRINCIPAL_NAME = "a string that names nobody (empty, blank, or holding a control, separator or invisible format character)";
3
+ function ownerValueFault(owner) {
4
+ if (typeof owner === "string")
5
+ return NOT_A_PRINCIPAL_NAME;
6
+ return owner === undefined ? "undefined" : typeof owner;
7
+ }
8
+ export function isSessionOwnerValue(owner) {
9
+ return owner === null || principalNameOf(owner) !== undefined;
10
+ }
2
11
  export function forkOwnerOf(requested, sourceOwner) {
3
- return typeof requested === "string" ? requested : sourceOwner;
12
+ if (requested === undefined || requested === null)
13
+ return sourceOwner;
14
+ if (principalNameOf(requested) === undefined) {
15
+ throw new SessionError("storage", `fork: session owner must be a principal name or null, got ${ownerValueFault(requested)} — refusing, nothing written`);
16
+ }
17
+ return requested;
4
18
  }
5
19
  export function assertFirstOwnerWritable(sessionId, owner) {
6
- if (typeof owner === "string" || owner === null)
20
+ if (isSessionOwnerValue(owner))
7
21
  return;
8
- throw new SessionError("storage", `register(${sessionId}): a first ownership write must carry a principal (string) or null (anonymous), got ${owner === undefined ? "undefined" : typeof owner} — ` +
9
- "a stored value that the head read reads back as 'no row' would leave the session claimable forever and ownable never; refusing, nothing written");
22
+ throw new SessionError("storage", `register(${sessionId}): a first ownership write must carry a principal name or null (anonymous), got ${ownerValueFault(owner)} — ` +
23
+ "a value that names nobody would leave the session claimable by anyone or ownable by no one; refusing, nothing written");
24
+ }
25
+ export function importerOwnerOf(owner) {
26
+ if (isSessionOwnerValue(owner))
27
+ return owner;
28
+ throw new TypeError(`session owner must be a principal name or null (anonymous), got ${ownerValueFault(owner)} — an import stamps it as the session's owner; refusing, nothing written`);
10
29
  }
11
30
  //# sourceMappingURL=session-ownership.js.map
@@ -0,0 +1,17 @@
1
+ import type { SessionWorkspace } from "../session-workspace.js";
2
+ import { type JsonColumnReader } from "./sql-json-column.js";
3
+ /** 列定义的唯一属主(两方言 DDL 内插它;存量库缺这一列 ⇒ 起服列册对账拒启,拒句里的 ALTER 由建表语句生成)。 */
4
+ export declare const SESSION_META_WORKSPACE_COLUMN: {
5
+ readonly name: "workspace";
6
+ readonly tidb: "workspace JSON NULL";
7
+ readonly pg: "workspace JSONB";
8
+ };
9
+ /** 这一格的形读者(三只店与帧投影同一只;写前也过它 —— 写得进的就是读得出的)。 */
10
+ export declare const readSessionWorkspaceCell: JsonColumnReader<SessionWorkspace>;
11
+ /** 这一格的失败留痕 tag(F 类;登记行在 `observability/fail-open.ts`)。记录座(写 / 帧)与本文件(读)同一只。 */
12
+ export declare const SESSION_WORKSPACE_DEGRADED: "server.session-workspace.record-degraded";
13
+ /** 值 → 这一格的文本。`encode` 是该承载的编码器(MySQL 协议与 local:`JSON.stringify`;PG:`pgSafeJsonStringify`)。写前过形读者,不合形响亮抛、什么都不写。 */
14
+ export declare function encodeSessionWorkspaceCell(workspace: SessionWorkspace, encode: (value: unknown) => string, sessionId: string): string;
15
+ /** 一格(已按文本投影;SQL NULL / local 缺键 ⇒ 调用方传 `null`)→ 值。坏体 ⇒ 读作没有记录并计一次(见文件头);读腿漏投影 ⇒ 抛。 */
16
+ export declare function decodeSessionWorkspaceCell(cell: unknown, sessionId: string): SessionWorkspace | undefined;
17
+ //# sourceMappingURL=session-workspace-cell.d.ts.map
@@ -0,0 +1,38 @@
1
+ import { PROJECT_ID_REGEX } from "@sema-agent/core";
2
+ import { z } from "zod";
3
+ import { recordFailOpen } from "../observability/fail-open.js";
4
+ import { assertJsonColumnWritable, createZodColumnReader, decodeJsonColumn, isJsonColumnBodyProblem } from "./sql-json-column.js";
5
+ export const SESSION_META_WORKSPACE_COLUMN = {
6
+ name: "workspace",
7
+ tidb: "workspace JSON NULL",
8
+ pg: "workspace JSONB",
9
+ };
10
+ const SESSION_WORKSPACE_SHAPE = z.object({
11
+ cwd: z.string().min(1),
12
+ root: z.string().min(1),
13
+ entered: z.object({ dir: z.string().min(1), byPath: z.literal(true).optional() }).optional(),
14
+ project: z.object({ id: z.string().regex(PROJECT_ID_REGEX), source: z.enum(["marker", "declared"]) }).optional(),
15
+ remote: z.boolean(),
16
+ });
17
+ export const readSessionWorkspaceCell = createZodColumnReader(SESSION_WORKSPACE_SHAPE);
18
+ export const SESSION_WORKSPACE_DEGRADED = "server.session-workspace.record-degraded";
19
+ const where = (sessionId) => `session_meta.workspace for session ${sessionId}`;
20
+ export function encodeSessionWorkspaceCell(workspace, encode, sessionId) {
21
+ const text = encode(workspace);
22
+ assertJsonColumnWritable(text, readSessionWorkspaceCell, where(sessionId));
23
+ return text;
24
+ }
25
+ export function decodeSessionWorkspaceCell(cell, sessionId) {
26
+ if (cell === null)
27
+ return undefined;
28
+ try {
29
+ return decodeJsonColumn(cell, readSessionWorkspaceCell, where(sessionId));
30
+ }
31
+ catch (e) {
32
+ if (!isJsonColumnBodyProblem(e))
33
+ throw e;
34
+ recordFailOpen(SESSION_WORKSPACE_DEGRADED, `op=read ${e.where} problem=${e.problem}`);
35
+ return undefined;
36
+ }
37
+ }
38
+ //# sourceMappingURL=session-workspace-cell.js.map
@@ -145,7 +145,7 @@ export declare const MYSQL_CONNECTION_UNUSABLE_ERRORS: ReadonlyArray<{
145
145
  export declare function isConnectionUnusableError(err: unknown): boolean;
146
146
  /**
147
147
  * **连接类故障**的识别表(闭集;逐行登记「为什么」)—— 「到库的那条连接坏了 / 库此刻不接」:与这一条语句的内容无关、什么都不改稍后再试可能成。
148
- * 读者(整仓一只判官 `plugins/store-fault.ts` 的 `storeFaultClassOf`,三处同读):审批队列读口、文件历史店的折点(`permanence: "transient"`)、会话同步拉取口(`503`)。
148
+ * 读者(整仓一只判官 `plugins/store-fault.ts` 的 `storeFaultClassOf`,三处同读):审批队列读口、文件历史店的折点(`permanence: "transient"`)、会话同步拉取口(`503` + `permanence: "transient"`)。
149
149
  *
150
150
  * 识别集 = 三张表的并集,**没有第四处**:
151
151
  * · 本表(下):套接字层与协议层的断连 / 拒连 / 连接数满 / 库的关停与只读切换,按 `code` 登记(MySQL 协议的数字 errno 在场的并登 —— 同本文件其余谓词的姿势:`errno` 与 `code` 是同一件事的两种写法);
@@ -153,7 +153,7 @@ export declare function isConnectionUnusableError(err: unknown): boolean;
153
153
  * · {@link CONNECTION_FAULT_DRIVER_SENTENCES}:驱动自己抛的**无 `code` 的裸 `Error`**(node-pg 的断连在这一形),按整句相等认。
154
154
  *
155
155
  * **不在识别集里**(认不出一律不是 —— 错判成连接类的代价是调用方被劝「再试」去撞一个注定失败的语句):
156
- * · 语句级的错:唯一键冲突、CHECK 被拒、缺表缺列、语法错、权限错、行 / 包超墙(1153 / 8025 / `54000`);
156
+ * · 语句级的错:唯一键冲突、CHECK 被拒、缺列、语法错、行 / 包超墙(1153 / 8025 / `54000`);缺表与权限拒也不是连接类 —— 它们是**部署错配类**(判官的另一个词,识别表 {@link DEPLOYMENT_FAULT_ERRORS},与本表互斥);
157
157
  * · 死锁(引擎的仲裁产物,重试的前提在调用方的整事务重来,见 {@link isDeadlockError})与锁等待 / 语句超时(延迟信号,重试只把长等待乘上次数);
158
158
  * · 认证类拒连(MySQL 1045、PG `28xxx`、`08004`:凭据 / 白名单要人去改)与协议违例(PG `08P01`、mysql2 `PROTOCOL_ERROR`:我方的码病);
159
159
  * · TiDB 自己的忙 / 区域不可用(9001 / 9005 一族)—— 候真库逐码读数再登,今天不在表里(登记在案的未收项);
@@ -180,6 +180,27 @@ export declare const CONNECTION_FAULT_DRIVER_SENTENCES: ReadonlyArray<{
180
180
  * 归因键三种:`code`(字符串)、`errno`(数字)、无 `code` 的驱动裸 `Error` 的整句 —— 只读被抛出的这一只对象身上的结构化字段 / 整句,**不读散文里的在册词**。
181
181
  */
182
182
  export declare function isConnectionFaultError(err: unknown): boolean;
183
+ /**
184
+ * **部署错配类故障**的识别表(闭集;逐行登记「为什么」)—— 到库的连接是好的、语句也是对的,是这套库的形与本部署的要求不符:**重试注定失败**,修表 / 授权之前什么都不会变
185
+ * (与连接类互为反面:那一类是「什么都不改稍后再试可能成」)。读者:整仓一只判官 `plugins/store-fault.ts` 的 `storeFaultClassOf` 的 `deployment` 一词 ——
186
+ * 文件历史店的折点与会话同步拉取口(`503 state.file_history_unreadable`)据它判 `permanence: "terminal"`;审批队列读口并入「此刻读不出」的 503;各读者各自表态,**不在自己那里写码**。
187
+ *
188
+ * 识别集 = 本表一张,按归因键登记:`code`(字符串)与 MySQL 协议的数字 `errno`(两键是同一件事的两种写法,代理 / 序列化往返可能只留一个;同本文件其余谓词的姿势)。
189
+ * **与连接类互斥**:本表的任何一码都不在 {@link CONNECTION_FAULT_ERRORS} / {@link MYSQL_CONNECTION_UNUSABLE_ERRORS} 的识别集里,反之亦然(`test/store-fault-judge.test.ts` 钉两个方向)—— 同一只错只落一个词。
190
+ *
191
+ * **不在表里**(认不出一律不是;本批只收缺表与权限拒两形,其余是登记在案的未收项,不是「已裁定不判」):缺列(1054 / `42703`:升级前置断言 `assert*Schema` 族有自己的判据与出路)、
192
+ * 认证类拒连(MySQL 1045、PG `28xxx`:凭据 / 白名单)、库级与列级的权限拒(MySQL 1044 / 1143)、TiDB 自己的忙 / 区域不可用一族(同连接类表的登记)。
193
+ */
194
+ export declare const DEPLOYMENT_FAULT_ERRORS: ReadonlyArray<{
195
+ readonly code: string;
196
+ readonly errno?: number;
197
+ readonly why: string;
198
+ }>;
199
+ /**
200
+ * 「这个错误**是**部署错配类故障吗」—— {@link DEPLOYMENT_FAULT_ERRORS} 的唯一判据(识别集与排除项见该表头注)。纯谓词、不抛;认不出的一律不是。
201
+ * 只读被抛出的**这一只**对象身上的结构化字段(`code` 字符串 / `errno` 数字),不沿 `cause` 链找、不读散文里的在册词。
202
+ */
203
+ export declare function isDeploymentFaultError(err: unknown): boolean;
183
204
  /**
184
205
  * 检查点店的两笔写(续跑输入 `putCtx` / 停驻行 `put`)被引擎以「一行装不下」拒 ⇒ **这一只**带码错误(码 `store.row_too_large`),不以裸驱动错上抛
185
206
  * (其余店写今天仍是各自的驱动错 —— 未收,登记在案)。
@@ -130,6 +130,21 @@ export function isConnectionFaultError(err) {
130
130
  return true;
131
131
  return err instanceof Error && code === undefined && CONNECTION_FAULT_SENTENCES.has(err.message);
132
132
  }
133
+ export const DEPLOYMENT_FAULT_ERRORS = [
134
+ { code: "42P01", why: "PG undefined_table(缺表:库没按本版的表结构建好 / 迁移没跑 —— 重试不会让表长出来)" },
135
+ { code: "42501", why: "PG insufficient_privilege(权限拒:库账号缺这张表 / 这类语句的授权 —— 授权之前重试注定失败)" },
136
+ { code: "ER_NO_SUCH_TABLE", errno: 1146, why: "MySQL 协议(MySQL / MariaDB / TiDB)缺表:同 PG `42P01`" },
137
+ { code: "ER_TABLEACCESS_DENIED_ERROR", errno: 1142, why: "MySQL 协议表级权限拒:库账号对这张表缺这类语句的授权,同 PG `42501`" },
138
+ ];
139
+ const DEPLOYMENT_FAULT_CODES = new Set(DEPLOYMENT_FAULT_ERRORS.map((r) => r.code));
140
+ const DEPLOYMENT_FAULT_ERRNOS = new Set(DEPLOYMENT_FAULT_ERRORS.flatMap((r) => (r.errno === undefined ? [] : [r.errno])));
141
+ export function isDeploymentFaultError(err) {
142
+ if (err === null || typeof err !== "object")
143
+ return false;
144
+ const code = keyOf(err, "code");
145
+ const errno = keyOf(err, "errno");
146
+ return (typeof code === "string" && DEPLOYMENT_FAULT_CODES.has(code)) || (typeof errno === "number" && DEPLOYMENT_FAULT_ERRNOS.has(errno));
147
+ }
133
148
  export class StoreRowTooLargeError extends Error {
134
149
  row;
135
150
  wall;
@@ -53,7 +53,7 @@ import { TiDBSessionStore } from "./tidb-session-store.js";
53
53
  import { PgSessionStore } from "./pg-session-storage.js";
54
54
  import { TiDBSharedMemoryStore, PgSharedMemoryStore } from "./shared-memory-store-sql.js";
55
55
  import { TiDBAdoptionLogStore, PgAdoptionLogStore } from "./adoption-log-sql.js";
56
- import { TiDBRetentionStore, PgRetentionStore } from "./retention-store-sql.js";
56
+ import { TiDBRetentionStore, PgRetentionStore, sqlStoreRetention } from "./retention-store-sql.js";
57
57
  import { TiDBRetentionLaneStore, PgRetentionLaneStore } from "./retention-lane-store-sql.js";
58
58
  import { createSqlPermissionRuleStores } from "./permission-rule-store-sql.js";
59
59
  import { createFilePermissionRuleStores } from "./permission-rule-store-file.js";
@@ -149,9 +149,9 @@ class TiDBBackend {
149
149
  workflowParkDecisions() { return (this.parkDecisionsInst ??= new SqlWorkflowParkDecisionStore(this.run())); }
150
150
  parkDecisionsInst;
151
151
  sharedMemoryStore(authorizer) { return new TiDBSharedMemoryStore(this.pool, authorizer); }
152
- checkpoint(logger) { return new TiDBCheckpointStore(this.pool, logger); }
152
+ checkpoint(logger) { return new TiDBCheckpointStore(this.pool, logger, { retention: sqlStoreRetention(this.config.retentionSweep) }); }
153
153
  checkpointReadView() { return this.checkpoint(); }
154
- toolResult() { return new TiDBToolResultStore(this.pool); }
154
+ toolResult() { return new TiDBToolResultStore(this.pool, { retention: sqlStoreRetention(this.config.retentionSweep) }); }
155
155
  imageIndex() { return new TiDBImageIndex(this.pool); }
156
156
  imageBake() { return new TiDBImageBake(this.pool); }
157
157
  leaderRun() { return new TiDBLeaderRunStore(this.pool); }
@@ -161,7 +161,7 @@ class TiDBBackend {
161
161
  breaker(onWriteFail) { return new TiDBBreakerState(this.pool, onWriteFail); }
162
162
  costQuota(limitMicroUsd, windowMs, onDegraded) { return new TiDBCostQuota(this.pool, limitMicroUsd, windowMs, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
163
163
  rateLimiter(limit, onDegraded) { return new TiDBRateLimiter(this.pool, limit, undefined, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
164
- session() { return new TiDBSessionStore(this.pool, { log: createLogger(this.config.logLevel) }); }
164
+ session() { return new TiDBSessionStore(this.pool, { log: createLogger(this.config.logLevel), retention: sqlStoreRetention(this.config.retentionSweep) }); }
165
165
  adoptionLog() { return new TiDBAdoptionLogStore(this.pool); }
166
166
  mysqlPool() { return this.pool; }
167
167
  pgPool() { return undefined; }
@@ -203,9 +203,9 @@ class PgBackend {
203
203
  workflowParkDecisions() { return (this.parkDecisionsInst ??= new SqlWorkflowParkDecisionStore(this.run())); }
204
204
  parkDecisionsInst;
205
205
  sharedMemoryStore(authorizer) { return new PgSharedMemoryStore(this.pool, authorizer); }
206
- checkpoint(logger) { return new PgCheckpointStore(this.pool, logger); }
206
+ checkpoint(logger) { return new PgCheckpointStore(this.pool, logger, { retention: sqlStoreRetention(this.config.retentionSweep) }); }
207
207
  checkpointReadView() { return this.checkpoint(); }
208
- toolResult() { return new PgToolResultStore(this.pool); }
208
+ toolResult() { return new PgToolResultStore(this.pool, { retention: sqlStoreRetention(this.config.retentionSweep) }); }
209
209
  imageIndex() { return new PgImageIndex(this.pool); }
210
210
  imageBake() { return new PgImageBake(this.pool); }
211
211
  leaderRun() { return new PgLeaderRunStore(this.pool); }
@@ -215,7 +215,7 @@ class PgBackend {
215
215
  breaker(onWriteFail) { return new PgBreakerState(this.pool, onWriteFail); }
216
216
  costQuota(limitMicroUsd, windowMs, onDegraded) { return new PgCostQuota(this.pool, limitMicroUsd, windowMs, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
217
217
  rateLimiter(limit, onDegraded) { return new PgRateLimiter(this.pool, limit, undefined, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
218
- session() { return new PgSessionStore(this.pool, { log: createLogger(this.config.logLevel) }); }
218
+ session() { return new PgSessionStore(this.pool, { log: createLogger(this.config.logLevel), retention: sqlStoreRetention(this.config.retentionSweep) }); }
219
219
  adoptionLog() { return new PgAdoptionLogStore(this.pool); }
220
220
  mysqlPool() { return undefined; }
221
221
  pgPool() { return this.pool; }
@@ -19,6 +19,7 @@
19
19
  * code should import from this file.
20
20
  */
21
21
  import type { PeerSessionTempo, TaskResult, TaskStatus } from "@sema-agent/core";
22
+ import type { RunIdentity } from "../identity-source.js";
22
23
  /**
23
24
  * **File 店族的 boot 期拒启基类**([ref];把 `RunStoreStrictHydrateError` 的那条论证升成一条族规)。
24
25
  *
@@ -212,8 +213,13 @@ export interface RunRecord {
212
213
  * (MCP façade / portal). null when the caller didn't supply one. */
213
214
  jobId: string | null;
214
215
  /** Which SYSTEM's credential submitted the run (oa/cc-mcp/portal…), derived at the auth gate — never
215
- * self-declared. null = legacy single-token deployment (authenticated, no system identity). */
216
+ * self-declared. null = legacy single-token deployment (authenticated, no system identity).
217
+ * **归因用,不是认证来源**:任何凭据判都不读它(认证来源 = {@link RunRecord.identity});系统名是运维写的任意串,`"sso"` 也只是归因值。 */
216
218
  source: string | null;
219
+ /** 🔴 **run 行身份元组**(三列 `identity_source` / `identity_scope` / `identity_principal_inc`):受理时在凭据门上铸、建行时写入、之后只读 ——
220
+ * 续跑认领 / 挂起 / 终局 / 重启都不改它,没有按当前状态重算的读者。`null` = 这一行没有「属主在受理时验过的凭据」的记录(三列之前的行 /
221
+ * 无鉴权写面的受理 / 别人替属主按下的那一跑),一律不合格。律与形的唯一属主 = `identity-source.ts`。不上 wire(run 读面是显式投影,不带它)。 */
222
+ identity: RunIdentity | null;
217
223
  /** The replica currently HOLDING this run — written at createRun and TAKEN OVER by markResuming ([ref]: a
218
224
  * cross-replica resume moves the seat, so a reader comparing it with its own instanceId is asking "is the
219
225
  * live leg here NOW", not "who minted the row"). Lets a preempt/cancel/steer handler tell "this run is on
@@ -263,6 +269,9 @@ export interface RunIdemBinding {
263
269
  export interface NewRunMeta {
264
270
  jobId?: string | null;
265
271
  source?: string | null;
272
+ /** 这一行的身份元组(`RunRecord.identity` 的写口)。缺席 = `null`(没有记录;不合格)。`src/http/**` 的每个建行点都显式写它(机器门
273
+ * `test/run-identity-tuple.test.ts`),取值只经凭据门铸下的那一份(`principal-gate.ts` 的 `runIdentityOf`)。 */
274
+ identity?: RunIdentity | null;
266
275
  objectivePreview?: string | null;
267
276
  idem?: RunIdemBinding | null;
268
277
  }
@@ -1,4 +1,4 @@
1
- export type StoreFaultClass = "corrupt" | "connection" | "unclassified";
2
- /** 判官本体。纯函数、不抛;只看被抛出的这一只对象(不沿 `cause` 链找)。 */
1
+ export type StoreFaultClass = "corrupt" | "connection" | "deployment" | "unclassified";
2
+ /** 判官本体。纯函数、不抛;只看被抛出的这一只对象(不沿 `cause` 链找)。两张识别表互斥,判序不影响结果(`test/store-fault-judge.test.ts` 钉互斥)。 */
3
3
  export declare function storeFaultClassOf(err: unknown): StoreFaultClass;
4
4
  //# sourceMappingURL=store-fault.d.ts.map
@@ -1,8 +1,10 @@
1
- import { isConnectionFaultError } from "./sql-errors.js";
1
+ import { isConnectionFaultError, isDeploymentFaultError } from "./sql-errors.js";
2
2
  import { StoreCorruptError } from "./sql-json-column.js";
3
3
  export function storeFaultClassOf(err) {
4
4
  if (err instanceof StoreCorruptError)
5
5
  return "corrupt";
6
- return isConnectionFaultError(err) ? "connection" : "unclassified";
6
+ if (isConnectionFaultError(err))
7
+ return "connection";
8
+ return isDeploymentFaultError(err) ? "deployment" : "unclassified";
7
9
  }
8
10
  //# sourceMappingURL=store-fault.js.map
@@ -7,6 +7,8 @@ import { TIDB_ADOPTION_LOG_STATEMENTS } from "./adoption-log-sql.js";
7
7
  import { TIDB_PERMISSION_RULE_STATEMENTS } from "./permission-rule-store-sql.js";
8
8
  import { TIDB_RETENTION_STATEMENTS } from "./retention-store-sql.js";
9
9
  import { SESSION_META_INCARNATION_COLUMN } from "../session-incarnation.js";
10
+ import { SESSION_META_WORKSPACE_COLUMN } from "./session-workspace-cell.js";
11
+ import { RUN_IDENTITY_COLUMNS } from "../identity-source.js";
10
12
  import { SESSION_RULES_COLUMN } from "./session-rules-column.js";
11
13
  import { SESSION_TITLE_MAX_CHARS } from "../session-row.js";
12
14
  import { PRINCIPAL_MAX_UTF8_BYTES } from "../security.js";
@@ -72,6 +74,11 @@ export const SCHEMA_STATEMENTS = [
72
74
  -- (CLAUDE.md / .claude/CLAUDE.md / AGENTS.md / .claude/AGENTS.md)。服务端元数据:不进模型上下文、不进 wire
73
75
  -- 会话面;住在会话行上 ⇒ 随会话删除 / 留存清扫一起消失,fork 出的新行为 NULL(新会话首 run 同样只写不发)。
74
76
  instruction_source VARCHAR(64) NULL,
77
+ -- workspace:本会话上一条腿**自己的**最后一帧 workspace_changed(引擎 7.58.0 的整份快照:cwd / root / entered / project / remote)。
78
+ -- NULL = 还没有任何腿记过;唯一写者 = 腿的记录座(src/session-workspace.ts),列属主 = src/plugins/session-workspace-cell.ts
79
+ -- (列定义、形读者、编解码;存量库缺这一列 ⇒ 起服列册对账拒启,拒句里给出 ALTER)。下一条腿的 TaskSpec.projectId 读它的 project.id。
80
+ -- 服务端元数据:不进 wire 会话面、不进模型上下文;住在会话行上 ⇒ 随会话删除 / 留存清扫一起消失,fork 出的新行为 NULL。
81
+ ${SESSION_META_WORKSPACE_COLUMN.tidb},
75
82
  -- #292 C18(core 5.48.0 design/323)subagent 转录持久化 —— placement 元组,**创建时一次落行、
76
83
  -- first-write 不可变**(register 的 ON DUPLICATE 臂永不重写这六列)。判别位 = placement_kind:
77
84
  -- 在场 ⇒ 该会话住在 placement 分区里(不上宿主枚举、claim 形 acquire 恒拒、release=真删除、
@@ -155,6 +162,12 @@ export const SCHEMA_STATEMENTS = [
155
162
  -- source (credential-derived system identity, clay 2026-06-12): which door submitted the run
156
163
  -- (oa / cc-mcp / portal).
157
164
  source VARCHAR(64) NULL,
165
+ -- identity_source / identity_scope / identity_principal_inc: the run's identity tuple, minted ONCE at the credential gate when the
166
+ -- run is accepted and never rewritten (no UPDATE touches them). NULL = no record of a credential the owner presented at acceptance
167
+ -- (rows from before these columns, unauthenticated-write acceptance, a run someone else accepted on the owner's behalf) ⇒ not
168
+ -- qualified. Column definitions' single owner = src/identity-source.ts RUN_IDENTITY_COLUMNS (the boot column probe derives its
169
+ -- ALTER suggestion from this statement). \`source\` above is attribution only, never an authentication source.
170
+ ${RUN_IDENTITY_COLUMNS.tidb},
158
171
  -- objective_preview: the list's "what is this task" glance — redacted + truncated at write.
159
172
  objective_preview VARCHAR(160) NULL,
160
173
  -- cancel_requested: durable cross-replica CANCEL flag. The running instance's heartbeat tick honors it
@@ -13,6 +13,8 @@
13
13
  import { type AcquiredSession, type PlacedSessionRow, type SessionHead, type SessionPlacementRecord, type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
14
14
  import type { Pool } from "mysql2/promise";
15
15
  import { type InstructionSourceBaseline } from "../instruction-source-notice.js";
16
+ import type { SessionWorkspace } from "../session-workspace.js";
17
+ import type { RetentionDeclaration } from "@sema-agent/core";
16
18
  import { type SessionFace } from "../session-incarnation.js";
17
19
  import type { SessionSummary } from "./store-contracts.js";
18
20
  import type { SessionRowPatch } from "../session-row.js";
@@ -21,9 +23,9 @@ import { type PlacementAcquireOpts } from "./session-placement.js";
21
23
  import { type StagingHandle } from "../session-sync-kernel.js";
22
24
  export declare class TiDBSessionStore implements SessionStore {
23
25
  private readonly pool;
24
- /** [ref] 车1:托管留存声明。读法与「为什么 SQL 店答 managed 而实现体在别处」逐字见
26
+ /** 托管留存声明 = 装配交给它的词(后端按扫车道开不开给;不给 ⇒ `"none"`)。读法逐字见
25
27
  * `retention-store-sql.ts` 的 {@link MANAGED_RETENTION}。 */
26
- readonly retention: import("@sema-agent/core").RetentionDeclaration;
28
+ readonly retention: RetentionDeclaration;
27
29
  /** [ref] C18(core 5.48.0 [ref]):placement **声明**。六条义务的实装点逐条见
28
30
  * {@link SQL_SESSION_PLACEMENTS} 顶注与本类的 acquire / listSessions / release / listPlaced /
29
31
  * placementOf 各处的 `[ref]` 注。 */
@@ -38,6 +40,7 @@ export declare class TiDBSessionStore implements SessionStore {
38
40
  private readonly log;
39
41
  constructor(pool: Pool, opts?: {
40
42
  readonly log?: OrphanOwnerLog;
43
+ readonly retention?: RetentionDeclaration;
41
44
  });
42
45
  acquire(sessionId?: string, opts?: PlacementAcquireOpts): Promise<AcquiredSession>;
43
46
  private load;
@@ -165,6 +168,18 @@ export declare class TiDBSessionStore implements SessionStore {
165
168
  * 在期限内拒。⚠️ mysql2 的超时是客户端侧的 —— 拒之后那条连接仍被挂着的命令占到服务端结束(S-9 同形,如实披露)。
166
169
  */
167
170
  recordInstructionSource(sessionId: string, expected: InstructionSourceBaseline, source: string | null): Promise<void>;
171
+ /**
172
+ * 会话行的位置与项目那一格(`session_meta.workspace`;域律 `src/session-workspace.ts`,列属主 `session-workspace-cell.ts`)。
173
+ * 一行 PK 读,按文本投影、恰好解一次;行不在 / 格为 NULL ⇒ `undefined`;格读不出 ⇒ 读作没有记录并计一次(F 类,见列属主头注)。
174
+ */
175
+ readSessionWorkspace(sessionId: string): Promise<SessionWorkspace | undefined>;
176
+ /**
177
+ * 整格覆写(最后一帧胜;唯一调用方 = 腿的记录座,它在腿的流循环里一笔一笔等写完)。**住客围栏**:只写化身仍是 `incarnation` 的那一行 ——
178
+ * 行不在、或同 id 已换了住客 ⇒ 0 行、不抛(那一行不是这条腿的)。**不**碰 `updated_at`(那是会话活动时刻,留存腿按它判龄;记下站在哪里不是一次会话活动)。
179
+ * 走店的一般查询面(与腿循环里的账本追加同一形,不另设每查询的客户端超时):mysql2 的客户端超时只是不再等,服务端照把那条 UPDATE 跑完 ——
180
+ * 一笔「放弃等待却仍会落地」的写正是这条腿离开之后还能盖掉下一条腿的那一形。卡住的上界归服务端(锁等待超时)与部署的池策略。
181
+ */
182
+ recordSessionWorkspace(sessionId: string, incarnation: string, workspace: SessionWorkspace): Promise<void>;
168
183
  /**
169
184
  * E17 — fork a session: copy its WHOLE durable history to a NEW uuidv7 session owned by `owner`, mirroring
170
185
  * core's `PgSessionRepo.fork`. Entry ids / parent links are per-session and copy VERBATIM; only `seq` is
@@ -4,24 +4,27 @@ import { decodeSessionEventPayload } from "./session-event-payload.js";
4
4
  import { jsonColumnText } from "./sql-json-column.js";
5
5
  import { escapeLike } from "./sql-escape.js";
6
6
  import { BASELINE_IO_DEADLINE_MS, decodeInstructionSource, encodeInstructionSource } from "../instruction-source-notice.js";
7
- import { MANAGED_RETENTION } from "./retention-store-sql.js";
7
+ import { decodeSessionWorkspaceCell, encodeSessionWorkspaceCell } from "./session-workspace-cell.js";
8
+ import { MANAGED_RETENTION, UNMANAGED_RETENTION } from "./retention-store-sql.js";
8
9
  import { carriedIncarnation, headFromRow, mintSessionIncarnation, sessionFaceFromRow } from "../session-incarnation.js";
9
10
  import { contentForkRelation, fastForwardSharedContentDiverged } from "../session-sync-content.js";
10
11
  import { CLAIM_OWNERLESS_PLACED_SQL, claimOwnerlessParams, createPlacedSessionRow } from "../delegated-session-owner.js";
11
12
  import { createLogger } from "../observability/logger.js";
12
13
  import { placementCapabilityOf, LIST_PLACED_BATCH, PLACEMENT_SELECT_COLUMNS, placedRowFromRow, placementFromRow, placementInsertValues, SQL_SESSION_PLACEMENTS, } from "./session-placement.js";
13
14
  import { classifySyncRelationshipByIds, SyncConflictError, StagedCommitOwnerChangedError, stagingIdFor, STAGING_ID_MARKER, STAGING_GC_GRACE_MS, } from "../session-sync-kernel.js";
14
- import { assertFirstOwnerWritable, forkOwnerOf } from "./session-ownership.js";
15
- import { forkCopyOf, forkPointOf } from "./session-fork.js";
15
+ import { assertFirstOwnerWritable, forkOwnerOf, isSessionOwnerValue } from "./session-ownership.js";
16
+ import { selectForkRows } from "@sema-agent/core";
17
+ import { FORK_LOG_ROW_SHAPE, forkPointOf } from "./session-fork.js";
16
18
  export class TiDBSessionStore {
17
19
  pool;
18
- retention = MANAGED_RETENTION;
20
+ retention;
19
21
  placements = SQL_SESSION_PLACEMENTS;
20
22
  pending = new Map();
21
23
  log;
22
24
  constructor(pool, opts = {}) {
23
25
  this.pool = pool;
24
26
  this.log = opts.log ?? createLogger();
27
+ this.retention = opts.retention ?? UNMANAGED_RETENTION;
25
28
  }
26
29
  async acquire(sessionId, opts) {
27
30
  if (!sessionId) {
@@ -58,7 +61,7 @@ export class TiDBSessionStore {
58
61
  return { session: new StoredSession(storage), sessionId };
59
62
  }
60
63
  async register(sessionId, owner) {
61
- if (typeof owner !== "string" && owner !== null) {
64
+ if (!isSessionOwnerValue(owner)) {
62
65
  if ((await this.headOf(sessionId)) !== undefined)
63
66
  return;
64
67
  assertFirstOwnerWritable(sessionId, owner);
@@ -247,6 +250,14 @@ export class TiDBSessionStore {
247
250
  await this.pool.query({ sql: "UPDATE session_meta SET instruction_source = ? WHERE session_id = ? AND instruction_source IS NULL", timeout: BASELINE_IO_DEADLINE_MS }, [next, sessionId]);
248
251
  }
249
252
  }
253
+ async readSessionWorkspace(sessionId) {
254
+ const [rows] = await this.pool.query(`SELECT ${jsonColumnText("tidb", "workspace")} FROM session_meta WHERE session_id = ?`, [sessionId]);
255
+ const row = rows[0];
256
+ return row === undefined ? undefined : decodeSessionWorkspaceCell(row.workspace, sessionId);
257
+ }
258
+ async recordSessionWorkspace(sessionId, incarnation, workspace) {
259
+ await this.pool.query("UPDATE session_meta SET workspace = ? WHERE session_id = ? AND incarnation = ?", [encodeSessionWorkspaceCell(workspace, JSON.stringify, sessionId), sessionId, incarnation]);
260
+ }
250
261
  async fork(sourceId, owner) {
251
262
  const [metaRows] = await this.pool.query("SELECT leaf_id, owner FROM session_meta WHERE session_id = ?", [sourceId]);
252
263
  if (!metaRows[0])
@@ -258,7 +269,7 @@ export class TiDBSessionStore {
258
269
  return null;
259
270
  const point = await forkPointOf(storage);
260
271
  const [allRows] = await this.pool.query(`SELECT entry_id, parent_id, type, ${jsonColumnText("tidb", "payload")}, ts FROM session_event WHERE session_id = ? ORDER BY seq ASC`, [sourceId]);
261
- const { rows: eventRows, leafId: forkLeafId } = forkCopyOf(allRows, leafId, point);
272
+ const { rows: eventRows, leafId: forkLeafId } = selectForkRows(allRows, leafId, point, FORK_LOG_ROW_SHAPE);
262
273
  const newId = uuidv7();
263
274
  const now = new Date();
264
275
  const conn = await this.pool.getConnection();
@@ -353,7 +364,7 @@ export class TiDBSessionStore {
353
364
  }
354
365
  await conn.query("DELETE FROM session_event WHERE session_id = ?", [sessionId]);
355
366
  await conn.query("DELETE FROM session_meta WHERE session_id = ? AND owner <=> ? AND placement_kind IS NULL", [sessionId, owner]);
356
- await this.insertValidatedLog(conn, sessionId, owner, validated, carriedIncarnation(sessionId, placedRows[0] === undefined ? undefined : { owner: placedRows[0].owner, incarnation: placedRows[0].incarnation }, owner));
367
+ await this.insertValidatedLog(conn, sessionId, owner, validated, carriedIncarnation(sessionId, placedRows[0] === undefined ? undefined : { incarnation: placedRows[0].incarnation }));
357
368
  await conn.commit();
358
369
  }
359
370
  catch (err) {
@@ -2,6 +2,7 @@ import type { ToolResultProvenance, ToolResultStore, ToolResultSlice, ToolResult
2
2
  import type { Pool as MySqlPool } from "mysql2/promise";
3
3
  import type { Pool as PgPool, PoolClient as PgPoolClient } from "pg";
4
4
  import { type SqlDriver } from "./sql-driver.js";
5
+ import type { RetentionDeclaration } from "@sema-agent/core";
5
6
  import { type IndexSpec } from "./ensure-index.js";
6
7
  /** PG schema for the tool_result table — the PG translation of tidb-pool.ts's tool_result DDL
7
8
  * (LONGTEXT→TEXT, DATETIME(3)→TIMESTAMPTZ(3), inline KEY→separate CREATE INDEX). Disjoint from other stores'
@@ -29,10 +30,12 @@ export declare function assertToolResultProvenanceSchema(query: (sql: string) =>
29
30
  /** Dual-dialect durable ToolResultStore. See the file header for the dialect-delta ledger. */
30
31
  export declare class SqlToolResultStore implements ToolResultStore {
31
32
  protected readonly db: SqlDriver;
32
- /** [ref] 车1:托管留存声明。读法与「为什么 SQL 店答 managed 而三方法的实现体在 `retention-store-sql.ts`」
33
- * 逐字见 {@link MANAGED_RETENTION}(本店的 `tool_result` 行由那只聚合店按期清:随会话树删 + 孤儿腿)。 */
34
- readonly retention: import("@sema-agent/core").RetentionDeclaration;
35
- constructor(db: SqlDriver);
33
+ /** 托管留存声明 = 装配交给它的词(后端按扫车道开不开给;不给 ⇒ `"none"`)。读法与「为什么 SQL 店答 managed 而三方法的实现体在
34
+ * `retention-store-sql.ts`」逐字见 {@link MANAGED_RETENTION}(扫车道开着时本店的 `tool_result` 行由那只聚合店按期清:随会话树删 + 孤儿腿)。 */
35
+ readonly retention: RetentionDeclaration;
36
+ constructor(db: SqlDriver, opts?: {
37
+ readonly retention?: RetentionDeclaration;
38
+ });
36
39
  /** Pick the dialect's SQL text. Both statements stay written out at the call site ON PURPOSE. */
37
40
  private q;
38
41
  /** D1(试剂盒揪出,[ref] 语义):ref 是主键,而 `deleteBySession` 只认**记录下来的出处**与单射的
@@ -97,10 +100,14 @@ export declare class SqlToolResultStore implements ToolResultStore {
97
100
  }
98
101
  /** MySQL-protocol (TiDB) binding — historical class name + ctor shape preserved. */
99
102
  export declare class TiDBToolResultStore extends SqlToolResultStore {
100
- constructor(pool: MySqlPool);
103
+ constructor(pool: MySqlPool, opts?: {
104
+ readonly retention?: RetentionDeclaration;
105
+ });
101
106
  }
102
107
  /** PostgreSQL binding — historical class name + ctor shape preserved. */
103
108
  export declare class PgToolResultStore extends SqlToolResultStore {
104
- constructor(pool: PgPool);
109
+ constructor(pool: PgPool, opts?: {
110
+ readonly retention?: RetentionDeclaration;
111
+ });
105
112
  }
106
113
  //# sourceMappingURL=tool-result-store-sql.d.ts.map