@sema-agent/server 7.146.0 → 7.147.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 (398) hide show
  1. package/MIGRATION.md +384 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +170 -66
  5. package/deploy/facts/lanes.json +7 -0
  6. package/deploy/sema-up/README.md +2 -2
  7. package/deploy/sema-up/chart/templates/_helpers.tpl +22 -0
  8. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -4
  9. package/deploy/sema-up/chart/templates/server.yaml +5 -4
  10. package/deploy/sema-up/chart/values.yaml +1 -1
  11. package/deploy/sema-up/cluster-up.sh +2 -1
  12. package/deploy/sema-up/lib/flagshape.sh +4 -0
  13. package/deploy/sema-up/lib/lanes.json +2 -5
  14. package/deploy/sema-up/sema-up.sh +12 -9
  15. package/deploy/sema-up/stack/compose.yaml +5 -4
  16. package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -3
  17. package/dist/approval-card.d.ts +4 -4
  18. package/dist/approval.d.ts +3 -3
  19. package/dist/audit.js +2 -2
  20. package/dist/bench/s1/live-deps.js +3 -1
  21. package/dist/boot/crash-last.js +2 -1
  22. package/dist/boot/device-lane.js +5 -5
  23. package/dist/boot/engine-lease.d.ts +12 -11
  24. package/dist/boot/execution-env.d.ts +2 -1
  25. package/dist/boot/execution-env.js +45 -33
  26. package/dist/boot/execution-lane.d.ts +37 -9
  27. package/dist/boot/execution-lane.js +74 -20
  28. package/dist/boot/exit-boundary.d.ts +1 -1
  29. package/dist/boot/exit-last.js +2 -1
  30. package/dist/boot/governance-seams.d.ts +2 -2
  31. package/dist/boot/leader.js +1 -1
  32. package/dist/boot/memory-boundary.d.ts +11 -11
  33. package/dist/boot/memory-boundary.js +3 -3
  34. package/dist/boot/memory-consolidation.d.ts +13 -24
  35. package/dist/boot/memory-consolidation.js +0 -13
  36. package/dist/boot/org-memory.js +3 -2
  37. package/dist/boot/parked-revive-gate.d.ts +1 -1
  38. package/dist/boot/parked-revive-gate.js +1 -1
  39. package/dist/boot/reapers.js +1 -1
  40. package/dist/boot/resolve-spec.js +91 -111
  41. package/dist/boot/retention-lane.d.ts +4 -42
  42. package/dist/boot/session-faces.d.ts +1 -0
  43. package/dist/boot/session-faces.js +8 -2
  44. package/dist/boot/stage-01-config.d.ts +1 -1
  45. package/dist/boot/stage-01-config.js +6 -2
  46. package/dist/boot/stage-02-web-admin-pull.d.ts +1 -1
  47. package/dist/boot/stage-02-web-admin-pull.js +10 -8
  48. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  49. package/dist/boot/stage-04-stores.d.ts +1 -1
  50. package/dist/boot/stage-05-execution-env.d.ts +2 -2
  51. package/dist/boot/stage-05-execution-env.js +3 -3
  52. package/dist/boot/stage-06-runners.d.ts +3 -3
  53. package/dist/boot/stage-06-runners.js +1 -3
  54. package/dist/boot/stage-07-capability-layer.d.ts +3 -3
  55. package/dist/boot/stage-07-capability-layer.js +4 -9
  56. package/dist/boot/stage-08-reapers.d.ts +3 -3
  57. package/dist/boot/stage-09-leader.d.ts +4 -3
  58. package/dist/boot/stage-10-http-server.d.ts +4 -3
  59. package/dist/boot/stage-10-http-server.js +2 -1
  60. package/dist/boot/stores.d.ts +9 -0
  61. package/dist/boot/stores.js +18 -7
  62. package/dist/boot/web-admin.js +3 -3
  63. package/dist/capabilities/center-plugins.d.ts +2 -0
  64. package/dist/capabilities/center-plugins.js +6 -2
  65. package/dist/capabilities/composite-members.d.ts +1 -0
  66. package/dist/capabilities/composite-members.js +1 -0
  67. package/dist/capabilities/execution-lane.d.ts +7 -7
  68. package/dist/capabilities/execution-lane.js +2 -2
  69. package/dist/capabilities/hands-lane.d.ts +1 -1
  70. package/dist/capabilities/scenarios.d.ts +32 -18
  71. package/dist/capabilities/scenarios.js +13 -9
  72. package/dist/capabilities/settings-contract.d.ts +29 -0
  73. package/dist/capabilities/settings-contract.js +14 -0
  74. package/dist/capabilities/skills.d.ts +5 -5
  75. package/dist/capability-facts.d.ts +38 -0
  76. package/dist/capability-facts.js +34 -1
  77. package/dist/center-credential-renewer.js +3 -2
  78. package/dist/config-catalog.js +6 -5
  79. package/dist/config-invariants.d.ts +18 -3
  80. package/dist/config-invariants.js +36 -19
  81. package/dist/config-lkg.d.ts +1 -1
  82. package/dist/config-lkg.js +5 -6
  83. package/dist/config-provider.js +2 -0
  84. package/dist/config-types.d.ts +190 -186
  85. package/dist/config.d.ts +68 -5
  86. package/dist/config.js +80 -54
  87. package/dist/degenerate-instrument.js +1 -1
  88. package/dist/deploy-facts.js +3 -2
  89. package/dist/deployment-shape.d.ts +21 -12
  90. package/dist/deployment-shape.js +24 -6
  91. package/dist/env-facts.d.ts +7 -5
  92. package/dist/env-facts.js +10 -6
  93. package/dist/execution-config-root.d.ts +5 -5
  94. package/dist/execution-config-root.js +5 -5
  95. package/dist/execution-env-purpose.d.ts +14 -0
  96. package/dist/execution-env-purpose.js +29 -0
  97. package/dist/execution-lane-caps.d.ts +49 -86
  98. package/dist/execution-lane-caps.js +52 -62
  99. package/dist/execution-placement.d.ts +18 -2
  100. package/dist/execution-placement.js +19 -0
  101. package/dist/file-history-disclosure.d.ts +2 -2
  102. package/dist/fleet/drain-entry.d.ts +17 -10
  103. package/dist/fleet/drain-entry.js +1 -1
  104. package/dist/fleet/serving-lease.js +3 -4
  105. package/dist/history-anchor.d.ts +22 -0
  106. package/dist/history-anchor.js +14 -0
  107. package/dist/hooks/command-spawn.d.ts +1 -4
  108. package/dist/hooks/command-spawn.js +0 -11
  109. package/dist/hooks/hook-runner.d.ts +52 -8
  110. package/dist/hooks/hook-runner.js +160 -36
  111. package/dist/http/approval-sweeps.d.ts +2 -5
  112. package/dist/http/approval-sweeps.js +3 -2
  113. package/dist/http/checkpoint-ctx.d.ts +17 -0
  114. package/dist/http/checkpoint-ctx.js +6 -0
  115. package/dist/http/claim-latency.d.ts +10 -0
  116. package/dist/http/claim-latency.js +12 -0
  117. package/dist/http/dispatch.js +1 -1
  118. package/dist/http/durable-run-leg.js +2 -1
  119. package/dist/http/execution-context.d.ts +3 -1
  120. package/dist/http/execution-context.js +4 -0
  121. package/dist/http/memory-compliance-failure-reply.d.ts +1 -1
  122. package/dist/http/memory-compliance-failure-reply.js +3 -0
  123. package/dist/http/memory-store-refusal-reply.d.ts +3 -3
  124. package/dist/http/memory-store-refusal-reply.js +3 -0
  125. package/dist/http/owner-access.d.ts +11 -0
  126. package/dist/http/owner-access.js +7 -4
  127. package/dist/http/principal-gate.d.ts +3 -14
  128. package/dist/http/principal-gate.js +0 -13
  129. package/dist/http/request-guards.d.ts +1 -1
  130. package/dist/http/resume-legs.d.ts +7 -10
  131. package/dist/http/resume-legs.js +79 -50
  132. package/dist/http/rewind-files-reply.d.ts +34 -0
  133. package/dist/http/rewind-files-reply.js +36 -0
  134. package/dist/http/route-ctx.d.ts +32 -16
  135. package/dist/http/route-table.js +2 -0
  136. package/dist/http/routes/approvals-assistant.js +5 -25
  137. package/dist/http/routes/capabilities.js +8 -2
  138. package/dist/http/routes/devices.js +1 -1
  139. package/dist/http/routes/memory-origin.d.ts +1 -1
  140. package/dist/http/routes/notify-wake.js +2 -1
  141. package/dist/http/routes/projects.d.ts +70 -0
  142. package/dist/http/routes/projects.js +86 -0
  143. package/dist/http/routes/rules.js +30 -2
  144. package/dist/http/routes/runs.js +8 -8
  145. package/dist/http/routes/session-sync.js +27 -10
  146. package/dist/http/routes/sessions.d.ts +7 -1
  147. package/dist/http/routes/sessions.js +104 -2
  148. package/dist/http/routes/tasks.js +9 -3
  149. package/dist/http/server.d.ts +24 -10
  150. package/dist/http/server.js +17 -6
  151. package/dist/http/stored-body-replay.d.ts +5 -3
  152. package/dist/http/stored-body-replay.js +10 -1
  153. package/dist/http/wire-types.d.ts +19 -10
  154. package/dist/index.d.ts +2 -2
  155. package/dist/index.js +1 -1
  156. package/dist/instruction-source-notice.d.ts +1 -1
  157. package/dist/memory-embedder-reembed.d.ts +38 -0
  158. package/dist/memory-embedder-reembed.js +20 -0
  159. package/dist/memory-incident-sink.d.ts +0 -28
  160. package/dist/memory-incident-sink.js +5 -0
  161. package/dist/memory-scope.d.ts +2 -2
  162. package/dist/memory-scope.js +1 -1
  163. package/dist/memory-store-refusal.d.ts +17 -4
  164. package/dist/memory-store-refusal.js +1 -1
  165. package/dist/memory-sync-client.d.ts +2 -0
  166. package/dist/memory-sync-client.js +13 -11
  167. package/dist/memory-sync.js +1 -1
  168. package/dist/model-compat.d.ts +35 -21
  169. package/dist/model-compat.js +49 -21
  170. package/dist/model-entry-refusal.d.ts +11 -1
  171. package/dist/model-entry-refusal.js +7 -0
  172. package/dist/namespaced-rule-name.d.ts +18 -1
  173. package/dist/namespaced-rule-name.js +12 -0
  174. package/dist/observability/fail-open.d.ts +17 -9
  175. package/dist/observability/fail-open.js +17 -9
  176. package/dist/observability/metrics.d.ts +2 -0
  177. package/dist/observability/metrics.js +2 -0
  178. package/dist/observability/secret-env-scrub.d.ts +30 -4
  179. package/dist/observability/secret-env-scrub.js +15 -3
  180. package/dist/orchestration/workflow-agent-session-index.d.ts +7 -12
  181. package/dist/orchestration/workflow-agent-session-index.js +1 -6
  182. package/dist/orchestration/workflow-completion-inbox.d.ts +26 -6
  183. package/dist/orchestration/workflow-completion-inbox.js +63 -45
  184. package/dist/org-memory-admission.d.ts +5 -2
  185. package/dist/org-memory-admission.js +25 -10
  186. package/dist/parked-decide.d.ts +33 -26
  187. package/dist/parked-decide.js +36 -44
  188. package/dist/plugins/approval-ask-store-file.d.ts +10 -2
  189. package/dist/plugins/approval-ask-store-file.js +37 -4
  190. package/dist/plugins/approval-ask-store-memory.d.ts +5 -3
  191. package/dist/plugins/approval-ask-store-memory.js +11 -2
  192. package/dist/plugins/approval-ask-store-sql.d.ts +3 -0
  193. package/dist/plugins/approval-ask-store-sql.js +3 -1
  194. package/dist/plugins/blob-backend.d.ts +38 -195
  195. package/dist/plugins/blob-backend.js +33 -229
  196. package/dist/plugins/caching-session-store.d.ts +9 -4
  197. package/dist/plugins/checkpoint-index-columns.d.ts +1 -1
  198. package/dist/plugins/checkpoint-index-columns.js +3 -2
  199. package/dist/plugins/checkpoint-store-face.d.ts +1 -1
  200. package/dist/plugins/device-store-sql.d.ts +2 -2
  201. package/dist/plugins/device-store-sql.js +5 -10
  202. package/dist/plugins/execution-lane-rename-m40.d.ts +20 -0
  203. package/dist/plugins/execution-lane-rename-m40.js +10 -0
  204. package/dist/plugins/execution-placement-sql.d.ts +63 -88
  205. package/dist/plugins/execution-placement-sql.js +94 -54
  206. package/dist/plugins/file-run-store.d.ts +26 -12
  207. package/dist/plugins/file-run-store.js +63 -63
  208. package/dist/plugins/imported-layer-root-retirement.d.ts +17 -8
  209. package/dist/plugins/imported-layer-root-retirement.js +4 -8
  210. package/dist/plugins/inbox-payload-column.d.ts +14 -0
  211. package/dist/plugins/inbox-payload-column.js +13 -0
  212. package/dist/plugins/local-checkpoint-store.d.ts +5 -0
  213. package/dist/plugins/local-checkpoint-store.js +11 -7
  214. package/dist/plugins/local-data-dir-modes-m39.d.ts +48 -0
  215. package/dist/plugins/local-data-dir-modes-m39.js +182 -0
  216. package/dist/plugins/local-engine-high-water.d.ts +11 -0
  217. package/dist/plugins/local-engine-high-water.js +59 -0
  218. package/dist/plugins/local-session-store.d.ts +91 -25
  219. package/dist/plugins/local-session-store.js +124 -45
  220. package/dist/plugins/local-task-attachment-store.d.ts +2 -0
  221. package/dist/plugins/local-task-attachment-store.js +10 -11
  222. package/dist/plugins/memory-embedder-fingerprint.d.ts +33 -10
  223. package/dist/plugins/memory-embedder-fingerprint.js +52 -12
  224. package/dist/plugins/memory-embedder.d.ts +1 -1
  225. package/dist/plugins/memory-embedder.js +2 -2
  226. package/dist/plugins/memory-engine-pg.d.ts +4 -3
  227. package/dist/plugins/memory-engine-pg.js +4 -4
  228. package/dist/plugins/memory-engine-sql-apply.d.ts +13 -4
  229. package/dist/plugins/memory-engine-sql-apply.js +1 -1
  230. package/dist/plugins/memory-engine-tidb.d.ts +8 -5
  231. package/dist/plugins/memory-engine-tidb.js +7 -8
  232. package/dist/plugins/one-time-migrations.d.ts +145 -35
  233. package/dist/plugins/one-time-migrations.js +272 -120
  234. package/dist/plugins/owner-only-file-mode.d.ts +29 -0
  235. package/dist/plugins/owner-only-file-mode.js +141 -0
  236. package/dist/plugins/permission-rule-store-file.d.ts +8 -8
  237. package/dist/plugins/permission-rule-store-file.js +14 -2
  238. package/dist/plugins/pg-pool.d.ts +2 -1
  239. package/dist/plugins/pg-pool.js +11 -4
  240. package/dist/plugins/release-version.d.ts +20 -0
  241. package/dist/plugins/release-version.js +28 -0
  242. package/dist/plugins/remote-env-adb.d.ts +20 -4
  243. package/dist/plugins/remote-env-adb.js +39 -11
  244. package/dist/plugins/remote-env-e2b.d.ts +12 -3
  245. package/dist/plugins/remote-env-e2b.js +6 -4
  246. package/dist/plugins/remote-env-host.d.ts +9 -1
  247. package/dist/plugins/remote-env-host.js +6 -5
  248. package/dist/plugins/remote-env-k8s.d.ts +5 -2
  249. package/dist/plugins/remote-env-k8s.js +15 -4
  250. package/dist/plugins/remote-env-local-docker.d.ts +4 -1
  251. package/dist/plugins/remote-env-local-docker.js +3 -3
  252. package/dist/plugins/remote-env-ssh.d.ts +8 -2
  253. package/dist/plugins/remote-env-ssh.js +26 -24
  254. package/dist/plugins/remote-shell.d.ts +59 -30
  255. package/dist/plugins/remote-shell.js +175 -62
  256. package/dist/plugins/retention-declaration.d.ts +37 -0
  257. package/dist/plugins/retention-declaration.js +9 -0
  258. package/dist/plugins/retention-deployment.d.ts +126 -0
  259. package/dist/plugins/retention-deployment.js +88 -0
  260. package/dist/plugins/retention-lane-store-sql.d.ts +74 -4
  261. package/dist/plugins/retention-lane-store-sql.js +103 -1
  262. package/dist/plugins/retention-sql.d.ts +29 -0
  263. package/dist/plugins/retention-sql.js +8 -0
  264. package/dist/plugins/schema-consistency.d.ts +0 -6
  265. package/dist/plugins/schema-consistency.js +1 -2
  266. package/dist/plugins/schema-ensure-legs.d.ts +1 -1
  267. package/dist/plugins/schema-ensure-legs.js +11 -1
  268. package/dist/plugins/session-ext-table.d.ts +74 -0
  269. package/dist/plugins/session-ext-table.js +121 -0
  270. package/dist/plugins/session-fork.d.ts +1 -1
  271. package/dist/plugins/session-row-sql.d.ts +8 -7
  272. package/dist/plugins/session-row-sql.js +15 -7
  273. package/dist/plugins/session-store-sql.d.ts +131 -0
  274. package/dist/plugins/session-store-sql.js +298 -0
  275. package/dist/plugins/session-workspace-cell.d.ts +2 -2
  276. package/dist/plugins/session-workspace-cell.js +2 -2
  277. package/dist/plugins/shared-memory-store-sql.d.ts +10 -0
  278. package/dist/plugins/shared-memory-store-sql.js +13 -13
  279. package/dist/plugins/snapshot-bucket-presence.js +1 -1
  280. package/dist/plugins/sql-driver.d.ts +23 -7
  281. package/dist/plugins/sql-driver.js +41 -8
  282. package/dist/plugins/sql-errors.d.ts +5 -2
  283. package/dist/plugins/sql-errors.js +4 -0
  284. package/dist/plugins/store-backend.d.ts +35 -8
  285. package/dist/plugins/store-backend.js +184 -62
  286. package/dist/plugins/store-contracts.d.ts +9 -2
  287. package/dist/plugins/store-contracts.js +1 -0
  288. package/dist/plugins/task-attachment-store.d.ts +6 -8
  289. package/dist/plugins/task-attachment-store.js +15 -10
  290. package/dist/plugins/task-list-store-sql.d.ts +1 -1
  291. package/dist/plugins/text-column-capacity.d.ts +21 -0
  292. package/dist/plugins/text-column-capacity.js +5 -0
  293. package/dist/plugins/tidb-pool.d.ts +3 -2
  294. package/dist/plugins/tidb-pool.js +19 -31
  295. package/dist/plugins/user-input-ledger-sql.d.ts +1 -1
  296. package/dist/read-face-posture.d.ts +6 -6
  297. package/dist/read-face-posture.js +2 -2
  298. package/dist/request-value-closure.d.ts +5 -5
  299. package/dist/request-value-closure.js +1 -1
  300. package/dist/rules-consent.d.ts +41 -13
  301. package/dist/rules-consent.js +101 -53
  302. package/dist/run-local.js +17 -13
  303. package/dist/runs.d.ts +48 -30
  304. package/dist/runs.js +26 -16
  305. package/dist/runtime-caps-resolver.d.ts +15 -8
  306. package/dist/runtime-caps-resolver.js +14 -10
  307. package/dist/sealed-key-layout.d.ts +2 -3
  308. package/dist/sealed-key-layout.js +0 -1
  309. package/dist/sealed-key.js +7 -5
  310. package/dist/security.d.ts +5 -3
  311. package/dist/sema-config-dir.js +2 -2
  312. package/dist/server-secret-env.d.ts +2 -0
  313. package/dist/service-version.d.ts +2 -1
  314. package/dist/service-version.js +2 -2
  315. package/dist/session-error-wire.d.ts +1 -1
  316. package/dist/session-incarnation.d.ts +8 -5
  317. package/dist/session-resident-background.d.ts +85 -32
  318. package/dist/session-resident-background.js +75 -7
  319. package/dist/session-row.d.ts +1 -1
  320. package/dist/session-sync-kernel.d.ts +1 -1
  321. package/dist/session-workspace.d.ts +11 -2
  322. package/dist/session-workspace.js +5 -0
  323. package/dist/sighup-idle.d.ts +1 -1
  324. package/dist/store-posture.d.ts +2 -1
  325. package/dist/stored-request-hooks-m20.d.ts +3 -2
  326. package/dist/stored-request-hooks-m20.js +19 -14
  327. package/dist/stores-sql/blob-index-sql.d.ts +148 -0
  328. package/dist/stores-sql/blob-index-sql.js +154 -0
  329. package/dist/stores-sql/checkpoint-store-sql.d.ts +1 -1
  330. package/dist/stores-sql/checkpoint-store-sql.js +11 -27
  331. package/dist/{plugins → stores-sql}/file-history-store-sql.d.ts +23 -11
  332. package/dist/{plugins → stores-sql}/file-history-store-sql.js +23 -18
  333. package/dist/{plugins → stores-sql}/pg-session-storage.d.ts +23 -76
  334. package/dist/{plugins → stores-sql}/pg-session-storage.js +80 -209
  335. package/dist/{plugins → stores-sql}/retention-store-sql.d.ts +123 -217
  336. package/dist/{plugins → stores-sql}/retention-store-sql.js +66 -190
  337. package/dist/{plugins → stores-sql}/session-event-payload.d.ts +1 -1
  338. package/dist/{plugins → stores-sql}/session-event-payload.js +1 -1
  339. package/dist/stores-sql/session-policy-store-sql.d.ts +1 -1
  340. package/dist/stores-sql/session-write-hooks.d.ts +59 -0
  341. package/dist/stores-sql/session-write-hooks.js +2 -0
  342. package/dist/{plugins → stores-sql}/tidb-session-storage.d.ts +10 -11
  343. package/dist/{plugins → stores-sql}/tidb-session-storage.js +10 -21
  344. package/dist/{plugins → stores-sql}/tidb-session-store.d.ts +32 -122
  345. package/dist/{plugins → stores-sql}/tidb-session-store.js +71 -171
  346. package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
  347. package/dist/stores-sql/tool-result-store-sql.js +1 -1
  348. package/dist/stores-sql/windowed-session-storage.d.ts +56 -0
  349. package/dist/stores-sql/windowed-session-storage.js +61 -0
  350. package/dist/task-a2a.d.ts +7 -1
  351. package/dist/task-a2a.js +15 -14
  352. package/dist/task-cwd.d.ts +11 -3
  353. package/dist/task-cwd.js +17 -1
  354. package/dist/task-mcp.d.ts +10 -2
  355. package/dist/task-mcp.js +13 -16
  356. package/dist/task-settings.d.ts +9 -4
  357. package/dist/task-settings.js +17 -6
  358. package/dist/tool-approval.d.ts +21 -8
  359. package/dist/tool-approval.js +10 -6
  360. package/dist/trace/core-keyset-guard.d.ts +9 -3
  361. package/dist/trace/engine-notice-wire.d.ts +1 -1
  362. package/dist/trace/engine-notice-wire.js +2 -0
  363. package/dist/trace/exit-seat.d.ts +23 -1
  364. package/dist/trace/exit-seat.js +3 -0
  365. package/dist/trace/project.d.ts +33 -16
  366. package/dist/trace/project.js +12 -9
  367. package/dist/trace/redact.d.ts +1 -1
  368. package/dist/trace/redact.js +61 -73
  369. package/dist/trace/self-minted-wire.d.ts +263 -10
  370. package/dist/trace/self-minted-wire.js +90 -2
  371. package/dist/trace/sema-provenance.d.ts +45 -41
  372. package/dist/trace/sema-provenance.js +81 -10
  373. package/dist/trace/task-notification-facets.d.ts +70 -2
  374. package/dist/trace/task-notification-facets.js +71 -1
  375. package/dist/trace/wire-projection-faces.d.ts +38 -2
  376. package/dist/trace/wire-projection-faces.js +26 -1
  377. package/dist/unread-request-members.d.ts +66 -0
  378. package/dist/unread-request-members.js +41 -0
  379. package/dist/user-input-ledger.d.ts +2 -2
  380. package/dist/web-admin-client/apply-effective.js +22 -26
  381. package/dist/web-admin-client/candidate-gate.d.ts +35 -3
  382. package/dist/web-admin-client/candidate-gate.js +53 -5
  383. package/dist/web-admin-client/center-request.d.ts +4 -1
  384. package/dist/web-admin-client/center-request.js +2 -1
  385. package/dist/web-admin-client/effective-keys.js +0 -1
  386. package/dist/web-admin-client/facade.d.ts +1 -1
  387. package/dist/web-admin-client/http-client.d.ts +1 -0
  388. package/dist/web-admin-client/http-client.js +17 -9
  389. package/dist/web-admin-client/restart-signal.js +5 -2
  390. package/dist/web-admin-client/skills-mcp.d.ts +20 -6
  391. package/dist/web-admin-client/skills-mcp.js +26 -21
  392. package/dist/web-admin-client/types.d.ts +34 -49
  393. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +2 -2
  394. package/package.json +13 -12
  395. package/scripts/drain-check-local.mjs +2 -28
  396. package/scripts/drain-check.mysql.sql +2 -18
  397. package/scripts/drain-check.pg.sql +2 -18
  398. package/wire-changes/server@7.147.0.json +813 -0
