@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
@@ -20,6 +20,10 @@ export declare function retiredKeyOf(bag: object, table: Readonly<Record<string,
20
20
  * `RunWorkflowToolDeps`, `TaskSpec`).
21
21
  */
22
22
  export declare function assertNoRetiredKeys(bag: object, table: Readonly<Record<string, string>>, owner: string): void;
23
+ /** What replaced the `hooks` record, on a deps bag and on a `TaskSpec` alike: one seat name, one sentence, quoted by both
24
+ * tables (this one and `runner/retired-runner-deps.ts`). The record's callbacks never run, so a deny one carried would pass
25
+ * unseen — the key is refused by name instead. */
26
+ export declare const RETIRED_HOOKS_REPLACEMENT = "the callback seats are `mods` registrations now \u2014 register the extension on `RunnerDeps.mods` (a deployment's) or `TaskSpec.mods` (a task's), hung on the `classic.*` events (`classic.PreToolUse`, `classic.PostToolUse`, `classic.PostToolBatch`, `classic.UserPromptSubmit`, `classic.Stop`, `classic.SubagentStop`, \u2026); a callback that denied is a handler answering `{ action: \"deny\", message }`";
23
27
  /** The RETIRED `TaskSpec` keys, each with the sentence that names its replacement — the table the spec door reads
24
28
  * ({@link assertNoRetiredKeys} with owner `TaskSpec`). A caller still writing one of these is refused by name
25
29
  * (`config.spec_retired_key`), never read as absence: a mode a caller believes it declared must not silently run
@@ -42,7 +46,13 @@ export declare const RETIRED_SHELL_READ_BOUNDARY_KEYS: Readonly<Record<string, s
42
46
  * decision that carries one is denied in the engine's own words, never read without it: the type retires a member only where
43
47
  * a decision is a literal in an annotated position, and a `check` whose return type is inferred still compiles with it. */
44
48
  export declare const RETIRED_DECISION_MEMBERS: Readonly<Record<string, string>>;
45
- /** The `ToolPolicy` door ({@link RETIRED_TOOL_POLICY_KEYS}); `undefined` is no policy. */
46
- export declare function assertNoRetiredToolPolicyKeys(policy: object | undefined): void;
49
+ /**
50
+ * The `ToolPolicy` door — every policy the engine installs passes it (a task's or deployment's seat, a combined member, an inherited
51
+ * constraint): `undefined` (or `null`, the seat's other absence spelling) is no policy; a value that is not an object whose `check`
52
+ * is a function is no policy either, and refuses by name (`config.invalid_argument`, `detail.field: "ToolPolicy"`) — a policy the
53
+ * engine cannot call is never installed as if it were absent, which would run the leg with nothing the deployment meant to apply;
54
+ * a retired member refuses by name ({@link RETIRED_TOOL_POLICY_KEYS}).
55
+ */
56
+ export declare function assertNoRetiredToolPolicyKeys(policy: unknown): void;
47
57
  /** The `ShellReadBoundary` door ({@link RETIRED_SHELL_READ_BOUNDARY_KEYS}). */
48
58
  export declare function assertNoRetiredShellReadBoundaryKeys(boundary: object): void;
@@ -24,11 +24,14 @@ export function assertNoRetiredKeys(bag, table, owner) {
24
24
  e.code = owner === "TaskSpec" ? "config.spec_retired_key" : "config.deps_retired_key";
25
25
  throw e;
26
26
  }
27
+ export const RETIRED_HOOKS_REPLACEMENT = 'the callback seats are `mods` registrations now — register the extension on `RunnerDeps.mods` (a deployment\'s) or `TaskSpec.mods` (a task\'s), hung on the `classic.*` events (`classic.PreToolUse`, `classic.PostToolUse`, `classic.PostToolBatch`, `classic.UserPromptSubmit`, `classic.Stop`, `classic.SubagentStop`, …); a callback that denied is a handler answering `{ action: "deny", message }`';
27
28
  export const RETIRED_TASK_SPEC_KEYS = Object.freeze({
29
+ hooks: RETIRED_HOOKS_REPLACEMENT,
28
30
  autoModeRequested: 'the permission mode is one key now — write `permissionMode: "auto"`',
29
31
  approverPosture: 'a posture never authorized anything; drop the key (the engine renders the posture from the effective mode). Releasing asks is a separate decision: `permissionMode: "bypassPermissions"`',
30
32
  "attachments.planModeReminder": "the read-only planning posture is stated whenever the leg's mode is `plan` (first turn, every 5 turns, and an exit frame when it ends) — drop the key",
31
33
  "skills[].manifest": "a skill's tools are its `allowedTools` / `disallowedTools` now — an allow-rule and a deny-rule source for the run the skill is activated in, never a fence; move `manifest.allowTools` to `allowedTools`. To fence tools write deny rules (or a delegated agent definition's `allowTools`); to fence write paths use session `allowDirs`",
34
+ promptProvider: "a task changes prompt text through overlays: its role text is `systemPrompt` (it replaces the role base `promptRole` selects), its added block `appendSystemPrompt`, the minimal form `promptForm: \"minimal\"`; anything else is a `prompt.compose` registration on the task's own `mods` answering `{ overlays }` (an already-assembled prompt is refused, never passed through)",
32
35
  });
