@sema-agent/core 7.54.1 → 7.56.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 (621) hide show
  1. package/CHANGELOG.md +950 -0
  2. package/dist/agents/agent-transcript-tool.js +2 -1
  3. package/dist/agents/builtin-agents.d.ts +12 -14
  4. package/dist/agents/cascade.js +1 -1
  5. package/dist/agents/cc-peer-directory.d.ts +36 -0
  6. package/dist/agents/cc-peer-directory.js +139 -0
  7. package/dist/agents/cc-peer-wire.d.ts +105 -0
  8. package/dist/agents/cc-peer-wire.js +98 -0
  9. package/dist/agents/cc-uds-peer-channel.d.ts +40 -0
  10. package/dist/agents/cc-uds-peer-channel.js +457 -0
  11. package/dist/agents/child-model-seat.d.ts +0 -11
  12. package/dist/agents/child-model-seat.js +0 -3
  13. package/dist/agents/cross-session-envelope.d.ts +4 -1
  14. package/dist/agents/cross-session-envelope.js +8 -1
  15. package/dist/agents/cross-session-judge.d.ts +2 -2
  16. package/dist/agents/list-agents-tool.d.ts +3 -1
  17. package/dist/agents/list-agents-tool.js +9 -8
  18. package/dist/agents/observer.d.ts +4 -5
  19. package/dist/agents/observer.js +2 -1
  20. package/dist/agents/peer-admission.d.ts +6 -0
  21. package/dist/agents/peer-admission.js +4 -1
  22. package/dist/agents/peer-directory.d.ts +65 -13
  23. package/dist/agents/peer-directory.js +90 -25
  24. package/dist/agents/peer-notices.d.ts +1 -1
  25. package/dist/agents/peer-session-drain.d.ts +3 -1
  26. package/dist/agents/peer-session-drain.js +3 -2
  27. package/dist/agents/read-inbox-tool.js +2 -1
  28. package/dist/agents/repair-loop.js +2 -2
  29. package/dist/agents/retain-ledger.d.ts +1 -1
  30. package/dist/agents/roster-store.d.ts +1 -1
  31. package/dist/agents/send-message-tool.d.ts +10 -0
  32. package/dist/agents/send-message-tool.js +37 -8
  33. package/dist/agents/subagent.d.ts +39 -82
  34. package/dist/agents/subagent.js +109 -106
  35. package/dist/agents/tool-filter.d.ts +31 -46
  36. package/dist/agents/tool-filter.js +13 -33
  37. package/dist/agents/verify.d.ts +6 -5
  38. package/dist/agents/verify.js +3 -3
  39. package/dist/brain/anthropic.js +43 -81
  40. package/dist/brain/errors.d.ts +15 -0
  41. package/dist/brain/errors.js +10 -0
  42. package/dist/brain/media-degrade.d.ts +18 -7
  43. package/dist/brain/media-degrade.js +13 -2
  44. package/dist/brain/model-capability.d.ts +37 -0
  45. package/dist/brain/model-capability.js +34 -0
  46. package/dist/brain/model-presets.d.ts +6 -12
  47. package/dist/brain/model-presets.js +1 -6
  48. package/dist/brain/open-responses.js +27 -35
  49. package/dist/brain/openai.js +30 -98
  50. package/dist/brain/provider-dialect.d.ts +39 -3
  51. package/dist/brain/provider-dialect.js +28 -0
  52. package/dist/brain/reasoning-request.d.ts +96 -0
  53. package/dist/brain/reasoning-request.js +174 -0
  54. package/dist/brain/reasoning.d.ts +12 -12
  55. package/dist/brain/reasoning.js +4 -3
  56. package/dist/brain/request-params.d.ts +62 -9
  57. package/dist/brain/request-params.js +42 -7
  58. package/dist/brain/retry.d.ts +1 -1
  59. package/dist/brain/route-adjudicator.d.ts +15 -0
  60. package/dist/brain/route-adjudicator.js +15 -0
  61. package/dist/brain/status-sink.d.ts +20 -0
  62. package/dist/brain/status-sink.js +7 -0
  63. package/dist/brain/stream-engine.js +6 -5
  64. package/dist/brain/stream-shared.d.ts +1 -1
  65. package/dist/core/a2a.d.ts +2 -1
  66. package/dist/core/a2a.js +19 -13
  67. package/dist/core/advisor-verdict.d.ts +120 -0
  68. package/dist/core/advisor-verdict.js +92 -0
  69. package/dist/core/agent-definition.d.ts +17 -8
  70. package/dist/core/allow-entry.d.ts +69 -36
  71. package/dist/core/allow-entry.js +81 -52
  72. package/dist/core/allow-rule-shadow.d.ts +10 -3
  73. package/dist/core/approval-object.d.ts +2 -1
  74. package/dist/core/approval-object.js +6 -6
  75. package/dist/core/ask-origin.d.ts +127 -29
  76. package/dist/core/ask-origin.js +87 -25
  77. package/dist/core/ask-question.d.ts +51 -8
  78. package/dist/core/ask-question.js +12 -7
  79. package/dist/core/ask-unresolvable-notice.d.ts +8 -3
  80. package/dist/core/ask-unresolvable-notice.js +16 -2
  81. package/dist/core/auto-compaction.d.ts +11 -8
  82. package/dist/core/auto-compaction.js +4 -2
  83. package/dist/core/auto-mode-arming.d.ts +2 -2
  84. package/dist/core/auto-mode-defaults.d.ts +8 -8
  85. package/dist/core/auto-mode-prompt-assets.d.ts +3 -3
  86. package/dist/core/auto-mode-prompt.d.ts +1 -1
  87. package/dist/core/auto-mode.d.ts +17 -9
  88. package/dist/core/auto-mode.js +9 -6
  89. package/dist/core/background-agent-store.d.ts +3 -3
  90. package/dist/core/canonical-json.d.ts +1 -1
  91. package/dist/core/canonical-json.js +2 -2
  92. package/dist/core/checkpoint-generation.d.ts +53 -0
  93. package/dist/core/checkpoint-generation.js +35 -0
  94. package/dist/core/checkpoint-queries.d.ts +180 -0
  95. package/dist/core/checkpoint-queries.js +272 -0
  96. package/dist/core/checkpoint-requirements.d.ts +19 -4
  97. package/dist/core/checkpoint-requirements.js +8 -14
  98. package/dist/core/checkpoint-store.d.ts +165 -72
  99. package/dist/core/checkpoint-store.js +79 -82
  100. package/dist/core/child-clamp-seats.d.ts +6 -0
  101. package/dist/core/child-clamp-seats.js +3 -16
  102. package/dist/core/compliance.d.ts +2 -2
  103. package/dist/core/context-edit.d.ts +6 -7
  104. package/dist/core/cross-boundary-taint.d.ts +11 -4
  105. package/dist/core/cross-boundary-taint.js +3 -3
  106. package/dist/core/decision-receipt.d.ts +37 -3
  107. package/dist/core/decision-receipt.js +19 -19
  108. package/dist/core/delegation-not-started.d.ts +6 -0
  109. package/dist/core/delegation-not-started.js +17 -0
  110. package/dist/core/effective-path-target.d.ts +1 -1
  111. package/dist/core/engine-attestation.d.ts +93 -0
  112. package/dist/core/engine-attestation.js +70 -0
  113. package/dist/core/engine-capabilities.d.ts +4 -1
  114. package/dist/core/engine-capabilities.js +1 -1
  115. package/dist/core/engine-notice.d.ts +45 -12
  116. package/dist/core/exec-output-tail.d.ts +1 -1
  117. package/dist/core/file-history-retention.d.ts +1 -1
  118. package/dist/core/file-history-store.d.ts +147 -21
  119. package/dist/core/file-history-store.js +58 -32
  120. package/dist/core/gate-fold.d.ts +1 -1
  121. package/dist/core/gate-fold.js +24 -11
  122. package/dist/core/gate-lanes.js +81 -68
  123. package/dist/core/gate-outcome.d.ts +40 -6
  124. package/dist/core/gate-outcome.js +56 -0
  125. package/dist/core/governance-codes.d.ts +17 -3
  126. package/dist/core/governance-codes.js +16 -0
  127. package/dist/core/hands-band.d.ts +1 -1
  128. package/dist/core/hooks.d.ts +21 -20
  129. package/dist/core/hooks.js +3 -1
  130. package/dist/core/host-floor.d.ts +128 -0
  131. package/dist/core/host-floor.js +206 -0
  132. package/dist/core/host-target.d.ts +84 -0
  133. package/dist/core/host-target.js +92 -0
  134. package/dist/core/image-downsample.d.ts +1 -1
  135. package/dist/core/lsp-diagnostics.d.ts +4 -4
  136. package/dist/core/lsp.d.ts +3 -3
  137. package/dist/core/mailbox-store.d.ts +4 -0
  138. package/dist/core/mcp-connection-pool.d.ts +18 -2
  139. package/dist/core/mcp-connection-pool.js +53 -6
  140. package/dist/core/mcp-failure.d.ts +23 -4
  141. package/dist/core/mcp-failure.js +26 -11
  142. package/dist/core/mcp-listing-drift.d.ts +10 -0
  143. package/dist/core/mcp-listing-drift.js +6 -0
  144. package/dist/core/mcp-server-link.d.ts +173 -0
  145. package/dist/core/mcp-server-link.js +127 -0
  146. package/dist/core/mcp-server-spec.d.ts +4 -2
  147. package/dist/core/mcp-session-end.d.ts +26 -0
  148. package/dist/core/mcp-session-end.js +29 -0
  149. package/dist/core/mcp-startup-request.d.ts +17 -0
  150. package/dist/core/mcp-startup-request.js +17 -0
  151. package/dist/core/mcp.d.ts +17 -13
  152. package/dist/core/mcp.js +240 -189
  153. package/dist/core/media-byte-cap.d.ts +1 -1
  154. package/dist/core/memory-engine/delegation-settlement.js +15 -24
  155. package/dist/core/memory-engine/engine.d.ts +9 -9
  156. package/dist/core/memory-engine/engine.js +4 -4
  157. package/dist/core/memory-engine/layout.d.ts +60 -8
  158. package/dist/core/memory-engine/layout.js +65 -6
  159. package/dist/core/memory-engine/provenance-wording.d.ts +1 -1
  160. package/dist/core/memory-engine/tools.js +4 -1
  161. package/dist/core/mode-policy.d.ts +1 -1
  162. package/dist/core/model-seat.d.ts +10 -3
  163. package/dist/core/mods/classic-events.d.ts +67 -0
  164. package/dist/core/mods/classic-events.js +1 -0
  165. package/dist/core/mods/dollar.d.ts +13 -0
  166. package/dist/core/mods/extension-call.d.ts +31 -0
  167. package/dist/core/mods/extension-call.js +43 -0
  168. package/dist/core/mods/kernel/dispatch.d.ts +20 -3
  169. package/dist/core/mods/kernel/dispatch.js +140 -69
  170. package/dist/core/mods/kernel/events.d.ts +47 -11
  171. package/dist/core/mods/kernel/events.js +66 -42
  172. package/dist/core/mods/kernel/index.d.ts +4 -4
  173. package/dist/core/mods/kernel/index.js +2 -2
  174. package/dist/core/mods/kernel/receive.d.ts +39 -5
  175. package/dist/core/mods/kernel/receive.js +290 -17
  176. package/dist/core/mods/kernel/registration.d.ts +33 -2
  177. package/dist/core/mods/kernel/registration.js +6 -7
  178. package/dist/core/mods/kernel/site-rules.d.ts +44 -16
  179. package/dist/core/mods/kernel/site-rules.js +24 -42
  180. package/dist/core/mods/spec-seats.d.ts +69 -0
  181. package/dist/core/mods/spec-seats.js +114 -0
  182. package/dist/core/mods/stations.d.ts +28 -8
  183. package/dist/core/mods/stations.js +29 -13
  184. package/dist/core/mods/tool-call.d.ts +79 -0
  185. package/dist/core/mods/tool-call.js +152 -0
  186. package/dist/core/namespaced-rule-name.d.ts +44 -24
  187. package/dist/core/namespaced-rule-name.js +50 -43
  188. package/dist/core/output-style.d.ts +1 -1
  189. package/dist/core/param-rule-reach.d.ts +15 -0
  190. package/dist/core/param-rule-reach.js +30 -0
  191. package/dist/core/parent-spec-seat.d.ts +13 -1
  192. package/dist/core/parent-spec-seat.js +6 -0
  193. package/dist/core/park-selfcheck.js +1 -0
  194. package/dist/core/pause-registry.d.ts +16 -5
  195. package/dist/core/pause-registry.js +6 -2
  196. package/dist/core/peer-channel.d.ts +70 -0
  197. package/dist/core/peer-channel.js +1 -0
  198. package/dist/core/permission-rule-consent.d.ts +30 -5
  199. package/dist/core/permission-rule-consent.js +147 -50
  200. package/dist/core/permission-rule-model.d.ts +245 -65
  201. package/dist/core/permission-rule-model.js +421 -107
  202. package/dist/core/permission-rule-org.d.ts +6 -2
  203. package/dist/core/permission-rule-org.js +7 -3
  204. package/dist/core/permission-rule-provider.d.ts +6 -2
  205. package/dist/core/permission-rule-provider.js +41 -11
  206. package/dist/core/permission-rule-store.d.ts +22 -26
  207. package/dist/core/permission-rule-store.js +12 -6
  208. package/dist/core/permission-rule-sync.d.ts +11 -2
  209. package/dist/core/permission-rule-sync.js +11 -3
  210. package/dist/core/permission-rule-syntax.d.ts +5 -4
  211. package/dist/core/permission-rule-syntax.js +2 -2
  212. package/dist/core/permission-rules.d.ts +53 -15
  213. package/dist/core/permission-rules.js +125 -100
  214. package/dist/core/persisted-rule-arms.d.ts +6 -4
  215. package/dist/core/persisted-rule-arms.js +10 -12
  216. package/dist/core/present-plan-tool.js +3 -1
  217. package/dist/core/principal-name.d.ts +20 -0
  218. package/dist/core/principal-name.js +22 -0
  219. package/dist/core/prompt-section-seat.js +4 -6
  220. package/dist/core/protocol-http-auth.d.ts +26 -5
  221. package/dist/core/protocol-http-auth.js +137 -4
  222. package/dist/core/protocol-naming.d.ts +2 -2
  223. package/dist/core/read-only-shell-table.d.ts +1 -1
  224. package/dist/core/read-only-shell.d.ts +1 -1
  225. package/dist/core/retired-keys.d.ts +16 -0
  226. package/dist/core/retired-keys.js +16 -4
  227. package/dist/core/rewrite-rejudge.d.ts +60 -0
  228. package/dist/core/rewrite-rejudge.js +36 -0
  229. package/dist/core/roles.d.ts +34 -3
  230. package/dist/core/roles.js +66 -53
  231. package/dist/core/rule-lane-reads.d.ts +20 -15
  232. package/dist/core/rule-lane-reads.js +45 -17
  233. package/dist/core/rule-offer-read.d.ts +53 -0
  234. package/dist/core/rule-offer-read.js +146 -0
  235. package/dist/core/rule-owner.d.ts +46 -0
  236. package/dist/core/rule-owner.js +29 -0
  237. package/dist/core/runner/advisor-instructions.d.ts +70 -0
  238. package/dist/core/runner/advisor-instructions.js +61 -0
  239. package/dist/core/runner/advisor-tool.d.ts +33 -0
  240. package/dist/core/runner/advisor-tool.js +112 -0
  241. package/dist/core/runner/announce-once-ledger.d.ts +18 -26
  242. package/dist/core/runner/announce-once-ledger.js +19 -46
  243. package/dist/core/runner/approval-feedback.js +6 -3
  244. package/dist/core/runner/assemble-result.d.ts +2 -1
  245. package/dist/core/runner/assemble-result.js +1 -1
  246. package/dist/core/runner/call-hook-stations.d.ts +3 -2
  247. package/dist/core/runner/caller-roster.d.ts +21 -2
  248. package/dist/core/runner/caller-roster.js +38 -0
  249. package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
  250. package/dist/core/runner/capability-withheld-seat.js +24 -0
  251. package/dist/core/runner/classifier-ladder.d.ts +33 -13
  252. package/dist/core/runner/classifier-ladder.js +15 -14
  253. package/dist/core/runner/compaction-restate.d.ts +10 -6
  254. package/dist/core/runner/compaction-restate.js +9 -3
  255. package/dist/core/runner/construction-doors.js +3 -0
  256. package/dist/core/runner/contracts.d.ts +40 -33
  257. package/dist/core/runner/conversation-segment.d.ts +28 -0
  258. package/dist/core/runner/conversation-segment.js +42 -0
  259. package/dist/core/runner/cross-boundary-lane.d.ts +21 -16
  260. package/dist/core/runner/cross-boundary-lane.js +58 -34
  261. package/dist/core/runner/decide-continuation.d.ts +7 -4
  262. package/dist/core/runner/decide-continuation.js +2 -2
  263. package/dist/core/runner/denial-limit-arms.d.ts +4 -4
  264. package/dist/core/runner/denial-limit-arms.js +1 -1
  265. package/dist/core/runner/derived-route-fallback.d.ts +24 -24
  266. package/dist/core/runner/derived-route-fallback.js +9 -7
  267. package/dist/core/runner/file-history-request.d.ts +18 -0
  268. package/dist/core/runner/file-history-request.js +21 -13
  269. package/dist/core/runner/file-history-restore.d.ts +45 -0
  270. package/dist/core/runner/file-history-restore.js +46 -0
  271. package/dist/core/runner/gate-exit.d.ts +9 -3
  272. package/dist/core/runner/gate-exit.js +11 -5
  273. package/dist/core/runner/image.d.ts +7 -17
  274. package/dist/core/runner/image.js +9 -60
  275. package/dist/core/runner/initial-run-state.js +1 -1
  276. package/dist/core/runner/permission-rule-lanes.d.ts +6 -6
  277. package/dist/core/runner/permission-rule-lanes.js +38 -15
  278. package/dist/core/runner/person-path-rows.d.ts +12 -9
  279. package/dist/core/runner/person-path-rows.js +19 -8
  280. package/dist/core/runner/prepare-advisor.d.ts +63 -0
  281. package/dist/core/runner/prepare-advisor.js +77 -0
  282. package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
  283. package/dist/core/runner/prepare-ask-lane.js +5 -2
  284. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
  285. package/dist/core/runner/prepare-caps-and-workflow.js +5 -4
  286. package/dist/core/runner/prepare-config-doors.d.ts +31 -38
  287. package/dist/core/runner/prepare-config-doors.js +57 -34
  288. package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
  289. package/dist/core/runner/prepare-defer-classify.js +7 -8
  290. package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
  291. package/dist/core/runner/prepare-delegation-surface.js +1 -1
  292. package/dist/core/runner/prepare-file-history.d.ts +48 -8
  293. package/dist/core/runner/prepare-file-history.js +41 -73
  294. package/dist/core/runner/prepare-gate-stations.d.ts +2 -5
  295. package/dist/core/runner/prepare-gate-stations.js +12 -8
  296. package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
  297. package/dist/core/runner/prepare-hands-readface.js +15 -14
  298. package/dist/core/runner/prepare-inherited-gate.d.ts +11 -7
  299. package/dist/core/runner/prepare-inherited-gate.js +8 -6
  300. package/dist/core/runner/prepare-memory-engine-session.js +1 -1
  301. package/dist/core/runner/prepare-park-ask.js +12 -12
  302. package/dist/core/runner/prepare-policy-chain.d.ts +7 -4
  303. package/dist/core/runner/prepare-policy-chain.js +68 -81
  304. package/dist/core/runner/prepare-project-context.d.ts +5 -2
  305. package/dist/core/runner/prepare-project-context.js +6 -3
  306. package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
  307. package/dist/core/runner/prepare-prompt-assembly.js +10 -8
  308. package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
  309. package/dist/core/runner/prepare-prompt-inputs.js +4 -6
  310. package/dist/core/runner/prepare-protocol-tools.d.ts +4 -2
  311. package/dist/core/runner/prepare-protocol-tools.js +5 -4
  312. package/dist/core/runner/prepare-safety-scan.d.ts +9 -12
  313. package/dist/core/runner/prepare-safety-scan.js +8 -23
  314. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
  315. package/dist/core/runner/prepare-suspend-saga.js +5 -6
  316. package/dist/core/runner/prepare-task.d.ts +1 -1
  317. package/dist/core/runner/prepare-task.js +41 -35
  318. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
  319. package/dist/core/runner/prepare-tool-disclosure-mount.js +24 -18
  320. package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
  321. package/dist/core/runner/prepare-turn-wiring.js +2 -7
  322. package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -4
  323. package/dist/core/runner/prepare-wiring-manifest.js +3 -3
  324. package/dist/core/runner/resume-admission.js +1 -1
  325. package/dist/core/runner/resume-apply.js +11 -12
  326. package/dist/core/runner/resume-checkpoint-screen.js +3 -0
  327. package/dist/core/runner/resume-claim.d.ts +4 -2
  328. package/dist/core/runner/resume-claim.js +15 -8
  329. package/dist/core/runner/resume-policy-outcome.js +1 -1
  330. package/dist/core/runner/retired-runner-deps.js +2 -1
  331. package/dist/core/runner/rewind-files.d.ts +15 -0
  332. package/dist/core/runner/rewind-files.js +132 -0
  333. package/dist/core/runner/run-attachment-seats.js +2 -2
  334. package/dist/core/runner/run-brain-sinks.d.ts +4 -1
  335. package/dist/core/runner/run-brain-sinks.js +4 -2
  336. package/dist/core/runner/run-compaction-machinery.d.ts +1 -1
  337. package/dist/core/runner/run-compaction-machinery.js +2 -12
  338. package/dist/core/runner/run-git-lane.d.ts +1 -0
  339. package/dist/core/runner/run-harness-handlers.js +14 -7
  340. package/dist/core/runner/run-leg.d.ts +1 -1
  341. package/dist/core/runner/run-leg.js +43 -18
  342. package/dist/core/runner/run-settle-and-teardown.js +3 -2
  343. package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
  344. package/dist/core/runner/run-turn-boundary.d.ts +1 -0
  345. package/dist/core/runner/run-turn-boundary.js +15 -22
  346. package/dist/core/runner/runtask.d.ts +3 -0
  347. package/dist/core/runner/runtask.js +8 -9
  348. package/dist/core/runner/session-read-file-states.d.ts +15 -0
  349. package/dist/core/runner/session-read-file-states.js +28 -0
  350. package/dist/core/runner/session-rule-policy.d.ts +22 -21
  351. package/dist/core/runner/session-rule-policy.js +17 -31
  352. package/dist/core/runner/shell-env-withheld.d.ts +33 -0
  353. package/dist/core/runner/shell-env-withheld.js +51 -0
  354. package/dist/core/runner/side-call-account.d.ts +32 -8
  355. package/dist/core/runner/side-call-account.js +23 -1
  356. package/dist/core/runner/skills-seat.js +6 -2
  357. package/dist/core/runner/stream-settle-backstop.js +1 -1
  358. package/dist/core/runner/strict-output-schema.d.ts +1 -1
  359. package/dist/core/runner/sub-agent-deny-lists.js +4 -6
  360. package/dist/core/runner/synthetic-tools.d.ts +16 -13
  361. package/dist/core/runner/synthetic-tools.js +8 -3
  362. package/dist/core/runner/tool-disclosure.d.ts +10 -12
  363. package/dist/core/runner/tool-disclosure.js +3 -4
  364. package/dist/core/runner/tool-end-body.d.ts +1 -1
  365. package/dist/core/runner/tool-end-body.js +10 -9
  366. package/dist/core/runner/tool-face-overlay.d.ts +2 -1
  367. package/dist/core/runner/tool-face-overlay.js +17 -1
  368. package/dist/core/runner/tool-not-executed.d.ts +5 -0
  369. package/dist/core/runner/tool-not-executed.js +11 -0
  370. package/dist/core/runner/tool-occurrence.d.ts +8 -0
  371. package/dist/core/runner/tool-occurrence.js +7 -0
  372. package/dist/core/runner/tool-progress-lane.d.ts +2 -2
  373. package/dist/core/runner/tool-turn-repair-seat.d.ts +3 -2
  374. package/dist/core/runner/turn-attachments.d.ts +91 -80
  375. package/dist/core/runner/turn-attachments.js +62 -37
  376. package/dist/core/runner-deps.d.ts +42 -42
  377. package/dist/core/runtime-caps.d.ts +4 -4
  378. package/dist/core/safety-axis-vocab.d.ts +6 -4
  379. package/dist/core/safety-axis-vocab.js +6 -5
  380. package/dist/core/safety-merge-corpus.js +26 -2
  381. package/dist/core/same-plain-value.d.ts +40 -0
  382. package/dist/core/same-plain-value.js +49 -0
  383. package/dist/core/scheduler.d.ts +1 -1
  384. package/dist/core/secret-env.d.ts +26 -3
  385. package/dist/core/secret-env.js +44 -8
  386. package/dist/core/select-model.js +3 -3
  387. package/dist/core/sensitive-path-policy.d.ts +1 -1
  388. package/dist/core/sensitive-path-policy.js +1 -1
  389. package/dist/core/session-policy-store.d.ts +102 -35
  390. package/dist/core/session-policy-store.js +210 -48
  391. package/dist/core/session-reconcile.d.ts +2 -2
  392. package/dist/core/session-store.d.ts +106 -37
  393. package/dist/core/session-store.js +165 -91
  394. package/dist/core/session.d.ts +101 -57
  395. package/dist/core/session.js +53 -0
  396. package/dist/core/shared-memory/tools.js +3 -1
  397. package/dist/core/shared-memory/types.d.ts +1 -1
  398. package/dist/core/shell-read-silence.d.ts +11 -12
  399. package/dist/core/shell-read-silence.js +9 -5
  400. package/dist/core/shell-run-candidates.js +3 -1
  401. package/dist/core/shell-wrapper-projection.js +1 -1
  402. package/dist/core/shell-wrapper-table.d.ts +14 -7
  403. package/dist/core/shell-wrapper-table.js +5 -4
  404. package/dist/core/side-query.d.ts +10 -0
  405. package/dist/core/side-query.js +15 -1
  406. package/dist/core/skill-grant.d.ts +7 -2
  407. package/dist/core/skill-grant.js +5 -0
  408. package/dist/core/skills-directory.js +6 -2
  409. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
  410. package/dist/core/store-contracts/checkpoint-store-contract.js +168 -3
  411. package/dist/core/store-contracts/file-history-store-contract.js +74 -4
  412. package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
  413. package/dist/core/store-contracts/peer-directory-contract.js +14 -2
  414. package/dist/core/store-contracts/session-policy-store-contract.d.ts +7 -0
  415. package/dist/core/store-contracts/session-policy-store-contract.js +130 -0
  416. package/dist/core/store-contracts/session-repo-contract.js +176 -0
  417. package/dist/core/store-contracts/session-store-contract.d.ts +6 -8
  418. package/dist/core/store-contracts/session-store-contract.js +361 -51
  419. package/dist/core/store-contracts/workflow-journal-store-contract.js +26 -1
  420. package/dist/core/stub-env.d.ts +2 -0
  421. package/dist/core/stub-env.js +1 -0
  422. package/dist/core/surrogate-safe-slice.d.ts +3 -3
  423. package/dist/core/synthetic-read-verdict.js +3 -3
  424. package/dist/core/task-event.d.ts +42 -8
  425. package/dist/core/task-notification.d.ts +19 -15
  426. package/dist/core/task-registry-agent.d.ts +4 -4
  427. package/dist/core/task-registry-shared.d.ts +4 -4
  428. package/dist/core/task-registry-shared.js +1 -0
  429. package/dist/core/task-registry.d.ts +13 -4
  430. package/dist/core/task-registry.js +14 -2
  431. package/dist/core/task-result.d.ts +21 -3
  432. package/dist/core/task-spec.d.ts +69 -64
  433. package/dist/core/task-stream.d.ts +6 -6
  434. package/dist/core/task-tool-shape.d.ts +4 -4
  435. package/dist/core/tighten-task-spec.d.ts +1 -1
  436. package/dist/core/tighten-task-spec.js +2 -1
  437. package/dist/core/tool-catalog-entries.d.ts +36 -2
  438. package/dist/core/tool-catalog-entries.js +69 -43
  439. package/dist/core/tool-check-reading.d.ts +11 -0
  440. package/dist/core/tool-check-reading.js +11 -6
  441. package/dist/core/tool-conformance.js +1 -0
  442. package/dist/core/tool-errors.d.ts +2 -2
  443. package/dist/core/tool-face-reader.js +5 -3
  444. package/dist/core/tool-face.d.ts +21 -2
  445. package/dist/core/tool-face.js +1 -1
  446. package/dist/core/tool-model-gate.d.ts +5 -5
  447. package/dist/core/tool-name-aliases.d.ts +29 -8
  448. package/dist/core/tool-name-aliases.js +22 -4
  449. package/dist/core/tool-name-readings.d.ts +10 -43
  450. package/dist/core/tool-name-readings.js +2 -11
  451. package/dist/core/tool-policy.d.ts +85 -196
  452. package/dist/core/tool-policy.js +150 -175
  453. package/dist/core/tool-registry.d.ts +14 -7
  454. package/dist/core/tool-registry.js +17 -7
  455. package/dist/core/tool-result-store.js +5 -1
  456. package/dist/core/tool-roster.d.ts +57 -33
  457. package/dist/core/tool-roster.js +56 -68
  458. package/dist/core/tool-spec-members.js +8 -3
  459. package/dist/core/tool-spec.d.ts +53 -31
  460. package/dist/core/tools.js +51 -10
  461. package/dist/core/trace.d.ts +6 -2
  462. package/dist/core/types.d.ts +1 -1
  463. package/dist/core/untrusted-egress.d.ts +1 -1
  464. package/dist/core/untrusted-text.d.ts +1 -1
  465. package/dist/core/user-attachment.d.ts +8 -1
  466. package/dist/core/user-attachment.js +64 -4
  467. package/dist/core/warm-resume.d.ts +1 -1
  468. package/dist/core/wiring-manifest.d.ts +58 -0
  469. package/dist/core/wiring-manifest.js +14 -5
  470. package/dist/core/workflow-journal-store.d.ts +62 -0
  471. package/dist/core/workflow-journal-store.js +78 -2
  472. package/dist/core/workflow-run-store.d.ts +6 -0
  473. package/dist/core/workflow-run-store.js +2 -0
  474. package/dist/engine/compaction/compaction.d.ts +9 -9
  475. package/dist/engine/compaction/compaction.js +3 -2
  476. package/dist/engine/execution-env/node-execution-env.d.ts +26 -8
  477. package/dist/engine/execution-env/node-execution-env.js +54 -24
  478. package/dist/engine/harness/agent-harness.d.ts +39 -9
  479. package/dist/engine/harness/agent-harness.js +87 -33
  480. package/dist/engine/harness/types.d.ts +58 -9
  481. package/dist/engine/harness/types.js +12 -1
  482. package/dist/engine/llm/types.d.ts +36 -19
  483. package/dist/engine/llm/validation.d.ts +4 -1
  484. package/dist/engine/llm/validation.js +13 -1
  485. package/dist/engine/loop/agent-loop.d.ts +23 -1
  486. package/dist/engine/loop/agent-loop.js +26 -34
  487. package/dist/engine/loop/types.d.ts +31 -19
  488. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  489. package/dist/engine/session/memory-repo.d.ts +18 -12
  490. package/dist/engine/session/memory-repo.js +24 -9
  491. package/dist/engine/session/parent-chain-guard.d.ts +3 -2
  492. package/dist/engine/session/parent-chain-guard.js +1 -1
  493. package/dist/engine/session/repo-utils.d.ts +32 -3
  494. package/dist/engine/session/repo-utils.js +50 -5
  495. package/dist/index.d.ts +47 -23
  496. package/dist/index.js +35 -17
  497. package/dist/internal/harness-types.d.ts +1 -1
  498. package/dist/internal/harness.d.ts +3 -3
  499. package/dist/internal/harness.js +2 -2
  500. package/dist/internal/llm.d.ts +2 -2
  501. package/dist/internal/llm.js +1 -1
  502. package/dist/orchestration/goal.js +2 -2
  503. package/dist/orchestration/run-workflow-tool.d.ts +8 -6
  504. package/dist/orchestration/run-workflow-tool.js +10 -6
  505. package/dist/orchestration/workflow-size-guideline.d.ts +4 -4
  506. package/dist/orchestration/workflow-types.d.ts +18 -0
  507. package/dist/orchestration/workflow-types.js +6 -0
  508. package/dist/orchestration/workflow.d.ts +5 -13
  509. package/dist/orchestration/workflow.js +57 -49
  510. package/dist/prompt-assembly/artifact.d.ts +2 -2
  511. package/dist/prompt-assembly/artifact.js +5 -3
  512. package/dist/prompt-assembly/assemble.d.ts +3 -2
  513. package/dist/prompt-assembly/assemble.js +1 -1
  514. package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
  515. package/dist/prompt-assembly/catalog/schema.js +34 -2
  516. package/dist/prompt-assembly/catalog/sections.js +0 -1
  517. package/dist/prompt-assembly/composer.d.ts +3 -1
  518. package/dist/prompt-assembly/composer.js +1 -1
  519. package/dist/prompt-assembly/event-registry.js +2 -0
  520. package/dist/prompt-assembly/overlay.js +3 -3
  521. package/dist/prompt-assembly/renderers.d.ts +1 -1
  522. package/dist/prompt-assembly/renderers.js +0 -3
  523. package/dist/prompt-assembly/role-base.d.ts +15 -0
  524. package/dist/prompt-assembly/role-base.js +9 -0
  525. package/dist/prompt-assembly/select.d.ts +39 -14
  526. package/dist/prompt-assembly/select.js +47 -16
  527. package/dist/prompt-assembly/sugar.d.ts +17 -11
  528. package/dist/prompt-assembly/sugar.js +8 -3
  529. package/dist/prompt-assembly/tool-catalog.d.ts +39 -2
  530. package/dist/prompt-assembly/tool-catalog.js +117 -4
  531. package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
  532. package/dist/prompt-assembly/turn-snapshot.js +0 -3
  533. package/dist/prompt-assembly/types.d.ts +0 -7
  534. package/dist/prompts/default.d.ts +14 -14
  535. package/dist/scenarios/full-body.d.ts +15 -15
  536. package/dist/scenarios/full-body.js +4 -3
  537. package/dist/shell/lex.js +10 -1
  538. package/dist/stores/file/adoption/adopt.d.ts +4 -3
  539. package/dist/stores/file/adoption/adopt.js +27 -33
  540. package/dist/stores/file/adoption/marker.d.ts +6 -13
  541. package/dist/stores/file/adoption/marker.js +9 -17
  542. package/dist/stores/file/checkpoint-store.d.ts +24 -0
  543. package/dist/stores/file/checkpoint-store.js +45 -7
  544. package/dist/stores/file/file-history-store.d.ts +20 -19
  545. package/dist/stores/file/file-history-store.js +157 -141
  546. package/dist/stores/file/fs-atomic.d.ts +15 -0
  547. package/dist/stores/file/fs-atomic.js +89 -14
  548. package/dist/stores/file/index.d.ts +1 -1
  549. package/dist/stores/file/index.js +2 -1
  550. package/dist/stores/file/mailbox-store.d.ts +3 -0
  551. package/dist/stores/file/mailbox-store.js +3 -1
  552. package/dist/stores/file/permission-rule-adopt.d.ts +1 -1
  553. package/dist/stores/file/permission-rule-adopt.js +18 -18
  554. package/dist/stores/file/permission-rule-store.d.ts +18 -2
  555. package/dist/stores/file/permission-rule-store.js +31 -18
  556. package/dist/stores/file/session-policy-store.d.ts +3 -3
  557. package/dist/stores/file/session-store.d.ts +54 -16
  558. package/dist/stores/file/session-store.js +114 -85
  559. package/dist/stores/file/workflow-journal-store.d.ts +10 -4
  560. package/dist/stores/file/workflow-journal-store.js +28 -13
  561. package/dist/tools/artifact/artifact-text.d.ts +1 -1
  562. package/dist/tools/artifact/artifact-tool.js +5 -3
  563. package/dist/tools/fs/bash-program-position.d.ts +19 -2
  564. package/dist/tools/fs/bash-program-position.js +56 -9
  565. package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -3
  566. package/dist/tools/fs/fs-bash.d.ts +2 -2
  567. package/dist/tools/fs/fs-bash.js +8 -6
  568. package/dist/tools/fs/fs-glob.d.ts +86 -0
  569. package/dist/tools/fs/fs-glob.js +226 -0
  570. package/dist/tools/fs/fs-read.js +14 -14
  571. package/dist/tools/fs/fs-search-tools.js +7 -7
  572. package/dist/tools/fs/fs-shared.d.ts +8 -8
  573. package/dist/tools/fs/gh-rate-limit.d.ts +1 -1
  574. package/dist/tools/fs/notebook.d.ts +2 -2
  575. package/dist/tools/fs/pattern-kill-guard.d.ts +22 -0
  576. package/dist/tools/fs/pattern-kill-guard.js +397 -0
  577. package/dist/tools/fs/pdf.d.ts +9 -6
  578. package/dist/tools/fs/pdf.js +3 -3
  579. package/dist/tools/fs/program-read-model.d.ts +57 -7
  580. package/dist/tools/fs/program-read-model.js +11 -1
  581. package/dist/tools/fs/program-read-model.rows.js +78 -21
  582. package/dist/tools/fs/read-deny-home.js +3 -2
  583. package/dist/tools/fs/read-deny.d.ts +29 -7
  584. package/dist/tools/fs/read-deny.js +63 -22
  585. package/dist/tools/fs/removal-targets.d.ts +18 -8
  586. package/dist/tools/fs/removal-targets.js +47 -20
  587. package/dist/tools/fs/safety.d.ts +9 -9
  588. package/dist/tools/fs/search.d.ts +16 -6
  589. package/dist/tools/fs/search.js +20 -26
  590. package/dist/tools/fs/shell-read-argv.js +89 -12
  591. package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
  592. package/dist/tools/fs/shell-read-bindings.js +41 -0
  593. package/dist/tools/fs/shell-read-check.js +12 -20
  594. package/dist/tools/fs/shell-read-environment.d.ts +5 -1
  595. package/dist/tools/fs/shell-read-environment.js +3 -2
  596. package/dist/tools/fs/shell-read-establish.d.ts +15 -0
  597. package/dist/tools/fs/shell-read-establish.js +19 -20
  598. package/dist/tools/fs/shell-read-judge.d.ts +4 -0
  599. package/dist/tools/fs/shell-read-judge.js +5 -2
  600. package/dist/tools/fs/shell-read-plan.js +24 -16
  601. package/dist/tools/fs/shell-read-start.d.ts +6 -1
  602. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
  603. package/dist/tools/fs/shell-read-write-targets.js +2 -3
  604. package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
  605. package/dist/tools/fs/shell-reentry-text.js +40 -2
  606. package/dist/tools/loop-tick.d.ts +2 -2
  607. package/dist/tools/scheduler-tools.js +5 -1
  608. package/dist/tools/task-list.d.ts +7 -7
  609. package/dist/tools/task-list.js +5 -1
  610. package/dist/tools/todo.js +65 -64
  611. package/dist/tools/web.d.ts +20 -15
  612. package/dist/tools/web.js +55 -69
  613. package/dist/tools/worktree.d.ts +3 -3
  614. package/dist/tools/worktree.js +3 -1
  615. package/package.json +1 -1
  616. package/test/export-surface.snapshot.json +5894 -5638
  617. package/wire-changes/core@7.55.0.json +3318 -0
  618. package/wire-changes/core@7.56.0.json +3891 -0
  619. package/wire-changes/mods-kernel@7.56.0.json +303 -0
  620. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +0 -39
  621. package/dist/core/store-contracts/session-store-incarnation-contract.js +0 -95
