@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,6 +1,6 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { homedir } from "node:os";
3
- import { withArgsReading } from "./effective-path-target.js";
3
+ import { argsReadFrom, carryArgsReadFrom, withArgsReading } from "./effective-path-target.js";
4
4
  import { brandPolicyAskClass } from "./ask-class.js";
5
5
  import { decisionAskClassesOf, headlessDenialMessage } from "./ask-origin.js";
6
6
  import { ownReadRootCandidate, readRootGrantSeat } from "./read-root-grant-screen.js";
@@ -12,12 +12,12 @@ import { join, normalize as normalizePath, sep } from "node:path";
12
12
  import { BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName } from "../tools/fs/index.js";
13
13
  import { protectivePathTargetOf, shellFaceToolNames } from "./tool-registry.js";
14
14
  import { heldBy } from "./tool-name-readings.js";
15
- import { boundInputHashOf } from "./canonical-json.js";
15
+ import { bindableValueOf, boundInputHashOf, describeBindingFault, exactBoundInputHashOf } from "./canonical-json.js";
16
16
  import { delimitUntrusted, inlineUntrusted, REVIEWER_NOTE_MAX_BODY } from "./untrusted-text.js";
17
17
  import { describeRejectedValue } from "./tool-search-setting.js";
18
18
  import { egressText, egressThrownText } from "./untrusted-egress.js";
19
- import { assertNoRetiredToolPolicyKeys, RETIRED_DECISION_MEMBERS } from "./retired-keys.js";
20
- import { isEngineRefusal, nestedRecordsOf, receiveContract, receiveNestedRecords, refusedOutOfContract, screenContractValues } from "./decision-receipt.js";
19
+ import { assertNoRetiredKeys, assertNoRetiredToolPolicyKeys, RETIRED_DECISION_MEMBERS, RETIRED_TOOL_POLICY_KEYS } from "./retired-keys.js";
20
+ import { DECISION_MEMBER_ARMS, isEngineRefusal, nestedRecordsOf, receiveContract, receiveNestedRecords, refusedOutOfContract, screenContractValues } from "./decision-receipt.js";
21
21
  export { isEngineRefusal } from "./decision-receipt.js";
22
22
  import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "./permission-rules.js";
23
23
  import { ruleSpellingOf } from "./permission-rule-syntax.js";
@@ -45,6 +45,7 @@ const ATTESTATION_GROUP_OF = {
45
45
  unresolvableCause: "unresolvableCause",
46
46
  foldedClasses: "foldedClasses",
47
47
  pathDenial: "pathDenial",
48
+ bindingRefusal: "bindingRefusal",
48
49
  };
49
50
  const ATTESTATION_MEMBERS = Object.keys(ATTESTATION_GROUP_OF);
50
51
  const groupLead = (g) => ATTESTATION_MEMBERS.find((k) => ATTESTATION_GROUP_OF[k] === g);
