@sema-agent/server 7.145.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 (526) hide show
  1. package/MIGRATION.md +876 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +374 -99
  5. package/deploy/facts/CHANGES.json +25 -0
  6. package/deploy/facts/README.md +57 -0
  7. package/deploy/facts/lanes.json +61 -0
  8. package/deploy/facts/lanes.schema.json +57 -0
  9. package/deploy/facts/sandbox-rbac.json +113 -0
  10. package/deploy/facts/sandbox-rbac.schema.json +74 -0
  11. package/deploy/facts/sealed-key.json +9 -0
  12. package/deploy/facts/sealed-key.schema.json +52 -0
  13. package/deploy/sema-up/README.md +2 -2
  14. package/deploy/sema-up/chart/templates/_helpers.tpl +41 -0
  15. package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +47 -7
  16. package/deploy/sema-up/chart/templates/server-v4pro.yaml +9 -4
  17. package/deploy/sema-up/chart/templates/server.yaml +9 -4
  18. package/deploy/sema-up/chart/values.yaml +8 -1
  19. package/deploy/sema-up/cluster-up.sh +2 -1
  20. package/deploy/sema-up/lib/flagshape.sh +4 -0
  21. package/deploy/sema-up/lib/lanes.json +2 -5
  22. package/deploy/sema-up/sema-up.sh +12 -9
  23. package/deploy/sema-up/stack/compose.yaml +5 -4
  24. package/deploy/sema-up/stack/sema-stack-cluster.yaml +34 -17
  25. package/dist/adoption/import-limits.d.ts +6 -0
  26. package/dist/adoption/import-limits.js +7 -0
  27. package/dist/adoption/import.d.ts +62 -0
  28. package/dist/adoption/import.js +107 -0
  29. package/dist/adoption/wire.d.ts +52 -0
  30. package/dist/adoption/wire.js +9 -0
  31. package/dist/approval-ask-machine.d.ts +2 -2
  32. package/dist/approval-card.d.ts +7 -16
  33. package/dist/approval-card.js +0 -4
  34. package/dist/approval-gate-currency.d.ts +1 -1
  35. package/dist/approval-gate-currency.js +1 -1
  36. package/dist/approval-reconciler.d.ts +1 -1
  37. package/dist/approval.d.ts +3 -3
  38. package/dist/audit.js +2 -2
  39. package/dist/bench/s1/live-deps.js +3 -1
  40. package/dist/boot/crash-last.js +2 -1
  41. package/dist/boot/deployment-mods.d.ts +11 -1
  42. package/dist/boot/deployment-mods.js +15 -2
  43. package/dist/boot/device-lane.js +7 -5
  44. package/dist/boot/engine-lease.d.ts +195 -22
  45. package/dist/boot/engine-lease.js +146 -20
  46. package/dist/boot/execution-env.d.ts +5 -0
  47. package/dist/boot/execution-env.js +57 -33
  48. package/dist/boot/execution-lane.d.ts +37 -9
  49. package/dist/boot/execution-lane.js +74 -20
  50. package/dist/boot/exit-boundary.d.ts +50 -0
  51. package/dist/boot/exit-boundary.js +32 -0
  52. package/dist/boot/exit-last.d.ts +20 -4
  53. package/dist/boot/exit-last.js +23 -5
  54. package/dist/boot/governance-seams.d.ts +2 -2
  55. package/dist/boot/governance-seams.js +1 -0
  56. package/dist/boot/leader.js +1 -1
  57. package/dist/boot/memory-boundary.d.ts +11 -11
  58. package/dist/boot/memory-boundary.js +3 -3
  59. package/dist/boot/memory-consolidation.d.ts +42 -41
  60. package/dist/boot/memory-consolidation.js +26 -28
  61. package/dist/boot/org-memory.js +3 -2
  62. package/dist/boot/parked-revive-gate.d.ts +1 -1
  63. package/dist/boot/parked-revive-gate.js +1 -1
  64. package/dist/boot/reapers.d.ts +12 -4
  65. package/dist/boot/reapers.js +40 -16
  66. package/dist/boot/resolve-spec.d.ts +2 -0
  67. package/dist/boot/resolve-spec.js +126 -123
  68. package/dist/boot/retention-lane.d.ts +4 -42
  69. package/dist/boot/runner-deps.js +1 -1
  70. package/dist/boot/session-faces.d.ts +1 -0
  71. package/dist/boot/session-faces.js +11 -3
  72. package/dist/boot/shutdown.js +27 -9
  73. package/dist/boot/stage-01-config.d.ts +1 -1
  74. package/dist/boot/stage-01-config.js +7 -3
  75. package/dist/boot/stage-02-web-admin-pull.d.ts +1 -1
  76. package/dist/boot/stage-02-web-admin-pull.js +10 -8
  77. package/dist/boot/stage-03-store-backend.d.ts +2 -1
  78. package/dist/boot/stage-03-store-backend.js +2 -2
  79. package/dist/boot/stage-04-stores.d.ts +2 -1
  80. package/dist/boot/stage-05-execution-env.d.ts +4 -1
  81. package/dist/boot/stage-05-execution-env.js +6 -6
  82. package/dist/boot/stage-06-runners.d.ts +5 -2
  83. package/dist/boot/stage-06-runners.js +12 -13
  84. package/dist/boot/stage-07-capability-layer.d.ts +5 -2
  85. package/dist/boot/stage-07-capability-layer.js +7 -7
  86. package/dist/boot/stage-08-reapers.d.ts +5 -2
  87. package/dist/boot/stage-08-reapers.js +3 -3
  88. package/dist/boot/stage-09-leader.d.ts +6 -2
  89. package/dist/boot/stage-10-http-server.d.ts +6 -2
  90. package/dist/boot/stage-10-http-server.js +5 -3
  91. package/dist/boot/stores.d.ts +10 -0
  92. package/dist/boot/stores.js +53 -26
  93. package/dist/boot/web-admin.js +3 -3
  94. package/dist/boot/workflow-orchestration.d.ts +1 -1
  95. package/dist/boot/workflow-orchestration.js +2 -1
  96. package/dist/capabilities/center-plugins.d.ts +2 -0
  97. package/dist/capabilities/center-plugins.js +6 -2
  98. package/dist/capabilities/composite-members.d.ts +4 -1
  99. package/dist/capabilities/composite-members.js +4 -1
  100. package/dist/capabilities/execution-lane.d.ts +7 -7
  101. package/dist/capabilities/execution-lane.js +2 -2
  102. package/dist/capabilities/hands-lane.d.ts +1 -1
  103. package/dist/capabilities/scenarios.d.ts +34 -20
  104. package/dist/capabilities/scenarios.js +13 -9
  105. package/dist/capabilities/settings-contract.d.ts +29 -0
  106. package/dist/capabilities/settings-contract.js +14 -0
  107. package/dist/capabilities/skills.d.ts +5 -5
  108. package/dist/capability-facts.d.ts +56 -1
  109. package/dist/capability-facts.js +59 -8
  110. package/dist/center-credential-renewer.js +3 -2
  111. package/dist/checkpoint-ctx-seal-m28.d.ts +1 -1
  112. package/dist/config-catalog.js +19 -9
  113. package/dist/config-invariants.d.ts +18 -3
  114. package/dist/config-invariants.js +36 -19
  115. package/dist/config-lkg.d.ts +1 -1
  116. package/dist/config-lkg.js +5 -6
  117. package/dist/config-provider.d.ts +2 -2
  118. package/dist/config-provider.js +2 -0
  119. package/dist/config-types.d.ts +228 -185
  120. package/dist/config.d.ts +74 -6
  121. package/dist/config.js +146 -64
  122. package/dist/degenerate-instrument.js +1 -1
  123. package/dist/deleted-session-ids.d.ts +19 -0
  124. package/dist/deleted-session-ids.js +26 -0
  125. package/dist/deploy-facts.d.ts +155 -0
  126. package/dist/deploy-facts.js +95 -0
  127. package/dist/deployment-shape.d.ts +21 -12
  128. package/dist/deployment-shape.js +24 -6
  129. package/dist/device-ws-hub.d.ts +48 -3
  130. package/dist/device-ws-hub.js +48 -2
  131. package/dist/env-facts.d.ts +7 -5
  132. package/dist/env-facts.js +10 -6
  133. package/dist/error-code-family.d.ts +35 -0
  134. package/dist/error-code-family.js +26 -0
  135. package/dist/execution-config-root.d.ts +5 -5
  136. package/dist/execution-config-root.js +5 -5
  137. package/dist/execution-env-purpose.d.ts +14 -0
  138. package/dist/execution-env-purpose.js +29 -0
  139. package/dist/execution-lane-caps.d.ts +49 -86
  140. package/dist/execution-lane-caps.js +52 -62
  141. package/dist/execution-placement.d.ts +18 -2
  142. package/dist/execution-placement.js +19 -0
  143. package/dist/file-history-disclosure.d.ts +2 -2
  144. package/dist/fleet/drain-entry.d.ts +46 -3
  145. package/dist/fleet/drain-entry.js +6 -0
  146. package/dist/fleet/fleet-bus.d.ts +2 -1
  147. package/dist/fleet/serving-lease.js +3 -4
  148. package/dist/history-anchor.d.ts +22 -0
  149. package/dist/history-anchor.js +14 -0
  150. package/dist/hooks/branch-transcript.d.ts +1 -1
  151. package/dist/hooks/branch-transcript.js +1 -0
  152. package/dist/hooks/classic-stations.d.ts +25 -8
  153. package/dist/hooks/classic-stations.js +29 -3
  154. package/dist/hooks/command-spawn.d.ts +1 -4
  155. package/dist/hooks/command-spawn.js +0 -11
  156. package/dist/hooks/hook-runner.d.ts +85 -24
  157. package/dist/hooks/hook-runner.js +326 -109
  158. package/dist/hooks/hook-source.d.ts +14 -2
  159. package/dist/hooks/hook-source.js +8 -0
  160. package/dist/http/active-run-conflict.d.ts +1 -1
  161. package/dist/http/active-run-conflict.js +1 -1
  162. package/dist/http/admission.js +11 -1
  163. package/dist/http/approval-sweeps.d.ts +2 -5
  164. package/dist/http/approval-sweeps.js +3 -2
  165. package/dist/http/checkpoint-ctx.d.ts +76 -71
  166. package/dist/http/checkpoint-ctx.js +40 -40
  167. package/dist/http/claim-latency.d.ts +10 -0
  168. package/dist/http/claim-latency.js +12 -0
  169. package/dist/http/dispatch.js +19 -3
  170. package/dist/http/durable-run-leg.d.ts +5 -0
  171. package/dist/http/durable-run-leg.js +3 -1
  172. package/dist/http/execution-context.d.ts +7 -1
  173. package/dist/http/execution-context.js +13 -0
  174. package/dist/http/health-self-report.d.ts +6 -2
  175. package/dist/http/health-self-report.js +3 -2
  176. package/dist/http/memory-compliance-failure-reply.d.ts +2 -2
  177. package/dist/http/memory-compliance-failure-reply.js +5 -15
  178. package/dist/http/memory-control-plane-corrupt-reply.d.ts +25 -0
  179. package/dist/http/memory-control-plane-corrupt-reply.js +19 -0
  180. package/dist/http/memory-store-refusal-reply.d.ts +3 -3
  181. package/dist/http/memory-store-refusal-reply.js +3 -0
  182. package/dist/http/owner-access.d.ts +11 -0
  183. package/dist/http/owner-access.js +7 -4
  184. package/dist/http/principal-gate.d.ts +28 -16
  185. package/dist/http/principal-gate.js +10 -19
  186. package/dist/http/request-guards.d.ts +2 -2
  187. package/dist/http/request-guards.js +5 -5
  188. package/dist/http/resume-legs.d.ts +29 -10
  189. package/dist/http/resume-legs.js +94 -56
  190. package/dist/http/rewind-files-reply.d.ts +34 -0
  191. package/dist/http/rewind-files-reply.js +36 -0
  192. package/dist/http/route-ctx.d.ts +43 -26
  193. package/dist/http/route-table.js +4 -0
  194. package/dist/http/routes/adoption.d.ts +11 -0
  195. package/dist/http/routes/adoption.js +80 -6
  196. package/dist/http/routes/agents-roster.js +1 -0
  197. package/dist/http/routes/approvals-assistant.js +7 -26
  198. package/dist/http/routes/background.js +1 -0
  199. package/dist/http/routes/capabilities.js +12 -3
  200. package/dist/http/routes/devices.js +1 -1
  201. package/dist/http/routes/diagnostics.d.ts +9 -14
  202. package/dist/http/routes/diagnostics.js +10 -20
  203. package/dist/http/routes/engine.d.ts +31 -0
  204. package/dist/http/routes/engine.js +81 -0
  205. package/dist/http/routes/memory-bundle.js +3 -0
  206. package/dist/http/routes/memory-consolidation.js +3 -5
  207. package/dist/http/routes/memory-origin.d.ts +2 -2
  208. package/dist/http/routes/memory-origin.js +2 -4
  209. package/dist/http/routes/memory-policy.js +5 -1
  210. package/dist/http/routes/notify-wake.js +2 -1
  211. package/dist/http/routes/observability.js +3 -6
  212. package/dist/http/routes/projects.d.ts +70 -0
  213. package/dist/http/routes/projects.js +86 -0
  214. package/dist/http/routes/rules.js +30 -2
  215. package/dist/http/routes/runs.js +15 -11
  216. package/dist/http/routes/session-sync.js +39 -35
  217. package/dist/http/routes/sessions-list.d.ts +1 -1
  218. package/dist/http/routes/sessions.d.ts +7 -1
  219. package/dist/http/routes/sessions.js +108 -2
  220. package/dist/http/routes/tasks.js +32 -8
  221. package/dist/http/routes/trace-usage.js +1 -1
  222. package/dist/http/run-concurrency-cap.d.ts +86 -0
  223. package/dist/http/run-concurrency-cap.js +54 -0
  224. package/dist/http/server.d.ts +31 -14
  225. package/dist/http/server.js +29 -3
  226. package/dist/http/stored-body-replay.d.ts +12 -7
  227. package/dist/http/stored-body-replay.js +28 -5
  228. package/dist/http/wire-types.d.ts +27 -13
  229. package/dist/index.d.ts +2 -2
  230. package/dist/index.js +1 -1
  231. package/dist/instruction-source-notice.d.ts +1 -1
  232. package/dist/json-body-limit.d.ts +8 -0
  233. package/dist/json-body-limit.js +2 -0
  234. package/dist/leader/diffout.d.ts +1 -1
  235. package/dist/local-data-root.d.ts +2 -2
  236. package/dist/memory-embedder-reembed.d.ts +38 -0
  237. package/dist/memory-embedder-reembed.js +20 -0
  238. package/dist/memory-incident-sink.d.ts +0 -28
  239. package/dist/memory-incident-sink.js +5 -0
  240. package/dist/memory-operator-faces.d.ts +9 -4
  241. package/dist/memory-scope-stores.d.ts +9 -7
  242. package/dist/memory-scope-stores.js +3 -14
  243. package/dist/memory-scope.d.ts +38 -2
  244. package/dist/memory-scope.js +33 -2
  245. package/dist/memory-store-refusal.d.ts +17 -4
  246. package/dist/memory-store-refusal.js +1 -1
  247. package/dist/memory-sync-client.d.ts +2 -0
  248. package/dist/memory-sync-client.js +13 -11
  249. package/dist/memory-sync.js +1 -1
  250. package/dist/model-compat.d.ts +35 -21
  251. package/dist/model-compat.js +49 -21
  252. package/dist/model-entry-refusal.d.ts +11 -1
  253. package/dist/model-entry-refusal.js +7 -0
  254. package/dist/namespaced-rule-name.d.ts +18 -1
  255. package/dist/namespaced-rule-name.js +12 -0
  256. package/dist/net-address.d.ts +53 -0
  257. package/dist/net-address.js +111 -0
  258. package/dist/observability/fail-open.d.ts +29 -17
  259. package/dist/observability/fail-open.js +29 -17
  260. package/dist/observability/metrics.d.ts +2 -0
  261. package/dist/observability/metrics.js +2 -0
  262. package/dist/observability/secret-env-scrub.d.ts +30 -4
  263. package/dist/observability/secret-env-scrub.js +15 -3
  264. package/dist/orchestration/workflow-agent-session-index.d.ts +7 -12
  265. package/dist/orchestration/workflow-agent-session-index.js +1 -6
  266. package/dist/orchestration/workflow-completion-inbox.d.ts +26 -6
  267. package/dist/orchestration/workflow-completion-inbox.js +63 -45
  268. package/dist/orchestration/workflow-notify-journal.js +2 -3
  269. package/dist/org-delivery-gate.js +1 -1
  270. package/dist/org-memory-admission.d.ts +5 -2
  271. package/dist/org-memory-admission.js +25 -10
  272. package/dist/parked-decide.d.ts +33 -26
  273. package/dist/parked-decide.js +36 -44
  274. package/dist/peer-directory.d.ts +6 -12
  275. package/dist/peer-directory.js +5 -1
  276. package/dist/plugins/approval-ask-store-file.d.ts +10 -2
  277. package/dist/plugins/approval-ask-store-file.js +37 -4
  278. package/dist/plugins/approval-ask-store-memory.d.ts +5 -3
  279. package/dist/plugins/approval-ask-store-memory.js +11 -2
  280. package/dist/plugins/approval-ask-store-sql.d.ts +3 -0
  281. package/dist/plugins/approval-ask-store-sql.js +3 -1
  282. package/dist/plugins/blob-backend.d.ts +38 -195
  283. package/dist/plugins/blob-backend.js +33 -229
  284. package/dist/plugins/caching-session-store.d.ts +12 -5
  285. package/dist/plugins/caching-session-store.js +3 -0
  286. package/dist/plugins/checkpoint-index-columns.d.ts +1 -1
  287. package/dist/plugins/checkpoint-index-columns.js +3 -2
  288. package/dist/plugins/checkpoint-store-face.d.ts +426 -0
  289. package/dist/plugins/checkpoint-store-face.js +152 -0
  290. package/dist/plugins/device-store-sql.d.ts +2 -2
  291. package/dist/plugins/device-store-sql.js +5 -10
  292. package/dist/plugins/execution-lane-rename-m40.d.ts +20 -0
  293. package/dist/plugins/execution-lane-rename-m40.js +10 -0
  294. package/dist/plugins/execution-placement-sql.d.ts +63 -88
  295. package/dist/plugins/execution-placement-sql.js +94 -54
  296. package/dist/plugins/file-run-store.d.ts +26 -18
  297. package/dist/plugins/file-run-store.js +64 -75
  298. package/dist/plugins/fork-routing-session-store.d.ts +6 -2
  299. package/dist/plugins/fork-routing-session-store.js +2 -2
  300. package/dist/plugins/imported-layer-root-retirement.d.ts +22 -11
  301. package/dist/plugins/imported-layer-root-retirement.js +4 -8
  302. package/dist/plugins/inbox-payload-column.d.ts +14 -0
  303. package/dist/plugins/inbox-payload-column.js +13 -0
  304. package/dist/plugins/local-checkpoint-store.d.ts +7 -2
  305. package/dist/plugins/local-checkpoint-store.js +13 -8
  306. package/dist/plugins/local-data-dir-modes-m39.d.ts +48 -0
  307. package/dist/plugins/local-data-dir-modes-m39.js +182 -0
  308. package/dist/plugins/local-engine-high-water.d.ts +11 -0
  309. package/dist/plugins/local-engine-high-water.js +59 -0
  310. package/dist/plugins/local-session-store.d.ts +119 -30
  311. package/dist/plugins/local-session-store.js +156 -53
  312. package/dist/plugins/local-task-attachment-store.d.ts +2 -0
  313. package/dist/plugins/local-task-attachment-store.js +10 -11
  314. package/dist/plugins/memory-embedder-fingerprint.d.ts +33 -10
  315. package/dist/plugins/memory-embedder-fingerprint.js +52 -12
  316. package/dist/plugins/memory-embedder.d.ts +1 -1
  317. package/dist/plugins/memory-embedder.js +2 -2
  318. package/dist/plugins/memory-engine-pg.d.ts +30 -6
  319. package/dist/plugins/memory-engine-pg.js +96 -214
  320. package/dist/plugins/memory-engine-sql-apply.d.ts +130 -0
  321. package/dist/plugins/memory-engine-sql-apply.js +358 -0
  322. package/dist/plugins/memory-engine-tidb.d.ts +38 -9
  323. package/dist/plugins/memory-engine-tidb.js +99 -230
  324. package/dist/plugins/memory-key-guards.d.ts +1 -1
  325. package/dist/plugins/memory-origin-law.d.ts +3 -3
  326. package/dist/plugins/one-time-migrations.d.ts +169 -83
  327. package/dist/plugins/one-time-migrations.js +295 -235
  328. package/dist/plugins/owner-only-file-mode.d.ts +29 -0
  329. package/dist/plugins/owner-only-file-mode.js +141 -0
  330. package/dist/plugins/permission-rule-store-file.d.ts +17 -3
  331. package/dist/plugins/permission-rule-store-file.js +20 -1
  332. package/dist/plugins/pg-pool.d.ts +2 -1
  333. package/dist/plugins/pg-pool.js +12 -5
  334. package/dist/plugins/release-version.d.ts +20 -0
  335. package/dist/plugins/release-version.js +28 -0
  336. package/dist/plugins/remote-env-adb.d.ts +20 -4
  337. package/dist/plugins/remote-env-adb.js +39 -11
  338. package/dist/plugins/remote-env-e2b.d.ts +12 -3
  339. package/dist/plugins/remote-env-e2b.js +6 -4
  340. package/dist/plugins/remote-env-host.d.ts +9 -1
  341. package/dist/plugins/remote-env-host.js +6 -5
  342. package/dist/plugins/remote-env-k8s.d.ts +5 -2
  343. package/dist/plugins/remote-env-k8s.js +15 -4
  344. package/dist/plugins/remote-env-local-docker.d.ts +4 -1
  345. package/dist/plugins/remote-env-local-docker.js +3 -3
  346. package/dist/plugins/remote-env-ssh.d.ts +8 -2
  347. package/dist/plugins/remote-env-ssh.js +26 -24
  348. package/dist/plugins/remote-shell.d.ts +59 -30
  349. package/dist/plugins/remote-shell.js +175 -62
  350. package/dist/plugins/retention-declaration.d.ts +37 -0
  351. package/dist/plugins/retention-declaration.js +9 -0
  352. package/dist/plugins/retention-deployment.d.ts +126 -0
  353. package/dist/plugins/retention-deployment.js +88 -0
  354. package/dist/plugins/retention-lane-store-sql.d.ts +74 -4
  355. package/dist/plugins/retention-lane-store-sql.js +103 -1
  356. package/dist/plugins/retention-sql.d.ts +29 -0
  357. package/dist/plugins/retention-sql.js +8 -0
  358. package/dist/plugins/run-store-sql.js +2 -2
  359. package/dist/plugins/schema-consistency.d.ts +0 -6
  360. package/dist/plugins/schema-consistency.js +1 -2
  361. package/dist/plugins/schema-ensure-legs.d.ts +1 -1
  362. package/dist/plugins/schema-ensure-legs.js +13 -3
  363. package/dist/plugins/session-ext-table.d.ts +74 -0
  364. package/dist/plugins/session-ext-table.js +121 -0
  365. package/dist/plugins/session-fork.d.ts +31 -9
  366. package/dist/plugins/session-fork.js +3 -2
  367. package/dist/plugins/session-placement.d.ts +4 -2
  368. package/dist/plugins/session-row-sql.d.ts +8 -7
  369. package/dist/plugins/session-row-sql.js +15 -7
  370. package/dist/plugins/session-store-sql.d.ts +131 -0
  371. package/dist/plugins/session-store-sql.js +298 -0
  372. package/dist/plugins/session-workspace-cell.d.ts +2 -2
  373. package/dist/plugins/session-workspace-cell.js +2 -2
  374. package/dist/plugins/shared-memory-store-sql.d.ts +10 -0
  375. package/dist/plugins/shared-memory-store-sql.js +13 -13
  376. package/dist/plugins/snapshot-bucket-presence.js +1 -1
  377. package/dist/plugins/sql-driver.d.ts +23 -7
  378. package/dist/plugins/sql-driver.js +41 -8
  379. package/dist/plugins/sql-errors.d.ts +5 -2
  380. package/dist/plugins/sql-errors.js +4 -0
  381. package/dist/plugins/sql-json-column.d.ts +5 -1
  382. package/dist/plugins/store-backend.d.ts +46 -16
  383. package/dist/plugins/store-backend.js +192 -69
  384. package/dist/plugins/store-contracts.d.ts +10 -13
  385. package/dist/plugins/store-contracts.js +1 -9
  386. package/dist/plugins/store-sweep.d.ts +63 -0
  387. package/dist/plugins/store-sweep.js +48 -0
  388. package/dist/plugins/task-attachment-store.d.ts +6 -8
  389. package/dist/plugins/task-attachment-store.js +15 -10
  390. package/dist/plugins/task-list-store-sql.d.ts +1 -1
  391. package/dist/plugins/text-column-capacity.d.ts +21 -0
  392. package/dist/plugins/text-column-capacity.js +5 -0
  393. package/dist/plugins/tidb-pool.d.ts +3 -2
  394. package/dist/plugins/tidb-pool.js +20 -32
  395. package/dist/plugins/user-input-ledger-sql.d.ts +1 -1
  396. package/dist/prompt-screen.d.ts +6 -9
  397. package/dist/prompt-screen.js +2 -5
  398. package/dist/read-face-posture.d.ts +6 -6
  399. package/dist/read-face-posture.js +2 -2
  400. package/dist/request-value-closure.d.ts +5 -5
  401. package/dist/request-value-closure.js +1 -1
  402. package/dist/rules-consent.d.ts +48 -27
  403. package/dist/rules-consent.js +147 -23
  404. package/dist/run-cancel-context.d.ts +4 -1
  405. package/dist/run-cancel-context.js +2 -1
  406. package/dist/run-local.js +17 -13
  407. package/dist/runs.d.ts +48 -30
  408. package/dist/runs.js +27 -17
  409. package/dist/runtime-caps-resolver.d.ts +15 -8
  410. package/dist/runtime-caps-resolver.js +14 -10
  411. package/dist/sandbox-egress-policy.js +6 -11
  412. package/dist/sandbox-rbac-rules.d.ts +88 -0
  413. package/dist/sandbox-rbac-rules.js +80 -0
  414. package/dist/sealed-key-layout.d.ts +16 -0
  415. package/dist/sealed-key-layout.js +3 -0
  416. package/dist/sealed-key.js +8 -6
  417. package/dist/security.d.ts +43 -9
  418. package/dist/security.js +9 -2
  419. package/dist/sema-config-dir.js +2 -2
  420. package/dist/server-secret-env.d.ts +2 -0
  421. package/dist/service-version.d.ts +2 -1
  422. package/dist/service-version.js +2 -2
  423. package/dist/session-error-wire.d.ts +1 -1
  424. package/dist/session-incarnation.d.ts +8 -5
  425. package/dist/session-notify-door.d.ts +5 -3
  426. package/dist/session-resident-background.d.ts +110 -0
  427. package/dist/session-resident-background.js +88 -0
  428. package/dist/session-row.d.ts +1 -1
  429. package/dist/session-sync-kernel.d.ts +53 -14
  430. package/dist/session-sync-kernel.js +70 -1
  431. package/dist/session-sync.d.ts +5 -3
  432. package/dist/session-workspace.d.ts +12 -2
  433. package/dist/session-workspace.js +6 -0
  434. package/dist/sighup-idle.d.ts +9 -7
  435. package/dist/sighup-idle.js +4 -5
  436. package/dist/spec-fields.d.ts +16 -0
  437. package/dist/spec-fields.js +7 -0
  438. package/dist/store-posture.d.ts +2 -1
  439. package/dist/stored-request-env-credentials-m38.d.ts +3 -0
  440. package/dist/stored-request-env-credentials-m38.js +8 -0
  441. package/dist/stored-request-hooks-m20.d.ts +3 -2
  442. package/dist/stored-request-hooks-m20.js +19 -14
  443. package/dist/stored-request-prompt-profile-m30.d.ts +1 -1
  444. package/dist/stores-sql/blob-index-sql.d.ts +148 -0
  445. package/dist/stores-sql/blob-index-sql.js +154 -0
  446. package/dist/{plugins → stores-sql}/checkpoint-store-sql.d.ts +14 -428
  447. package/dist/{plugins → stores-sql}/checkpoint-store-sql.js +43 -220
  448. package/dist/{plugins → stores-sql}/file-history-store-sql.d.ts +23 -11
  449. package/dist/{plugins → stores-sql}/file-history-store-sql.js +23 -18
  450. package/dist/{plugins → stores-sql}/mailbox-store-sql.d.ts +2 -2
  451. package/dist/{plugins → stores-sql}/mailbox-store-sql.js +4 -4
  452. package/dist/{plugins → stores-sql}/pg-session-storage.d.ts +27 -67
  453. package/dist/{plugins → stores-sql}/pg-session-storage.js +82 -207
  454. package/dist/{plugins → stores-sql}/retention-store-sql.d.ts +123 -217
  455. package/dist/{plugins → stores-sql}/retention-store-sql.js +66 -190
  456. package/dist/{plugins → stores-sql}/roster-store-sql.d.ts +2 -2
  457. package/dist/{plugins → stores-sql}/roster-store-sql.js +1 -1
  458. package/dist/{plugins → stores-sql}/session-event-payload.d.ts +1 -1
  459. package/dist/{plugins → stores-sql}/session-event-payload.js +1 -1
  460. package/dist/stores-sql/session-policy-store-sql.d.ts +1 -1
  461. package/dist/stores-sql/session-write-hooks.d.ts +59 -0
  462. package/dist/stores-sql/session-write-hooks.js +2 -0
  463. package/dist/{plugins → stores-sql}/tidb-session-storage.d.ts +10 -11
  464. package/dist/{plugins → stores-sql}/tidb-session-storage.js +10 -21
  465. package/dist/{plugins → stores-sql}/tidb-session-store.d.ts +35 -112
  466. package/dist/{plugins → stores-sql}/tidb-session-store.js +73 -169
  467. package/dist/{plugins → stores-sql}/tool-result-store-sql.d.ts +3 -3
  468. package/dist/{plugins → stores-sql}/tool-result-store-sql.js +6 -6
  469. package/dist/stores-sql/windowed-session-storage.d.ts +56 -0
  470. package/dist/stores-sql/windowed-session-storage.js +61 -0
  471. package/dist/{plugins → stores-sql}/workflow-journal-store-sql.d.ts +7 -12
  472. package/dist/{plugins → stores-sql}/workflow-journal-store-sql.js +3 -8
  473. package/dist/task-a2a.d.ts +7 -1
  474. package/dist/task-a2a.js +15 -14
  475. package/dist/task-cwd.d.ts +11 -3
  476. package/dist/task-cwd.js +17 -1
  477. package/dist/task-mcp.d.ts +10 -2
  478. package/dist/task-mcp.js +13 -16
  479. package/dist/task-settings.d.ts +68 -8
  480. package/dist/task-settings.js +63 -6
  481. package/dist/tool-approval.d.ts +23 -10
  482. package/dist/tool-approval.js +10 -6
  483. package/dist/trace/core-keyset-guard.d.ts +17 -10
  484. package/dist/trace/engine-notice-wire.d.ts +1 -1
  485. package/dist/trace/engine-notice-wire.js +4 -0
  486. package/dist/trace/exit-seat.d.ts +29 -1
  487. package/dist/trace/exit-seat.js +4 -0
  488. package/dist/trace/project.d.ts +33 -16
  489. package/dist/trace/project.js +21 -9
  490. package/dist/trace/redact.d.ts +13 -2
  491. package/dist/trace/redact.js +347 -78
  492. package/dist/trace/self-minted-wire.d.ts +587 -16
  493. package/dist/trace/self-minted-wire.js +215 -9
  494. package/dist/trace/sema-provenance.d.ts +45 -41
  495. package/dist/trace/sema-provenance.js +81 -10
  496. package/dist/trace/task-notification-facets.d.ts +70 -2
  497. package/dist/trace/task-notification-facets.js +71 -1
  498. package/dist/trace/wire-projection-faces.d.ts +39 -3
  499. package/dist/trace/wire-projection-faces.js +27 -2
  500. package/dist/unread-request-members.d.ts +66 -0
  501. package/dist/unread-request-members.js +41 -0
  502. package/dist/usage-analytics.d.ts +4 -0
  503. package/dist/user-input-ledger.d.ts +2 -2
  504. package/dist/web-admin-client/apply-effective.js +22 -26
  505. package/dist/web-admin-client/candidate-gate.d.ts +35 -3
  506. package/dist/web-admin-client/candidate-gate.js +53 -5
  507. package/dist/web-admin-client/center-request.d.ts +4 -1
  508. package/dist/web-admin-client/center-request.js +2 -1
  509. package/dist/web-admin-client/effective-keys.js +0 -1
  510. package/dist/web-admin-client/facade.d.ts +1 -1
  511. package/dist/web-admin-client/http-client.d.ts +1 -0
  512. package/dist/web-admin-client/http-client.js +17 -9
  513. package/dist/web-admin-client/restart-signal.js +5 -2
  514. package/dist/web-admin-client/skills-mcp.d.ts +20 -6
  515. package/dist/web-admin-client/skills-mcp.js +26 -21
  516. package/dist/web-admin-client/types.d.ts +34 -49
  517. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +2 -2
  518. package/package.json +22 -13
  519. package/scripts/drain-check-local.mjs +8 -55
  520. package/scripts/drain-check.mysql.sql +3 -40
  521. package/scripts/drain-check.pg.sql +3 -40
  522. package/skills/update-config.md +1 -1
  523. package/wire-changes/server@7.146.0.json +3221 -0
  524. package/wire-changes/server@7.147.0.json +813 -0
  525. package/dist/approval-batch-census.d.ts +0 -27
  526. package/dist/approval-batch-census.js +0 -27
