@sema-agent/server 7.139.0 → 7.141.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 (328) hide show
  1. package/MIGRATION.md +471 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +94 -26
  5. package/dist/adoption/runner.js +1 -1
  6. package/dist/adoption/sql.js +1 -1
  7. package/dist/approval-batch-census.d.ts +27 -0
  8. package/dist/approval-batch-census.js +27 -0
  9. package/dist/approval-card.d.ts +37 -22
  10. package/dist/approval-card.js +6 -3
  11. package/dist/approval.d.ts +15 -0
  12. package/dist/approval.js +10 -0
  13. package/dist/audit.d.ts +4 -2
  14. package/dist/audit.js +2 -2
  15. package/dist/bench/s1/live-deps.js +3 -2
  16. package/dist/bench/s1/row.d.ts +5 -2
  17. package/dist/bench/s1/row.js +2 -22
  18. package/dist/boot/adoption.js +1 -1
  19. package/dist/boot/device-lane.d.ts +11 -0
  20. package/dist/boot/device-lane.js +16 -0
  21. package/dist/boot/engine-lease.d.ts +24 -3
  22. package/dist/boot/engine-lease.js +9 -2
  23. package/dist/boot/execution-env.js +18 -12
  24. package/dist/boot/execution-lane.d.ts +8 -0
  25. package/dist/boot/execution-lane.js +6 -1
  26. package/dist/boot/memory-boundary.d.ts +16 -53
  27. package/dist/boot/memory-boundary.js +10 -20
  28. package/dist/boot/memory-consolidation.d.ts +16 -12
  29. package/dist/boot/memory-consolidation.js +24 -13
  30. package/dist/boot/reapers.d.ts +2 -2
  31. package/dist/boot/resolve-spec.d.ts +3 -5
  32. package/dist/boot/resolve-spec.js +9 -8
  33. package/dist/boot/runner-deps.d.ts +3 -3
  34. package/dist/boot/runner-deps.js +1 -0
  35. package/dist/boot/session-faces.d.ts +1 -1
  36. package/dist/boot/session-faces.js +4 -3
  37. package/dist/boot/shutdown.js +5 -0
  38. package/dist/boot/stage-03-store-backend.d.ts +2 -6
  39. package/dist/boot/stage-03-store-backend.js +2 -3
  40. package/dist/boot/stage-04-stores.d.ts +2 -6
  41. package/dist/boot/stage-04-stores.js +5 -5
  42. package/dist/boot/stage-05-execution-env.d.ts +2 -6
  43. package/dist/boot/stage-05-execution-env.js +3 -1
  44. package/dist/boot/stage-06-runners.d.ts +2 -8
  45. package/dist/boot/stage-06-runners.js +3 -3
  46. package/dist/boot/stage-07-capability-layer.d.ts +2 -7
  47. package/dist/boot/stage-07-capability-layer.js +8 -10
  48. package/dist/boot/stage-08-reapers.d.ts +2 -7
  49. package/dist/boot/stage-09-leader.d.ts +2 -7
  50. package/dist/boot/stage-10-http-server.d.ts +2 -7
  51. package/dist/boot/stage-10-http-server.js +6 -4
  52. package/dist/boot/stores.d.ts +3 -6
  53. package/dist/boot/stores.js +37 -44
  54. package/dist/boot/task-list-lane.d.ts +1 -1
  55. package/dist/boot/task-list-lane.js +1 -1
  56. package/dist/boot/web-admin.js +36 -9
  57. package/dist/capabilities/execution-lane.d.ts +2 -2
  58. package/dist/capabilities/scenarios.d.ts +1 -1
  59. package/dist/capability-facts.d.ts +9 -0
  60. package/dist/capability-facts.js +9 -0
  61. package/dist/card-void.d.ts +38 -0
  62. package/dist/card-void.js +23 -0
  63. package/dist/config-catalog.js +12 -8
  64. package/dist/config-provider.d.ts +18 -17
  65. package/dist/config-provider.js +28 -36
  66. package/dist/config-types.d.ts +36 -9
  67. package/dist/config.js +56 -46
  68. package/dist/delegated-session-owner.d.ts +23 -20
  69. package/dist/delegated-session-owner.js +2 -2
  70. package/dist/deployment-shape.d.ts +9 -8
  71. package/dist/deployment-shape.js +4 -4
  72. package/dist/device-store.d.ts +7 -0
  73. package/dist/device-store.js +3 -0
  74. package/dist/execution-config-root.d.ts +22 -0
  75. package/dist/execution-config-root.js +35 -0
  76. package/dist/execution-lane-caps.d.ts +145 -107
  77. package/dist/execution-lane-caps.js +144 -83
  78. package/dist/execution-placement.d.ts +3 -0
  79. package/dist/execution-placement.js +7 -0
  80. package/dist/fleet/drain-entry.d.ts +3 -0
  81. package/dist/hosted-posture.d.ts +8 -0
  82. package/dist/hosted-posture.js +4 -0
  83. package/dist/http/admission.js +3 -3
  84. package/dist/http/caller-trust.d.ts +3 -2
  85. package/dist/http/caller-trust.js +2 -1
  86. package/dist/http/dispatch.js +4 -0
  87. package/dist/http/live-frame.d.ts +24 -0
  88. package/dist/http/live-frame.js +16 -0
  89. package/dist/http/memory-compliance-failure-reply.d.ts +3 -1
  90. package/dist/http/memory-compliance-failure-reply.js +5 -0
  91. package/dist/http/memory-layer-reply.d.ts +30 -0
  92. package/dist/http/memory-layer-reply.js +24 -0
  93. package/dist/http/resume-legs.js +49 -35
  94. package/dist/http/retired-service-deps.d.ts +1 -1
  95. package/dist/http/retired-service-deps.js +1 -1
  96. package/dist/http/route-table.js +2 -0
  97. package/dist/http/routes/adoption.js +1 -1
  98. package/dist/http/routes/approvals-assistant.js +1 -0
  99. package/dist/http/routes/capabilities.js +5 -4
  100. package/dist/http/routes/diagnostics.d.ts +0 -19
  101. package/dist/http/routes/diagnostics.js +16 -2
  102. package/dist/http/routes/memory-bundle.d.ts +2 -2
  103. package/dist/http/routes/memory-bundle.js +4 -1
  104. package/dist/http/routes/memory-compliance.js +9 -2
  105. package/dist/http/routes/memory-consolidation.js +12 -1
  106. package/dist/http/routes/memory-origin.js +14 -2
  107. package/dist/http/routes/memory-policy.js +7 -2
  108. package/dist/http/routes/run-permission-mode.d.ts +75 -0
  109. package/dist/http/routes/run-permission-mode.js +170 -0
  110. package/dist/http/routes/session-sync.d.ts +3 -6
  111. package/dist/http/routes/session-sync.js +7 -2
  112. package/dist/http/routes/sessions.js +33 -15
  113. package/dist/http/routes/tasks.js +67 -68
  114. package/dist/http/run-read-face.js +3 -3
  115. package/dist/http/send.d.ts +1 -1
  116. package/dist/http/send.js +2 -2
  117. package/dist/http/server.d.ts +14 -27
  118. package/dist/http/server.js +2 -2
  119. package/dist/http/sse-log.d.ts +3 -8
  120. package/dist/http/stored-body-replay.d.ts +3 -3
  121. package/dist/http/stored-body-replay.js +3 -1
  122. package/dist/identity-source.d.ts +1 -1
  123. package/dist/identity-source.js +1 -1
  124. package/dist/instruction-source-notice.d.ts +7 -0
  125. package/dist/instruction-source-notice.js +6 -6
  126. package/dist/lane-home-probe.d.ts +68 -42
  127. package/dist/lane-home-probe.js +53 -30
  128. package/dist/leader/wire.js +5 -4
  129. package/dist/mcp-assertion-header.d.ts +4 -0
  130. package/dist/mcp-assertion-header.js +5 -0
  131. package/dist/memory-bundle-engine.d.ts +16 -9
  132. package/dist/memory-bundle-engine.js +29 -6
  133. package/dist/memory-operator-faces.d.ts +85 -30
  134. package/dist/memory-operator-faces.js +136 -30
  135. package/dist/memory-posture.d.ts +1 -1
  136. package/dist/memory-project-layer.d.ts +3 -21
  137. package/dist/memory-project-layer.js +11 -8
  138. package/dist/memory-scope-stores.d.ts +73 -0
  139. package/dist/memory-scope-stores.js +86 -0
  140. package/dist/memory-scope.d.ts +33 -9
  141. package/dist/memory-scope.js +17 -5
  142. package/dist/memory-sync-client.d.ts +34 -9
  143. package/dist/memory-sync-client.js +108 -28
  144. package/dist/observability/fail-open.d.ts +30 -2
  145. package/dist/observability/fail-open.js +30 -2
  146. package/dist/observability/metrics.js +0 -1
  147. package/dist/observability/run-terminal.d.ts +6 -2
  148. package/dist/observability/run-terminal.js +25 -26
  149. package/dist/observability/secret-env-scrub.d.ts +20 -1
  150. package/dist/observability/secret-env-scrub.js +14 -0
  151. package/dist/orchestration/workflow-completion-inbox.d.ts +5 -2
  152. package/dist/orchestration/workflow-completion-inbox.js +13 -5
  153. package/dist/orchestration/workflow-notify-journal.d.ts +5 -3
  154. package/dist/orchestration/workflow-notify-journal.js +2 -1
  155. package/dist/permission-mode-admission.d.ts +68 -0
  156. package/dist/permission-mode-admission.js +23 -0
  157. package/dist/permission-rule-list.d.ts +55 -6
  158. package/dist/permission-rule-list.js +52 -5
  159. package/dist/plugins/adoption-log-sql.js +4 -4
  160. package/dist/plugins/approval-ask-store-sql.js +14 -14
  161. package/dist/plugins/approval-nonce-store.js +4 -4
  162. package/dist/plugins/blob-backend.d.ts +4 -4
  163. package/dist/plugins/blob-backend.js +7 -7
  164. package/dist/plugins/breaker-state-sql.js +2 -2
  165. package/dist/plugins/caching-session-store.d.ts +6 -0
  166. package/dist/plugins/caching-session-store.js +3 -0
  167. package/dist/plugins/checkpoint-index-columns.js +2 -2
  168. package/dist/plugins/checkpoint-store-sql.d.ts +65 -17
  169. package/dist/plugins/checkpoint-store-sql.js +90 -19
  170. package/dist/plugins/device-store-sql.d.ts +5 -2
  171. package/dist/plugins/device-store-sql.js +23 -20
  172. package/dist/plugins/ensure-index.d.ts +1 -2
  173. package/dist/plugins/execution-placement-sql.d.ts +19 -9
  174. package/dist/plugins/execution-placement-sql.js +20 -9
  175. package/dist/plugins/file-history-store-sql.d.ts +2 -2
  176. package/dist/plugins/file-history-store-sql.js +4 -4
  177. package/dist/plugins/file-run-store.d.ts +2 -2
  178. package/dist/plugins/file-run-store.js +1 -1
  179. package/dist/plugins/fork-routing-session-store.d.ts +10 -32
  180. package/dist/plugins/fork-routing-session-store.js +2 -61
  181. package/dist/plugins/image-bake-store-sql.js +9 -9
  182. package/dist/plugins/image-index-sql.js +11 -11
  183. package/dist/plugins/k8s-exec-protocol.d.ts +4 -1
  184. package/dist/plugins/k8s-exec-protocol.js +6 -1
  185. package/dist/plugins/leader-run-store-sql.js +4 -4
  186. package/dist/plugins/local-checkpoint-store.d.ts +10 -1
  187. package/dist/plugins/local-checkpoint-store.js +22 -0
  188. package/dist/plugins/local-session-store.d.ts +227 -35
  189. package/dist/plugins/local-session-store.js +518 -37
  190. package/dist/plugins/local-session-window.d.ts +17 -3
  191. package/dist/plugins/local-session-window.js +7 -13
  192. package/dist/plugins/mailbox-store-sql.d.ts +2 -1
  193. package/dist/plugins/mailbox-store-sql.js +4 -4
  194. package/dist/plugins/memory-engine-tidb.js +5 -5
  195. package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
  196. package/dist/plugins/memory-run-store.d.ts +2 -2
  197. package/dist/plugins/memory-run-store.js +1 -1
  198. package/dist/plugins/memory-sync-store-tidb.js +3 -3
  199. package/dist/plugins/one-time-migrations.d.ts +52 -11
  200. package/dist/plugins/one-time-migrations.js +101 -39
  201. package/dist/plugins/org-delivery-quota-store.js +2 -2
  202. package/dist/plugins/outcome-ledger-sql.js +2 -2
  203. package/dist/plugins/permission-rule-store-sql.d.ts +4 -4
  204. package/dist/plugins/permission-rule-store-sql.js +16 -16
  205. package/dist/plugins/pg-pool.js +3 -2
  206. package/dist/plugins/pg-session-storage.d.ts +2 -0
  207. package/dist/plugins/pg-session-storage.js +3 -2
  208. package/dist/plugins/remote-env-adb.d.ts +7 -24
  209. package/dist/plugins/remote-env-adb.js +22 -5
  210. package/dist/plugins/remote-env-device.d.ts +2 -28
  211. package/dist/plugins/remote-env-device.js +2 -1
  212. package/dist/plugins/remote-env-e2b.d.ts +40 -27
  213. package/dist/plugins/remote-env-e2b.js +180 -20
  214. package/dist/plugins/remote-env-file-error.d.ts +1 -1
  215. package/dist/plugins/remote-env-file-error.js +8 -2
  216. package/dist/plugins/remote-env-host.d.ts +19 -35
  217. package/dist/plugins/remote-env-host.js +26 -3
  218. package/dist/plugins/remote-env-k8s.d.ts +22 -14
  219. package/dist/plugins/remote-env-k8s.js +150 -26
  220. package/dist/plugins/remote-env-local-docker.d.ts +27 -24
  221. package/dist/plugins/remote-env-local-docker.js +91 -24
  222. package/dist/plugins/remote-env-ssh.d.ts +4 -24
  223. package/dist/plugins/remote-env-ssh.js +4 -3
  224. package/dist/plugins/resume-anchor-store-sql.js +2 -2
  225. package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
  226. package/dist/plugins/retention-lane-store-sql.js +2 -2
  227. package/dist/plugins/retention-store-sql.d.ts +1 -1
  228. package/dist/plugins/retention-store-sql.js +6 -6
  229. package/dist/plugins/run-store-sql.d.ts +3 -3
  230. package/dist/plugins/run-store-sql.js +19 -18
  231. package/dist/plugins/sandbox-read-floor.d.ts +273 -0
  232. package/dist/plugins/sandbox-read-floor.js +608 -0
  233. package/dist/plugins/schema-consistency.d.ts +6 -6
  234. package/dist/plugins/schema-consistency.js +1 -1
  235. package/dist/plugins/schema-ensure-legs.d.ts +2 -3
  236. package/dist/plugins/schema-ensure-legs.js +2 -2
  237. package/dist/plugins/schema-live-columns.d.ts +1 -1
  238. package/dist/plugins/session-capture-record-store-sql.js +1 -1
  239. package/dist/plugins/session-ownership.d.ts +2 -1
  240. package/dist/plugins/session-placement.d.ts +17 -4
  241. package/dist/plugins/session-placement.js +2 -1
  242. package/dist/plugins/session-rules-column.d.ts +1 -1
  243. package/dist/plugins/session-rules-column.js +1 -1
  244. package/dist/plugins/session-store.d.ts +18 -20
  245. package/dist/plugins/session-store.js +4 -12
  246. package/dist/plugins/session-workspace-cell.d.ts +1 -1
  247. package/dist/plugins/session-workspace-cell.js +1 -1
  248. package/dist/plugins/shared-memory-store-sql.js +2 -2
  249. package/dist/plugins/sql-driver.d.ts +10 -5
  250. package/dist/plugins/sql-driver.js +6 -6
  251. package/dist/plugins/sql-errors.js +1 -1
  252. package/dist/plugins/store-backend.d.ts +35 -6
  253. package/dist/plugins/store-backend.js +27 -10
  254. package/dist/plugins/store-contracts.d.ts +9 -2
  255. package/dist/plugins/task-list-store-sql.js +11 -11
  256. package/dist/plugins/tidb-pool.js +7 -6
  257. package/dist/plugins/tidb-session-storage.js +4 -4
  258. package/dist/plugins/tidb-session-store.d.ts +4 -1
  259. package/dist/plugins/tidb-session-store.js +16 -15
  260. package/dist/plugins/tool-result-store-sql.d.ts +2 -2
  261. package/dist/plugins/tool-result-store-sql.js +3 -3
  262. package/dist/plugins/user-input-ledger-sql.js +2 -2
  263. package/dist/plugins/workflow-journal-store-sql.js +5 -5
  264. package/dist/plugins/workflow-run-store-sql.js +19 -19
  265. package/dist/plugins/write-behind-counter.d.ts +2 -3
  266. package/dist/plugins/write-behind-counter.js +5 -5
  267. package/dist/resource-suspend.d.ts +14 -12
  268. package/dist/resource-suspend.js +1 -1
  269. package/dist/resource-window.d.ts +4 -3
  270. package/dist/run-cancel-context.d.ts +34 -0
  271. package/dist/run-cancel-context.js +7 -0
  272. package/dist/run-local.js +14 -19
  273. package/dist/runs.d.ts +47 -16
  274. package/dist/runs.js +112 -113
  275. package/dist/security.d.ts +2 -2
  276. package/dist/server-secret-env.d.ts +2 -1
  277. package/dist/server-secret-env.js +2 -4
  278. package/dist/session-error-wire.d.ts +22 -4
  279. package/dist/session-error-wire.js +16 -0
  280. package/dist/session-incarnation.d.ts +10 -4
  281. package/dist/session-incarnation.js +1 -1
  282. package/dist/session-policy-wire.d.ts +1 -1
  283. package/dist/session-sync-kernel.d.ts +42 -1
  284. package/dist/session-sync-kernel.js +17 -0
  285. package/dist/session-sync.js +16 -4
  286. package/dist/sql-engine-coordinates.d.ts +49 -0
  287. package/dist/sql-engine-coordinates.js +27 -0
  288. package/dist/sql-engine-posture.d.ts +1 -1
  289. package/dist/sql-engine-posture.js +1 -1
  290. package/dist/standing-answer-grant.d.ts +31 -2
  291. package/dist/standing-answer-grant.js +14 -2
  292. package/dist/store-posture.d.ts +1 -1
  293. package/dist/{plugins → stores-sql}/background-agent-store-sql.d.ts +2 -2
  294. package/dist/{plugins → stores-sql}/background-agent-store-sql.js +8 -8
  295. package/dist/{plugins → stores-sql}/session-policy-store-sql.d.ts +7 -5
  296. package/dist/{plugins → stores-sql}/session-policy-store-sql.js +12 -12
  297. package/dist/{plugins → stores-sql}/usage-window-store-sql.d.ts +1 -1
  298. package/dist/{plugins → stores-sql}/usage-window-store-sql.js +3 -3
  299. package/dist/task-a2a.d.ts +1 -1
  300. package/dist/task-a2a.js +5 -6
  301. package/dist/task-mcp.d.ts +21 -8
  302. package/dist/task-mcp.js +17 -9
  303. package/dist/task-settings.d.ts +52 -25
  304. package/dist/task-settings.js +91 -28
  305. package/dist/terminal.d.ts +103 -19
  306. package/dist/terminal.js +72 -20
  307. package/dist/trace/core-keyset-guard.d.ts +79 -2
  308. package/dist/trace/exit-seat.d.ts +7 -0
  309. package/dist/trace/exit-seat.js +1 -0
  310. package/dist/trace/model-segment.d.ts +2 -2
  311. package/dist/trace/redact.d.ts +3 -1
  312. package/dist/trace/redact.js +395 -110
  313. package/dist/trace/self-minted-wire.d.ts +226 -2
  314. package/dist/trace/self-minted-wire.js +79 -0
  315. package/dist/verifier-pause-card.d.ts +8 -0
  316. package/dist/verifier-pause-card.js +19 -0
  317. package/dist/web-admin-client/apply-effective.d.ts +5 -7
  318. package/dist/web-admin-client/apply-effective.js +2 -2
  319. package/dist/web-admin-client/candidate-gate.d.ts +11 -7
  320. package/dist/web-admin-client/candidate-gate.js +1 -1
  321. package/dist/web-admin-client/http-client.d.ts +5 -4
  322. package/dist/web-admin-client/http-client.js +2 -2
  323. package/dist/web-admin-client/read-warnings.d.ts +7 -17
  324. package/dist/web-admin-client/read-warnings.js +5 -9
  325. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
  326. package/package.json +2 -2
  327. package/wire-changes/server@7.140.0.json +184 -0
  328. package/wire-changes/server@7.141.0.json +367 -0
