@sema-agent/core 7.51.2 → 7.53.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 (446) hide show
  1. package/CHANGELOG.md +698 -2
  2. package/README.md +3 -1
  3. package/dist/agents/agent-transcript-tool.d.ts +1 -1
  4. package/dist/agents/cascade.js +4 -0
  5. package/dist/agents/cross-session-envelope.d.ts +8 -0
  6. package/dist/agents/cross-session-envelope.js +6 -0
  7. package/dist/agents/cross-session-judge.d.ts +21 -1
  8. package/dist/agents/cross-session-judge.js +8 -0
  9. package/dist/agents/cross-session-ref.d.ts +5 -0
  10. package/dist/agents/cross-session-ref.js +1 -0
  11. package/dist/agents/cumulative-stats.d.ts +3 -0
  12. package/dist/agents/cumulative-stats.js +3 -0
  13. package/dist/agents/list-agents-tool.d.ts +1 -1
  14. package/dist/agents/org-delivery-gate.d.ts +122 -0
  15. package/dist/agents/org-delivery-gate.js +69 -0
  16. package/dist/agents/peer-held-queue.d.ts +9 -4
  17. package/dist/agents/peer-held-queue.js +6 -5
  18. package/dist/agents/peer-session-drain.d.ts +35 -5
  19. package/dist/agents/peer-session-drain.js +271 -180
  20. package/dist/agents/read-inbox-tool.d.ts +8 -1
  21. package/dist/agents/read-inbox-tool.js +5 -1
  22. package/dist/agents/repair-loop.js +4 -0
  23. package/dist/agents/send-message-tool.d.ts +11 -16
  24. package/dist/agents/send-message-tool.js +11 -13
  25. package/dist/agents/subagent.d.ts +3 -0
  26. package/dist/agents/subagent.js +105 -76
  27. package/dist/agents/tool-filter.d.ts +58 -13
  28. package/dist/agents/tool-filter.js +34 -14
  29. package/dist/bench/metrics.d.ts +1 -0
  30. package/dist/brain/anthropic.d.ts +6 -1
  31. package/dist/brain/anthropic.js +17 -13
  32. package/dist/brain/model-presets.d.ts +4 -5
  33. package/dist/brain/model-presets.js +6 -5
  34. package/dist/brain/open-responses.js +16 -12
  35. package/dist/brain/openai.js +16 -12
  36. package/dist/brain/request-params.d.ts +12 -33
  37. package/dist/brain/request-params.js +5 -2
  38. package/dist/brain/request-route.d.ts +9 -8
  39. package/dist/brain/request-route.js +1 -0
  40. package/dist/brain/route-adjudicator.d.ts +123 -47
  41. package/dist/brain/route-adjudicator.js +171 -42
  42. package/dist/brain/route-conformance.js +2 -2
  43. package/dist/brain/routing.d.ts +24 -1
  44. package/dist/brain/routing.js +54 -19
  45. package/dist/brain/status-sink.d.ts +18 -0
  46. package/dist/brain/status-sink.js +7 -0
  47. package/dist/brain/timeout.js +5 -4
  48. package/dist/core/a2a.d.ts +5 -2
  49. package/dist/core/a2a.js +30 -13
  50. package/dist/core/allow-entry.d.ts +42 -9
  51. package/dist/core/allow-entry.js +25 -18
  52. package/dist/core/auto-compaction.d.ts +80 -20
  53. package/dist/core/auto-compaction.js +65 -18
  54. package/dist/core/auto-promote.d.ts +2 -1
  55. package/dist/core/auto-promote.js +2 -2
  56. package/dist/core/caller-tool-name.d.ts +9 -0
  57. package/dist/core/caller-tool-name.js +13 -0
  58. package/dist/core/checkpoint-requirements.d.ts +7 -1
  59. package/dist/core/checkpoint-requirements.js +2 -0
  60. package/dist/core/checkpoint-store.d.ts +57 -24
  61. package/dist/core/checkpoint-store.js +3 -3
  62. package/dist/core/child-clamp-seats.d.ts +6 -0
  63. package/dist/core/child-clamp-seats.js +2 -1
  64. package/dist/core/compliance.js +3 -1
  65. package/dist/core/credential-vocabulary.d.ts +33 -8
  66. package/dist/core/credential-vocabulary.js +32 -7
  67. package/dist/core/decision-receipt.d.ts +2 -2
  68. package/dist/core/delegation-frames.d.ts +9 -2
  69. package/dist/core/delegation-name.d.ts +18 -0
  70. package/dist/core/delegation-name.js +47 -0
  71. package/dist/core/effective-path-target.d.ts +25 -6
  72. package/dist/core/effective-path-target.js +24 -2
  73. package/dist/core/engine-capabilities.d.ts +8 -1
  74. package/dist/core/engine-capabilities.js +1 -1
  75. package/dist/core/engine-notice.d.ts +49 -21
  76. package/dist/core/frontmatter-fence.d.ts +10 -0
  77. package/dist/core/frontmatter-fence.js +6 -0
  78. package/dist/core/gate-fold.js +8 -25
  79. package/dist/core/gate-lanes.js +358 -274
  80. package/dist/core/gate-outcome.d.ts +11 -6
  81. package/dist/core/governance-codes.d.ts +11 -4
  82. package/dist/core/governance-codes.js +12 -3
  83. package/dist/core/hands-band-screen.d.ts +7 -0
  84. package/dist/core/hands-band-screen.js +32 -0
  85. package/dist/core/hooks.d.ts +283 -739
  86. package/dist/core/hooks.js +100 -193
  87. package/dist/{tools/fs → core}/image-admission.d.ts +21 -3
  88. package/dist/{tools/fs → core}/image-admission.js +24 -6
  89. package/dist/core/locked-config.d.ts +84 -32
  90. package/dist/core/locked-config.js +128 -42
  91. package/dist/core/mcp-connection-pool.d.ts +4 -1
  92. package/dist/core/mcp-connection-pool.js +7 -2
  93. package/dist/core/mcp-probe.d.ts +12 -9
  94. package/dist/core/mcp-probe.js +3 -3
  95. package/dist/core/mcp-server-spec.d.ts +104 -10
  96. package/dist/core/mcp-server-spec.js +183 -33
  97. package/dist/core/mcp.d.ts +31 -20
  98. package/dist/core/mcp.js +66 -56
  99. package/dist/core/memory-engine/data-plane.js +5 -1
  100. package/dist/core/memory-engine/distiller.js +16 -2
  101. package/dist/core/memory-engine/engine.d.ts +22 -30
  102. package/dist/core/memory-engine/engine.js +16 -10
  103. package/dist/core/memory-engine/frontmatter.d.ts +6 -0
  104. package/dist/core/memory-engine/frontmatter.js +19 -16
  105. package/dist/core/memory.d.ts +2 -2
  106. package/dist/core/mode-policy.d.ts +5 -16
  107. package/dist/core/mode-policy.js +7 -19
  108. package/dist/core/model-seat.d.ts +4 -1
  109. package/dist/core/mods/dollar.d.ts +109 -0
  110. package/dist/core/mods/dollar.js +154 -0
  111. package/dist/core/mods/host.d.ts +23 -0
  112. package/dist/core/mods/host.js +21 -0
  113. package/dist/core/mods/kernel/budget.d.ts +43 -0
  114. package/dist/core/mods/kernel/budget.js +83 -0
  115. package/dist/core/mods/kernel/dispatch.d.ts +100 -0
  116. package/dist/core/mods/kernel/dispatch.js +699 -0
  117. package/dist/core/mods/kernel/events.d.ts +245 -0
  118. package/dist/core/mods/kernel/events.js +210 -0
  119. package/dist/core/mods/kernel/index.d.ts +6 -0
  120. package/dist/core/mods/kernel/index.js +5 -0
  121. package/dist/core/mods/kernel/receive.d.ts +94 -0
  122. package/dist/core/mods/kernel/receive.js +188 -0
  123. package/dist/core/mods/kernel/registration.d.ts +131 -0
  124. package/dist/core/mods/kernel/registration.js +102 -0
  125. package/dist/core/mods/kernel/site-rules.d.ts +149 -0
  126. package/dist/core/mods/kernel/site-rules.js +296 -0
  127. package/dist/core/mods/stations.d.ts +344 -0
  128. package/dist/core/mods/stations.js +437 -0
  129. package/dist/core/mounted-mcp.d.ts +57 -0
  130. package/dist/core/mounted-mcp.js +71 -2
  131. package/dist/core/own-property-receipt.d.ts +13 -0
  132. package/dist/core/own-property-receipt.js +13 -23
  133. package/dist/core/parent-spec-seat.d.ts +18 -7
  134. package/dist/core/parent-spec-seat.js +6 -2
  135. package/dist/core/path-identity.js +2 -1
  136. package/dist/core/permission-rule-model.d.ts +58 -9
  137. package/dist/core/permission-rule-model.js +81 -7
  138. package/dist/core/permission-rule-org.d.ts +163 -33
  139. package/dist/core/permission-rule-org.js +205 -71
  140. package/dist/core/permission-rule-syntax.d.ts +15 -0
  141. package/dist/core/permission-rule-syntax.js +24 -16
  142. package/dist/core/permission-rules.d.ts +14 -2
  143. package/dist/core/permission-rules.js +63 -23
  144. package/dist/core/prompt-section-seat.d.ts +15 -27
  145. package/dist/core/prompt-section-seat.js +73 -40
  146. package/dist/core/protocol-http-auth.d.ts +3 -1
  147. package/dist/core/protocol-http-auth.js +2 -0
  148. package/dist/core/reminder-mint.d.ts +2 -2
  149. package/dist/core/remote-env.d.ts +24 -12
  150. package/dist/core/remote-env.js +1 -0
  151. package/dist/core/resume-startup-cause.d.ts +16 -1
  152. package/dist/core/resume-startup-cause.js +4 -1
  153. package/dist/core/retention.js +7 -2
  154. package/dist/core/retired-keys.d.ts +12 -2
  155. package/dist/core/retired-keys.js +15 -1
  156. package/dist/core/roles.js +60 -10
  157. package/dist/core/rule-lane-reads.js +1 -1
  158. package/dist/core/runner/announce-once-ledger.d.ts +31 -1
  159. package/dist/core/runner/announce-once-ledger.js +22 -0
  160. package/dist/core/runner/assemble-result.d.ts +9 -0
  161. package/dist/core/runner/assemble-result.js +3 -1
  162. package/dist/core/runner/call-hook-stations.d.ts +23 -27
  163. package/dist/core/runner/call-hook-stations.js +58 -42
  164. package/dist/core/runner/caller-stop-gate.d.ts +25 -0
  165. package/dist/core/runner/caller-stop-gate.js +7 -0
  166. package/dist/core/runner/compaction-seams.d.ts +8 -22
  167. package/dist/core/runner/compaction-seams.js +28 -53
  168. package/dist/core/runner/construction-doors.js +11 -1
  169. package/dist/core/runner/contracts.d.ts +86 -83
  170. package/dist/core/runner/credential-origin-seat.d.ts +2 -0
  171. package/dist/core/runner/credential-origin-seat.js +19 -0
  172. package/dist/core/runner/extra-body-dropped-seat.d.ts +2 -6
  173. package/dist/core/runner/gate-exit.d.ts +47 -36
  174. package/dist/core/runner/gate-exit.js +12 -5
  175. package/dist/core/runner/image.js +1 -2
  176. package/dist/core/runner/inline-image.js +1 -1
  177. package/dist/core/runner/mcp-redial.d.ts +52 -10
  178. package/dist/core/runner/mcp-redial.js +38 -9
  179. package/dist/core/runner/notice-seat-input.d.ts +11 -0
  180. package/dist/core/runner/notice-seat-input.js +1 -0
  181. package/dist/core/runner/permission-rule-lanes.d.ts +5 -2
  182. package/dist/core/runner/permission-rule-lanes.js +22 -10
  183. package/dist/core/runner/person-path-rows.d.ts +3 -1
  184. package/dist/core/runner/person-path-rows.js +3 -2
  185. package/dist/core/runner/prepare-acquire-reconcile.js +5 -1
  186. package/dist/core/runner/prepare-ask-lane.d.ts +5 -7
  187. package/dist/core/runner/prepare-ask-lane.js +6 -15
  188. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
  189. package/dist/core/runner/prepare-caps-and-workflow.js +25 -8
  190. package/dist/core/runner/prepare-config-doors.d.ts +52 -1
  191. package/dist/core/runner/prepare-config-doors.js +168 -143
  192. package/dist/core/runner/prepare-defer-classify.js +7 -11
  193. package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
  194. package/dist/core/runner/prepare-delegation-surface.js +7 -5
  195. package/dist/core/runner/prepare-gate-stations.d.ts +8 -11
  196. package/dist/core/runner/prepare-gate-stations.js +11 -10
  197. package/dist/core/runner/prepare-hands-readface.d.ts +1 -1
  198. package/dist/core/runner/prepare-hands-readface.js +2 -1
  199. package/dist/core/runner/prepare-inherited-gate.d.ts +8 -12
  200. package/dist/core/runner/prepare-inherited-gate.js +10 -23
  201. package/dist/core/runner/prepare-listings.d.ts +1 -1
  202. package/dist/core/runner/prepare-listings.js +4 -2
  203. package/dist/core/runner/prepare-memory-engine-session.d.ts +0 -6
  204. package/dist/core/runner/prepare-memory-engine-session.js +20 -7
  205. package/dist/core/runner/prepare-memory.d.ts +3 -2
  206. package/dist/core/runner/prepare-memory.js +6 -2
  207. package/dist/core/runner/prepare-offload-wrappers.d.ts +4 -4
  208. package/dist/core/runner/prepare-offload-wrappers.js +2 -1
  209. package/dist/core/runner/prepare-park-ask.js +10 -14
  210. package/dist/core/runner/prepare-policy-chain.d.ts +17 -15
  211. package/dist/core/runner/prepare-policy-chain.js +104 -109
  212. package/dist/core/runner/prepare-project-context.d.ts +1 -1
  213. package/dist/core/runner/prepare-project-context.js +11 -12
  214. package/dist/core/runner/prepare-prompt-assembly.d.ts +45 -40
  215. package/dist/core/runner/prepare-prompt-assembly.js +138 -101
  216. package/dist/core/runner/prepare-prompt-inputs.d.ts +28 -23
  217. package/dist/core/runner/prepare-prompt-inputs.js +11 -10
  218. package/dist/core/runner/prepare-protocol-tools.d.ts +11 -7
  219. package/dist/core/runner/prepare-protocol-tools.js +20 -13
  220. package/dist/core/runner/prepare-question-face.d.ts +4 -2
  221. package/dist/core/runner/prepare-question-face.js +4 -3
  222. package/dist/core/runner/prepare-safety-scan.js +6 -10
  223. package/dist/core/runner/prepare-suspend-saga.d.ts +6 -0
  224. package/dist/core/runner/prepare-suspend-saga.js +7 -5
  225. package/dist/core/runner/prepare-task.js +41 -23
  226. package/dist/core/runner/prepare-turn-wiring.d.ts +13 -15
  227. package/dist/core/runner/prepare-turn-wiring.js +29 -27
  228. package/dist/core/runner/prepare-wiring-manifest.d.ts +13 -9
  229. package/dist/core/runner/prepare-wiring-manifest.js +14 -11
  230. package/dist/core/runner/resume-admission.d.ts +4 -1
  231. package/dist/core/runner/resume-admission.js +7 -5
  232. package/dist/core/runner/resume-apply.d.ts +5 -2
  233. package/dist/core/runner/resume-apply.js +24 -42
  234. package/dist/core/runner/resume-checkpoint-screen.d.ts +1 -0
  235. package/dist/core/runner/resume-checkpoint-screen.js +9 -1
  236. package/dist/core/runner/resume-internals-and-config.d.ts +3 -3
  237. package/dist/core/runner/resume-internals-and-config.js +3 -8
  238. package/dist/core/runner/resume-preflight.js +38 -16
  239. package/dist/core/runner/retired-runner-deps.d.ts +5 -6
  240. package/dist/core/runner/retired-runner-deps.js +4 -5
  241. package/dist/core/runner/run-brain-sinks.d.ts +3 -2
  242. package/dist/core/runner/run-brain-sinks.js +5 -1
  243. package/dist/core/runner/run-compaction-machinery.d.ts +7 -1
  244. package/dist/core/runner/run-compaction-machinery.js +7 -33
  245. package/dist/core/runner/run-harness-handlers.js +4 -2
  246. package/dist/core/runner/run-identity-wiring.d.ts +3 -1
  247. package/dist/core/runner/run-identity-wiring.js +3 -2
  248. package/dist/core/runner/run-leg.js +103 -95
  249. package/dist/core/runner/run-notification-lane.js +1 -0
  250. package/dist/core/runner/run-recovery-lanes.d.ts +3 -0
  251. package/dist/core/runner/run-recovery-lanes.js +14 -11
  252. package/dist/core/runner/run-settle-and-teardown.js +9 -28
  253. package/dist/core/runner/run-stop-and-final-verify.js +18 -25
  254. package/dist/core/runner/run-terminal-adoption.d.ts +3 -0
  255. package/dist/core/runner/run-terminal-adoption.js +34 -22
  256. package/dist/core/runner/run-tool-mount-facts.js +5 -3
  257. package/dist/core/runner/run-turn-boundary.js +32 -37
  258. package/dist/core/runner/runtask.d.ts +6 -7
  259. package/dist/core/runner/runtask.js +15 -73
  260. package/dist/core/runner/session-rule-policy.d.ts +5 -5
  261. package/dist/core/runner/session-rule-policy.js +13 -8
  262. package/dist/core/runner/side-call-account.d.ts +68 -0
  263. package/dist/core/runner/side-call-account.js +61 -0
  264. package/dist/core/runner/skills-seat.d.ts +15 -0
  265. package/dist/core/runner/skills-seat.js +57 -0
  266. package/dist/core/runner/stream-halt-verbs.js +12 -17
  267. package/dist/core/runner/stream-lifecycle-verbs.js +8 -5
  268. package/dist/core/runner/stream-steer-verb.d.ts +1 -1
  269. package/dist/core/runner/stream-steer-verb.js +20 -38
  270. package/dist/core/runner/sub-agent-deny-lists.d.ts +124 -23
  271. package/dist/core/runner/sub-agent-deny-lists.js +230 -71
  272. package/dist/core/runner/synthetic-tools.d.ts +5 -2
  273. package/dist/core/runner/synthetic-tools.js +2 -12
  274. package/dist/core/runner/tool-end-body.d.ts +5 -6
  275. package/dist/core/runner/tool-end-body.js +6 -4
  276. package/dist/core/runner/tool-not-executed.d.ts +15 -0
  277. package/dist/core/runner/tool-not-executed.js +30 -0
  278. package/dist/core/runner/tool-occurrence.d.ts +8 -7
  279. package/dist/core/runner/tool-occurrence.js +5 -5
  280. package/dist/core/runner/tool-result-media-seat.d.ts +1 -1
  281. package/dist/core/runner-deps.d.ts +43 -36
  282. package/dist/core/safety-merge-corpus.js +18 -2
  283. package/dist/core/secret-env.d.ts +88 -20
  284. package/dist/core/secret-env.js +192 -38
  285. package/dist/core/session-policy-store.d.ts +71 -16
  286. package/dist/core/session-policy-store.js +138 -28
  287. package/dist/core/session-reconcile.d.ts +4 -0
  288. package/dist/core/session-reconcile.js +2 -1
  289. package/dist/core/shell-read-silence.js +3 -32
  290. package/dist/core/side-query.d.ts +5 -3
  291. package/dist/core/skill-grant.d.ts +3 -2
  292. package/dist/core/skill-grant.js +17 -9
  293. package/dist/core/skills-directory.d.ts +31 -11
  294. package/dist/core/skills-directory.js +655 -104
  295. package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
  296. package/dist/core/task-event.d.ts +49 -3
  297. package/dist/core/task-notification.js +2 -2
  298. package/dist/core/task-result.d.ts +8 -0
  299. package/dist/core/task-spec.d.ts +20 -19
  300. package/dist/core/task-stream.d.ts +14 -4
  301. package/dist/core/tighten-task-spec.d.ts +4 -3
  302. package/dist/core/tighten-task-spec.js +2 -4
  303. package/dist/core/tool-check-reading.d.ts +74 -0
  304. package/dist/core/tool-check-reading.js +80 -0
  305. package/dist/core/tool-policy.d.ts +62 -18
  306. package/dist/core/tool-policy.js +86 -15
  307. package/dist/core/tool-registry.d.ts +20 -0
  308. package/dist/core/tool-registry.js +4 -0
  309. package/dist/core/tool-spec.d.ts +10 -6
  310. package/dist/core/tools.js +2 -0
  311. package/dist/core/trace.d.ts +51 -32
  312. package/dist/core/types.d.ts +2 -2
  313. package/dist/core/types.js +1 -1
  314. package/dist/core/unc-spelling.d.ts +10 -0
  315. package/dist/core/unc-spelling.js +3 -0
  316. package/dist/core/untrusted-egress.d.ts +8 -0
  317. package/dist/core/untrusted-egress.js +4 -1
  318. package/dist/core/untrusted-text.d.ts +16 -0
  319. package/dist/core/untrusted-text.js +7 -2
  320. package/dist/core/user-attachment.d.ts +25 -4
  321. package/dist/core/user-attachment.js +63 -42
  322. package/dist/core/wiring-manifest.d.ts +18 -15
  323. package/dist/core/wiring-manifest.js +2 -2
  324. package/dist/engine/compaction/utils.js +1 -2
  325. package/dist/engine/execution-env/node-execution-env.d.ts +4 -3
  326. package/dist/engine/execution-env/symlink-chain.js +1 -1
  327. package/dist/engine/harness/agent-harness.d.ts +1 -1
  328. package/dist/engine/harness/agent-harness.js +5 -4
  329. package/dist/engine/harness/types.d.ts +20 -16
  330. package/dist/engine/harness/types.js +7 -1
  331. package/dist/engine/llm/types.d.ts +12 -7
  332. package/dist/engine/loop/agent-loop.d.ts +12 -1
  333. package/dist/engine/loop/agent-loop.js +18 -6
  334. package/dist/engine/loop/types.d.ts +8 -2
  335. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  336. package/dist/engine/session/import-validate.js +3 -10
  337. package/dist/engine/session/session.d.ts +4 -4
  338. package/dist/engine/session/session.js +4 -4
  339. package/dist/index.d.ts +33 -23
  340. package/dist/index.js +23 -15
  341. package/dist/internal/harness.d.ts +2 -1
  342. package/dist/internal/harness.js +2 -1
  343. package/dist/orchestration/goal.d.ts +24 -1
  344. package/dist/orchestration/goal.js +3 -2
  345. package/dist/orchestration/run-spec.d.ts +4 -6
  346. package/dist/orchestration/run-spec.js +39 -63
  347. package/dist/orchestration/run-workflow-tool.js +1 -2
  348. package/dist/orchestration/workflow.d.ts +11 -3
  349. package/dist/orchestration/workflow.js +11 -2
  350. package/dist/prompt-assembly/artifact-store.d.ts +72 -56
  351. package/dist/prompt-assembly/artifact-store.js +60 -52
  352. package/dist/prompt-assembly/artifact.d.ts +90 -76
  353. package/dist/prompt-assembly/artifact.js +197 -145
  354. package/dist/prompt-assembly/assemble.d.ts +36 -29
  355. package/dist/prompt-assembly/assemble.js +34 -220
  356. package/dist/prompt-assembly/bands.d.ts +20 -0
  357. package/dist/prompt-assembly/bands.js +18 -0
  358. package/dist/prompt-assembly/catalog/constitution.d.ts +23 -0
  359. package/dist/prompt-assembly/catalog/constitution.js +69 -0
  360. package/dist/prompt-assembly/catalog/core-behavior.d.ts +9 -0
  361. package/dist/prompt-assembly/catalog/core-behavior.js +85 -0
  362. package/dist/prompt-assembly/catalog/index.d.ts +11 -0
  363. package/dist/prompt-assembly/catalog/index.js +60 -0
  364. package/dist/prompt-assembly/catalog/memory.d.ts +13 -0
  365. package/dist/prompt-assembly/catalog/memory.js +6 -0
  366. package/dist/prompt-assembly/catalog/modes.d.ts +15 -0
  367. package/dist/prompt-assembly/catalog/modes.js +137 -0
  368. package/dist/prompt-assembly/catalog/role.d.ts +10 -0
  369. package/dist/prompt-assembly/catalog/role.js +157 -0
  370. package/dist/prompt-assembly/catalog/schema.d.ts +138 -0
  371. package/dist/prompt-assembly/catalog/schema.js +25 -0
  372. package/dist/prompt-assembly/catalog/sections.d.ts +9 -0
  373. package/dist/prompt-assembly/catalog/sections.js +98 -0
  374. package/dist/prompt-assembly/catalog/team.d.ts +4 -0
  375. package/dist/prompt-assembly/catalog/team.js +258 -0
  376. package/dist/prompt-assembly/composer.d.ts +26 -28
  377. package/dist/prompt-assembly/composer.js +124 -46
  378. package/dist/prompt-assembly/epoch.d.ts +89 -79
  379. package/dist/prompt-assembly/epoch.js +115 -142
  380. package/dist/prompt-assembly/explain.d.ts +58 -34
  381. package/dist/prompt-assembly/explain.js +21 -24
  382. package/dist/prompt-assembly/overlay.d.ts +137 -0
  383. package/dist/prompt-assembly/overlay.js +339 -0
  384. package/dist/prompt-assembly/renderers.d.ts +21 -0
  385. package/dist/prompt-assembly/renderers.js +39 -0
  386. package/dist/prompt-assembly/section-usage.d.ts +3 -3
  387. package/dist/prompt-assembly/section-usage.js +1 -1
  388. package/dist/prompt-assembly/select.d.ts +71 -0
  389. package/dist/prompt-assembly/select.js +106 -0
  390. package/dist/prompt-assembly/sugar.d.ts +31 -0
  391. package/dist/prompt-assembly/sugar.js +20 -0
  392. package/dist/prompt-assembly/turn-snapshot.d.ts +3 -2
  393. package/dist/prompt-assembly/types.d.ts +45 -148
  394. package/dist/prompts/coordinator.d.ts +2 -21
  395. package/dist/prompts/coordinator.js +3 -255
  396. package/dist/prompts/cowork.d.ts +27 -16
  397. package/dist/prompts/cowork.js +2 -23
  398. package/dist/prompts/default.d.ts +38 -511
  399. package/dist/prompts/default.js +20 -288
  400. package/dist/prompts/supervisor.d.ts +6 -71
  401. package/dist/prompts/supervisor.js +6 -117
  402. package/dist/stores/file/permission-rule-store.d.ts +1 -1
  403. package/dist/stores/file/permission-rule-store.js +2 -1
  404. package/dist/tools/artifact/artifact-tool.js +4 -3
  405. package/dist/tools/fs/bash-readonly-classifier.d.ts +6 -5
  406. package/dist/tools/fs/dir-entries.d.ts +4 -2
  407. package/dist/tools/fs/dir-entries.js +16 -4
  408. package/dist/tools/fs/fs-bash.d.ts +1 -1
  409. package/dist/tools/fs/fs-bash.js +22 -11
  410. package/dist/tools/fs/fs-pdf.js +17 -13
  411. package/dist/tools/fs/fs-read.js +4 -3
  412. package/dist/tools/fs/fs-shared.d.ts +1 -10
  413. package/dist/tools/fs/fs-shared.js +3 -4
  414. package/dist/tools/fs/fs-write.js +2 -1
  415. package/dist/tools/fs/notebook.js +1 -1
  416. package/dist/tools/fs/pdf.d.ts +20 -10
  417. package/dist/tools/fs/pdf.js +19 -10
  418. package/dist/tools/fs/program-read-model.d.ts +68 -8
  419. package/dist/tools/fs/program-read-model.js +112 -33
  420. package/dist/tools/fs/program-read-model.rows.js +30 -10
  421. package/dist/tools/fs/read-deny-home.d.ts +25 -9
  422. package/dist/tools/fs/read-deny-home.js +28 -27
  423. package/dist/tools/fs/read-deny.d.ts +41 -11
  424. package/dist/tools/fs/read-deny.js +51 -5
  425. package/dist/tools/fs/safety.d.ts +4 -26
  426. package/dist/tools/fs/safety.js +10 -32
  427. package/dist/tools/fs/search.js +15 -10
  428. package/dist/tools/fs/shell-read-argv.d.ts +3 -2
  429. package/dist/tools/fs/shell-read-argv.js +118 -38
  430. package/dist/tools/fs/shell-read-establish.d.ts +5 -5
  431. package/dist/tools/fs/shell-read-establish.js +11 -61
  432. package/dist/tools/fs/shell-read-identity.js +6 -3
  433. package/dist/tools/fs/shell-read-judge.d.ts +13 -15
  434. package/dist/tools/fs/shell-read-judge.js +18 -4
  435. package/dist/tools/fs/shell-read-plan.d.ts +2 -2
  436. package/dist/tools/web.js +1 -1
  437. package/package.json +13 -1
  438. package/test/export-surface.snapshot.json +306 -103
  439. package/wire-changes/core@7.52.0.json +5859 -0
  440. package/wire-changes/core@7.53.0.json +1946 -0
  441. package/dist/core/hook-seats.d.ts +0 -66
  442. package/dist/core/hook-seats.js +0 -37
  443. package/dist/prompt-assembly/packs/sema-default.d.ts +0 -2
  444. package/dist/prompt-assembly/packs/sema-default.js +0 -147
  445. package/dist/prompts/simple-sections.d.ts +0 -58
  446. package/dist/prompts/simple-sections.js +0 -43
