@sema-agent/core 7.52.0 → 7.54.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 (357) hide show
  1. package/CHANGELOG.md +470 -0
  2. package/LICENSE +3 -1
  3. package/README.md +3 -1
  4. package/dist/agents/cross-session-envelope.d.ts +8 -0
  5. package/dist/agents/cross-session-envelope.js +6 -0
  6. package/dist/agents/cross-session-judge.d.ts +21 -1
  7. package/dist/agents/cross-session-judge.js +8 -0
  8. package/dist/agents/cross-session-ref.d.ts +5 -0
  9. package/dist/agents/cross-session-ref.js +1 -0
  10. package/dist/agents/org-delivery-gate.d.ts +122 -0
  11. package/dist/agents/org-delivery-gate.js +69 -0
  12. package/dist/agents/peer-held-queue.d.ts +9 -4
  13. package/dist/agents/peer-held-queue.js +6 -5
  14. package/dist/agents/peer-session-drain.d.ts +35 -6
  15. package/dist/agents/peer-session-drain.js +271 -182
  16. package/dist/agents/read-inbox-tool.d.ts +7 -0
  17. package/dist/agents/read-inbox-tool.js +5 -1
  18. package/dist/agents/send-message-tool.js +3 -4
  19. package/dist/agents/subagent.d.ts +6 -5
  20. package/dist/agents/subagent.js +117 -83
  21. package/dist/agents/tool-filter.d.ts +25 -4
  22. package/dist/agents/tool-filter.js +13 -3
  23. package/dist/brain/anthropic.d.ts +6 -1
  24. package/dist/brain/anthropic.js +4 -4
  25. package/dist/brain/model-presets.js +2 -1
  26. package/dist/brain/route-adjudicator.d.ts +6 -0
  27. package/dist/brain/routing.d.ts +24 -1
  28. package/dist/brain/routing.js +54 -19
  29. package/dist/brain/timeout.js +5 -4
  30. package/dist/core/a2a.d.ts +5 -2
  31. package/dist/core/a2a.js +33 -14
  32. package/dist/core/allow-entry.d.ts +3 -1
  33. package/dist/core/allow-entry.js +3 -2
  34. package/dist/core/approval-object.d.ts +87 -0
  35. package/dist/core/approval-object.js +85 -0
  36. package/dist/core/arg-summary.d.ts +3 -2
  37. package/dist/core/arg-summary.js +17 -11
  38. package/dist/core/ask-origin.d.ts +43 -27
  39. package/dist/core/ask-origin.js +20 -11
  40. package/dist/core/ask-question.d.ts +0 -1
  41. package/dist/core/ask-question.js +4 -67
  42. package/dist/core/ask-unresolvable-notice.d.ts +3 -2
  43. package/dist/core/auto-compaction.d.ts +106 -50
  44. package/dist/core/auto-compaction.js +69 -53
  45. package/dist/core/auto-mode-prompt.d.ts +4 -2
  46. package/dist/core/auto-mode-prompt.js +4 -3
  47. package/dist/core/canonical-json.d.ts +69 -0
  48. package/dist/core/canonical-json.js +130 -8
  49. package/dist/core/checkpoint-requirements.d.ts +13 -7
  50. package/dist/core/checkpoint-requirements.js +4 -1
  51. package/dist/core/checkpoint-store.d.ts +60 -36
  52. package/dist/core/checkpoint-store.js +7 -6
  53. package/dist/core/child-clamp-seats.d.ts +45 -6
  54. package/dist/core/child-clamp-seats.js +56 -4
  55. package/dist/core/compliance.js +3 -1
  56. package/dist/core/consolidate-scope.d.ts +1 -1
  57. package/dist/core/cross-boundary-taint.d.ts +213 -0
  58. package/dist/core/cross-boundary-taint.js +196 -0
  59. package/dist/core/decision-receipt.d.ts +44 -1
  60. package/dist/core/decision-receipt.js +16 -0
  61. package/dist/core/effective-path-target.d.ts +28 -6
  62. package/dist/core/effective-path-target.js +28 -2
  63. package/dist/core/engine-notice.d.ts +47 -4
  64. package/dist/core/engine-notice.js +17 -1
  65. package/dist/core/engine-storage-backend.d.ts +73 -0
  66. package/dist/core/engine-storage-backend.js +1 -0
  67. package/dist/core/file-history-store.d.ts +6 -2
  68. package/dist/core/file-history-store.js +1 -0
  69. package/dist/core/gate-fold.js +13 -4
  70. package/dist/core/gate-lanes.js +41 -34
  71. package/dist/core/gate-outcome.d.ts +18 -9
  72. package/dist/core/governance-codes.d.ts +9 -2
  73. package/dist/core/governance-codes.js +9 -0
  74. package/dist/core/hands-band-screen.d.ts +7 -0
  75. package/dist/core/hands-band-screen.js +32 -0
  76. package/dist/core/hooks.d.ts +21 -19
  77. package/dist/core/hooks.js +6 -5
  78. package/dist/core/locked-config.d.ts +110 -31
  79. package/dist/core/locked-config.js +155 -42
  80. package/dist/core/lsp.d.ts +1 -1
  81. package/dist/core/mcp-probe.js +1 -1
  82. package/dist/core/mcp-server-spec.d.ts +152 -17
  83. package/dist/core/mcp-server-spec.js +223 -40
  84. package/dist/core/mcp.d.ts +21 -14
  85. package/dist/core/mcp.js +59 -54
  86. package/dist/core/memory-engine/engine.d.ts +14 -19
  87. package/dist/core/memory-engine/engine.js +9 -6
  88. package/dist/core/memory-engine/export-bundle.d.ts +1 -1
  89. package/dist/core/memory-engine/export-bundle.js +1 -1
  90. package/dist/core/memory-engine/file-backend.d.ts +2 -6
  91. package/dist/core/memory-engine/file-backend.js +1 -12
  92. package/dist/core/memory.d.ts +3 -3
  93. package/dist/core/mode-policy.d.ts +16 -26
  94. package/dist/core/mode-policy.js +5 -18
  95. package/dist/core/mods/kernel/dispatch.js +13 -15
  96. package/dist/core/mods/kernel/events.d.ts +9 -6
  97. package/dist/core/mods/kernel/events.js +2 -2
  98. package/dist/core/mods/kernel/receive.d.ts +41 -11
  99. package/dist/core/mods/kernel/receive.js +124 -54
  100. package/dist/core/mods/kernel/site-rules.d.ts +80 -15
  101. package/dist/core/mods/kernel/site-rules.js +232 -40
  102. package/dist/core/mods/stations.d.ts +0 -6
  103. package/dist/core/mods/stations.js +0 -7
  104. package/dist/core/mounted-mcp.d.ts +57 -0
  105. package/dist/core/mounted-mcp.js +71 -2
  106. package/dist/core/own-property-receipt.d.ts +13 -0
  107. package/dist/core/own-property-receipt.js +3 -1
  108. package/dist/core/parent-spec-seat.d.ts +12 -15
  109. package/dist/core/parent-spec-seat.js +14 -6
  110. package/dist/core/pause-registry.d.ts +35 -1
  111. package/dist/core/pause-registry.js +10 -0
  112. package/dist/core/permission-rule-consent.d.ts +18 -5
  113. package/dist/core/permission-rule-consent.js +13 -8
  114. package/dist/core/permission-rule-model.d.ts +87 -15
  115. package/dist/core/permission-rule-model.js +87 -8
  116. package/dist/core/permission-rule-org.d.ts +200 -33
  117. package/dist/core/permission-rule-org.js +217 -91
  118. package/dist/core/permission-rule-session.js +2 -2
  119. package/dist/core/permission-rule-store.d.ts +8 -0
  120. package/dist/core/permission-rule-store.js +1 -0
  121. package/dist/core/permission-rule-sync.js +3 -2
  122. package/dist/core/permission-rules.d.ts +7 -1
  123. package/dist/core/permission-rules.js +37 -8
  124. package/dist/core/read-only-shell.d.ts +1 -1
  125. package/dist/core/read-only-shell.js +30 -9
  126. package/dist/core/remote-env.d.ts +41 -1
  127. package/dist/core/remote-env.js +18 -0
  128. package/dist/core/resume-startup-cause.d.ts +18 -0
  129. package/dist/core/resume-startup-cause.js +12 -0
  130. package/dist/core/retention.js +7 -2
  131. package/dist/core/retired-keys.d.ts +8 -2
  132. package/dist/core/retired-keys.js +12 -1
  133. package/dist/core/roles.js +60 -10
  134. package/dist/core/rule-lane-reads.js +1 -1
  135. package/dist/core/runner/approval-feedback.d.ts +46 -0
  136. package/dist/core/runner/approval-feedback.js +41 -0
  137. package/dist/core/runner/compaction-call-options.d.ts +3 -3
  138. package/dist/core/runner/compaction-call-options.js +2 -2
  139. package/dist/core/runner/contracts.d.ts +34 -41
  140. package/dist/core/runner/cross-boundary-lane.d.ts +87 -0
  141. package/dist/core/runner/cross-boundary-lane.js +190 -0
  142. package/dist/core/runner/decide-continuation.d.ts +4 -4
  143. package/dist/core/runner/decide-continuation.js +3 -1
  144. package/dist/core/runner/gate-exit.d.ts +32 -12
  145. package/dist/core/runner/gate-exit.js +77 -34
  146. package/dist/core/runner/inherited-ask-grants.js +2 -2
  147. package/dist/core/runner/mcp-redial.d.ts +52 -10
  148. package/dist/core/runner/mcp-redial.js +38 -9
  149. package/dist/core/runner/permission-rule-lanes.d.ts +5 -2
  150. package/dist/core/runner/permission-rule-lanes.js +22 -10
  151. package/dist/core/runner/person-path-rows.d.ts +5 -3
  152. package/dist/core/runner/person-path-rows.js +2 -2
  153. package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -4
  154. package/dist/core/runner/prepare-acquire-reconcile.js +3 -3
  155. package/dist/core/runner/prepare-ask-lane.js +3 -3
  156. package/dist/core/runner/prepare-caps-and-workflow.d.ts +6 -5
  157. package/dist/core/runner/prepare-caps-and-workflow.js +3 -3
  158. package/dist/core/runner/prepare-config-doors.d.ts +58 -15
  159. package/dist/core/runner/prepare-config-doors.js +167 -146
  160. package/dist/core/runner/prepare-context-lane.js +6 -3
  161. package/dist/core/runner/prepare-defer-classify.js +4 -7
  162. package/dist/core/runner/prepare-delegation-surface.d.ts +5 -4
  163. package/dist/core/runner/prepare-delegation-surface.js +8 -7
  164. package/dist/core/runner/prepare-execution-env.d.ts +1 -2
  165. package/dist/core/runner/prepare-execution-env.js +2 -1
  166. package/dist/core/runner/prepare-gate-stations.d.ts +2 -0
  167. package/dist/core/runner/prepare-gate-stations.js +4 -3
  168. package/dist/core/runner/prepare-hands-readface.d.ts +3 -3
  169. package/dist/core/runner/prepare-hands-readface.js +3 -2
  170. package/dist/core/runner/prepare-inherited-gate.d.ts +2 -0
  171. package/dist/core/runner/prepare-inherited-gate.js +3 -2
  172. package/dist/core/runner/prepare-listings.d.ts +1 -1
  173. package/dist/core/runner/prepare-listings.js +4 -2
  174. package/dist/core/runner/prepare-memory-engine-session.d.ts +0 -6
  175. package/dist/core/runner/prepare-memory-engine-session.js +19 -6
  176. package/dist/core/runner/prepare-memory.d.ts +3 -2
  177. package/dist/core/runner/prepare-memory.js +6 -2
  178. package/dist/core/runner/prepare-offload-wrappers.d.ts +4 -4
  179. package/dist/core/runner/prepare-offload-wrappers.js +2 -1
  180. package/dist/core/runner/prepare-park-ask.d.ts +1 -1
  181. package/dist/core/runner/prepare-park-ask.js +9 -3
  182. package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
  183. package/dist/core/runner/prepare-policy-chain.js +14 -19
  184. package/dist/core/runner/prepare-project-context.d.ts +1 -1
  185. package/dist/core/runner/prepare-project-context.js +6 -4
  186. package/dist/core/runner/prepare-prompt-assembly.d.ts +1 -1
  187. package/dist/core/runner/prepare-prompt-assembly.js +20 -16
  188. package/dist/core/runner/prepare-prompt-inputs.d.ts +12 -6
  189. package/dist/core/runner/prepare-prompt-inputs.js +6 -3
  190. package/dist/core/runner/prepare-protocol-tools.d.ts +7 -5
  191. package/dist/core/runner/prepare-protocol-tools.js +19 -12
  192. package/dist/core/runner/prepare-question-face.d.ts +4 -2
  193. package/dist/core/runner/prepare-question-face.js +4 -3
  194. package/dist/core/runner/prepare-safety-scan.d.ts +7 -2
  195. package/dist/core/runner/prepare-safety-scan.js +34 -27
  196. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -2
  197. package/dist/core/runner/prepare-suspend-saga.js +6 -2
  198. package/dist/core/runner/prepare-task.js +22 -19
  199. package/dist/core/runner/prepare-turn-wiring.d.ts +10 -5
  200. package/dist/core/runner/prepare-turn-wiring.js +14 -49
  201. package/dist/core/runner/prepare-wiring-manifest.d.ts +10 -5
  202. package/dist/core/runner/prepare-wiring-manifest.js +9 -6
  203. package/dist/core/runner/prepare-workspace-restore.js +2 -2
  204. package/dist/core/runner/resume-admission.d.ts +4 -1
  205. package/dist/core/runner/resume-admission.js +16 -14
  206. package/dist/core/runner/resume-apply.js +4 -4
  207. package/dist/core/runner/resume-internals-and-config.d.ts +3 -3
  208. package/dist/core/runner/resume-internals-and-config.js +3 -8
  209. package/dist/core/runner/resume-policy-outcome.d.ts +2 -2
  210. package/dist/core/runner/resume-policy-outcome.js +18 -15
  211. package/dist/core/runner/resume-preflight.js +2 -2
  212. package/dist/core/runner/resume-review-outcome.js +3 -3
  213. package/dist/core/runner/retired-runner-deps.d.ts +5 -6
  214. package/dist/core/runner/retired-runner-deps.js +1 -4
  215. package/dist/core/runner/run-leg.js +97 -43
  216. package/dist/core/runner/run-recovery-lanes.js +5 -3
  217. package/dist/core/runner/run-settle-and-teardown.js +2 -0
  218. package/dist/core/runner/run-terminal-adoption.js +21 -9
  219. package/dist/core/runner/run-turn-boundary.js +9 -3
  220. package/dist/core/runner/runtask.js +1 -1
  221. package/dist/core/runner/session-file-state-replay.d.ts +5 -2
  222. package/dist/core/runner/session-file-state-replay.js +3 -2
  223. package/dist/core/runner/skills-seat.d.ts +15 -0
  224. package/dist/core/runner/skills-seat.js +57 -0
  225. package/dist/core/runner/stream-steer-verb.js +2 -2
  226. package/dist/core/runner/sub-agent-deny-lists.d.ts +13 -11
  227. package/dist/core/runner/sub-agent-deny-lists.js +7 -5
  228. package/dist/core/runner/synthetic-tools.d.ts +5 -2
  229. package/dist/core/runner/synthetic-tools.js +2 -12
  230. package/dist/core/runner/tool-face-overlay.d.ts +24 -6
  231. package/dist/core/runner/tool-face-overlay.js +24 -15
  232. package/dist/core/runner-deps.d.ts +37 -22
  233. package/dist/core/session-policy-store.d.ts +19 -0
  234. package/dist/core/session-policy-store.js +22 -2
  235. package/dist/core/session-store.d.ts +35 -16
  236. package/dist/core/session-store.js +20 -12
  237. package/dist/core/{shell-lexer.d.ts → shell-run-candidates.d.ts} +36 -12
  238. package/dist/core/{shell-lexer.js → shell-run-candidates.js} +145 -225
  239. package/dist/core/shell-wrapper-table.d.ts +5 -3
  240. package/dist/core/shell-wrapper-table.js +1 -1
  241. package/dist/core/store-contracts/checkpoint-store-contract.js +2 -2
  242. package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
  243. package/dist/core/store-contracts/session-store-contract.d.ts +49 -0
  244. package/dist/core/store-contracts/session-store-contract.js +639 -0
  245. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +12 -0
  246. package/dist/core/store-contracts/session-store-incarnation-contract.js +5 -2
  247. package/dist/core/task-event.d.ts +44 -6
  248. package/dist/core/task-notification.js +2 -2
  249. package/dist/core/task-registry-agent.js +1 -0
  250. package/dist/core/task-registry-shared.d.ts +5 -0
  251. package/dist/core/task-registry.d.ts +7 -0
  252. package/dist/core/task-registry.js +17 -0
  253. package/dist/core/task-result.d.ts +1 -1
  254. package/dist/core/task-spec.d.ts +7 -7
  255. package/dist/core/tighten-task-spec.d.ts +6 -4
  256. package/dist/core/tighten-task-spec.js +2 -2
  257. package/dist/core/tool-catalog-entries.d.ts +1 -1
  258. package/dist/core/tool-catalog-entries.js +52 -52
  259. package/dist/core/tool-face-reader.d.ts +49 -0
  260. package/dist/core/tool-face-reader.js +94 -0
  261. package/dist/core/tool-face.d.ts +17 -8
  262. package/dist/core/tool-face.js +1 -0
  263. package/dist/core/tool-policy.d.ts +67 -23
  264. package/dist/core/tool-policy.js +72 -60
  265. package/dist/core/tool-roster.d.ts +46 -28
  266. package/dist/core/tool-roster.js +91 -14
  267. package/dist/core/tool-spec-members.js +2 -2
  268. package/dist/core/tool-spec.d.ts +20 -4
  269. package/dist/core/tools.js +2 -0
  270. package/dist/core/trace.d.ts +24 -2
  271. package/dist/core/types.d.ts +3 -3
  272. package/dist/core/types.js +1 -1
  273. package/dist/core/untrusted-text.d.ts +23 -0
  274. package/dist/core/untrusted-text.js +10 -10
  275. package/dist/core/user-attachment.d.ts +56 -2
  276. package/dist/core/user-attachment.js +139 -56
  277. package/dist/core/wiring-manifest.d.ts +4 -2
  278. package/dist/engine/compaction/compaction.d.ts +2 -2
  279. package/dist/engine/compaction/utils.d.ts +2 -2
  280. package/dist/engine/harness/agent-harness.js +2 -1
  281. package/dist/engine/harness/types.d.ts +10 -4
  282. package/dist/engine/llm/types.d.ts +7 -2
  283. package/dist/engine/llm/types.js +2 -1
  284. package/dist/engine/loop/agent-loop.d.ts +12 -1
  285. package/dist/engine/loop/agent-loop.js +17 -5
  286. package/dist/engine/loop/types.d.ts +7 -1
  287. package/dist/engine/session/repo-utils.d.ts +5 -0
  288. package/dist/engine/session/repo-utils.js +9 -0
  289. package/dist/engine/session/storage-base.js +2 -2
  290. package/dist/index.d.ts +37 -17
  291. package/dist/index.js +31 -14
  292. package/dist/internal/harness.d.ts +1 -0
  293. package/dist/internal/harness.js +1 -0
  294. package/dist/internal/llm.d.ts +1 -1
  295. package/dist/internal/llm.js +1 -1
  296. package/dist/orchestration/goal.d.ts +24 -1
  297. package/dist/orchestration/goal.js +3 -2
  298. package/dist/orchestration/run-workflow-tool.d.ts +3 -0
  299. package/dist/orchestration/run-workflow-tool.js +1 -0
  300. package/dist/orchestration/workflow-governance.d.ts +1 -1
  301. package/dist/orchestration/workflow.d.ts +3 -0
  302. package/dist/orchestration/workflow.js +2 -1
  303. package/dist/prompt-assembly/artifact-store.d.ts +44 -9
  304. package/dist/prompt-assembly/artifact-store.js +38 -12
  305. package/dist/prompt-assembly/artifact.d.ts +12 -11
  306. package/dist/prompt-assembly/artifact.js +52 -21
  307. package/dist/prompt-assembly/assemble.d.ts +2 -0
  308. package/dist/prompt-assembly/assemble.js +2 -1
  309. package/dist/prompt-assembly/catalog/index.js +2 -1
  310. package/dist/prompt-assembly/catalog/memory.d.ts +13 -0
  311. package/dist/prompt-assembly/catalog/memory.js +6 -0
  312. package/dist/prompt-assembly/catalog/schema.d.ts +19 -2
  313. package/dist/prompt-assembly/catalog/schema.js +3 -0
  314. package/dist/prompt-assembly/composer.d.ts +2 -0
  315. package/dist/prompt-assembly/composer.js +1 -1
  316. package/dist/prompt-assembly/overlay.d.ts +21 -11
  317. package/dist/prompt-assembly/overlay.js +57 -19
  318. package/dist/prompt-assembly/select.d.ts +21 -6
  319. package/dist/prompt-assembly/select.js +41 -4
  320. package/dist/prompts/default.d.ts +1 -12
  321. package/dist/prompts/default.js +0 -3
  322. package/dist/shell/lex.d.ts +87 -8
  323. package/dist/shell/lex.js +283 -49
  324. package/dist/stores/file/index.d.ts +8 -6
  325. package/dist/stores/file/permission-rule-store.d.ts +1 -1
  326. package/dist/stores/file/permission-rule-store.js +2 -1
  327. package/dist/tools/artifact/artifact-tool.js +14 -3
  328. package/dist/tools/fs/bash-program-position.d.ts +3 -15
  329. package/dist/tools/fs/bash-program-position.js +3 -10
  330. package/dist/tools/fs/bash-readonly-classifier.js +2 -0
  331. package/dist/tools/fs/fs-bash.d.ts +3 -3
  332. package/dist/tools/fs/fs-bash.js +72 -101
  333. package/dist/tools/fs/fs-read.d.ts +12 -0
  334. package/dist/tools/fs/fs-read.js +10 -9
  335. package/dist/tools/fs/fs-shared.d.ts +27 -31
  336. package/dist/tools/fs/fs-shared.js +12 -15
  337. package/dist/tools/fs/fs-write.js +1 -1
  338. package/dist/tools/fs/index.js +2 -2
  339. package/dist/tools/fs/read-deny-home.d.ts +1 -1
  340. package/dist/tools/fs/read-deny-home.js +5 -4
  341. package/dist/tools/fs/read-deny.d.ts +16 -3
  342. package/dist/tools/fs/read-deny.js +12 -9
  343. package/dist/tools/fs/safety.d.ts +7 -6
  344. package/dist/tools/fs/shell-read-bindings.d.ts +5 -3
  345. package/dist/tools/fs/shell-read-bindings.js +15 -16
  346. package/dist/tools/fs/shell-read-device.js +1 -1
  347. package/dist/tools/fs/shell-read-plan.js +36 -47
  348. package/dist/tools/fs/shell-read-word.d.ts +1 -6
  349. package/dist/tools/fs/shell-read-word.js +2 -20
  350. package/dist/tools/fs/shell-reentry-text.js +1 -1
  351. package/dist/tools/web.d.ts +2 -2
  352. package/package.json +4 -1
  353. package/test/export-surface.snapshot.json +5651 -5457
  354. package/wire-changes/core@7.53.0.json +1968 -0
  355. package/wire-changes/core@7.54.0.json +2870 -0
  356. package/dist/core/shell-scan.d.ts +0 -60
  357. package/dist/core/shell-scan.js +0 -183