@@ -0,0 +1,68 @@
1
+ /**
2
+ * **一个调用方交来的权限模式词,本部署收不收、收成什么** —— 唯一的受理判官(规则一处、三只属主各一处、序一处)。
3
+ *
4
+ * ## 一条规则,三只属主,本模块只排序
5
+ * ① 本任务 settings 的 kill-switch 折叠(`task-settings.ts` `foldDisableAutoMode`:`disableAutoMode` 在 ⇒ `auto` 折 `default`);
6
+ * ② 运维 `AUTONOMY` 的入口地板钳(`runtime-governance.ts` `entryPermissionMode` × `autonomyModeFloor`:`plan` 地板下比它松的词折成 `plan`);
7
+ * ③ 托管姿态的写围栏拒(`hosted-posture.ts` `permissionModeWriteFaceRefusal`:开写面的词在托管形上 422 `request.host_posture_refused`)。
8
+ * ①② 是**入口一步**({@link entryStep}:改词、不拒),③ 是**托管一步**(只拒、不改词)。顺序承重的只有「② 在 ③ 之前」(地板把 bypass 钳成 plan 之后就不开写面,不拒);
9
+ * ① 只动 `auto`、③ 只看开写面的词,两者互不相交。
10
+ *
11
+ * ## 两口的调用形(同一组函数、同一个序;同一个词 × 同一份部署事实 × 同一份任务 settings ⇒ 同一个结果,钉 `test/run-permission-mode-admission.test.ts` 的两口表)
12
+ * · 在飞 run 的切档口(`http/routes/run-permission-mode.ts`:`POST /v1/runs/:id/permission-mode` 的 `mode`,本任务 settings 读存储体)调整只判官 {@link admitPermissionModeWord}。
13
+ * · 提交口(`POST /v1/tasks|/v1/tasks/stream|/v1/runs` 的词 = 顶层 `permissionMode` ?? bundle `settings.permissions.defaultMode`)把两步落在**上一版就在的两处**:
14
+ * 入口一步在受理门盖章({@link stampSubmissionEntryMode},`http/admission.ts`:值形门之后、装配之前 —— 首跑装配与 `buildCheckpointCtx` 读的都是盖过章的体);
15
+ * 托管一步是装配期那一处判(`boot/resolve-spec.ts`,对盖过章的词调同一只 ③;提交腿与续跑重放腿同经)。不把整只判官提前到受理门:那会让托管拒抢在
16
+ * 属主 / 会话 / 执行上下文与装配期其余值判之前答(拒序变了 —— 钉同一文件的拒序组)。续跑重放不再过 ②:地板是**入口**事实,热改只影响之后提交的任务。
17
+ *
18
+ * ## 为什么切档口必须经这只判官(而不是靠引擎的 deny 位)
19
+ * 引擎在根腿上只认两只模式拒位(`RuntimeCaps.bypassPermissions` / `RuntimeCaps.autoMode`,本仓由 center 与本地 kill-switch 写);上面三问
20
+ * 都不是引擎位 —— 根腿没有天花板座,托管姿态与任务 settings 都是逐提交的事实。切档口若不经这只判官,提交口在受理时拒过 / 折过的词
21
+ * 就能在 run 跑起来之后原样切进去。
22
+ *
23
+ * ## 答
24
+ * · `refused` —— ③ 拒:状态 422、码 `request.host_posture_refused`、句子是属主的那一句;两口同码同句。
25
+ * · `admitted` —— `requested`(调用方说的词,缺席 = 没说)、`admitted`(交给引擎的词)、`entry`(② 那一次求值的读数,盖章与地板通告只读它)、
26
+ * `foldedBy`(本判官把词改了的那一站;没改 ⇒ 缺席。① ② 都改了 ⇒ `entry_floor`:落定的词是地板给的)。
27
+ */
28
+ import type { PermissionMode } from "@sema-agent/core";
29
+ import { type Autonomy, type EntryPermissionMode } from "./runtime-governance.js";
30
+ import { HOST_POSTURE_REFUSED_CODE, type TaskWriteFaceInput } from "./hosted-posture.js";
31
+ import { type ParsedTaskSettings } from "./task-settings.js";
32
+ /** 本判官改词的站(闭集;wire 上切档回执的 `admission.foldedBy`)。引擎自己的折因词(`operator_deny` / `face_absent` / `inherited_ceiling`)在引擎回执里,不进这张表。 */
33
+ export declare const PERMISSION_MODE_ADMISSION_FOLDS: readonly ["entry_floor", "disable_auto_mode"];
34
+ export type PermissionModeAdmissionFold = (typeof PERMISSION_MODE_ADMISSION_FOLDS)[number];
35
+ /** 判官读的事实:部署(活 config:`AUTONOMY` 地板 + 托管射程与天花板旋钮)与本任务的 settings(提交口 = 提交体的,切档口 = 存储体的)。 */
36
+ export interface PermissionModeAdmissionFacts {
37
+ readonly deployment: TaskWriteFaceInput & {
38
+ readonly autonomy?: Autonomy | undefined;
39
+ };
40
+ readonly settings: ParsedTaskSettings | undefined;
41
+ }
42
+ export type PermissionModeAdmission = {
43
+ readonly kind: "refused";
44
+ readonly status: 422;
45
+ readonly code: typeof HOST_POSTURE_REFUSED_CODE;
46
+ readonly message: string;
47
+ } | {
48
+ readonly kind: "admitted";
49
+ readonly requested: PermissionMode | undefined;
50
+ readonly admitted: PermissionMode | undefined;
51
+ readonly entry: EntryPermissionMode;
52
+ readonly foldedBy?: PermissionModeAdmissionFold;
53
+ };
54
+ /** 整只判官(入口一步 → 托管一步)—— 在飞 run 的切档口调它。 */
55
+ export declare function admitPermissionModeWord(word: PermissionMode | undefined, facts: PermissionModeAdmissionFacts): PermissionModeAdmission;
56
+ /**
57
+ * 提交口的入口一步(`http/admission.ts` 唯一调用;直调装配腿的测试夹具也调它 —— 少了这一步的体是部署上到不了的体):
58
+ * 体上的词(顶层 `permissionMode` ?? bundle `settings.permissions.defaultMode`)过 {@link entryStep},本任务的 settings = 体上那一份;
59
+ * 入口词盖进体(`task-settings.ts` `stampEntryPermissionMode`:地板在场时写顶层 `permissionMode`,缺席原物)。不拒 —— 托管一步在装配期判(见顶注「两口的调用形」)。
60
+ */
61
+ export declare function stampSubmissionEntryMode<B extends {
62
+ permissionMode?: unknown;
63
+ settings?: unknown;
64
+ }>(body: B, deployment: PermissionModeAdmissionFacts["deployment"]): {
65
+ readonly body: B;
66
+ readonly entry: EntryPermissionMode;
67
+ };
68
+ //# sourceMappingURL=permission-mode-admission.d.ts.map
@@ -0,0 +1,23 @@
1
+ import { autonomyModeFloor, entryPermissionMode } from "./runtime-governance.js";
2
+ import { HOST_POSTURE_REFUSED_CODE, permissionModeWriteFaceRefusal } from "./hosted-posture.js";
3
+ import { foldDisableAutoMode, parseTaskSettings, requestedPermissionMode, stampEntryPermissionMode } from "./task-settings.js";
4
+ export const PERMISSION_MODE_ADMISSION_FOLDS = ["entry_floor", "disable_auto_mode"];
5
+ function entryStep(word, facts) {
6
+ const folded = foldDisableAutoMode(word, facts.settings);
7
+ const entry = entryPermissionMode(folded, autonomyModeFloor(facts.deployment.autonomy));
8
+ const foldedBy = entry.clamped ? "entry_floor" : folded !== word ? "disable_auto_mode" : undefined;
9
+ return { entry, ...(foldedBy !== undefined ? { foldedBy } : {}) };
10
+ }
11
+ export function admitPermissionModeWord(word, facts) {
12
+ const { entry, foldedBy } = entryStep(word, facts);
13
+ const why = permissionModeWriteFaceRefusal(entry.effective, facts.deployment);
14
+ if (why !== undefined)
15
+ return { kind: "refused", status: 422, code: HOST_POSTURE_REFUSED_CODE, message: why };
16
+ return { kind: "admitted", requested: word, admitted: entry.effective, entry, ...(foldedBy !== undefined ? { foldedBy } : {}) };
17
+ }
18
+ export function stampSubmissionEntryMode(body, deployment) {
19
+ const settings = parseTaskSettings(body.settings).settings;
20
+ const { entry } = entryStep(requestedPermissionMode(body, settings), { deployment, settings });
21
+ return { body: stampEntryPermissionMode(body, entry), entry };
22
+ }
23
+ //# sourceMappingURL=permission-mode-admission.js.map
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * **规则表的唯一编译口** —— 一张工具名规则表(`ask` / `deny` 之一)编成一只 `ToolPolicy`。读者:请求腿的 `settings.permissions.{ask,deny}`
3
- * 两桶(`task-settings.ts` 的 `deriveSettingsPolicy`)。
3
+ * 两桶(`task-settings.ts` 的 `deriveSettingsPolicy`,每桶按根至多编两集,见文件尾 {@link ruleRootOf})。设置层条目的形与层 → 根表也住这里(文件尾一节)。
4
4
  *