@@ -4,24 +4,28 @@ import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
4
4
  import { CheckpointError, readPendingSteerQueue, realApprovalOrgFact, remainingBudgetMicroUsd } from "../checkpoint-store.js";
5
5
  import { normalizePersistedRuleHit } from "../rule-lane-reads.js";
6
6
  import { decidersNote, SETTLEMENT_NOBODY_JUDGED } from "../gate-outcome.js";
7
- import { formatHookFeedback, hookSeatExpiredError, runHookSeat } from "../hooks.js";
7
+ import { formatHookFeedback } from "../hooks.js";
8
+ import { classicEventBase, failedHandlerClause, screenUserPrompt } from "../mods/stations.js";
8
9
  import { buildAppliedHumanInputEvent, buildHumanInputEvent, projectHumanInput } from "../human-input-projection.js";
9
10
  import { humanInputAttachmentsOf, readObjectiveAttachments, userAttachmentDeclarations } from "../user-attachment.js";
10
- import { uuidv7 } from "../../internal/harness.js";
11
+ import { readToolCallArguments, uuidv7 } from "../../internal/harness.js";
11
12
  import { ORG_ADJUDICATION_TIMEOUT_MS, settleOrgVerdictWithin } from "../permission-rule-org.js";
12
13
  import { applyPersistedTightening, disclosedRuleSet } from "../persisted-rule-arms.js";