@@ -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";
@@ -13,7 +13,7 @@ import { assertGuardPatternsUsable, buildApprovalGrantNotice, buildOnlySensitive
13
13
  import { createDeploymentListExemption, gateIntentUnserviceableReason, singleUserAutoAcceptBaselineApplies } from "../approval.js";
14
14
  import { acceptShellScratchpadDir, buildEnvFacts, egressForRemoteExec, ensureScratchpadDir, resumeFactsForLane, scratchpadCoveringTaskRoot } from "../env-facts.js";
15
15
  import { FleetEventBus } from "../fleet/fleet-bus.js";
16
- import { createSettingsHooksRegistration, settingsHooksBudgetMs } from "../hooks/hook-runner.js";
16
+ import { createSettingsHooksRegistrations, settingsHooksBudgetMs } from "../hooks/hook-runner.js";
17
17
  import { HOST_POSTURE_REFUSED_CODE, permissionModeWriteFaceRefusal, taskInheritEnvRefusal } from "../hosted-posture.js";
18
18
  import { headerStr } from "../http/principal-gate.js";
19
19
  import { explicitOperatorOk } from "../http/server.js";
@@ -27,13 +27,14 @@ 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";
33
34
  import { createMemoryProjectLayers } from "../memory-project-layer.js";
34
35
  import { inheritEnvFacts, inheritEnvFieldIssue, singleMemberOffFieldIssue } from "../request-value-closure.js";
35
36
  import { a2aForScenario, mcpForScenario } from "../web-admin-client/facade.js";
36
- import { normalizeAttachments, normalizeResilience, normalizeResumeAtMode, normalizeSuggestNextPrompts, promptLeanSpecFragment, resolveTaskLimits, retainBackgroundProcessesFromBody, taskAgentsSpecFragment, toolMaterializeStrategyFromBody, allowToolsSpecFragment, toolNameListFromBody } from "../spec-fields.js";
37
+ import { compactionSpecFragment, normalizeAttachments, normalizeResilience, normalizeResumeAtMode, normalizeSuggestNextPrompts, promptLeanSpecFragment, resolveTaskLimits, retainBackgroundProcessesFromBody, taskAgentsSpecFragment, toolMaterializeStrategyFromBody, allowToolsSpecFragment, toolNameListFromBody } from "../spec-fields.js";
37
38
  import { isAbsoluteHostPath } from "@sema-agent/settings-schema";
38
39
  import { effectiveHostWorkspace, parseAdditionalDirectories, satisfiedByProcessCwd, shellEnvMismatchCount } from "../task-cwd.js";
39
40
  import { DEPLOYMENT_SHAPE_PREDICATES } from "../deployment-shape.js";
@@ -43,7 +44,9 @@ import { assertRequestMcpEntries, assertRequestMcpUnlocked, resolveRequestMcp }
43
44
  import { GOVERNANCE_HTTP_STATUS } from "../governance-http-status.js";
44
45
  import { storedToolAxesRereadM19 } from "../stored-request-tool-axes-m19.js";
45
46
  import { storedHooksRereadM20 } from "../stored-request-hooks-m20.js";
46
- import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, REQUEST_SETTINGS_REFUSAL_PREFIX, SETTINGS_RULE_REFUSAL_CODE, SettingsRuleRefusalError, acceptAppendSystemPrompt, applyTaskSettings, createWorkflowAskPolicy, effectivePermissionMode, effectiveThinking, parseTaskSettings, taskHooksHonored, settingsPermissionBucketIssue } from "../task-settings.js";
47
+ import { storedEnvCredentialsDropM38 } from "../stored-request-env-credentials-m38.js";
48
+ import { serverCredentialValueSources } from "../server-secret-env.js";
49
+ import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, REQUEST_SETTINGS_REFUSAL_PREFIX, SETTINGS_RULE_REFUSAL_CODE, SettingsRuleRefusalError, acceptAppendSystemPrompt, applyTaskSettings, createWorkflowAskPolicy, effectivePermissionMode, effectiveThinking, parseTaskSettings, readSettingsEnv, taskHooksHonored, settingsEnvCredentialIssue, settingsPermissionBucketIssue, withoutKeys } from "../task-settings.js";
47
50
  import { tightenOnlySeatIssue } from "../tighten-only-seats.js";
