@sema-agent/server 7.147.0 → 7.149.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 (790) hide show
  1. package/MIGRATION.md +1468 -24
  2. package/README.md +35 -7
  3. package/README.zh-CN.md +18 -8
  4. package/USAGE.md +444 -193
  5. package/deploy/sema-up/README.md +16 -5
  6. package/deploy/sema-up/chart/templates/NOTES.txt +1 -1
  7. package/deploy/sema-up/chart/templates/_helpers.tpl +20 -4
  8. package/deploy/sema-up/chart/values.yaml +3 -2
  9. package/deploy/sema-up/cluster-up.sh +74 -176
  10. package/deploy/sema-up/kube-up.sh +29 -49
  11. package/deploy/sema-up/lib/chart-run.sh +23 -0
  12. package/deploy/sema-up/lib/dataroot.sh +3 -3
  13. package/deploy/sema-up/lib/health.sh +62 -13
  14. package/deploy/sema-up/lib/helm-values-cluster.py +18 -0
  15. package/deploy/sema-up/lib/helm-values-kube.py +35 -0
  16. package/deploy/sema-up/lib/regcred.py +8 -0
  17. package/deploy/sema-up/lib/remote/helm-install.sh +3 -0
  18. package/deploy/sema-up/lib/remote/image-import.sh +6 -0
  19. package/deploy/sema-up/lib/remote/machine-precheck.sh +11 -0
  20. package/deploy/sema-up/lib/remote/region-probe.sh +3 -0
  21. package/deploy/sema-up/lib/remote/stack-ready.sh +26 -0
  22. package/deploy/sema-up/lib/remote/vxlan-guard.sh +8 -0
  23. package/deploy/sema-up/lib/render-stack.py +17 -0
  24. package/deploy/sema-up/lib/shell-text.sh +87 -0
  25. package/deploy/sema-up/lib/usage-flags.txt +10 -0
  26. package/deploy/sema-up/lib/usage-head.txt +1 -0
  27. package/deploy/sema-up/lib/usage-tail.txt +13 -0
  28. package/deploy/sema-up/preflight.sh +10 -8
  29. package/deploy/sema-up/sema-up.sh +14 -39
  30. package/deploy/sema-up/smoke.sh +7 -6
  31. package/deploy/sema-up/stack/compose.dataroot.yaml +3 -0
  32. package/deploy/sema-up/stack/compose.yaml +13 -1
  33. package/deploy/sema-up/stack/sema-stack-cluster.yaml +21 -0
  34. package/dist/adoption/plan.d.ts +24 -0
  35. package/dist/adoption/plan.js +53 -1
  36. package/dist/adoption/runner.d.ts +10 -1
  37. package/dist/adoption/runner.js +36 -16
  38. package/dist/approval-card.d.ts +36 -38
  39. package/dist/approval-gate-currency.js +3 -2
  40. package/dist/approval-leg-origin.d.ts +33 -0
  41. package/dist/approval-leg-origin.js +4 -0
  42. package/dist/approval-reconciler.d.ts +4 -13
  43. package/dist/approval-reconciler.js +2 -2
  44. package/dist/approval.d.ts +13 -11
  45. package/dist/approval.js +3 -3
  46. package/dist/audit.d.ts +10 -3
  47. package/dist/audit.js +15 -7
  48. package/dist/auth-bridge.d.ts +9 -15
  49. package/dist/auth-bridge.js +4 -11
  50. package/dist/auth-keys.d.ts +10 -1
  51. package/dist/auth-keys.js +8 -0
  52. package/dist/auto-mode-face.d.ts +10 -7
  53. package/dist/auto-mode-face.js +7 -4
  54. package/dist/background-agent-name.d.ts +19 -1
  55. package/dist/background-agent-name.js +12 -2
  56. package/dist/background-session-reap.d.ts +1 -1
  57. package/dist/bake-runner/main.js +9 -6
  58. package/dist/bench/s1/arms.js +6 -5
  59. package/dist/bench/s1/live-deps.js +5 -2
  60. package/dist/bench/s1/run-firm.js +6 -5
  61. package/dist/bind-host.d.ts +25 -0
  62. package/dist/bind-host.js +25 -0
  63. package/dist/boot/adoption.d.ts +3 -0
  64. package/dist/boot/adoption.js +1 -0
  65. package/dist/boot/deployment-mods.d.ts +1 -1
  66. package/dist/boot/execution-env.d.ts +17 -7
  67. package/dist/boot/execution-env.js +47 -42
  68. package/dist/boot/execution-lane.d.ts +6 -4
  69. package/dist/boot/execution-lane.js +3 -1
  70. package/dist/boot/exit-boundary.d.ts +2 -2
  71. package/dist/boot/exit-boundary.js +6 -5
  72. package/dist/boot/fatal-exit.d.ts +3 -5
  73. package/dist/boot/fatal-exit.js +2 -2
  74. package/dist/boot/leader.d.ts +15 -0
  75. package/dist/boot/leader.js +17 -15
  76. package/dist/boot/memory-consolidation.d.ts +37 -29
  77. package/dist/boot/memory-consolidation.js +11 -5
  78. package/dist/boot/org-delivery.d.ts +3 -2
  79. package/dist/boot/org-memory.js +1 -1
  80. package/dist/boot/parked-revive-gate.js +2 -2
  81. package/dist/boot/reapers.d.ts +4 -3
  82. package/dist/boot/reapers.js +19 -16
  83. package/dist/boot/resolve-spec.d.ts +5 -3
  84. package/dist/boot/resolve-spec.js +60 -70
  85. package/dist/boot/retention-lane.d.ts +4 -4
  86. package/dist/boot/retention-lane.js +2 -2
  87. package/dist/boot/runner-deps.d.ts +28 -7
  88. package/dist/boot/runner-deps.js +14 -5
  89. package/dist/boot/runtime-caps.d.ts +2 -2
  90. package/dist/boot/runtime-caps.js +16 -2
  91. package/dist/boot/session-faces.d.ts +16 -7
  92. package/dist/boot/session-faces.js +114 -94
  93. package/dist/boot/shutdown.d.ts +5 -4
  94. package/dist/boot/shutdown.js +6 -4
  95. package/dist/boot/stage-01-config.d.ts +1 -0
  96. package/dist/boot/stage-01-config.js +13 -4
  97. package/dist/boot/stage-02-web-admin-pull.d.ts +2 -0
  98. package/dist/boot/stage-02-web-admin-pull.js +16 -3
  99. package/dist/boot/stage-03-store-backend.d.ts +4 -0
  100. package/dist/boot/stage-03-store-backend.js +4 -3
  101. package/dist/boot/stage-04-stores.d.ts +3 -0
  102. package/dist/boot/stage-04-stores.js +2 -2
  103. package/dist/boot/stage-05-execution-env.d.ts +8 -3
  104. package/dist/boot/stage-05-execution-env.js +2 -2
  105. package/dist/boot/stage-06-runners.d.ts +12 -13
  106. package/dist/boot/stage-06-runners.js +23 -15
  107. package/dist/boot/stage-07-capability-layer.d.ts +13 -9
  108. package/dist/boot/stage-07-capability-layer.js +5 -3
  109. package/dist/boot/stage-08-reapers.d.ts +13 -9
  110. package/dist/boot/stage-08-reapers.js +3 -3
  111. package/dist/boot/stage-09-leader.d.ts +14 -16
  112. package/dist/boot/stage-09-leader.js +12 -4
  113. package/dist/boot/stage-10-http-server.d.ts +14 -16
  114. package/dist/boot/stage-10-http-server.js +7 -4
  115. package/dist/boot/store-evidence.d.ts +20 -0
  116. package/dist/boot/store-evidence.js +13 -0
  117. package/dist/boot/stores.d.ts +6 -0
  118. package/dist/boot/stores.js +41 -27
  119. package/dist/boot/task-list-lane.d.ts +4 -4
  120. package/dist/boot/web-admin.d.ts +4 -2
  121. package/dist/boot/web-admin.js +55 -35
  122. package/dist/boot/webfetch-summarize-lane.d.ts +1 -1
  123. package/dist/boot-reclaim.d.ts +3 -1
  124. package/dist/boot-reclaim.js +1 -1
  125. package/dist/brain.d.ts +7 -18
  126. package/dist/brain.js +5 -17
  127. package/dist/budget.js +6 -6
  128. package/dist/capabilities/center-plugins.d.ts +7 -1
  129. package/dist/capabilities/center-plugins.js +32 -10
  130. package/dist/capabilities/center-wiring.js +1 -1
  131. package/dist/capabilities/composite-members.d.ts +2 -2
  132. package/dist/capabilities/composite-members.js +2 -2
  133. package/dist/capabilities/repo-tools.d.ts +2 -0
  134. package/dist/capabilities/repo-tools.js +14 -12
  135. package/dist/capabilities/scenarios.d.ts +6 -15
  136. package/dist/capabilities/scenarios.js +11 -16
  137. package/dist/capabilities/skills.d.ts +1 -1
  138. package/dist/capabilities/tool-defer.d.ts +1 -1
  139. package/dist/capability-facts.d.ts +39 -11
  140. package/dist/capability-facts.js +35 -7
  141. package/dist/card-settle-stored-scope.d.ts +56 -0
  142. package/dist/card-settle-stored-scope.js +27 -0
  143. package/dist/card-void.d.ts +8 -13
  144. package/dist/card-void.js +2 -7
  145. package/dist/center-credential-renewer.d.ts +6 -2
  146. package/dist/center-credential-renewer.js +7 -3
  147. package/dist/config-catalog.d.ts +28 -1
  148. package/dist/config-catalog.js +95 -85
  149. package/dist/config-dir-trust.d.ts +37 -4
  150. package/dist/config-dir-trust.js +88 -44
  151. package/dist/config-invariants.d.ts +43 -3
  152. package/dist/config-invariants.js +69 -5
  153. package/dist/config-lkg.d.ts +23 -1
  154. package/dist/config-lkg.js +17 -3
  155. package/dist/config-provider.d.ts +9 -9
  156. package/dist/config-provider.js +25 -110
  157. package/dist/config-pull-failure.d.ts +50 -0
  158. package/dist/config-pull-failure.js +48 -0
  159. package/dist/config-types.d.ts +62 -21
  160. package/dist/config.d.ts +14 -21
  161. package/dist/config.js +141 -64
  162. package/dist/context-window-notice.d.ts +31 -0
  163. package/dist/context-window-notice.js +28 -0
  164. package/dist/delegated-session-owner.d.ts +1 -1
  165. package/dist/deleted-session-ids.d.ts +3 -2
  166. package/dist/deployment-governance.d.ts +3 -3
  167. package/dist/deployment-shape.d.ts +46 -11
  168. package/dist/deployment-shape.js +8 -0
  169. package/dist/egress-redirect.d.ts +25 -7
  170. package/dist/egress-redirect.js +20 -2
  171. package/dist/elicitation.d.ts +6 -5
  172. package/dist/elicitation.js +23 -22
  173. package/dist/engine-identity.d.ts +28 -0
  174. package/dist/engine-identity.js +10 -0
  175. package/dist/entry-problems.d.ts +5 -7
  176. package/dist/entry-problems.js +1 -1
  177. package/dist/env-facts.js +2 -1
  178. package/dist/env-name-allowlist-knobs.d.ts +6 -5
  179. package/dist/env-name-allowlist-knobs.js +5 -0
  180. package/dist/env-witness.d.ts +7 -0
  181. package/dist/env-witness.js +16 -0
  182. package/dist/execution-lane-caps.d.ts +25 -23
  183. package/dist/execution-lane-caps.js +18 -26
  184. package/dist/execution-placement.d.ts +58 -18
  185. package/dist/execution-placement.js +41 -2
  186. package/dist/field-conflict.d.ts +7 -11
  187. package/dist/field-conflict.js +3 -3
  188. package/dist/file-history-capture.d.ts +3 -3
  189. package/dist/file-history-disclosure.js +1 -0
  190. package/dist/fleet/fleet-bus.d.ts +21 -3
  191. package/dist/fleet/fleet-bus.js +35 -25
  192. package/dist/fleet/fleet-reconciler.js +2 -2
  193. package/dist/fleet/serving-lease.js +3 -3
  194. package/dist/fleet-client.js +3 -3
  195. package/dist/fleet-lease.d.ts +0 -1
  196. package/dist/fleet-lease.js +4 -5
  197. package/dist/history-anchor.d.ts +23 -3
  198. package/dist/history-anchor.js +24 -4
  199. package/dist/hitl-delivery.d.ts +90 -0
  200. package/dist/hitl-delivery.js +98 -0
  201. package/dist/hooks/classic-stations.d.ts +8 -11
  202. package/dist/hooks/classic-stations.js +0 -7
  203. package/dist/hooks/command-spawn.d.ts +7 -2
  204. package/dist/hooks/command-spawn.js +13 -6
  205. package/dist/hooks/hook-llm.d.ts +5 -1
  206. package/dist/hooks/hook-llm.js +24 -15
  207. package/dist/hooks/hook-runner.d.ts +72 -57
  208. package/dist/hooks/hook-runner.js +271 -193
  209. package/dist/host-lsp-manager.d.ts +22 -8
  210. package/dist/host-lsp-manager.js +4 -1
  211. package/dist/http/active-run-conflict.d.ts +2 -43
  212. package/dist/http/active-run-conflict.js +3 -7
  213. package/dist/http/admission.d.ts +4 -18
  214. package/dist/http/admission.js +76 -79
  215. package/dist/http/approval-sweeps.d.ts +3 -3
  216. package/dist/http/approval-sweeps.js +56 -31
  217. package/dist/http/caller-trust.d.ts +8 -10
  218. package/dist/http/caller-trust.js +1 -2
  219. package/dist/http/claim-heartbeat.d.ts +49 -0
  220. package/dist/http/claim-heartbeat.js +46 -0
  221. package/dist/http/claimed-run.d.ts +16 -8
  222. package/dist/http/claimed-run.js +8 -0
  223. package/dist/http/dispatch.d.ts +8 -1
  224. package/dist/http/dispatch.js +78 -30
  225. package/dist/http/durable-run-leg.d.ts +11 -4
  226. package/dist/http/durable-run-leg.js +45 -21
  227. package/dist/http/execution-context.d.ts +122 -47
  228. package/dist/http/execution-context.js +135 -43
  229. package/dist/http/health-reader.d.ts +36 -0
  230. package/dist/http/health-reader.js +21 -0
  231. package/dist/http/health-self-report.d.ts +9 -9
  232. package/dist/http/health-self-report.js +4 -4
  233. package/dist/http/idempotency.d.ts +9 -5
  234. package/dist/http/idempotency.js +4 -4
  235. package/dist/http/memory-compliance-failure-reply.d.ts +15 -16
  236. package/dist/http/memory-compliance-failure-reply.js +4 -2
  237. package/dist/http/memory-face-fault-reply.d.ts +67 -0
  238. package/dist/http/memory-face-fault-reply.js +71 -0
  239. package/dist/http/memory-store-refusal-reply.d.ts +1 -1
  240. package/dist/http/memory-store-refusal-reply.js +3 -0
  241. package/dist/http/owner-access.d.ts +392 -67
  242. package/dist/http/owner-access.js +370 -35
  243. package/dist/http/principal-gate.d.ts +39 -89
  244. package/dist/http/principal-gate.js +26 -68
  245. package/dist/http/refusal-body.d.ts +35 -2
  246. package/dist/http/refusal-body.js +34 -0
  247. package/dist/http/request-guards.d.ts +9 -13
  248. package/dist/http/request-guards.js +34 -68
  249. package/dist/http/resume-composition.d.ts +37 -0
  250. package/dist/http/resume-composition.js +18 -0
  251. package/dist/http/resume-ctx-read.d.ts +46 -12
  252. package/dist/http/resume-ctx-read.js +31 -6
  253. package/dist/http/resume-legs.d.ts +54 -19
  254. package/dist/http/resume-legs.js +408 -196
  255. package/dist/http/retired-skill-manifest.d.ts +1 -1
  256. package/dist/http/route-ctx.d.ts +31 -32
  257. package/dist/http/routes/a2a-serve.d.ts +43 -5
  258. package/dist/http/routes/a2a-serve.js +60 -37
  259. package/dist/http/routes/admin-config-refresh.js +2 -2
  260. package/dist/http/routes/admin-drain.js +2 -2
  261. package/dist/http/routes/admin-memory-optout.js +4 -3
  262. package/dist/http/routes/adoption.d.ts +3 -0
  263. package/dist/http/routes/adoption.js +17 -10
  264. package/dist/http/routes/agents-roster.js +13 -7
  265. package/dist/http/routes/approvals-assistant.js +73 -67
  266. package/dist/http/routes/attachments.js +2 -2
  267. package/dist/http/routes/background.d.ts +3 -3
  268. package/dist/http/routes/background.js +9 -17
  269. package/dist/http/routes/capabilities.js +16 -19
  270. package/dist/http/routes/config-catalog.js +2 -2
  271. package/dist/http/routes/devices.d.ts +3 -3
  272. package/dist/http/routes/devices.js +4 -4
  273. package/dist/http/routes/diagnostics.d.ts +29 -3
  274. package/dist/http/routes/diagnostics.js +49 -18
  275. package/dist/http/routes/engine.js +2 -2
  276. package/dist/http/routes/fleet.js +5 -3
  277. package/dist/http/routes/images.js +10 -6
  278. package/dist/http/routes/leader.d.ts +7 -2
  279. package/dist/http/routes/leader.js +12 -3
  280. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  281. package/dist/http/routes/mcp-reconnect.js +7 -15
  282. package/dist/http/routes/memory-bundle.js +4 -7
  283. package/dist/http/routes/memory-compliance.js +4 -4
  284. package/dist/http/routes/memory-consolidation.js +6 -9
  285. package/dist/http/routes/memory-origin.d.ts +2 -0
  286. package/dist/http/routes/memory-origin.js +7 -8
  287. package/dist/http/routes/memory-policy.js +17 -12
  288. package/dist/http/routes/notify-wake.js +10 -19
  289. package/dist/http/routes/observability.js +3 -3
  290. package/dist/http/routes/principal-inbox.d.ts +4 -2
  291. package/dist/http/routes/principal-inbox.js +5 -4
  292. package/dist/http/routes/projects.d.ts +1 -1
  293. package/dist/http/routes/projects.js +3 -2
  294. package/dist/http/routes/retention-ops.js +6 -9
  295. package/dist/http/routes/rules.js +20 -5
  296. package/dist/http/routes/run-memory-capture.d.ts +2 -2
  297. package/dist/http/routes/run-memory-capture.js +6 -12
  298. package/dist/http/routes/run-permission-mode.d.ts +2 -2
  299. package/dist/http/routes/run-permission-mode.js +10 -17
  300. package/dist/http/routes/runs.js +155 -237
  301. package/dist/http/routes/session-memory-sync.d.ts +2 -2
  302. package/dist/http/routes/session-memory-sync.js +7 -13
  303. package/dist/http/routes/session-sync.d.ts +28 -7
  304. package/dist/http/routes/session-sync.js +63 -50
  305. package/dist/http/routes/sessions-list.d.ts +3 -3
  306. package/dist/http/routes/sessions-list.js +9 -9
  307. package/dist/http/routes/sessions.js +87 -124
  308. package/dist/http/routes/shared-memory.js +6 -6
  309. package/dist/http/routes/side-query.js +2 -2
  310. package/dist/http/routes/tasks.js +237 -187
  311. package/dist/http/routes/trace-usage.d.ts +0 -12
  312. package/dist/http/routes/trace-usage.js +40 -46
  313. package/dist/http/routes/workflows.d.ts +39 -4
  314. package/dist/http/routes/workflows.js +42 -14
  315. package/dist/http/run-concurrency-cap.d.ts +20 -12
  316. package/dist/http/run-concurrency-cap.js +39 -26
  317. package/dist/http/run-read-face.d.ts +3 -5
  318. package/dist/http/run-read-face.js +8 -13
  319. package/dist/http/send.d.ts +12 -3
  320. package/dist/http/send.js +42 -6
  321. package/dist/http/server.d.ts +43 -45
  322. package/dist/http/server.js +61 -11
  323. package/dist/http/sse-log.d.ts +17 -10
  324. package/dist/http/sse-log.js +7 -7
  325. package/dist/http/stored-body-replay.d.ts +12 -0
  326. package/dist/http/stored-body-replay.js +2 -2
  327. package/dist/http/submit-ctx.d.ts +17 -8
  328. package/dist/http/submit-ctx.js +8 -5
  329. package/dist/http/submit-replay.d.ts +19 -6
  330. package/dist/http/submit-replay.js +18 -6
  331. package/dist/http/sync-submit-body.d.ts +3 -4
  332. package/dist/http/sync-submit-body.js +4 -5
  333. package/dist/http/wire-types.d.ts +4 -3
  334. package/dist/identity-source.d.ts +36 -5
  335. package/dist/identity-source.js +27 -0
  336. package/dist/index.d.ts +4 -1
  337. package/dist/index.js +2 -0
  338. package/dist/key-resolver.d.ts +32 -0
  339. package/dist/key-resolver.js +23 -9
  340. package/dist/leader/diffup.js +2 -1
  341. package/dist/leader/endpoint.d.ts +26 -5
  342. package/dist/leader/endpoint.js +154 -14
  343. package/dist/leader/fanout.d.ts +3 -0
  344. package/dist/leader/fanout.js +78 -63
  345. package/dist/leader/leader.d.ts +16 -0
  346. package/dist/leader/leader.js +43 -3
  347. package/dist/leader/merge.d.ts +9 -1
  348. package/dist/leader/merge.js +16 -1
  349. package/dist/leader/repair-wire.js +1 -1
  350. package/dist/leader/wire.d.ts +36 -3
  351. package/dist/leader/wire.js +59 -18
  352. package/dist/leg-facts.d.ts +7 -2
  353. package/dist/leg-facts.js +1 -0
  354. package/dist/local-store-declaration.d.ts +54 -0
  355. package/dist/local-store-declaration.js +59 -0
  356. package/dist/lsp-evict.d.ts +6 -4
  357. package/dist/lsp-evict.js +2 -3
  358. package/dist/mcp-assertion-header.d.ts +1 -1
  359. package/dist/mcp-assertion-header.js +1 -1
  360. package/dist/memory-operator-faces.d.ts +5 -4
  361. package/dist/memory-operator-faces.js +1 -1
  362. package/dist/memory-project-layer.js +1 -1
  363. package/dist/memory-scope.d.ts +33 -6
  364. package/dist/memory-scope.js +68 -19
  365. package/dist/memory-store-refusal.d.ts +5 -2
  366. package/dist/memory-sync-client.d.ts +3 -2
  367. package/dist/memory-sync-client.js +8 -5
  368. package/dist/model-compat.d.ts +17 -8
  369. package/dist/model-compat.js +6 -2
  370. package/dist/model-context-window.d.ts +57 -0
  371. package/dist/model-context-window.js +21 -0
  372. package/dist/model-entry-headers.d.ts +46 -4
  373. package/dist/model-entry-headers.js +2 -2
  374. package/dist/model-entry-refusal.d.ts +40 -20
  375. package/dist/model-entry-refusal.js +57 -30
  376. package/dist/model-plane-face.d.ts +19 -11
  377. package/dist/model-plane-face.js +9 -1
  378. package/dist/model-plane-probe.d.ts +2 -0
  379. package/dist/model-plane-probe.js +17 -0
  380. package/dist/model-provider.d.ts +3 -3
  381. package/dist/model-reach-scope.d.ts +2 -1
  382. package/dist/model-route-endpoint.d.ts +9 -5
  383. package/dist/model-route-endpoint.js +29 -7
  384. package/dist/model-select.d.ts +16 -0
  385. package/dist/model-select.js +4 -0
  386. package/dist/mountinfo.d.ts +37 -0
  387. package/dist/mountinfo.js +47 -0
  388. package/dist/namespaced-rule-name.d.ts +23 -14
  389. package/dist/namespaced-rule-name.js +8 -11
  390. package/dist/net-address.d.ts +1 -1
  391. package/dist/observability/corrupt-read-seat.d.ts +4 -4
  392. package/dist/observability/corrupt-read-seat.js +5 -3
  393. package/dist/observability/fail-open.d.ts +72 -40
  394. package/dist/observability/fail-open.js +74 -40
  395. package/dist/observability/logger.d.ts +22 -1
  396. package/dist/observability/logger.js +89 -12
  397. package/dist/observability/metrics.js +4 -5
  398. package/dist/observability/otel-exporter.js +2 -1
  399. package/dist/observability/principal-context.d.ts +14 -7
  400. package/dist/observability/principal-context.js +8 -3
  401. package/dist/observability/run-terminal.d.ts +7 -1
  402. package/dist/observability/run-terminal.js +6 -2
  403. package/dist/observability/secret-env-scrub.d.ts +1 -1
  404. package/dist/observability/secret-env-scrub.js +1 -1
  405. package/dist/orchestration/hardened-vm-runner.d.ts +1 -0
  406. package/dist/orchestration/hardened-vm-runner.js +11 -5
  407. package/dist/orchestration/hardened-vm-worker-runner.d.ts +0 -14
  408. package/dist/orchestration/hardened-vm-worker-runner.js +5 -0
  409. package/dist/orchestration/hardened-vm-worker.js +2 -1
  410. package/dist/orchestration/workflow-completion-inbox.d.ts +3 -3
  411. package/dist/orchestration/workflow-completion-inbox.js +3 -2
  412. package/dist/org-delivery-gate.d.ts +36 -10
  413. package/dist/org-delivery-gate.js +12 -8
  414. package/dist/outbound-dispatcher.d.ts +1 -1
  415. package/dist/outbound-dispatcher.js +6 -12
  416. package/dist/owner-brands.d.ts +81 -0
  417. package/dist/owner-brands.js +42 -0
  418. package/dist/owner-faces.d.ts +532 -0
  419. package/dist/owner-faces.js +126 -0
  420. package/dist/park-row-commit.d.ts +67 -0
  421. package/dist/park-row-commit.js +76 -0
  422. package/dist/parked-decide.d.ts +76 -12
  423. package/dist/parked-decide.js +152 -11
  424. package/dist/parked-revive-surface.d.ts +14 -4
  425. package/dist/parked-revive-surface.js +5 -4
  426. package/dist/peer-directory.d.ts +7 -9
  427. package/dist/peer-directory.js +3 -2
  428. package/dist/permission-rule-vocab.d.ts +53 -8
  429. package/dist/permission-rule-vocab.js +30 -2
  430. package/dist/plugins/adoption-log-sql.d.ts +3 -25
  431. package/dist/plugins/adoption-log-sql.js +23 -21
  432. package/dist/plugins/approval-ask-retired-delete-by-task-m50.d.ts +7 -0
  433. package/dist/plugins/approval-ask-retired-delete-by-task-m50.js +17 -0
  434. package/dist/plugins/approval-ask-store-file.d.ts +18 -7
  435. package/dist/plugins/approval-ask-store-file.js +37 -14
  436. package/dist/plugins/approval-ask-store-memory.d.ts +12 -4
  437. package/dist/plugins/approval-ask-store-memory.js +24 -10
  438. package/dist/plugins/approval-ask-store-sql.d.ts +40 -21
  439. package/dist/plugins/approval-ask-store-sql.js +44 -15
  440. package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
  441. package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
  442. package/dist/plugins/approval-exemption-skill-m46.d.ts +14 -0
  443. package/dist/plugins/approval-exemption-skill-m46.js +21 -0
  444. package/dist/plugins/approval-exemption-store.d.ts +32 -2
  445. package/dist/plugins/approval-exemption-store.js +42 -19
  446. package/dist/plugins/approval-nonce-store.d.ts +39 -12
  447. package/dist/plugins/approval-nonce-store.js +72 -23
  448. package/dist/plugins/blob-backend.d.ts +2 -0
  449. package/dist/plugins/blob-backend.js +9 -6
  450. package/dist/plugins/caching-session-store.d.ts +13 -1
  451. package/dist/plugins/caching-session-store.js +43 -4
  452. package/dist/plugins/checkpoint-index-columns.d.ts +32 -5
  453. package/dist/plugins/checkpoint-index-columns.js +36 -1
  454. package/dist/plugins/checkpoint-store-face.d.ts +83 -10
  455. package/dist/plugins/checkpoint-store-face.js +18 -1
  456. package/dist/plugins/device-store-sql.js +1 -0
  457. package/dist/plugins/ensure-index.d.ts +13 -1
  458. package/dist/plugins/ensure-index.js +154 -21
  459. package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -18
  460. package/dist/plugins/ensure-schema-lock-policy.js +76 -9
  461. package/dist/plugins/file-run-store.d.ts +85 -32
  462. package/dist/plugins/file-run-store.js +177 -94
  463. package/dist/plugins/host-platform.d.ts +24 -3
  464. package/dist/plugins/host-platform.js +15 -1
  465. package/dist/plugins/image-bake-store-sql.js +2 -0
  466. package/dist/plugins/imported-layer-root-retirement.d.ts +2 -2
  467. package/dist/plugins/k8s-pod-reaper.d.ts +1 -3
  468. package/dist/plugins/k8s-pod-reaper.js +0 -1
  469. package/dist/plugins/leader-run-store-sql.d.ts +22 -0
  470. package/dist/plugins/leader-run-store-sql.js +34 -4
  471. package/dist/plugins/local-checkpoint-store.d.ts +62 -23
  472. package/dist/plugins/local-checkpoint-store.js +197 -77
  473. package/dist/plugins/local-data-dir-modes-m39.js +2 -1
  474. package/dist/plugins/local-data-root-admission.d.ts +52 -0
  475. package/dist/plugins/local-data-root-admission.js +100 -0
  476. package/dist/plugins/local-docker-capacity.d.ts +93 -0
  477. package/dist/plugins/local-docker-capacity.js +194 -0
  478. package/dist/plugins/local-docker-reaper.d.ts +92 -0
  479. package/dist/plugins/local-docker-reaper.js +102 -0
  480. package/dist/plugins/local-engine-high-water.d.ts +29 -6
  481. package/dist/plugins/local-engine-high-water.js +27 -19
  482. package/dist/plugins/local-session-store.d.ts +458 -140
  483. package/dist/plugins/local-session-store.js +906 -292
  484. package/dist/plugins/local-session-window.d.ts +3 -2
  485. package/dist/plugins/local-session-window.js +3 -2
  486. package/dist/plugins/local-sidecar-quarantine.js +3 -2
  487. package/dist/plugins/local-task-attachment-store.d.ts +18 -1
  488. package/dist/plugins/local-task-attachment-store.js +22 -1
  489. package/dist/plugins/memory-embedder.js +9 -7
  490. package/dist/plugins/memory-engine-pg.d.ts +3 -2
  491. package/dist/plugins/memory-engine-pg.js +14 -5
  492. package/dist/plugins/memory-engine-sql-apply.d.ts +8 -4
  493. package/dist/plugins/memory-engine-sql-apply.js +6 -8
  494. package/dist/plugins/memory-engine-tidb.d.ts +4 -2
  495. package/dist/plugins/memory-engine-tidb.js +11 -2
  496. package/dist/plugins/memory-optout-grant-store-sql.d.ts +1 -1
  497. package/dist/plugins/memory-optout-grant-store-sql.js +3 -3
  498. package/dist/plugins/memory-run-store.d.ts +53 -36
  499. package/dist/plugins/memory-run-store.js +116 -88
  500. package/dist/plugins/one-time-migration-marker.d.ts +26 -0
  501. package/dist/plugins/one-time-migration-marker.js +13 -0
  502. package/dist/plugins/one-time-migrations.d.ts +214 -47
  503. package/dist/plugins/one-time-migrations.js +481 -135
  504. package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
  505. package/dist/plugins/org-delivery-quota-store.js +31 -15
  506. package/dist/plugins/permission-rule-store-file.d.ts +3 -3
  507. package/dist/plugins/permission-rule-store-sql.d.ts +5 -64
  508. package/dist/plugins/permission-rule-store-sql.js +11 -95
  509. package/dist/plugins/pg-pool.d.ts +2 -32
  510. package/dist/plugins/pg-pool.js +24 -17
  511. package/dist/plugins/remote-env-device.d.ts +3 -2
  512. package/dist/plugins/remote-env-e2b.d.ts +8 -32
  513. package/dist/plugins/remote-env-e2b.js +44 -32
  514. package/dist/plugins/remote-env-host.d.ts +51 -17
  515. package/dist/plugins/remote-env-host.js +111 -42
  516. package/dist/plugins/remote-env-k8s.d.ts +40 -45
  517. package/dist/plugins/remote-env-k8s.js +111 -60
  518. package/dist/plugins/remote-env-local-docker.d.ts +152 -15
  519. package/dist/plugins/remote-env-local-docker.js +352 -72
  520. package/dist/plugins/remote-scratchpad.js +4 -0
  521. package/dist/plugins/retention-deployment.d.ts +49 -17
  522. package/dist/plugins/retention-deployment.js +39 -8
  523. package/dist/plugins/run-preview-m45.d.ts +11 -0
  524. package/dist/plugins/run-preview-m45.js +19 -0
  525. package/dist/plugins/run-store-sql.d.ts +82 -75
  526. package/dist/plugins/run-store-sql.js +164 -125
  527. package/dist/plugins/s3-answer.d.ts +2 -1
  528. package/dist/plugins/sandbox-reaper.d.ts +26 -0
  529. package/dist/plugins/sandbox-reaper.js +2 -0
  530. package/dist/plugins/scenario-prefix-switch-m42.d.ts +56 -0
  531. package/dist/plugins/scenario-prefix-switch-m42.js +56 -0
  532. package/dist/plugins/scheduler-support.d.ts +16 -1
  533. package/dist/plugins/scheduler-support.js +22 -2
  534. package/dist/plugins/schema-consistency.d.ts +131 -14
  535. package/dist/plugins/schema-consistency.js +388 -18
  536. package/dist/plugins/schema-drift-sentence.d.ts +10 -6
  537. package/dist/plugins/schema-drift-sentence.js +15 -7
  538. package/dist/plugins/schema-ensure-legs.d.ts +9 -0
  539. package/dist/plugins/schema-ensure-legs.js +1 -1
  540. package/dist/plugins/schema-indexes.js +3 -0
  541. package/dist/plugins/schema-live-columns.d.ts +14 -5
  542. package/dist/plugins/schema-live-columns.js +10 -10
  543. package/dist/plugins/send-user-file.js +2 -1
  544. package/dist/plugins/session-birth.d.ts +37 -0
  545. package/dist/plugins/session-birth.js +38 -0
  546. package/dist/plugins/session-epoch-anchor.d.ts +40 -12
  547. package/dist/plugins/session-epoch-anchor.js +33 -11
  548. package/dist/plugins/session-ext-table.d.ts +27 -3
  549. package/dist/plugins/session-ext-table.js +19 -6
  550. package/dist/plugins/session-fork.d.ts +15 -1
  551. package/dist/plugins/session-fork.js +3 -0
  552. package/dist/plugins/session-ownership.d.ts +1 -1
  553. package/dist/plugins/session-placement.d.ts +27 -20
  554. package/dist/plugins/session-placement.js +15 -12
  555. package/dist/plugins/session-row-sql.d.ts +12 -0
  556. package/dist/plugins/session-row-sql.js +3 -3
  557. package/dist/plugins/session-run-rollup.d.ts +29 -0
  558. package/dist/plugins/session-run-rollup.js +40 -0
  559. package/dist/plugins/session-store-sql.d.ts +38 -12
  560. package/dist/plugins/session-store-sql.js +130 -30
  561. package/dist/plugins/session-withdraw-sql.d.ts +36 -0
  562. package/dist/plugins/session-withdraw-sql.js +42 -0
  563. package/dist/plugins/shared-memory-store-sql.d.ts +0 -69
  564. package/dist/plugins/shared-memory-store-sql.js +2 -1
  565. package/dist/plugins/shell-sentinel-owner-m48.d.ts +42 -0
  566. package/dist/plugins/shell-sentinel-owner-m48.js +9 -0
  567. package/dist/plugins/snapshot-bucket-presence.d.ts +2 -1
  568. package/dist/plugins/sql-driver.d.ts +1 -1
  569. package/dist/plugins/sql-driver.js +2 -1
  570. package/dist/plugins/sql-errors.d.ts +32 -5
  571. package/dist/plugins/sql-errors.js +55 -7
  572. package/dist/plugins/sql-json-column.d.ts +8 -7
  573. package/dist/plugins/sql-json-column.js +10 -6
  574. package/dist/plugins/stop-then-start-sentence.d.ts +16 -0
  575. package/dist/plugins/stop-then-start-sentence.js +7 -0
  576. package/dist/plugins/store-backend.d.ts +99 -16
  577. package/dist/plugins/store-backend.js +230 -65
  578. package/dist/plugins/store-contracts.d.ts +123 -33
  579. package/dist/plugins/store-contracts.js +38 -1
  580. package/dist/plugins/store-fault.d.ts +28 -2
  581. package/dist/plugins/store-fault.js +20 -2
  582. package/dist/plugins/task-attachment-store.d.ts +15 -3
  583. package/dist/plugins/task-attachment-store.js +22 -9
  584. package/dist/plugins/tidb-pool.d.ts +11 -6
  585. package/dist/plugins/tidb-pool.js +39 -18
  586. package/dist/plugins/web-search.js +5 -3
  587. package/dist/plugins/workflow-run-store-sql.d.ts +6 -1
  588. package/dist/plugins/workflow-run-store-sql.js +11 -5
  589. package/dist/plugins/workspace-custody.d.ts +44 -0
  590. package/dist/plugins/workspace-custody.js +47 -0
  591. package/dist/principal-jwt.d.ts +4 -4
  592. package/dist/principal-jwt.js +20 -5
  593. package/dist/principal-shape.d.ts +41 -0
  594. package/dist/principal-shape.js +19 -0
  595. package/dist/project-identity.d.ts +8 -7
  596. package/dist/project-identity.js +40 -17
  597. package/dist/project-layer-key.d.ts +13 -2
  598. package/dist/project-layer-key.js +9 -1
  599. package/dist/question.d.ts +13 -23
  600. package/dist/question.js +21 -39
  601. package/dist/read-deny-floor-notice.d.ts +36 -0
  602. package/dist/read-deny-floor-notice.js +40 -0
  603. package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
  604. package/dist/request-declaration-disposition.js +39 -0
  605. package/dist/request-declaration-refusal.d.ts +35 -12
  606. package/dist/request-declaration-refusal.js +21 -9
  607. package/dist/request-form.d.ts +58 -0
  608. package/dist/request-form.js +72 -0
  609. package/dist/request-image-urls.d.ts +8 -2
  610. package/dist/request-image-urls.js +2 -1
  611. package/dist/request-images.d.ts +20 -0
  612. package/dist/request-images.js +59 -0
  613. package/dist/request-key-closure.d.ts +6 -7
  614. package/dist/request-key-closure.js +15 -2
  615. package/dist/resource-suspend.d.ts +7 -16
  616. package/dist/resource-suspend.js +1 -1
  617. package/dist/retired-name-host-notice.d.ts +21 -0
  618. package/dist/retired-name-host-notice.js +12 -0
  619. package/dist/rule-entry-list.d.ts +2 -2
  620. package/dist/rule-entry-list.js +3 -4
  621. package/dist/rule-issue-reading.d.ts +58 -0
  622. package/dist/rule-issue-reading.js +14 -0
  623. package/dist/rules-consent.d.ts +5 -3
  624. package/dist/rules-consent.js +1 -0
  625. package/dist/run-acceptance.d.ts +3 -1
  626. package/dist/run-acceptance.js +3 -0
  627. package/dist/run-cancel-card.d.ts +28 -0
  628. package/dist/run-cancel-card.js +19 -0
  629. package/dist/run-cancel-context.d.ts +10 -0
  630. package/dist/run-cancel-context.js +1 -0
  631. package/dist/run-local.d.ts +14 -6
  632. package/dist/run-local.js +117 -90
  633. package/dist/run-stale-default.d.ts +7 -0
  634. package/dist/run-stale-default.js +2 -0
  635. package/dist/runs.d.ts +56 -21
  636. package/dist/runs.js +73 -43
  637. package/dist/runtime-caps-resolver.d.ts +21 -6
  638. package/dist/runtime-caps-resolver.js +17 -4
  639. package/dist/runtime-governance.d.ts +2 -2
  640. package/dist/runtime-governance.js +5 -3
  641. package/dist/sealed-key-layout.d.ts +12 -5
  642. package/dist/sealed-key-layout.js +5 -0
  643. package/dist/sealed-key.d.ts +12 -2
  644. package/dist/sealed-key.js +115 -27
  645. package/dist/security.d.ts +128 -158
  646. package/dist/security.js +163 -59
  647. package/dist/sema-config-dir.d.ts +20 -0
  648. package/dist/sema-config-dir.js +25 -0
  649. package/dist/server-secret-env.d.ts +55 -25
  650. package/dist/server-secret-env.js +75 -22
  651. package/dist/session-agent.d.ts +3 -2
  652. package/dist/session-children-retire.d.ts +13 -8
  653. package/dist/session-children-retire.js +9 -7
  654. package/dist/session-deletion.d.ts +88 -0
  655. package/dist/session-deletion.js +8 -0
  656. package/dist/session-erase.d.ts +145 -0
  657. package/dist/session-erase.js +115 -0
  658. package/dist/session-error-wire.d.ts +5 -5
  659. package/dist/session-error-wire.js +1 -1
  660. package/dist/session-incarnation.d.ts +52 -5
  661. package/dist/session-incarnation.js +19 -2
  662. package/dist/session-policy-wire.d.ts +6 -3
  663. package/dist/session-policy-wire.js +11 -1
  664. package/dist/session-resident-background.d.ts +0 -71
  665. package/dist/session-resident-background.js +4 -3
  666. package/dist/session-row.d.ts +2 -1
  667. package/dist/session-rules-seat.d.ts +12 -0
  668. package/dist/session-rules-seat.js +19 -0
  669. package/dist/session-titler.d.ts +7 -15
  670. package/dist/session-titler.js +1 -1
  671. package/dist/session-workspace.d.ts +3 -3
  672. package/dist/spec-fields.d.ts +57 -3
  673. package/dist/spec-fields.js +72 -51
  674. package/dist/store-admission.d.ts +33 -0
  675. package/dist/store-admission.js +49 -0
  676. package/dist/store-posture.d.ts +141 -20
  677. package/dist/store-posture.js +205 -3
  678. package/dist/stored-request-hooks-m20.js +2 -2
  679. package/dist/stores-sql/background-agent-store-sql.d.ts +11 -2
  680. package/dist/stores-sql/background-agent-store-sql.js +73 -20
  681. package/dist/stores-sql/checkpoint-store-sql.d.ts +34 -29
  682. package/dist/stores-sql/checkpoint-store-sql.js +78 -49
  683. package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
  684. package/dist/stores-sql/file-history-store-sql.js +3 -5
  685. package/dist/stores-sql/mailbox-store-sql.d.ts +7 -4
  686. package/dist/stores-sql/mailbox-store-sql.js +31 -32
  687. package/dist/stores-sql/pg-session-storage.d.ts +7 -5
  688. package/dist/stores-sql/pg-session-storage.js +54 -46
  689. package/dist/stores-sql/retention-store-sql.d.ts +87 -19
  690. package/dist/stores-sql/retention-store-sql.js +92 -27
  691. package/dist/stores-sql/session-policy-store-sql.d.ts +32 -10
  692. package/dist/stores-sql/session-policy-store-sql.js +44 -36
  693. package/dist/stores-sql/session-write-hooks.d.ts +12 -6
  694. package/dist/stores-sql/tidb-session-storage.d.ts +4 -4
  695. package/dist/stores-sql/tidb-session-storage.js +13 -8
  696. package/dist/stores-sql/tidb-session-store.d.ts +36 -17
  697. package/dist/stores-sql/tidb-session-store.js +69 -39
  698. package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
  699. package/dist/stores-sql/tool-result-store-sql.js +4 -6
  700. package/dist/stores-sql/windowed-session-storage.d.ts +5 -0
  701. package/dist/stores-sql/windowed-session-storage.js +9 -0
  702. package/dist/submission-exit.d.ts +50 -0
  703. package/dist/submission-exit.js +108 -0
  704. package/dist/task-a2a.d.ts +3 -8
  705. package/dist/task-a2a.js +28 -30
  706. package/dist/task-cwd.d.ts +43 -7
  707. package/dist/task-cwd.js +11 -0
  708. package/dist/task-mcp.d.ts +3 -3
  709. package/dist/task-mcp.js +4 -4
  710. package/dist/task-settings.d.ts +14 -10
  711. package/dist/task-settings.js +19 -7
  712. package/dist/terminal.d.ts +27 -43
  713. package/dist/terminal.js +49 -14
  714. package/dist/tool-approval.d.ts +173 -163
  715. package/dist/tool-approval.js +247 -232
  716. package/dist/trace/core-keyset-guard.d.ts +13 -6
  717. package/dist/trace/core-vocab-wire.d.ts +95 -0
  718. package/dist/trace/core-vocab-wire.js +15 -0
  719. package/dist/trace/engine-notice-wire.d.ts +24 -21
  720. package/dist/trace/engine-notice-wire.js +7 -3
  721. package/dist/trace/exit-seat.d.ts +30 -4
  722. package/dist/trace/exit-seat.js +40 -36
  723. package/dist/trace/extension-call-face.d.ts +3 -2
  724. package/dist/trace/extension-call-face.js +3 -1
  725. package/dist/trace/ledger-events.d.ts +4 -7
  726. package/dist/trace/ledger-sink.d.ts +4 -31
  727. package/dist/trace/ledger-sink.js +0 -11
  728. package/dist/trace/model-segment.d.ts +5 -5
  729. package/dist/trace/model-segment.js +5 -5
  730. package/dist/trace/project.d.ts +59 -44
  731. package/dist/trace/project.js +60 -26
  732. package/dist/trace/redact.d.ts +135 -27
  733. package/dist/trace/redact.js +884 -260
  734. package/dist/trace/self-minted-wire.d.ts +567 -20
  735. package/dist/trace/self-minted-wire.js +205 -24
  736. package/dist/trace/wire-projection-faces.d.ts +5 -6
  737. package/dist/trace/wire-projection-faces.js +2 -2
  738. package/dist/upstream-body.d.ts +23 -0
  739. package/dist/upstream-body.js +16 -0
  740. package/dist/url-refusal.d.ts +3 -3
  741. package/dist/url-refusal.js +11 -4
  742. package/dist/user-authored-text.d.ts +1 -1
  743. package/dist/user-input-ledger.d.ts +7 -8
  744. package/dist/user-input-ledger.js +1 -1
  745. package/dist/web-admin-client/apply-effective.d.ts +6 -3
  746. package/dist/web-admin-client/apply-effective.js +33 -23
  747. package/dist/web-admin-client/apply-ledger.d.ts +16 -7
  748. package/dist/web-admin-client/apply-ledger.js +5 -2
  749. package/dist/web-admin-client/center-request.d.ts +2 -2
  750. package/dist/web-admin-client/center-request.js +15 -15
  751. package/dist/web-admin-client/effective-keys.d.ts +1 -1
  752. package/dist/web-admin-client/effective-keys.js +1 -1
  753. package/dist/web-admin-client/entry-metadata.d.ts +8 -0
  754. package/dist/web-admin-client/entry-metadata.js +13 -0
  755. package/dist/web-admin-client/http-client.d.ts +1 -1
  756. package/dist/web-admin-client/http-client.js +23 -4
  757. package/dist/web-admin-client/mcp-revocation.d.ts +1 -1
  758. package/dist/web-admin-client/mcp-revocation.js +2 -1
  759. package/dist/web-admin-client/read-warnings.d.ts +1 -0
  760. package/dist/web-admin-client/read-warnings.js +1 -0
  761. package/dist/web-admin-client/restart-signal.js +8 -4
  762. package/dist/web-admin-client/skills-mcp.d.ts +2 -2
  763. package/dist/web-admin-client/types.d.ts +1 -2
  764. package/dist/workspace-space.d.ts +3 -2
  765. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +4 -4
  766. package/docs/error-text-lexicon.json +317 -0
  767. package/package.json +8 -3
  768. package/scripts/drain-check-local.mjs +118 -147
  769. package/scripts/drain-check.mysql.sql +22 -2
  770. package/scripts/drain-check.pg.sql +22 -2
  771. package/scripts/embed-minimal.mjs +183 -0
  772. package/wire-changes/server@7.148.0.json +1517 -0
  773. package/wire-changes/server@7.149.0.json +372 -0
  774. package/dist/http/memory-control-plane-corrupt-reply.d.ts +0 -25
  775. package/dist/http/memory-control-plane-corrupt-reply.js +0 -19
  776. package/dist/http/memory-layer-reply.d.ts +0 -30
  777. package/dist/http/memory-layer-reply.js +0 -24
  778. package/dist/lsp/e2b-bridge.d.ts +0 -57
  779. package/dist/lsp/e2b-bridge.js +0 -139
  780. package/dist/lsp/e2b-manager.d.ts +0 -93
  781. package/dist/lsp/e2b-manager.js +0 -178
  782. package/dist/lsp/lsp-frames.d.ts +0 -14
  783. package/dist/lsp/lsp-frames.js +0 -25
  784. package/dist/lsp/manager.d.ts +0 -129
  785. package/dist/lsp/manager.js +0 -127
  786. package/dist/lsp/types.d.ts +0 -12
  787. package/dist/lsp/types.js +0 -2
  788. package/dist/lsp/ws-transport.d.ts +0 -40
  789. package/dist/lsp/ws-transport.js +0 -210
  790. package/dist/plain-string-record.js +0 -70