@@ -1,11 +1,12 @@
1
1
  import { attest } from "./tool-policy.js";
2
- import { MCP_NAMESPACE, protocolOf } from "./protocol-table.js";
2
+ import { MCP_NAMESPACE } from "./protocol-table.js";
3
3
  import { catalogRuleFaceOf, isShellFaceToolName, pathTargetOf } from "./tool-registry.js";
4
+ import { HOST_UNREADABLE_SENTENCE, callHostTargetOf } from "./host-target.js";
4
5
  import { indexOfUnescaped, lastIndexOfUnescaped, parsePermissionRule, ruleSpellingOf } from "./permission-rule-syntax.js";
5
- import { COMMAND_RULE_TOOL, NAME_RULE_FACES, PATH_RULE_BASE_LABEL, PATH_RULE_FACES, callPathFaceOf, isUsablePathBase, keyedValueAbsentReason, laneToolNamesOf, nameGrammarReads, nameRuleAdmits, nameRuleSubjectOf, parseRuleText, programRunReachOf, ruleBasesNeeded } from "./permission-rule-model.js";
6
+ import { callPathFaceOf, canonicalNameValue, COMMAND_RULE_TOOL, domainRuleAdmits, isUsablePathBase, laneToolNamesOf, mountedOnlyArgumentOf, mountedValueArmOf, NAME_RULE_FACES, nameRuleReach, nameRuleSubjectOf, nameValueAbsentReason, nameValuesUnreadReason, parseRuleText, PATH_RULE_BASE_LABEL, PATH_RULE_FACES, programRunReachOf, ruleBasesNeeded, ruleLaneOf, ruleShapeOf, shellRuleParamOf, ruleContentOf } from "./permission-rule-model.js";
6
7
  import { pathFamilyOf } from "../tools/fs/safety.js";