@@ -2,7 +2,7 @@ import { realpathSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { NodeExecutionEnv, QUESTION_AWAITS_RESUME, deriveAskEffective, expandTiers, resolveAskSeamForm } from "@sema-agent/core";
4
4
  import { cappedCeiling } from "../budget.js";
5
- import { recordFailOpen } from "../observability/fail-open.js";
5
+ import { unreadRequestMembers, unreadRequestMembersRefusal } from "../unread-request-members.js";
6
6
  import { SessionEnvironmentSelection, selectEnvironmentTool } from "../capabilities/select-environment-tool.js";
7
7
  import { sendUserFileTool } from "../capabilities/send-user-file-tool.js";
8
8
  import { buildExcludeToolsSeat, buildPromptSeats, buildRunSkills, createScenarioGate, selectScenario } from "../capabilities/scenarios.js";
@@ -27,6 +27,7 @@ import { routeServiceTask, supPostureOverrides } from "../router/route-orchestra
27
27
  import { tightenGoverned } from "../governance-overrides.js";
28
28
  import { applyRuntimeGovernance } from "../runtime-governance.js";
29
29
  import { HttpError, createCodedHttpError, encodeCheckpointScope } from "../security.js";
30
+ import { resolveHistoryAnchor } from "../history-anchor.js";
30
31
  import { headReadOf, sessionFaceOfHead } from "../session-incarnation.js";
31
32
  import { legProjectIdOf, sessionWorkspaceStoreOf } from "../session-workspace.js";
32
33
  import { memorySpecForRequest } from "../memory-scope.js";
@@ -71,11 +72,11 @@ export function createResolveSpec(ctx) {
71
72
  approvalSeat: durableEnabled ? "durable" : "absent",
72
73
  singleUserAutoAcceptBaseline: singleUserAutoAcceptBaselineApplies(config),
73
74
  });