5
5
  * 🔴 core 7.42.0 起策略只说 deny / ask:allow 规则有且只有引擎 allow 层的两个席位 —— 请求的 `settings.permissions.allow` 整份投
6
6
  * `TaskSpec.allowedTools`(`task-settings.ts` 的 `applyTaskSettings`),运维的 `APPROVAL_GRANT` 投 `RunnerDeps.allowedTools`
@@ -9,6 +9,7 @@
9
9
  * 为什么住在一只叶模块里(不留在 `task-settings.ts`):本模块只 import core 与契约包 settings-schema(纯叶),读者引它不成环。
10
10
  */
11
11
  import { type PathRuleBases, type PermissionRule, type PermissionRulePolicyOptions, type ToolPolicy } from "@sema-agent/core";
12
+ import { type SettingsSource } from "@sema-agent/settings-schema";
12
13
  /** 一张表里规则条数的上限 —— 请求腿 wire 门(`task-settings.ts` 的 deny / ask 两桶判形)读的也是这一个名字:core 的缺省帽是 256,
13
14
  * 不对齐的话第 257 条起编译当场抛,等于服务端自己收下的东西自己反悔。 */
14
15
  export declare const MAX_PERMISSION_RULES_PER_LIST = 1000;
@@ -21,13 +22,13 @@ export declare const MAX_PERMISSION_RULES_PER_LIST = 1000;
21
22
  * 交一只名册解析器会多出一种读法:目录没有的名字成 `unsupported.tool_unknown` —— 本仓自铸的工具(`repo_read_file(path:…)`)上一条编得出、真判的规则会在受理口被拒。