48
51
  import { entryProblemsFacts } from "../entry-problems.js";
49
52
  import { inertToolListEntryOf } from "../rule-entry-list.js";
@@ -59,7 +62,7 @@ function unrooted(spec) {
59
62
  return resolved;
60
63
  }
61
64
  export function createResolveSpec(ctx) {
62
- const { config, logger, metrics, localRoot, scenarios, principalCaps, centerRuntimeCapsResolver, getKeyResolver, taskAttachmentStore, perSessionCwd, setSessionCwd, setSessionShellEnv, fenceSessionOwner, hookLlm, hookAgent, fleetBus, hookWakeBus, resumeAnchorStore, ownerAware, taskLimitCaps, taskTimeoutSec, selectEnvTool, sendUserFileToolSpec, memoryEngine, memorySyncRunner, durableEnabled, approvalExemptionStore, checkpointStore, imageIndex, perTaskImage, sessionEnvSelection, liveQuestionFace, approverSeat, lockedKeys, loadedSkills, peerDesk, } = ctx;
65
+ const { config, logger, metrics, localRoot, scenarios, principalCaps, centerRuntimeCapsResolver, getKeyResolver, taskAttachmentStore, perSessionCwd, setSessionCwd, setSessionShellEnv, fenceSessionOwner, hookLlm, hookAgent, belowTaskChainPatterns, fleetBus, hookWakeBus, resumeAnchorStore, ownerAware, taskLimitCaps, taskTimeoutSec, selectEnvTool, sendUserFileToolSpec, memoryEngine, memorySyncRunner, durableEnabled, approvalExemptionStore, checkpointStore, imageIndex, perTaskImage, sessionEnvSelection, liveQuestionFace, approverSeat, lockedKeys, loadedSkills, peerDesk, } = ctx;
63
66
  const deploymentSkillSources = new Map(loadedSkills.map((k) => [k.spec.name, k.source]));
64
67
  const scenarioGate = createScenarioGate({ config, scenarios, principalCaps, logger }, "enforce");
65
68
  const sessionHeadOf = headReadOf(ownerAware);
@@ -69,11 +72,11 @@ export function createResolveSpec(ctx) {
69
72
  approvalSeat: durableEnabled ? "durable" : "absent",
70
73
  singleUserAutoAcceptBaseline: singleUserAutoAcceptBaselineApplies(config),
71
74
  });