14
+ import { argsReadBy, stampArgsReading } from "../effective-path-target.js";
13
15
  import { parkedSkillApprovalRefusal, skillRowRefusal } from "../skill-grant.js";
14
16
  import { SKILL_TOOL_NAME } from "./synthetic-tools.js";
15
17
  import { computeCostMicroUsd } from "../pricing.js";
16
18
  import { mintSystemReminder } from "../reminder-mint.js";
17
19
  import { hasDestroy } from "../remote-env.js";
18
- import { advertisedWritableRootsSeat, attestationOf, exemptRootsSeat, humanRefusalSentence, policyCannotAnswer, policyRefusalMessage, refuseOutOfContractDecision } from "../tool-policy.js";
20
+ import { advertisedWritableRootsSeat, attestationOf, exemptRootsSeat, humanRefusalSentence, ownedReading, policyCannotAnswer, policyRefusalMessage, refuseOutOfContractDecision } from "../tool-policy.js";
21
+ import { failedJudgmentDeny } from "./policy-throw.js";
19
22
  import { pathDenialCardOf } from "../../tools/fs/safety.js";
20
23
  import { callFaceSeat, judgeParkedToolIdentity, parkedRowLiveFace, rosterEntryNamed } from "../tool-roster.js";
21
24
  import { deliverEngineNotice } from "../types.js";