7
- import { argsAsTheToolReads, callTargetReadingOf, callTargetViewsOf } from "./effective-path-target.js";
8
- import { canonicalize, UNCANONICALIZABLE } from "./canonical-json.js";
8
+ import { callTargetReadingOf, callTargetViewsOf } from "./effective-path-target.js";
9
+ import { DEFAULT_MAX_SCALAR_VALUE_CHARS, paramRuleReaches } from "./param-rule-reach.js";
9
10
  import { bindPathRules, judgeRuleRows, policyAnchors, rowsWhereTheyLead } from "./path-rule-binding.js";
10
11
  import { ruleDenialSentence } from "./rule-denial-sentence.js";
11
12
  import { heldValues } from "./tool-name-readings.js";
@@ -25,20 +26,27 @@ function describeBehavior(v) {
25
26
  default: return v === null ? "null" : "an object";
26
27
  }
27
28
  }
29
+ export function ruleIssue(rule, code, message, libraryOption) {
30
+ return { rule, code, message, ...(libraryOption !== undefined ? { libraryOption } : {}) };
31
+ }
28
32
  export const DEFAULT_CAPS = {
29
33
  maxRules: 256,
30
34
  maxRuleLength: 512,
31
35
  maxPatternLength: 256,
32
36
  maxStars: 16,
33
- maxScalarValueChars: 16_384,
37
+ maxScalarValueChars: DEFAULT_MAX_SCALAR_VALUE_CHARS,
38
+ };
39
+ import { isCoveringRuleName, ruleNameCovers, wildcardMatch } from "./namespaced-rule-name.js";
40
+ export { isCoveringRuleName, ruleNameCovers, wildcardMatch };
41
+ const vocabularyOf = (face) => face.params ?? face.primaryParams;
42
+ const carriedPhrase = (face) => {
43
+ const vocabulary = vocabularyOf(face);
44
+ if (vocabulary.length > 0)
45
+ return `it carries ${[...vocabulary].sort().join(", ")}`;
46
+ return face.params !== undefined ? "it declares no rule-readable parameters" : "its parameters are not declared statically: each mount's schema is its own";
34
47
  };