@@ -1,4 +1,4 @@
1
- import { withArgsReading } from "../effective-path-target.js";
1
+ import { argsAsTheToolReads, withArgsReading } from "../effective-path-target.js";
2
2
  import { policyAskClassOf } from "../ask-class.js";
3
3
  import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
4
4
  import { classifierUnavailableSeat } from "./classifier-ladder.js";
@@ -6,7 +6,8 @@ import { resolveCheckpointStore } from "../checkpoint-store.js";
6
6
  import { chainJudges, inheritedToolChecks, screeningInstallationsOf, standsInFor } from "../mods/stations.js";
7
7
  import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "../permission-rules.js";
8
8
  import { isIsolated } from "../remote-env.js";
9
- import { earlierGrammarAdvisory } from "../session-policy-store.js";
9
+ import { deliverEngineNotice } from "../engine-notice.js";
10
+ import { earlierGrammarNotice } from "../session-policy-store.js";
10
11
  import { attest, attestationOf, checkToolPolicyProjection, combinePolicies, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, durableParkOptInDeclared, isLiveApproverSeat, mergeAttestation, refuseOutOfContractDecision, resolveAsk, toolPolicyNameSets, withAttestation, wrapToolPolicy } from "../tool-policy.js";
11
12
  import { judgeRuleToolName, mountedToolNames } from "../tool-name-aliases.js";