22
25
  import { delimitUntrusted, inlineUntrusted, REVIEWER_NOTE_MAX_BODY, sanitizeUntrustedText } from "../untrusted-text.js";
23
26
  import { errorCodeOf } from "./terminal-account.js";
24
27
  import { DEFAULT_PRECALL_OUTPUT_TOKENS, platformLimitTerminal } from "./clock-and-limits.js";
28
+ import { legContextOverlayOption } from "./compaction-call-options.js";
25
29
  import { mintOutputStyleReminder, owedPostureText } from "./compaction-restate.js";
26
30
  import { deepJsonEqual, resumeContinuation } from "./decide-continuation.js";
27
31
  import { chainCannotJudge } from "./call-hook-stations.js";
@@ -37,10 +41,11 @@ import { maybeHumanRejectionHalt } from "./prepare-gate-stations.js";
37
41
  import { nextHumanInputSeq } from "./steer-admission.js";
38
42
  import { settleTeardownLeg } from "./teardown-bounded.js";
39
43
  import { announceToolCall, emitSettled, toolResultMsg } from "./tool-end-body.js";
44
+ import { rowDetailsOf, withRowNotExecuted } from "./tool-not-executed.js";
40
45
  import { announceListingTruncation } from "../skill-listing-budget.js";
41
46
  import { attachmentEnvelopeTags, collectDateChange, commitAgentListing, commitSkillsListing, reduceToolEnd, renderAgentListingFrame, renderOrphanedBackgroundTasks, renderSkillsListingFrame, stampWriteAnchor } from "./turn-attachments.js";
42
47
  import { flushOwedAnnouncedSnapshot } from "./announce-once-ledger.js";
43
- import { asThrownError, thrownMarksOf } from "../thrown-value.js";
48
+ import { thrownMarksOf } from "../thrown-value.js";
44
49
  import { egressThrownText, egressValue } from "../untrusted-egress.js";
45
50
  import { ruleSourcePhrase } from "../rule-denial-sentence.js";
46
51
  import { wireOf } from "../tool-name-readings.js";
@@ -167,32 +172,21 @@ export async function runLeg(input) {
167
172
  engineSegments.push({ start: hookStart, end: continuation.length });
168
173
  }