22
23
  */
23
24
  export declare function buildRuleListJudgeOptions(pathBases: PathRuleBases | undefined): Pick<PermissionRulePolicyOptions, "caps" | "pathBases">;
24
- /** A name-keyed rule-list ToolPolicy: a tool named by `names` gets `behavior` (`ask` tightens to an approval gate;
25
+ /** A name-keyed rule-list ToolPolicy: a tool named by `rules` gets `behavior` (`ask` tightens to an approval gate;
25
26
  * `deny` hard-blocks); every other tool is out of scope (`defaultAction: "allow"` = this policy has no opinion about
26
27
  * anything it does not name — core 7.42.0: it states nothing and clears nothing). Composed deny-wins with the rest of
27
28
  * the fold, so both only ever tighten.
28
29
  *
29
- * `source` = 这张表**写在哪**(请求腿 `settings.permissions.<桶>`)。它盖进每条规则(core 的 deny / ask
30
- * 句里点名它:`flagged by permission rule "mcp__figma__*" (settings.permissions.ask)`),编不出来时的错误句也点名它;只是出处,
30
+ * `source` = 这条规则**写在哪**(请求腿 `settings.permissions.<桶>`,带层条目再加层:`settings.permissions.ask, layer userSettings`)。它盖进每条规则(core 的 deny / ask
31
+ * 句里点名它:`flagged by permission rule "mcp__figma__*" (settings.permissions.ask)`),编不出来时的错误句点名桶;只是出处,
31
32
  * 不带任何优先级(层序在各自的折叠里)。
32
33
  *
33
34
  * 🔴 [ref] / core [ref] —— 本函数曾是 `new Set(askNames).has(req.toolName)` 的**逐字**比对,那是
@@ -74,6 +75,54 @@ export declare function buildRuleListJudgeOptions(pathBases: PathRuleBases | und
74
75
  * 排除在外),dist 亲读在案。审计归因改由 `matchedAskRule` + `source` 承担,后者比前者强:它还让 core 的 auto-mode 分类器
75
76
  * **拒绝**替人清掉这条 ask(「运维写下的『每次问我』不是分类器的犹豫」),方向是收紧。
76
77
  */