12
13
  import { approvalCardMemberOf } from "../tool-roster.js";
@@ -15,6 +16,7 @@ import { emitTrace } from "../trace.js";
15
16
  import { skillGrantBindingMembers } from "../skill-grant.js";
16
17
  import { SKILL_TOOL_NAME } from "./synthetic-tools.js";
17
18
  import { delegationPoolReading } from "./sub-agent-deny-lists.js";
19
+ import { valveLeaves } from "../../agents/tool-filter.js";
18
20
  import { autoStrippedRule, cardDisclosureOf, nearMissSpellingOf, rootFacingToolNames } from "../allow-entry.js";
19
21
  import { arbitrateByMode, askClassMembersOf, askFaceOf, askMandateMember } from "../ask-origin.js";
20
22
  import { createModeGatePolicy, mountedToolDeclaresReadOnly } from "../mode-policy.js";
@@ -46,7 +48,7 @@ export async function preparePolicyChain(input) {
46
48
  const known = mountedToolNames(tools);
47
49
  for (const t of harnessTools)
48
50
  known.add(t.name);
49
- const pool = delegationPoolReading(spec.tools ?? [], selector);
51
+ const pool = delegationPoolReading(spec.tools ?? [], valveLeaves(spec, selector));
50
52
  const callerNames = mountedToolNames(spec.tools ?? []);
51
53
  const rootFacing = rootFacingToolNames([...known, ...callerNames, ...pool.names]);
52
54
  const unmatched = new Set();
@@ -119,7 +121,7 @@ export async function preparePolicyChain(input) {
119
121
  catch {
120
122
  }
121
123
  };
122
- const announceEarlierGrammar = (rulesSessionId) => (entries, field, grammar) => deps.onError?.(Object.assign(new Error(earlierGrammarAdvisory(rulesSessionId, entries, field, grammar)), { code: "config.session_rules_earlier_grammar" }), { phase: "config", sessionId });
124
+ const announceEarlierGrammar = (rulesSessionId) => (entries, field, grammar) => deliverEngineNotice(deps.onNotice, earlierGrammarNotice({ rulesSessionId, sessionId, entries, field, grammar }));
123
125
  let sessionRulePolicy;
124
126
  if (deps.sessionPolicyStore && spec.sessionId) {
125
127
  const store = deps.sessionPolicyStore;
@@ -343,7 +345,7 @@ export async function preparePolicyChain(input) {
343
345
  const recheckApprovedEdit = async (pol, onAskOf, creq, edit, approved, csignal, ancestorAutoMode) => {
344
346
  const ancestorDecider = ancestorAutoMode?.decider;
345
347
  const ancestorTracker = ancestorAutoMode?.denialTracking;
346
- let editArgs = edit;
348
+ let editArgs = argsAsTheToolReads(creq, edit);
347
349
  let settledBy = approved;
348
350
  const onApproval = (d) => withAttestation(d, mergeAttestation(creq, attestationOf(settledBy, creq), attestationOf(d, creq), "answer"));
349
351
  const vetoed = onApproval;
@@ -356,8 +358,7 @@ export async function preparePolicyChain(input) {
356
358
  }
357
359
  let re;
358
360
  try {
359
- const editReq = withArgsReading(creq, editArgs, csignal ?? abortController.signal);
360
- re = refuseOutOfContractDecision(await pol.check(editReq !== undefined ? await editReq : { ...creq, args: editArgs }, csignal ?? abortController.signal));
361
+ re = refuseOutOfContractDecision(await pol.check(await withArgsReading(creq, editArgs, csignal ?? abortController.signal), csignal ?? abortController.signal));
361
362
  }
362
363
  catch (err) {
363
364
  reportPolicyThrow(notifyOwnHookCrash, "an inherited parent policy's re-check of the approved edit", creq, err, csignal ?? abortController.signal);
@@ -373,7 +374,7 @@ export async function preparePolicyChain(input) {
373
374
  return onApproval(withAttestation({ action: "allow", updatedInput: re.updatedInput !== undefined ? re.updatedInput : editArgs, ...(stated !== undefined ? { decisionReason: stated } : {}) }, re.attestation));
374
375
  }
375
376
  if (re.updatedInput !== undefined)
376
- editArgs = re.updatedInput;
377
+ editArgs = argsAsTheToolReads(creq, re.updatedInput);
377
378
  const judged = await judgeInheritedClassifier({ liveMode: () => permissionMode.current, autoMode: ancestorAutoMode, ask: re, req: { ...creq, args: editArgs }, signal: csignal ?? abortController.signal, subject: "the approved edit", allowRewrite: editArgs, facts: inheritedStationFacts(creq), unavailableSeat: classifierUnavailableSeat({ station: "ancestor", ...(ancestorDecider?.timeoutMs !== undefined ? { budgetMs: ancestorDecider.timeoutMs } : {}), route: frozenApproverRoute(onAskOf), onNotice: deps.onNotice, sessionId, runId }) });
378
379
  if (judged.kind === "allow") {
379
380
  return onApproval(judged.result);
@@ -408,7 +409,7 @@ export async function preparePolicyChain(input) {
408
409
  settledBy = rr;
409
410
  if (rr.updatedInput === undefined)
410
411
  return onApproval({ action: "allow", updatedInput: editArgs, decisionReason: "mode" });
411
- editArgs = rr.updatedInput;
412
+ editArgs = argsAsTheToolReads(creq, rr.updatedInput);
412
413
  }
413
414
  };
414
415
  const settleInstallationAsk = async (pc, decision, creq, csignal) => {
@@ -427,7 +428,7 @@ export async function preparePolicyChain(input) {
427
428
  return settledAs(decision);
428
429
  return settledAs(mandateUnreconstructibleDeny(creq));
429
430
  }
430
- const presentedArgs = decision.updatedInput !== undefined ? decision.updatedInput : creq.args;
431
+ const presentedArgs = decision.updatedInput !== undefined ? argsAsTheToolReads(creq, decision.updatedInput) : creq.args;
431
432
  const judged = await judgeInheritedClassifier({ liveMode: () => permissionMode.current, autoMode: pc.autoMode, ask: decision, req: { ...creq, args: presentedArgs }, signal: csignal ?? abortController.signal, subject: "this call", allowRewrite: decision.updatedInput, facts: inheritedStationFacts(creq), unavailableSeat: classifierUnavailableSeat({ station: "ancestor", ...(pc.autoMode?.decider.timeoutMs !== undefined ? { budgetMs: pc.autoMode.decider.timeoutMs } : {}), route: frozenApproverRoute(pc.onAsk), onNotice: deps.onNotice, sessionId, runId }) });
432
433
  if (judged.kind === "allow")
433
434
  return settledAs(judged.result);
@@ -635,11 +636,9 @@ export async function preparePolicyChain(input) {
635
636
  }
636
637
  }
637
638
  const recheckLayers = [...recheckPrefix, ...postEmitterSameInstanceAdapters];
638
- const finalRead = withArgsReading(req, decision.updatedInput, signal);
639
- const finalReq = finalRead !== undefined ? await finalRead : { ...req, args: decision.updatedInput };
639
+ const finalReq = await withArgsReading(req, decision.updatedInput, signal);
640
640
  let asked;
641
641
  let revalidated;
642
- let restated;
643
642
  try {
644
643
  for (const layer of recheckLayers) {
645
644
  const d = refuseOutOfContractDecision(await layer.check(finalReq, signal));
@@ -655,8 +654,6 @@ export async function preparePolicyChain(input) {
655
654
  }
656
655
  if (d.action === "ask" && asked === undefined)
657
656
  asked = d;
658
- if (d.action === "allow" && restated === undefined && d.decisionReason !== undefined)
659
- restated = d.decisionReason;
660
657
  revalidated = mergeAttestation(req, revalidated, d.attestation);
661
658
  }
662
659
  }
@@ -666,10 +663,8 @@ export async function preparePolicyChain(input) {
666
663
  if (asked !== undefined && decision.action === "allow") {
667
664
  return { ...asked, updatedInput: decision.updatedInput };
668
665
  }
669
- if (decision.action === "allow") {
670
- const owned = { ...decision, ...(decision.decisionReason === undefined && restated !== undefined ? { decisionReason: restated } : {}) };
671
- return withAttestation(owned, mergeAttestation(req, attestationOf(decision, req), revalidated));
672
- }
666
+ if (decision.action === "allow")
667
+ return withAttestation(decision, mergeAttestation(req, attestationOf(decision, req), revalidated));
673
668
  return decision;
674
669
  })
675
670
  : foldedPolicy;
@@ -14,7 +14,7 @@ export interface PrepareProjectContextInput {
14
14
  /** borrowed-readonly — the REBOUND spec (`spec′`). Read: `sessionId` (phase derivation + the
15
15
  * continuation projections), `skills` (the roster), `userInvokedSkills` (the person's invoked skills — their
16
16
  * rows are written here), `principal` (the shared-memory tools' trusted identity). Never mutated. */
17
- spec: Pick<TaskSpec, "sessionId" | "skills" | "userInvokedSkills" | "principal">;
17
+ spec: Pick<TaskSpec, "sessionId" | "skills" | "userInvokedSkills" | "principal" | "excludeAllTools">;
18
18
  /** borrowed-readonly — trusted internals: `agentName` (seam ctx), `inheritedSkillGrants` (the parent's captured
19
19
  * skill grant rows, seeded as `inherited`), `inheritedAllowedTools` (the parent's request entries, seeded as this leg's
20
20
  * own). `undefined` on a standalone prepare. */
@@ -13,10 +13,12 @@ import { SKILL_CONTENT_MAX_CHARS, SKILL_TOOL_NAME, createSkillTool, normalizeSki
13
13
  import { skillLoadReading } from "./skill-base-dir.js";
14
14
  import { RosterBuilder } from "../tool-roster.js";
15
15
  import { mountedToolNames } from "../tool-name-aliases.js";
16
+ import { valveLeaves } from "../../agents/tool-filter.js";
16
17
  import { asThrownError } from "../thrown-value.js";
17
18
  export async function prepareProjectContext(input) {
18
19
  const { deps, spec, internals, session, sessionId, runId, hostTaskId, taskRootFinal, handsEnabled, delegation, seedContextFiles, memoryBlockFromEngine, skillGrants, allowedTools, allowedToolTables, roster, toolFaceSnapshot, onceLedger, memoryTools, memoryEngineSession, memorySearchToolsPlanned, memoryPairExcludedName, memoryPairOccupiedName, resume, skillListingBudget } = input;
19
20
  const tools = roster.tools;
21
+ const leaves = valveLeaves(spec, toolFaceSnapshot.selector);
20
22
  let memoryBlock = memoryBlockFromEngine;
21
23
  let instructionSources;
22
24
  let projectInstructionContent;
@@ -115,11 +117,11 @@ export async function prepareProjectContext(input) {
115
117
  for (const alias of t.aliases ?? [])
116
118
  mountedNameDomain.add(alias);
117
119
  }
118
- const excludedName = SHARED_MEMORY_TOOL_NAMES.find((n) => !toolFaceSnapshot.selector.admits({ name: n }));
120
+ const excludedName = SHARED_MEMORY_TOOL_NAMES.find((n) => !leaves({ name: n }));
119
121
  const occupiedName = SHARED_MEMORY_TOOL_NAMES.find((n) => mountedNameDomain.has(n));
120
122
  if (excludedName !== undefined || occupiedName !== undefined) {
121
123
  announceMemoryNotMounted(onceLedger, sessionId, "shared", SHARED_MEMORY_TOOL_NAMES, excludedName !== undefined
122
- ? `the run's tool selector (allowTools / excludeTools) does not admit "${excludedName}"`
124
+ ? `the run's tool face (allowTools / excludeTools / excludeAllTools) does not admit "${excludedName}"`
123
125
  : `this task already declares a tool named "${occupiedName}" (the built-in yields to it)`);
124
126
  }
125
127
  else {
@@ -137,10 +139,10 @@ export async function prepareProjectContext(input) {
137
139
  }
138
140
  else if (memoryEngineSession !== undefined && !memorySearchToolsPlanned) {
139
141
  announceMemoryNotMounted(onceLedger, sessionId, "engine", MEMORY_ENGINE_TOOL_NAMES, memoryPairExcludedName !== undefined
140
- ? `the run's tool selector (allowTools / excludeTools) does not admit "${memoryPairExcludedName}"`
142
+ ? `the run's tool face (allowTools / excludeTools / excludeAllTools) does not admit "${memoryPairExcludedName}"`
141
143
  : `this task already declares a tool named "${memoryPairOccupiedName}" (the built-in yields to it)`);
142
144
  }
143
- const skillsListing = skillSpecs.length > 0
145
+ const skillsListing = skillSpecs.length > 0 && leaves({ name: SKILL_TOOL_NAME })
144
146
  ? {
145
147
  entries: skillSpecs.map((s) => ({
146
148
  name: s.name,
@@ -31,7 +31,7 @@ export interface PreparePromptAssemblyInput {
31
31
  readonly role?: HostRole;
32
32
  readonly form?: HostForm;
33
33
  };
34
- /** borrowed-readonly — the center binding (`TaskSpec.promptBinding`, validated), or undefined. */
34
+ /** borrowed-readonly — the run's binding (`TaskSpec.promptBinding`, validated), or undefined: a selector value. */
35
35
  binding: string | undefined;
36
36
  /** borrowed-readonly — the leg's mods bus: `prompt.compose` collects the deploy and task seats' overlays. */
37
37
  modBus: LegModBus;
@@ -1,12 +1,13 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { SEND_MESSAGE_TOOL_NAME } from "../../agents/send-message-tool.js";
3
3
  import { assemblePrompt } from "../../prompt-assembly/assemble.js";
4
- import { adoptCenter, centerOverlaysOf } from "../../prompt-assembly/artifact.js";
4
+ import { adoptCenter, centerOverlaysOf, verifyPromptArtifactBody } from "../../prompt-assembly/artifact.js";
5
+ import { refusalClause, storedArtifactLine } from "../../prompt-assembly/artifact-store.js";
5
6
  import { catalogDigestOf, digestOf, prepareEpochRecord } from "../../prompt-assembly/epoch.js";
6
7
  import { rendererVector } from "../../prompt-assembly/renderers.js";
7
8
  import { SEMA_DEFAULT_CATALOG } from "../../prompt-assembly/catalog/index.js";
8
9
  import { describeCatalog } from "../../prompt-assembly/explain.js";
9
- import { selectorsOf } from "../../prompt-assembly/select.js";
10
+ import { selectorRecordOf, selectorsOf } from "../../prompt-assembly/select.js";
10
11
  import { auditToolCollisions, projectToolManifest } from "../../prompt-assembly/tool-catalog.js";
11
12
  import { buildEnvironmentContext } from "../../prompts/default.js";
12
13
  import { raisePromptCompose } from "../mods/stations.js";
@@ -31,13 +32,21 @@ export async function preparePromptAssembly(input) {
31
32
  const stored = await session.getPromptEpoch();
32
33
  let centerAdoption;
33
34
  {
34
- const failUnavailable = (what) => {
35
- throw Object.assign(new Error(`prompt snapshot unavailable: ${what} (artifact source miss / not verifiable here${deps.promptSource === undefined ? "; RunnerDeps.promptSource is not configured" : ""}) — refusing to recompose a hybrid prompt`), { code: "prompt.snapshot_unavailable" });
35
+ const failUnavailable = (what, refusal) => {
36
+ const why = refusal !== undefined ? `the source's copy is ${refusalClause(refusal)}` : `artifact source miss / not verifiable here${deps.promptSource === undefined ? "; RunnerDeps.promptSource is not configured" : ""}`;
37
+ throw Object.assign(new Error(`prompt snapshot unavailable: ${what} (${why}) — refusing to recompose a hybrid prompt`), { code: "prompt.snapshot_unavailable" });
36
38
  };
37
39
  const resolvePinned = async (digest, sourceRevision, via) => {
38
- const art = await deps.promptSource?.get(digest);
40
+ const told = {};
41
+ const art = await deps.promptSource?.get(digest, (r) => void (told.current = r));
39
42
  const adopted = art !== undefined ? adoptCenter(art, sourceRevision) : undefined;
40
- return adopted ?? failUnavailable(`${via} center prompt artifact ${digest.slice(0, 23)}… has no verified resolvable copy`);
43
+ if (adopted !== undefined)
44
+ return adopted;
45
+ const checked = art !== undefined ? verifyPromptArtifactBody(art) : undefined;
46
+ const refusal = told.current ?? (checked !== undefined && !checked.ok ? { code: checked.code, reason: checked.reason } : undefined);
47
+ if (refusal !== undefined)
48
+ deps.onError?.(new Error(storedArtifactLine(digest, refusal, `the session fails prompt.snapshot_unavailable (a hybrid prompt is never recomposed)`)), { phase: "prompt-constitution", sessionId });
49
+ return failUnavailable(`${via} center prompt artifact ${digest.slice(0, 23)}… has no verified resolvable copy`, refusal);
41
50
  };
42
51
  const pinned = stored?.kind === "pin" ? stored.descriptor : undefined;
43
52
  const retiredCenterPin = stored?.kind === "legacy" && stored.centerPinned;
@@ -76,14 +85,8 @@ export async function preparePromptAssembly(input) {
76
85
  promptProfile,
77
86
  fableMitigations,
78
87
  };
79
- const selectors = selectorsOf(facts, host);
80
- const selectorRecord = {
81
- ...(binding !== undefined ? { binding } : {}),
82
- traits: [...selectors.traits].sort(),
83
- host: { role: selectors.host.role, form: selectors.host.form },
84
- facts: { ...selectors.facts },
85
- };
86
- const centerOverlays = centerOverlaysOf(centerAdoption, binding);
88
+ const selectorRecord = selectorRecordOf(selectorsOf(facts, host, binding));
89
+ const centerOverlays = centerOverlaysOf(centerAdoption);
87
90
  const lowerAdds = new Map();
88
91
  for (const { overlay } of [...sugar, ...centerOverlays])
89
92
  if (overlay.op === "add")
@@ -91,16 +94,17 @@ export async function preparePromptAssembly(input) {
91
94
  const composed = await raisePromptCompose(modBus, {
92
95
  model: model.id,
93
96
  catalog: describeCatalog().sections,
94
- selectors: { traits: [...selectors.traits], host: selectors.host, facts: selectors.facts },
97
+ selectors: selectorRecord,
95
98
  }, { lowerAdds, ...(input.signal !== undefined ? { signal: input.signal } : {}) });
96
99
  for (const w of composed.warnings)
97
100
  deps.onError?.(new Error(w), { phase: "prompt-constitution", sessionId });
98
101
  const taskOverlays = [...sugar, ...composed.task];
99
102
  const buildAssembleInputs = (center) => ({
100
103
  taskOverlays,
101
- centerOverlays: centerOverlaysOf(center, binding),
104
+ centerOverlays: centerOverlaysOf(center),
102
105
  deployOverlays: composed.deploy,
103
106
  host,
107
+ ...(binding !== undefined ? { binding } : {}),
104
108
  tools,
105
109
  facts,
106
110
  ...(envFacts.cwd !== undefined ? { workspaceFolder: envFacts.cwd } : {}),
@@ -27,6 +27,7 @@ import type { SourcedOverlay } from "../../prompt-assembly/overlay.js";
27
27
  import type { ContainmentFace } from "../../tools/fs/index.js";
28
28
  import type { LockedPreflight } from "../locked-config.js";
29
29
  import type { MaterializedMcp } from "../mcp.js";
30
+ import type { RosterBuilder } from "../tool-roster.js";
30
31
  import type { ResolvedRole } from "../roles.js";
31
32
  import type { RunnerDeps, TaskSpec } from "../types.js";
32
33
  import type { SessionTreeEntry } from "../../internal/harness-types.js";
@@ -37,8 +38,8 @@ import { type ContextWindowOverlay } from "../context-settings.js";
37
38
  export interface PreparePromptInputsInput {
38
39
  /** borrowed-readonly — the REBOUND spec (`spec′`). Read: `systemPrompt` / `appendSystemPrompt` (handed whole to the
39
40
  * request-body sugar), `clientContext` (zone, email), `envFacts` (the deployment's sandbox + resume facts),
40
- * `compaction` (the within-task flag). Never mutated. */
41
- spec: Pick<TaskSpec, "systemPrompt" | "appendSystemPrompt" | "clientContext" | "envFacts" | "compaction">;
41
+ * `compaction` (the within-task flag), `excludeAllTools` (the valve's whole-face switch). Never mutated. */
42
+ spec: Pick<TaskSpec, "systemPrompt" | "appendSystemPrompt" | "clientContext" | "envFacts" | "compaction" | "excludeAllTools">;
42
43
  /** borrowed-readonly — deployment deps: `onError` (the operator lane: fail-closed advisory, cwd misalignment,
43
44
  * git-lane degrade), `modelKnowledgeCutoffs`. Receiver preserved (`deps.onError?.(…)`). */
44
45
  deps: Pick<RunnerDeps, "onError" | "modelKnowledgeCutoffs">;
@@ -61,8 +62,9 @@ export interface PreparePromptInputsInput {
61
62
  resolvedReadFace: ContainmentFace | undefined;
62
63
  /** borrowed-readonly — the resolved write face (the open-writes flag + the structured env fact). */
63
64
  resolvedWriteFace: ContainmentFace | undefined;
64
- /** borrowed-readonly — the frozen tool face; only `defer` is read (the Workflow short-pointer flag). */
65
- toolFaceSnapshot: Pick<ToolFaceSnapshot, "defer">;
65
+ /** borrowed-readonly — the frozen tool face; `defer` (the Workflow short-pointer flag) and `selector` (with the spec's whole-face
66
+ * switch, the valve's reading that decides which servers' instructions are taught). */
67
+ toolFaceSnapshot: Pick<ToolFaceSnapshot, "defer" | "selector">;
66
68
  /** borrowed-readonly — the resolved prompt profile (rides the flags to the legacy ctx). */
67
69
  promptProfile: "simple" | "classic";
68
70
  /** borrowed-readonly — the fable-mitigations profile axis (rides the flags with the profile). */
@@ -81,8 +83,12 @@ export interface PreparePromptInputsInput {
81
83
  };
82
84
  /** borrowed-readonly — the resolved role; only its `systemPrompt` preset is read (second source). */
83
85
  resolvedRole: Pick<ResolvedRole, "systemPrompt">;
84
- /** borrowed-readonly — the materialized MCP roster; only `serverInstructions` (the disposed entries) is read. */
85
- mcp: Pick<MaterializedMcp, "serverInstructions">;
86
+ /** borrowed-mutable — the materialized MCP roster; `serverInstructions` (the disposed entries) and `tools` (each server's listing: did it list
87
+ * any tool) are read, and the instructions lane's ledger is stated: the block is what the model is told at the run's start. */
88
+ mcp: Pick<MaterializedMcp, "serverInstructions" | "tools" | "instructionsDelta">;
89
+ /** borrowed-readonly — the run's roster as the protocol-tools phase mounted it (the deployment's overlay applied, the valve not yet):
90
+ * the tools the teaching answer reads, with the valve's predicate. */
91
+ roster: Pick<RosterBuilder, "tools">;
86
92
  /** borrowed-readonly — the resolved model (id for the env line + the cutoff lookup). */
87
93
  model: Model;
88
94
  /** borrowed-readonly — the run's external-content-target fold (the single-source disclosure fact). */
@@ -1,5 +1,7 @@
1
1
  import { formatLocalDate, isValidTimeZone } from "../../prompts/default.js";
2
2
  import { sugarOverlays } from "../../prompt-assembly/sugar.js";
3
+ import { valveLeaves } from "../../agents/tool-filter.js";
4
+ import { instructionsTaught, toldAtStart } from "../mounted-mcp.js";
3
5
  import { isIsolated } from "../remote-env.js";
4
6
  import { readDateAnchor } from "./announce-once-ledger.js";
5
7
  import { probeGitStatusLane } from "./git-status-frame.js";
@@ -31,9 +33,10 @@ export async function preparePromptInputs(input) {
31
33
  isSubagent: delegation.isNonForkChild,
32
34
  };
33
35
  const sugar = sugarOverlays({ spec, resolvedRole, ...(internals !== undefined ? { internals } : {}) });
34
- const mcpInstructionsBlock = mcp.serverInstructions.length
35
- ? `# MCP Server Instructions\n${mcp.serverInstructions.map(renderMcpInstructionsEntry).join("\n\n")}`
36
- : undefined;
36
+ const valveLeft = valveLeaves(spec, toolFaceSnapshot.selector);
37
+ const taught = mcp.serverInstructions.filter((entry) => instructionsTaught(valveLeft, entry.server, input.roster.tools, mcp.tools));
38
+ toldAtStart(mcp.instructionsDelta, new Set(taught.map((entry) => entry.server)));
39
+ const mcpInstructionsBlock = taught.length ? `# MCP Server Instructions\n${taught.map(renderMcpInstructionsEntry).join("\n\n")}` : undefined;
37
40
  const userTz = spec.clientContext?.timeZone;
38
41
  const tzValid = userTz !== undefined && isValidTimeZone(userTz);
39
42
  const dateAnchor = await readDateAnchor(session);
@@ -32,12 +32,14 @@ import type { AnnounceOnceSink, IrreversibilityTier, Prepared, RollbackStack, To
32
32
  import { RosterBuilder, type ToolRosterDeltaSeat } from "../tool-roster.js";
33
33
  import type { LegModBus } from "../mods/stations.js";
34
34
  export interface PrepareProtocolToolsInput {
35
- /** borrowed-readonly — the frozen preflight; only `mcp` (the declared server entries) is read: the
36
- * materialize input, the RefreshMcpTools mount predicate, and whether a real client was acquired. */
37
- lockedPreflight: Pick<LockedPreflight, "mcp">;
35
+ /** borrowed-readonly — the frozen preflight; `mcp` (the declared server entries: the materialize input, the RefreshMcpTools
36
+ * mount predicate, and whether a real client was acquired) and `a2a` (the declared peers the door judged: the materialize
37
+ * input and whether a handle was acquired) are read. */
38
+ lockedPreflight: Pick<LockedPreflight, "mcp" | "a2a">;
38
39
  /** borrowed-readonly — the REBOUND spec. Read: `principal` (the MCP header / the A2A identity), `tools`
39
- * (the caller names both reserved-name guards check against), `a2a` (the peer entries). */
40
- spec: Pick<TaskSpec, "principal" | "tools" | "a2a">;
40
+ * (the caller names both reserved-name guards check against), `excludeAllTools` (the valve's whole-face switch: the live roster lane's
41
+ * reading, and the first-dial gate). */
42
+ spec: Pick<TaskSpec, "principal" | "tools" | "excludeAllTools">;
41
43
  /** borrowed-readonly — the deployment seats the materializers and their operator faces read: `onElicit`
42
44
  * and `mcpImageResizer` ride into the MCP intake; `onError` takes the A2A warnings (no ledger — a peer is
43
45
  * re-read every prepare); `mcpRevocations` + `onNotice` make the revocation wiring. */
@@ -1,6 +1,8 @@
1
1
  import { Type } from "typebox";
2
2
  import { materializeMcpTools } from "../mcp.js";
3
- import { applyMcpRosterDelta, commitMcpRosterChanges, redialMcpServer } from "./mcp-redial.js";
3
+ import { applyMcpRosterDelta, commitMcpRosterChanges, redialMcpServer, rosterHolding, settledOnRoster } from "./mcp-redial.js";
4
+ import { valveLeaves, valveLeavesPeer } from "../../agents/tool-filter.js";
5
+ import { resourceFacesLeft } from "../mounted-mcp.js";
4
6
  import { materializeA2aTools } from "../a2a.js";
5
7
  import { deliverEngineNotice } from "../types.js";
6
8
  import { RosterBuilder } from "../tool-roster.js";
@@ -24,8 +26,11 @@ export async function prepareProtocolTools(input) {
24
26
  if (overPeer !== undefined) {
25
27
  throw Object.assign(new Error(`MCP server name ${JSON.stringify(overPeer.name.slice(0, 40) + "…")} is ${overPeer.name.length} characters; a peer rides every roster row of its tools and the roster's bound on a name is ${TOOL_WIRE_NAME_MAX_CHARS}.`), { code: "config.tool_name_too_long" });
26
28
  }
29
+ const serverReached = valveLeavesPeer(spec, toolFaceSnapshot.selector);
30
+ const leaves = valveLeaves(spec, toolFaceSnapshot.selector);
31
+ const resourcesReached = resourceFacesLeft(leaves);
27
32
  const mcp = lockedPreflight.mcp?.length
28
- ? await materializeMcpTools(lockedPreflight.mcp, spec.principal, deps.onElicit, deps.mcpImageResizer, { reminderMark, counts: reminderDisclosureCounts }, mcpRevocationWiring(deps, runId), mcpPool === undefined ? undefined : { pool: mcpPool.pool, ownsPool: mcpPool.owned }, sectionDisposerOf(input.modBus, abortController.signal))
33
+ ? await materializeMcpTools(lockedPreflight.mcp, spec.principal, deps.onElicit, deps.mcpImageResizer, { reminderMark, counts: reminderDisclosureCounts }, mcpRevocationWiring(deps, runId), mcpPool === undefined ? undefined : { pool: mcpPool.pool, ownsPool: mcpPool.owned }, sectionDisposerOf(input.modBus, abortController.signal), (entry) => resourcesReached || serverReached(mintNamespacePrefix(MCP_NAMESPACE, entry.name)))
29
34
  :
30
35
  { tools: [], toolAxes: [], warnings: [], serverInstructions: [], instructionsDelta: { pendingAdds: [], pendingRemovals: [] }, droppedTools: [], statuses: [], refresh: async () => [], reconnect: async (server) => ({ server, prefix: mintNamespacePrefix(MCP_NAMESPACE, server), outcome: "not_declared", reason: "this task declared no MCP servers", toolCount: 0, added: [], removed: [] }), dispose: async () => { } };
31
36
  if (lockedPreflight.mcp?.length)
@@ -69,7 +74,7 @@ export async function prepareProtocolTools(input) {
69
74
  const rebuildHarnessToolsRef = {};
70
75
  const contentOriginWrapRef = {};
71
76
  const toolCallGateArmedRef = { armed: false };
72
- const rosterApply = { toolFaceSnapshot, withFaces, remoteToolOffload, foldProtocolAxes: (axes, label) => foldProtocolAxes(axes, label), toolEffects, axisExplicitNegatives, roster };
77
+ const rosterApply = { spec, toolFaceSnapshot, withFaces, remoteToolOffload, foldProtocolAxes: (axes, label) => foldProtocolAxes(axes, label), toolEffects, axisExplicitNegatives, roster, declared: lockedPreflight.mcp ?? [], instructionsDelta: mcp.instructionsDelta };
73
78
  const rosterCommit = { rebuildHarnessToolsRef, rosterSeat, toolCallGateArmedRef, irreversibleTools, egressTools };
74
79
  const redialInput = { ...rosterApply, ...rosterCommit, mcp, deps, sessionId, runId, irreversibilityTier };
75
80
  const mcpRedial = lockedPreflight.mcp?.length ? (server) => redialMcpServer(redialInput, server) : undefined;
@@ -88,14 +93,17 @@ export async function prepareProtocolTools(input) {
88
93
  const lines = [];
89
94
  let changed = false;
90
95
  let anyActiveFailure = false;
96
+ const reported = [];
91
97
  for (const r of results) {
92
98
  if (r.tools === undefined) {
99
+ reported.push(settledOnRoster(r, rosterHolding(rosterApply, r.server), roster));
93
100
  lines.push(`${r.server}: ${r.status}${r.error !== undefined ? ` (${r.error})` : ""}`);
94
101
  if (r.status === "failed")
95
102
  anyActiveFailure = true;
96
103
  continue;
97
104
  }
98
- const applied = applyMcpRosterDelta(rosterApply, { server: r.server, prefix: r.prefix, tools: r.tools, axes: r.axes ?? [], dropped: r.dropped ?? [] });
105
+ const applied = applyMcpRosterDelta(rosterApply, { server: r.server, prefix: r.prefix, tools: r.tools, axes: r.axes ?? [], dropped: r.dropped ?? [], ...(r.instructions !== undefined ? { instructions: r.instructions } : {}) });
106
+ reported.push(settledOnRoster(r, applied, roster));
99
107
  if (!applied.applied) {
100
108
  lines.push(`${r.server}: failed (${applied.foldError})`);
101
109
  anyActiveFailure = true;
@@ -103,16 +111,15 @@ export async function prepareProtocolTools(input) {
103
111
  }
104
112
  changed = true;
105
113
  const detail = [];
106
- const shownAdded = r.added.filter((n) => !applied.excluded.includes(n));
107
- if (shownAdded.length > 0)
108
- detail.push(`added: ${shownAdded.join(", ")}`);
109
- if (r.removed.length > 0)
110
- detail.push(`removed: ${r.removed.join(", ")}`);
114
+ if (applied.added.length > 0)
115
+ detail.push(`added: ${applied.added.join(", ")}`);
116
+ if (applied.removed.length > 0)
117
+ detail.push(`removed: ${applied.removed.join(", ")}`);
111
118
  if (applied.excluded.length > 0)
112
119
  detail.push(`excluded by deployment config (not mounted): ${applied.excluded.join(", ")}`);
113
120
  if ((r.dropped?.length ?? 0) > 0)
114
121
  detail.push(`dropped: ${r.dropped.map((d) => `${d.tool} (${d.reason.length > 90 ? `${d.reason.slice(0, 90)}…` : d.reason})`).join("; ")}`);
115
- lines.push(`${r.server}: refreshed — ${applied.pushed} tool${applied.pushed === 1 ? "" : "s"}${detail.length > 0 ? ` (${detail.join("; ")})` : ""}`);
122
+ lines.push(`${r.server}: refreshed — ${applied.mounted.length} tool${applied.mounted.length === 1 ? "" : "s"}${detail.length > 0 ? ` (${detail.join("; ")})` : ""}`);
116
123
  }
117
124
  if (changed) {
118
125
  const ungated = await commitMcpRosterChanges(rosterCommit);
@@ -122,7 +129,7 @@ export async function prepareProtocolTools(input) {
122
129
  const text = lines.length === 0 ? "No connected MCP servers to refresh." : lines.join("\n");
123
130
  return {
124
131
  content: [{ type: "text", text }],
125
- details: { results },
132
+ details: { results: reported },
126
133
  terminate: false,
127
134
  ...(anyActiveFailure && !changed ? { isError: true } : {}),
128
135
  };
@@ -157,7 +164,7 @@ export async function prepareProtocolTools(input) {
157
164
  }
158
165
  };
159
166
  foldProtocolAxes(mcp.toolAxes, "MCP");
160
- const a2aDeclared = spec.a2a?.length ? spec.a2a : undefined;
167
+ const a2aDeclared = lockedPreflight.a2a;
161
168
  const a2a = a2aDeclared
162
169
  ? await materializeA2aTools(a2aDeclared, spec.principal, abortController.signal)
163
170
  : { tools: [], toolAxes: [], warnings: [], statuses: [], refresh: async () => [], dispose: async () => { } };
@@ -20,7 +20,7 @@ import type { AgentTool } from "../../internal/harness.js";
20
20
  import { type OnQuestion } from "../ask-question.js";
21
21
  import type { CheckpointStore } from "../checkpoint-store.js";
22
22
  import type { RunnerDeps, RuntimeCaps, TaskSpec } from "../types.js";
23
- import type { PrepareResume } from "./contracts.js";
23
+ import type { PrepareResume, ToolFaceSnapshot } from "./contracts.js";
24
24
  import { type ContentAskBinding } from "./content-ask-bindings.js";
25
25
  import { RosterBuilder } from "../tool-roster.js";
26
26
  export { CONTENT_ASK_BINDING_CAP, type ContentAskBinding } from "./content-ask-bindings.js";
@@ -31,7 +31,9 @@ export interface PrepareQuestionFaceInput {
31
31
  /** borrowed-readonly — the REBOUND spec. Read: `durableApproval` (the durable face's opt-in), `interactiveTools`
32
32
  * (the override), `principal` (the tool's source identity), `interactiveQuestionFallback` (restores the
33
33
  * continuation under a resolved posture). Never mutated. */
34
- spec: Pick<TaskSpec, "durableApproval" | "interactiveTools" | "principal" | "interactiveQuestionFallback">;
34
+ spec: Pick<TaskSpec, "durableApproval" | "interactiveTools" | "principal" | "interactiveQuestionFallback" | "excludeAllTools">;
35
+ /** borrowed-readonly — the frozen tool face; its selector with the spec's `excludeAllTools` is the valve's reading: the tool mounts only if the valve leaves it. */
36
+ toolFaceSnapshot: Pick<ToolFaceSnapshot, "selector">;
35
37
  /** borrowed-readonly — the deployment seat `onError` (the stranded-answer and synthetic-continuation operator
36
38
  * lines; swallow-guarded). */
37
39
  deps: Pick<RunnerDeps, "onError">;
@@ -1,11 +1,12 @@
1
- import { createAskUserQuestionTool, isLiveQuestionFace } from "../ask-question.js";
1
+ import { valveLeaves } from "../../agents/tool-filter.js";
2
+ import { ASK_USER_QUESTION_TOOL_NAME, createAskUserQuestionTool, isLiveQuestionFace } from "../ask-question.js";
2
3
  import { boundInputHashOf } from "../canonical-json.js";
3
4
  import { durableParkOptInDeclared } from "../tool-policy.js";
4
5
  import { CONTENT_ASK_BINDING_CAP } from "./content-ask-bindings.js";
5
6
  import { RosterBuilder } from "../tool-roster.js";
6
7
  export { CONTENT_ASK_BINDING_CAP } from "./content-ask-bindings.js";
7
8
  export function prepareQuestionFace(input) {
8
- const { frozenOnQuestion, spec, deps, checkpointStore, runtimeCaps, resolvedInteractionPosture, resume, sessionId, roster, inheritedUnavailableAsks } = input;
9
+ const { frozenOnQuestion, spec, deps, checkpointStore, runtimeCaps, resolvedInteractionPosture, resume, sessionId, roster, toolFaceSnapshot, inheritedUnavailableAsks } = input;
9
10
  const tools = roster.tools;
10
11
  const onQuestion = frozenOnQuestion;
11
12
  const liveQuestionFace = isLiveQuestionFace(onQuestion) ? onQuestion : undefined;
@@ -58,7 +59,7 @@ export function prepareQuestionFace(input) {
58
59
  return liveQuestionFace(req, signal);
59
60
  }
60
61
  : onQuestion;
61
- const questionToolMounted = spec.interactiveTools === true || (spec.interactiveTools !== false && (onQuestion !== undefined || durableQuestionFace));
62
+ const questionToolMounted = (spec.interactiveTools === true || (spec.interactiveTools !== false && (onQuestion !== undefined || durableQuestionFace))) && valveLeaves(spec, toolFaceSnapshot.selector)({ name: ASK_USER_QUESTION_TOOL_NAME });
62
63
  let mountedQuestionTool;
63
64
  if (questionToolMounted)
64
65
  roster.mount((mountedQuestionTool =
@@ -7,7 +7,7 @@ export interface PrepareSafetyScanInput {
7
7
  * `tools`, `handsReadOnly` and `enablePlanMode`; it never mutates. Typed as a spec whose roster is snapshot faces. */
8
8
  spec: RosterSpec;
9
9
  /** borrowed-readonly — read only for the hands-enablement fact (`executionEnvFactory`/
10
- * `executionEnv` presence gates the hand-band effect preseed). */
10
+ * `executionEnv` presence puts the hand band among the wake candidates). */
11
11
  deps: RunnerDeps;
12
12
  }
13
13
  /**
@@ -26,8 +26,13 @@ export interface PrepareSafetyScanInput {
26
26
  * overrides a scanned value).
27
27
  */
28
28
  export interface PrepareSafetyScanResult {
29
- /** borrowed-mutable — per-tool effect registry (alias-complete), the reconcile/path-policy read. */
29
+ /** borrowed-mutable — per-tool effect registry (alias-complete), the path-policy / gate read. This scan writes the caller tools'
30
+ * own declarations (the roster's kept instance); every engine effect arrives with its tool's mount, never by name beforehand. Open
31
+ * defect #2107 (7.55.0, design ticket): a selector that keeps a caller instance under a name and unmounts only the engine's leaves the engine's entry. */
30
32
  toolEffects: Map<string, ToolEffect>;
33
+ /** owned, read once — the wake reconcile's reading (`wakeEffectsOf`): `toolEffects` as this scan leaves it, with every catalog
34
+ * definition this leg may still mount (`engineCandidatesOf`) folded in as a candidate. Built before any mount; no later phase writes it. */
35
+ wakeEffects: Map<string, ToolEffect>;
31
36
  /** borrowed-mutable — egress-marked tools (external writes; the gate never auto-allows them). */
32
37
  egressTools: Set<string>;
33
38
  /** borrowed-mutable — tools whose effect is irreversible (`always`, or `maybe` incl. by probe). */