72
- const realTaskRootOf = (auth) => {
75
+ const realTaskRootOf = (root) => {
73
76
  if (DEPLOYMENT_SHAPE_PREDICATES.sandboxPathAdjudication.holds(config))
74
77
  return undefined;
75
- const sessionCwd = auth?.sessionId ? effectiveHostWorkspace(perSessionCwd.get(auth.sessionId), {}) : undefined;
76
- 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());
77
80
  };
78
81
  const memoryProjectLayers = createMemoryProjectLayers({ stores: memoryEngine, syncRunner: memorySyncRunner, log: logger });
79
82
  if (onlySensitiveBaseline)
@@ -82,6 +85,7 @@ export function createResolveSpec(ctx) {
82
85
  if (approvalGrantNotice)
83
86
  logger.info(approvalGrantNotice.event, approvalGrantNotice.fields);
84
87
  const resolveSpec = async (body, req, auth, opts) => {
88
+ const root = opts.execution.root;
85
89
  const seatRefusal = gateIntentUnserviceableReason(config, checkpointStore !== undefined);
86
90
  if (seatRefusal !== undefined)
87
91
  throw createCodedHttpError(501, "capability.checkpoint_store_required", seatRefusal);
@@ -100,7 +104,7 @@ export function createResolveSpec(ctx) {
100
104
  cwd: body.cwd,
101
105
  shellScratchpadDir: body.scratchpadDir,
102
106
  localDataRoot: config.localDataRoot ?? localRoot,
103
- sessionId: auth?.sessionId,
107
+ sessionId: root,
104
108
  requirePrincipal: config.requirePrincipal,
105
109
  callerOwnsWorkerDisk: DEPLOYMENT_SHAPE_PREDICATES.callerOwnsWorkerDisk.holds(config),
106
110
  });
@@ -117,15 +121,13 @@ export function createResolveSpec(ctx) {
117
121
  if (inheritEnvIssue)
118
122
  throw new HttpError(400, inheritEnvIssue.message, { code: "request.field_invalid", extra: inheritEnvIssue.facts });
119
123
  if (body.inheritEnv === "all") {
120
- const lane = executionLaneOf(config.remoteExec?.provider);
124
+ const lane = config.remoteExec.provider;
121
125
  if (lane !== "host") {
122
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") });
123
127
  }
124
128
  const why = taskInheritEnvRefusal(config);
125
129
  if (why !== undefined)
126
130
  throw new HttpError(422, why, { code: HOST_POSTURE_REFUSED_CODE });
127
- if (!auth?.sessionId)
128
- 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") });
129
131
  }
130
132
  }
131
133
  {
@@ -138,6 +140,26 @@ export function createResolveSpec(ctx) {
138
140
  if (seatIssue)
139
141
  throw new HttpError(400, seatIssue.message, { code: "request.field_invalid", extra: seatIssue.fields });
140
142
  }
143
+ let settingsEnv = readSettingsEnv(body.settings);
144
+ {
145
+ const envIssue = settingsEnvCredentialIssue(settingsEnv.reaching, serverCredentialValueSources(config.modelApiKeyEnv));
146
+ if (envIssue !== null) {
147
+ if (opts?.leg !== "fresh" && storedEnvCredentialsDropM38(new Date().toISOString().slice(0, 10))) {
148
+ settingsEnv = withoutKeys(settingsEnv, envIssue.keys);
149
+ const dropped = { name: 0, value_shape: 0 };
150
+ for (const e of envIssue.fields.entries)
151
+ dropped[e.match]++;
152
+ logger.warn("settings_env_credentials_dropped", {
153
+ migration: "M38",
154
+ sessionId: root,
155
+ dropped,
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
+ });
158
+ }
159
+ else
160
+ throw createCodedHttpError(400, "request.env_credential_refused", envIssue.message, { ...envIssue.fields });
161
+ }
162
+ }
141
163
  {
142
164
  const replay = opts?.leg === "resume";
143
165
  const inertList = inertToolListEntryOf(body, replay ? ["deny"] : undefined);
@@ -147,7 +169,7 @@ export function createResolveSpec(ctx) {
147
169
  const stale = inertToolListEntryOf(body, ["allow"]);
148
170
  if (stale !== undefined) {
149
171
  logger.warn("stored_allow_list_inert_resumed", {
150
- sessionId: auth?.sessionId ?? null,
172
+ sessionId: root,
151
173
  layer: stale.layer,
152
174
  sentence: stale.message,
153
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",
@@ -157,51 +179,54 @@ export function createResolveSpec(ctx) {
157
179
  }
158
180
  if (opts?.leg === "fresh")
159
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
+ }
160
189
  if (opts?.leg === "fresh")
161
190
  assertRequestImageUrls(body.images);
162
- const gated = await gateScenarioAndAppend(body, auth, opts);
191
+ const gated = await gateScenarioAndAppend(body, auth, root, opts, settingsEnv);
163
192
  const effMode = effectivePermissionMode(body, gated.parsedSettings.settings);
164
193
  {
165
194
  const why = permissionModeWriteFaceRefusal(effMode, config);
166
195
  if (why !== undefined)
167
196
  throw new HttpError(422, why, { code: HOST_POSTURE_REFUSED_CODE });
168
197
  }
169
- const lane = bindSettingsCwdEnvAndModel(body, auth, gated, opts);
170
- const anchors = await resolveHistoryAnchors(body, auth);
171
- 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;
172
201
  const runSkills = buildRunSkills({ scenario: gated.cap.skills, request: body.skills, disable: body.disableSkills === true, deploymentSources: deploymentSkillSources }, logger);
173
- const spec = assembleSpecLiteral(body, auth, req, opts, { ...gated, ...lane, ...anchors, projectKey, a2aPeers, storedToolAxes, runSkills }, effMode);
174
- const folded = await foldGovernanceAndSettings(body, auth, spec, gated);
175
- 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, {
176
205
  scenarioName: gated.scenarioName,
177
206
  scratchpadDir: folded.scratchpadDir,
178
207
  hostSemanticsLane: folded.hostSemanticsLane,
179
208
  });
180
209
  return { spec: final, facts: { hands: gated.hands, skills: runSkills.roster, sessionWitness: gated.sessionWitness } };
181
210
  };
182
- const gateScenarioAndAppend = async (body, auth, opts) => {
211
+ const gateScenarioAndAppend = async (body, auth, root, opts, settingsEnv) => {
183
212
  const scenarioName = await scenarioGate(auth?.principal, body.scenario);
184
- const root = opts.execution.root;
185
213
  const rootFace = sessionHeadOf === undefined ? undefined : sessionFaceOfHead(root, await sessionHeadOf(root));
186
214
  const sessionWitness = { sessionId: root, owner: rootFace?.owner ?? null, incarnation: rootFace?.incarnation ?? null };
187
215
  const cap = selectScenario(scenarios, scenarioName)(body, auth?.principal, { sessionId: sessionWitness.sessionId, delegationRoot: sessionWitness });
188
- 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 }));
189
217
  const objective = typeof body.objective === "string" ? body.objective : "";
190
- const parsedSettings = parseTaskSettings(body.settings, opts?.leg === "fresh" || !taskHooksHonored(config) ? {} : { storedHooksReread: storedHooksRereadM20(new Date().toISOString().slice(0, 10)) });
191
- if (parsedSettings.deferred.length > 0) {
192
- logger.warn("task_settings_deferred", { fields: parsedSettings.deferred, sessionId: auth?.sessionId ?? null });
193
- }
218
+ const parsedSettings = parseTaskSettings(body.settings, {
219
+ ...(opts?.leg === "fresh" || !taskHooksHonored(config) ? {} : { storedHooksReread: storedHooksRereadM20(new Date().toISOString().slice(0, 10)) }),
220
+ settingsEnv,
221
+ });
194
222
  if (parsedSettings.hooksReread !== undefined) {
195
223
  logger.warn("hooks_read_as_before_upgrade", {
196
224
  migration: "M20",
197
- sessionId: auth?.sessionId ?? null,
225
+ sessionId: root,
198
226
  stripped: parsedSettings.hooksReread.stripped,
199
- 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)",
200
228
  });
201
229
  }
202
- if (parsedSettings.deferred.includes("hooks") && taskHooksHonored(config)) {
203
- recordFailOpen("server.hooks.resume-reader-refused", `leg=${opts?.leg ?? "resume"}`);
204
- }
205
230
  let attachmentNotice;
206
231
  {
207
232
  const reqAtt = body.attachmentIds;
@@ -214,28 +239,25 @@ export function createResolveSpec(ctx) {
214
239
  if (reqAtt.length > 0) {
215
240
  if (!taskAttachmentStore)
216
241
  throw new HttpError(501, "attachmentIds require a store backend (DB_BACKEND=mysql|pg|local)");
217
- if (!auth?.sessionId)
218
- throw new HttpError(400, "`attachmentIds` requires a session-resolving deployment (no authorizer session)");
219
- const sid = auth.sessionId;
220
242
  const lane = opts.execution.lane;
221
243
  const r = await bindAttachmentsForTask({
222
244
  store: taskAttachmentStore,
223
245
  owner: auth?.principal ?? "default",
224
246
  ids: reqAtt,
225
- sessionId: sid,
247
+ sessionId: root,
226
248
  lane: { word: lane, isolated: laneIsolated(lane) },
227
249
  leg: opts?.leg === "fresh" ? "fresh" : "resume",
228
250
  nowMs: Date.now(),
229
251
  onMissing: (id) => {
230
252
  if (opts?.leg === "fresh")
231
253
  throw new HttpError(400, `attachment not found: ${id}`);
232
- logger.warn("attachment_missing_on_resume", { sessionId: sid, id });
254
+ logger.warn("attachment_missing_on_resume", { sessionId: root, id });
233
255
  },
234
256
  onRefused: (refusal) => {
235
257
  const answer = attachmentBindRefusalAnswer(refusal);
236
258
  if (opts?.leg === "fresh")
237
259
  throw createCodedHttpError(answer.status, answer.errorCode, answer.message, answer.extra);
238
- 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 });
239
261
  },
240
262
  });
241
263
  attachmentNotice = r.notice;
@@ -244,75 +266,71 @@ export function createResolveSpec(ctx) {
244
266
  }
245
267
  return { scenarioName, cap, hands: cap.hands, acceptedAppend, objective, parsedSettings, attachmentNotice, sessionWitness };
246
268
  };
247
- const bindSettingsCwdEnvAndModel = (body, auth, gated, opts) => {
269
+ const bindSettingsCwdEnvAndModel = (body, auth, root, gated, opts) => {
248
270
  const { objective, parsedSettings } = gated;
249
271
  const cwdWriteGate = DEPLOYMENT_SHAPE_PREDICATES.callerCwd.holds(config);
250
- const execLane = executionLaneOf(config.remoteExec?.provider);
251
- if (auth?.sessionId)
252
- fenceSessionOwner(auth.sessionId, auth.principal ?? null);
253
- 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) {
254
275
  if (cwdWriteGate && isAbsoluteHostPath(body.cwd))
255
- setSessionCwd(auth.sessionId, body.cwd);
256
- else if (DEPLOYMENT_SHAPE_PREDICATES.inProcessSingleUser.holds(config) && isAbsoluteHostPath(body.cwd) && satisfiedByProcessCwd(body.cwd, realpathSync))
257
- 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 });
258
279
  else
259
- logger.warn("task_cwd_ignored", { honored: cwdWriteGate, lane: execLane, sessionId: auth.sessionId });
280
+ logger.warn("task_cwd_ignored", { honored: cwdWriteGate, lane: execLane, sessionId: root });
260
281
  }
261
- if (parsedSettings.settings?.shellEnv && auth?.sessionId) {
282
+ if (parsedSettings.settings?.shellEnv) {
262
283
  if (cwdWriteGate)
263
- setSessionShellEnv(auth.sessionId, parsedSettings.settings.shellEnv);
264
- else if (DEPLOYMENT_SHAPE_PREDICATES.inProcessSingleUser.holds(config)) {
284
+ setSessionShellEnv(root, parsedSettings.settings.shellEnv);
285
+ else if (DEPLOYMENT_SHAPE_PREDICATES.noHandsSingleUser.holds(config)) {
265
286
  const requested = parsedSettings.settings.shellEnv;
266
287
  const mismatched = shellEnvMismatchCount(requested, process.env);
267
288
  if (mismatched === 0)
268
- 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 });
269
290
  else
270
- 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 });
271
292
  }