169
174
  if (source === "steer") {
170
- const parkedScreen = (spec.hooks ?? runner.deps.hooks)?.userPromptSubmit;
171
- if (parkedScreen !== undefined) {
172
- let outcome;
173
- try {
174
- const seat = await runHookSeat("userPromptSubmit", { timeoutMs: prepared.hookTimeoutMs, signal: prepared.abortController.signal, abortEnds: true }, (sig) => parkedScreen(steer.text, {
175
- identity: prepared.hookIdentity, permissionMode: prepared.permissionMode.observed,
176
- signal: sig,
177
- source: "parked_redelivery",
178
- ...(steer.inputId !== undefined ? { inputId: steer.inputId } : {}),
179
- ...(steer.actor !== undefined ? { actor: snapshotActorAssertion(steer.actor) } : {}),
180
- }));
181
- outcome = seat.expired
182
- ? { blocked: seat.cause === "timeout" ? `the screen did not answer within its ${prepared.hookTimeoutMs}ms bound (fail-closed)` : "the run was cancelled while the screen was still deciding (fail-closed)" }
183
- : seat.value?.block !== undefined && seat.value.block !== ""
184
- ? { blocked: inlineUntrusted(seat.value.block) }
185
- : { ...(seat.value?.additionalContext !== undefined && seat.value.additionalContext !== "" ? { context: seat.value.additionalContext } : {}) };
186
- }
187
- catch (hookErr) {
188
- const err = asThrownError(hookErr);
189
- try {
190
- runner.deps.onError?.(err, { phase: "hook", sessionId: prepared.sessionId });
191
- }
192
- catch {
193
- }
194
- outcome = { blocked: `the screen crashed (${inlineUntrusted(err.message)}; fail-closed)` };
195
- }
175
+ const screen = await screenUserPrompt(prepared.modBus, {
176
+ ...classicEventBase(prepared.hookIdentity, prepared.permissionMode.observed),
177
+ prompt: steer.text,
178
+ source: "parked_redelivery",
179
+ ...(steer.inputId !== undefined ? { inputId: steer.inputId } : {}),
180
+ ...(steer.actor !== undefined ? { actor: snapshotActorAssertion(steer.actor) } : {}),
181
+ }, prepared.abortController.signal);
182
+ if (screen !== undefined) {
183
+ const outcome = screen.kind === "aborted"
184
+ ? { blocked: "the run was cancelled while the screen was still deciding (fail-closed)" }
185
+ : screen.kind === "failed"
186
+ ? { blocked: `the screen ${failedHandlerClause(screen)} (fail-closed)` }
187
+ : screen.block !== undefined && screen.block !== ""
188
+ ? { blocked: inlineUntrusted(screen.block) }
189
+ : { ...(screen.additionalContext !== undefined && screen.additionalContext !== "" ? { context: screen.additionalContext } : {}) };
196
190
  if ("blocked" in outcome) {
197
191
  if (steer.inputId !== undefined)
198
192
  withheldSteerIds.add(steer.inputId);
@@ -290,49 +284,31 @@ export async function runLeg(input) {
290
284
  const projectedObjective = projectHumanInput({ text: spec.objective, actor: objectiveActor, source: "objective" });
291
285
  let effectiveObjective = projectedObjective;
292
286
  let promptBlocked = false;
293
- const userPromptSubmit = (spec.hooks ?? runner.deps.hooks)?.userPromptSubmit;
294
- if (userPromptSubmit) {
295
- try {
296
- const promptSeat = await runHookSeat("userPromptSubmit", { timeoutMs: prepared.hookTimeoutMs, signal: prepared.abortController.signal, abortEnds: true }, (sig) => userPromptSubmit(spec.objective, { identity: prepared.hookIdentity, permissionMode: prepared.permissionMode.observed, signal: sig, source: "objective", ...(objectiveActor !== undefined ? { actor: snapshotActorAssertion(objectiveActor) } : {}), ...(prepared.userAttachments !== undefined ? { userAttachments: userAttachmentDeclarations(prepared.userAttachments) } : {}) }));
297
- if (promptSeat.expired) {
298
- if (promptSeat.cause === "timeout") {
299
- try {
300
- runner.deps.onError?.(hookSeatExpiredError("userPromptSubmit", prepared.hookTimeoutMs, promptSeat.cause, "the prompt was NOT submitted (fail-closed) and the task ends blocked"), { phase: "hook", sessionId: prepared.sessionId });
301
- }
302
- catch {
303
- }
304
- }
305
- const timedOut = promptSeat.cause === "timeout";
306
- holdPrompt(prepared.blockedRef, prepared.reminderMark, timedOut ? "timeout" : "cancelled", timedOut
307
- ? `the deployment's userPromptSubmit hook did not answer within its ${prepared.hookTimeoutMs}ms bound while screening this prompt; ` +
308
- `the prompt was NOT submitted (fail-closed)`
309
- : `the task was cancelled while the deployment's userPromptSubmit hook was still screening this prompt; ` +
310
- `the prompt was NOT submitted (fail-closed)`);
311
- promptBlocked = true;
312
- }
313
- const decision = promptSeat.expired ? undefined : promptSeat.value;
314
- const blockWords = decision?.block;
315
- if (blockWords) {
316
- holdPrompt(prepared.blockedRef, prepared.reminderMark, "block", blockWords);
317
- promptBlocked = true;
318
- }
319
- else if (decision?.additionalContext) {
320
- effectiveObjective = `${formatHookFeedback(decision.additionalContext, prepared.reminderMark)}\n\n${projectedObjective}`;
321
- }
322
- }
323
- catch (hookErr) {
324
- const err = asThrownError(hookErr);
325
- try {
326
- runner.deps.onError?.(err, { phase: "hook", sessionId: prepared.sessionId });
327
- }
328
- catch {
329
- }
330
- holdPrompt(prepared.blockedRef, prepared.reminderMark, "crashed", `the deployment's userPromptSubmit hook crashed while screening this prompt (${err.message}); ` + `the prompt was NOT submitted (fail-closed)`);
331
- promptBlocked = true;
332
- }
287
+ const screen = await screenUserPrompt(prepared.modBus, {
288
+ ...classicEventBase(prepared.hookIdentity, prepared.permissionMode.observed),
289
+ prompt: spec.objective,
290
+ source: "objective",
291
+ ...(objectiveActor !== undefined ? { actor: snapshotActorAssertion(objectiveActor) } : {}),
292
+ ...(prepared.userAttachments !== undefined ? { userAttachments: userAttachmentDeclarations(prepared.userAttachments) } : {}),
293
+ }, prepared.abortController.signal);
294
+ if (screen?.kind === "aborted") {
295
+ holdPrompt(prepared.blockedRef, prepared.reminderMark, "cancelled", `the task was cancelled while the deployment's userPromptSubmit hook was still screening this prompt; ` +
296
+ `the prompt was NOT submitted (fail-closed)`);
297
+ promptBlocked = true;
298
+ }
299
+ else if (screen?.kind === "failed") {
300
+ holdPrompt(prepared.blockedRef, prepared.reminderMark, screen.cause === "timeout" ? "timeout" : "crashed", `the deployment's userPromptSubmit hook ${failedHandlerClause(screen)} while screening this prompt; the prompt was NOT submitted (fail-closed)`);
301
+ promptBlocked = true;
302
+ }
303
+ else if (screen?.block) {
304
+ holdPrompt(prepared.blockedRef, prepared.reminderMark, "block", screen.block);
305
+ promptBlocked = true;
306
+ }
307
+ else if (screen?.additionalContext) {
308
+ effectiveObjective = `${formatHookFeedback(screen.additionalContext, prepared.reminderMark)}\n\n${projectedObjective}`;
333
309
  }
334
310
  const objectiveInputId = uuidv7();
335
- const { frames: attachmentFrames, chars: attachmentChars } = await readObjectiveAttachments(prepared, objectiveInputId, promptBlocked);
311
+ const { frames: attachmentFrames, chars: attachmentChars } = await readObjectiveAttachments(prepared, objectiveInputId, promptBlocked, { overlay: () => legContextOverlayOption(prepared, runner).contextOverlay, objectiveChars: effectiveObjective.length });
336
312
  let gitLegDelivered;
337
313
  if (!promptBlocked) {
338
314
  const gitBody = await resolveGitLegDelivery(prepared, undefined, (err) => {
@@ -580,20 +556,41 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
580
556
  throw new CheckpointError("checkpoint.invalid_outcome", "pending action reached the resolver with no settlement record on its decision (gateOutcome) — refusing to execute or settle a decision that carries no record");
581
557
  }
582
558
  const humanRewrite = wireOf("resume.questionArgsShown", pendingAction) === ASK_USER_QUESTION_TOOL_NAME ? undefined : outcome.updatedInput;
583
- const resolvedArgs = humanRewrite !== undefined ? humanRewrite : pendingAction.args;
559
+ const liveTool = prepared.tools.find((x) => x.name === pendingAction.toolName);
560
+ const reading = liveTool === undefined ? undefined : ownedReading((a) => readToolCallArguments(liveTool, { type: "toolCall", id: pendingAction.toolCallId, name: pendingAction.toolName, arguments: {} }, a));
561
+ const beltFace = () => { const f = parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction); if (f !== undefined && reading !== undefined)
562
+ stampArgsReading(f, reading); return f; };
563
+ const tryRead = (v) => { try {
564
+ return { args: reading === undefined ? v : argsReadBy(reading, v) };
565
+ }
566
+ catch (error) {
567
+ return { args: v, unread: { error } };
568
+ } };
569
+ const decided = outcome.decision === "allow" ? tryRead(humanRewrite !== undefined ? humanRewrite : pendingAction.args) : { args: humanRewrite !== undefined ? humanRewrite : pendingAction.args };
570
+ const resolvedArgs = decided.args;
584
571
  const pendingLabel = (() => { const l = prepared.tools.find((t) => t.name === pendingAction.toolName)?.label; return l !== undefined && l !== pendingAction.toolName ? { label: l } : {}; })();
585
572
  const spelledName = pendingAction.names?.[0] ?? pendingAction.toolName;
586
573
  const occurrences = prepared.toolOccurrences;
587
574
  const callStart = { toolCallId: pendingAction.toolCallId, spelledName, wireName: pendingAction.toolName, ...pendingLabel, args: resolvedArgs };
588
575
  announceToolCall(occurrences, callStart, { push: emit });
589
576
  occurrences.gateRound(pendingAction.toolCallId, decidedGate, frozenInputSnapshot(resolvedArgs));
590
- const settleEnd = async (isError, result, refusedBy) => {
577
+ let notExecuted = false;
578
+ const resultRow = (text, isError) => withRowNotExecuted(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, text, isError), notExecuted);
579
+ const settleEnd = async (isError, result, refusedBy, neverRan) => {
591
580
  if (refusedBy !== undefined)
592
581
  occurrences.refuse(pendingAction.toolCallId, refusedBy);
593
- const gate = emitSettled(occurrences, callStart, { result, isError }, { push: emit, structured: prepared.structuredProjector, mediaByteCapBytes: runner.deps.mediaByteCapBytes }).gate ?? decidedGate;
582
+ const settled = emitSettled(occurrences, callStart, { result, isError, ...(neverRan ? { notExecuted: true } : {}) }, { push: emit, structured: prepared.structuredProjector, mediaByteCapBytes: runner.deps.mediaByteCapBytes });
583
+ notExecuted = settled.notExecuted === true;
584
+ const gate = settled.gate ?? decidedGate;
594
585
  const word = await resume.recordExecutionOutcome(gate);
595
586
  settleExecutionRecord(runner.deps.onNotice, word, { toolName: pendingAction.toolName, gate, sessionId: prepared.sessionId, runId: prepared.runId, scope: resume.cp.scope, ...(resume.cp.checkpointId !== undefined ? { checkpointId: resume.cp.checkpointId } : {}) });
596
587
  };
588
+ const settleUnreadable = async (error, which) => {
589
+ const marks = egressValue("same-principal", thrownMarksOf(error));
590
+ const text = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: the tool could not read ${which} — its argument preparation failed (${egressThrownText("same-principal", error)}). This approval is spent — the call has to be re-issued.`, prepared.reminderMark);
591
+ await settleEnd(true, { content: text, ...(marks !== undefined ? { details: marks } : {}) }, undefined, true);
592
+ emitCommitted(await prepared.session.appendMessage(resultRow(text, true)), "toolResult", pendingAction.toolCallId);
593
+ };
597
594
  if (outcome.decision === "deny") {
598
595
  const settlementKind = outcome.gateOutcome?.settlement?.kind;
599
596
  const reason = settlementKind === "policy_refused"
@@ -604,7 +601,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
604
601
  : `No one answered the approval request for the pending tool call "${pendingAction.toolName}" — the approval window elapsed with no answer, so it was not executed.`
605
602
  : humanRefusalSentence("tool use", outcome.reason, prepared.hookIdentity.isDelegatedChild);
606
603
  await settleEnd(true, { content: formatHookFeedback(reason, prepared.reminderMark) });
607
- const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, formatHookFeedback(reason, prepared.reminderMark), true));
604
+ const eid = await prepared.session.appendMessage(resultRow(formatHookFeedback(reason, prepared.reminderMark), true));
608
605
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
609
606
  const parkedFallback = pendingAction.denialLimitFallback;
610
607
  if (parkedFallback !== undefined && settlementKind !== undefined && SETTLEMENT_NOBODY_JUDGED[settlementKind]) {
@@ -615,22 +612,27 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
615
612
  if (outcome.decision !== "allow") {
616
613
  throw new CheckpointError("checkpoint.invalid_outcome", `pending action reached the resolver with decision "${String(outcome.decision)}" — only "allow" executes and only "deny" injects a denial; refusing to execute`);
617
614
  }
615
+ if (decided.unread !== undefined)
616
+ return settleUnreadable(decided.unread.error, humanRewrite !== undefined ? "the arguments the decision edited it to" : "its arguments");
618
617
  const screened = await prepared.approvedCallScreen?.({ toolCallId: pendingAction.toolCallId, toolName: pendingAction.toolName, args: structuredClone(resolvedArgs), decidedBy: outcome.hostDecision.decidedBy });
619
618
  if (screened !== undefined && "refused" in screened) {
620
619
  const hookDenial = formatHookFeedback(screened.refused, prepared.reminderMark);
621
620
  await settleEnd(true, { content: hookDenial }, "hook");
622
- emitCommitted(await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, hookDenial, true)), "toolResult", pendingAction.toolCallId);
621
+ emitCommitted(await prepared.session.appendMessage(resultRow(hookDenial, true)), "toolResult", pendingAction.toolCallId);
623
622
  return;
624
623
  }
625
- const executedArgs = humanRewrite !== undefined ? resolvedArgs : screened !== undefined ? screened.args : resolvedArgs;
624
+ const rescreened = humanRewrite === undefined && screened !== undefined ? tryRead(screened.args) : undefined;
625
+ if (rescreened?.unread !== undefined)
626
+ return settleUnreadable(rescreened.unread.error, "the arguments a PreToolUse hook rewrote it to");
627
+ const executedArgs = rescreened !== undefined ? rescreened.args : resolvedArgs;
626
628
  const unseen = !deepJsonEqual(executedArgs, pendingAction.args);
627
629
  let beltReading;
628
- const beltReq = () => ({ toolName: pendingAction.toolName, args: executedArgs, toolCallId: pendingAction.toolCallId, ...callFaceSeat(parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction)), budget: beltBudget, ...(prepared.cwdRef !== undefined ? { cwd: prepared.cwdRef.current } : {}), ...(prepared.handsRoot !== undefined ? { root: prepared.handsRoot } : {}), ...advertisedWritableRootsSeat(prepared.advertisedWritableDirs), ...exemptRootsSeat(prepared.exemptRoots), ...(beltReading !== undefined ? { targetReading: beltReading } : {}) });
630
+ const beltReq = () => ({ toolName: pendingAction.toolName, args: executedArgs, toolCallId: pendingAction.toolCallId, ...callFaceSeat(beltFace()), budget: beltBudget, ...(prepared.cwdRef !== undefined ? { cwd: prepared.cwdRef.current } : {}), ...(prepared.handsRoot !== undefined ? { root: prepared.handsRoot } : {}), ...advertisedWritableRootsSeat(prepared.advertisedWritableDirs), ...exemptRootsSeat(prepared.exemptRoots), ...(beltReading !== undefined ? { targetReading: beltReading } : {}) });
629
631
  const unjudgeable = unseen ? chainCannotJudge(resume.cp.state.inheritedGate) : undefined;
630
632
  if (unjudgeable !== undefined) {
631
633
  const chainDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: its input changed after the approval and the inherited ancestor chain cannot judge the changed input (${unjudgeable}). This approval is spent — the call has to be re-issued.`, prepared.reminderMark);
632
634
  await settleEnd(true, { content: chainDenial }, "policy");
633
- emitCommitted(await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, chainDenial, true)), "toolResult", pendingAction.toolCallId);
635
+ emitCommitted(await prepared.session.appendMessage(resultRow(chainDenial, true)), "toolResult", pendingAction.toolCallId);
634
636
  return;
635
637
  }
636
638
  const beltBudget = {
@@ -642,14 +644,20 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
642
644
  const card = pathDenialCardOf(attestationOf(d, { toolCallId: pendingAction.toolCallId, toolName: pendingAction.toolName })?.pathDenial);
643
645
  return card !== undefined ? { details: card } : {};
644
646
  };
647
+ const beltCheck = async (judge, seat) => { const signal = prepared.abortController.signal; try {
648
+ return await judge(signal);
649
+ }
650
+ catch (err) {
651
+ return failedJudgmentDeny(err, signal, (e) => runner.deps.onError?.(e, { phase: "hook", sessionId: prepared.sessionId }), seat, pendingAction);
652
+ } };
645
653
  const beltStamped = prepared.stampCallTarget?.(beltReq(), prepared.abortController.signal);
646
654
  if (beltStamped !== undefined)
647
655
  beltReading = (await beltStamped).targetReading;
648
656
  if (unseen && prepared.basePolicyForResumeEdit) {
649
- const rechecked = refuseOutOfContractDecision(await prepared.basePolicyForResumeEdit.check(beltReq(), prepared.abortController.signal));
657
+ const rechecked = refuseOutOfContractDecision(await beltCheck((signal) => prepared.basePolicyForResumeEdit.check(beltReq(), signal), "the deployment's tool policy re-checking a resumed call"));
650
658
  const personUnanswered = policyCannotAnswer(rechecked, outcome.hostDecision.decidedBy);
651
659
  const beltUnsafe = rechecked.action === "deny" ||
652
- (rechecked.updatedInput !== undefined && !deepJsonEqual(rechecked.updatedInput, executedArgs)) ||
660
+ (rechecked.updatedInput !== undefined && ((read) => read.unread !== undefined || !deepJsonEqual(read.args, executedArgs))(tryRead(rechecked.updatedInput))) ||
653
661
  personUnanswered;
654
662
  if (beltUnsafe) {
655
663
  const why = rechecked.action === "deny"
@@ -659,7 +667,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
659
667
  : " (the policy rewrote these bytes to a value that was not approved)";
660
668
  const editedDenial = formatHookFeedback(`${outcome.updatedInput !== undefined ? "The approver EDITED this call's input; the edited call" : "A PreToolUse hook REWROTE this approved call's input; the rewritten call"} is refused by the deployment's tool policy and was not executed${why}.`, prepared.reminderMark);
661
669
  await settleEnd(true, { content: editedDenial, ...denialCard(rechecked) }, "policy");
662
- const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, editedDenial, true));
670
+ const eid = await prepared.session.appendMessage(resultRow(editedDenial, true));
663
671
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
664
672
  return;
665
673
  }
@@ -669,13 +677,13 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
669
677
  if (gateOrgGoverned && prepared.permissionRuleOrg === undefined) {
670
678
  const unwiredDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: its approval was minted under organization governance (${gateRealApproval.origin}), and this worker has no org adjudication wiring — a governed approval may only be redeemed where governance can be enforced. This approval is spent; re-issue the call on an org-wired worker.`, prepared.reminderMark);
671
679
  await settleEnd(true, { content: unwiredDenial }, "org");
672
- const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, unwiredDenial, true));
680
+ const eid = await prepared.session.appendMessage(resultRow(unwiredDenial, true));
673
681
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
674
682
  return;
675
683
  }
676
684
  if (prepared.permissionRuleOrg !== undefined) {
677
685
  const orgVerdict = prepared.permissionRuleOrg
678
- .adjudicate({ toolName: pendingAction.toolName, args: executedArgs, toolCallId: pendingAction.toolCallId, ...callFaceSeat(parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction)) })
686
+ .adjudicate({ toolName: pendingAction.toolName, args: executedArgs, toolCallId: pendingAction.toolCallId, ...callFaceSeat(beltFace()) })
679
687
  .catch(() => ({ status: "unavailable", disclosures: ["the org adjudication face threw on resume"] }));
680
688
  let orgWaitCancelled = false;
681
689
  const org = await settleOrgVerdictWithin(orgVerdict, { status: "unavailable", disclosures: [`the org adjudication face did not answer within ${ORG_ADJUDICATION_TIMEOUT_MS}ms (or the task ended first)`] }, {
@@ -703,17 +711,17 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
703
711
  : "";
704
712
  const orgDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: ${blocked}.${orgDisclosures} This approval is spent — the call has to be re-issued and ${unanswered ? "decided by a person" : "approved again once organization policy permits it"}.`, prepared.reminderMark);
705
713
  await settleEnd(true, { content: orgDenial }, "org");
706
- const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, orgDenial, true));
714
+ const eid = await prepared.session.appendMessage(resultRow(orgDenial, true));
707
715
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
708
716
  return;
709
717
  }