33
36
  export const RETIRED_TOOL_POLICY_KEYS = Object.freeze({
34
37
  writeTargetGuard: "the guarded write targets are stated as rows now — `ToolPolicy.writeGuardRows`, an async provider of the one path table's `PathGuardRow`s the leg's ONE write judgment reads for every writer the policy cannot see as a call (the shell's file commands). A wrapper carries it through `wrapToolPolicy`, which reads every member a policy declares",
@@ -42,8 +45,19 @@ export const RETIRED_DECISION_MEMBERS = Object.freeze({
42
45
  guard: 'write `guards: ["<word>"]` instead (the same five words, as a list: one ask may stand on several integrity guards)',
43
46
  });
44
47
  export function assertNoRetiredToolPolicyKeys(policy) {
45
- if (policy !== undefined)
48
+ if (policy === undefined || policy === null)
49
+ return;
50
+ const isRecord = typeof policy === "object" && !Array.isArray(policy);
51
+ if (isRecord)
46
52
  assertNoRetiredKeys(policy, RETIRED_TOOL_POLICY_KEYS, "ToolPolicy");
53
+ const check = isRecord ? policy.check : undefined;
54
+ if (typeof check !== "function") {
55
+ const got = typeof policy !== "object" ? typeof policy : Array.isArray(policy) ? "an array" : `an object whose check is ${check === null ? "null" : typeof check}`;
56
+ const e = new Error(`ToolPolicy must be an object whose \`check\` is a function (got ${got}) — a policy the engine cannot call is refused rather than run as no policy; omit the seat for none.`);
57
+ e.code = "config.invalid_argument";
58
+ e.detail = { field: "ToolPolicy" };
59
+ throw e;
60
+ }
47
61
  }
48
62
  export function assertNoRetiredShellReadBoundaryKeys(boundary) {
49
63
  assertNoRetiredKeys(boundary, RETIRED_SHELL_READ_BOUNDARY_KEYS, "ShellReadBoundary");
@@ -1,11 +1,29 @@
1
1
  import { selectModel } from "./select-model.js";
2
2
  import { MODEL_ROLES } from "./types.js";
3
3
  export { MODEL_ROLES } from "./types.js";
4
+ function catalogModel(ref, models) {
5
+ const m = models != null && (typeof models === "object" || typeof models === "function") && Object.hasOwn(models, ref) ? models[ref] : undefined;
6
+ return m || undefined;
7
+ }
8
+ function modelBindingRefusal(seat, reason, message) {
9
+ const e = new Error(message);
10
+ e.code = "config.unknown_role";
11
+ e.detail = { field: seat, reason };
12
+ return e;
13
+ }
14
+ function bindingShown(value) {
15
+ if (typeof value === "string")
16
+ return JSON.stringify(value.length > 80 ? `${value.slice(0, 80)}…` : value);
17
+ return value === null ? "null" : Array.isArray(value) ? "a list" : `a ${typeof value}`;
18
+ }
19
+ function unknownModelRefRefusal(ref, seat) {
20
+ return modelBindingRefusal(seat, "unknown_model_ref", `Unknown model ref ${bindingShown(ref)} in ${seat}. Provide it in RunnerDeps.models or pass a Model object.`);
21
+ }
4
22
  export function resolveModel(ref, models) {
5
23
  if (typeof ref !== "string") {
6
24
  return ref;
7
25
  }
8
- const m = models !== undefined && Object.hasOwn(models, ref) ? models[ref] : undefined;
26
+ const m = catalogModel(ref, models);
9
27
  if (!m) {
10
28
  throw new Error(`Unknown model ref "${ref}". Provide it in RunnerDeps.models or pass a Model object.`);
11
29
  }
@@ -33,7 +51,19 @@ export function expandTiers(models, tiers) {
33
51
  out[TIER_ALIAS_VIA] = aliasVia;
34
52
  const bound = (name) => {
35
53
  const b = Object.hasOwn(tiers, name) ? tiers[name] : undefined;
36
- return b === undefined ? undefined : resolveModel(b, models);
54
+ if (b === undefined)
55
+ return undefined;
56
+ const seat = `tiers.${name}`;
57
+ if (typeof b === "string") {
58
+ const held = catalogModel(b, models);
59
+ if (held === undefined)
60
+ throw unknownModelRefRefusal(b, seat);
61
+ return held;
62
+ }
63
+ if (typeof b !== "object" || b === null || Array.isArray(b)) {
64
+ throw modelBindingRefusal(seat, "not_a_model_ref", `${seat} is ${bindingShown(b)}, not a model reference — a tier binds a catalog model name or a Model object.`);
65
+ }
66
+ return b;
37
67
  };
38
68
  const ownKey = (k) => models !== undefined && Object.hasOwn(models, k) && Boolean(models[k]);
39
69
  const landing = (t, self) => {
@@ -131,13 +161,16 @@ const FALLBACK = {
131
161
  classifier: ["summarize", "default"],
132
162
  consolidate: ["summarize"],
133
163
  };
134
- function specParts(s) {
164
+ function specParts(s, seat = "a role seat") {
135
165
  if (s == null) {
136
166
  return {};
137
167
  }
138
168
  if (typeof s === "string") {
139
169
  return { model: s };
140
170
  }
171
+ if (typeof s !== "object" && typeof s !== "function") {
172
+ throw modelBindingRefusal(seat, "not_a_model_ref", `${seat} is ${bindingShown(s)}, not a model reference — a role binds a catalog model name, a Model object or a { model, select, thinking, systemPrompt } record.`);
173
+ }
141
174
  if ("id" in s && "api" in s) {
142
175
  return { model: s };
143
176
  }
@@ -191,12 +224,17 @@ function mergeRoles(base, over) {
191
224
  }
192
225
  return out;
193
226
  }
194
- function partsModel(parts, models) {
227
+ function partsModel(parts, models, seat = "a role seat") {
195
228
  if (parts.model) {
196
229
  return resolveModel(parts.model, models);
197
230
  }
198
231
  if (parts.select) {
199
- return selectModel(models ?? {}, parts.select);
232
+ const needs = parts.select.needs;
233
+ if (needs != null && !Array.isArray(needs)) {
234
+ throw modelBindingRefusal(`${seat}.select`, "not_a_model_ref", `${seat}.select.needs is ${bindingShown(needs)}, not a list of capabilities (vision / reasoning).`);
235
+ }
236
+ const held = models != null && typeof models === "object" ? Object.values(models).filter(Boolean) : [];
237
+ return selectModel(held, parts.select);
200
238
  }
201
239
  return undefined;
202
240
  }
@@ -204,7 +242,7 @@ export function resolveTaskModel(spec, deps) {
204
242
  const start = spec.modelRole ?? "default";
205
243
  assertKnownRole(start, "modelRole");
206
244
  if (spec.model) {
207
- const startParts = specParts(mergeRoles(deps.roles, spec.roles)[start]);
245
+ const startParts = specParts(mergeRoles(deps.roles, spec.roles)[start], `roles.${start}`);
208
246
  return {
209
247
  model: resolveModel(spec.model, deps.models),
210
248
  modelRef: spec.model,
@@ -213,10 +251,10 @@ export function resolveTaskModel(spec, deps) {
213
251
  };
214
252
  }
215
253
  const merged = mergeRoles(deps.roles, spec.roles);
216
- const startSystemPrompt = specParts(merged[start]).systemPrompt;
254
+ const startSystemPrompt = specParts(merged[start], `roles.${start}`).systemPrompt;
217
255
  for (const role of [start, ...FALLBACK[start]]) {
218
- const parts = specParts(merged[role]);
219
- const fromParts = partsModel(parts, deps.models);
256
+ const parts = specParts(merged[role], `roles.${role}`);
257
+ const fromParts = partsModel(parts, deps.models, `roles.${role}`);
220
258
  const model = fromParts ?? roleTierModel(role, deps.models);
221
259
  if (model) {
222
260
  const modelRef = fromParts !== undefined ? (parts.model ?? model) : (ROLE_TIER_DEFAULTS[role] ?? model);
@@ -227,5 +265,17 @@ export function resolveTaskModel(spec, deps) {
227
265
  }
228
266
  export function roleModelIfSet(role, spec, deps) {
229
267
  const merged = mergeRoles(deps.roles, spec.roles);
230
- return partsModel(specParts(merged[role]), deps.models) ?? roleTierModel(role, deps.models);
268
+ const seat = `roles.${role}`;
269
+ const parts = specParts(merged[role], seat);
270
+ const named = parts.model;
271
+ if (named) {
272
+ if (typeof named === "string") {
273
+ if (catalogModel(named, deps.models) === undefined)
274
+ throw unknownModelRefRefusal(named, seat);
275
+ }
276
+ else if (typeof named !== "object" || Array.isArray(named)) {
277
+ throw modelBindingRefusal(seat, "not_a_model_ref", `${seat}.model is ${bindingShown(named)}, not a model reference — a role binds a catalog model name or a Model object.`);
278
+ }
279
+ }
280
+ return partsModel(parts, deps.models, seat) ?? roleTierModel(role, deps.models);
231
281
  }
@@ -65,7 +65,7 @@ export function normalizeOrgGateVerdict(answer, unreadable) {
65
65
  if ((behavior !== "deny" && behavior !== "ask") || typeof rule !== "string")
66
66
  return clean({ status: "unavailable", disclosures: [unreadable] });
67
67
  const reason = ownDataValue(verdict, "unreadable");
68
- const unreadableCell = behavior === "ask" && typeof reason === "string" ? { unreadable: reason } : {};
68
+ const unreadableCell = typeof reason === "string" ? { unreadable: reason } : {};
69
69
  return clean({ status: "available", verdict: clean({ behavior: behavior, rule, ...unreadableCell }), ...revisionCell });
70
70
  }
71
71
  function copiedDenial(raw, ruleTexts) {
@@ -1,6 +1,6 @@
1
1
  import type { AnnouncedListingSnapshot, AnnouncedListingSnapshotInput, AnnouncedMcpFailure } from "../../internal/harness.js";
2
2
  import type { SessionTreeEntry } from "../../internal/harness-types.js";
3
- import type { DateAnchorRead } from "./contracts.js";
3
+ import type { AnnounceOnceSink, DateAnchorRead } from "./contracts.js";
4
4
  import type { McpDroppedTool, McpServerStatus } from "../mcp.js";
5
5
  import type { RunnerDeps } from "../types.js";
6
6
  /** Upper bound on the advisory-digest arm kept in the record (oldest dropped past it). A digest is
@@ -18,6 +18,31 @@ export declare function announceDigest(lane: string, text: string): string;
18
18
  * an equality oracle on a secret is still an oracle. The forwarded line itself is untouched (the sink
19
19
  * owns its own redaction posture); only the identity is judged on the redacted form. */
20
20
  export declare function warningDigest(err: unknown): string;
21
+ /** The two built-in memory pairs a mount can decline, each with its sentence frame and the `classification`
22
+ * word its advisory carries on the operator sink. */
23
+ declare const MEMORY_MOUNT_ADVISORY: {
24
+ readonly shared: {
25
+ readonly label: "Shared memory tools";
26
+ readonly classification: "shared-memory-not-mounted";
27
+ readonly tail: "the pair mounts together or not at all";
28
+ };
29
+ readonly engine: {
30
+ readonly label: "Memory tools";
31
+ readonly classification: "memory-tools-not-mounted";
32
+ readonly tail: "these tools mount together or not at all";
33
+ };
34
+ };
35
+ /** Which built-in memory pair an advisory is about. */
36
+ export type MemoryMountPair = keyof typeof MEMORY_MOUNT_ADVISORY;
37
+ /**
38
+ * THE one mint for "a built-in memory pair was NOT mounted": the shared-memory pair and the engine memory trio each
39
+ * decline to mount when the deployment's selector excludes a name, when a caller tool already occupies one, or when
40
+ * mounting them would inject the ToolSearch tool under a name the task already declares — four stations, one sentence
41
+ * frame, one scope. The fact belongs to the deployment's configuration, so it is told once per RUNNER
42
+ * ({@link AnnounceOnceLedger.onErrorOncePerRunner}), not once per conversation. `reason` is the clause after the
43
+ * colon; the pair's `names` are the tools that stay unmounted together.
44
+ */
45
+ export declare function announceMemoryNotMounted(sink: Pick<AnnounceOnceSink, "onErrorOncePerRunner">, sessionId: string, pair: MemoryMountPair, names: readonly string[], reason: string): void;
21
46
  /** The digest of one model-facing dropped-tool entry (server, tool, reason — the three fields the
22
47
  * frame prints). */
23
48
  export declare function droppedToolDigest(d: McpDroppedTool): string;
@@ -60,6 +85,10 @@ export interface AnnounceOnceLedger {
60
85
  * the record is dropped; a new one is forwarded to `deps.onError` and recorded. With no sink wired
61
86
  * nothing is recorded either — "announced" means delivered. Same signature as `RunnerDeps.onError`. */
62
87
  onError: NonNullable<RunnerDeps["onError"]>;
88
+ /** The operator-lane sink for a DEPLOYMENT fact (see {@link AnnounceOnceSink.onErrorOncePerRunner}): the same
89
+ * `(code, message)` digest, judged against what THIS RUNNER's sink has already been told rather than against
90
+ * the session's record. Writes no digest into the record and owes the transcript nothing. */
91
+ onErrorOncePerRunner: NonNullable<RunnerDeps["onError"]>;
63
92
  /** The MODEL-face pending set for this run: the currently failed servers (name/error neutralized +
64
93
  * bounded at intake, the reminder's own bounds) MINUS the pairs already announced on this branch.
65
94
  * As a side effect the record's `mcpFailed` arm is pruned to the pairs that are STILL failing —
@@ -122,3 +151,4 @@ export declare function owedDateAnchor(session: {
122
151
  } | undefined, state: {
123
152
  announcedDate: string;
124
153
  } | undefined): (() => Promise<void>) | undefined;
154
+ export {};
@@ -3,6 +3,7 @@ import { egressText } from "../untrusted-egress.js";
3
3
  import { inlineUntrusted } from "../untrusted-text.js";
4
4
  import { thrownText } from "../thrown-value.js";
5
5
  export const ANNOUNCE_ONCE_MAX_DIGESTS = 200;
6
+ const RUNNER_ANNOUNCED = new WeakMap();
6
7
  const DROPPED_TOOL_MODEL_LANE = "mcp_dropped_tools";
7
8
  export function announceDigest(lane, text) {
8
9
  return createHash("sha256").update(lane).update("\n").update(text).digest("hex");
@@ -13,6 +14,14 @@ export function warningDigest(err) {
13
14
  const message = thrownText(err);
14
15
  return announceDigest(code, egressText("same-principal", message));
15
16
  }
17
+ const MEMORY_MOUNT_ADVISORY = {
18
+ shared: { label: "Shared memory tools", classification: "shared-memory-not-mounted", tail: "the pair mounts together or not at all" },
19
+ engine: { label: "Memory tools", classification: "memory-tools-not-mounted", tail: "these tools mount together or not at all" },
20
+ };
21
+ export function announceMemoryNotMounted(sink, sessionId, pair, names, reason) {
22
+ const p = MEMORY_MOUNT_ADVISORY[pair];
23
+ sink.onErrorOncePerRunner(new Error(`${p.label} ${names.join("/")} were NOT mounted: ${reason} — ${p.tail}.`), { phase: "config", sessionId, classification: p.classification });
24
+ }
16
25
  export function droppedToolDigest(d) {
17
26
  return announceDigest(DROPPED_TOOL_MODEL_LANE, `${d.server}\n${d.tool}\n${d.reason}`);
18
27
  }
@@ -62,6 +71,19 @@ export async function loadAnnounceOnceLedger(session, checkpointMirror, onError)
62
71
  advisories.add(digest);
63
72
  dirty = true;
64
73
  },
74
+ onErrorOncePerRunner: (err, ctx) => {
75
+ if (onError === undefined)
76
+ return;
77
+ const digest = warningDigest(err);
78
+ const told = RUNNER_ANNOUNCED.get(onError) ?? new Set();
79
+ RUNNER_ANNOUNCED.set(onError, told);
80
+ if (told.has(digest))
81
+ return;
82
+ onError(err, ctx);
83
+ told.add(digest);
84
+ if (told.size > ANNOUNCE_ONCE_MAX_DIGESTS)
85
+ told.delete(told.values().next().value);
86
+ },
65
87
  mcpFailuresToAnnounce: (statuses) => {
66
88
  const current = statuses
67
89
  .filter((s) => s.status === "failed")
@@ -67,6 +67,11 @@ export interface Stats {
67
67
  * (so it can't be re-derived from `costMicroUsd` alone). The {@link costBreakdown.compactionMicroUsd}
68
68
  * source. Run-loop internal — not a public `TaskResult.stats` field. */
69
69
  compactionMicroUsd?: number;
70
+ /** The permission classifier's and a mod's model-call cost (micro-USD), accumulated by `recordSideCallUsage`. Folded
71
+ * into `costMicroUsd` like compaction, but it STAYS inside {@link costBreakdown.llmRootMicroUsd} (an "of which" line,
72
+ * not a partition member). Absent until a call is booked. Run-loop internal — the public figure is
73
+ * `costBreakdown.sideCallMicroUsd`. */
74
+ sideCallMicroUsd?: number;
70
75
  /**
71
76
  * A thin FINANCE TAXONOMY of the LLM-derived costs the engine actually
72
77
  * prices, decomposing the task's spend into report categories (no new persisted structure — derived from
@@ -92,6 +97,10 @@ export interface Stats {
92
97
  /** Within-task compaction LLM cost (micro-USD) = the running `compactionMicroUsd` accumulator (the
93
98
  * category Framing-4 missed). This IS part of `costMicroUsd`, so it is subtracted from `llmRoot`. */
94
99
  compactionMicroUsd: number;
100
+ /** Side model-call LLM cost (micro-USD) — the permission classifier's and mods' calls — present once one is booked.
101
+ * An "of which" line: it is part of `costMicroUsd` AND of `llmRootMicroUsd` (not subtracted from root), so the
102
+ * partition `llmRoot + compaction === costMicroUsd` keeps holding. */
103
+ sideCallMicroUsd?: number;
95
104
  };
96
105
  }
97
106
  /** The two cumulative budget ceilings a task can trip. Tokens outrank cost when both are
@@ -161,6 +161,7 @@ export function assembleResult(spec, sessionId, final, stats, flags) {
161
161
  nestedSubagentMicroUsd,
162
162
  memoryConsolidationMicroUsd: 0,
163
163
  compactionMicroUsd,
164
+ ...(stats.sideCallMicroUsd !== undefined ? { sideCallMicroUsd: stats.sideCallMicroUsd } : {}),
164
165
  };
165
166
  }
166
167
  const result = text;
@@ -171,8 +172,9 @@ export function assembleResult(spec, sessionId, final, stats, flags) {
171
172
  salvagedOutput = text.trim() || undefined;
172
173
  }
173
174
  const retryAfterMs = errorCode === "usage.window_exhausted" || errorCode === "memory.admission_required" ? flags.retryAfterMs : undefined;
174
- const { compactionMicroUsd: _internalCompaction, ...publicStats } = stats;
175
+ const { compactionMicroUsd: _internalCompaction, sideCallMicroUsd: _internalSideCall, ...publicStats } = stats;
175
176
  void _internalCompaction;
177
+ void _internalSideCall;
176
178
  if (flags.unpricedSpend)
177
179
  delete publicStats.costMicroUsd;
178
180
  const stampHaltedByUser = haltConsumed(flags.haltConsumption);
@@ -8,7 +8,8 @@
8
8
  * the decide that approved it — and the station through `AgentHarness.finalizeToolCall`, the loop's own finalize.
9
9
  */
10
10
  import type { DocumentContent, ImageContent, TextContent } from "../../internal/llm.js";
11
- import { type HookEnvCapabilities, type HookInvocationIdentity, type Hooks } from "../hooks.js";
11
+ import { type HookEnvCapabilities, type HookInvocationIdentity } from "../hooks.js";
12
+ import { type LegModBus } from "../mods/stations.js";
12
13
  import type { PermissionModeController } from "../mode-policy.js";
13
14
  import type { TaskSpec } from "../types.js";
14
15
  import type { CwdRef } from "../../tools/fs/fs-shared.js";
@@ -30,32 +31,29 @@ export type ToolResultStation = (e: ToolResultSeatEvent) => Promise<{
30
31
  content: Array<TextContent | ImageContent | DocumentContent>;
31
32
  } | undefined>;
32
33
  export interface ToolResultStationInput {
33
- /** borrowed-readonly — the resolved hook record: the two post seats and the failure seat, called through the record. */
34
- hooks: Hooks | undefined;
34
+ /** borrowed-readonly — the leg's mods bus: `classic.PostToolUse` / `classic.PostToolUseFailure` are raised on it, and a
35
+ * `classic.PreToolUse` handler arms the station too (its context is drained onto the result here). */
36
+ modBus: LegModBus;
35
37
  /** borrowed-mutable — the blocked/suspended call ids. Writer here: the one-shot `delete`. */
36
38
  blockedToolCalls: Set<string>;
37
- /** borrowed-readonly — the leg's delta seat: the post seats receive the call's wire name off its current roster. */
39
+ /** borrowed-readonly — the leg's delta seat: the post events carry the call's wire name off its current roster. */
38
40
  toolRosterDeltas: ToolRosterDeltaSeat;
39
41
  /** borrowed-mutable — PreToolUse `additionalContext` per call id. Writer here: the one-shot drain (`delete`). */
40
42
  preToolContexts: Map<string, string[]>;
41
- /** borrowed-readonly — the validated per-prepare hook seat bound. */
42
- hookTimeoutMs: number;
43
- /** borrowed-readonly — prepare's abort seat; `.signal` bounds the post seats and is the failure seat's interrupt fact. */
43
+ /** borrowed-readonly — prepare's abort seat; `.signal` is the post events' abort and the failure event's interrupt fact. */
44
44
  abortController: {
45
45
  readonly signal: AbortSignal;
46
46
  };
47
- /** borrowed-readonly — the REBOUND spec's `signal` (the failure seat's interrupt fact). */
47
+ /** borrowed-readonly — the REBOUND spec's `signal` (the failure event's interrupt fact). */
48
48
  spec: Pick<TaskSpec, "signal">;
49
- /** borrowed-readonly — the hand's live tracked cwd, or undefined; `current` is read per post seat. */
49
+ /** borrowed-readonly — the hand's live tracked cwd, or undefined; `current` is read per post event. */
50
50
  handsCwdRef: CwdRef | undefined;
51
- /** borrowed-readonly — the env face the post seats' contexts carry, or undefined. */
51
+ /** borrowed-readonly — the env face the post events carry, or undefined. */
52
52
  hookEnvFace: HookEnvCapabilities | undefined;
53
- /** borrowed-readonly — the leg's identity envelope every HookToolContext carries. */
53
+ /** borrowed-readonly — the leg's identity envelope every post event carries. */
54
54
  hookIdentity: HookInvocationIdentity;
55
- /** borrowed-readonly — the leg's live permission-mode seat (each context reads `observed`). */
55
+ /** borrowed-readonly — the leg's live permission-mode seat (each event reads `observed`). */
56
56
  permissionMode: PermissionModeController;
57
- /** borrowed-readonly — where an expired post seat is reported (the leg's own hook-crash lane). */
58
- notifyOwnHookCrash: (err: unknown) => void;
59
57
  /** borrowed-readonly — the leg's reminder provenance mark (every hook context line carries it). */
60
58
  reminderMark: string;
61
59
  /** borrowed-mutable — the leg's settlement seam. Writer here: a carrier whose output a host hook rewrote (`noteHostRewrite`). */
@@ -69,11 +67,11 @@ export declare function createToolResultStation(input: ToolResultStationInput):
69
67
  export type ApprovedCallScreen = NonNullable<Prepared["approvedCallScreen"]>;
70
68
  export type ApprovedCallVerdict = Awaited<ReturnType<ApprovedCallScreen>>;
71
69
  export interface ApprovedCallScreenInput {
72
- /** borrowed-readonly — the face the gate screens with (the observational wrapper when declared; the leg's mode on every context). */
73
- preToolUse: Hooks["preToolUse"] | undefined;
74
- /** borrowed-readonly — the validated per-prepare hook seat bound. */
75
- hookTimeoutMs: number;
76
- /** borrowed-readonly — prepare's abort seat (the screening seat is abort-ended on it). */
70
+ /** borrowed-readonly — the leg's mods bus (the re-screen raises `classic.PreToolUse` on it, as the gate does). */
71
+ modBus: LegModBus;
72
+ /** borrowed-readonly — the leg's live permission-mode seat (each screening e reads `observed`). */
73
+ permissionMode: PermissionModeController;
74
+ /** borrowed-readonly — prepare's abort seat (the screening is abort-ended on it). */
77
75
  abortController: {
78
76
  readonly signal: AbortSignal;
79
77
  };
@@ -83,18 +81,16 @@ export interface ApprovedCallScreenInput {
83
81
  hookEnvFace: HookEnvCapabilities | undefined;
84
82
  /** borrowed-readonly — the leg's identity envelope. */
85
83
  hookIdentity: HookInvocationIdentity;
86
- /** borrowed-readonly — the own hook-crash reporter (a crashing or timed-out screening face is reported through it). */
87
- notifyOwnHookCrash: (err: unknown) => void;
88
84
  /** borrowed-mutable — PreToolUse `additionalContext` per call id. Writer here: `admit`'s stash (the station drains it). */
89
85
  preToolContexts: Map<string, string[]>;
90
86
  }
91
87
  /**
92
- * The approved call's PreToolUse screening — the gate's own seat, its answer FOLDED UNDER THE DECIDE that approved the
93
- * call (the decide is the upper bound; the screen can only narrow): a deny, a crash, a silence or a refused answer
94
- * refuses the call in the live gate's own sentences; an ask is the question the decide already answered — unless it
95
- * demands a person and the decide was the deployment's policy (the one predicate every resume station holds a decide
96
- * against); a rewrite is what executes when the decide carried none of its own (the person's bytes are the upper bound);
97
- * context rides the result. Undefined when no face is wired.
88
+ * The approved call's PreToolUse screening — the gate's own screening, its answer FOLDED UNDER THE DECIDE that approved
89
+ * the call (the decide is the upper bound; the screen can only narrow): a deny, a failed or cancelled screening, or a
90
+ * refused answer refuses the call in the live gate's own sentences; an ask is the question the decide already answered —
91
+ * unless it demands a person and the decide was the deployment's policy (the one predicate every resume station holds a
92
+ * decide against); a rewrite is what executes when the decide carried none of its own (the person's bytes are the upper
93
+ * bound); context rides the result. Undefined when no handler hangs on `classic.PreToolUse`.
98
94
  */
99
95
  export declare function createApprovedCallScreen(input: ApprovedCallScreenInput): ApprovedCallScreen | undefined;
100
96
  /**
@@ -1,14 +1,28 @@
1
- import { createPreToolUseScreening, formatHookFeedback, hookSeatExpiredError, runHookSeat } from "../hooks.js";
2
- import { isEngineRefusal } from "../tool-policy.js";
1
+ import { createPreToolUseScreening, formatHookFeedback } from "../hooks.js";
2
+ import { classicEventBase, dispatchClassic, stringMembersAnswer, stringMembersOf } from "../mods/stations.js";
3
3
  import { policyCannotAnswer } from "../real-approval.js";
4
- import { traceHookCrash } from "../gate-crash-trace.js";
5
- import { createSafeNotifier } from "../safe-notify.js";
6
4
  import { rosterToolName } from "../tool-roster.js";
7
5
  import { wireOf } from "../tool-name-readings.js";
8
6
  import { noteHostRewrite } from "../frame-settlement.js";
7
+ function postToolUseAnswer(answer) {
8
+ const strings = stringMembersAnswer("classic.PostToolUse", ["additionalContext"])(answer);
9
+ if (strings !== undefined || typeof answer !== "object" || answer === null)
10
+ return strings;
11
+ const out = Reflect.get(answer, "updatedOutput");
12
+ return out === undefined || Array.isArray(out) ? undefined : "answered a non-array \"updatedOutput\"; it replaces the content array";
13
+ }
14
+ function updatedOutputOf(answer) {
15
+ if (typeof answer !== "object" || answer === null)
16
+ return undefined;
17
+ const out = Reflect.get(answer, "updatedOutput");
18
+ return Array.isArray(out) ? out.filter(isContentBlock) : undefined;
19
+ }
20
+ function isContentBlock(c) {
21
+ return typeof c === "object" && c !== null && typeof Reflect.get(c, "type") === "string";
22
+ }
9
23
  export function createToolResultStation(input) {
10
- const { hooks, blockedToolCalls, toolRosterDeltas, preToolContexts, hookTimeoutMs, abortController, spec, handsCwdRef, hookEnvFace, hookIdentity, permissionMode, notifyOwnHookCrash, reminderMark, frameSettlement } = input;
11
- const toolResultStationArmed = Boolean(hooks?.postToolUse || hooks?.preToolUse || hooks?.postToolUseFailure);
24
+ const { modBus, blockedToolCalls, toolRosterDeltas, preToolContexts, abortController, spec, handsCwdRef, hookEnvFace, hookIdentity, permissionMode, reminderMark, frameSettlement } = input;
25
+ const toolResultStationArmed = modBus.hasHandlers("classic.PostToolUse") || modBus.hasHandlers("classic.PreToolUse") || modBus.hasHandlers("classic.PostToolUseFailure");
12
26
  if (toolResultStationArmed) {
13
27
  return async (e) => {
14
28
  if (blockedToolCalls.delete(e.toolCallId)) {
@@ -17,16 +31,23 @@ export function createToolResultStation(input) {
17
31
  let content = e.content;
18
32
  let changed = false;
19
33
  const post = { toolName: rosterToolName(toolRosterDeltas.current, e.toolName) };
34
+ const callFacts = (tool) => ({
35
+ ...classicEventBase(hookIdentity, permissionMode.observed),
36
+ tool,
37
+ tool_use_id: e.toolCallId,
38
+ input: e.input,
39
+ ...(handsCwdRef?.current !== undefined ? { cwd: handsCwdRef.current } : {}),
40
+ ...(hookEnvFace !== undefined ? { env: hookEnvFace } : {}),
41
+ });
20
42
  if (e.isError) {
21
- if (hooks?.postToolUseFailure) {
43
+ if (modBus.hasHandlers("classic.PostToolUseFailure")) {
22
44
  let clonedDetails = e.details;
23
45
  try {
24
46
  clonedDetails = structuredClone(e.details);
25
47
  }
26
48
  catch {
27
49
  }
28
- const failedName = wireOf("hook.postToolUseFailure", post);
29
- const failureSeat = await runHookSeat("postToolUseFailure", { timeoutMs: hookTimeoutMs, signal: abortController.signal }, (sig) => hooks.postToolUseFailure(failedName, e.input, {
50
+ const failure = {
30
51
  error: e.content
31
52
  .filter((c) => c.type === "text")
32
53
  .map((c) => c.text)
@@ -34,30 +55,26 @@ export function createToolResultStation(input) {
34
55
  isInterrupt: abortController.signal.aborted || spec.signal?.aborted === true,
35
56
  content: e.content.map((c) => ({ ...c })),
36
57
  details: clonedDetails,
37
- }, { toolCallId: e.toolCallId, toolName: failedName, signal: sig, ...(handsCwdRef?.current !== undefined ? { cwd: handsCwdRef.current } : {}), ...(hookEnvFace !== undefined ? { env: hookEnvFace } : {}), identity: hookIdentity, permissionMode: permissionMode.observed }));
38
- if (failureSeat.expired) {
39
- notifyOwnHookCrash(hookSeatExpiredError("postToolUseFailure", hookTimeoutMs, failureSeat.cause, "the observation was abandoned and its additionalContext dropped; the failure result itself is unchanged"));
40
- }
41
- const patch = failureSeat.expired ? undefined : failureSeat.value;
58
+ };
59
+ const outcome = await dispatchClassic(modBus, "classic.PostToolUseFailure", { ...callFacts(wireOf("hook.postToolUseFailure", post)), failure }, { signal: abortController.signal, checkAnswer: stringMembersAnswer("classic.PostToolUseFailure", ["additionalContext"]) }).catch(() => undefined);
60
+ const patch = outcome?.kind === "answered" ? stringMembersOf(outcome.answer, ["additionalContext"]) : undefined;
42
61
  if (patch?.additionalContext) {
43
62
  content = [...content, { type: "text", text: formatHookFeedback(patch.additionalContext, reminderMark) }];
44
63
  changed = true;
45
64
  }
46
65
  }
47
66
  }
48
- else if (hooks?.postToolUse) {
49
- const ranName = wireOf("hook.postToolUse", post);
50
- const successSeat = await runHookSeat("postToolUse", { timeoutMs: hookTimeoutMs, signal: abortController.signal }, (sig) => hooks.postToolUse(ranName, e.input, { content: e.content, details: e.details, isError: e.isError }, { toolCallId: e.toolCallId, toolName: ranName, signal: sig, ...(handsCwdRef?.current !== undefined ? { cwd: handsCwdRef.current } : {}), ...(hookEnvFace !== undefined ? { env: hookEnvFace } : {}), identity: hookIdentity, permissionMode: permissionMode.observed }));
51
- if (successSeat.expired) {
52
- notifyOwnHookCrash(hookSeatExpiredError("postToolUse", hookTimeoutMs, successSeat.cause, "the seat was abandoned; the tool result is delivered to the model UNMODIFIED (no updatedOutput, no additionalContext)"));
53
- }
54
- const patch = successSeat.expired ? undefined : successSeat.value;
55
- if (patch?.updatedOutput) {
56
- content = patch.updatedOutput;
67
+ else if (modBus.hasHandlers("classic.PostToolUse")) {
68
+ const outcome = await dispatchClassic(modBus, "classic.PostToolUse", { ...callFacts(wireOf("hook.postToolUse", post)), output: { content: e.content, details: e.details, isError: e.isError } }, { signal: abortController.signal, checkAnswer: postToolUseAnswer }).catch(() => undefined);
69
+ const answer = outcome?.kind === "answered" ? outcome.answer : undefined;
70
+ const updatedOutput = updatedOutputOf(answer);
71
+ const patch = stringMembersOf(answer, ["additionalContext"]);
72
+ if (updatedOutput) {
73
+ content = updatedOutput;
57
74
  changed = true;
58
75
  noteHostRewrite(frameSettlement, e.toolCallId);
59
76
  }
60
- if (patch?.additionalContext) {
77
+ if (patch.additionalContext) {
61
78
  content = [...content, { type: "text", text: formatHookFeedback(patch.additionalContext, reminderMark) }];
62
79
  changed = true;
63
80
  }
@@ -74,27 +91,26 @@ export function createToolResultStation(input) {
74
91
  return undefined;
75
92
  }
76
93
  export function createApprovedCallScreen(input) {
77
- const { preToolUse, hookTimeoutMs, abortController, handsCwdRef, hookEnvFace, hookIdentity, notifyOwnHookCrash, preToolContexts } = input;
78
- if (preToolUse === undefined)
94
+ const { modBus, permissionMode, abortController, handsCwdRef, hookEnvFace, hookIdentity, preToolContexts } = input;
95
+ if (!modBus.hasHandlers("classic.PreToolUse"))
79
96
  return undefined;
80
97
  return async ({ toolCallId, toolName, args, decidedBy }) => {
81
- const notifier = createSafeNotifier();
82
- const seatInput = { event: { toolCallId, toolName, input: args }, ...(handsCwdRef !== undefined ? { trackedCwd: () => handsCwdRef.current } : {}), ...(hookEnvFace !== undefined ? { hookEnv: hookEnvFace } : {}), identity: hookIdentity, onHookError: notifyOwnHookCrash, abortSignal: abortController.signal };
83
- const screening = createPreToolUseScreening(preToolUse, seatInput, hookTimeoutMs, notifier);
98
+ const screening = createPreToolUseScreening({
99
+ event: { toolCallId, toolName, input: {} },
100
+ modBus,
101
+ observedPermissionMode: () => permissionMode.observed,
102
+ ...(handsCwdRef !== undefined ? { trackedCwd: () => handsCwdRef.current } : {}),
103
+ ...(hookEnvFace !== undefined ? { hookEnv: hookEnvFace } : {}),
104
+ identity: hookIdentity,
105
+ abortSignal: abortController.signal,
106
+ });
107
+ if (screening === undefined)
108
+ return { args, admit: () => undefined };
84
109
  const subject = `this call to "${toolName}"`;
85
- let r;
86
- try {
87
- const seat = await screening.screen(args);
88
- if (seat.expired)
89
- return { refused: await screening.unansweredReason(subject, seat.cause) };
90
- r = screening.screened(seat.value);
91
- }
92
- catch (err) {
93
- traceHookCrash(seatInput, err, notifier);
94
- return { refused: screening.crashReason(subject, err) };
95
- }
96
- if (r !== undefined && isEngineRefusal(r))
97
- return { refused: screening.refusedReason(r) };
110
+ const screened = await screening.screen(args, subject);
111
+ if (screened.kind === "refused")
112
+ return { refused: screened.reason };
113
+ const r = screened.answer;
98
114
  if (r?.action === "deny")
99
115
  return { refused: screening.deniedReason(r) };
100
116
  if (r !== undefined && policyCannotAnswer(r, decidedBy))
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The run's ONE caller-stop gate: tripped by every channel through which the run's CALLER asks it to stop — the
3
+ * `halt()`, `interrupt()` and `destroy()` verbs (`stop()`) and the caller's own `TaskSpec.signal` (composed into
4
+ * `signal` at the mint) — at any moment until the run publishes its result, the loop's end included. It answers one
5
+ * question, "did the caller ask this run to stop?", and every compaction pass of the run reads it the same way: a
6
+ * tripped gate admits no pass, and a pass in flight carries it both as an abort and as its withdrawal signal, so a
7
+ * stop landing mid-pass cuts the summary call and the pass reports a cancel. It is not an attribution: who OWNS the
8
+ * run's ending stays on the loop latch's first-writer seats, and an engine stop (a limit, an output retry cap, a
9
+ * gate) never trips it.
10
+ *
11
+ * Minted once per run beside the loop latch and carried on it (`LiveHandle.loop.callerStop`), so the verbs and the
12
+ * run body hold the same object.
13
+ */
14
+ export interface CallerStopGate {
15
+ /** The verbs' write face; idempotent. */
16
+ stop(): void;
17
+ /** The read face: aborted once any caller channel fired. */
18
+ readonly signal: AbortSignal;
19
+ }
20
+ /**
21
+ * The caller's own signal is COMPOSED into the read face, not listened to: there is nothing to release, so the gate
22
+ * keeps answering after the leg dropped its own listener on that signal — which is exactly when the end-of-task
23
+ * pass runs.
24
+ */
25
+ export declare function mintCallerStopGate(callerSignal: AbortSignal | undefined): CallerStopGate;