77
- /** `behavior` = 这张表的态度 —— 型直接是 core 的 `PermissionRule["behavior"]`(不手抄:core 加 / 减一种态度,这里与它同步、读者 tsc 上见到)。 */
78
- export declare function createRuleListPolicy(names: readonly string[], behavior: PermissionRule["behavior"], source: string, pathBases: PathRuleBases | undefined): ToolPolicy;
78
+ /** `behavior` = 这张表的态度 —— 型直接是 core 的 `PermissionRule["behavior"]`(不手抄:core 加 / 减一种态度,这里与它同步、读者 tsc 上见到)。
79
+ * `rules` = 这一集的规则,**每条自带出处**({@link SourcedRule}:请求自己写的纯串 = 桶坐标;带层条目 = 桶坐标 + 层,{@link ruleSourceOf});
80
+ * `table` = 这一集出自哪只桶(只进编不出时的兜底句;逐条坐标由先跑的受理判 `rulePolicyBucketsRefusal` 给)。 */
81
+ export declare function createRuleListPolicy(rules: readonly SourcedRule[], behavior: PermissionRule["behavior"], table: string, pathBases: PathRuleBases | undefined): ToolPolicy;
82
+ /**
83
+ * deny / ask 桶的一个条目:**纯串** = 请求自己写的规则(今天的形,读在任务根);**带层条目** `{ rule, layer }` = 端从某个设置层读来的规则,`layer` 是
84
+ * 契约包 `SETTINGS_SOURCES` 的来源词(= 参照实现的设置来源词)。层只决定这条规则的 `/` 读在哪个根({@link layerRuleRoot}),**不决定准入档**
85
+ * (准入只由凭据推,`http/caller-trust.ts`):调用方自报任何层,挪动的只是它自己那条收紧读在哪,与它自己写 `//abs` 等价。
86
+ *
87
+ * 为什么是「条目带层」而不是一只新键:本版之前的每一个读者(回滚、滚动发布中的旧副本)对一只没见过的键是**静默忽略**(续跑重放走宽容层),
88
+ * 带层的收紧会整批消失;对一个不是串的条目则在桶门上 `bad_entry` —— 新提交 400、续跑 409,响亮拒。条数帽也因此仍是「一桶一张表」。
89
+ */
90
+ export type RuleListEntry = string | LayeredRule;
91
+ /** 带层条目(恰两键;受理判 {@link ruleListEntryOk})。 */
92
+ export interface LayeredRule {
93
+ readonly rule: string;
94
+ readonly layer: SettingsSource;
95
+ }
96
+ /** 一条进编译口的规则与它的出处串(core 规则行逐条带 `source`,问 / 拒句点名它)。 */
97
+ export interface SourcedRule {
98
+ readonly rule: string;
99
+ readonly source: string;
100
+ }
101
+ /** 一个条目合不合 deny / ask 桶的条目律:非空串;或恰 `rule`(非空串)+ `layer`(`SETTINGS_SOURCES` 里的词)两键的纯对象。别的形一律不合(多键、空串、未知层、数组、原型对象)。 */
102
+ export declare function ruleListEntryOk(x: unknown): x is RuleListEntry;
103
+ /** 条目的规则原文(纯串即它自己)。 */
104
+ export declare function ruleTextOf(entry: RuleListEntry): string;
105
+ /** 条目进编译口的出处串:纯串 = 桶坐标(今天的字面);带层 = 桶坐标 + 层(`settings.permissions.deny, layer userSettings`)。 */
106
+ export declare function ruleSourceOf(table: string, entry: RuleListEntry): string;
107
+ /** 规则的 `/` 读在哪个根(闭集,也是一桶里各集的编译序与判序):`task` = 任务根;`configuration` = 执行环境的配置根(`execution-config-root.ts`)。 */
108
+ export declare const RULE_ROOTS: readonly ["task", "configuration"];
109
+ export type RuleRoot = (typeof RULE_ROOTS)[number];
110
+ /**
111
+ * 一个设置层的 `/` 读在哪个根 —— 参照实现(CC 2.1.309)的表照录(`cli309.js:258818` `zBt` → `:252700` `D8o` / `swn`:user 层 ⇒ 配置目录 `Le()`〔`:251921`〕;
112
+ * project / local / policy ⇒ 工作目录;flag ⇒ flag 文件的目录,内联 ⇒ 工作目录)。本服务的两处取舍:`flagSettings` 读任务根(flag 文件的目录是端那台机的事实,本服务手里没有;
113
+ * 要固定位置写 `//abs`);`foreignProjectSettings`(仓库里写给别的工具的项目文件)与项目层同根。契约包加一个来源词 ⇒ 这里编译红。
114
+ */
115
+ export declare function layerRuleRoot(layer: SettingsSource): RuleRoot;
116
+ /**
117
+ * 一个条目编进哪一集:**只有 `/` 随层变** —— 带层条目的层根是配置根 ∧ 这条规则要 `root`(core 的必需基分类 `ruleBasesNeeded`)⇒ `configuration`;
118
+ * 其余一律 `task`(纯串、别的层、`~/` / 相对形、`//abs` 与 subpath 这类分类为空的规则 —— 后者在 Windows 族上仍随声明的根选盘,必须留在今天那一集)。
119
+ * 文法读不出的串 ⇒ `task`(受理判在前面就拒它,这里不另说一句)。
120
+ *
121
+ * 为什么按根分集、不按层分集:共根各层给出逐字相同的锚,合一集判决不变;而一只声明了 `root` 却没声明 `cwd` 的集把相对形读在声明的根上(core
122
+ * `policyAnchors`)—— 「一层一集」在任务根读不出的腿(未登记工作目录的 host 腿、每一条沙箱腿)上会把 user 层的相对规则读到配置根下。配置根那一集只装要
123
+ * `root` 的规则,`cwd` 永远不被问。
124
+ */
125
+ export declare function ruleRootOf(entry: RuleListEntry, behavior: PermissionRule["behavior"]): RuleRoot;
126
+ /** 一桶的条目按根分集(受理判与编译读同一只:判的就是要编的那一集);集内保持原序。 */
127
+ export declare function ruleSetsOf(entries: readonly RuleListEntry[], behavior: PermissionRule["behavior"]): Readonly<Record<RuleRoot, readonly RuleListEntry[]>>;
79
128
  //# sourceMappingURL=permission-rule-list.d.ts.map
@@ -1,5 +1,5 @@
1
- import { createPermissionRulePolicy } from "@sema-agent/core";
2
- import { stripControlAndBidi } from "@sema-agent/settings-schema";
1
+ import { createPermissionRulePolicy, parseRuleText, ruleBasesNeeded } from "@sema-agent/core";
2
+ import { SETTINGS_SOURCES, stripControlAndBidi } from "@sema-agent/settings-schema";
3
3
  export const MAX_PERMISSION_RULES_PER_LIST = 1_000;