@@ -1,22 +1,24 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { composeHostSubprocessEnv, hostSubprocessEnv } from "../server-secret-env.js";
3
3
  import vm from "node:vm";
4
- import { hostShell, resolveHostShell, adoptHostForegroundChild, killTreeSoft, killTreeHard } from "../plugins/host-platform.js";
4
+ import { hostShell, resolveHostShell, adoptHostForegroundChild, killTreeSoft, killTreeHard, signalProcessTree, reapedLeaderGroupAlive } from "../plugins/host-platform.js";
5
5
  import { classifyHooksConfig, DEFAULT_HOOK_TIMEOUT_SECONDS, HOOK_ENTRY_TYPES, HOOK_EVENTS, HOOK_EVENT_OWNER, HOOK_EVENT_MATCHER_FIELD, hookMatcherForm, hookMatcherSelects, interpolateHookEnvVars, } from "@sema-agent/settings-schema/hooks";
6
- import { findUrlCredential, formatConfigPath, outgoingPath } from "@sema-agent/settings-schema";
6
+ import { findUrlCredential, outgoingPath } from "@sema-agent/settings-schema";
7
7
  import { httpHookEnvVarsAllowed, httpHookUrlVerdict } from "@sema-agent/settings-schema";
8
8
  import { ENGINE_OWNED_HOOK_EVENTS } from "@sema-agent/settings-schema/hooks";