272
293
  else
273
- 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 });
274
295
  }
275
296
  const taskHooks = (() => {
276
297
  const hc = parsedSettings.settings?.hooks;
277
298
  if (!hc)
278
- return undefined;
299
+ return [];
279
300
  if (!taskHooksHonored(config)) {
280
- logger.warn("task_hooks_ignored", { honored: false, sessionId: auth?.sessionId ?? null });
281
- return undefined;
301
+ logger.warn("task_hooks_ignored", { honored: false, sessionId: root });
302
+ return [];
282
303
  }
283
- return createSettingsHooksRegistration(hc, {
304
+ return createSettingsHooksRegistrations(hc, {
284
305
  logger,
285
- sessionId: auth?.sessionId ?? "",
286
- cwd: (auth?.sessionId ? perSessionCwd.get(auth.sessionId) : undefined) ?? process.cwd(),
306
+ sessionId: root,
307
+ cwd: perSessionCwd.get(root) ?? process.cwd(),
287
308
  ...(parsedSettings.settings?.shellEnv ? { shellEnv: parsedSettings.settings.shellEnv } : {}),
288
309
  httpHookAllowlistLayers: parsedSettings.settings?.httpHookAllowlist !== undefined ? [parsedSettings.settings.httpHookAllowlist] : [],
310
+ belowTaskChainPatterns,
289
311
  hookLlm,
290
312
  hookAgent,
291
313
  onHookNotice: (n) => fleetBus.publishHookNotice({
292
314
  ...n,
293
315
  ...(auth?.principal ? { ownerScope: auth.principal } : {}),
294
- ...(auth?.sessionId ? { ownerSessionId: auth.sessionId } : {}),
316
+ ownerSessionId: root,
295
317
  }),
296
- ...(auth?.sessionId
297
- ? {
298
- wake: async (text) => hookWakeBus.deliver
299
- ?
300
- hookWakeBus.deliver(auth.sessionId, `[hook asyncRewake] ${redactSecrets(text)}`)
301
- : false,
302
- }
303
- : {}),
318
+ wake: async (text) => hookWakeBus.deliver
319
+ ?
320
+ hookWakeBus.deliver(root, `[hook asyncRewake] ${redactSecrets(text)}`)
321
+ : false,
304
322
  }, settingsHooksBudgetMs(config));
305
323
  })();
306
324
  const rawAddDirs = body.additionalDirectories;
307
325
  const callerOwnsWorkerDisk = DEPLOYMENT_SHAPE_PREDICATES.callerOwnsWorkerDisk.holds(config);
308
326
  const additionalDirectories = callerOwnsWorkerDisk ? parseAdditionalDirectories(rawAddDirs) : undefined;
309
327
  if (rawAddDirs !== undefined && !callerOwnsWorkerDisk) {
310
- logger.warn("task_additional_directories_ignored", { honored: false, sessionId: auth?.sessionId ?? null });
328
+ logger.warn("task_additional_directories_ignored", { honored: false, sessionId: root });
311
329
  }
312
330
  const rawAddReadDirs = body.additionalReadDirectories;
313
331
  const additionalReadDirectories = callerOwnsWorkerDisk ? parseAdditionalDirectories(rawAddReadDirs) : undefined;
314
332
  if (rawAddReadDirs !== undefined && !callerOwnsWorkerDisk) {
315
- 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 });
316
334
  }