@@ -146,9 +147,31 @@ export const ASK_EVIDENCE_ABSENCE_VALUES = ["not_wired", "not_adjudicated", "una
146
147
  export function decisionText(d) {
147
148
  return d.message;
148
149
  }
150
+ export function licenseCovers(licensed, runs) {
151
+ return licensed !== undefined && (licensed === exactBoundInputHashOf(runs) || licensed === exactBoundInputHashOf(argsReadFrom(runs)));
152
+ }
153
+ export function bindableArgsOf(toolName, args) {
154
+ const bound = bindableValueOf(args);
155
+ if (!bound.ok)
156
+ return { ok: false, refusal: bindingRefusalOf(toolName, args, bound.fault) };
157
+ if (typeof args === "object" && args !== null && OWNED_ARGS.has(args))
158
+ return { ok: true, value: args };
159
+ if (typeof bound.value === "object" && bound.value !== null)
160
+ OWNED_ARGS.add(bound.value);
161
+ return { ok: true, value: bound.value };
162
+ }
163
+ export function bindingRefusalOf(toolName, args, fault) {
164
+ return (`no approval can be bound to the arguments of "${toolName}": they hold ${inlineUntrusted(describeBindingFault(args, fault), 300)} — an approval binds arguments that are ` +
165
+ `a record of plain JSON data (records, dense lists, strings, finite numbers, booleans, null; no getter, hidden member, Proxy, ` +
166
+ `function, symbol, bigint or object of another kind; no cycle or shared object) nested at most 256 levels deep; denied fail-closed`);
167
+ }
168
+ export function answeredFor(d, call, runs) {
169
+ const record = attestationOf(d, call);
170
+ return record?.settlement !== undefined && licenseCovers(record.inputDigest, runs);
171
+ }
149
172
  const TOOL_POLICY_CARRIED_MEMBERS = ["projection", "pathRules", "writeGuardRows", "nameSets"];
150
173
  export function carriedMembersOf(p) {
151
- assertNoRetiredToolPolicyKeys(p);
174
+ assertNoRetiredKeys(p, RETIRED_TOOL_POLICY_KEYS, "ToolPolicy");
152
175
  const out = {};
153
176
  const carry = (k) => {
154
177
  const v = p[k];
@@ -259,12 +282,7 @@ export function constraintChainDigest(chain) {
259
282
  return `cpv1:${createHash("sha256").update(stableJson(chain)).digest("hex")}`;
260
283
  }
261
284
  const ALLOW = Object.freeze({ action: "allow" });
262
- const ALLOW_BY_RULE = Object.freeze({ action: "allow", decisionReason: "rule" });
263
- export const DECISION_MEMBERS = Object.keys({
264
- action: 0, updatedInput: 0, message: 0, decisionReason: 0, requiresRealApproval: 0, denialLimitFallback: 0, classifierNoRuling: 0, allowRuleShadowed: 0, probeReason: 0,
265
- probeCause: 0, probeMandated: 0, mandated: 0, mandate: 0, probeReadRootCandidate: 0, matchedAskRule: 0, ruleEvidence: 0, segmentCoverage: 0,
266
- origin: 0, askClass: 0, classes: 0, guards: 0, ruleUnreadable: 0, authoredBy: 0, foldedAskClasses: 0, attestation: 0,
267
- });
285
+ export const DECISION_MEMBERS = Object.keys(DECISION_MEMBER_ARMS);
268
286
  const HOOK_RESULT_MEMBERS = [...DECISION_MEMBERS, "additionalContext"];
269
287
  const HOOK_SEAM_UNREAD = new Set(["decisionReason"]);
270
288
  const HOOK_SEAM_OPTIONAL = new Set(["action"]);
@@ -315,7 +333,10 @@ export function refuseOutOfContractDecision(d, opts) {
315
333
  return refusedOutOfContract(`a permission decision's members could not be detached from the layer that returned them (${ownedRewrite.reason}) — ` +
316
334
  `the engine keeps its own copy of what it read; denied fail-closed`);
317
335
  }
318
- const receipt = Object.freeze(attestation !== undefined ? { ...detached.value, attestation } : detached.value);
336
+ carryArgsReadFrom(contract.updatedInput, rewrite);
337
+ const held = detached.value;
338
+ const value = held.crossBoundaryMandated === true && held.requiresRealApproval !== true ? { ...held, requiresRealApproval: true } : held;
339
+ const receipt = Object.freeze(attestation !== undefined ? { ...value, attestation } : value);
319
340
  for (const v of Object.values(receipt))
320
341
  if (Array.isArray(v))
321
342
  Object.freeze(v);
@@ -355,6 +376,7 @@ export function toolPolicyNameSets(p) {
355
376
  return Array.isArray(sets) ? sets : [];
356
377
  }
357
378
  export function createAllowDenyPolicy(opts) {
379
+ assertNoRetiredKeys(opts, RETIRED_ALLOW_DENY_POLICY_OPTIONS, "createAllowDenyPolicy");
358
380
  const invalid = [];
359
381
  const screen = (entries, list) => {
360
382
  if (entries === undefined)
@@ -444,10 +466,13 @@ export function createAllowDenyPolicy(opts) {
444
466
  if (allow && !nameListHolds(allow, req) && !namespacedCoveringHit(allowCovering, req)) {
445
467
  return { action: "deny", message: `tool "${req.toolName}" is not in the allowlist` };
446
468
  }
447
- return allow && opts.scope !== "narrowing" ? ALLOW_BY_RULE : ALLOW;
469
+ return ALLOW;
448
470
  },
449
471
  };
450
472
  }
473
+ const RETIRED_ALLOW_DENY_POLICY_OPTIONS = Object.freeze({
474
+ scope: "an allow list is only ever a narrowing now (a tool it does not name is denied; a tool it names gets no objection, not consent) — drop the option, and put the consent in the allow layer: `RunnerDeps.allowedTools` for the deployment's, `TaskSpec.allowedTools` for a request's",
475
+ });
451
476
  export function createApprovalPolicy(opts) {
452
477
  if (opts.approvalTimeoutMs !== undefined && !Number.isFinite(opts.approvalTimeoutMs)) {
453
478
  throw new Error(`createApprovalPolicy: approvalTimeoutMs must be a finite number of ms (got ${opts.approvalTimeoutMs}) — omit it to wait indefinitely`);
@@ -481,17 +506,17 @@ export function createApprovalPolicy(opts) {
481
506
  return { action: "deny", message: `tool "${req.toolName}" is denied by policy` };
482
507
  }
483
508
  if (nameListHolds(need, req) || namespacedCoveringHit(needCovering, req)) {
484
- const attestOver = (inputDigest) => (d, settlement) => ({ ...d, attestation: mintAttestation(req, { settlement, origin: "policy", inputDigest }) });
509
+ const attestOver = (inputDigest) => (d, settlement, bindingRefusal) => ({ ...d, attestation: mintAttestation(req, { settlement, origin: "policy", ...(inputDigest !== undefined ? { inputDigest } : {}), ...(bindingRefusal !== undefined ? { bindingRefusal } : {}) }) });
485
510
  const unasked = unaskedSeatAnswer(req, signal, { aborted: `approval aborted for "${req.toolName}" (run or turn interrupted)`, unreachable: `approval for "${req.toolName}" was not requested: nobody can be asked about this call` }, "policy");
486
511
  if (unasked !== undefined)
487
512
  return unasked;
488
- const shown = tryCloneArgs(req.args);
489
- if (!shown.ok) {
490
- return attestOver(boundInputHashOf(req.args))({ action: "deny", message: `approval for "${req.toolName}" could not present the args safely (unclonable value: ${shown.reason}) — denied fail-closed` }, settledByNobody("presentation_failed"));
491
- }
492
- const askedDigest = boundInputHashOf(shown.value);
513
+ const bound = bindableArgsOf(req.toolName, req.args);
514
+ if (!bound.ok)
515
+ return attestOver(undefined)({ action: "deny", message: bound.refusal }, settledByNobody("presentation_failed"), bound.refusal);
516
+ const shown = { value: structuredClone(bound.value) };
517
+ const askedDigest = exactBoundInputHashOf(shown.value);
493
518
  const attest = attestOver(askedDigest);
494
- const heldWhileWaiting = () => boundInputHashOf(req.args) === askedDigest;
519
+ const heldWhileWaiting = () => licenseCovers(askedDigest, req.args);
495
520
  const changedWhilePending = () => attest({
496
521
  action: "deny",
497
522
  message: `the arguments of "${req.toolName}" changed while its approval was pending — denied fail-closed ` +
@@ -544,7 +569,7 @@ export function createApprovalPolicy(opts) {
544
569
  return attest({ action: "deny", message: `approval denied for "${req.toolName}"` }, settledByDecider("person", "refused", undefined));
545
570
  }
546
571
  if (nameListHolds(auto, req) || namespacedCoveringHit(autoCovering, req))
547
- return ALLOW_BY_RULE;
572
+ return ALLOW;
548
573
  if (opts.denyByDefault) {
549
574
  return { action: "deny", message: `tool "${req.toolName}" requires explicit allow` };
550
575
  }
@@ -587,7 +612,6 @@ export function combinePolicies(...policies) {
587
612
  let asked;
588
613
  let current = Object.freeze({ ...req });
589
614
  let rewrite;
590
- let stated;
591
615
  let records;
592
616
  let ruleAskText;
593
617
  let probeMandateSeen = false;
@@ -612,13 +636,8 @@ export function combinePolicies(...policies) {
612
636
  continue;
613
637
  }
614
638
  if (d.updatedInput !== undefined) {
615
- const reread = withArgsReading(current, d.updatedInput, signal);
616
- current = Object.freeze(reread !== undefined ? await reread : { ...current, args: d.updatedInput });
639
+ current = Object.freeze(await withArgsReading(current, d.updatedInput, signal));
617
640
  rewrite = d;
618
- stated = d.action === "allow" ? d.decisionReason : undefined;
619
- }
620
- else if (d.action === "allow" && stated === undefined && d.decisionReason !== undefined) {
621
- stated = d.decisionReason;
622
641
  }
623
642
  if (d.action === "allow" && d.attestation !== undefined)
624
643
  records = mergeAttestation(req, records, d.attestation);
@@ -663,8 +682,7 @@ export function combinePolicies(...policies) {
663
682
  const out = merged !== undefined ? { ...withClasses, updatedInput: merged } : withClasses;
664
683
  return folded.size > 0 ? attest(out, req, { foldedClasses: [...folded] }) : out;
665
684
  }
666
- const base = rewrite ?? ALLOW;
667
- const allowed = stated !== undefined && base.decisionReason !== stated ? { ...base, decisionReason: stated } : base;
685
+ const allowed = rewrite ?? ALLOW;
668
686
  return records === undefined ? allowed : { ...allowed, attestation: records };
669
687
  },
670
688
  };
@@ -714,7 +732,7 @@ export function createCoarseCommandNamePolicy(opts) {
714
732
  if (allow && !allow.has(parsed.name)) {
715
733
  return fallback(`command "${parsed.name}" is not in the allowlist`);
716
734
  }
717
- return allow ? ALLOW_BY_RULE : ALLOW;
735
+ return ALLOW;
718
736
  },
719
737
  }, "sandbox_local");
720
738
  }
@@ -900,7 +918,7 @@ export function refusalOf(deny, judged) {
900
918
  export function foldHookAsk(verdict, hookAsk) {
901
919
  if (verdict.action === "deny")
902
920
  return verdict;
903
- const mandate = hookAsk.requiresRealApproval === true ? { requiresRealApproval: true } : {};
921
+ const mandate = { ...(hookAsk.requiresRealApproval === true ? { requiresRealApproval: true } : {}), ...(hookAsk.crossBoundaryMandated === true ? { crossBoundaryMandated: true } : {}) };
904
922
  if (verdict.action === "allow") {
905
923
  return { action: "ask", ...(hookAsk.message !== undefined ? { message: hookAsk.message } : {}), decisionReason: "hook", ...mandate, ...(hookAsk.updatedInput !== undefined ? { updatedInput: hookAsk.updatedInput } : {}) };
906
924
  }
@@ -915,6 +933,13 @@ export function ownArgs(v, root = "args") {
915
933
  const copy = tryCloneArgs(v);
916
934
  return copy.ok ? ownedCopy(copy.value, root) : { ...copy, reason: `unclonable value: ${copy.reason}` };
917
935
  }
936
+ export function ownedReading(read) {
937
+ return (args) => {
938
+ const out = read(args);
939
+ const owned = ownArgs(out);
940
+ return owned.ok ? owned.value : out;
941
+ };
942
+ }
918
943
  function ownedCopy(fresh, root) {
919
944
  const pending = [[fresh, root]];
920
945
  for (let next = pending.pop(); next !== undefined; next = pending.pop()) {
@@ -1071,12 +1096,12 @@ export function carriesBidiControls(value, limits) {
1071
1096
  }
1072
1097
  }
1073
1098
  export async function resolveAsk(req, onAsk, signal, onLateSettlement) {
1074
- const askedDigest = boundInputHashOf(req.args);
1075
- const { settlement, ...r } = await resolveAskArms(req, onAsk, signal, onLateSettlement);
1099
+ const askedDigest = exactBoundInputHashOf(req.args);
1100
+ const { settlement, bindingRefusal, ...r } = await resolveAskArms(req, onAsk, signal, onLateSettlement);
1076
1101
  if (settlement === undefined)
1077
1102
  return r;
1078
- const licensedDigest = r.action === "allow" && r.updatedInput !== undefined ? boundInputHashOf(r.updatedInput) : r.presentedInput !== undefined ? boundInputHashOf(r.presentedInput) : askedDigest;
1079
- return attest(r, req, { settlement, ...(req.origin !== undefined ? { origin: req.origin } : {}), ...(req.classes !== undefined ? { classes: req.classes } : {}), inputDigest: licensedDigest });
1103
+ const licensedDigest = r.action === "allow" && r.updatedInput !== undefined ? exactBoundInputHashOf(r.updatedInput) : r.presentedInput !== undefined ? exactBoundInputHashOf(r.presentedInput) : askedDigest;
1104
+ return attest(r, req, { settlement, ...(req.origin !== undefined ? { origin: req.origin } : {}), ...(req.classes !== undefined ? { classes: req.classes } : {}), ...(licensedDigest !== undefined ? { inputDigest: licensedDigest } : {}), ...(bindingRefusal !== undefined ? { bindingRefusal } : {}) });
1080
1105
  }
1081
1106
  function raceAskWaitAgainstSignal(wait, signal) {
1082
1107
  const settledWait = wait.then((value) => ({ tag: "value", value }), (error) => ({ tag: "threw", error }));
@@ -1192,10 +1217,9 @@ function readApproverOutcomeObject(ok, toolName, editLane) {
1192
1217
  `re-adjudication an approver's edit gets; denied fail-closed (approve or refuse what was shown, and route edits ` +
1193
1218
  `through the run's approver seat)`, settledByNobody("approver_contract"));
1194
1219
  }
1195
- const edit = ownArgs(suppliedEdit);
1196
- if (!edit.ok) {
1197
- return refused(`the approved edit for "${toolName}" is not safely clonable (${edit.reason}) — denied fail-closed`, settledByNobody("presentation_failed"));
1198
- }
1220
+ const edit = bindableArgsOf(toolName, suppliedEdit);
1221
+ if (!edit.ok)
1222
+ return { kind: "refused", message: edit.refusal, settlement: settledByNobody("presentation_failed"), binding: true };
1199
1223
  return { kind: "allow", edit: { value: edit.value }, settlement: settledByDecider(decider, "allowed", attribution.approver), grant };
1200
1224
  }
1201
1225
  async function resolveAskArms(req, onAsk, signal, onLateSettlement) {
@@ -1205,37 +1229,25 @@ async function resolveAskArms(req, onAsk, signal, onLateSettlement) {
1205
1229
  return { action: "allow", decisionReason: "mode" };
1206
1230
  }
1207
1231
  if (onAsk === undefined || onAsk === "deny") {
1232
+ const bound = bindableArgsOf(req.toolName, req.args);
1208
1233
  return {
1209
1234
  action: "deny",
1210
- message: headlessDenialMessage(req.toolName, req.message),
1235
+ message: bound.ok ? headlessDenialMessage(req.toolName, req.message) : bound.refusal,
1211
1236
  decisionReason: "mode",
1212
1237
  settlement: settledByNobody("no_approver"),
1238
+ ...(bound.ok ? {} : { bindingRefusal: bound.refusal }),
1213
1239
  };
1214
1240
  }
1215
1241
  if (signal?.aborted) {
1216
1242
  return { action: "deny", message: `approval aborted for "${req.toolName}" (run or turn interrupted)`, decisionReason: "mode", settlement: settledByNobody("task_aborted") };
1217
1243
  }
1218
- const presented = ownArgs(req.args);
1219
- if (!presented.ok) {
1220
- return {
1221
- action: "deny",
1222
- message: `approval for "${req.toolName}" could not present the args safely (${presented.reason}) — denied fail-closed`,
1223
- decisionReason: "mode",
1224
- settlement: settledByNobody("presentation_failed"),
1225
- };
1226
- }
1244
+ const presented = bindableArgsOf(req.toolName, req.args);
1245
+ if (!presented.ok)
1246
+ return { action: "deny", message: presented.refusal, decisionReason: "mode", settlement: settledByNobody("presentation_failed"), bindingRefusal: presented.refusal };
1227
1247
  const offered = ownReadRootCandidate(req.readRootCandidate);
1228
1248
  let ok;
1229
1249
  try {
1230
- const approverView = tryCloneArgs(presented.value);
1231
- if (!approverView.ok) {
1232
- return {
1233
- action: "deny",
1234
- message: `approval for "${req.toolName}" could not present the args safely (unclonable value: ${approverView.reason}) — denied fail-closed`,
1235
- decisionReason: "mode",
1236
- settlement: settledByNobody("presentation_failed"),
1237
- };
1238
- }
1250
+ const approverView = { value: structuredClone(presented.value) };
1239
1251
  const bidi = carriesBidiControls(presented.value) || carriesBidiControls(req.preview);
1240
1252
  const { hasBidiControls: _carried, ...bare } = req;
1241
1253
  const wait = Promise.resolve(onAsk({
@@ -1289,7 +1301,7 @@ async function resolveAskArms(req, onAsk, signal, onLateSettlement) {
1289
1301
  if (typeof ok === "object" && ok !== null) {
1290
1302
  const reading = readApproverOutcomeObject(ok, req.toolName, "readjudicated");
1291
1303
  if (reading.kind === "refused")
1292
- return { action: "deny", message: reading.message, decisionReason: "mode", settlement: reading.settlement };
1304
+ return { action: "deny", message: reading.message, decisionReason: "mode", settlement: reading.settlement, ...(reading.binding === true ? { bindingRefusal: reading.message } : {}) };
1293
1305
  if (reading.kind === "allow" && reading.settlement.who.party === "policy" && req.requiresRealApproval === true) {
1294
1306
  return { ...unjudgedAllowRefused(req, "policy"), ...readRootGrantSeat(reading.grant, offered, false) };
1295
1307
  }
@@ -2,6 +2,7 @@ import { Type, type Static, type TSchema } from "typebox";
2
2
  import type { AgentTool } from "../internal/harness-types.js";
3
3
  import { type ReservedApprovalCard, type ToolApprovalCard, type ToolFamily, type ToolRosterPathTarget, type ToolMountTag, type ToolPathTarget, type ToolRenderHints, type ToolRuleFace } from "./tool-face.js";
4
4
  import type { ToolContentOrigin, ToolEffect } from "./tool-spec.js";
5
+ import type { ToolMarkSource } from "./ask-origin.js";
5
6
  export declare const ROSTER_SOURCES: readonly ["builtin", "caller", "host", "mcp", "a2a", "external", "synthetic"];
6
7
  export type RosterSource = (typeof ROSTER_SOURCES)[number];
7
8
  export declare const ToolRosterRenderHints: Type.TObject<{
@@ -50,6 +51,9 @@ export declare const ToolRosterEntry: Type.TObject<{
50
51
  contentOrigin: Type.TUnion<[Type.TLiteral<"local">, Type.TLiteral<"execution">, Type.TLiteral<"external">]>;
51
52
  contentOriginProvenance: Type.TUnion<[Type.TLiteral<"declared">, Type.TLiteral<"server">, Type.TLiteral<"exempted">, Type.TLiteral<"default">]>;
52
53
  family: Type.TUnion<[Type.TLiteral<"shell">, Type.TLiteral<"file-read">, Type.TLiteral<"file-write">, Type.TLiteral<"search">, Type.TLiteral<"web">, Type.TLiteral<"delegate">, Type.TLiteral<"plan">, Type.TLiteral<"scaffold">, Type.TLiteral<"memory">, Type.TLiteral<"protocol">, Type.TLiteral<"other">]>;
54
+ /** The legs a call of this tool travels (`BOUNDARY_LEGS`), or `"per_call"` when its dispatch gives them per call: the engine's own
55
+ * definitions and the protocol tools state them, every other row follows its `effect` (`rosterBoundaryLegs`). */
56
+ boundaryLegs: Type.TUnion<[Type.TLiteral<"per_call">, Type.TArray<Type.TUnion<[Type.TLiteral<"env">, Type.TLiteral<"outside_read">, Type.TLiteral<"outside_write">]>>]>;
53
57
  pathTarget: Type.TOptional<Type.TObject<{
54
58
  param: Type.TString;
55
59
  aliases: Type.TArray<Type.TString>;
@@ -124,6 +128,9 @@ export declare const ToolRoster: Type.TObject<{
124
128
  contentOrigin: Type.TUnion<[Type.TLiteral<"local">, Type.TLiteral<"execution">, Type.TLiteral<"external">]>;
125
129
  contentOriginProvenance: Type.TUnion<[Type.TLiteral<"declared">, Type.TLiteral<"server">, Type.TLiteral<"exempted">, Type.TLiteral<"default">]>;
126
130
  family: Type.TUnion<[Type.TLiteral<"shell">, Type.TLiteral<"file-read">, Type.TLiteral<"file-write">, Type.TLiteral<"search">, Type.TLiteral<"web">, Type.TLiteral<"delegate">, Type.TLiteral<"plan">, Type.TLiteral<"scaffold">, Type.TLiteral<"memory">, Type.TLiteral<"protocol">, Type.TLiteral<"other">]>;
131
+ /** The legs a call of this tool travels (`BOUNDARY_LEGS`), or `"per_call"` when its dispatch gives them per call: the engine's own
132
+ * definitions and the protocol tools state them, every other row follows its `effect` (`rosterBoundaryLegs`). */
133
+ boundaryLegs: Type.TUnion<[Type.TLiteral<"per_call">, Type.TArray<Type.TUnion<[Type.TLiteral<"env">, Type.TLiteral<"outside_read">, Type.TLiteral<"outside_write">]>>]>;
127
134
  pathTarget: Type.TOptional<Type.TObject<{
128
135
  param: Type.TString;
129
136
  aliases: Type.TArray<Type.TString>;
@@ -206,6 +213,9 @@ export declare const ToolRosterDelta: Type.TObject<{
206
213
  contentOrigin: Type.TUnion<[Type.TLiteral<"local">, Type.TLiteral<"execution">, Type.TLiteral<"external">]>;
207
214
  contentOriginProvenance: Type.TUnion<[Type.TLiteral<"declared">, Type.TLiteral<"server">, Type.TLiteral<"exempted">, Type.TLiteral<"default">]>;
208
215
  family: Type.TUnion<[Type.TLiteral<"shell">, Type.TLiteral<"file-read">, Type.TLiteral<"file-write">, Type.TLiteral<"search">, Type.TLiteral<"web">, Type.TLiteral<"delegate">, Type.TLiteral<"plan">, Type.TLiteral<"scaffold">, Type.TLiteral<"memory">, Type.TLiteral<"protocol">, Type.TLiteral<"other">]>;
216
+ /** The legs a call of this tool travels (`BOUNDARY_LEGS`), or `"per_call"` when its dispatch gives them per call: the engine's own
217
+ * definitions and the protocol tools state them, every other row follows its `effect` (`rosterBoundaryLegs`). */
218
+ boundaryLegs: Type.TUnion<[Type.TLiteral<"per_call">, Type.TArray<Type.TUnion<[Type.TLiteral<"env">, Type.TLiteral<"outside_read">, Type.TLiteral<"outside_write">]>>]>;
209
219
  pathTarget: Type.TOptional<Type.TObject<{
210
220
  param: Type.TString;
211
221
  aliases: Type.TArray<Type.TString>;
@@ -281,15 +291,10 @@ export declare function approvalCardMemberOf(call: {
281
291
  * other aliases — the ONE order of a call's names: a reader that must pick one of them by position (a `member` seat)
282
292
  * picks the spelling first, as the same call was judged before name resolution. */
283
293
  export declare function toolCallFaceOf(roster: ToolRoster | undefined, toolName: string): import("./tool-policy.js").ToolCallFace | undefined;
284
- /** design/388 B18 — the identity members a park row carries, read off a roster snapshot by name; an empty object when
285
- * the name is not on the snapshot (the row then reads pre-identity and the resume takes the name-only path). */
286
- export declare function parkedToolIdentity(roster: ToolRoster | undefined, toolName: string): {
287
- capabilityId?: string;
288
- contractId?: string;
289
- shapeDigest?: string;
290
- implementationRevision?: string;
291
- rosterDigest?: string;
292
- };
294
+ /** design/388 B18 — the identity members a park row carries (the tool member of its approval object,
295
+ * `approval-object.ts`), read off a roster snapshot by name; an empty object when the name is not on the snapshot
296
+ * (the row then reads pre-identity and the resume binds the name alone). */
297
+ export declare function parkedToolIdentity(roster: ToolRoster | undefined, toolName: string): Partial<ToolIdentity>;
293
298
  /** design/388 B6 × B18 — the FACE members a park row carries beside its identity: the display family, the declared
294
299
  * path target and the names the parked call was judged under. `names` is copied from the face the gate stamped on the
295
300
  * request (the model's spelling first — the row carries the judged fact, it is not re-derived); a request with no face
@@ -375,7 +380,7 @@ export type RosterBoundCode = "config.tool_name_too_long" | "config.tool_contrac
375
380
  * undefined when every member fits. Read by the declaration door (a `TaskSpec.tools` entry, refused before session
376
381
  * acquire) and by the row mint (every source — an MCP/A2A peer, a definition that reached the mint by a route the
377
382
  * door does not cover — refused before the row exists). A member over its bound is NEVER truncated onto the row: a
378
- * truncated identity is a different identity (`judgeParkedToolIdentity` compares it across a park; the card
383
+ * truncated identity is a different identity (`judgeApprovalObject` compares it across a park; the card
379
384
  * namespace door reads it), and the schema's own bounds would then describe a row the mint never made.
380
385
  */
381
386
  export declare function rosterMemberBoundProblem(m: RosterBoundMembers): {
@@ -427,6 +432,7 @@ export interface MountedToolFace {
427
432
  compactable?: true;
428
433
  budgetExempt?: true;
429
434
  modelGate?: string;
435
+ boundaryLegs?: unknown;
430
436
  }
431
437
  export declare const faceOf: (t: AgentTool) => MountedToolFace;
432
438
  /** The leg facts the snapshot reads beside the instances — the safety scan's folds and the per-task knobs. */
@@ -441,20 +447,32 @@ export interface RosterSnapshotFacts {
441
447
  /** `TaskSpec.memory.trustedTools` — the exemption channel for an undeclared content class. */
442
448
  trustedTools: ReadonlySet<string>;
443
449
  }
450
+ /** The leg's per-name safety-axis tables the builder keeps aligned with its mounts beside the effect map (the safety scan mints
451
+ * them; the protocol folds and the shell seat also write them). */
452
+ export interface RosterAxisTables {
453
+ irreversibilityTier: Map<string, "never" | "maybe" | "always">;
454
+ irreversibleTools: Set<string>;
455
+ reversibilityProbes: Map<string, unknown>;
456
+ egressTools: Set<string>;
457
+ toolMarkSources: Map<string, Set<ToolMarkSource>>;
458
+ }
444
459
  export declare class RosterBuilder {
445
460
  #private;
446
- constructor(effects: Map<string, ToolEffect>);
461
+ /** `axes` — the leg's safety-axis tables beside the effect map (a builder for a single probe tool may go without). */
462
+ constructor(effects: Map<string, ToolEffect>, axes?: RosterAxisTables);
447
463
  /** The mount array as a READ face. The order is the wire order. */
448
464
  get tools(): readonly AgentTool[];
449
465
  get length(): number;
450
466
  metaOf(tool: AgentTool): RosterMountMeta | undefined;
451
467
  /** Mount one instance at the tail. An engine-lane instance that DECLARES an effect writes it into the leg's effect
452
468
  * map — the later mount under a name is the one the harness dispatches to (`snapshot`'s yield rule), so its
453
- * declaration is the map's truth for that name; a pre-mount registration (the hand band, the plan pair, an
454
- * MCP axis) stands only for names no mounted instance declares. The `scenario` lane never writes the map: its
469
+ * declaration is the map's truth for that name — an engine tool's effect reaches the map from its own declaration, here at its
470
+ * mount (nothing writes it by name beforehand; a protocol axis fills a name no mounted instance declares, and the gate's
471
+ * post-assembly sync a kept instance the map still lacks). The `scenario` lane never writes the map: its
455
472
  * declarations were latched by the safety scan BEFORE any mount (on the kept instance of each name, on the
456
473
  * synchronous doors+scan stretch — a microtask cannot flip them), so a scenario mount, kept or dropped, leaves
457
- * the map as the scan made it; an engine lane's mount under that name still displaces it. */
474
+ * the map as the scan made it; an engine lane's mount under that name still displaces it, and the aliases the displaced
475
+ * instance answered to move to the member they now resolve to (`#resettleAliases`). */
458
476
  mount(tool: AgentTool, meta: RosterMountMeta): void;
459
477
  /** An ENGINE-INJECTED instance the harness list carries outside the mount array (the ToolSearch lane): a roster
460
478
  * row — the model can call it — never a mount-array element (the disclosure lane owns that list and appends the
@@ -497,6 +515,20 @@ export declare function rosterCardId(source: RosterSource, toolName: string, pee
497
515
  /** The card namespace a `TaskSpec.tools` entry will own once mounted — the same mint the row makes, so the prepare
498
516
  * door and the roster row cannot disagree about which namespace a caller card must live under. */
499
517
  export declare function callerCardIdOf(tool: Pick<AgentTool, "name" | "parameters">): string;
518
+ /** The protocol segment of a mounted protocol tool's name (`mcp__srv__write_file` ⇒ `write_file`): the name itself when no protocol owns it.
519
+ * ONE reading, asked by the row's mint below and by the judge that holds an MCP face's cards to the namespace that row will own. */
520
+ export declare function protocolToolOf(toolName: string): string;
521
+ /** The refusal of a `boundaryLegs` declaration that is not one — the ONE sentence the roster's declaration door and the row mint both
522
+ * throw (`config.tool_face_invalid`, the code a caller tool's bad face has). */
523
+ export declare function boundaryLegsRefusal(toolName: unknown): Error & {
524
+ code: string;
525
+ };
526
+ /** The judge of a caller roster's `boundaryLegs` where the roster enters, every entry the caller handed, mounted or not: the config-door
527
+ * phase over the snapshot's faces and a resume's screen before its claim over the entries it is handed (one function, so the row stays
528
+ * pending). A declaration that is not one is refused. Not judged here — the snapshot reads it, and only by running the caller's code:
529
+ * an entry or a list of another prototype (its prototype chain answers), a Proxy, an accessor (or a non-enumerable member the receipt
530
+ * does not take) as the name, the declaration or a slot of the list. The row mint judges every other source. */
531
+ export declare function assertToolBoundaryLegs(tools: unknown): void;
500
532
  /** One row (design/388 §2.5). Every axis is read off the instance or the leg facts; nothing off a name table. */
501
533
  export declare function mintRosterEntry(tool: AgentTool, meta: RosterMountMeta, facts: RosterSnapshotFacts): ToolRosterEntry;
502
534
  /**
@@ -533,20 +565,6 @@ export declare function ruleFacesFromRoster(roster: ToolRoster): (toolName: stri
533
565
  } | undefined;
534
566
  /** The delta between two snapshots (design/388 §2.5): the whole `next` roster plus the name summary. */
535
567
  export declare function diffToolRoster(prev: ToolRoster, next: ToolRoster): ToolRosterDelta;
536
- /**
537
- * The resume-side identity judgement (design/388 §2.5 boundary ②, B18/B19): a parked action carrying the
538
- * four identity members is redeemed only against a same-name row whose four members ALL match; a row
539
- * whose contract / shape / revision / source-peer moved is a replacement wearing the name, and the
540
- * resume refuses it (`resume.tool_contract_mismatch`, same family and disposition as
541
- * `resume.tool_unavailable`). A parked action minted BEFORE the identity members existed (all four absent)
542
- * follows the name-only path and is never widened by their absence.
543
- */
544
- export declare function judgeParkedToolIdentity(pending: {
545
- capabilityId?: string;
546
- contractId?: string;
547
- shapeDigest?: string;
548
- implementationRevision?: string;
549
- }, row: ToolRosterEntry | undefined): "match" | "mismatch" | "name_only" | "absent";
550
568
  /** The card-namespace check a CALLER declaration must pass at prepare (design/388 §2.2 ④): a `resultCards`
551
569
  * entry must live under the tool's own `cardId`; naming an engine card (`builtin:*`, or a bare engine card
552
570
  * type) is refused. Returns the offending entry, or undefined. */