35
- import { isNamespacedCoveringRuleName, namespacedRuleNameCovers, wildcardMatch } from "./namespaced-rule-name.js";
36
- export { isNamespacedCoveringRuleName, namespacedRuleNameCovers, wildcardMatch };
37
48
  export function catalogRuleFaceView(toolName) {
38
- const face = catalogRuleFaceOf(toolName);
39
- if (face === undefined)
40
- return undefined;
41
- return { ...face, pathTargeting: pathTargetOf(toolName) !== undefined };
49
+ return catalogRuleFaceOf(toolName);
42
50
  }
43
51
  export const fileToolParamVocabulary = (canonicalTool) => {
44
52
  const face = catalogRuleFaceOf(canonicalTool);
@@ -83,25 +91,25 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
83
91
  const command = { deny: [], ask: [] };
84
92
  const namespacedCovering = { deny: [], ask: [] };
85
93
  const issues = [];
86
- const bad = (rule, code, message) => {
87
- issues.push({ rule, code, message });
94
+ const bad = (rule, code, message, libraryOption) => {
95
+ issues.push(ruleIssue(rule, code, message, libraryOption));
88
96
  };
89
97
  if (rules.length > caps.maxRules) {
90
- return { byTool, command, namespacedCovering, issues: [{ rule: "", code: "invalid.cap_exceeded", message: `${rules.length} rules > maxRules ${caps.maxRules}` }] };
98
+ return { byTool, command, namespacedCovering, issues: [ruleIssue("", "invalid.cap_exceeded", `${rules.length} rules — a rule set holds at most ${caps.maxRules}`, { name: "caps.maxRules" })] };
91
99
  }
92
100
  for (const r of rules) {
93
101
  const text = r.rule;
94
102
  const behavior = r.behavior;
95
103
  if (behavior !== "deny" && behavior !== "ask") {
96
104
  if (behavior === "allow")
97
- bad(text, "unsupported.allow", "an allow rule does not belong to a policy — allow entries live on the allow layer: put the entry in `TaskSpec.allowedTools` (a request's) or `RunnerDeps.allowedTools` (the deployment's); deny / ask rules stay here");
105
+ bad(text, "unsupported.allow", "an allow rule does not belong to a policy — allow entries live on the allow layer (the request's allow list, or the deployment's); deny / ask rules stay here", { name: "TaskSpec.allowedTools" });
98
106
  else
99
107
  bad(text, "invalid.behavior", `a rule's behavior is one of "deny" | "ask" — got ${describeBehavior(behavior)}; a misspelled verb would compile to a rule that silently never fires`);
100
108
  continue;
101
109
  }
102
110
  const verb = behavior;
103
111
  if (text.length > caps.maxRuleLength) {
104
- bad(text, "invalid.cap_exceeded", `rule longer than ${caps.maxRuleLength} chars`);
112
+ bad(text, "invalid.cap_exceeded", `rule longer than ${caps.maxRuleLength} chars`, { name: "caps.maxRuleLength" });
105
113
  continue;
106
114
  }
107
115
  const parsed = ruleSpellingOf(text);
@@ -110,24 +118,21 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
110
118
  bad(text, why.code, why.message);
111
119
  continue;
112
120
  }
113
- if (parsed.toolName === "*") {
114
- bad(text, "invalid.tool_name", `\`*\` names no tool — a rule reaches the tool it names, so this one would compile and never match; name the tool, or state the answer for every call no rule reaches with \`defaultAction\``);
115
- continue;
116
- }
117
121
  const toolName = parsed.toolName;
118
122
  const parenthesised = parsed.ruleContent !== undefined || indexOfUnescaped(text, "(") !== -1;
119
123
  if (toolName.startsWith(MCP_NAMESPACE.prefix) && parenthesised) {
120
- bad(text, "unsupported.mcp_paren", "MCP rules do not support patterns in parentheses (CC parity); use the toolAxes system");
124
+ bad(text, "unsupported.mcp_paren", "MCP rules do not support patterns in parentheses (CC parity); a rule names a whole tool (`mcp__<server>__<tool>`) or a whole server (`mcp__<server>`), and what a tool does is declared per tool in the MCP server's spec", { name: "toolAxes" });
121
125
  continue;
122
126
  }
123
- if (parenthesised && isNamespacedCoveringRuleName(toolName)) {
127
+ if (ruleContentOf(parsed) !== undefined && isCoveringRuleName(toolName, verb)) {
124
128
  bad(text, "unsupported.covering_paren", `"${toolName}" reaches a SET of tools, and the generic param DSL is keyed by exact tool name — a parenthesised rule on it can never match. ` +
125
129
  `Write the parenthesised rule against one exact tool name, or drop the parentheses to keep the covering rule.`);
126
130
  continue;
127
131
  }
128
132
  const entry = byTool.get(toolName) ?? { bare: {}, param: { deny: [], ask: [] }, content: { deny: [], ask: [] } };
129
- if (parsed.ruleContent === undefined) {
130
- if (isNamespacedCoveringRuleName(toolName)) {
133
+ const content = ruleContentOf(parsed);
134
+ if (content === undefined) {
135
+ if (isCoveringRuleName(toolName, verb)) {
131
136
  namespacedCovering[verb].push({ ruleName: toolName, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
132
137
  continue;
133
138
  }
@@ -135,52 +140,70 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
135
140
  byTool.set(toolName, entry);
136
141
  continue;
137
142
  }
138
- const content = parsed.ruleContent;
139
143
  const colon = content.indexOf(":");
140
- if (isShellFaceToolName(toolName)) {
141
- const paramPart = colon > 0 ? content.slice(0, colon).trim() : "";
142
- const declaresParam = (tool) => colon > 0 && /^[A-Za-z_][A-Za-z0-9_]*$/.test(paramPart) && (catalogRuleFaceOf(tool)?.params ?? []).includes(paramPart);
143
- const looksLikeParamRule = declaresParam(toolName);
144
- if (toolName !== COMMAND_RULE_TOOL && !looksLikeParamRule) {
145
- const commandWordParam = declaresParam(COMMAND_RULE_TOOL) && !content.endsWith(":*");
146
- bad(text, "invalid.command_rule", commandWordParam
147
- ? `"${text}" is a parameter rule on "${paramPart}", which ${toolName} does not declare (its rule parameters: ${(catalogRuleFaceOf(toolName)?.params ?? []).join(", ")}); a parameter rule reaches only the tool that declares the parameter, so ${COMMAND_RULE_TOOL}(${content}) is a rule on ${COMMAND_RULE_TOOL}'s own argument and does not reach ${toolName}. A shell command rule is written ${COMMAND_RULE_TOOL}(<command>) — it reaches ${toolName} and every other tool that runs a shell command by the command it runs.`
144
+ let face;
145
+ if (!isShellFaceToolName(toolName)) {
146
+ const resolved = faceOf(toolName);
147
+ if (resolved.judged && resolved.face === undefined) {
148
+ bad(text, "unsupported.tool_unknown", `"${toolName}" is not a tool on this leg's roster — the rule would compile and never match`);
149
+ continue;
150
+ }
151
+ face = resolved.face;
152
+ }
153
+ const lane = ruleLaneOf(toolName, content);
154
+ if (lane === "command") {
155
+ if (toolName !== COMMAND_RULE_TOOL) {
156
+ const commandWordParam = shellRuleParamOf(COMMAND_RULE_TOOL, content);
157
+ bad(text, "invalid.command_rule", commandWordParam !== undefined && !content.endsWith(":*")
158
+ ? `"${text}" is a parameter rule on "${commandWordParam}", which ${toolName} does not declare (its rule parameters: ${(catalogRuleFaceOf(toolName)?.params ?? []).join(", ")}); a parameter rule reaches only the tool that declares the parameter, so ${COMMAND_RULE_TOOL}(${content}) is a rule on ${COMMAND_RULE_TOOL}'s own argument and does not reach ${toolName}. A shell command rule is written ${COMMAND_RULE_TOOL}(<command>) — it reaches ${toolName} and every other tool that runs a shell command by the command it runs.`
148
159
  : `a shell command rule is written ${COMMAND_RULE_TOOL}(…) — it reaches ${toolName} and every other tool that runs a shell command by the command it runs; "${text}" names no rule upstream reads. Write ${COMMAND_RULE_TOOL}(${content}).`);
149
160
  continue;
150
161
  }
151
- if (toolName === COMMAND_RULE_TOOL && (!looksLikeParamRule || content.endsWith(":*"))) {
152
- const parsedCommand = parseRuleText(text, verb);
153
- if ("reject" in parsedCommand) {
154
- bad(text, "invalid.command_rule", `${parsedCommand.reject.code}: ${parsedCommand.reject.message}`);
155
- continue;
156
- }
157
- command[verb].push({ parsed: parsedCommand.rule, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
162
+ const parsedCommand = parseRuleText(text, verb);
163
+ if ("reject" in parsedCommand) {
164
+ bad(text, "invalid.command_rule", `${parsedCommand.reject.code}: ${parsedCommand.reject.message}`);
158
165
  continue;
159
166
  }
167
+ command[verb].push({ parsed: parsedCommand.rule, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
168
+ continue;
160
169
  }
161
170
  else {
162
- const resolved = faceOf(toolName);
163
- if (resolved.judged && resolved.face === undefined) {
164
- bad(text, "unsupported.tool_unknown", `"${toolName}" is not a tool on this leg's roster — the rule would compile and never match`);
165
- continue;
166
- }
167
- const face = resolved.face;
168
- if (nameGrammarReads(toolName, content)) {
171
+ if (lane === "name") {
169
172
  const parsedName = parseRuleText(text, verb);
170
173
  if ("reject" in parsedName) {
171
174
  bad(text, "invalid.command_rule", `${parsedName.reject.code}: ${parsedName.reject.message}`);
172
175
  continue;
173
176
  }
174
177
  const param = NAME_RULE_FACES[toolName].param;
175
- if (face?.params !== undefined && !face.params.includes(param)) {
176
- bad(text, "unsupported.param_unknown", `"${param}" is not a parameter of ${toolName} on this leg (it carries ${[...face.params].sort().join(", ")}) — a ${toolName} rule is read against it, so the rule would compile and never match`);
178
+ if (face !== undefined && !vocabularyOf(face).includes(param)) {
179
+ bad(text, "unsupported.param_unknown", `"${param}" is not a parameter of ${toolName} on this leg (${carriedPhrase(face)}) — a ${toolName} rule is read against it, so the rule would compile and never match`);
180
+ continue;
181
+ }
182
+ const mountedOnly = mountedOnlyArgumentOf(toolName, content, face?.params);
183
+ if (mountedOnly !== undefined) {
184
+ bad(text, "unsupported.param_unknown", `"${mountedOnly}" is an argument declared only by the ${toolName} tool this leg mounts, which is not rule-readable (#2248) — "${text}" would read as the ${param} "${content}" and never reach a call setting ${mountedOnly}; write the rule on the whole tool (\`${toolName}\`), or on the ${param} it means`);
185
+ continue;
186
+ }
187
+ const resolved = face?.nameValues !== undefined ? canonicalNameValue(parsedName.rule.command, face.nameValues) : undefined;
188
+ if (resolved?.kind === "ambiguous") {
189
+ bad(text, "invalid.name_ambiguous", `"${parsedName.rule.command}" names ${resolved.entries.length} of the ${param} values this leg's ${toolName} offers (${resolved.entries.join(", ")}) — they differ only by case, spacing or punctuation, so which one the rule means is not determinable; write the exact one`);
177
190
  continue;
178
191
  }
179
192
  entry.content[verb].push({ parsed: parsedName.rule, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
180
193
  byTool.set(toolName, entry);
181
194
  continue;
182
195
  }
183
- if (face !== undefined && face.pathTargeting === true && colon <= 0) {
196
+ if (lane === "domain") {
197
+ const parsedHost = parseRuleText(text, verb);
198
+ if ("reject" in parsedHost) {
199
+ bad(text, "invalid.command_rule", `${parsedHost.reject.code}: ${parsedHost.reject.message}`);
200
+ continue;
201
+ }
202
+ entry.content[verb].push({ parsed: parsedHost.rule, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
203
+ byTool.set(toolName, entry);
204
+ continue;
205
+ }
206
+ if (lane === "path") {
184
207
  const parsedPath = parseRuleText(text, verb);
185
208
  if ("reject" in parsedPath) {
186
209
  bad(text, "invalid.command_rule", `${parsedPath.reject.code}: ${parsedPath.reject.message}`);
@@ -189,7 +212,7 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
189
212
  for (const base of ruleBasesNeeded(parsedPath.rule)) {
190
213
  const declared = base === "cwd" ? (pathBases.cwd ?? pathBases.root) : pathBases[base];
191
214
  if (declared !== undefined && !isUsablePathBase(declared, pathFamilyOf(pathBases))) {
192
- bad(text, "unsupported.path_base", `"${text}" is relative to ${PATH_RULE_BASE_LABEL[base]}, and the \`pathBases.${base === "cwd" && pathBases.cwd === undefined ? "root" : base}\` this policy declares is not an absolute path of its tree's family — the rule could not be judged on any call`);
215
+ bad(text, "unsupported.path_base", `"${text}" is relative to ${PATH_RULE_BASE_LABEL[base]}, and the one this policy declares for it is not an absolute path of its tree's family — the rule could not be judged on any call`, { name: `pathBases.${base === "cwd" && pathBases.cwd === undefined ? "root" : base}` });
193
216
  }
194
217
  }
195
218
  if (issues.length > 0 && issues[issues.length - 1].rule === text && issues[issues.length - 1].code === "unsupported.path_base")
@@ -199,15 +222,21 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
199
222
  byTool.set(toolName, entry);
200
223
  continue;
201
224
  }
202
- if (face?.params !== undefined && colon > 0) {
225
+ if (face !== undefined && colon > 0) {
203
226
  const paramPart = content.slice(0, colon).trim();
204
- if (!face.params.includes(paramPart)) {
227
+ const vocabulary = vocabularyOf(face);
228
+ if (!vocabulary.includes(paramPart)) {
205
229
  if (face.nonScalar?.includes(paramPart)) {
206
230
  bad(text, "unsupported.param_non_scalar", `"${paramPart}" is a parameter of ${toolName} but its value is an object or an array — the generic matcher compares scalars only; the rule would compile and never match`);
207
231
  }
208
232
  else {
209
- bad(text, "unsupported.param_unknown", `"${paramPart}" is not a parameter of ${toolName} (it carries ${[...face.params].sort().join(", ")}) — the rule would compile and never match. ` +
210
- `For a path glob use the tool-specific lane (\`${toolName}(src/**)\` is not the generic param DSL); a Windows path such as \`${toolName}(C:/foo)\` parses as the param "C".`);
233
+ const statesNothing = face.params === undefined && vocabulary.length === 0;
234
+ bad(text, "unsupported.param_unknown", statesNothing
235
+ ? `"${paramPart}" cannot be judged on ${toolName} here (${carriedPhrase(face)}) — write the rule on the whole tool (\`${toolName}\`).`
236
+ : `"${paramPart}" is not a scalar parameter of ${toolName} (${carriedPhrase(face)}${vocabulary.length > 0 ? "; arrays and objects are not rule-readable" : ""}) — the rule would compile and never match. ` +
237
+ (pathTargetOf(toolName) !== undefined
238
+ ? `For a path glob use the tool-specific lane (\`${toolName}(src/**)\` is not the generic param DSL); a Windows path such as \`${toolName}(C:/foo)\` parses as the param "C".`
239
+ : `${vocabulary.length > 0 ? "Name one of its parameters, or write" : "Write"} the rule on the whole tool (\`${toolName}\`).`), statesNothing ? { name: "ruleFaces" } : undefined);
211
240
  }
212
241
  continue;
213
242
  }
@@ -224,14 +253,19 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
224
253
  continue;
225
254
  }
226
255
  if (pattern.length > caps.maxPatternLength || countStars(pattern) > caps.maxStars) {
227
- bad(text, "invalid.cap_exceeded", `pattern exceeds maxPatternLength ${caps.maxPatternLength} or maxStars ${caps.maxStars}`);
256
+ bad(text, "invalid.cap_exceeded", `a pattern holds at most ${caps.maxPatternLength} characters and ${caps.maxStars} stars`, { name: pattern.length > caps.maxPatternLength ? "caps.maxPatternLength" : "caps.maxStars" });
228
257
  continue;
229
258
  }
230
259
  if (faceOf(toolName).face?.primaryParams.includes(param) === true && primaryFieldGeneric === "reject") {
231
- bad(text, "invalid.primary_field", `"${param}" is ${toolName}'s primary field — the generic matcher is a trim+FULL-STRING lexical match (no shell/path semantics); '${toolName}(${param}:git push*)' would NOT match 'cd /x && git push'. Opt in with primaryFieldGeneric:"allow-lexical" if you understand this.`);
260
+ const form = ruleShapeOf({ toolName, args: {} }, verb);
261
+ bad(text, "invalid.primary_field", `"${param}" is ${toolName}'s primary field, and a rule on it matches the WHOLE value lexically — no shell or path semantics — so \`${toolName}(${param}:git push*)\` would NOT match \`cd /x && git push\`. ` +
262
+ `Write the rule ${form === undefined ? "" : `as \`${form}\`, or `}on the whole tool (\`${toolName}\`).`, { name: "primaryFieldGeneric", value: "allow-lexical" });
232
263
  continue;
233
264
  }
234
265
  entry.param[verb].push({ param, pattern, behavior: verb, ruleText: text, source: r.source });
266
+ const valueArm = mountedValueArmOf(text, toolName, verb);
267
+ if (valueArm !== undefined)
268
+ entry.content[verb].push({ parsed: valueArm, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
235
269
  byTool.set(toolName, entry);
236
270
  }
237
271
  return { byTool, command, namespacedCovering, issues };
@@ -244,42 +278,10 @@ function isPlainObjectArgs(args) {
244
278
  return typeof args === "object" && args !== null && !Array.isArray(args);
245
279
  }
246
280
  function matchParamRules(rules, req, maxScalarValueChars) {
247
- const args = req.args;
248
- if (!isPlainObjectArgs(args))
249
- return undefined;
250
- for (const r of rules) {
251
- if (!Object.hasOwn(args, r.param)) {
252
- if (readingAbsorbs(req, r.param, r.pattern))
253
- return r;
254
- continue;
255
- }
256
- const raw = args[r.param];
257
- if (raw === undefined || raw === null)
258
- continue;
259
- const t = typeof raw;
260
- if (t === "object" || t === "function" || t === "symbol")
261
- continue;
262
- const value = String(raw).trim();
263
- if (value.length > maxScalarValueChars)
264
- return r;
265
- if (wildcardMatch(r.pattern, value))
266
- return r;
267
- }
268
- return undefined;
269
- }
270
- function readingAbsorbs(req, param, pattern) {
271
- if (pattern.includes("*"))
272
- return false;
273
- try {
274
- const read = canonicalize(argsAsTheToolReads(req, { ...req.args, [param]: pattern }));
275
- return read !== UNCANONICALIZABLE && read === canonicalize(req.args);
276
- }
277
- catch {
278
- return false;
279
- }
281
+ return rules.find((r) => paramRuleReaches(req, r.param, r.pattern, maxScalarValueChars));
280
282
  }
281
- function ruleDenial(req, ruleText, source) {
282
- return ruleDenialSentence({ source: "permission", tool: req.toolName, rule: ruleText, ...(source ? { origin: source } : {}) });
283
+ function ruleDenial(req, ruleText, source, detail) {
284
+ return ruleDenialSentence({ source: "permission", tool: req.toolName, rule: ruleText, ...(source ? { origin: source } : {}), ...(detail !== undefined ? { detail } : {}) });
283
285
  }
284
286
  function ruleAskMessage(ruleText, source) {
285
287
  return `flagged by permission rule "${ruleText}"${source ? ` (${source})` : ""}`;
@@ -327,7 +329,8 @@ export function createPermissionRulePolicy(rules, opts) {
327
329
  for (const r of namespacedCovering[behavior])
328
330
  nameSets[behavior].push(r.ruleName);
329
331
  }
330
- const coveringHit = (lane, toolName) => lane.length === 0 ? undefined : lane.find((r) => namespacedRuleNameCovers(r.ruleName, toolName));
332
+ const heldFor = (table, req) => heldValues("policy.permissionRules", table, req);
333
+ const coveringHit = (lane, req) => lane.length === 0 ? undefined : heldFor({ get: (name) => lane.find((r) => ruleNameCovers(r.ruleName, name)) }, req)[0];
331
334
  const hasCovering = namespacedCovering.deny.length > 0 || namespacedCovering.ask.length > 0;
332
335
  const faceRules = {
333
336
  deny: [...byTool.values()].flatMap((e) => e.content.deny.filter((r) => r.faces !== undefined)),
@@ -386,11 +389,33 @@ export function createPermissionRulePolicy(rules, opts) {
386
389
  const judgeOthers = (lane, req) => {
387
390
  const command = isPlainObjectArgs(req.args) ? req.args[commandParam] : undefined;
388
391
  let unreadable;
392
+ let host = null;
389
393
  for (const r of lane) {
390
394
  if (r.parsed.match === "name" || r.parsed.match === "name_prefix") {
391
395
  const named = nameRuleSubjectOf(r.parsed.tool, req.args);
392
- if (named !== undefined && nameRuleAdmits(r.parsed, named))
396
+ if (named === undefined)
397
+ continue;
398
+ const reach = nameRuleReach(r.parsed, named, req.face?.nameValues);
399
+ if (reach === "reached")
393
400
  return { rule: r };
401
+ if (reach === "unread")
402
+ unreadable ??= { rule: r, unreadable: nameValuesUnreadReason(r.parsed.tool) };
403
+ continue;
404
+ }
405
+ if (r.parsed.match === "host" || r.parsed.match === "subdomain") {
406
+ if (host === null)
407
+ host = callHostTargetOf(req, "tighten");
408
+ if (host === undefined)
409
+ continue;
410
+ if ("host" in host) {
411
+ if (domainRuleAdmits(r.parsed, host.host))
412
+ return { rule: r };
413
+ continue;
414
+ }
415
+ const why = `the host the call reaches cannot be read (${HOST_UNREADABLE_SENTENCE[host.unreadable]})`;
416
+ if (r.parsed.behavior === "deny")
417
+ return { rule: r, detail: why };
418
+ unreadable ??= { rule: r, unreadable: why };
394
419
  continue;
395
420
  }
396
421
  if (typeof command !== "string")
@@ -407,7 +432,7 @@ export function createPermissionRulePolicy(rules, opts) {
407
432
  for (const r of [...entry.content.deny, ...entry.content.ask]) {
408
433
  if (r.parsed.match !== "name" || nameRuleSubjectOf(r.parsed.tool, req.args) !== undefined)
409
434
  continue;
410
- const absent = keyedValueAbsentReason(r.parsed.tool);
435
+ const absent = nameValueAbsentReason(r.parsed.tool);
411
436
  if (absent !== undefined)
412
437
  return ruleDenialSentence({ source: "permission", tool: req.toolName, rule: r.ruleText, ...(r.source ? { origin: r.source } : {}), detail: absent });
413
438
  }
@@ -420,7 +445,7 @@ export function createPermissionRulePolicy(rules, opts) {
420
445
  requiresRealApproval: true,
421
446
  });
422
447
  const entryFor = (req) => {
423
- const entries = heldValues("policy.permissionRules", byTool, req);
448
+ const entries = heldFor(byTool, req);
424
449
  if (entries.length <= 1)
425
450
  return entries[0];
426
451
  const bare = {};
@@ -440,12 +465,12 @@ export function createPermissionRulePolicy(rules, opts) {
440
465
  ...(pathSpecs.length > 0 ? { pathRules: (anchors) => boundAt(policyAnchors(pathBases, anchors)).rows } : {}),
441
466
  check(req) {
442
467
  const entry = entryFor(req);
443
- const covering = hasCovering && protocolOf(req.toolName) !== undefined;
468
+ const covering = hasCovering;
444
469
  if (entry?.bare.deny) {
445
470
  return { action: "deny", message: ruleDenial(req, entry.bare.deny.ruleText, entry.bare.deny.source) };
446
471
  }
447
472
  if (covering) {
448
- const coveringDeny = coveringHit(namespacedCovering.deny, req.toolName);
473
+ const coveringDeny = coveringHit(namespacedCovering.deny, req);
449
474
  if (coveringDeny)
450
475
  return { action: "deny", message: ruleDenial(req, coveringDeny.ruleText, coveringDeny.source) };
451
476
  }
@@ -454,7 +479,7 @@ export function createPermissionRulePolicy(rules, opts) {
454
479
  const denyLane = contentLaneOf("deny", entry, shellCall, callFace);
455
480
  const contentDeny = denyLane.length > 0 ? contentHit(denyLane, req) : undefined;
456
481
  if (contentDeny !== undefined && contentDeny.unreadable === undefined) {
457
- const denied = { action: "deny", message: ruleDenial(req, contentDeny.rule.ruleText, contentDeny.rule.source) };
482
+ const denied = { action: "deny", message: ruleDenial(req, contentDeny.rule.ruleText, contentDeny.rule.source, contentDeny.detail) };
458
483
  const face = contentDeny.view !== undefined ? callPathFaceOf(req) : undefined;
459
484
  return face !== undefined ? attest(denied, req, { pathDenial: { rule: contentDeny.rule.ruleText, view: contentDeny.view, face } }) : denied;
460
485
  }
@@ -475,7 +500,7 @@ export function createPermissionRulePolicy(rules, opts) {
475
500
  }
476
501
  }
477
502
  if (covering) {
478
- const coveringAsk = coveringHit(namespacedCovering.ask, req.toolName);
503
+ const coveringAsk = coveringHit(namespacedCovering.ask, req);
479
504
  if (coveringAsk)
480
505
  return { action: "ask", message: ruleAskMessage(coveringAsk.ruleText, coveringAsk.source), matchedAskRule: coveringAsk.ruleText };
481
506
  }
@@ -44,7 +44,7 @@ export declare function disclosedRuleSet(rules: readonly PersistedRuleHitRule[])
44
44
  * lane's allow carries: one authority, one word) and the rule text disclosed through the display
45
45
  * transform; the STATION attributes the refusal (`tightened: "deny"` ⇒ it writes the pass's refusing
46
46
  * layer — the attribution is a station's word and lives in the station file). A path row's hit reports where
47
- * it met the call; with `call` given and the face the call's own, the deny carries that as its attested `pathDenial`, so every exit that
47
+ * it met the call; with the face the call's own (`call`, the request the lane read), the deny carries that as its attested `pathDenial`, so every exit that
48
48
  * reads the deny (the gate's exit, the approved-edit re-check, a resumed leg's belt) mints the same card from the same fact.
49
49
  * · ASK — on an allow, a fresh ask is minted carrying `matchedAskRule` (the marker an explicit `ask`
50
50
  * permission rule stamps, so the ask's origin derives as `ask_rule`: the classifier never answers
@@ -61,13 +61,15 @@ export declare function disclosedRuleSet(rules: readonly PersistedRuleHitRule[])
61
61
  * · UNREADABLE STORE — a partition of the store (or all of it) could not be READ (`unreadable` without a `reason`): a deny
62
62
  * or ask row inside it may forbid this call and nobody can tell, so it fails CLOSED the same way, to the question
63
63
  * only a person answers — an allow becomes an ask carrying `requiresRealApproval`, an ask acquires the bit, a deny stays
64
- * a deny. Every call the lane judges is in this state until a read succeeds again (the lane announces the skipped store,
65
- * once per run, and reads again on the next call). The two forms differ in WHICH fact the gate records (one class for
64
+ * a deny. Every call is in this state until a read succeeds again, whatever its tool — rules nobody could read are rules
65
+ * whose tools nobody knows (a newer engine's grammar names rules for tools this one names none for), so the lane hands
66
+ * this form for a call no rule grammar here speaks for too; it announces the skipped store once per run and reads again
67
+ * on the next call. The two forms differ in WHICH fact the gate records (one class for
66
68
  * both, `rule_unreadable`, bypass-immune) and in the
67
69
  * resumed-call belt, which vetoes only the call form: a person already answered that call's question.
68
70
  * An allow hit (or no hit) returns the decision untouched: the allow arm is the station's.
69
71
  */
70
- export declare function applyPersistedTightening(decision: PermissionResult, read: PersistedRuleRead | undefined, call?: ToolCallRequest): {
72
+ export declare function applyPersistedTightening(decision: PermissionResult, read: PersistedRuleRead | undefined, call: ToolCallRequest): {
71
73
  decision: PermissionResult;
72
74
  tightened?: "deny" | "ask" | "unreadable" | "store_unreadable";
73
75
  };
@@ -1,6 +1,6 @@
1
- import { attest } from "./tool-policy.js";
1
+ import { attest, attestationOf } from "./tool-policy.js";
2
2
  import { callPathFaceOf } from "./permission-rule-model.js";
3
- import { decisionAskClassesOf } from "./ask-origin.js";
3
+ import { ownAskClassesOf } from "./ask-origin.js";
4
4
  import { inlineUntrusted } from "./untrusted-text.js";
5
5
  export function strongestAnswer(answers) {
6
6
  const rank = (a) => (a === undefined ? 0 : "unreadable" in a ? 4 : "behavior" in a ? { deny: 5, ask: 3, allow: 2 }[a.behavior] : 1);
@@ -20,15 +20,13 @@ export function applyPersistedTightening(decision, read, call) {
20
20
  ? `this call could not be read against the person's standing deny/ask rules (${read.reason}) — whether one of them forbids it is unknown, so it needs a real approval`
21
21
  : "the person's standing permission rules could not be read — whether one of them forbids this call is unknown, so it needs a real approval";
22
22
  const unreadableCall = callForm ? { ruleUnreadable: "persisted_call" } : {};
23
- const standingFence = decision.action === "ask" && decisionAskClassesOf({ ...decision, foldedAskClasses: undefined }).has("policy_rra")
24
- ? { foldedAskClasses: [...(decision.foldedAskClasses ?? []), "policy_rra"] }
25
- : {};
26
- return {
27
- decision: decision.action === "allow"
28
- ? { action: "ask", message, decisionReason: "persisted_rule", requiresRealApproval: true, ...unreadableCall, ...(decision.updatedInput !== undefined ? { updatedInput: decision.updatedInput } : {}) }
29
- : { ...decision, requiresRealApproval: true, ...unreadableCall, ...standingFence, message: `${decision.message !== undefined ? `${decision.message} ` : ""}(${message})` },
30
- tightened: callForm ? "unreadable" : "store_unreadable",
31
- };
23
+ const tightened = callForm ? "unreadable" : "store_unreadable";
24
+ if (decision.action === "allow") {
25
+ return { decision: { action: "ask", message, decisionReason: "persisted_rule", requiresRealApproval: true, ...unreadableCall, ...(decision.updatedInput !== undefined ? { updatedInput: decision.updatedInput } : {}) }, tightened };
26
+ }
27
+ const record = attestationOf(decision, call);
28
+ const asked = { ...decision, requiresRealApproval: true, ...unreadableCall, message: `${decision.message !== undefined ? `${decision.message} ` : ""}(${message})` };
29
+ return { decision: ownAskClassesOf(decision, record).has("policy_rra") ? attest(asked, call, { foldedClasses: [...new Set([...(record?.foldedClasses ?? []), "policy_rra"])] }) : asked, tightened };
32
30
  }
33
31
  const hit = read?.hit;
34
32
  if (hit === undefined || hit.behavior === "allow")
@@ -36,7 +34,7 @@ export function applyPersistedTightening(decision, read, call) {
36
34
  const shown = disclosedRuleSet(hit.rules);
37
35
  if (hit.behavior === "deny") {
38
36
  const denied = { action: "deny", message: `a persisted deny rule (${shown}) refuses this call`, decisionReason: "persisted_rule" };
39
- const attested = hit.denial !== undefined && call !== undefined && hit.denial.face === callPathFaceOf(call);
37
+ const attested = hit.denial !== undefined && hit.denial.face === callPathFaceOf(call);
40
38
  return { decision: attested ? attest(denied, call, { pathDenial: hit.denial }) : denied, tightened: "deny" };
41
39
  }
42
40
  if (decision.action === "deny")
@@ -1,6 +1,6 @@
1
1
  import { Type } from "typebox";
2
2
  import { delimitUntrusted } from "./untrusted-text.js";
3
- import { toolFace } from "./tool-catalog-entries.js";
3
+ import { mountRuleFace, toolFace } from "./tool-catalog-entries.js";
4
4
  export const PRESENT_PLAN_TOOL_NAME = "ExitPlanMode";
5
5
  export const ENTER_PLAN_MODE_TOOL_NAME = "EnterPlanMode";
6
6
  const ENTER_PLAN_MODE_DESCRIPTION = `Enter PLAN MODE (read-only): stop making changes and switch to exploration/planning. For the rest of this run, every write/edit/mutating tool call ASKS the user first ("Cannot write to <path> while in plan mode."; where nobody can answer, it is refused) while read-only tools (Read, Grep, Glob, etc.) still work. When your plan is ready, call ${PRESENT_PLAN_TOOL_NAME} with it — the run PAUSES for a human to approve it, then continues (read-only lifted) so you can execute.
@@ -33,6 +33,7 @@ export function createEnterPlanModeTool(enterPlanMode) {
33
33
  return {
34
34
  name: ENTER_PLAN_MODE_TOOL_NAME,
35
35
  ...toolFace("enter-plan-mode"),
36
+ ruleFace: mountRuleFace("enter-plan-mode"),
36
37
  description: ENTER_PLAN_MODE_DESCRIPTION,
37
38
  parameters: Type.Object({}),
38
39
  executionMode: "sequential",
@@ -62,6 +63,7 @@ export function createPresentPlanTool(requestReview) {
62
63
  return {
63
64
  name: PRESENT_PLAN_TOOL_NAME,
64
65
  ...toolFace("exit-plan-mode"),
66
+ ruleFace: mountRuleFace("exit-plan-mode"),
65
67
  description: PRESENT_PLAN_DESCRIPTION,
66
68
  parameters: Type.Object({
67
69
  plan: Type.String({
@@ -0,0 +1,20 @@
1
+ export declare function principalNameOf(raw: unknown): string | undefined;
2
+ /** What a value offered as THE principal of a task or of a lookup is — read once, here, so no face decides it on its own. */
3
+ export type PrincipalReading = {
4
+ readonly kind: "name";
5
+ readonly name: string;
6
+ } | {
7
+ readonly kind: "absent";
8
+ } | {
9
+ readonly kind: "invalid";
10
+ readonly fault: string;
11
+ };
12
+ /**
13
+ * A principal offered to a face that tolerates having none: `name` (a principal name), `absent` (no principal — `undefined`, and the
14
+ * empty string, which the task door and the bucket resolvers have always spelled the same), or `invalid` (it was PROVIDED and is not a name). Only absence reaches
15
+ * the unauthenticated floor, or the declared local owner's bucket; an invalid value is a bad value, refused where a principal is taken
16
+ * (never read as absence — a caller who appends one invisible character to a principal must not become the machine owner).
17
+ */
18
+ export declare function readPrincipal(raw: unknown): PrincipalReading;
19
+ /** Why a value is not a principal name, as a clause for a refusal sentence: the kind of string it is, or the type of the value. */
20
+ export declare function principalNameFault(raw: unknown): string;
@@ -0,0 +1,22 @@
1
+ const NOT_IN_A_NAME = /[\p{Cc}\p{Zl}\p{Zp}]|(?![\u200c\u200d])\p{Cf}/u;
2
+ const NOT_VISIBLE = /[\s\p{Cf}]+/gu;
3
+ export function principalNameOf(raw) {
4
+ return typeof raw === "string" && raw.replace(NOT_VISIBLE, "") !== "" && !NOT_IN_A_NAME.test(raw) ? raw : undefined;
5
+ }
6
+ export function readPrincipal(raw) {
7
+ if (raw === undefined || raw === "")
8
+ return { kind: "absent" };
9
+ const name = principalNameOf(raw);
10
+ return name !== undefined ? { kind: "name", name } : { kind: "invalid", fault: principalNameFault(raw) };
11
+ }
12
+ export function principalNameFault(raw) {
13
+ if (typeof raw !== "string")
14
+ return raw === null ? "null" : typeof raw;
15
+ if (raw === "")
16
+ return "an empty string";
17
+ if (raw.trim() === "")
18
+ return "a blank string";
19
+ if (raw.replace(NOT_VISIBLE, "") === "")
20
+ return "a string with no visible character";
21
+ return "a string holding a control, separator or format character";
22
+ }
@@ -1,16 +1,14 @@
1
1
  import { bandOf } from "../prompt-assembly/bands.js";
2
- import { lockedTextIn, receivePromptData } from "../prompt-assembly/overlay.js";
2
+ import { lockedTextIn } from "../prompt-assembly/overlay.js";
3
+ import { isPlainRecord } from "./mods/kernel/receive.js";
3
4
  import { inlineUntrusted } from "./untrusted-text.js";
4
5
  import { egressThrownText, extensionWords } from "./untrusted-egress.js";
5
6
  export const DISPOSABLE_PROMPT_SECTIONS = Object.freeze(["core/discovery.mcp-instructions"]);
6
7
  const DEFECT_MAX = 600;
7
8
  function readAnswer(answer, seat) {
8
- if (typeof answer !== "object" || answer === null || Array.isArray(answer))
9
+ if (!isPlainRecord(answer))
9
10
  return `answered ${answer === null ? "null" : Array.isArray(answer) ? "an array" : typeof answer}; prompt.section takes { text: string | null }`;
10
- const received = receivePromptData(answer);
11
- if ("notData" in received)
12
- return `a prompt.section answer is data (plain objects, arrays, strings, booleans); it holds ${received.notData}`;
13
- const data = received.value;
11
+ const data = answer;
14
12
  const keys = Object.keys(data);
15
13
  const stray = keys.filter((k) => k !== "text");
16
14
  if (stray.length > 0)
@@ -10,8 +10,8 @@
10
10
  * A declaration that breaks the rule is that peer's defect: the resolver throws inside the peer's own dial,
11
11
  * so the peer is skipped with a coded warning and its siblings still mount. The MCP transport binds its
12
12
  * endpoint by dialing only the declared URL with redirects not followed (`declaredEndpointFetch`); the A2A
13
- * peer, whose card may name another endpoint, is bound by {@link assertEndpointBound} and by
14
- * {@link redirectPolicy}.
13
+ * peer, whose card may name another endpoint, is bound by {@link assertEndpointBound} and by its follow law (a request carrying
14
+ * declared headers follows no redirect, {@link carriesDeclaredHeaders}).
15
15
  */
16
16
  import type { ProtocolId } from "./protocol-table.js";
17
17
  /** The per-peer HTTP auth declaration every protocol spec carries in the same two fields. */
@@ -35,10 +35,31 @@ export declare function resolveProtocolHttpHeaders(protocol: ProtocolId, t: Prot
35
35
  /** The engine's default request headers under the declared ones: a declared name, in any case, owns that header
36
36
  * (the default of the same name is not sent beside it). */
37
37
  export declare function underDeclaredHeaders(defaults: Readonly<Record<string, string>>, declared: Record<string, string> | undefined): Record<string, string>;
38
- /** Whether a resolved header set carries anything the declaration bound to its endpoints. */
38
+ /**
39
+ * Every header VALUE one HTTP peer's requests carry, whatever the header's NAME: each string value of the declaration's static
40
+ * `headers` and the principal the engine sends under `principalHeader`, as declared. The transport knows these; the credential vocabulary
41
+ * can only guess by name. How an endpoint can print one back — edges dropped, its credentials part, percent-encoded — is derived from
42
+ * each value by {@link requestEchoSpellings}, once, and nowhere else.
43
+ * Total: a declaration whose members cannot be read yields what could be read, because it is called on a failure path.
44
+ */
45
+ export declare function declaredHeaderValues(transport: unknown, principal?: string): readonly string[];
46
+ /**
47
+ * A peer's error text with what the peer was SENT taken out of it. Both kinds of removal are found on the ORIGINAL text (so no marker is
48
+ * rescanned and no replacement can disturb what another one reads) and the ranges they take are merged, one marker per merged range: every
49
+ * occurrence of a declared value in any spelling {@link requestEchoSpellings} derives from it (as declared and as sent, its credentials
50
+ * part, JSON-escaped with or without `\/`, percent-encoded, form-urlencoded, `+` for a space), in any letter case, longest first, and every `Cookie` / `Set-Cookie` member
51
+ * whole — a header line to its end, a record member's string, array or object to its close. The two never disarm each other: a declared
52
+ * value that lies wholly inside a Cookie member's NAME leaves the name (and the member's value is still taken); one that overlaps the name
53
+ * from outside takes its own range and the member's value goes with it. A declared value that is also an ordinary word or number (`en`, `1`,
54
+ * `application/json`) goes wherever it occurs in the remote's words, in any case — a legibility cost, never a leak; the failure's closed
55
+ * fields (code, status, delivery) are not text. A declaration too large for one matcher (tens of thousands of characters, which no header
56
+ * carries) makes the whole text the marker: the pass never throws and never shows what it could not match. Run BEFORE the credential
57
+ * vocabulary: that pass rewrites parts of a value, after which the value no longer matches whole.
58
+ */
59
+ export declare function scrubRequestEcho(text: string, declared: readonly string[]): string;
60
+ /** Whether a resolved header set carries anything the declaration bound to its endpoints — a request that does follows no redirect (the
61
+ * next hop is not a declared endpoint; A2A's follow law reads this). */
39
62
  export declare function carriesDeclaredHeaders(headers: Record<string, string> | undefined): boolean;
40
- /** A request carrying declared headers does not follow a redirect (the next hop is not a declared endpoint). */
41
- export declare function redirectPolicy(headers: Record<string, string> | undefined): "manual" | "follow";
42
63
  /**
43
64
  * Refuse an endpoint a peer advertised (an A2A card's interface URL) when it lies outside every origin the
44
65
  * declaration names and the peer's requests carry declared headers: `config.protocol_endpoint_unbound`.