4
4
  export function buildRuleListJudgeOptions(pathBases) {
5
5
  return {
@@ -7,13 +7,60 @@ export function buildRuleListJudgeOptions(pathBases) {
7
7
  ...(pathBases !== undefined ? { pathBases } : {}),
8
8
  };
9
9
  }
10
- export function createRuleListPolicy(names, behavior, source, pathBases) {
10
+ export function createRuleListPolicy(rules, behavior, table, pathBases) {
11
11
  try {
12
- return createPermissionRulePolicy(names.map((name) => ({ rule: name, behavior, source })), { defaultAction: "allow", ...buildRuleListJudgeOptions(pathBases) });
12
+ return createPermissionRulePolicy(rules.map(({ rule, source }) => ({ rule, behavior, source })), { defaultAction: "allow", ...buildRuleListJudgeOptions(pathBases) });
13
13
  }
14
14
  catch (e) {
15
15
  const coreMsg = stripControlAndBidi(e instanceof Error ? e.message : String(e));
16
- throw new Error(`${source.replace("settings.", "")} has rule(s) core cannot compile — ${coreMsg}`, { cause: e });
16
+ throw new Error(`${table.replace("settings.", "")} has rule(s) core cannot compile — ${coreMsg}`, { cause: e });
17
17
  }
18
18
  }
19
+ const SETTINGS_SOURCE_SET = new Set(SETTINGS_SOURCES);
20
+ export function ruleListEntryOk(x) {
21
+ if (typeof x === "string")
22
+ return x.length > 0;
23
+ if (x === null || typeof x !== "object" || Array.isArray(x) || Object.getPrototypeOf(x) !== Object.prototype)
24
+ return false;
25
+ const keys = Object.keys(x);
26
+ if (keys.length !== 2 || !Object.hasOwn(x, "rule") || !Object.hasOwn(x, "layer"))
27
+ return false;
28
+ const { rule, layer } = x;
29
+ return typeof rule === "string" && rule.length > 0 && typeof layer === "string" && SETTINGS_SOURCE_SET.has(layer);
30
+ }
31
+ export function ruleTextOf(entry) {
32
+ return typeof entry === "string" ? entry : entry.rule;
33
+ }
34
+ export function ruleSourceOf(table, entry) {
35
+ return typeof entry === "string" ? table : `${table}, layer ${entry.layer}`;
36
+ }
37
+ export const RULE_ROOTS = ["task", "configuration"];
38
+ export function layerRuleRoot(layer) {
39
+ switch (layer) {
40
+ case "userSettings":
41
+ return "configuration";
42
+ case "projectSettings":
43
+ case "localSettings":
44
+ case "flagSettings":
45
+ case "policySettings":
46
+ case "foreignProjectSettings":
47
+ return "task";
48
+ default: {
49
+ const unhandled = layer;
50
+ return unhandled;
51
+ }
52
+ }
53
+ }
54
+ export function ruleRootOf(entry, behavior) {
55
+ if (typeof entry === "string" || layerRuleRoot(entry.layer) === "task")
56
+ return "task";
57
+ const parsed = parseRuleText(entry.rule, behavior);
58
+ return "rule" in parsed && ruleBasesNeeded(parsed.rule).includes("root") ? "configuration" : "task";
59
+ }
60
+ export function ruleSetsOf(entries, behavior) {
61
+ const sets = { task: [], configuration: [] };
62
+ for (const entry of entries)
63
+ sets[ruleRootOf(entry, behavior)].push(entry);
64
+ return sets;
65
+ }
19
66
  //# sourceMappingURL=permission-rule-list.js.map
@@ -86,8 +86,8 @@ export class SqlAdoptionLogStore {
86
86
  constructor(db) {
87
87
  this.db = db;
88
88
  }
89
- q(tidb, pg) {
90
- return this.db.dialect === "tidb" ? tidb : pg;
89
+ q(mysql, pg) {
90
+ return this.db.dialect === "mysql" ? mysql : pg;
91
91
  }
92
92
  get reader() {
93
93
  return this.db;
@@ -191,7 +191,7 @@ export class SqlAdoptionLogStore {
191
191
  try {
192
192
  lockName = qualifyAdoptionLockName(await this.resolveLockKeyspace(conn), name);
193
193
  for (let i = 0; i < attempts && !held; i += 1) {
194
- const res = await conn.query(this.q("SELECT GET_LOCK(?, 0) AS got", "SELECT pg_try_advisory_lock($1, $2) AS got"), this.db.dialect === "tidb" ? [lockName] : [PG_ADOPTION_LOCK_CLASS, pgLockObjectKey(lockName)]);
194
+ const res = await conn.query(this.q("SELECT GET_LOCK(?, 0) AS got", "SELECT pg_try_advisory_lock($1, $2) AS got"), this.db.dialect === "mysql" ? [lockName] : [PG_ADOPTION_LOCK_CLASS, pgLockObjectKey(lockName)]);
195
195
  const got = res.rows[0]?.got;
196
196
  held = got === 1 || got === true || got === "1";
197
197
  if (!held)
@@ -204,7 +204,7 @@ export class SqlAdoptionLogStore {
204
204
  finally {
205
205
  if (held) {
206
206
  try {
207
- await conn.query(this.q("SELECT RELEASE_LOCK(?) AS released", "SELECT pg_advisory_unlock($1, $2) AS released"), this.db.dialect === "tidb" ? [lockName] : [PG_ADOPTION_LOCK_CLASS, pgLockObjectKey(lockName)]);
207
+ await conn.query(this.q("SELECT RELEASE_LOCK(?) AS released", "SELECT pg_advisory_unlock($1, $2) AS released"), this.db.dialect === "mysql" ? [lockName] : [PG_ADOPTION_LOCK_CLASS, pgLockObjectKey(lockName)]);
208
208
  }
209
209
  catch (releaseErr) {
210
210
  console.warn("[adoption-log] releasing the adoption arc lock failed (it auto-frees when the connection closes):", releaseErr);
@@ -386,7 +386,7 @@ function patchColumns(patch, json) {
386
386
  return out;
387
387
  }
388
388
  function ph(dialect, n) {
389
- return dialect === "tidb" ? "?" : `$${n}`;
389
+ return dialect === "mysql" ? "?" : `$${n}`;
390
390
  }
391
391
  function pendingClaimWhere(dialect, firstParam) {
392
392
  return `ask_id = ${ph(dialect, firstParam)} AND batch_id = ${ph(dialect, firstParam + 1)} AND state = 'STREAM_PENDING'`;
@@ -394,15 +394,15 @@ function pendingClaimWhere(dialect, firstParam) {
394
394
  function decideOwnerWhere(dialect, owner, param) {
395
395
  if (owner === null)
396
396
  return { sql: "owner IS NULL", params: [] };
397
- return dialect === "tidb" ? { sql: "CAST(owner AS BINARY) = CAST(? AS BINARY)", params: [owner] } : { sql: `owner = ${ph(dialect, param)}`, params: [owner] };
397
+ return dialect === "mysql" ? { sql: "CAST(owner AS BINARY) = CAST(? AS BINARY)", params: [owner] } : { sql: `owner = ${ph(dialect, param)}`, params: [owner] };
398
398
  }
399
399
  export class SqlApprovalAskStore {
400
400
  db;
401
401
  constructor(db) {
402
402
  this.db = db;
403
403
  }
404
- q(tidb, pg) {
405
- return this.db.dialect === "tidb" ? tidb : pg;
404
+ q(mysql, pg) {
405
+ return this.db.dialect === "mysql" ? mysql : pg;
406
406
  }
407
407
  json(value) {
408
408
  return dialectJsonEncoder(this.db.dialect)(value);
@@ -411,7 +411,7 @@ export class SqlApprovalAskStore {
411
411
  return isDupKeyError(this.db.dialect, e);
412
412
  }
413
413
  async getAskOn(conn, askId) {
414
- const { rows } = await conn.query(this.q(`SELECT ${askCols("tidb")} FROM ${APPROVAL_ASK_TABLE} WHERE ask_id = ?`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE ask_id = $1`), [askId]);
414
+ const { rows } = await conn.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE ask_id = ?`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE ask_id = $1`), [askId]);
415
415
  return rows[0] ? mapAskRow(rows[0]) : null;
416
416
  }
417
417
  async getBatchOn(conn, batchId) {
@@ -704,40 +704,40 @@ export class SqlApprovalAskStore {
704
704
  }
705
705
  }
706
706
  async listByState(state, limit) {
707
- const { rows } = await this.db.query(this.q(`SELECT ${askCols("tidb")} FROM ${APPROVAL_ASK_TABLE} WHERE state = ? ORDER BY updated_at_ms ASC, created_at_ms ASC LIMIT ?`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE state = $1 ORDER BY updated_at_ms ASC, created_at_ms ASC LIMIT $2`), [state, limit]);
707
+ const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE state = ? ORDER BY updated_at_ms ASC, created_at_ms ASC LIMIT ?`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE state = $1 ORDER BY updated_at_ms ASC, created_at_ms ASC LIMIT $2`), [state, limit]);
708
708
  return rows.map(mapAskRow);
709
709
  }
710
710
  async listPendingByTask(taskId, signal) {
711
711
  if (signal?.aborted === true)
712
712
  throw abortedReadError("listPendingByTask");
713
- const { rows } = await withReadSignal(this.db.query(this.q(`SELECT ${askCols("tidb")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = ? AND state = 'STREAM_PENDING' ORDER BY created_at_ms ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = $1 AND state = 'STREAM_PENDING' ORDER BY created_at_ms ASC`), [taskId]), signal, "listPendingByTask");
713
+ const { rows } = await withReadSignal(this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = ? AND state = 'STREAM_PENDING' ORDER BY created_at_ms ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = $1 AND state = 'STREAM_PENDING' ORDER BY created_at_ms ASC`), [taskId]), signal, "listPendingByTask");
714
714
  return rows.map(mapAskRow);
715
715
  }
716
716
  async listPendingBySession(sessionId, owner, signal) {
717
717
  if (signal?.aborted === true)
718
718
  throw abortedReadError("listPendingBySession");
719
719
  const { rows } = await withReadSignal(this.db.query(owner === null
720
- ? this.q(`SELECT ${askCols("tidb")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = ? AND state = 'STREAM_PENDING' AND owner IS NULL ORDER BY created_at_ms ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = $1 AND state = 'STREAM_PENDING' AND owner IS NULL ORDER BY created_at_ms ASC`)
721
- : this.q(`SELECT ${askCols("tidb")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = ? AND state = 'STREAM_PENDING' AND owner = ? ORDER BY created_at_ms ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = $1 AND state = 'STREAM_PENDING' AND owner = $2 ORDER BY created_at_ms ASC`), owner === null ? [sessionId] : [sessionId, owner]), signal, "listPendingBySession");
720
+ ? this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = ? AND state = 'STREAM_PENDING' AND owner IS NULL ORDER BY created_at_ms ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = $1 AND state = 'STREAM_PENDING' AND owner IS NULL ORDER BY created_at_ms ASC`)
721
+ : this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = ? AND state = 'STREAM_PENDING' AND owner = ? ORDER BY created_at_ms ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = $1 AND state = 'STREAM_PENDING' AND owner = $2 ORDER BY created_at_ms ASC`), owner === null ? [sessionId] : [sessionId, owner]), signal, "listPendingBySession");
722
722
  return rows.map(mapAskRow);
723
723
  }
724
724
  async listByCall(call) {
725
- const { rows } = await this.db.query(this.q(`SELECT ${askCols("tidb")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = ? AND leg_key = ? AND tool_call_id = ? AND source_task_id = ? ORDER BY created_at_ms ASC, ask_id ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = $1 AND leg_key = $2 AND tool_call_id = $3 AND source_task_id = $4 ORDER BY created_at_ms ASC, ask_id ASC`), [call.taskId, call.legKey, call.toolCallId, call.sourceTaskId]);
725
+ const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = ? AND leg_key = ? AND tool_call_id = ? AND source_task_id = ? ORDER BY created_at_ms ASC, ask_id ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = $1 AND leg_key = $2 AND tool_call_id = $3 AND source_task_id = $4 ORDER BY created_at_ms ASC, ask_id ASC`), [call.taskId, call.legKey, call.toolCallId, call.sourceTaskId]);
726
726
  return rows.map(mapAskRow).filter((r) => askRowOnCall(r, call));
727
727
  }
728
728
  async listParkingBySession(sessionId) {
729
- const { rows } = await this.db.query(this.q(`SELECT ${askCols("tidb")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = ? AND state = 'PARKING' ORDER BY created_at_ms ASC, ask_id ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = $1 AND state = 'PARKING' ORDER BY created_at_ms ASC, ask_id ASC`), [sessionId]);
729
+ const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = ? AND state = 'PARKING' ORDER BY created_at_ms ASC, ask_id ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE session_id = $1 AND state = 'PARKING' ORDER BY created_at_ms ASC, ask_id ASC`), [sessionId]);
730
730
  return rows.map(mapAskRow).filter((r) => r.sessionId === sessionId);
731
731
  }
732
732
  async getAsk(askId) {
733
- const { rows } = await this.db.query(this.q(`SELECT ${askCols("tidb")} FROM ${APPROVAL_ASK_TABLE} WHERE ask_id = ?`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE ask_id = $1`), [
733
+ const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE ask_id = ?`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE ask_id = $1`), [
734
734
  askId,
735
735
  ]);
736
736
  return rows[0] ? mapAskRow(rows[0]) : null;
737
737
  }
738
738
  async getByIdempotencyKey(taskId, key) {
739
739
  assertIdempotencyKeyShape(key);
740
- const { rows } = await this.db.query(this.q(`SELECT ${askCols("tidb")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = ? AND idempotency_key = ?`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = $1 AND idempotency_key = $2`), [taskId, key]);
740
+ const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = ? AND idempotency_key = ?`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE task_id = $1 AND idempotency_key = $2`), [taskId, key]);
741
741
  return rows[0] ? mapAskRow(rows[0]) : null;
742
742
  }
743
743
  async deferReconcile(askId, expectedState, expectedRev, nowMs) {
@@ -772,7 +772,7 @@ export class SqlApprovalAskStore {
772
772
  const ANCHOR_COLUMNS = ["task_id", "session_id", "source_task_id"];
773
773
  let keepSql = "";
774
774
  let keepParams = [];
775
- if (keep.length > 0 && dialect === "tidb") {
775
+ if (keep.length > 0 && dialect === "mysql") {
776
776
  const list = keep.map(() => "?").join(", ");
777
777
  keepSql = ANCHOR_COLUMNS.map((c) => ` AND ${c} NOT IN (${list})`).join("");
778
778
  keepParams = ANCHOR_COLUMNS.flatMap(() => keep);
@@ -10,15 +10,15 @@ export class SqlApprovalNonceStore {
10
10
  constructor(db) {
11
11
  this.db = db;
12
12
  }
13
- q(tidb, pg) {
14
- return this.db.dialect === "tidb" ? tidb : pg;
13
+ q(mysql, pg) {
14
+ return this.db.dialect === "mysql" ? mysql : pg;
15
15
  }
16
16
  async nowMs() {
17
17
  return sqlDbNowMs(this.db, APPROVAL_NONCE_TABLE);
18
18
  }
19
19
  async consume(sessionId, nonce, expiresAtMs) {
20
20
  try {
21
- await this.db.query(this.q(`INSERT INTO ${APPROVAL_NONCE_TABLE} (session_id, nonce, consumed_at_ms, expires_at_ms) VALUES (?,?,${SQL_DB_NOW_MS.tidb},?)`, `INSERT INTO ${APPROVAL_NONCE_TABLE} (session_id, nonce, consumed_at_ms, expires_at_ms) VALUES ($1,$2,${SQL_DB_NOW_MS.pg},$3)`), [sessionId, nonce, expiresAtMs]);
21
+ await this.db.query(this.q(`INSERT INTO ${APPROVAL_NONCE_TABLE} (session_id, nonce, consumed_at_ms, expires_at_ms) VALUES (?,?,${SQL_DB_NOW_MS.mysql},?)`, `INSERT INTO ${APPROVAL_NONCE_TABLE} (session_id, nonce, consumed_at_ms, expires_at_ms) VALUES ($1,$2,${SQL_DB_NOW_MS.pg},$3)`), [sessionId, nonce, expiresAtMs]);
22
22
  return true;
23
23
  }
24
24
  catch (err) {
@@ -28,7 +28,7 @@ export class SqlApprovalNonceStore {
28
28
  }
29
29
  }
30
30
  async reapExpired() {
31
- const res = await this.db.query(this.q(`DELETE FROM ${APPROVAL_NONCE_TABLE} WHERE expires_at_ms <= ${SQL_DB_NOW_MS.tidb}`, `DELETE FROM ${APPROVAL_NONCE_TABLE} WHERE expires_at_ms <= ${SQL_DB_NOW_MS.pg}`), []);
31
+ const res = await this.db.query(this.q(`DELETE FROM ${APPROVAL_NONCE_TABLE} WHERE expires_at_ms <= ${SQL_DB_NOW_MS.mysql}`, `DELETE FROM ${APPROVAL_NONCE_TABLE} WHERE expires_at_ms <= ${SQL_DB_NOW_MS.pg}`), []);
32
32
  return res.affected;
33
33
  }
34
34
  }
@@ -1,6 +1,6 @@
1
1
  import type { Pool as MysqlPool } from "mysql2/promise";
2
2
  import type { Pool as PgPool } from "pg";
3
- import { type SqlEngineFacts, type SqlEngineReading, type SqlWallSource, type SqlWallsReading } from "./sql-driver.js";
3
+ import { type SqlEngineFacts, type SqlEngineReading, type SqlWallSource, type SqlWallsReading, type SqlDialect } from "./sql-driver.js";
4
4
  import { type Logger } from "../observability/logger.js";
5
5
  /**
6
6
  * 文本协议的 blob 膨胀律 —— mysql2 `query()` 把 Buffer 参数写成 `X'<hex>'`,一字节两个字符,所以承载一个 blob 的语句至少是它的 2 倍。
@@ -115,7 +115,7 @@ export declare class SqlBlobBackend implements BlobBackend {
115
115
  private readonly db;
116
116
  /** Where a stale connection's replacement is logged ({@link connectJudged}); the boot assembly passes the service logger. */
117
117
  private readonly log;
118
- constructor(dialect: "tidb" | "pg", pool: MysqlPool | PgPool, maxBytes?: number, table?: string, log?: Pick<Logger, "warn">);
118
+ constructor(dialect: SqlDialect, pool: MysqlPool | PgPool, maxBytes?: number, table?: string, log?: Pick<Logger, "warn">);
119
119
  /** The created_at-refreshing content-addressed upsert — VERBATIM the tidb/pg stores' `putBlobRow`. Refreshes
120
120
  * created_at even on a dedup hit so a re-used/just-written blob is "touched=now" and GC-grace-protected.
121
121
  * (a): an over-cap blob is REJECTED (typed {@link BlobTooLargeError}) BEFORE the driver ever sees the bytes —
@@ -140,7 +140,7 @@ export declare class SqlBlobBackend implements BlobBackend {
140
140
  /** SHARED index op(workspace 浏览面 #3,[ref]②)—— per-blob 字节数,读 SQL INDEX 的 `byte_len`
141
141
  * 列(sqlHasBlobs 同款单 IN 查询;MinIO 后端的 bytes-NULL 索引行同样带 byte_len,两后端同源)。
142
142
  * tree/file 面的 size 投影与「超限先拒后拉」都靠它——绝不为拿大小去 getBlob 整块字节。 */
143
- export declare function sqlBlobSizes(dialect: "tidb" | "pg", pool: MysqlPool | PgPool, hashes: string[]): Promise<Map<string, number>>;
143
+ export declare function sqlBlobSizes(dialect: SqlDialect, pool: MysqlPool | PgPool, hashes: string[]): Promise<Map<string, number>>;
144
144
  export interface MinioBlobBackendConfig {
145
145
  endpoint: string;
146
146
  bucket: string;
@@ -198,7 +198,7 @@ export declare class MinioBlobBackend implements BlobBackend {
198
198
  /** Blob-domain index table ([ref] 域隔离,SqlBlobBackend.table 同款;默认 = E19 纪元的 snapshot_blob)。 */
199
199
  private readonly indexTable;
200
200
  constructor(cfg: MinioBlobBackendConfig, index?: {
201
- dialect: "tidb" | "pg";
201
+ dialect: SqlDialect;
202
202
  pool: MysqlPool | PgPool;
203
203
  table?: string;
204
204
  });
@@ -76,7 +76,7 @@ export class SqlBlobBackend {
76
76
  this.pool = pool;
77
77
  this.explicitCapBytes = maxBytes;
78
78
  this.table = table;
79
- this.db = dialect === "tidb" ? mysqlDriver(pool) : pgDriver(pool);
79
+ this.db = dialect === "mysql" ? mysqlDriver(pool) : pgDriver(pool);
80
80
  this.log = log ?? createLogger();
81
81
  }
82
82
  async putBlob(hash, bytes) {
@@ -90,7 +90,7 @@ export class SqlBlobBackend {
90
90
  if (judged.refusal !== undefined)
91
91
  throw new BlobTooLargeError(bytes.byteLength, judged.refusal.cap);
92
92
  try {
93
- await judged.conn.query(this.dialect === "tidb"
93
+ await judged.conn.query(this.dialect === "mysql"
94
94
  ? `INSERT INTO ${this.table} (blob_hash, byte_len, bytes, created_at) VALUES (?,?,?,?) ON DUPLICATE KEY UPDATE created_at = VALUES(created_at)`
95
95
  : `INSERT INTO ${this.table} (blob_hash, byte_len, bytes, created_at) VALUES ($1,$2,$3,$4) ON CONFLICT (blob_hash) DO UPDATE SET created_at = EXCLUDED.created_at`, [hash, bytes.byteLength, Buffer.from(bytes), new Date()]);
96
96
  }
@@ -99,7 +99,7 @@ export class SqlBlobBackend {
99
99
  }
100
100
  }
101
101
  async getBlob(hash) {
102
- if (this.dialect === "tidb") {
102
+ if (this.dialect === "mysql") {
103
103
  const [rows] = await this.pool.query(`SELECT bytes FROM ${this.table} WHERE blob_hash = ?`, [hash]);
104
104
  return rows[0]?.bytes != null ? new Uint8Array(rows[0].bytes) : undefined;
105
105
  }
@@ -118,7 +118,7 @@ async function sqlHasBlobs(dialect, pool, hashes, table = "snapshot_blob") {
118
118
  if (hashes.length === 0)
119
119
  return new Set();
120
120
  const distinct = [...new Set(hashes)];
121
- if (dialect === "tidb") {
121
+ if (dialect === "mysql") {
122
122
  const ph = distinct.map(() => "?").join(",");
123
123
  const [rows] = await pool.query(`SELECT blob_hash FROM ${table} WHERE blob_hash IN (${ph})`, distinct);
124
124
  return new Set(rows.map((r) => String(r.blob_hash)));
@@ -135,7 +135,7 @@ export async function sqlBlobSizes(dialect, pool, hashes) {
135
135
  const out = new Map();
136
136
  for (let i = 0; i < distinct.length; i += CHUNK) {
137
137
  const part = distinct.slice(i, i + CHUNK);
138
- if (dialect === "tidb") {
138
+ if (dialect === "mysql") {
139
139
  const ph = part.map(() => "?").join(",");
140
140
  const [rows] = await pool.query(`SELECT blob_hash, byte_len FROM snapshot_blob WHERE blob_hash IN (${ph})`, part);
141
141
  for (const r of rows)
@@ -155,7 +155,7 @@ async function sqlDeleteIndexRowsPastGrace(dialect, pool, hashes, table = "snaps
155
155
  return [];
156
156
  const distinct = [...new Set(hashes)];
157
157
  const cutoff = new Date(Date.now() - BLOB_GC_GRACE_MS);
158
- if (dialect === "tidb") {
158
+ if (dialect === "mysql") {
159
159
  const ph = distinct.map(() => "?").join(",");
160
160
  const grace = await pool
161
161
  .query(`SELECT blob_hash FROM ${table} WHERE created_at < ? AND blob_hash IN (${ph})`, [cutoff, ...distinct])
@@ -216,7 +216,7 @@ export class MinioBlobBackend {
216
216
  throw new Error(`MinioBlobBackend.putBlob ${hash}: HTTP ${res.status} ${detail.slice(0, 200)}`);
217
217
  }
218
218
  if (this.indexPool && this.indexDialect) {
219
- if (this.indexDialect === "tidb") {
219
+ if (this.indexDialect === "mysql") {
220
220
  await this.indexPool.query(`INSERT INTO ${this.indexTable} (blob_hash, byte_len, bytes, created_at) VALUES (?,?,NULL,?) ON DUPLICATE KEY UPDATE created_at = VALUES(created_at)`, [hash, bytes.byteLength, new Date()]);
221
221
  }
222
222
  else {
@@ -24,8 +24,8 @@ export class SqlBreakerState {
24
24
  this.db = db;
25
25
  this.onWriteFail = onWriteFail;
26
26
  }
27
- q(tidb, pg) {
28
- return this.db.dialect === "tidb" ? tidb : pg;
27
+ q(mysql, pg) {
28
+ return this.db.dialect === "mysql" ? mysql : pg;
29
29
  }
30
30
  get(key) {
31
31
  return this.cache.get(key);
@@ -142,6 +142,12 @@ export declare class CachingSessionStore implements SessionStore {
142
142
  * 只读快照而非 getter:声明是店的构造期常量(会变的声明本身就是缺陷)。
143
143
  */
144
144
  readonly placements?: SessionStore["placements"];
145
+ /**
146
+ * 内层店的**会话耐久声明**(core `SessionStore.durability`,说的是未 placed 的会话)转发 —— 与 {@link retention} / {@link placements} 同一族教训:
147
+ * 生产默认把真店包进本类,core 的接线清单(`wiring_manifest.session.store`)与停驻自检读的就是包装层;不转发 = 一只声明了 `durable` 的店在默认部署上
148
+ * 读成 `process_local`(core 对缺席的 fail-closed 读法),没有任何一处报错。只读快照;缺席则不设。
149
+ */
150
+ readonly durability?: SessionStore["durability"];
145
151
  /** [ref]:placed 分区的两只读面(reap 分区腿 / 准入探针)——同款转发理由:reaper 与准入判据拿到的
146
152
  * 是包装层,不转发 = 分区腿静默不可用、暖命中的 claim 关门静默失效。缺席则不设(诚实降级)。 */
147
153
  readonly listPlaced?: (kind: "subagent", opts?: {
@@ -33,6 +33,7 @@ export class CachingSessionStore {
33
33
  replaceEntries;
34
34
  retention;
35
35
  placements;
36
+ durability;
36
37
  listPlaced;
37
38
  placementOf;
38
39
  constructor(inner, opts) {
@@ -43,6 +44,8 @@ export class CachingSessionStore {
43
44
  const declared = inner.retention;
44
45
  if (declared !== undefined)
45
46
  this.retention = declared;
47
+ if (inner.durability !== undefined)
48
+ this.durability = inner.durability;
46
49
  if (inner.placements !== undefined)
47
50
  this.placements = inner.placements;
48
51
  if (typeof inner.listPlaced === "function")
@@ -33,7 +33,7 @@ export function buildCheckpointIndexCells(cp) {
33
33
  };
34
34
  }
35
35
  export const APPROVAL_CARD_COLUMN_MAX_BYTES = {
36
- tidb: 65_535,
36
+ mysql: 65_535,
37
37
  pg: Number.POSITIVE_INFINITY,
38
38
  };
39
39
  export function judgeCheckpointIndexCells(cp, dialect) {
@@ -83,7 +83,7 @@ function renderFacetCase(compared) {
83
83
  return `CASE ${CHECKPOINT_FACET_CASES.map((c) => `WHEN ${compared(c.column)} IN (${c.words.map(literal).join(", ")}) THEN ${literal(c.facet)}`).join(" ")} END`;
84
84
  }
85
85
  export const CHECKPOINT_FACET_SQL = Object.freeze({
86
- tidb: renderFacetCase((column) => `CAST(${column} AS BINARY)`),
86
+ mysql: renderFacetCase((column) => `CAST(${column} AS BINARY)`),
87
87
  pg: renderFacetCase((column) => column),
88
88
  });
89
89
  export const CHECKPOINT_SWEEP_ORDER_SQL = "CASE WHEN approval_card IS NULL THEN 1 ELSE 0 END ASC, deadline ASC, token ASC";