317
335
  const wireCatalog = selectableCatalog(config.models, config.tiers, config.modelRefusals);
318
336
  const picked = resolveTaskModel(body.model ?? parsedSettings.settings?.model, objective, wireCatalog, config.atMention, config.modelRefusals);
@@ -322,7 +340,7 @@ export function createResolveSpec(ctx) {
322
340
  throw new HttpError(400, modelUnavailableMessage(source === "mention" ? "@-mention" : "model", requested, name, refusal), { code: "request.model_unavailable" });
323
341
  }
324
342
  metrics.inc("task_model_unavailable_fallback_total");
325
- 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 });
326
344
  }
327
345
  if (picked.notAllowed !== undefined) {
328
346
  const { requested, resolved, source } = picked.notAllowed;
@@ -330,39 +348,30 @@ export function createResolveSpec(ctx) {
330
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" });
331
349
  }
332
350
  metrics.inc("task_model_not_allowlisted_resume_total");
333
- 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" });
334
352
  }
335
353
  if (picked.unknownExplicit !== undefined) {
336
354
  metrics.inc("task_model_unknown_fallback_total");
337
- 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 });
338
356
  }
339
357
  return { taskHooks, additionalDirectories, additionalReadDirectories, wireCatalog, picked };
340
358
  };
341
- 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)";
342
- const resolveHistoryAnchors = async (body, auth) => {
359
+ const resolveHistoryAnchors = async (body, auth, root) => {
343
360
  let resumeAtEntryId;
344
361
  if (typeof body.resumeAt === "string" && body.resumeAt.length > 0) {
345
- if (!auth?.sessionId)
346
- throw new HttpError(422, "resumeAt requires a session to branch (resume_at.no_session)", { code: "resume_at.no_session" });
347
362
  if (!resumeAnchorStore || !sessionHeadOf)
348
363
  throw new HttpError(501, "resume-at is not available on this worker (no session-store backend for the anchor map)");
349
- resumeAtEntryId = await resumeAnchorStore.resolve(auth.sessionId, body.resumeAt, auth.principal ?? null);
350
- if (resumeAtEntryId === undefined)
351
- 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");
352
365
  }
353
366
  let rewindFilesToEntryId;
354
367
  if (resumeAtEntryId === undefined && typeof body.rewindFilesTo === "string" && body.rewindFilesTo.length > 0) {
355
- if (!auth?.sessionId)
356
- throw new HttpError(422, "rewindFilesTo requires a session (rewind_files_to.no_session)", { code: "rewind_files_to.no_session" });
357
368
  if (!resumeAnchorStore || !sessionHeadOf)
358
369
  throw new HttpError(501, "rewind-files-to is not available on this worker (no session-store backend for the anchor map)");
359
- rewindFilesToEntryId = await resumeAnchorStore.resolve(auth.sessionId, body.rewindFilesTo, auth.principal ?? null);
360
- if (rewindFilesToEntryId === undefined)
361
- 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");
362
371
  }
363
372
  const submittedProjectId = auth?.resolvedProjectId ?? (typeof body.projectId === "string" && body.projectId ? body.projectId.toLowerCase() : undefined);
364
373
  const s4DefaultScopes = submittedProjectId ? config.projects[submittedProjectId]?.defaultScopes : undefined;
365
- const legProjectId = await legProjectIdOf(submittedProjectId, sessionWorkspace, auth?.sessionId);
374
+ const legProjectId = await legProjectIdOf(submittedProjectId, sessionWorkspace, root);
366
375
  return { resumeAtEntryId, rewindFilesToEntryId, s4DefaultScopes, legProjectId };
367
376
  };
368
377
  const declaresInteractivePosture = (body, req, opts) => {
@@ -379,7 +388,7 @@ export function createResolveSpec(ctx) {
379
388
  const askForm = resolveAskSeamForm(body.approvalReach !== undefined ? { approvalReach: body.approvalReach } : {}, approverSeat !== undefined ? { onAsk: approverSeat } : {});
380
389
  return deriveAskEffective(askForm.form, "unresolved") === "human_reachable";
381
390
  };
382
- const assembleSpecLiteral = (body, auth, req, opts, parts, effMode) => {
391
+ const assembleSpecLiteral = (body, auth, root, req, opts, parts, effMode) => {
383
392
  const { scenarioName, cap, hands, acceptedAppend, parsedSettings, attachmentNotice, taskHooks, additionalDirectories, additionalReadDirectories, wireCatalog, picked, resumeAtEntryId, rewindFilesToEntryId, s4DefaultScopes, legProjectId, projectKey, a2aPeers, storedToolAxes, runSkills, } = parts;
384
393
  const spec = {
385
394
  objective: attachmentNotice ? `${picked.cleanedObjective}\n\n${attachmentNotice}` : picked.cleanedObjective,
@@ -392,10 +401,7 @@ export function createResolveSpec(ctx) {
392
401
  images: body.images,
393
402
  ...(body.userAttachments !== undefined ? { userAttachments: body.userAttachments } : {}),
394
403
  ...(body.clientContext ? { clientContext: { timeZone: body.clientContext.timeZone, userEmail: body.clientContext.userEmail } } : {}),
395
- ...(() => {
396
- const ct = body.compaction?.clampTolerance;
397
- return typeof ct === "number" && Number.isFinite(ct) && ct >= 0 && ct <= 1 ? { compaction: { clampTolerance: ct } } : {};
398
- })(),
404
+ ...compactionSpecFragment(body.compaction?.clampTolerance, parsedSettings.settings?.autoCompactEnabled),
399
405
  outputSchema: body.outputSchema,
400
406
  ...(typeof body.outputRetries === "number" && Number.isFinite(body.outputRetries) && body.outputRetries >= 1
401
407
  ? { outputRetries: Math.min(10, Math.floor(body.outputRetries)) }
@@ -416,8 +422,8 @@ export function createResolveSpec(ctx) {
416
422
  selfOrchestration: selfOrchestrationFromBody({ selfOrchestration: body.selfOrchestration === true || parsedSettings.settings?.ultracode === true }, config, Boolean(centerRuntimeCapsResolver)),
417
423
  forwardSubagentEvents: body.forwardSubagentEvents === true ? true : undefined,
418
424
  retainSubagentSessions: normalizeRetainSubagentSessions(body.retainSubagentSessions),
419
- ...taskAgentsSpecFragment(body.agents, config.requirePrincipal, (event, fields) => logger.warn(event, { ...fields, sessionId: auth?.sessionId ?? null })),
420
- ...(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
421
427
  ? { retainBackgroundProcesses: true }
422
428
  : {}),
423
429
  ...(body.excludeAllTools === true ? { excludeAllTools: true } : {}),
@@ -433,7 +439,7 @@ export function createResolveSpec(ctx) {
433
439
  resilience: normalizeResilience(body.resilience, explicitOperatorOk(auth?.principal, config)),
434
440
  finalVerification: cap.finalVerification === true || body.finalVerification === true ? true : undefined,
435
441
  attachments: normalizeAttachments(body.attachments),
436
- ...(taskHooks ? { mods: [taskHooks] } : {}),
442
+ ...(taskHooks.length > 0 ? { mods: [...taskHooks] } : {}),
437
443
  model: picked.model,
438
444
  ...((() => {
439
445
  if (typeof body.compactionModel !== "string" || body.compactionModel.length === 0)
@@ -448,7 +454,7 @@ export function createResolveSpec(ctx) {
448
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)`);
449
455
  }
450
456
  metrics.inc("task_model_unknown_fallback_total");
451
- 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 });
452
458
  return {};
453
459
  }
454
460
  if (!isAtMentionable(cm, wireCatalog, config.atMention, config.modelRefusals)) {
@@ -457,14 +463,14 @@ export function createResolveSpec(ctx) {
457
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" });
458
464
  }
459
465
  metrics.inc("task_model_not_allowlisted_resume_total");
460
- 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" });
461
467
  }
462
468
  return { compactionModel: cm };
463
469
  })()),
464
470
  thinking: effectiveThinking(body.reasoningEffort, parsedSettings.settings?.ultracode === true),
465
471
  getApiKeyAndHeaders: getKeyResolver(),
466
472
  ...(() => {
467
- 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 }));
468
474
  const declarations = [];
469
475
  if (taskLimitCaps.timeoutSec !== undefined)
470
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)" });
@@ -512,13 +518,13 @@ export function createResolveSpec(ctx) {
512
518
  ...(() => { const v = toolNameListFromBody(body.userInvokedSkills); return v ? { userInvokedSkills: v } : {}; })(),
513
519
  ...(parsedSettings.settings?.skillListingBudgetFraction !== undefined ? { skillListingBudgetFraction: parsedSettings.settings.skillListingBudgetFraction } : {}),
514
520
  ...(parsedSettings.settings?.skillListingMaxDescChars !== undefined ? { skillListingMaxDescChars: parsedSettings.settings.skillListingMaxDescChars } : {}),
515
- 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),
516
522
  a2a: resolveRequestA2a(a2aForScenario(config.a2aPeers, scenarioName), a2aPeers, config, peerDesk, opts.lease, logger, opts?.leg === "fresh" ? "fresh" : "resume", storedToolAxes),
517
523
  toolPolicy: toolPolicyForHands(hands, durableEnabled
518
524
  ? createApprovalBaselinePolicy(config, {
519
525
  kind: "durable",
520
526
  question: liveQuestionFace,
521
- ...(approvalExemptionStore !== undefined && auth?.sessionId ? { exemption: createDeploymentListExemption(approvalExemptionStore, auth.sessionId, logger) } : {}),
527
+ ...(approvalExemptionStore !== undefined ? { exemption: createDeploymentListExemption(approvalExemptionStore, root, logger) } : {}),
522
528
  })
523
529
  : singleUserAutoAcceptBaselineApplies(config)
524
530
  ? createApprovalBaselinePolicy(config, { kind: "absent" })
@@ -545,7 +551,7 @@ export function createResolveSpec(ctx) {
545
551
  };
546
552
  return spec;
547
553
  };
548
- const foldGovernanceAndSettings = async (body, auth, spec, gated) => {
554
+ const foldGovernanceAndSettings = async (body, auth, root, spec, gated) => {
549
555
  const { acceptedAppend, parsedSettings } = gated;
550
556
  const hostSemanticsLane = !DEPLOYMENT_SHAPE_PREDICATES.sandboxPathAdjudication.holds(config);
551
557
  const laneHomeBase = () => {
@@ -554,7 +560,7 @@ export function createResolveSpec(ctx) {
554
560
  };
555
561
  const pathAdjudication = hostSemanticsLane
556
562
  ? (() => {
557
- const realRoot = realTaskRootOf(auth);
563
+ const realRoot = realTaskRootOf(root);
558
564
  const gateCwd = realRoot ?? join(config.localDataRoot ?? localRoot, "fs-write-gate-unrooted");
559
565
  return {
560
566
  env: new NodeExecutionEnv({ cwd: gateCwd }),
@@ -565,9 +571,9 @@ export function createResolveSpec(ctx) {
565
571
  })()
566
572
  : {
567
573
  env: new DeferredSandboxPathEnv({
568
- sessionId: auth?.sessionId,
574
+ sessionId: root,
569
575
  slots: sandboxPathEnvSlots,
570
- 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 }) },
571
577
  }),
572
578
  ...laneHomeBase(),
573
579
  };
@@ -575,18 +581,18 @@ export function createResolveSpec(ctx) {
575
581
  let governed = governedBase;
576
582
  let effectiveSettings = parsedSettings.settings;
577
583
  if (effectiveSettings?.outputStyle && acceptedAppend && acceptedAppend.length + 2 + effectiveSettings.outputStyle.length > MAX_SETTINGS_OUTPUT_STYLE_CHARS) {
578
- 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 });
579
585
  const { outputStyle: _dropped2, ...rest2 } = effectiveSettings;
580
586
  effectiveSettings = Object.keys(rest2).length > 0 ? rest2 : undefined;
581
587
  }
582
588
  const shellScratchpad = await acceptShellScratchpadDir(body.scratchpadDir, {
583
589
  requirePrincipal: config.requirePrincipal,
584
590
  hostSemanticsLane,
585
- warn: (msg, meta) => logger.warn(msg, { ...(meta ?? {}), sessionId: auth?.sessionId ?? null }),
591
+ warn: (msg, meta) => logger.warn(msg, { ...(meta ?? {}), sessionId: root }),
586
592
  });
587
593
  const scratchpadDir = shellScratchpad ??
588
- (hostSemanticsLane && auth?.sessionId
589
- ? 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 }))
590
596
  : undefined);
591
597
  if (effectiveSettings) {
592
598
  const configRoot = executionConfigRootOf(config);
@@ -606,11 +612,11 @@ export function createResolveSpec(ctx) {
606
612
  }
607
613
  if (governed.selfOrchestration === true) {
608
614
  governed = tightenGoverned(governed, {
609
- toolPolicy: createWorkflowAskPolicy(approvalExemptionStore && auth?.sessionId
615
+ toolPolicy: createWorkflowAskPolicy(approvalExemptionStore
610
616
  ? async (toolName) => {
611
- const hit = await approvalExemptionStore.has(auth.sessionId, toolName);
617
+ const hit = await approvalExemptionStore.has(root, toolName);
612
618
  if (hit)
613
- logger.info("workflow_gate_exempted", { toolName, sessionId: auth.sessionId });
619
+ logger.info("workflow_gate_exempted", { toolName, sessionId: root });
614
620
  return hit;
615
621
  }
616
622
  : undefined),
@@ -618,40 +624,37 @@ export function createResolveSpec(ctx) {
618
624
  }
619
625
  return { governed, scratchpadDir, hostSemanticsLane };
620
626
  };
621
- const applyImageFactsAndRouting = async (body, auth, governed, folded) => {
627
+ const applyImageFactsAndRouting = async (body, auth, root, governed, folded) => {
622
628
  const { scenarioName, scratchpadDir, hostSemanticsLane } = folded;
623
629
  const bodyProfile = typeof body.sandboxImageProfile === "string" && body.sandboxImageProfile.length > 0 ? body.sandboxImageProfile : undefined;
624
- 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));
625
631
  let resolvedImageCaps;
626
632
  if (taskImageProfile !== undefined) {
627
- if (config.remoteExec?.provider !== "k8s") {
633
+ if (config.remoteExec.provider !== "k8s") {
628
634
  throw createCodedHttpError(501, "capability.k8s_lane_required", "sandboxImageProfile is only supported on the k8s sandbox backend");
629
635
  }
630
636
  if (!imageIndex) {
631
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");
632
638
  }
633
- if (!auth?.sessionId) {
634
- throw createCodedHttpError(400, "request.precondition_unmet", "sandboxImageProfile requires a resolved session");
635
- }
636
639
  const capsNeeded = Array.isArray(body.capabilitiesNeeded)
637
640
  ? body.capabilitiesNeeded.filter((c) => typeof c === "string")
638
641
  : undefined;
639
642
  const resolved = await resolveSandboxImageRef({
640
643
  profile: taskImageProfile,
641
644
  ...(capsNeeded && capsNeeded.length > 0 ? { capabilitiesNeeded: capsNeeded } : {}),
642
- viewer: { operator: explicitOperatorOk(auth.principal, config), tenantId: auth.principal ?? null },
645
+ viewer: { operator: explicitOperatorOk(auth?.principal, config), tenantId: auth?.principal ?? null },
643
646
  index: imageIndex,
644
647
  });
645
648
  if (!resolved.ok)
646
649
  throw createCodedHttpError(resolved.status, resolved.errorCode, resolved.message);
647
- perTaskImage.set(auth.sessionId, resolved.ref);
650
+ perTaskImage.set(root, resolved.ref);
648
651
  resolvedImageCaps = resolved.capabilities;
649
652
  }
650
653
  const remoteScratchpadDir = !hostSemanticsLane && DEPLOYMENT_SHAPE_PREDICATES.remoteScratchpad.holds(config)
651
- ? remoteScratchpadDirFor(auth?.sessionId)
654
+ ? remoteScratchpadDirFor(root)
652
655
  : undefined;
653
656
  const declaredScratchpadDir = scratchpadDir ?? remoteScratchpadDir;
654
- const pkgSourceLane = config.remoteExec?.provider === "e2b" || config.remoteExec?.provider === "k8s";
657
+ const pkgSourceLane = config.remoteExec.provider === "e2b" || config.remoteExec.provider === "k8s";
655
658
  const facts = buildEnvFacts({
656
659
  ...(declaredScratchpadDir ? { scratchpadDir: declaredScratchpadDir } : {}),
657
660
  ...(config.envFactsEnabled
@@ -660,7 +663,7 @@ export function createResolveSpec(ctx) {
660
663
  capabilities: resolvedImageCaps,
661
664
  ...(pkgSourceLane ? { pkgSource: config.sandboxPkgSource } : {}),
662
665
  egress: egressForRemoteExec(config.remoteExec),
663
- 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),
664
667
  }
665
668
  : {}),
666
669
  });
@@ -669,10 +672,10 @@ export function createResolveSpec(ctx) {
669
672
  if (config.routerEnabled) {
670
673
  const decision = routeServiceTask({
671
674
  vmIsolatedExecEnv: DEPLOYMENT_SHAPE_PREDICATES.vmIsolatedHands.holds(config),
672
- hasExecutionEnv: laneWiresExecutionEnv(executionLaneOf(config.remoteExec?.provider)),
675
+ hasExecutionEnv: laneWiresExecutionEnv(config.remoteExec.provider),
673
676
  ...(config.autonomy ? { autonomy: config.autonomy } : {}),
674
677
  });
675
- 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 });
676
679
  if (decision.mode === "supervisor") {
677
680
  return tightenGoverned(governed, supPostureOverrides());
678
681
  }