74
- const realTaskRootOf = (auth) => {
75
+ const realTaskRootOf = (root) => {
75
76
  if (DEPLOYMENT_SHAPE_PREDICATES.sandboxPathAdjudication.holds(config))
76
77
  return undefined;
77
- const sessionCwd = auth?.sessionId ? effectiveHostWorkspace(perSessionCwd.get(auth.sessionId), {}) : undefined;
78
- return sessionCwd ?? (executionLaneOf(config.remoteExec?.provider) === "in-process" ? process.cwd() : undefined);
78
+ const sessionCwd = effectiveHostWorkspace(perSessionCwd.get(root), {});
79
+ return sessionCwd ?? (laneWiresExecutionEnv(config.remoteExec.provider) ? undefined : process.cwd());
79
80
  };
80
81
  const memoryProjectLayers = createMemoryProjectLayers({ stores: memoryEngine, syncRunner: memorySyncRunner, log: logger });
81
82
  if (onlySensitiveBaseline)
@@ -84,6 +85,7 @@ export function createResolveSpec(ctx) {
84
85
  if (approvalGrantNotice)
85
86
  logger.info(approvalGrantNotice.event, approvalGrantNotice.fields);
86
87
  const resolveSpec = async (body, req, auth, opts) => {
88
+ const root = opts.execution.root;
87
89
  const seatRefusal = gateIntentUnserviceableReason(config, checkpointStore !== undefined);
88
90
  if (seatRefusal !== undefined)
89
91
  throw createCodedHttpError(501, "capability.checkpoint_store_required", seatRefusal);
@@ -102,7 +104,7 @@ export function createResolveSpec(ctx) {
102
104
  cwd: body.cwd,
103
105
  shellScratchpadDir: body.scratchpadDir,
104
106
  localDataRoot: config.localDataRoot ?? localRoot,
105
- sessionId: auth?.sessionId,
107
+ sessionId: root,
106
108
  requirePrincipal: config.requirePrincipal,
107
109
  callerOwnsWorkerDisk: DEPLOYMENT_SHAPE_PREDICATES.callerOwnsWorkerDisk.holds(config),
108
110
  });
@@ -119,15 +121,13 @@ export function createResolveSpec(ctx) {
119
121
  if (inheritEnvIssue)
120
122
  throw new HttpError(400, inheritEnvIssue.message, { code: "request.field_invalid", extra: inheritEnvIssue.facts });
121
123
  if (body.inheritEnv === "all") {
122
- const lane = executionLaneOf(config.remoteExec?.provider);
124
+ const lane = config.remoteExec.provider;
123
125
  if (lane !== "host") {
124
126
  throw new HttpError(400, `inheritEnv:"all" applies to the host lane only (this deployment runs ${lane}) — only the host lane builds the model-driven shell's environment from this machine's own, so the declaration has no effect here; omit it (or send "scrub", the default, which every lane accepts)`, { code: "request.field_invalid", extra: inheritEnvFacts("lane_not_host") });
125
127
  }
126
128
  const why = taskInheritEnvRefusal(config);
127
129
  if (why !== undefined)
128
130
  throw new HttpError(422, why, { code: HOST_POSTURE_REFUSED_CODE });
129
- if (!auth?.sessionId)
130
- throw new HttpError(400, `inheritEnv:"all" requires a session-resolving deployment (no authorizer session) — the host shell's environment is bound per session`, { code: "request.field_invalid", extra: inheritEnvFacts("no_authorizer_session") });
131
131
  }
132
132
  }
133
133
  {
@@ -151,7 +151,7 @@ export function createResolveSpec(ctx) {
151
151
  dropped[e.match]++;
152
152
  logger.warn("settings_env_credentials_dropped", {
153
153
  migration: "M38",
154
- sessionId: auth?.sessionId ?? null,
154
+ sessionId: root,
155
155
  dropped,
156
156
  note: "this replayed request was stored before the upgrade and its settings.env carries credentials (a credential variable name of this engine, or a value shaped like a secret); while one-time migration M38 is open they are dropped from what the session's shell and hooks receive and the task resumes — the engine's own credentials come from its process environment and are unaffected; once the window closes the same request is refused",
157
157
  });
@@ -169,7 +169,7 @@ export function createResolveSpec(ctx) {
169
169
  const stale = inertToolListEntryOf(body, ["allow"]);
170
170
  if (stale !== undefined) {
171
171
  logger.warn("stored_allow_list_inert_resumed", {
172
- sessionId: auth?.sessionId ?? null,
172
+ sessionId: root,
173
173
  layer: stale.layer,
174
174
  sentence: stale.message,
175
175
  note: "this resumed task's stored request carries an allow-list entry the engine reads as nothing (a retired name, a case twin, an unreadable spelling or a content form): the entry stays as written and grants nothing — the task ran that way before the upgrade, so it continues; fix the entry in a new submission to get what it was meant to allow",
@@ -179,54 +179,54 @@ export function createResolveSpec(ctx) {
179
179
  }
180
180
  if (opts?.leg === "fresh")
181
181
  assertRequestA2aEntries(a2aPeers);
182
+ {
183
+ const unread = unreadRequestMembers({ settings: body.settings, mcpServers: body.mcpServers, a2aPeers }, config, opts?.leg === "fresh" ? { replay: false, settingsEnv } : { replay: true, today: new Date().toISOString().slice(0, 10), storedToolAxes, settingsEnv });
184
+ if (unread.length > 0) {
185
+ const refusal = unreadRequestMembersRefusal(unread);
186
+ throw new HttpError(400, refusal.message, { code: refusal.errorCode, ...(refusal.facts !== undefined ? { extra: { ...refusal.facts } } : {}) });
187
+ }
188
+ }
182
189
  if (opts?.leg === "fresh")
183
190
  assertRequestImageUrls(body.images);
184
- const gated = await gateScenarioAndAppend(body, auth, opts, settingsEnv);
191
+ const gated = await gateScenarioAndAppend(body, auth, root, opts, settingsEnv);
185
192
  const effMode = effectivePermissionMode(body, gated.parsedSettings.settings);
186
193
  {
187
194
  const why = permissionModeWriteFaceRefusal(effMode, config);
188
195
  if (why !== undefined)
189
196
  throw new HttpError(422, why, { code: HOST_POSTURE_REFUSED_CODE });
190
197
  }
191
- const lane = bindSettingsCwdEnvAndModel(body, auth, gated, opts);
192
- const anchors = await resolveHistoryAnchors(body, auth);
193
- const projectKey = memoryEngine ? await memoryProjectLayers.prepare(config, auth?.memoryScope, realTaskRootOf(auth)) : undefined;
198
+ const lane = bindSettingsCwdEnvAndModel(body, auth, root, gated, opts);
199
+ const anchors = await resolveHistoryAnchors(body, auth, root);
200
+ const projectKey = memoryEngine ? await memoryProjectLayers.prepare(config, auth?.memoryScope, realTaskRootOf(root)) : undefined;
194
201
  const runSkills = buildRunSkills({ scenario: gated.cap.skills, request: body.skills, disable: body.disableSkills === true, deploymentSources: deploymentSkillSources }, logger);
195
- const spec = assembleSpecLiteral(body, auth, req, opts, { ...gated, ...lane, ...anchors, projectKey, a2aPeers, storedToolAxes, runSkills }, effMode);
196
- const folded = await foldGovernanceAndSettings(body, auth, spec, gated);
197
- const final = await applyImageFactsAndRouting(body, auth, folded.governed, {
202
+ const spec = assembleSpecLiteral(body, auth, root, req, opts, { ...gated, ...lane, ...anchors, projectKey, a2aPeers, storedToolAxes, runSkills }, effMode);
203
+ const folded = await foldGovernanceAndSettings(body, auth, root, spec, gated);
204
+ const final = await applyImageFactsAndRouting(body, auth, root, folded.governed, {
198
205
  scenarioName: gated.scenarioName,
199
206
  scratchpadDir: folded.scratchpadDir,
200
207
  hostSemanticsLane: folded.hostSemanticsLane,
201
208
  });
202
209
  return { spec: final, facts: { hands: gated.hands, skills: runSkills.roster, sessionWitness: gated.sessionWitness } };
203
210
  };
204
- const gateScenarioAndAppend = async (body, auth, opts, settingsEnv) => {
211
+ const gateScenarioAndAppend = async (body, auth, root, opts, settingsEnv) => {
205
212
  const scenarioName = await scenarioGate(auth?.principal, body.scenario);
206
- const root = opts.execution.root;
207
213
  const rootFace = sessionHeadOf === undefined ? undefined : sessionFaceOfHead(root, await sessionHeadOf(root));
208
214
  const sessionWitness = { sessionId: root, owner: rootFace?.owner ?? null, incarnation: rootFace?.incarnation ?? null };
209
215
  const cap = selectScenario(scenarios, scenarioName)(body, auth?.principal, { sessionId: sessionWitness.sessionId, delegationRoot: sessionWitness });
210
- const acceptedAppend = acceptAppendSystemPrompt(body.appendSystemPrompt, (detail) => logger.warn("append_system_prompt_dropped", { detail, sessionId: auth?.sessionId ?? null }));
216
+ const acceptedAppend = acceptAppendSystemPrompt(body.appendSystemPrompt, (detail) => logger.warn("append_system_prompt_dropped", { detail, sessionId: root }));
211
217
  const objective = typeof body.objective === "string" ? body.objective : "";
212
218
  const parsedSettings = parseTaskSettings(body.settings, {
213
219
  ...(opts?.leg === "fresh" || !taskHooksHonored(config) ? {} : { storedHooksReread: storedHooksRereadM20(new Date().toISOString().slice(0, 10)) }),
214
220
  settingsEnv,
215
221
  });
216
- if (parsedSettings.deferred.length > 0) {
217
- logger.warn("task_settings_deferred", { fields: parsedSettings.deferred, sessionId: auth?.sessionId ?? null });
218
- }
219
222
  if (parsedSettings.hooksReread !== undefined) {
220
223
  logger.warn("hooks_read_as_before_upgrade", {
221
224
  migration: "M20",
222
- sessionId: auth?.sessionId ?? null,
225
+ sessionId: root,
223
226
  stripped: parsedSettings.hooksReread.stripped,
224
- note: "this replayed request was stored before the upgrade and its settings.hooks carries a shape the hooks reader now refuses (a key the reader does not know that hides a guard-event member, or a JSON `__proto__` event key); while one-time migration M20 is open the keys named in `stripped` are dropped — what the pre-upgrade reader dropped — and the rest goes through the same reader again, so the guard hooks keep running; once the window closes the same request has its whole settings.hooks left out",
227
+ note: "this replayed request was stored before the upgrade and its settings.hooks carries a shape the hooks reader now refuses (a key the reader does not know that hides a guard-event member, or a JSON `__proto__` event key); while one-time migration M20 is open the keys named in `stripped` are dropped — what the pre-upgrade reader dropped — and the rest goes through the same reader again, so the guard hooks keep running; once the window closes the same request is refused on resume (409 resume_blocked_by_policy)",
225
228
  });
226
229
  }
227
- if (parsedSettings.deferred.includes("hooks") && taskHooksHonored(config)) {
228
- recordFailOpen("server.hooks.resume-reader-refused", `leg=${opts?.leg ?? "resume"}`);
229
- }
230
230
  let attachmentNotice;
231
231
  {
232
232
  const reqAtt = body.attachmentIds;
@@ -239,28 +239,25 @@ export function createResolveSpec(ctx) {
239
239
  if (reqAtt.length > 0) {
240
240
  if (!taskAttachmentStore)
241
241
  throw new HttpError(501, "attachmentIds require a store backend (DB_BACKEND=mysql|pg|local)");
242
- if (!auth?.sessionId)
243
- throw new HttpError(400, "`attachmentIds` requires a session-resolving deployment (no authorizer session)");
244
- const sid = auth.sessionId;
245
242
  const lane = opts.execution.lane;
246
243
  const r = await bindAttachmentsForTask({
247
244
  store: taskAttachmentStore,
248
245
  owner: auth?.principal ?? "default",
249
246
  ids: reqAtt,
250
- sessionId: sid,
247
+ sessionId: root,
251
248
  lane: { word: lane, isolated: laneIsolated(lane) },
252
249
  leg: opts?.leg === "fresh" ? "fresh" : "resume",
253
250
  nowMs: Date.now(),
254
251
  onMissing: (id) => {
255
252
  if (opts?.leg === "fresh")
256
253
  throw new HttpError(400, `attachment not found: ${id}`);
257
- logger.warn("attachment_missing_on_resume", { sessionId: sid, id });
254
+ logger.warn("attachment_missing_on_resume", { sessionId: root, id });
258
255
  },
259
256
  onRefused: (refusal) => {
260
257
  const answer = attachmentBindRefusalAnswer(refusal);
261
258
  if (opts?.leg === "fresh")
262
259
  throw createCodedHttpError(answer.status, answer.errorCode, answer.message, answer.extra);
263
- logger.warn("attachment_refused_on_resume", { sessionId: sid, errorCode: answer.errorCode, ...answer.extra });
260
+ logger.warn("attachment_refused_on_resume", { sessionId: root, errorCode: answer.errorCode, ...answer.extra });
264
261
  },
265
262
  });
266
263
  attachmentNotice = r.notice;
@@ -269,46 +266,45 @@ export function createResolveSpec(ctx) {
269
266
  }
270
267
  return { scenarioName, cap, hands: cap.hands, acceptedAppend, objective, parsedSettings, attachmentNotice, sessionWitness };
271
268
  };
272
- const bindSettingsCwdEnvAndModel = (body, auth, gated, opts) => {
269
+ const bindSettingsCwdEnvAndModel = (body, auth, root, gated, opts) => {
273
270
  const { objective, parsedSettings } = gated;
274
271
  const cwdWriteGate = DEPLOYMENT_SHAPE_PREDICATES.callerCwd.holds(config);
275
- const execLane = executionLaneOf(config.remoteExec?.provider);
276
- if (auth?.sessionId)
277
- fenceSessionOwner(auth.sessionId, auth.principal ?? null);
278
- if (typeof body.cwd === "string" && body.cwd.length > 0 && auth?.sessionId) {
272
+ const execLane = config.remoteExec.provider;
273
+ fenceSessionOwner(root, auth?.principal ?? null);
274
+ if (typeof body.cwd === "string" && body.cwd.length > 0) {
279
275
  if (cwdWriteGate && isAbsoluteHostPath(body.cwd))
280
- setSessionCwd(auth.sessionId, body.cwd);
281
- else if (DEPLOYMENT_SHAPE_PREDICATES.inProcessSingleUser.holds(config) && isAbsoluteHostPath(body.cwd) && satisfiedByProcessCwd(body.cwd, realpathSync))
282
- logger.debug("task_cwd_inherited", { lane: execLane, sessionId: auth.sessionId });
276
+ setSessionCwd(root, body.cwd);
277
+ else if (DEPLOYMENT_SHAPE_PREDICATES.noHandsSingleUser.holds(config) && isAbsoluteHostPath(body.cwd) && satisfiedByProcessCwd(body.cwd, realpathSync))
278
+ logger.debug("task_cwd_inherited", { lane: execLane, sessionId: root });
283
279
  else
284
- logger.warn("task_cwd_ignored", { honored: cwdWriteGate, lane: execLane, sessionId: auth.sessionId });
280
+ logger.warn("task_cwd_ignored", { honored: cwdWriteGate, lane: execLane, sessionId: root });
285
281
  }
286
- if (parsedSettings.settings?.shellEnv && auth?.sessionId) {
282
+ if (parsedSettings.settings?.shellEnv) {
287
283
  if (cwdWriteGate)
288
- setSessionShellEnv(auth.sessionId, parsedSettings.settings.shellEnv);
289
- else if (DEPLOYMENT_SHAPE_PREDICATES.inProcessSingleUser.holds(config)) {
284
+ setSessionShellEnv(root, parsedSettings.settings.shellEnv);
285
+ else if (DEPLOYMENT_SHAPE_PREDICATES.noHandsSingleUser.holds(config)) {
290
286
  const requested = parsedSettings.settings.shellEnv;
291
287
  const mismatched = shellEnvMismatchCount(requested, process.env);
292
288
  if (mismatched === 0)
293
- logger.debug("task_shell_env_inherited", { lane: execLane, keys: Object.keys(requested).length, sessionId: auth.sessionId });
289
+ logger.debug("task_shell_env_inherited", { lane: execLane, keys: Object.keys(requested).length, sessionId: root });
294
290
  else
295
- logger.warn("task_shell_env_ignored", { honored: false, lane: execLane, mismatchedKeys: mismatched, sessionId: auth.sessionId });
291
+ logger.warn("task_shell_env_ignored", { honored: false, lane: execLane, mismatchedKeys: mismatched, sessionId: root });
296
292
  }
297
293
  else
298
- logger.warn("task_shell_env_ignored", { honored: false, lane: execLane, sessionId: auth.sessionId });
294
+ logger.warn("task_shell_env_ignored", { honored: false, lane: execLane, sessionId: root });
299
295
  }
300
296
  const taskHooks = (() => {
301
297
  const hc = parsedSettings.settings?.hooks;
302
298
  if (!hc)
303
299
  return [];
304
300
  if (!taskHooksHonored(config)) {
305
- logger.warn("task_hooks_ignored", { honored: false, sessionId: auth?.sessionId ?? null });
301
+ logger.warn("task_hooks_ignored", { honored: false, sessionId: root });
306
302
  return [];
307
303
  }
308
304
  return createSettingsHooksRegistrations(hc, {
309
305
  logger,
310
- sessionId: auth?.sessionId ?? "",
311
- cwd: (auth?.sessionId ? perSessionCwd.get(auth.sessionId) : undefined) ?? process.cwd(),
306
+ sessionId: root,
307
+ cwd: perSessionCwd.get(root) ?? process.cwd(),
312
308
  ...(parsedSettings.settings?.shellEnv ? { shellEnv: parsedSettings.settings.shellEnv } : {}),
313
309
  httpHookAllowlistLayers: parsedSettings.settings?.httpHookAllowlist !== undefined ? [parsedSettings.settings.httpHookAllowlist] : [],
314
310
  belowTaskChainPatterns,
@@ -317,28 +313,24 @@ export function createResolveSpec(ctx) {
317
313
  onHookNotice: (n) => fleetBus.publishHookNotice({
318
314
  ...n,
319
315
  ...(auth?.principal ? { ownerScope: auth.principal } : {}),
320
- ...(auth?.sessionId ? { ownerSessionId: auth.sessionId } : {}),
316
+ ownerSessionId: root,
321
317
  }),
322
- ...(auth?.sessionId
323
- ? {
324
- wake: async (text) => hookWakeBus.deliver
325
- ?
326
- hookWakeBus.deliver(auth.sessionId, `[hook asyncRewake] ${redactSecrets(text)}`)
327
- : false,
328
- }
329
- : {}),
318
+ wake: async (text) => hookWakeBus.deliver
319
+ ?
320
+ hookWakeBus.deliver(root, `[hook asyncRewake] ${redactSecrets(text)}`)
321
+ : false,
330
322
  }, settingsHooksBudgetMs(config));
331
323
  })();
332
324
  const rawAddDirs = body.additionalDirectories;
333
325
  const callerOwnsWorkerDisk = DEPLOYMENT_SHAPE_PREDICATES.callerOwnsWorkerDisk.holds(config);
334
326
  const additionalDirectories = callerOwnsWorkerDisk ? parseAdditionalDirectories(rawAddDirs) : undefined;
335
327
  if (rawAddDirs !== undefined && !callerOwnsWorkerDisk) {
336
- logger.warn("task_additional_directories_ignored", { honored: false, sessionId: auth?.sessionId ?? null });
328
+ logger.warn("task_additional_directories_ignored", { honored: false, sessionId: root });
337
329
  }
338
330
  const rawAddReadDirs = body.additionalReadDirectories;
339
331
  const additionalReadDirectories = callerOwnsWorkerDisk ? parseAdditionalDirectories(rawAddReadDirs) : undefined;
340
332
  if (rawAddReadDirs !== undefined && !callerOwnsWorkerDisk) {
341
- logger.warn("task_additional_read_directories_ignored", { honored: false, sessionId: auth?.sessionId ?? null });
333
+ logger.warn("task_additional_read_directories_ignored", { honored: false, sessionId: root });
342
334
  }
343
335
  const wireCatalog = selectableCatalog(config.models, config.tiers, config.modelRefusals);
344
336
  const picked = resolveTaskModel(body.model ?? parsedSettings.settings?.model, objective, wireCatalog, config.atMention, config.modelRefusals);
@@ -348,7 +340,7 @@ export function createResolveSpec(ctx) {
348
340
  throw new HttpError(400, modelUnavailableMessage(source === "mention" ? "@-mention" : "model", requested, name, refusal), { code: "request.model_unavailable" });
349
341
  }
350
342
  metrics.inc("task_model_unavailable_fallback_total");
351
- logger.warn("task_model_unavailable_fallback", { requested: echoModelRef(requested), name, code: refusal.code, source, fallback: picked.model, sessionId: auth?.sessionId ?? null });
343
+ logger.warn("task_model_unavailable_fallback", { requested: echoModelRef(requested), name, code: refusal.code, source, fallback: picked.model, sessionId: root });
352
344
  }
353
345
  if (picked.notAllowed !== undefined) {
354
346
  const { requested, resolved, source } = picked.notAllowed;
@@ -356,39 +348,30 @@ export function createResolveSpec(ctx) {
356
348
  throw new HttpError(400, `model "${echoModelRef(requested)}" is not @-mentionable on this deployment (it resolves to catalog model "${resolved}") — which models can be @-mentioned is configured by the operator (models.atMention)`, { code: "request.model_not_allowed" });
357
349
  }
358
350
  metrics.inc("task_model_not_allowlisted_resume_total");
359
- logger.warn("task_model_not_allowlisted_resume", { requested: echoModelRef(requested), resolved, source, sessionId: auth?.sessionId ?? null, note: "resumed leg keeps running the model it was started on — the allowlist gates fresh picks only" });
351
+ logger.warn("task_model_not_allowlisted_resume", { requested: echoModelRef(requested), resolved, source, sessionId: root, note: "resumed leg keeps running the model it was started on — the allowlist gates fresh picks only" });
360
352
  }
361
353
  if (picked.unknownExplicit !== undefined) {
362
354
  metrics.inc("task_model_unknown_fallback_total");
363
- logger.warn("task_model_unknown_fallback", { requested: echoModelRef(picked.unknownExplicit), fallback: picked.model, sessionId: auth?.sessionId ?? null });
355
+ logger.warn("task_model_unknown_fallback", { requested: echoModelRef(picked.unknownExplicit), fallback: picked.model, sessionId: root });
364
356
  }
365
357
  return { taskHooks, additionalDirectories, additionalReadDirectories, wireCatalog, picked };
366
358
  };
367
- const NO_ANCHOR_HINT = "no rewind anchor is recorded under that handle (a prompt that carried attachments records none when its attachment frames were interrupted or their count did not match)";
368
- const resolveHistoryAnchors = async (body, auth) => {
359
+ const resolveHistoryAnchors = async (body, auth, root) => {
369
360
  let resumeAtEntryId;
370
361
  if (typeof body.resumeAt === "string" && body.resumeAt.length > 0) {
371
- if (!auth?.sessionId)
372
- throw new HttpError(422, "resumeAt requires a session to branch (resume_at.no_session)", { code: "resume_at.no_session" });
373
362
  if (!resumeAnchorStore || !sessionHeadOf)
374
363
  throw new HttpError(501, "resume-at is not available on this worker (no session-store backend for the anchor map)");
375
- resumeAtEntryId = await resumeAnchorStore.resolve(auth.sessionId, body.resumeAt, auth.principal ?? null);
376
- if (resumeAtEntryId === undefined)
377
- throw new HttpError(404, `resumeAt: no such message in this session (resume_at.unknown_event) — ${NO_ANCHOR_HINT}; give an explicit resumeAt`, { code: "resume_at.unknown_event" });
364
+ resumeAtEntryId = await resolveHistoryAnchor("resumeAt", resumeAnchorStore, root, body.resumeAt, auth?.principal ?? null, "resumeAt");
378
365
  }
379
366
  let rewindFilesToEntryId;
380
367
  if (resumeAtEntryId === undefined && typeof body.rewindFilesTo === "string" && body.rewindFilesTo.length > 0) {
381
- if (!auth?.sessionId)
382
- throw new HttpError(422, "rewindFilesTo requires a session (rewind_files_to.no_session)", { code: "rewind_files_to.no_session" });
383
368
  if (!resumeAnchorStore || !sessionHeadOf)
384
369
  throw new HttpError(501, "rewind-files-to is not available on this worker (no session-store backend for the anchor map)");
385
- rewindFilesToEntryId = await resumeAnchorStore.resolve(auth.sessionId, body.rewindFilesTo, auth.principal ?? null);
386
- if (rewindFilesToEntryId === undefined)
387
- throw new HttpError(404, `rewindFilesTo: no such message in this session (rewind_files_to.unknown_event) — ${NO_ANCHOR_HINT}; name another prompt`, { code: "rewind_files_to.unknown_event" });
370
+ rewindFilesToEntryId = await resolveHistoryAnchor("rewindFilesTo", resumeAnchorStore, root, body.rewindFilesTo, auth?.principal ?? null, "rewindFilesTo");
388
371
  }
389
372
  const submittedProjectId = auth?.resolvedProjectId ?? (typeof body.projectId === "string" && body.projectId ? body.projectId.toLowerCase() : undefined);
390
373
  const s4DefaultScopes = submittedProjectId ? config.projects[submittedProjectId]?.defaultScopes : undefined;
391
- const legProjectId = await legProjectIdOf(submittedProjectId, sessionWorkspace, auth?.sessionId);
374
+ const legProjectId = await legProjectIdOf(submittedProjectId, sessionWorkspace, root);
392
375
  return { resumeAtEntryId, rewindFilesToEntryId, s4DefaultScopes, legProjectId };
393
376
  };
394
377
  const declaresInteractivePosture = (body, req, opts) => {
@@ -405,7 +388,7 @@ export function createResolveSpec(ctx) {
405
388
  const askForm = resolveAskSeamForm(body.approvalReach !== undefined ? { approvalReach: body.approvalReach } : {}, approverSeat !== undefined ? { onAsk: approverSeat } : {});
406
389
  return deriveAskEffective(askForm.form, "unresolved") === "human_reachable";
407
390
  };
408
- const assembleSpecLiteral = (body, auth, req, opts, parts, effMode) => {
391
+ const assembleSpecLiteral = (body, auth, root, req, opts, parts, effMode) => {
409
392
  const { scenarioName, cap, hands, acceptedAppend, parsedSettings, attachmentNotice, taskHooks, additionalDirectories, additionalReadDirectories, wireCatalog, picked, resumeAtEntryId, rewindFilesToEntryId, s4DefaultScopes, legProjectId, projectKey, a2aPeers, storedToolAxes, runSkills, } = parts;
410
393
  const spec = {
411
394
  objective: attachmentNotice ? `${picked.cleanedObjective}\n\n${attachmentNotice}` : picked.cleanedObjective,
@@ -439,8 +422,8 @@ export function createResolveSpec(ctx) {
439
422
  selfOrchestration: selfOrchestrationFromBody({ selfOrchestration: body.selfOrchestration === true || parsedSettings.settings?.ultracode === true }, config, Boolean(centerRuntimeCapsResolver)),
440
423
  forwardSubagentEvents: body.forwardSubagentEvents === true ? true : undefined,
441
424
  retainSubagentSessions: normalizeRetainSubagentSessions(body.retainSubagentSessions),
442
- ...taskAgentsSpecFragment(body.agents, config.requirePrincipal, (event, fields) => logger.warn(event, { ...fields, sessionId: auth?.sessionId ?? null })),
443
- ...(retainBackgroundProcessesFromBody(body.retainBackgroundProcesses, config.requirePrincipal, (event, fields) => logger.warn(event, { ...fields, sessionId: auth?.sessionId ?? null })) === true
425
+ ...taskAgentsSpecFragment(body.agents, config.requirePrincipal, (event, fields) => logger.warn(event, { ...fields, sessionId: root })),
426
+ ...(retainBackgroundProcessesFromBody(body.retainBackgroundProcesses, config.requirePrincipal, (event, fields) => logger.warn(event, { ...fields, sessionId: root })) === true
444
427
  ? { retainBackgroundProcesses: true }
445
428
  : {}),
446
429
  ...(body.excludeAllTools === true ? { excludeAllTools: true } : {}),
@@ -471,7 +454,7 @@ export function createResolveSpec(ctx) {
471
454
  throw new HttpError(400, `unknown compactionModel "${echoModelRef(body.compactionModel)}" — not in the configured catalog (name, tier word, or id; a catalog refresh may have removed it mid-request)`);
472
455
  }
473
456
  metrics.inc("task_model_unknown_fallback_total");
474
- logger.warn("compaction_model_unknown_fallback", { requested: echoModelRef(body.compactionModel), sessionId: auth?.sessionId ?? null });
457
+ logger.warn("compaction_model_unknown_fallback", { requested: echoModelRef(body.compactionModel), sessionId: root });
475
458
  return {};
476
459
  }
477
460
  if (!isAtMentionable(cm, wireCatalog, config.atMention, config.modelRefusals)) {
@@ -480,14 +463,14 @@ export function createResolveSpec(ctx) {
480
463
  throw new HttpError(400, `compactionModel "${echoModelRef(body.compactionModel)}" is not @-mentionable on this deployment (it resolves to catalog model "${terminal}") — which models can be @-mentioned is configured by the operator (models.atMention)`, { code: "request.model_not_allowed" });
481
464
  }
482
465
  metrics.inc("task_model_not_allowlisted_resume_total");
483
- logger.warn("task_model_not_allowlisted_resume", { requested: echoModelRef(body.compactionModel), resolved: terminal, source: "compaction", sessionId: auth?.sessionId ?? null, note: "resumed leg keeps the compaction model it was started with — the allowlist gates fresh picks only" });
466
+ logger.warn("task_model_not_allowlisted_resume", { requested: echoModelRef(body.compactionModel), resolved: terminal, source: "compaction", sessionId: root, note: "resumed leg keeps the compaction model it was started with — the allowlist gates fresh picks only" });
484
467
  }
485
468
  return { compactionModel: cm };
486
469
  })()),
487
470
  thinking: effectiveThinking(body.reasoningEffort, parsedSettings.settings?.ultracode === true),
488
471
  getApiKeyAndHeaders: getKeyResolver(),
489
472
  ...(() => {
490
- const limits = resolveTaskLimits(body.limits, taskLimitCaps, taskTimeoutSec, config.requirePrincipal, (event, fields) => logger.warn(event, { ...fields, sessionId: auth?.sessionId ?? null }));
473
+ const limits = resolveTaskLimits(body.limits, taskLimitCaps, taskTimeoutSec, config.requirePrincipal, (event, fields) => logger.warn(event, { ...fields, sessionId: root }));
491
474
  const declarations = [];
492
475
  if (taskLimitCaps.timeoutSec !== undefined)
493
476
  declarations.push({ key: "server.limits.timeoutSecCap", value: String(taskLimitCaps.timeoutSec), reason: "env TASK_TIMEOUT_MAX_SEC (seconds; operator ceiling applied to caller limits.maxWalltimeMs as cap×1000)" });
@@ -535,13 +518,13 @@ export function createResolveSpec(ctx) {
535
518
  ...(() => { const v = toolNameListFromBody(body.userInvokedSkills); return v ? { userInvokedSkills: v } : {}; })(),
536
519
  ...(parsedSettings.settings?.skillListingBudgetFraction !== undefined ? { skillListingBudgetFraction: parsedSettings.settings.skillListingBudgetFraction } : {}),
537
520
  ...(parsedSettings.settings?.skillListingMaxDescChars !== undefined ? { skillListingMaxDescChars: parsedSettings.settings.skillListingMaxDescChars } : {}),
538
- mcp: resolveRequestMcp(mcpForScenario(config.mcpServers, scenarioName), body.mcpServers, config, peerDesk, opts.lease, logger, opts?.onNotice !== undefined ? { sessionId: auth?.sessionId, emit: opts.onNotice } : undefined, storedToolAxes),
521
+ mcp: resolveRequestMcp(mcpForScenario(config.mcpServers, scenarioName), body.mcpServers, config, peerDesk, opts.lease, logger, opts?.onNotice !== undefined ? { sessionId: root, emit: opts.onNotice } : undefined, storedToolAxes),
539
522
  a2a: resolveRequestA2a(a2aForScenario(config.a2aPeers, scenarioName), a2aPeers, config, peerDesk, opts.lease, logger, opts?.leg === "fresh" ? "fresh" : "resume", storedToolAxes),
540
523
  toolPolicy: toolPolicyForHands(hands, durableEnabled
541
524
  ? createApprovalBaselinePolicy(config, {
542
525
  kind: "durable",
543
526
  question: liveQuestionFace,
544
- ...(approvalExemptionStore !== undefined && auth?.sessionId ? { exemption: createDeploymentListExemption(approvalExemptionStore, auth.sessionId, logger) } : {}),
527
+ ...(approvalExemptionStore !== undefined ? { exemption: createDeploymentListExemption(approvalExemptionStore, root, logger) } : {}),
545
528
  })
546
529
  : singleUserAutoAcceptBaselineApplies(config)
547
530
  ? createApprovalBaselinePolicy(config, { kind: "absent" })
@@ -568,7 +551,7 @@ export function createResolveSpec(ctx) {
568
551
  };
569
552
  return spec;
570
553
  };
571
- const foldGovernanceAndSettings = async (body, auth, spec, gated) => {
554
+ const foldGovernanceAndSettings = async (body, auth, root, spec, gated) => {
572
555
  const { acceptedAppend, parsedSettings } = gated;
573
556
  const hostSemanticsLane = !DEPLOYMENT_SHAPE_PREDICATES.sandboxPathAdjudication.holds(config);
574
557
  const laneHomeBase = () => {
@@ -577,7 +560,7 @@ export function createResolveSpec(ctx) {
577
560
  };
578
561
  const pathAdjudication = hostSemanticsLane
579
562
  ? (() => {
580
- const realRoot = realTaskRootOf(auth);
563
+ const realRoot = realTaskRootOf(root);
581
564
  const gateCwd = realRoot ?? join(config.localDataRoot ?? localRoot, "fs-write-gate-unrooted");
582
565
  return {
583
566
  env: new NodeExecutionEnv({ cwd: gateCwd }),
@@ -588,9 +571,9 @@ export function createResolveSpec(ctx) {
588
571
  })()
589
572
  : {
590
573
  env: new DeferredSandboxPathEnv({
591
- sessionId: auth?.sessionId,
574
+ sessionId: root,
592
575
  slots: sandboxPathEnvSlots,
593
- logger: { warn: (event, fields) => logger.warn(event, { ...(fields ?? {}), lane: config.remoteExec?.provider }) },
576
+ logger: { warn: (event, fields) => logger.warn(event, { ...(fields ?? {}), lane: config.remoteExec.provider }) },
594
577
  }),
595
578
  ...laneHomeBase(),
596
579
  };
@@ -598,18 +581,18 @@ export function createResolveSpec(ctx) {
598
581
  let governed = governedBase;
599
582
  let effectiveSettings = parsedSettings.settings;
600
583
  if (effectiveSettings?.outputStyle && acceptedAppend && acceptedAppend.length + 2 + effectiveSettings.outputStyle.length > MAX_SETTINGS_OUTPUT_STYLE_CHARS) {
601
- logger.warn("output_style_dropped", { detail: `combined append carriers exceed the ${MAX_SETTINGS_OUTPUT_STYLE_CHARS} cap (rider ${acceptedAppend.length} + style ${effectiveSettings.outputStyle.length}) — style dropped (pre-cap stored body on a resume leg?)`, sessionId: auth?.sessionId ?? null });
584
+ logger.warn("output_style_dropped", { detail: `combined append carriers exceed the ${MAX_SETTINGS_OUTPUT_STYLE_CHARS} cap (rider ${acceptedAppend.length} + style ${effectiveSettings.outputStyle.length}) — style dropped (pre-cap stored body on a resume leg?)`, sessionId: root });
602
585
  const { outputStyle: _dropped2, ...rest2 } = effectiveSettings;
603
586
  effectiveSettings = Object.keys(rest2).length > 0 ? rest2 : undefined;
604
587
  }
605
588
  const shellScratchpad = await acceptShellScratchpadDir(body.scratchpadDir, {
606
589
  requirePrincipal: config.requirePrincipal,
607
590
  hostSemanticsLane,
608
- warn: (msg, meta) => logger.warn(msg, { ...(meta ?? {}), sessionId: auth?.sessionId ?? null }),
591
+ warn: (msg, meta) => logger.warn(msg, { ...(meta ?? {}), sessionId: root }),
609
592
  });
610
593
  const scratchpadDir = shellScratchpad ??
611
- (hostSemanticsLane && auth?.sessionId
612
- ? await ensureScratchpadDir(config.localDataRoot ?? localRoot, auth.sessionId, (msg, meta) => logger.warn(msg, { ...(meta ?? {}), sessionId: auth.sessionId }))
594
+ (hostSemanticsLane
595
+ ? await ensureScratchpadDir(config.localDataRoot ?? localRoot, root, (msg, meta) => logger.warn(msg, { ...(meta ?? {}), sessionId: root }))
613
596
  : undefined);
614
597
  if (effectiveSettings) {
615
598
  const configRoot = executionConfigRootOf(config);
@@ -629,11 +612,11 @@ export function createResolveSpec(ctx) {
629
612
  }
630
613
  if (governed.selfOrchestration === true) {
631
614
  governed = tightenGoverned(governed, {
632
- toolPolicy: createWorkflowAskPolicy(approvalExemptionStore && auth?.sessionId
615
+ toolPolicy: createWorkflowAskPolicy(approvalExemptionStore
633
616
  ? async (toolName) => {
634
- const hit = await approvalExemptionStore.has(auth.sessionId, toolName);
617
+ const hit = await approvalExemptionStore.has(root, toolName);
635
618
  if (hit)
636
- logger.info("workflow_gate_exempted", { toolName, sessionId: auth.sessionId });
619
+ logger.info("workflow_gate_exempted", { toolName, sessionId: root });
637
620
  return hit;
638
621
  }
639
622
  : undefined),
@@ -641,40 +624,37 @@ export function createResolveSpec(ctx) {
641
624
  }
642
625
  return { governed, scratchpadDir, hostSemanticsLane };
643
626
  };
644
- const applyImageFactsAndRouting = async (body, auth, governed, folded) => {
627
+ const applyImageFactsAndRouting = async (body, auth, root, governed, folded) => {
645
628
  const { scenarioName, scratchpadDir, hostSemanticsLane } = folded;
646
629
  const bodyProfile = typeof body.sandboxImageProfile === "string" && body.sandboxImageProfile.length > 0 ? body.sandboxImageProfile : undefined;
647
- const taskImageProfile = bodyProfile ?? (body.cascade === true || body.verify === true ? undefined : sessionEnvSelection.get(auth?.sessionId));
630
+ const taskImageProfile = bodyProfile ?? (body.cascade === true || body.verify === true ? undefined : sessionEnvSelection.get(root));
648
631
  let resolvedImageCaps;
649
632
  if (taskImageProfile !== undefined) {
650
- if (config.remoteExec?.provider !== "k8s") {
633
+ if (config.remoteExec.provider !== "k8s") {
651
634
  throw createCodedHttpError(501, "capability.k8s_lane_required", "sandboxImageProfile is only supported on the k8s sandbox backend");
652
635
  }
653
636
  if (!imageIndex) {
654
637
  throw createCodedHttpError(501, "capability.image_index_required", "sandboxImageProfile requires the sandbox-image-pool, which needs a SQL store backend (DB_BACKEND=mysql|pg) — this deployment's store wires no image index");
655
638
  }
656
- if (!auth?.sessionId) {
657
- throw createCodedHttpError(400, "request.precondition_unmet", "sandboxImageProfile requires a resolved session");
658
- }
659
639
  const capsNeeded = Array.isArray(body.capabilitiesNeeded)
660
640
  ? body.capabilitiesNeeded.filter((c) => typeof c === "string")
661
641
  : undefined;
662
642
  const resolved = await resolveSandboxImageRef({
663
643
  profile: taskImageProfile,
664
644
  ...(capsNeeded && capsNeeded.length > 0 ? { capabilitiesNeeded: capsNeeded } : {}),
665
- viewer: { operator: explicitOperatorOk(auth.principal, config), tenantId: auth.principal ?? null },
645
+ viewer: { operator: explicitOperatorOk(auth?.principal, config), tenantId: auth?.principal ?? null },
666
646
  index: imageIndex,
667
647
  });
668
648
  if (!resolved.ok)
669
649
  throw createCodedHttpError(resolved.status, resolved.errorCode, resolved.message);
670
- perTaskImage.set(auth.sessionId, resolved.ref);
650
+ perTaskImage.set(root, resolved.ref);
671
651
  resolvedImageCaps = resolved.capabilities;
672
652
  }
673
653
  const remoteScratchpadDir = !hostSemanticsLane && DEPLOYMENT_SHAPE_PREDICATES.remoteScratchpad.holds(config)
674
- ? remoteScratchpadDirFor(auth?.sessionId)
654
+ ? remoteScratchpadDirFor(root)
675
655
  : undefined;
676
656
  const declaredScratchpadDir = scratchpadDir ?? remoteScratchpadDir;
677
- const pkgSourceLane = config.remoteExec?.provider === "e2b" || config.remoteExec?.provider === "k8s";
657
+ const pkgSourceLane = config.remoteExec.provider === "e2b" || config.remoteExec.provider === "k8s";
678
658
  const facts = buildEnvFacts({
679
659
  ...(declaredScratchpadDir ? { scratchpadDir: declaredScratchpadDir } : {}),
680
660
  ...(config.envFactsEnabled
@@ -683,7 +663,7 @@ export function createResolveSpec(ctx) {
683
663
  capabilities: resolvedImageCaps,
684
664
  ...(pkgSourceLane ? { pkgSource: config.sandboxPkgSource } : {}),
685
665
  egress: egressForRemoteExec(config.remoteExec),
686
- resumeFacts: resumeFactsForLane(config.remoteExec?.provider, config.remoteExec?.provider === "k8s" ? { k8sSnapshot: Boolean(config.remoteExec.s3Snapshot) } : undefined),
666
+ resumeFacts: resumeFactsForLane(config.remoteExec.provider, config.remoteExec.provider === "k8s" ? { k8sSnapshot: Boolean(config.remoteExec.s3Snapshot) } : undefined),
687
667
  }
688
668
  : {}),
689
669
  });
@@ -692,10 +672,10 @@ export function createResolveSpec(ctx) {
692
672
  if (config.routerEnabled) {
693
673
  const decision = routeServiceTask({
694
674
  vmIsolatedExecEnv: DEPLOYMENT_SHAPE_PREDICATES.vmIsolatedHands.holds(config),
695
- hasExecutionEnv: laneWiresExecutionEnv(executionLaneOf(config.remoteExec?.provider)),
675
+ hasExecutionEnv: laneWiresExecutionEnv(config.remoteExec.provider),
696
676
  ...(config.autonomy ? { autonomy: config.autonomy } : {}),
697
677
  });
698
- logger.info("orchestration_routed", { mode: decision.mode, reason: decision.reason, sessionId: auth?.sessionId ?? null });
678
+ logger.info("orchestration_routed", { mode: decision.mode, reason: decision.reason, sessionId: root });
699
679
  if (decision.mode === "supervisor") {
700
680
  return tightenGoverned(governed, supPostureOverrides());
701
681
  }
@@ -29,47 +29,16 @@
29
29
  * (车1 已实现)。lane **不补记**它们 —— 补记 = 「删了但审计没落地」的窗口重新打开。receipt 在本文件里
30
30
  * 只做两件事:二次确认(日志/指标)与「本轮到底动了多少」的读数。
31
31
  */
32
- import type { RetentionPolicy, RetentionReceipt } from "@sema-agent/core";
32
+ import type { RetentionPolicy } from "@sema-agent/core";
33
33
  import type { RetentionMode } from "../config-types.js";
34
- import type { EndedSpace, SpaceReclaimer } from "../workspace-space.js";
34
+ import type { SpaceReclaimer } from "../workspace-space.js";
35
+ import type { RetentionExecutor } from "../plugins/retention-deployment.js";
35
36
  /** 同 domain 连续失败多少次算「卡住了」(fail-loud 的阈值)。`5` 与 reaper 家族的
36
37
  * `REAPER_FAILURE_WARN_THRESHOLD` 同值同理由:一次抖动(一次重连、一次超时)正是容错要吸收的,
37
38
  * 只有**连败**才越过「可诊断」这条线。 */
38
39
  export declare const RETENTION_SWEEP_STUCK_THRESHOLD = 5;
39
40
  /** 租约 TTL = 本倍数 × sweep 间隔(设计稿 §3)。`2` = 允许一轮跑满一个完整间隔还有余量,再多就该让位。 */
40
41
  export declare const RETENTION_LEASE_TTL_FACTOR = 2;
41
- /**
42
- * lane 消费的**执行器**面 —— core `ManagedRetentionCapability` 的三方法 + 车1 的非契约窄读口
43
- * `previewRetention`(audit-only 档的读数源;core 契约无 count 面)+ 声明位。
44
- *
45
- * 🔴 三方法的入参是 core 契约形的**超集**(多一个 `audit`):车1 的店在运行期对缺席的审计上下文
46
- * fail-closed 抛错,所以这里把它写进类型 —— 让「忘了传」变成编译错,而不是一次运行期的破坏性调用被拒。
47
- */
48
- export interface RetentionExecutor {
49
- readonly retention?: "managed" | "none";
50
- listRetentionDomains(): Promise<readonly string[]>;
51
- previewRetention(input: {
52
- domain: string;
53
- cutoffMs: number;
54
- }): Promise<{
55
- checkpoints: number;
56
- sessions: number;
57
- toolResults: number;
58
- }>;
59
- expireCheckpoints(input: RetentionDestructiveInput): Promise<RetentionReceipt>;
60
- deleteExpiredSessions(input: RetentionDestructiveInput): Promise<RetentionSessionsReceipt>;
61
- deleteOrphanToolResults(input: RetentionDestructiveInput): Promise<RetentionReceipt>;
62
- }
63
- /** 破坏性调用的入参(判定时点的三格随行 —— 理由逐字见车1 `RetentionAuditContext` 的头注)。 */
64
- export interface RetentionDestructiveInput {
65
- domain: string;
66
- cutoffMs: number;
67
- audit: {
68
- mode: RetentionMode;
69
- policyDays: number;
70
- fencingToken: number | null;
71
- };
72
- }
73
42
  /** 非破坏性审计行的写口(lane 侧属主的那五个词)。 */
74
43
  export interface RetentionAuditSink {
75
44
  append(row: {
@@ -132,13 +101,6 @@ export interface RetentionSweepCtx {
132
101
  * (缓存卷、`space/` 快照、该会话停驻车道的快照一并回收)。它从不抛(失败 = 一行 + fail-open 计数);缺席 = 本部署没有可回收的东西。 */
133
102
  spaceReclaimer?: SpaceReclaimer;
134
103
  }
135
- /**
136
- * 会话树 sweep 的回执 = core 契约的 `RetentionReceipt` + 本仓一位:`endedSpaces` = 本次删掉的会话树里**结束了的空间**(会话 id + 住客空间键 = 会话化身;
137
- * 读不出住客的空化身不算),present-iff 非空。lane 把它交给空间的回收座(与会话删除协调器同一只),缓存卷与快照随空间的终结回收。
138
- */
139
- export type RetentionSessionsReceipt = RetentionReceipt & {
140
- readonly endedSpaces?: readonly EndedSpace[];
141
- };
142
104
  /** 一轮的读数(给日志与判据用;lane 自己不做任何决策依赖它)。 */
143
105
  export interface RetentionSweepOutcome {
144
106
  /** 本轮真正处理完的 domain 数(丢租中止时 = 中止之前那些)。 */
@@ -168,7 +130,7 @@ export interface RetentionSweepOutcome {
168
130
  * 为什么本道必须存在:引擎的门不拦
169
131
  * · 没锁时,执行器在场 × 一只 `"none"` 的店 —— 部署于是**广告了一个不执行的留存面**:能力位说
170
132
  * `{mode,maxAgeDays}`、审计表也在长,而那只店的行谁都没在删。
171
- * 本仓的 SQL 后端按同一个事实(扫车道开不开,`plugins/retention-store-sql.ts` 的 `retentionSweepRuns`)给它铸的三只店声明词,所以 lane 开着时
133
+ * 本仓的 SQL 后端按同一个事实(扫车道开不开,`plugins/retention-declaration.ts` 的 `retentionSweepRuns`)给它铸的三只店声明词,所以 lane 开着时
172
134
  * 这三只店在这一格上恒是 `managed`;这一格防的是声明与 lane 脱钩的店(别的后端、替身)。
173
135
  * 这些都在**启动期**拒(安全控件不得半开),不是让运维从一台"启动成功、什么也没删"的机器上猜。
174
136
  *