710
718
  }
711
719
  if (prepared.denyNarrowingPolicy) {
712
- const narrowed = refuseOutOfContractDecision(await prepared.denyNarrowingPolicy.check(beltReq(), prepared.abortController.signal));
720
+ const narrowed = refuseOutOfContractDecision(await beltCheck((signal) => prepared.denyNarrowingPolicy.check(beltReq(), signal), "the narrowing rules re-checking a resumed call"));
713
721
  if (narrowed.action === "deny") {
714
722
  const narrowedDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" is now denied by ${ruleSourcePhrase("narrowing")} and was not executed${narrowed.message ? `: ${narrowed.message}` : ""}.`, prepared.reminderMark);
715
723
  await settleEnd(true, { content: narrowedDenial, ...denialCard(narrowed) }, "policy");
716
- const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, narrowedDenial, true));
724
+ const eid = await prepared.session.appendMessage(resultRow(narrowedDenial, true));
717
725
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
718
726
  return;
719
727
  }
@@ -722,7 +730,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
722
730
  if (skillRefusal !== undefined) {
723
731
  const skillDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: ${skillRefusal.message}. This approval is spent — the call has to be re-issued.`, prepared.reminderMark);
724
732
  await settleEnd(true, { content: skillDenial }, "policy");
725
- emitCommitted(await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, skillDenial, true)), "toolResult", pendingAction.toolCallId);
733
+ emitCommitted(await prepared.session.appendMessage(resultRow(skillDenial, true)), "toolResult", pendingAction.toolCallId);
726
734
  return;
727
735
  }
728
736
  if (prepared.persistedRuleLane !== undefined) {
@@ -745,13 +753,13 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
745
753
  : `it could not be read against your standing deny/ask rules (${read.reason})`;
746
754
  const ruleDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: ${why}. This approval is spent — the call has to be re-issued and approved again.`, prepared.reminderMark);