9
9
  import { describeToolCatalog } from "@sema-agent/core";
10
- import { hangClassic, wrapClassic } from "./classic-stations.js";
10
+ import { hangClassic } from "./classic-stations.js";
11
11
  import { MAX_HOOK_NOTICE_TEXT_CHARS, boundedNoticeText } from "../fleet/fleet-bus.js";
12
12
  import { recordFailOpen } from "../observability/fail-open.js";
13
- import { LIMIT_REASONS } from "../limit-refusal.js";
13
+ import { LIMIT_REASONS, limitFacts } from "../limit-refusal.js";
14
+ import { fieldCoordinate } from "../http/refusal-body.js";
14
15
  import { clipDataText, echoCallerText } from "../caller-text-echo.js";
15
16
  import { seatText } from "../trace/exit-seat.js";
16
17
  import { redactSecrets, buildDisplaySafeUrl } from "../trace/redact.js";
17
18
  import { canonicalJsonStringify } from "@sema-agent/core";
18
19
  import { ccPromptSystemFor, wrapCondition, parseCcVerdict, CC_EVALUATOR_MAX_OUTPUT_TOKENS } from "./cc-stop-prompt.js";
19
20
  import { ccAgentHookSystemFor } from "./cc-agent-hook-prompt.js";
21
+ import { createEgressFetch } from "../egress-redirect.js";
20
22
  import { renderBranchTranscript } from "./branch-transcript.js";