747
755
  await settleEnd(true, { content: ruleDenial, ...denialCard(tightened.decision) }, "persisted_rule");
748
- const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, ruleDenial, true));
756
+ const eid = await prepared.session.appendMessage(resultRow(ruleDenial, true));
749
757
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
750
758
  return;
751
759
  }
752
760
  }
753
761
  if (prepared.shellReadCheck !== undefined) {
754
- const readCall = { toolName: pendingAction.toolName, ...callFaceSeat(parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction)) };
762
+ const readCall = { toolName: pendingAction.toolName, ...callFaceSeat(beltFace()) };
755
763
  const judged = prepared.shellReadCheck.judge(readCall, executedArgs, prepared.cwdRef?.current, prepared.abortController.signal, {
756
764
  toolCallId: pendingAction.toolCallId,
757
765
  ...(unseen ? { seat: "rejudge" } : {}),
@@ -768,7 +776,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
768
776
  if (reading.kind === "refuse" || reading.kind === "silence" || (unseen && reading.kind !== "vouch")) {
769
777
  const readDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: ${reading.verdict.sentence ?? "the read boundary does not vouch for what it reads on this leg"} This approval is spent — the call has to be re-issued and approved again.`, prepared.reminderMark);
770
778
  await settleEnd(true, { content: readDenial, ...(reading.verdict.details !== undefined ? { details: reading.verdict.details } : {}) }, "read_boundary");
771
- const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, readDenial, true));
779
+ const eid = await prepared.session.appendMessage(resultRow(readDenial, true));
772
780
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
773
781
  return;
774
782
  }
@@ -779,7 +787,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
779
787
  if (grantRefusal !== undefined) {
780
788
  const grantDenial = formatHookFeedback(grantRefusal, prepared.reminderMark);
781
789
  await settleEnd(true, { content: grantDenial }, "policy");
782
- emitCommitted(await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, grantDenial, true)), "toolResult", pendingAction.toolCallId);
790
+ emitCommitted(await prepared.session.appendMessage(resultRow(grantDenial, true)), "toolResult", pendingAction.toolCallId);
783
791
  return;
784
792
  }
785
793
  const tool = prepared.tools.find((t) => t.name === pendingAction.toolName);
@@ -791,7 +799,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
791
799
  const args = executedArgs;
792
800
  screened?.admit();
793
801
  onExecuteStart?.(pendingAction.toolCallId);
794
- occurrences.execute(pendingAction.toolCallId);
802
+ occurrences.release(pendingAction.toolCallId);
795
803
  prepared.suspendProgressRef.executedApproved = true;
796
804
  const finalize = (executed) => prepared.harness.finalizeToolCall({ type: "toolCall", id: pendingAction.toolCallId, name: spelledName, arguments: executedArgs }, executedArgs, executed);
797
805
  let res;
@@ -804,7 +812,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
804
812
  const failed = await finalize({ result: { content: [{ type: "text", text: execError }], details: marks ?? {} }, isError: true });
805
813
  const failedText = failed.result.content.flatMap((c) => (c.type === "text" ? [c.text] : [])).join("\n");
806
814
  await settleEnd(true, { content: failedText, ...(marks !== undefined ? { details: marks } : {}) });
807
- const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, failedText, true));
815
+ const eid = await prepared.session.appendMessage(resultRow(failedText, true));
808
816
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
809
817
  return;
810
818
  }
@@ -816,7 +824,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
816
824
  toolCallId: pendingAction.toolCallId,
817
825
  toolName: pendingAction.toolName,
818
826
  content: ran.result.content,
819
- details: ran.result.details,
827
+ details: rowDetailsOf(ran.result.details, notExecuted),
820
828
  isError: ran.isError,
821
829
  timestamp: Date.now(),
822
830
  });
@@ -15,6 +15,7 @@ async function runNotificationLaneAs(input, obligations) {
15
15
  suspendedBatch: new Set(resume.cp.pendingAction.kind === "tool_approval" ? resume.cp.pendingAction.batchToolCallIds : []),
16
16
  seed: resume.cp.state,
17
17
  outcome: resume.outcome,
18
+ ...(resume.legMods !== undefined ? { legMods: resume.legMods } : {}),
18
19
  priorSuspendCount: resume.cp.suspendCount,
19
20
  priorLedger: resume.cp.resourceLedger,
20
21
  priorHumanReview: resume.cp.humanReview,
@@ -3,6 +3,7 @@ import { type MaybeCompactOptions } from "../auto-compaction.js";
3
3
  import type { PushQueue } from "../push-queue.js";
4
4
  import type { Brain, TaskEvent, TaskSpec } from "../types.js";
5
5
  import type { InstallingPhaseResult, Prepared, RunnerDepsSeat, RunState } from "./contracts.js";
6
+ import type { CallerStopGate } from "./caller-stop-gate.js";
6
7
  export interface RunRecoveryLanesInput {
7
8
  /** borrowed-readonly — the task spec: the compaction settings / instructions and the key-and-headers seat. */
8
9
  spec: TaskSpec;
@@ -30,6 +31,8 @@ export interface RunRecoveryLanesInput {
30
31
  };
31
32
  /** borrowed-readonly — the window-safety option builder (the compaction-machinery lane's), per pass. */
32
33
  windowSafetyOptions: (mainModel: Model) => Pick<MaybeCompactOptions, "fallbackBudget" | "onWindowSafety">;
34
+ /** borrowed-readonly — the run's caller-stop gate: the shared pass admits on it and carries it. */
35
+ callerStop: CallerStopGate;
33
36
  /** borrowed-readonly — the Runner's deployment deps, read LIVE (`onError`; the compaction seams the pass reaches down
34
37
  * for — compaction-seams.ts — read the summary provider and the hooks slot through it on every pass). */
35
38
  runner: RunnerDepsSeat;
@@ -2,7 +2,7 @@ import { compactionKindOf } from "../task-notification.js";
2
2
  import { planRejectionClears } from "../context-edit.js";
3
3
  import { rosterToolName } from "../tool-roster.js";
4
4
  import { landStaleResultClears } from "./prepare-context-lane.js";
5
- import { DEFAULT_COMPACTION_INSTRUCTIONS, maybeCompact, mintCompactedEvent } from "../auto-compaction.js";
5
+ import { compactionPassReport, DEFAULT_COMPACTION_INSTRUCTIONS, isCompactionManualCancel, maybeCompact, mintCompactedEvent } from "../auto-compaction.js";
6
6
  import { emitTrace } from "../trace.js";
7
7
  import { isDegenerateCutMessage } from "../../brain/terminal-cause.js";
8
8
  import { rebaseCadenceWindows } from "./turn-attachments.js";
@@ -13,17 +13,20 @@ import { COMPACTION_FREED_EPSILON, COMPACTION_REGROWTH_FACTOR, MAX_CONSECUTIVE_C
13
13
  import { compactionHookOptions, recordCompactionReuse, seamCCompactionOptions } from "./compaction-seams.js";
14
14
  import { asThrownError, thrownText } from "../thrown-value.js";
15
15
  export function runRecoveryLanes(input) {
16
- const { spec, prepared, queue, rs, ident, compactionBrain, compactionBreaker, windowSafetyOptions, runner } = input;
16
+ const { spec, prepared, queue, rs, ident, compactionBrain, compactionBreaker, windowSafetyOptions, callerStop, runner } = input;
17
17
  const runForcedCompactionPass = async (lane, turnSignal) => {
18
18
  if (!compactionEnabled(spec.compaction?.enabled, legContextOverlayOption(prepared, runner).contextOverlay))
19
19
  return false;
20
20
  if (compactionBreaker.failures >= MAX_CONSECUTIVE_COMPACTION_FAILURES)
21
21
  return false;
22
- const passSignal = turnSignal !== undefined ? AbortSignal.any([prepared.abortController.signal, turnSignal]) : prepared.abortController.signal;
22
+ if (callerStop.signal.aborted)
23
+ return false;
24
+ const passSignal = AbortSignal.any([prepared.abortController.signal, callerStop.signal, ...(turnSignal !== undefined ? [turnSignal] : [])]);
25
+ const passReport = compactionPassReport(queue, ident);
23
26
  try {
24
27
  const comp = await maybeCompact({
25
28
  session: prepared.session,
26
- epochDeclaredSections: prepared.epochDeclaredSections,
29
+ promptIdentity: prepared.promptIdentity,
27
30
  ...centerAdoptionOption(prepared),
28
31
  model: prepared.harness.getModel(),
29
32
  ...legContextOverlayOption(prepared, runner),
@@ -35,6 +38,7 @@ export function runRecoveryLanes(input) {
35
38
  settings: legCompactionSettings(spec, legContextOverlayOption(prepared, runner).contextOverlay),
36
39
  customInstructions: spec.compaction?.instructions ?? DEFAULT_COMPACTION_INSTRUCTIONS,
37
40
  signal: passSignal,
41
+ manualCancelSignal: callerStop.signal,
38
42
  minTokens: 0,
39
43
  force: true,
40
44
  overheadTokens: prepared.promptOverheadTokens,
@@ -46,7 +50,8 @@ export function runRecoveryLanes(input) {
46
50
  ...seamCCompactionOptions(runner, prepared),
47
51
  ...compactionRestateOptions(prepared),
48
52
  ...windowSafetyOptions(prepared.harness.getModel()),
49
- ...compactionHookOptions(runner, spec, prepared.sessionId, "forced", prepared.hookIdentity, { timeoutMs: prepared.hookTimeoutMs, signal: passSignal }),
53
+ ...compactionHookOptions(runner, prepared, "forced", passSignal),
54
+ onStarted: passReport.onStarted,
50
55
  });
51
56
  if (comp.compacted) {
52
57
  compactionBreaker.failures = 0;
@@ -90,17 +95,15 @@ export function runRecoveryLanes(input) {
90
95
  return comp.compacted === true;
91
96
  }
92
97
  catch (err) {
93
- if (turnSignal?.aborted === true && !prepared.abortController.signal.aborted) {
94
- const interruptReason = lane === "rejection"
95
- ? "prompt-too-long recovery pass cut short by a turn interrupt"
96
- : "guard-chain forced compaction cut short by a turn interrupt";
97
- queue.push({ type: "compaction_outcome", outcome: "failed", trigger: "forced", reason: interruptReason, ...ident() });
98
+ if (isCompactionManualCancel(err) || (turnSignal?.aborted === true && !prepared.abortController.signal.aborted)) {
99
+ emitTrace(rs.telemetry.tracer, () => ({ kind: "compaction.mooted", version: 1, taskId: rs.telemetry.taskId, reason: "cancelled", ts: Date.now() }));
100
+ queue.push({ type: "compaction_outcome", outcome: "mooted", trigger: "forced", reason: "cancelled", ...passReport.end, ...ident() });
98
101
  return false;
99
102
  }
100
103
  compactionBreaker.failures += 1;
101
104
  runner.deps.onError?.(asThrownError(err), { phase: "compaction", sessionId: prepared.sessionId });
102
105
  const msg = thrownText(err);
103
- queue.push({ type: "compaction_outcome", outcome: "failed", trigger: "forced", reason: msg.length > 512 ? `${msg.slice(0, 512)}…` : msg, ...ident() });
106
+ queue.push({ type: "compaction_outcome", outcome: "failed", trigger: "forced", reason: msg.length > 512 ? `${msg.slice(0, 512)}…` : msg, ...passReport.end, ...ident() });
104
107
  return false;
105
108
  }
106
109
  };
@@ -6,7 +6,7 @@ import { isDegenerateCutMessage } from "../../brain/terminal-cause.js";
6
6
  import { hasBackgroundShell, sweepRunBoundaryBackgroundShells } from "../background-shell.js";
7
7
  import { resolveCheckpointStore } from "../checkpoint-store.js";
8
8
  import { reopenReasonOf, reopenedUnstartedSentence, resumeStartupCauseOf } from "../resume-startup-cause.js";
9
- import { hookSeatExpiredError, runHookSeat } from "../hooks.js";
9
+ import { classicEventBase, observeClassic } from "../mods/stations.js";
10
10
  import { modelCostToPricing } from "../pricing.js";
11
11
  import { hasDestroy, isIsolated } from "../remote-env.js";
12
12
  import { resolveTaskModel } from "../roles.js";
@@ -25,7 +25,6 @@ import { owedDateAnchor } from "./announce-once-ledger.js";
25
25
  import { autoRunConsolidationFromRecommendation, autoRunOnRecommendationEffective, scopeHasUnconsumedRecommendation } from "./memory-consolidation-driver.js";
26
26
  import { amendTerminal, terminalProjection } from "./terminal-projection.js";
27
27
  import { mintCompactedEvent } from "../auto-compaction.js";
28
- import { asThrownError } from "../thrown-value.js";
29
28
  export async function runSettleAndTeardown(input) {
30
29
  const { spec, queue, prepared, resume, internals, rs, stats, ident, loopLatch, timeout, ownCommittedTailRef, emitDelegationLifecycle, taskIdRef, manualCompactRef, drainManualCompact, final, threw, abortedLive, userInterruptedLive, answerSettled, strandedHumanAnswers, reasoningResolution, comp, compactionBreaker, owedUserInput, setResult, onSuggestions, onSuspend, runner, sessions } = input;
31
30
  try {
@@ -57,7 +56,7 @@ export async function runSettleAndTeardown(input) {
57
56
  const cause = rs.degrade.degraded
58
57
  ? `a mid-task model switch (${rs.degrade.degraded.from} → ${rs.degrade.degraded.to}, degradation) reset the prefix cache — this is the likely cause`
59
58
  : cacheWritten > 0
60
- ? `this task reported ${cacheWritten} cache-write tokens across its calls (compaction included) but served almost none back as reads — consistent with a prompt prefix that CHANGES between turns (client-side: volatile content up front, or per-turn tool churn/reorder) and, less often, with server-side eviction. Keep volatile content (memory/timestamps/ids) out of the prefix and the tool list stable in membership AND order`
59
+ ? `this task reported ${cacheWritten} cache-write tokens across its calls (compaction and the classifier's included) but served almost none back as reads — consistent with a prompt prefix that CHANGES between turns (client-side: volatile content up front, or per-turn tool churn/reorder) and, less often, with server-side eviction. Keep volatile content (memory/timestamps/ids) out of the prefix and the tool list stable in membership AND order`
61
60
  : `no call in this task reported any cache-write tokens — and this API family may not report them at all (an openai-shaped usage row carries cached READS only), so the write side is no evidence here; check that the prompt prefix (system prompt + tool list, membership AND order) is byte-stable across turns and that this route caches this model`;
62
61
  runner.deps.onError?.(new Error(`prompt-cache: low prefix-cache hit rate ${(stats.cacheHitRate * 100).toFixed(0)}% over ${stats.turns} turns (${stats.totalInputTokens} prompt tokens) — ${cause}. See design/09.`), { phase: "prompt-cache", sessionId: prepared.sessionId });
63
62
  }
@@ -168,8 +167,7 @@ export async function runSettleAndTeardown(input) {
168
167
  }
169
168
  }
170
169
  }
171
- const stopFailureHook = (spec.hooks ?? runner.deps.hooks)?.stopFailure;
172
- if (stopFailureHook !== undefined &&
170
+ if (prepared.modBus.hasHandlers("classic.StopFailure") &&
173
171
  result.terminal.kind === "failed" &&
174
172
  final?.stopReason === "error" &&
175
173
  !isDegenerateCutMessage(final) &&
@@ -180,29 +178,12 @@ export async function runSettleAndTeardown(input) {
180
178
  !abortedLive &&
181
179
  result.terminal.code !== "conflict") {
182
180
  const failedCause = result.terminal;
183
- try {
184
- const failureSeat = await runHookSeat("stopFailure", { timeoutMs: prepared.hookTimeoutMs }, (sig) => stopFailureHook({
185
- identity: prepared.hookIdentity,
186
- error: failedCause.message ?? "model error",
187
- ...(failedCause.code !== undefined ? { errorKind: failedCause.code } : {}),
188
- turns: stats.turns,
189
- signal: sig,
190
- }));
191
- if (failureSeat.expired) {
192
- try {
193
- runner.deps.onError?.(hookSeatExpiredError("stopFailure", prepared.hookTimeoutMs, failureSeat.cause, "the terminal observation was abandoned; the assembled TaskResult is unchanged"), { phase: "hook", sessionId: prepared.sessionId });
194
- }
195
- catch {
196
- }
197
- }
198
- }
199
- catch (err) {
200
- try {
201
- runner.deps.onError?.(asThrownError(err), { phase: "hook", sessionId: prepared.sessionId });
202
- }
203
- catch {
204
- }
205
- }
181
+ await observeClassic(prepared.modBus, "classic.StopFailure", {
182
+ ...classicEventBase(prepared.hookIdentity),
183
+ error: failedCause.message ?? "model error",
184
+ ...(failedCause.code !== undefined ? { errorKind: failedCause.code } : {}),
185
+ turns: stats.turns,
186
+ }, undefined);
206
187
  }
207
188
  const terminalFace = terminalProjection(result.terminal);
208
189
  emitDelegationLifecycle({