21
23
  import { buildRequestUrlCredentialRefusal, urlCredentialHeaderExit } from "../url-credential-refusal.js";
22
24
  import { HOOK_PHASES, HOOK_SOURCE_VOCABULARY_SENTENCE, hookLaneOf, hookPhaseOf, readHookGroupSource } from "./hook-source.js";
@@ -34,39 +36,37 @@ const MIN_HOOK_CONTEXT_PARTIAL_CHARS = 256;
34
36
  const MAX_TOOL_RESPONSE_CHARS = 32_768;
35
37
  const MAX_TOOL_INPUT_CHARS = 262_144;
36
38
  const HOOK_ENV_ALLOWLIST = ["PATH", "HOME", "SHELL", "USER", "LOGNAME", "TERM", "TZ", "LANG", "LC_ALL", "LC_CTYPE", "LC_MESSAGES", "TMPDIR"];
37
- function hookChildEnv(layer, spawning) {
38
- const o = { policy: [...HOOK_ENV_ALLOWLIST], allow: [], grants: [layer] };
39
+ function hookChildEnv(layer, putBack, spawning) {
40
+ const o = { policy: [...HOOK_ENV_ALLOWLIST], allow: putBack, grants: [layer] };
39
41
  return spawning ? hostSubprocessEnv({ site: "server.hooks.spawn-env", ...o }) : composeHostSubprocessEnv(o);
40
42
  }
43
+ function hookChildView(ctx) {
44
+ return (layer) => hookChildEnv(layer, ctx.hookEnvAllow, false);
45
+ }
41
46
  function hookEnv(ctx) {
42
- return hookChildEnv(composeHookEnvLayer(ctx.shellEnv, ctx.cwd, undefined), false);
47
+ return hookChildView(ctx)(composeHookEnvLayer(ctx.shellEnv, ctx.cwd, undefined));
43
48
  }
44
49
  export const SETTINGS_HOOK_STATIONS = {
45
- PreToolUse: ["classic.PreToolUse"],
46
- PostToolUse: ["classic.PostToolUse"],
47
- PostToolUseFailure: ["classic.PostToolUseFailure"],
48
- PostToolBatch: ["classic.PostToolBatch"],
49
- UserPromptSubmit: ["classic.UserPromptSubmit"],
50
- Stop: ["classic.Stop", "classic.SubagentStop"],
51
- StopFailure: ["classic.StopFailure"],
52
- PreCompact: ["classic.PreCompact"],
53
- PostCompact: ["classic.PostCompact"],
50
+ PreToolUse: "classic.PreToolUse",
51
+ PostToolUse: "classic.PostToolUse",
52
+ PostToolUseFailure: "classic.PostToolUseFailure",
53
+ PostToolBatch: "classic.PostToolBatch",
54
+ UserPromptSubmit: "classic.UserPromptSubmit",
55
+ Stop: "classic.Stop",
56
+ StopFailure: "classic.StopFailure",
57
+ PreCompact: "classic.PreCompact",
58
+ PostCompact: "classic.PostCompact",
54
59
  };
55
60
  function chainsBelowTaskOn(patterns, station) {
56
61
  return patterns.some((p) => p === station || (p.endsWith(".*") && station.startsWith(p.slice(0, -1))));
57
62
  }
58
- function managedTightenOnlyOn(lane, station, belowTaskChainPatterns) {
59
- return lane === "managed" && chainsBelowTaskOn(belowTaskChainPatterns, station);
60
- }
61
- const MANAGED_REWRITE_UNSHOWN_REASON = "a managed PreToolUse hook rewrote this call's input, but this deployment runs its own handler for this call after the request's hooks and that handler never sees a rewrite made above it, so the rewrite cannot be honored and the call was not executed";
62
- const MANAGED_ALLOW_UNJUDGED_REASON = "a managed PreToolUse hook allowed this call, but this deployment runs its own handler for this call after the request's hooks, and a request hook's allow does not stand in for that handler's judgment, so the call was not executed (the same outcome as the same hook without a managed source)";
63
- function hangTranslator(on, event, translators, lane) {
63
+ const REQUEST_HOOK_REWRITE_UNSHOWN_REASON = "a request PreToolUse hook rewrote this call's input, but this deployment runs its own handler for this call after the request's hooks and that handler never sees a rewrite made above it, so the rewrite cannot be honored and the call was not executed";
64
+ const REQUEST_HOOK_ALLOW_UNJUDGED_REASON = "a request PreToolUse hook allowed this call, but this deployment runs its own handler for this call after the request's hooks, and a request hook's allow does not stand in for that handler's judgment, so the call was not executed";
65
+ function hangTranslator(on, event, translators) {
64
66
  const translate = translators[event];
65
67
  if (translate === undefined)
66
68
  return;
67
- const hang = lane === "managed" ? wrapClassic : hangClassic;
68
- for (const station of SETTINGS_HOOK_STATIONS[event])
69
- hang(on, station, translate);
69
+ hangClassic(on, SETTINGS_HOOK_STATIONS[event], translate);
70
70
  }
71
71
  export const SETTINGS_HOOKS_REGISTRATIONS = {
72
72
  managed: "settings.hooks.managed",
@@ -242,54 +242,61 @@ function hooksCapIssue(limit, event, path, count) {
242
242
  }
243
243
  const matcherPath = (event, groupIndex) => ["hooks", event, groupIndex, "matcher"];
244
244
  export function buildHooksRefusal(issue) {
245
- const field = "settings.hooks";
246
245
  switch (issue.reason) {
247
- case "dead_alias":
246
+ case "dead_alias": {
247
+ const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
248
248
  return {
249
249
  message: `settings.hooks.${issue.event}: matcher "${issue.alias}" is an alias; tool-event matchers match the tool's wire name (PostToolUse / PostToolUseFailure since 7.107.0) — use "${issue.canonical}"`,
250
- field,
251
- detail: { reason: issue.reason, event: issue.event, alias: issue.alias, canonical: issue.canonical, path: matcherPath(issue.event, issue.groupIndex) },
250
+ facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, alias: issue.alias, canonical: issue.canonical },
252
251
  };
253
- case "over_budget":
252
+ }
253
+ case "over_budget": {
254
+ const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
254
255
  return {
255
- message: `settings.hooks.${issue.event}[${issue.groupIndex}].matcher: evaluating the pattern did not finish within ${issue.budgetMs} ms (catastrophic regex backtracking) — rewrite it as a tool-name list or a pattern without nested repetition`,
256
- field,
257
- detail: { reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, budgetMs: issue.budgetMs, path: matcherPath(issue.event, issue.groupIndex) },
256
+ message: `${field}: evaluating the pattern did not finish within ${issue.budgetMs} ms (catastrophic regex backtracking) — rewrite it as a tool-name list or a pattern without nested repetition`,
257
+ facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, budgetMs: issue.budgetMs },
258
258
  };
259
- case "budget_exceeded":
259
+ }
260
+ case "budget_exceeded": {
261
+ const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
260
262
  return {
261
- message: `settings.hooks.${issue.event}[${issue.groupIndex}].matcher: evaluating this configuration's regular-expression matchers took longer than ${issue.totalMs} ms in total (very slow patterns) — write tool names as a list such as "Read|Edit", or simplify the patterns`,
262
- field,
263
- detail: { reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, totalMs: issue.totalMs, path: matcherPath(issue.event, issue.groupIndex) },
263
+ message: `${field}: evaluating this configuration's regular-expression matchers took longer than ${issue.totalMs} ms in total (very slow patterns) — write tool names as a list such as "Read|Edit", or simplify the patterns`,
264
+ facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, totalMs: issue.totalMs },
264
265
  };
265
- case "invalid_regex":
266
+ }
267
+ case "invalid_regex": {
268
+ const field = hooksFieldCoordinate(matcherPath(issue.event, issue.groupIndex));
266
269
  return {
267
- message: `settings.hooks.${issue.event}[${issue.groupIndex}].matcher: ${JSON.stringify(issue.matcher)} is not a valid regular expression (${issue.compileError}) — fix the pattern, or write the tool names as a list such as "Read|Edit"`,
268
- field,
269
- detail: { reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex, path: matcherPath(issue.event, issue.groupIndex) },
270
+ message: `${field}: ${JSON.stringify(issue.matcher)} is not a valid regular expression (${issue.compileError}) — fix the pattern, or write the tool names as a list such as "Read|Edit"`,
271
+ facts: { field, reason: issue.reason, event: issue.event, groupIndex: issue.groupIndex },
270
272
  };
271
- case "unsupported_entry_type":
273
+ }
274
+ case "unsupported_entry_type": {
275
+ const field = hooksFieldCoordinate(issue.path);
272
276
  return {
273
- message: `${hooksCoordinate(issue.path)}: this server does not run hook entries of type ${issue.type}; supported: ${SUPPORTED_HOOK_ENTRY_TYPES.join(" / ")}`,
274
- field,
275
- detail: { reason: issue.reason, path: hooksOutgoingPath(issue.path), type: issue.type },
277
+ message: `${field}: this server does not run hook entries of type ${issue.type}; supported: ${SUPPORTED_HOOK_ENTRY_TYPES.join(" / ")}`,
278
+ facts: { field, reason: issue.reason, type: issue.type },
276
279
  };
280
+ }
277
281
  case "over_cap":
278
282
  case "too_long": {
279
283
  const cap = issue;
280
- return { message: HOOKS_CAPS[cap.limit].sentence(cap.event, cap.count), field, detail: { reason: cap.reason, path: hooksOutgoingPath(cap.path), count: cap.count, cap: cap.cap } };
284
+ return { message: HOOKS_CAPS[cap.limit].sentence(cap.event, cap.count), facts: { ...limitFacts(hooksFieldCoordinate(cap.path), HOOKS_CAPS[cap.limit].measure, cap.count, cap.cap), reason: cap.reason } };
285
+ }
286
+ case "unnamed_refusal": {
287
+ const field = hooksFieldCoordinate(issue.path);
288
+ return { message: `${field}: the hooks reader refused this configuration without naming a piece`, facts: { field, reason: issue.reason } };
289
+ }
290
+ case "wire_key_invalid": {
291
+ const field = hooksFieldCoordinate(issue.path);
292
+ return { message: `${field}: ${HOOKS_WIRE_KEY_SHAPE[issue.key]}`, facts: { field, reason: issue.reason, key: issue.key } };
281
293
  }
282
- case "unnamed_refusal":
283
- return { message: `${hooksCoordinate(issue.path)}: the hooks reader refused this configuration without naming a piece`, field, detail: { reason: issue.reason, path: hooksOutgoingPath(issue.path) } };
284
- case "wire_key_invalid":
285
- return { message: `${hooksCoordinate(issue.path)}: ${HOOKS_WIRE_KEY_SHAPE[issue.key]}`, field, detail: { reason: issue.reason, path: hooksOutgoingPath(issue.path), key: issue.key } };
286
294
  default: {
287
295
  const piece = issue;
288
296
  const key = piece.key !== undefined ? hooksOutgoingKey(piece.key) : undefined;
289
297
  return {
290
298
  message: hooksPieceRefusal(piece),
291
- field,
292
- detail: { reason: piece.reason, path: hooksOutgoingPath(piece.path), ...(key !== undefined ? { key } : {}) },
299
+ facts: { field: hooksFieldCoordinate(piece.path), reason: piece.reason, ...(key !== undefined ? { key } : {}) },
293
300
  };
294
301
  }
295
302
  }
@@ -352,8 +359,8 @@ export function hooksUrlCredentialIssue(config) {
352
359
  return undefined;
353
360
  }
354
361
  export function buildHooksUrlCredentialRefusal(issue) {
355
- const entry = `settings.hooks.${issue.event}[${issue.groupIndex}].hooks[${issue.entryIndex}]`;
356
- return buildRequestUrlCredentialRefusal(`${entry}.url`, issue.credential, urlCredentialHeaderExit(`${entry}.headers`));
362
+ const entry = ["hooks", issue.event, issue.groupIndex, "hooks", issue.entryIndex];
363
+ return buildRequestUrlCredentialRefusal(hooksFieldCoordinate([...entry, "url"]), issue.credential, urlCredentialHeaderExit(hooksFieldCoordinate([...entry, "headers"])));
357
364
  }
358
365
  const HOOKS_PIECE_MEANING = {
359
366
  "hooks-not-object": "`hooks` must be an object keyed by hook event name",
@@ -371,8 +378,8 @@ const HOOKS_PIECE_MEANING = {
371
378
  export function hooksOutgoingPath(path) {
372
379
  return outgoingPath(path).map((seg) => (typeof seg === "string" ? echoCallerText(seg) : seg));
373
380
  }
374
- export function hooksCoordinate(path) {
375
- return `settings.${formatConfigPath(hooksOutgoingPath(path))}`;
381
+ export function hooksFieldCoordinate(path) {
382
+ return fieldCoordinate("settings", hooksOutgoingPath(path));
376
383
  }
377
384
  function hooksOutgoingKey(key) {
378
385
  return echoCallerText(String(outgoingPath([key])[0] ?? ""));
@@ -382,7 +389,7 @@ function hooksPieceIssue(piece) {
382
389
  }
383
390
  function hooksPieceRefusal(piece) {
384
391
  const field = piece.key !== undefined ? ` (field: ${hooksOutgoingKey(piece.key)})` : "";
385
- return `${hooksCoordinate(piece.path)}: ${piece.reason} — ${HOOKS_PIECE_MEANING[piece.reason]}${field}`;
392
+ return `${hooksFieldCoordinate(piece.path)}: ${piece.reason} — ${HOOKS_PIECE_MEANING[piece.reason]}${field}`;
386
393
  }
387
394
  function hooksRefused(issue, pieces) {
388
395
  const error = buildHooksRefusal(issue).message;
@@ -733,24 +740,26 @@ const VERDICT_GAP_CAUSE = {
733
740
  input_truncated: "verdict_unreadable",
734
741
  matcher_over_budget: "verdict_unreadable",
735
742
  };
736
- function createUnrunLedger(ctx, event, toolName) {
743
+ function createUnrunLedger(ctx, event, toolName, once) {
737
744
  let managedVerdictGap;
738
745
  let haltNoted = false;
739
746
  const ledger = {
740
747
  halted(source, entry) {
741
- if (haltNoted)
748
+ if (haltNoted || !isSyncEntry(entry))
742
749
  return;
743
750
  haltNoted = true;
744
751
  ledger.unrun(source, entry, "budget_exhausted", ENGINE_BUDGET_SPENT_DETAIL);
745
752
  },
746
753
  untrusted(source, entry, reason) {
754
+ once.unsettled(entry);
747
755
  if (hookLaneOf(source) === "unmanaged")
748
756
  return;
749
757
  managedVerdictGap ??= VERDICT_GAP_CAUSE[reason];
750
758
  noteVerdictUntrusted(ctx, { event, reason, entry, source, toolName });
751
759
  },
752
760
  unrun(source, entry, reason, detail) {
753
- if (source === undefined || hookLaneOf(source) === "unmanaged")
761
+ once.unsettled(entry);
762
+ if (source === undefined || hookLaneOf(source) === "unmanaged" || !isSyncEntry(entry))
754
763
  return;
755
764
  managedVerdictGap ??= VERDICT_GAP_CAUSE[reason];
756
765
  ctx.logger.warn("hook_managed_unrun", { event, reason, source: echoCallerText(source), type: entry.type, ...(toolName !== undefined ? { tool: toolName } : {}) });
@@ -830,8 +839,12 @@ function withBelowContext(parts, below) {
830
839
  const tail = belowString(below, "additionalContext");
831
840
  return tail === undefined ? [...parts] : [...parts, tail];
832
841
  }
833
- function alsoAsks(below, own) {
834
- return below === undefined || below === own ? own : `${below} (a managed PreToolUse hook also asks: ${own})`;
842
+ const ALSO_ASKS_SPEAKER = {
843
+ managed: "a managed PreToolUse hook",
844
+ unmanaged: "a PreToolUse hook",
845
+ };
846
+ function alsoAsks(lane, below, own) {
847
+ return below === undefined || below === own ? own : `${below} (${ALSO_ASKS_SPEAKER[lane]} also asks: ${own})`;
835
848
  }
836
849
  function readBelowPreToolUse(below) {
837
850
  const action = belowString(below, "action");
@@ -845,20 +858,78 @@ function readBelowPreToolUse(below) {
845
858
  allowed: action === "allow",
846
859
  ...(action === "ask" && (cause === undefined || cause === "asked") ? { asked: message } : {}),
847
860
  ...(action === "ask" && cause !== undefined && cause !== "asked" ? { unreadable: { message, cause: unreadableCause } } : {}),
848
- realApproval: action === "ask" && typeof below === "object" && below !== null && Reflect.get(below, "requiresRealApproval") === true,
861
+ ...(action === "ask" && typeof below === "object" && below !== null && Object.hasOwn(below, "requiresRealApproval") && Reflect.get(below, "requiresRealApproval") === true ? { realApproval: true } : {}),
849
862
  ...(rewrite !== null && typeof rewrite === "object" ? { updatedInput: rewrite } : {}),
850
863
  ...(additionalContext !== undefined ? { additionalContext } : {}),
851
864
  };
852
865
  }
853
866
  function spawnPlannedCommand(plan, ctx, stdio) {
854
- const env = hookChildEnv(plan.env, true);
867
+ const env = hookChildEnv(plan.env, ctx.hookEnvAllow, true);
855
868
  if (plan.kind === "exec")
856
869
  return spawn(plan.file, [...plan.args], { cwd: ctx.cwd, env, stdio, detached: true });
857
870
  const sh = hostShell();
858
871
  return spawn(sh.shell, [...sh.args, plan.command], { cwd: ctx.cwd, env, stdio, detached: true });
859
872
  }
860
- async function runCommandHook(entry, payload, ctx, halt) {
861
- const plan = await planCommandSpawn(entry, ctx.cwd, ctx.shellEnv);
873
+ function createHookTreeLadder(child, ctx, event) {
874
+ const leaderOurs = () => child.pid !== undefined && child.exitCode === null && child.signalCode === null;
875
+ const alive = () => leaderOurs() || (child.pid !== undefined && reapedLeaderGroupAlive(child.pid));
876
+ const shoot = (sig) => {
877
+ const pid = child.pid;
878
+ if (pid === undefined) {
879
+ child.kill(sig);
880
+ return;
881
+ }
882
+ if (leaderOurs()) {
883
+ signalProcessTree(pid, sig);
884
+ return;
885
+ }
886
+ if (!reapedLeaderGroupAlive(pid))
887
+ return;
888
+ try {
889
+ (sig === "SIGTERM" ? killTreeSoft : killTreeHard)(pid);
890
+ }
891
+ catch {
892
+ child.kill(sig);
893
+ }
894
+ };
895
+ let hardFired = false;
896
+ const hard = (end) => {
897
+ if (hardFired)
898
+ return;
899
+ hardFired = true;
900
+ shoot("SIGKILL");
901
+ const recheck = setTimeout(() => {
902
+ const clean = !alive();
903
+ if (!clean)
904
+ shoot("SIGKILL");
905
+ const fields = { event, type: "command", end, shots: clean ? 1 : 2, clean };
906
+ if (clean)
907
+ ctx.logger.info("hook_command_tree_swept", fields);
908
+ else
909
+ ctx.logger.warn("hook_command_tree_swept", fields);
910
+ }, HOOK_KILL_GRACE_MS);
911
+ recheck.unref();
912
+ };
913
+ return {
914
+ halt(onEscalate) {
915
+ shoot("SIGTERM");
916
+ const escalate = setTimeout(() => {
917
+ if (hardFired || !alive())
918
+ return;
919
+ onEscalate();
920
+ hard("halt");
921
+ }, HOOK_KILL_GRACE_MS);
922
+ escalate.unref();
923
+ },
924
+ kill: hard,
925
+ ended() {
926
+ if (alive())
927
+ hard("exit");
928
+ },
929
+ };
930
+ }
931
+ async function runCommandHook(entry, payload, ctx, halt, event) {
932
+ const plan = await planCommandSpawn(entry, ctx.cwd, ctx.shellEnv, hookChildView(ctx));
862
933
  if (plan.kind === "refused")
863
934
  return { code: null, stdout: "", stderr: "", timedOut: false, spawnError: plan.error };
864
935
  if (plan.kind === "shell") {
@@ -882,6 +953,7 @@ async function runCommandHook(entry, payload, ctx, halt) {
882
953
  return;
883
954
  }
884
955
  const ticket = adoptHostForegroundChild(child);
956
+ const tree = createHookTreeLadder(child, ctx, event);
885
957
  let stdout = "";
886
958
  let stderr = "";
887
959
  let timedOut = false;
@@ -900,40 +972,16 @@ async function runCommandHook(entry, payload, ctx, halt) {
900
972
  timedOut = true;
901
973
  if (sent !== undefined)
902
974
  sent = "SIGKILL";
903
- try {
904
- if (child.pid)
905
- process.kill(-child.pid, "SIGKILL");
906
- else
907
- child.kill("SIGKILL");
908
- }
909
- catch {
910
- child.kill("SIGKILL");
911
- }
912
975
  settle(null);
976
+ tree.kill("timeout");
913
977
  }, timeoutMs);
914
- const signalGroup = (sig) => {
915
- try {
916
- if (child.pid)
917
- (sig === "SIGTERM" ? killTreeSoft : killTreeHard)(child.pid);
918
- else
919
- child.kill(sig);
920
- }
921
- catch {
922
- child.kill(sig);
923
- }
924
- };
925
978
  const onHalt = () => {
926
979
  if (settled)
927
980
  return;
928
981
  sent = "SIGTERM";
929
- signalGroup("SIGTERM");
930
- const escalate = setTimeout(() => {
931
- if (child.exitCode !== null || child.signalCode !== null)
932
- return;
982
+ tree.halt(() => {
933
983
  sent = "SIGKILL";
934
- signalGroup("SIGKILL");
935
- }, HOOK_KILL_GRACE_MS);
936
- escalate.unref();
984
+ });
937
985
  };
938
986
  halt.addEventListener("abort", onHalt, { once: true });
939
987
  child.stdout?.on("data", (d) => {
@@ -952,7 +1000,12 @@ async function runCommandHook(entry, payload, ctx, halt) {
952
1000
  resolve({ code: null, stdout, stderr, timedOut, spawnError: String(e) });
953
1001
  }
954
1002
  });
955
- child.on("close", (code) => settle(code));
1003
+ child.on("close", (code) => {
1004
+ const natural = !settled && sent === undefined;
1005
+ settle(code);
1006
+ if (natural)
1007
+ tree.ended();
1008
+ });
956
1009
  child.stdin?.on("error", () => { });
957
1010
  child.stdin?.end(`${JSON.stringify(boundedToolInputPayload(payload))}\n`);
958
1011
  });
@@ -961,7 +1014,7 @@ async function fireAsyncCommandHook(entry, payload, ctx, event, halt) {
961
1014
  try {
962
1015
  const rewake = entry.asyncRewake === true;
963
1016
  const timeoutMs = Math.min(entry.timeout ?? DEFAULT_HOOK_TIMEOUT_SECONDS, MAX_HOOK_TIMEOUT_SECONDS) * 1000;
964
- const plan = await planCommandSpawn(entry, ctx.cwd, ctx.shellEnv);
1017
+ const plan = await planCommandSpawn(entry, ctx.cwd, ctx.shellEnv, hookChildView(ctx));
965
1018
  if (plan.kind === "refused")
966
1019
  throw new Error(plan.error);
967
1020
  if (plan.kind === "shell")
@@ -970,18 +1023,11 @@ async function fireAsyncCommandHook(entry, payload, ctx, event, halt) {
970
1023
  return;
971
1024
  const child = spawnPlannedCommand(plan, ctx, ["pipe", "ignore", rewake ? "pipe" : "ignore"]);
972
1025
  const ticket = adoptHostForegroundChild(child);
1026
+ const tree = createHookTreeLadder(child, ctx, event);
973
1027
  let killedByTimeout = false;
974
1028
  const timer = setTimeout(() => {
975
1029
  killedByTimeout = true;
976
- try {
977
- if (child.pid)
978
- process.kill(-child.pid, "SIGKILL");
979
- else
980
- child.kill("SIGKILL");
981
- }
982
- catch {
983
- child.kill("SIGKILL");
984
- }
1030
+ tree.kill("timeout");
985
1031
  }, timeoutMs);
986
1032
  timer.unref?.();
987
1033
  let stderr = "";
@@ -1000,6 +1046,8 @@ async function fireAsyncCommandHook(entry, payload, ctx, event, halt) {
1000
1046
  child.on("close", (code) => {
1001
1047
  clearTimeout(timer);
1002
1048
  ticket?.release();
1049
+ if (!killedByTimeout)
1050
+ tree.ended();
1003
1051
  noteAsyncOutcome(entry, ctx, event, payload, { code, rewake, killedByTimeout });
1004
1052
  if (!rewake || code !== 2)
1005
1053
  return;
@@ -1119,6 +1167,7 @@ function httpHookWithheldSentence(event, block) {
1119
1167
  return `settings.hooks.${event}: http hook not sent — ${why} (rule: ${block.rule}); ${exit}`;
1120
1168
  }
1121
1169
  const MAX_BLANKED_REFERENCES_LOGGED = 16;
1170
+ const httpHookFetch = createEgressFetch("declare the final address as this hook entry's url");
1122
1171
  async function runHttpHook(entry, payload, ctx, event) {
1123
1172
  const block = httpHookUrlVerdict(entry.url, ctx.httpHookAllowlistLayers, SERVER_WORKSPACE_TRUST);
1124
1173
  if (block !== undefined)
@@ -1146,12 +1195,11 @@ async function runHttpHook(entry, payload, ctx, event) {
1146
1195
  const ac = new AbortController();
1147
1196
  const timer = setTimeout(() => ac.abort(), timeoutMs);
1148
1197
  try {
1149
- const res = await fetch(entry.url, {
1198
+ const res = await httpHookFetch(entry.url, {
1150
1199
  method: "POST",
1151
1200
  headers,
1152
1201
  body: `${JSON.stringify(boundedToolInputPayload(payload))}\n`,
1153
1202
  signal: ac.signal,
1154
- redirect: "error",
1155
1203
  });
1156
1204
  let body = "";
1157
1205
  const reader = res.body?.getReader();
@@ -1277,7 +1325,7 @@ function runRunnableEntry(entry, payload, ctx, event, llmExtra, halt) {
1277
1325
  case "agent":
1278
1326
  return runLlmHook(entry, payload, ctx, { system: ccAgentHookSystemFor(event), event });
1279
1327
  case "command":
1280
- return runCommandHook(entry, payload, ctx, halt);
1328
+ return runCommandHook(entry, payload, ctx, halt, event);
1281
1329
  default: {
1282
1330
  const unreachable = entry;
1283
1331
  void unreachable;
@@ -1285,6 +1333,41 @@ function runRunnableEntry(entry, payload, ctx, event, llmExtra, halt) {
1285
1333
  }
1286
1334
  }
1287
1335
  }
1336
+ async function settleOnce(spentOf, body) {
1337
+ const candidates = new Set();
1338
+ let refused = false;
1339
+ const once = {
1340
+ spent: (entry) => spentOf.has(entry),
1341
+ ran: (entry) => {
1342
+ if (entry.once)
1343
+ candidates.add(entry);
1344
+ },
1345
+ handedOff: (entry) => {
1346
+ if (entry.once)
1347
+ spentOf.add(entry);
1348
+ },
1349
+ unsettled: (entry) => {
1350
+ candidates.delete(entry);
1351
+ },
1352
+ refused: (answer) => {
1353
+ refused = true;
1354
+ return answer;
1355
+ },
1356
+ mark: () => {
1357
+ const at = new Set(candidates);
1358
+ return () => {
1359
+ candidates.clear();
1360
+ for (const entry of at)
1361
+ candidates.add(entry);
1362
+ };
1363
+ },
1364
+ };
1365
+ const answer = await body(once);
1366
+ if (!refused)
1367
+ for (const entry of candidates)
1368
+ spentOf.add(entry);
1369
+ return answer;
1370
+ }
1288
1371
  function isSyncEntry(entry) {
1289
1372
  return !(entry.type === "command" && (entry.async === true || entry.asyncRewake === true));
1290
1373
  }
@@ -1342,7 +1425,7 @@ function noteRanVerdictFlaw(ctx, ledger, event, ran, flaw, toolName) {
1342
1425
  }
1343
1426
  }
1344
1427
  }
1345
- async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceFired, halt, deadlineAt, ledger, llmExtra) {
1428
+ async function runMatchingEntries(event, groups, matchValue, payload, ctx, once, halt, deadlineAt, ledger, llmExtra) {
1346
1429
  const results = [];
1347
1430
  let llmEntries = 0;
1348
1431
  const toolName = toolNameOf(payload);
@@ -1350,10 +1433,10 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
1350
1433
  const truncatedFor = (entry) => (entry.type === "prompt" || entry.type === "agent" ? llmHookArguments(payload).truncated : inputTruncated);
1351
1434
  const blockedBy = (entry, source, cause) => ({ entry, run: blockingFailureRun(event, cause), source });
1352
1435
  let laneSpent = false;
1353
- const settle = async (entry, onceKey) => {
1436
+ const settle = async (entry) => {
1354
1437
  if (halt.signal.aborted)
1355
1438
  return { kind: "halted" };
1356
- if (entry.once && onceFired.has(onceKey))
1439
+ if (entry.once && once.spent(entry))
1357
1440
  return { kind: "passed" };
1358
1441
  let ifOverBudget = false;
1359
1442
  if (entry.if !== undefined) {
@@ -1379,7 +1462,7 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
1379
1462
  }
1380
1463
  if (entry.type === "command" && entry.shell === "powershell") {
1381
1464
  ctx.logger.warn("hook_entries_skipped", { event, type: entry.type, reason: "powershell_not_supported" });
1382
- return isSyncEntry(entry) ? { kind: "unrun", reason: "powershell_unsupported" } : { kind: "passed" };
1465
+ return { kind: "unrun", reason: "powershell_unsupported" };
1383
1466
  }
1384
1467
  if (entry.type === "prompt" || entry.type === "agent") {
1385
1468
  const carrier = entry.type === "prompt" ? ctx.hookLlm : ctx.hookAgent;
@@ -1393,8 +1476,7 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
1393
1476
  }
1394
1477
  }
1395
1478
  if (entry.type === "command" && (entry.async || entry.asyncRewake)) {
1396
- if (entry.once)
1397
- onceFired.add(onceKey);
1479
+ once.handedOff(entry);
1398
1480
  void fireAsyncCommandHook(entry, payload, ctx, event, halt.signal);
1399
1481
  return { kind: "passed" };
1400
1482
  }
@@ -1403,8 +1485,6 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
1403
1485
  ctx.logger.warn("hook_event_deadline_exceeded", { event, budgetSec: MAX_HOOK_EVENT_TOTAL_SECONDS });
1404
1486
  return { kind: "unrun", reason: "budget_exhausted" };
1405
1487
  }
1406
- if (entry.once)
1407
- onceFired.add(onceKey);
1408
1488
  if (entry.type === "prompt" || entry.type === "agent")
1409
1489
  llmEntries++;
1410
1490
  const run = await runRunnableEntry(entry, payload, ctx, event, llmExtra, halt.signal);
@@ -1437,15 +1517,13 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
1437
1517
  return { kind: "unrun", reason: "bad_json" };
1438
1518
  return ifOverBudget ? { kind: "ran", run, overBudget: true } : { kind: "ran", run };
1439
1519
  };
1440
- for (const { group, index } of groups) {
1520
+ for (const group of groups) {
1441
1521
  const pending = laneSpent ? group.hooks.filter((entry) => blocksOnFailure(entry, event)) : group.hooks;
1442
1522
  if (laneSpent && pending.length === 0)
1443
1523
  continue;
1444
1524
  const selected = matcherGroupSelected(ctx, event, group, matchValue, toolName, pending);
1445
1525
  if (selected === "invalid") {
1446
1526
  for (const entry of pending) {
1447
- if (!isSyncEntry(entry))
1448
- continue;
1449
1527
  if (!laneSpent)
1450
1528
  ledger.unrun(group.source, entry, "matcher_invalid");
1451
1529
  if (blocksOnFailure(entry, event))
@@ -1455,12 +1533,13 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
1455
1533
  }
1456
1534
  if (selected === false)
1457
1535
  continue;
1458
- for (const [ei, entry] of group.hooks.entries()) {
1536
+ for (const entry of group.hooks) {
1459
1537
  if (laneSpent && !blocksOnFailure(entry, event))
1460
1538
  continue;
1461
- const fate = await settle(entry, `${event}:${index}:${ei}`);
1539
+ const fate = await settle(entry);
1462
1540
  switch (fate.kind) {
1463
1541
  case "ran": {
1542
+ once.ran(entry);
1464
1543
  const flaw = blocksOnFailure(entry, event) ? ranVerdictFlaw(event, fate.run) : undefined;
1465
1544
  if (flaw !== undefined) {
1466
1545
  noteRanVerdictFlaw(ctx, ledger, event, { entry, run: fate.run, source: group.source }, flaw, toolName);
@@ -1490,7 +1569,7 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
1490
1569
  case "passed":
1491
1570
  break;
1492
1571
  case "halted":
1493
- if (isSyncEntry(entry) && halt.budgetSpent())
1572
+ if (halt.budgetSpent())
1494
1573
  ledger.halted(group.source, entry);
1495
1574
  return results;
1496
1575
  default: {
@@ -1508,17 +1587,16 @@ function createEventClock() {
1508
1587
  }
1509
1588
  const ENGINE_BUDGET_SPENT_DETAIL = "the managed lane's handler ran past its engine budget (HOOKS_TIMEOUT_MS); the managed entries after this one did not run on this event";
1510
1589
  function hookPhasesOf(groups) {
1511
- const indexed = groups.map((group, index) => ({ group, index, phase: hookPhaseOf(group.source) }));
1512
- return HOOK_PHASES.map((phase) => ({ phase, groups: indexed.filter((g) => g.phase === phase).map(({ group, index }) => ({ group, index })) })).filter((l) => l.groups.length > 0);
1590
+ return HOOK_PHASES.map((phase) => ({ phase, groups: groups.filter((g) => hookPhaseOf(g.source) === phase) })).filter((l) => l.groups.length > 0);
1513
1591
  }
1514
1592
  function trustRank(phase) {
1515
1593
  return HOOK_PHASES.length - 1 - HOOK_PHASES.indexOf(phase);
1516
1594
  }
1517
- async function runEventLanes(event, groups, matchValue, payload, ctx, onceFired, halt, ledger, llmExtra) {
1595
+ async function runEventLanes(event, groups, matchValue, payload, ctx, once, halt, ledger, llmExtra) {
1518
1596
  const deadline = createEventClock();
1519
1597
  const ran = [];
1520
1598
  for (const lane of hookPhasesOf(groups)) {
1521
- for (const r of await runMatchingEntries(event, lane.groups, matchValue, payload, ctx, onceFired, halt, deadline(), ledger, llmExtra))
1599
+ for (const r of await runMatchingEntries(event, lane.groups, matchValue, payload, ctx, once, halt, deadline(), ledger, llmExtra))
1522
1600
  ran.push({ ...r, phase: lane.phase });
1523
1601
  }
1524
1602
  return ran.sort((a, b) => trustRank(a.phase) - trustRank(b.phase)).map(({ entry, run, source }) => ({ entry, run, source }));
@@ -1534,9 +1612,9 @@ function basePayload(ctx, permissionMode) {
1534
1612
  function ignoreMatchers(groups) {
1535
1613
  return groups.map((g) => (g.matcher === undefined ? g : { ...g, matcher: undefined }));
1536
1614
  }
1537
- async function runObserveOnlyEvent(event, groups, matchValue, payload, ctx, onceFired, halt) {
1538
- const ledger = createUnrunLedger(ctx, event, toolNameOf(payload));
1539
- const singles = await runEventLanes(event, groups, matchValue, payload, ctx, onceFired, halt, ledger);
1615
+ async function runObserveOnlyEvent(event, groups, matchValue, payload, ctx, once, halt) {
1616
+ const ledger = createUnrunLedger(ctx, event, toolNameOf(payload), once);
1617
+ const singles = await runEventLanes(event, groups, matchValue, payload, ctx, once, halt, ledger);
1540
1618
  for (const ran of singles) {
1541
1619
  const { run } = ran;
1542
1620
  if (run.code !== 0) {
@@ -1589,17 +1667,16 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1589
1667
  if (!pre && !post && !postFailure && !postBatch && !promptSubmit && !stopEntries && !stopFailureEntries && !preCompactEntries && !postCompactEntries) {
1590
1668
  return undefined;
1591
1669
  }
1592
- const onceFired = new Set();
1670
+ const onceSpent = new Set();
1593
1671
  const translators = {};
1594
1672
  if (pre) {
1595
- const tightenOnly = managedTightenOnlyOn(lane, "classic.PreToolUse", ctx.belowTaskChainPatterns);
1596
- translators.PreToolUse = async (e, halt, below) => {
1673
+ const tightenOnly = chainsBelowTaskOn(ctx.belowTaskChainPatterns, "classic.PreToolUse");
1674
+ translators.PreToolUse = (e, halt, below) => settleOnce(onceSpent, async (once) => {
1597
1675
  const prior = readBelowPreToolUse(below);
1598
- const realApproval = prior.realApproval ? { requiresRealApproval: true } : {};
1599
1676
  if (prior.denied)
1600
1677
  return undefined;
1601
1678
  const toolName = e.tool;
1602
- const ledger = createUnrunLedger(ctx, "PreToolUse", toolName);
1679
+ const ledger = createUnrunLedger(ctx, "PreToolUse", toolName, once);
1603
1680
  const deadline = createEventClock();
1604
1681
  let currentInput = prior.updatedInput ?? e.input;
1605
1682
  let rewritten = prior.updatedInput !== undefined;
@@ -1609,9 +1686,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1609
1686
  let unknownDecision = false;
1610
1687
  const contexts = { unmanaged: [], managedPlugin: [], managedPolicy: [] };
1611
1688
  const contextField = () => buildHookContextField([...[...HOOK_PHASES].sort((a, b) => trustRank(a) - trustRank(b)).flatMap((p) => contexts[p]), ...(prior.additionalContext !== undefined ? [prior.additionalContext] : [])]);
1612
- const runPass = async (phase, groups, once) => {
1689
+ const strictness = prior.realApproval === true ? { requiresRealApproval: true } : {};
1690
+ const runPass = async (phase, groups) => {
1613
1691
  let rewroteBy;
1614
- for (const laneGroup of groups) {
1692
+ for (const group of groups) {
1615
1693
  const groupInput = currentInput;
1616
1694
  const payload = {
1617
1695
  ...basePayload(ctx, e.permissionMode),
@@ -1620,7 +1698,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1620
1698
  tool_input: groupInput,
1621
1699
  tool_use_id: e.tool_use_id,
1622
1700
  };
1623
- const singles = await runMatchingEntries("PreToolUse", [laneGroup], toolName, payload, ctx, once, halt, deadline(), ledger);
1701
+ const singles = await runMatchingEntries("PreToolUse", [group], toolName, payload, ctx, once, halt, deadline(), ledger);
1624
1702
  for (const ran of singles) {
1625
1703
  const { entry, run } = ran;
1626
1704
  if (run.code === 2) {
@@ -1659,13 +1737,14 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1659
1737
  const proposed = h.updatedInput !== null && typeof h.updatedInput === "object" ? h.updatedInput : undefined;
1660
1738
  const proposesRewrite = proposed !== undefined && canonicalJsonStringify(proposed) !== canonicalJsonStringify(groupInput);
1661
1739
  if (tightenOnly && ran.distrust === undefined && (decision === "allow" || (proposesRewrite && (decision === "ask" || decision === undefined)))) {
1662
- return { deny: { action: "deny", message: proposesRewrite ? MANAGED_REWRITE_UNSHOWN_REASON : MANAGED_ALLOW_UNJUDGED_REASON, ...contextField() } };
1740
+ return { deny: { action: "deny", message: proposesRewrite ? REQUEST_HOOK_REWRITE_UNSHOWN_REASON : REQUEST_HOOK_ALLOW_UNJUDGED_REASON, ...contextField() } };
1663
1741
  }
1664
1742
  if (decision === "ask") {
1665
- asked = alsoAsks(prior.asked ?? prior.unreadable?.message, clipDataText(typeof h.permissionDecisionReason === "string" ? h.permissionDecisionReason : "a PreToolUse hook requires approval", MAX_HOOK_FEEDBACK_CHARS));
1743
+ asked = alsoAsks(lane, prior.asked ?? prior.unreadable?.message, clipDataText(typeof h.permissionDecisionReason === "string" ? h.permissionDecisionReason : "a PreToolUse hook requires approval", MAX_HOOK_FEEDBACK_CHARS));
1666
1744
  spoke = true;
1667
1745
  }
1668
- if (decision === "allow" || decision === undefined) {
1746
+ const counted = decision === "allow" || decision === "ask" || decision === undefined;
1747
+ if (counted) {
1669
1748
  if (ran.distrust !== undefined && hookLaneOf(ran.source) === "unmanaged" && (decision === "allow" || proposesRewrite)) {
1670
1749
  noteVerdictUntrusted(ctx, { event: "PreToolUse", reason: ran.distrust, entry, source: ran.source, toolName });
1671
1750
  }
@@ -1694,54 +1773,52 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1694
1773
  };
1695
1774
  for (const lane of hookPhasesOf(pre)) {
1696
1775
  if (lane.phase === "unmanaged") {
1697
- const pass = await runPass(lane.phase, lane.groups, onceFired);
1776
+ const pass = await runPass(lane.phase, lane.groups);
1698
1777
  if (pass.deny !== undefined)
1699
- return pass.deny;
1778
+ return once.refused(pass.deny);
1700
1779
  continue;
1701
1780
  }
1702
- const onceBefore = new Set(onceFired);
1703
- const first = await runPass(lane.phase, lane.groups, onceFired);
1781
+ const rollback = once.mark();
1782
+ const first = await runPass(lane.phase, lane.groups);
1704
1783
  if (first.deny !== undefined)
1705
- return first.deny;
1784
+ return once.refused(first.deny);
1706
1785
  if (first.rewroteBy === undefined)
1707
1786
  continue;
1708
1787
  contexts[lane.phase].length = 0;
1709
- const rejudgeOnce = new Set(onceBefore);
1710
- const second = await runPass(lane.phase, lane.groups, rejudgeOnce);
1711
- for (const key of rejudgeOnce)
1712
- onceFired.add(key);
1788
+ rollback();
1789
+ const second = await runPass(lane.phase, lane.groups);
1713
1790
  if (second.deny !== undefined)
1714
- return second.deny;
1791
+ return once.refused(second.deny);
1715
1792
  if (second.rewroteBy !== undefined) {
1716
1793
  ledger.unrun(second.rewroteBy.source, second.rewroteBy.entry, "rewrite_unsettled", "the managed hooks of this phase rewrote the tool input again after being re-run on their own rewrite; approval required");
1717
1794
  }
1718
1795
  }
1719
1796
  const managedGap = ledger.managedVerdictGap;
1720
- if (below !== undefined && !spoke && managedGap === undefined)
1797
+ if (!spoke && managedGap === undefined)
1721
1798
  return undefined;
1722
1799
  if (asked !== undefined) {
1723
- return { action: "ask", message: asked, questionCause: "asked", ...(rewritten ? { updatedInput: currentInput } : {}), ...realApproval, ...contextField() };
1800
+ return { action: "ask", message: asked, questionCause: "asked", ...strictness, ...(rewritten ? { updatedInput: currentInput } : {}), ...contextField() };
1724
1801
  }
1725
1802
  if (managedGap !== undefined) {
1726
1803
  return {
1727
1804
  action: "ask",
1728
1805
  message: "a managed PreToolUse hook did not run to a verdict — approval required",
1729
1806
  questionCause: managedGap,
1807
+ ...strictness,
1730
1808
  ...(rewritten ? { updatedInput: currentInput } : {}),
1731
- ...realApproval,
1732
1809
  ...contextField(),
1733
1810
  };
1734
1811
  }
1735
1812
  if (prior.unreadable !== undefined) {
1736
- return { action: "ask", message: prior.unreadable.message, questionCause: prior.unreadable.cause, ...(rewritten ? { updatedInput: currentInput } : {}), ...realApproval, ...contextField() };
1813
+ return { action: "ask", message: prior.unreadable.message, questionCause: prior.unreadable.cause, ...strictness, ...(rewritten ? { updatedInput: currentInput } : {}), ...contextField() };
1737
1814
  }
1738
1815
  if (unknownDecision) {
1739
1816
  return {
1740
1817
  action: "ask",
1741
1818
  message: "a PreToolUse hook returned an unrecognized permissionDecision — approval required",
1742
1819
  questionCause: "verdict_unreadable",
1820
+ ...strictness,
1743
1821
  ...(rewritten ? { updatedInput: currentInput } : {}),
1744
- ...realApproval,
1745
1822
  ...contextField(),
1746
1823
  };
1747
1824
  }
@@ -1751,10 +1828,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1751
1828
  if (rewritten || HOOK_PHASES.some((p) => contexts[p].length > 0) || prior.additionalContext !== undefined)
1752
1829
  return carried;
1753
1830
  return undefined;
1754
- };
1831
+ });
1755
1832
  }
1756
1833
  if (post) {
1757
- translators.PostToolUse = async (e, halt, below) => {
1834
+ translators.PostToolUse = (e, halt, below) => settleOnce(onceSpent, async (once) => {
1758
1835
  const toolName = e.tool;
1759
1836
  const input = e.input;
1760
1837
  const output = e.output;
@@ -1770,8 +1847,8 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1770
1847
  tool_response: { isError: output.isError, text: clipDataText(responseText, MAX_TOOL_RESPONSE_CHARS) },
1771
1848
  tool_use_id: e.tool_use_id,
1772
1849
  };
1773
- const ledger = createUnrunLedger(ctx, "PostToolUse", toolName);
1774
- const singles = await runEventLanes("PostToolUse", post, toolName, payload, ctx, onceFired, halt, ledger);
1850
+ const ledger = createUnrunLedger(ctx, "PostToolUse", toolName, once);
1851
+ const singles = await runEventLanes("PostToolUse", post, toolName, payload, ctx, once, halt, ledger);
1775
1852
  for (const ran of singles) {
1776
1853
  const { entry, run } = ran;
1777
1854
  if (run.code === 2) {
@@ -1807,10 +1884,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1807
1884
  if (contexts.length === 0)
1808
1885
  return undefined;
1809
1886
  return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
1810
- };
1887
+ });
1811
1888
  }
1812
1889
  if (postFailure) {
1813
- translators.PostToolUseFailure = async (e, halt, below) => {
1890
+ translators.PostToolUseFailure = (e, halt, below) => settleOnce(onceSpent, async (once) => {
1814
1891
  const toolName = e.tool;
1815
1892
  const f = e.failure;
1816
1893
  const contexts = [];
@@ -1823,8 +1900,8 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1823
1900
  error: clipDataText(f.error, MAX_TOOL_RESPONSE_CHARS),
1824
1901
  is_interrupt: f.isInterrupt,
1825
1902
  };
1826
- const ledger = createUnrunLedger(ctx, "PostToolUseFailure", toolName);
1827
- const singles = await runEventLanes("PostToolUseFailure", postFailure, toolName, payload, ctx, onceFired, halt, ledger);
1903
+ const ledger = createUnrunLedger(ctx, "PostToolUseFailure", toolName, once);
1904
+ const singles = await runEventLanes("PostToolUseFailure", postFailure, toolName, payload, ctx, once, halt, ledger);
1828
1905
  for (const ran of singles) {
1829
1906
  const { entry, run } = ran;
1830
1907
  if (run.code === 2) {
@@ -1856,10 +1933,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1856
1933
  if (contexts.length === 0)
1857
1934
  return undefined;
1858
1935
  return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
1859
- };
1936
+ });
1860
1937
  }
1861
1938
  if (postBatch) {
1862
- translators.PostToolBatch = async (e, halt, below) => {
1939
+ translators.PostToolBatch = (e, halt, below) => settleOnce(onceSpent, async (once) => {
1863
1940
  const contexts = [];
1864
1941
  const payload = {
1865
1942
  ...basePayload(ctx, e.permissionMode),
@@ -1871,8 +1948,8 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1871
1948
  tool_response: { isError: c.isError, ...(c.response !== undefined ? { text: clipDataText(c.response, MAX_TOOL_RESPONSE_CHARS) } : {}) },
1872
1949
  })),
1873
1950
  };
1874
- const ledger = createUnrunLedger(ctx, "PostToolBatch", undefined);
1875
- const singles = await runEventLanes("PostToolBatch", ignoreMatchers(postBatch), "", payload, ctx, onceFired, halt, ledger);
1951
+ const ledger = createUnrunLedger(ctx, "PostToolBatch", undefined, once);
1952
+ const singles = await runEventLanes("PostToolBatch", ignoreMatchers(postBatch), "", payload, ctx, once, halt, ledger);
1876
1953
  for (const ran of singles) {
1877
1954
  const { entry, run } = ran;
1878
1955
  if (run.code === 2) {
@@ -1900,19 +1977,19 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1900
1977
  if (contexts.length === 0)
1901
1978
  return undefined;
1902
1979
  return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
1903
- };
1980
+ });
1904
1981
  }
1905
1982
  if (promptSubmit) {
1906
- translators.UserPromptSubmit = async (e, halt, below) => {
1983
+ translators.UserPromptSubmit = (e, halt, below) => settleOnce(onceSpent, async (once) => {
1907
1984
  const contexts = [];
1908
1985
  const payload = { ...basePayload(ctx, e.permissionMode), hook_event_name: "UserPromptSubmit", prompt: clipDataText(e.prompt, MAX_TOOL_INPUT_CHARS) };
1909
- const ledger = createUnrunLedger(ctx, "UserPromptSubmit", undefined);
1910
- const singles = await runEventLanes("UserPromptSubmit", ignoreMatchers(promptSubmit), "", payload, ctx, onceFired, halt, ledger);
1986
+ const ledger = createUnrunLedger(ctx, "UserPromptSubmit", undefined, once);
1987
+ const singles = await runEventLanes("UserPromptSubmit", ignoreMatchers(promptSubmit), "", payload, ctx, once, halt, ledger);
1911
1988
  for (const ran of singles) {
1912
1989
  const { entry, run } = ran;
1913
1990
  if (run.code === 2) {
1914
1991
  const reason = clipDataText(run.stderr.trim(), MAX_HOOK_FEEDBACK_CHARS) || "blocked by a UserPromptSubmit hook";
1915
- return { block: reason, ...buildHookContextField(contexts) };
1992
+ return once.refused({ block: reason, ...buildHookContextField(contexts) });
1916
1993
  }
1917
1994
  if (run.code !== 0) {
1918
1995
  noteExitNonzero(ctx, ledger, "UserPromptSubmit", ran);
@@ -1925,11 +2002,11 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1925
2002
  logHookSystemMessage(ctx, "UserPromptSubmit", out.systemMessage);
1926
2003
  if (out.continue === false) {
1927
2004
  const reason = clipDataText(typeof out.stopReason === "string" ? out.stopReason : "hook requested stop", MAX_HOOK_FEEDBACK_CHARS);
1928
- return { block: reason, ...buildHookContextField(contexts) };
2005
+ return once.refused({ block: reason, ...buildHookContextField(contexts) });
1929
2006
  }
1930
2007
  if (out.decision === "block") {
1931
2008
  const reason = clipDataText(typeof out.reason === "string" ? out.reason : "blocked by a UserPromptSubmit hook", MAX_HOOK_FEEDBACK_CHARS);
1932
- return { block: reason, ...buildHookContextField(contexts) };
2009
+ return once.refused({ block: reason, ...buildHookContextField(contexts) });
1933
2010
  }
1934
2011
  const hso = out.hookSpecificOutput;
1935
2012
  if (hso !== null && typeof hso === "object" && hso.hookEventName === "UserPromptSubmit") {
@@ -1941,10 +2018,10 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1941
2018
  if (contexts.length === 0)
1942
2019
  return undefined;
1943
2020
  return { ...belowMembers(below), ...buildHookContextField(withBelowContext(contexts, below)) };
1944
- };
2021
+ });
1945
2022
  }
1946
2023
  if (stopEntries) {
1947
- translators.Stop = async (sctx, halt, below) => {
2024
+ translators.Stop = (sctx, halt, below) => settleOnce(onceSpent, async (once) => {
1948
2025
  const payload = { ...basePayload(ctx, sctx.permissionMode), hook_event_name: "Stop", stop_hook_active: sctx.stopHookActive };
1949
2026
  let llmExtra;
1950
2027
  const wantsPrompt = stopEntries.some((g) => g.hooks.some((h) => h.type === "prompt"));
@@ -1972,7 +2049,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1972
2049
  }
1973
2050
  }
1974
2051
  const stopGroups = ignoreMatchers(stopEntries);
1975
- const ledger = createUnrunLedger(ctx, "Stop", undefined);
2052
+ const ledger = createUnrunLedger(ctx, "Stop", undefined, once);
1976
2053
  if (!llmExtra && wantsPrompt) {
1977
2054
  for (const g of stopGroups)
1978
2055
  for (const h of g.hooks)
@@ -1982,7 +2059,7 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
1982
2059
  const effectiveGroups = llmExtra || !wantsPrompt
1983
2060
  ? stopGroups
1984
2061
  : stopGroups.map((g) => ({ ...g, hooks: g.hooks.filter((h) => h.type !== "prompt") })).filter((g) => g.hooks.length > 0);
1985
- const singles = await runEventLanes("Stop", effectiveGroups, "", payload, ctx, onceFired, halt, ledger, llmExtra);
2062
+ const singles = await runEventLanes("Stop", effectiveGroups, "", payload, ctx, once, halt, ledger, llmExtra);
1986
2063
  let block;
1987
2064
  let sawContinueFalse = false;
1988
2065
  const contexts = [];
@@ -2036,15 +2113,16 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
2036
2113
  return undefined;
2037
2114
  if (block === undefined && contexts.length === 0)
2038
2115
  return undefined;
2039
- return {
2116
+ const answer = {
2040
2117
  ...belowMembers(below),
2041
2118
  ...(block !== undefined ? { block } : {}),
2042
2119
  ...buildHookContextField(withBelowContext(contexts, below)),
2043
2120
  };
2044
- };
2121
+ return block !== undefined ? once.refused(answer) : answer;
2122
+ });
2045
2123
  }
2046
2124
  if (stopFailureEntries) {
2047
- translators.StopFailure = async (fctx, halt) => {
2125
+ translators.StopFailure = (fctx, halt) => settleOnce(onceSpent, async (once) => {
2048
2126
  const turnError = toAssistantTurnError(fctx.errorKind);
2049
2127
  const payload = {
2050
2128
  ...basePayload(ctx, undefined),
@@ -2052,23 +2130,23 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
2052
2130
  error: turnError,
2053
2131
  ...(fctx.error ? { error_details: clipDataText(redactSecrets(fctx.error), MAX_HOOK_FEEDBACK_CHARS) } : {}),
2054
2132
  };
2055
- await runObserveOnlyEvent("StopFailure", stopFailureEntries, turnError, payload, ctx, onceFired, halt);
2056
- };
2133
+ await runObserveOnlyEvent("StopFailure", stopFailureEntries, turnError, payload, ctx, once, halt);
2134
+ });
2057
2135
  }
2058
2136
  if (preCompactEntries) {
2059
- translators.PreCompact = async (pctx, halt, below) => {
2137
+ translators.PreCompact = (pctx, halt, below) => settleOnce(onceSpent, async (once) => {
2060
2138
  const payload = {
2061
2139
  ...basePayload(ctx, undefined),
2062
2140
  hook_event_name: "PreCompact",
2063
2141
  trigger: pctx.trigger,
2064
2142
  custom_instructions: pctx.customInstructions ?? null,
2065
2143
  };
2066
- const ledger = createUnrunLedger(ctx, "PreCompact", undefined);
2067
- const singles = await runEventLanes("PreCompact", preCompactEntries, pctx.trigger, payload, ctx, onceFired, halt, ledger);
2144
+ const ledger = createUnrunLedger(ctx, "PreCompact", undefined, once);
2145
+ const singles = await runEventLanes("PreCompact", preCompactEntries, pctx.trigger, payload, ctx, once, halt, ledger);
2068
2146
  for (const ran of singles) {
2069
2147
  const { entry, run } = ran;
2070
2148
  if (run.code === 2) {
2071
- return { ...belowMembers(below), block: clipDataText(run.stderr.trim(), MAX_HOOK_FEEDBACK_CHARS) || "blocked by a PreCompact hook" };
2149
+ return once.refused({ ...belowMembers(below), block: clipDataText(run.stderr.trim(), MAX_HOOK_FEEDBACK_CHARS) || "blocked by a PreCompact hook" });
2072
2150
  }
2073
2151
  if (run.code !== 0) {
2074
2152
  noteExitNonzero(ctx, ledger, "PreCompact", ran);
@@ -2083,31 +2161,31 @@ function createLaneRegistration(lane, config, ctx, budgetMs) {
2083
2161
  ctx.logger.warn("hook_continue_false_unsupported", { event: "PreCompact" });
2084
2162
  }
2085
2163
  if (out.decision === "block") {
2086
- return { ...belowMembers(below), block: clipDataText(typeof out.reason === "string" ? out.reason : "blocked by a PreCompact hook", MAX_HOOK_FEEDBACK_CHARS) };
2164
+ return once.refused({ ...belowMembers(below), block: clipDataText(typeof out.reason === "string" ? out.reason : "blocked by a PreCompact hook", MAX_HOOK_FEEDBACK_CHARS) });
2087
2165
  }
2088
2166
  }
2089
2167
  return undefined;
2090
- };
2168
+ });
2091
2169
  }
2092
2170
  if (postCompactEntries) {
2093
- translators.PostCompact = async (cctx, halt) => {
2171
+ translators.PostCompact = (cctx, halt) => settleOnce(onceSpent, async (once) => {
2094
2172
  const payload = {
2095
2173
  ...basePayload(ctx, undefined),
2096
2174
  hook_event_name: "PostCompact",
2097
2175
  trigger: cctx.trigger,
2098
2176
  compact_summary: clipDataText(cctx.summary, MAX_TOOL_RESPONSE_CHARS),
2099
2177
  };
2100
- await runObserveOnlyEvent("PostCompact", postCompactEntries, cctx.trigger, payload, ctx, onceFired, halt);
2101
- };
2178
+ await runObserveOnlyEvent("PostCompact", postCompactEntries, cctx.trigger, payload, ctx, once, halt);
2179
+ });
2102
2180
  }
2103
2181
  const events = Object.keys(translators);
2104
2182
  return {
2105
2183
  name: SETTINGS_HOOKS_REGISTRATIONS[lane],
2106
- uses: { events: events.flatMap((event) => SETTINGS_HOOK_STATIONS[event]), calls: [] },
2184
+ uses: { events: events.map((event) => SETTINGS_HOOK_STATIONS[event]), calls: [] },
2107
2185
  budgetMs,
2108
2186
  register(on) {
2109
2187
  for (const event of events)
2110
- hangTranslator(on, event, translators, lane);
2188
+ hangTranslator(on, event, translators);
2111
2189
  },
2112
2190
  };
2113
2191
  }