@sema-agent/core 7.54.1 → 7.55.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 (399) hide show
  1. package/CHANGELOG.md +437 -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/cc-peer-directory.d.ts +36 -0
  5. package/dist/agents/cc-peer-directory.js +138 -0
  6. package/dist/agents/cc-peer-wire.d.ts +105 -0
  7. package/dist/agents/cc-peer-wire.js +98 -0
  8. package/dist/agents/cc-uds-peer-channel.d.ts +40 -0
  9. package/dist/agents/cc-uds-peer-channel.js +457 -0
  10. package/dist/agents/cross-session-envelope.d.ts +4 -1
  11. package/dist/agents/cross-session-envelope.js +8 -1
  12. package/dist/agents/cross-session-judge.d.ts +2 -2
  13. package/dist/agents/list-agents-tool.js +2 -1
  14. package/dist/agents/observer.d.ts +4 -5
  15. package/dist/agents/observer.js +2 -1
  16. package/dist/agents/peer-admission.d.ts +6 -0
  17. package/dist/agents/peer-admission.js +4 -1
  18. package/dist/agents/peer-directory.d.ts +43 -9
  19. package/dist/agents/peer-directory.js +66 -23
  20. package/dist/agents/peer-notices.d.ts +1 -1
  21. package/dist/agents/peer-session-drain.d.ts +3 -1
  22. package/dist/agents/peer-session-drain.js +1 -0
  23. package/dist/agents/read-inbox-tool.js +2 -1
  24. package/dist/agents/retain-ledger.d.ts +1 -1
  25. package/dist/agents/roster-store.d.ts +1 -1
  26. package/dist/agents/send-message-tool.d.ts +10 -0
  27. package/dist/agents/send-message-tool.js +34 -5
  28. package/dist/agents/subagent.d.ts +34 -79
  29. package/dist/agents/subagent.js +45 -46
  30. package/dist/agents/tool-filter.d.ts +29 -46
  31. package/dist/agents/tool-filter.js +8 -31
  32. package/dist/agents/verify.d.ts +3 -3
  33. package/dist/brain/anthropic.js +14 -9
  34. package/dist/brain/errors.d.ts +15 -0
  35. package/dist/brain/errors.js +10 -0
  36. package/dist/brain/model-presets.d.ts +4 -4
  37. package/dist/brain/open-responses.js +15 -10
  38. package/dist/brain/openai.js +17 -12
  39. package/dist/brain/provider-dialect.d.ts +39 -3
  40. package/dist/brain/provider-dialect.js +28 -0
  41. package/dist/brain/reasoning.d.ts +1 -1
  42. package/dist/brain/request-params.d.ts +55 -5
  43. package/dist/brain/request-params.js +35 -3
  44. package/dist/brain/retry.d.ts +1 -1
  45. package/dist/brain/route-adjudicator.d.ts +15 -0
  46. package/dist/brain/route-adjudicator.js +15 -0
  47. package/dist/brain/stream-engine.js +6 -5
  48. package/dist/brain/stream-shared.d.ts +1 -1
  49. package/dist/core/advisor-verdict.d.ts +120 -0
  50. package/dist/core/advisor-verdict.js +92 -0
  51. package/dist/core/agent-definition.d.ts +7 -8
  52. package/dist/core/allow-entry.d.ts +49 -23
  53. package/dist/core/allow-entry.js +57 -32
  54. package/dist/core/allow-rule-shadow.d.ts +7 -0
  55. package/dist/core/approval-object.d.ts +2 -1
  56. package/dist/core/approval-object.js +6 -6
  57. package/dist/core/ask-origin.d.ts +63 -11
  58. package/dist/core/ask-origin.js +27 -5
  59. package/dist/core/ask-question.js +10 -4
  60. package/dist/core/auto-compaction.d.ts +11 -8
  61. package/dist/core/auto-compaction.js +4 -2
  62. package/dist/core/auto-mode-arming.d.ts +2 -2
  63. package/dist/core/auto-mode-defaults.d.ts +8 -8
  64. package/dist/core/auto-mode-prompt-assets.d.ts +3 -3
  65. package/dist/core/auto-mode-prompt.d.ts +1 -1
  66. package/dist/core/auto-mode.d.ts +17 -9
  67. package/dist/core/auto-mode.js +9 -6
  68. package/dist/core/background-agent-store.d.ts +3 -3
  69. package/dist/core/canonical-json.d.ts +1 -1
  70. package/dist/core/canonical-json.js +2 -2
  71. package/dist/core/checkpoint-requirements.d.ts +6 -3
  72. package/dist/core/checkpoint-requirements.js +4 -14
  73. package/dist/core/checkpoint-store.d.ts +80 -51
  74. package/dist/core/checkpoint-store.js +56 -74
  75. package/dist/core/child-clamp-seats.d.ts +6 -0
  76. package/dist/core/child-clamp-seats.js +3 -16
  77. package/dist/core/compliance.d.ts +2 -2
  78. package/dist/core/context-edit.d.ts +6 -7
  79. package/dist/core/cross-boundary-taint.d.ts +9 -3
  80. package/dist/core/cross-boundary-taint.js +5 -3
  81. package/dist/core/decision-receipt.js +2 -2
  82. package/dist/core/effective-path-target.d.ts +1 -1
  83. package/dist/core/engine-notice.d.ts +19 -5
  84. package/dist/core/exec-output-tail.d.ts +1 -1
  85. package/dist/core/file-history-retention.d.ts +1 -1
  86. package/dist/core/file-history-store.d.ts +59 -9
  87. package/dist/core/file-history-store.js +35 -17
  88. package/dist/core/gate-fold.js +3 -2
  89. package/dist/core/gate-lanes.js +12 -8
  90. package/dist/core/gate-outcome.d.ts +17 -4
  91. package/dist/core/gate-outcome.js +30 -0
  92. package/dist/core/governance-codes.d.ts +13 -3
  93. package/dist/core/governance-codes.js +10 -0
  94. package/dist/core/hands-band.d.ts +1 -1
  95. package/dist/core/hooks.d.ts +4 -4
  96. package/dist/core/host-target.d.ts +49 -0
  97. package/dist/core/host-target.js +59 -0
  98. package/dist/core/image-downsample.d.ts +1 -1
  99. package/dist/core/lsp-diagnostics.d.ts +4 -4
  100. package/dist/core/lsp.d.ts +3 -3
  101. package/dist/core/mailbox-store.d.ts +4 -0
  102. package/dist/core/mcp-connection-pool.d.ts +18 -2
  103. package/dist/core/mcp-connection-pool.js +53 -6
  104. package/dist/core/mcp-failure.d.ts +23 -4
  105. package/dist/core/mcp-failure.js +26 -11
  106. package/dist/core/mcp-listing-drift.d.ts +10 -0
  107. package/dist/core/mcp-listing-drift.js +6 -0
  108. package/dist/core/mcp-server-link.d.ts +173 -0
  109. package/dist/core/mcp-server-link.js +127 -0
  110. package/dist/core/mcp-server-spec.d.ts +4 -2
  111. package/dist/core/mcp-session-end.d.ts +26 -0
  112. package/dist/core/mcp-session-end.js +29 -0
  113. package/dist/core/mcp-startup-request.d.ts +17 -0
  114. package/dist/core/mcp-startup-request.js +17 -0
  115. package/dist/core/mcp.d.ts +13 -13
  116. package/dist/core/mcp.js +187 -162
  117. package/dist/core/media-byte-cap.d.ts +1 -1
  118. package/dist/core/memory-engine/engine.d.ts +9 -9
  119. package/dist/core/memory-engine/provenance-wording.d.ts +1 -1
  120. package/dist/core/memory-engine/tools.js +4 -1
  121. package/dist/core/mode-policy.d.ts +1 -1
  122. package/dist/core/namespaced-rule-name.d.ts +33 -7
  123. package/dist/core/namespaced-rule-name.js +39 -25
  124. package/dist/core/output-style.d.ts +1 -1
  125. package/dist/core/param-rule-reach.d.ts +15 -0
  126. package/dist/core/param-rule-reach.js +30 -0
  127. package/dist/core/parent-spec-seat.d.ts +8 -1
  128. package/dist/core/parent-spec-seat.js +4 -0
  129. package/dist/core/pause-registry.d.ts +16 -5
  130. package/dist/core/pause-registry.js +6 -2
  131. package/dist/core/peer-channel.d.ts +70 -0
  132. package/dist/core/peer-channel.js +1 -0
  133. package/dist/core/permission-rule-consent.d.ts +11 -5
  134. package/dist/core/permission-rule-consent.js +37 -30
  135. package/dist/core/permission-rule-model.d.ts +233 -64
  136. package/dist/core/permission-rule-model.js +384 -85
  137. package/dist/core/permission-rule-provider.d.ts +2 -1
  138. package/dist/core/permission-rule-store.d.ts +20 -25
  139. package/dist/core/permission-rule-store.js +1 -4
  140. package/dist/core/permission-rule-sync.d.ts +11 -2
  141. package/dist/core/permission-rule-sync.js +8 -1
  142. package/dist/core/permission-rules.d.ts +49 -11
  143. package/dist/core/permission-rules.js +123 -89
  144. package/dist/core/persisted-rule-arms.d.ts +4 -2
  145. package/dist/core/present-plan-tool.js +3 -1
  146. package/dist/core/protocol-naming.d.ts +2 -2
  147. package/dist/core/read-only-shell-table.d.ts +1 -1
  148. package/dist/core/read-only-shell.d.ts +1 -1
  149. package/dist/core/roles.d.ts +6 -2
  150. package/dist/core/roles.js +45 -44
  151. package/dist/core/rule-offer-read.d.ts +53 -0
  152. package/dist/core/rule-offer-read.js +146 -0
  153. package/dist/core/rule-owner.d.ts +46 -0
  154. package/dist/core/rule-owner.js +28 -0
  155. package/dist/core/runner/advisor-instructions.d.ts +70 -0
  156. package/dist/core/runner/advisor-instructions.js +61 -0
  157. package/dist/core/runner/advisor-tool.d.ts +33 -0
  158. package/dist/core/runner/advisor-tool.js +112 -0
  159. package/dist/core/runner/announce-once-ledger.d.ts +4 -26
  160. package/dist/core/runner/announce-once-ledger.js +14 -46
  161. package/dist/core/runner/approval-feedback.js +6 -3
  162. package/dist/core/runner/assemble-result.d.ts +1 -1
  163. package/dist/core/runner/caller-roster.d.ts +7 -0
  164. package/dist/core/runner/caller-roster.js +11 -0
  165. package/dist/core/runner/classifier-ladder.d.ts +27 -5
  166. package/dist/core/runner/classifier-ladder.js +12 -11
  167. package/dist/core/runner/compaction-restate.d.ts +10 -6
  168. package/dist/core/runner/compaction-restate.js +9 -3
  169. package/dist/core/runner/contracts.d.ts +13 -9
  170. package/dist/core/runner/conversation-segment.d.ts +28 -0
  171. package/dist/core/runner/conversation-segment.js +42 -0
  172. package/dist/core/runner/cross-boundary-lane.d.ts +6 -5
  173. package/dist/core/runner/cross-boundary-lane.js +26 -15
  174. package/dist/core/runner/decide-continuation.d.ts +7 -4
  175. package/dist/core/runner/decide-continuation.js +2 -2
  176. package/dist/core/runner/denial-limit-arms.d.ts +2 -2
  177. package/dist/core/runner/derived-route-fallback.d.ts +24 -24
  178. package/dist/core/runner/derived-route-fallback.js +9 -7
  179. package/dist/core/runner/gate-exit.d.ts +6 -0
  180. package/dist/core/runner/gate-exit.js +7 -2
  181. package/dist/core/runner/initial-run-state.js +1 -1
  182. package/dist/core/runner/permission-rule-lanes.d.ts +2 -2
  183. package/dist/core/runner/permission-rule-lanes.js +14 -7
  184. package/dist/core/runner/person-path-rows.js +1 -1
  185. package/dist/core/runner/prepare-advisor.d.ts +63 -0
  186. package/dist/core/runner/prepare-advisor.js +77 -0
  187. package/dist/core/runner/prepare-caps-and-workflow.js +1 -1
  188. package/dist/core/runner/prepare-config-doors.d.ts +6 -4
  189. package/dist/core/runner/prepare-config-doors.js +18 -12
  190. package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
  191. package/dist/core/runner/prepare-delegation-surface.js +1 -1
  192. package/dist/core/runner/prepare-file-history.js +39 -39
  193. package/dist/core/runner/prepare-gate-stations.d.ts +1 -4
  194. package/dist/core/runner/prepare-gate-stations.js +2 -7
  195. package/dist/core/runner/prepare-inherited-gate.d.ts +5 -4
  196. package/dist/core/runner/prepare-inherited-gate.js +3 -3
  197. package/dist/core/runner/prepare-park-ask.js +7 -7
  198. package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
  199. package/dist/core/runner/prepare-policy-chain.js +4 -10
  200. package/dist/core/runner/prepare-project-context.d.ts +5 -2
  201. package/dist/core/runner/prepare-project-context.js +6 -3
  202. package/dist/core/runner/prepare-prompt-inputs.js +1 -1
  203. package/dist/core/runner/prepare-protocol-tools.d.ts +2 -2
  204. package/dist/core/runner/prepare-protocol-tools.js +3 -2
  205. package/dist/core/runner/prepare-safety-scan.d.ts +9 -12
  206. package/dist/core/runner/prepare-safety-scan.js +8 -6
  207. package/dist/core/runner/prepare-task.js +15 -18
  208. package/dist/core/runner/prepare-tool-disclosure-mount.js +6 -4
  209. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -3
  210. package/dist/core/runner/prepare-wiring-manifest.js +2 -2
  211. package/dist/core/runner/resume-policy-outcome.js +1 -1
  212. package/dist/core/runner/retired-runner-deps.js +1 -1
  213. package/dist/core/runner/run-attachment-seats.js +0 -1
  214. package/dist/core/runner/run-compaction-machinery.d.ts +1 -1
  215. package/dist/core/runner/run-compaction-machinery.js +2 -12
  216. package/dist/core/runner/run-git-lane.d.ts +1 -0
  217. package/dist/core/runner/run-harness-handlers.js +2 -3
  218. package/dist/core/runner/run-leg.js +13 -0
  219. package/dist/core/runner/run-settle-and-teardown.js +1 -1
  220. package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
  221. package/dist/core/runner/run-turn-boundary.d.ts +1 -0
  222. package/dist/core/runner/run-turn-boundary.js +14 -12
  223. package/dist/core/runner/session-rule-policy.d.ts +22 -21
  224. package/dist/core/runner/session-rule-policy.js +13 -28
  225. package/dist/core/runner/side-call-account.d.ts +32 -8
  226. package/dist/core/runner/side-call-account.js +23 -1
  227. package/dist/core/runner/strict-output-schema.d.ts +1 -1
  228. package/dist/core/runner/sub-agent-deny-lists.js +4 -3
  229. package/dist/core/runner/synthetic-tools.d.ts +10 -13
  230. package/dist/core/runner/synthetic-tools.js +4 -2
  231. package/dist/core/runner/tool-disclosure.js +2 -1
  232. package/dist/core/runner/tool-face-overlay.d.ts +2 -1
  233. package/dist/core/runner/tool-face-overlay.js +17 -1
  234. package/dist/core/runner/tool-progress-lane.d.ts +2 -2
  235. package/dist/core/runner/tool-turn-repair-seat.d.ts +3 -2
  236. package/dist/core/runner/turn-attachments.d.ts +60 -67
  237. package/dist/core/runner-deps.d.ts +37 -37
  238. package/dist/core/runtime-caps.d.ts +4 -4
  239. package/dist/core/safety-merge-corpus.js +17 -1
  240. package/dist/core/same-plain-value.d.ts +40 -0
  241. package/dist/core/same-plain-value.js +49 -0
  242. package/dist/core/scheduler.d.ts +1 -1
  243. package/dist/core/sensitive-path-policy.d.ts +1 -1
  244. package/dist/core/sensitive-path-policy.js +1 -1
  245. package/dist/core/session-policy-store.d.ts +77 -22
  246. package/dist/core/session-policy-store.js +56 -14
  247. package/dist/core/session-reconcile.d.ts +2 -2
  248. package/dist/core/session-store.d.ts +80 -30
  249. package/dist/core/session-store.js +118 -76
  250. package/dist/core/session.d.ts +24 -46
  251. package/dist/core/shared-memory/tools.js +3 -1
  252. package/dist/core/shared-memory/types.d.ts +1 -1
  253. package/dist/core/side-query.d.ts +10 -0
  254. package/dist/core/side-query.js +5 -0
  255. package/dist/core/store-contracts/checkpoint-store-contract.js +29 -2
  256. package/dist/core/store-contracts/file-history-store-contract.js +43 -3
  257. package/dist/core/store-contracts/session-policy-store-contract.d.ts +7 -0
  258. package/dist/core/store-contracts/session-policy-store-contract.js +130 -0
  259. package/dist/core/store-contracts/session-repo-contract.js +125 -0
  260. package/dist/core/store-contracts/session-store-contract.d.ts +4 -7
  261. package/dist/core/store-contracts/session-store-contract.js +215 -41
  262. package/dist/core/store-contracts/workflow-journal-store-contract.js +26 -1
  263. package/dist/core/surrogate-safe-slice.d.ts +3 -3
  264. package/dist/core/task-event.d.ts +10 -4
  265. package/dist/core/task-notification.d.ts +3 -3
  266. package/dist/core/task-registry-agent.d.ts +4 -4
  267. package/dist/core/task-registry-shared.d.ts +4 -4
  268. package/dist/core/task-registry-shared.js +1 -0
  269. package/dist/core/task-registry.d.ts +4 -4
  270. package/dist/core/task-registry.js +3 -1
  271. package/dist/core/task-result.d.ts +3 -3
  272. package/dist/core/task-spec.d.ts +52 -52
  273. package/dist/core/task-stream.d.ts +6 -6
  274. package/dist/core/task-tool-shape.d.ts +4 -4
  275. package/dist/core/tighten-task-spec.d.ts +1 -1
  276. package/dist/core/tool-catalog-entries.d.ts +19 -2
  277. package/dist/core/tool-catalog-entries.js +57 -42
  278. package/dist/core/tool-conformance.js +1 -0
  279. package/dist/core/tool-errors.d.ts +2 -2
  280. package/dist/core/tool-face-reader.js +5 -3
  281. package/dist/core/tool-face.d.ts +21 -2
  282. package/dist/core/tool-face.js +1 -1
  283. package/dist/core/tool-model-gate.d.ts +3 -3
  284. package/dist/core/tool-name-aliases.d.ts +29 -8
  285. package/dist/core/tool-name-aliases.js +27 -3
  286. package/dist/core/tool-name-readings.d.ts +5 -8
  287. package/dist/core/tool-name-readings.js +1 -2
  288. package/dist/core/tool-policy.d.ts +24 -5
  289. package/dist/core/tool-policy.js +34 -10
  290. package/dist/core/tool-registry.d.ts +14 -7
  291. package/dist/core/tool-registry.js +17 -7
  292. package/dist/core/tool-result-store.js +2 -1
  293. package/dist/core/tool-roster.d.ts +47 -18
  294. package/dist/core/tool-roster.js +53 -32
  295. package/dist/core/tool-spec-members.js +1 -1
  296. package/dist/core/tool-spec.d.ts +35 -21
  297. package/dist/core/tools.js +3 -2
  298. package/dist/core/trace.d.ts +4 -0
  299. package/dist/core/untrusted-egress.d.ts +1 -1
  300. package/dist/core/untrusted-text.d.ts +1 -1
  301. package/dist/core/warm-resume.d.ts +1 -1
  302. package/dist/core/wiring-manifest.d.ts +49 -0
  303. package/dist/core/wiring-manifest.js +13 -5
  304. package/dist/core/workflow-journal-store.d.ts +62 -0
  305. package/dist/core/workflow-journal-store.js +77 -1
  306. package/dist/core/workflow-run-store.d.ts +6 -0
  307. package/dist/core/workflow-run-store.js +2 -0
  308. package/dist/engine/compaction/compaction.d.ts +9 -9
  309. package/dist/engine/execution-env/node-execution-env.d.ts +19 -5
  310. package/dist/engine/execution-env/node-execution-env.js +43 -22
  311. package/dist/engine/harness/agent-harness.d.ts +14 -8
  312. package/dist/engine/harness/agent-harness.js +33 -26
  313. package/dist/engine/harness/types.d.ts +29 -7
  314. package/dist/engine/harness/types.js +12 -1
  315. package/dist/engine/llm/types.d.ts +9 -9
  316. package/dist/engine/llm/validation.d.ts +4 -1
  317. package/dist/engine/llm/validation.js +13 -1
  318. package/dist/engine/loop/agent-loop.d.ts +1 -1
  319. package/dist/engine/loop/agent-loop.js +10 -8
  320. package/dist/engine/loop/types.d.ts +15 -13
  321. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  322. package/dist/engine/session/memory-repo.d.ts +10 -11
  323. package/dist/engine/session/memory-repo.js +13 -8
  324. package/dist/engine/session/parent-chain-guard.d.ts +3 -2
  325. package/dist/engine/session/parent-chain-guard.js +1 -1
  326. package/dist/engine/session/repo-utils.d.ts +31 -3
  327. package/dist/engine/session/repo-utils.js +42 -5
  328. package/dist/index.d.ts +27 -15
  329. package/dist/index.js +21 -11
  330. package/dist/internal/harness-types.d.ts +1 -1
  331. package/dist/internal/harness.d.ts +3 -3
  332. package/dist/internal/harness.js +2 -2
  333. package/dist/internal/llm.d.ts +1 -1
  334. package/dist/internal/llm.js +1 -1
  335. package/dist/orchestration/goal.js +2 -2
  336. package/dist/orchestration/run-workflow-tool.d.ts +2 -2
  337. package/dist/orchestration/run-workflow-tool.js +5 -3
  338. package/dist/orchestration/workflow-size-guideline.d.ts +4 -4
  339. package/dist/orchestration/workflow-types.d.ts +18 -0
  340. package/dist/orchestration/workflow-types.js +6 -0
  341. package/dist/orchestration/workflow.d.ts +2 -13
  342. package/dist/orchestration/workflow.js +21 -31
  343. package/dist/prompt-assembly/event-registry.js +1 -0
  344. package/dist/prompt-assembly/tool-catalog.d.ts +3 -0
  345. package/dist/prompt-assembly/tool-catalog.js +3 -0
  346. package/dist/prompts/default.d.ts +14 -14
  347. package/dist/scenarios/full-body.d.ts +4 -4
  348. package/dist/stores/file/adoption/adopt.d.ts +4 -3
  349. package/dist/stores/file/adoption/adopt.js +24 -31
  350. package/dist/stores/file/adoption/marker.d.ts +6 -13
  351. package/dist/stores/file/adoption/marker.js +6 -15
  352. package/dist/stores/file/checkpoint-store.d.ts +3 -0
  353. package/dist/stores/file/checkpoint-store.js +9 -3
  354. package/dist/stores/file/file-history-store.d.ts +20 -19
  355. package/dist/stores/file/file-history-store.js +152 -135
  356. package/dist/stores/file/fs-atomic.d.ts +15 -0
  357. package/dist/stores/file/fs-atomic.js +89 -14
  358. package/dist/stores/file/index.d.ts +1 -1
  359. package/dist/stores/file/mailbox-store.d.ts +3 -0
  360. package/dist/stores/file/mailbox-store.js +3 -1
  361. package/dist/stores/file/permission-rule-adopt.d.ts +1 -1
  362. package/dist/stores/file/permission-rule-adopt.js +15 -16
  363. package/dist/stores/file/permission-rule-store.d.ts +18 -2
  364. package/dist/stores/file/permission-rule-store.js +21 -14
  365. package/dist/stores/file/session-policy-store.d.ts +3 -3
  366. package/dist/stores/file/session-store.d.ts +26 -11
  367. package/dist/stores/file/session-store.js +77 -40
  368. package/dist/stores/file/workflow-journal-store.d.ts +10 -4
  369. package/dist/stores/file/workflow-journal-store.js +28 -13
  370. package/dist/tools/artifact/artifact-text.d.ts +1 -1
  371. package/dist/tools/artifact/artifact-tool.js +2 -1
  372. package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -3
  373. package/dist/tools/fs/fs-bash.d.ts +2 -2
  374. package/dist/tools/fs/fs-bash.js +3 -1
  375. package/dist/tools/fs/fs-shared.d.ts +8 -8
  376. package/dist/tools/fs/gh-rate-limit.d.ts +1 -1
  377. package/dist/tools/fs/notebook.d.ts +2 -2
  378. package/dist/tools/fs/read-deny.d.ts +29 -7
  379. package/dist/tools/fs/read-deny.js +63 -22
  380. package/dist/tools/fs/removal-targets.d.ts +1 -1
  381. package/dist/tools/fs/safety.d.ts +9 -9
  382. package/dist/tools/fs/search.d.ts +6 -6
  383. package/dist/tools/fs/shell-read-check.js +6 -1
  384. package/dist/tools/fs/shell-read-judge.d.ts +4 -0
  385. package/dist/tools/fs/shell-read-judge.js +5 -2
  386. package/dist/tools/loop-tick.d.ts +2 -2
  387. package/dist/tools/scheduler-tools.js +5 -1
  388. package/dist/tools/task-list.d.ts +7 -7
  389. package/dist/tools/task-list.js +5 -1
  390. package/dist/tools/todo.js +2 -1
  391. package/dist/tools/web.d.ts +1 -1
  392. package/dist/tools/web.js +40 -37
  393. package/dist/tools/worktree.d.ts +3 -3
  394. package/dist/tools/worktree.js +3 -1
  395. package/package.json +1 -1
  396. package/test/export-surface.snapshot.json +5756 -5638
  397. package/wire-changes/core@7.55.0.json +3318 -0
  398. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +0 -39
  399. 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
2
  import { MCP_NAMESPACE, protocolOf } 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,28 @@ 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,
34
38
  };
35
39
  import { isNamespacedCoveringRuleName, namespacedRuleNameCovers, wildcardMatch } from "./namespaced-rule-name.js";
40
+ import { wildcardPeerRefusalOf } from "./tool-name-aliases.js";
36
41
  export { isNamespacedCoveringRuleName, namespacedRuleNameCovers, wildcardMatch };
42
+ const vocabularyOf = (face) => face.params ?? face.primaryParams;
43
+ const carriedPhrase = (face) => {
44
+ const vocabulary = vocabularyOf(face);
45
+ if (vocabulary.length > 0)
46
+ return `it carries ${[...vocabulary].sort().join(", ")}`;
47
+ return face.params !== undefined ? "it declares no rule-readable parameters" : "its parameters are not declared statically: each mount's schema is its own";
48
+ };
37
49
  export function catalogRuleFaceView(toolName) {
38
- const face = catalogRuleFaceOf(toolName);
39
- if (face === undefined)
40
- return undefined;
41
- return { ...face, pathTargeting: pathTargetOf(toolName) !== undefined };
50
+ return catalogRuleFaceOf(toolName);
42
51
  }
43
52
  export const fileToolParamVocabulary = (canonicalTool) => {
44
53
  const face = catalogRuleFaceOf(canonicalTool);
@@ -83,25 +92,25 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
83
92
  const command = { deny: [], ask: [] };
84
93
  const namespacedCovering = { deny: [], ask: [] };
85
94
  const issues = [];
86
- const bad = (rule, code, message) => {
87
- issues.push({ rule, code, message });
95
+ const bad = (rule, code, message, libraryOption) => {
96
+ issues.push(ruleIssue(rule, code, message, libraryOption));
88
97
  };
89
98
  if (rules.length > caps.maxRules) {
90
- return { byTool, command, namespacedCovering, issues: [{ rule: "", code: "invalid.cap_exceeded", message: `${rules.length} rules > maxRules ${caps.maxRules}` }] };
99
+ return { byTool, command, namespacedCovering, issues: [ruleIssue("", "invalid.cap_exceeded", `${rules.length} rules — a rule set holds at most ${caps.maxRules}`, { name: "caps.maxRules" })] };
91
100
  }
92
101
  for (const r of rules) {
93
102
  const text = r.rule;
94
103
  const behavior = r.behavior;
95
104
  if (behavior !== "deny" && behavior !== "ask") {
96
105
  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");
106
+ 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
107
  else
99
108
  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
109
  continue;
101
110
  }
102
111
  const verb = behavior;
103
112
  if (text.length > caps.maxRuleLength) {
104
- bad(text, "invalid.cap_exceeded", `rule longer than ${caps.maxRuleLength} chars`);
113
+ bad(text, "invalid.cap_exceeded", `rule longer than ${caps.maxRuleLength} chars`, { name: "caps.maxRuleLength" });
105
114
  continue;
106
115
  }
107
116
  const parsed = ruleSpellingOf(text);
@@ -111,23 +120,29 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
111
120
  continue;
112
121
  }
113
122
  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\``);
123
+ 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", { name: "defaultAction" });
115
124
  continue;
116
125
  }
117
126
  const toolName = parsed.toolName;
118
127
  const parenthesised = parsed.ruleContent !== undefined || indexOfUnescaped(text, "(") !== -1;
119
128
  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");
129
+ 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
130
  continue;
122
131
  }
123
- if (parenthesised && isNamespacedCoveringRuleName(toolName)) {
132
+ const wildPeer = wildcardPeerRefusalOf(toolName, verb);
133
+ if (wildPeer !== undefined) {
134
+ bad(text, "invalid.tool_name", wildPeer);
135
+ continue;
136
+ }
137
+ if (parenthesised && isNamespacedCoveringRuleName(toolName, verb)) {
124
138
  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
139
  `Write the parenthesised rule against one exact tool name, or drop the parentheses to keep the covering rule.`);
126
140
  continue;
127
141
  }
128
142
  const entry = byTool.get(toolName) ?? { bare: {}, param: { deny: [], ask: [] }, content: { deny: [], ask: [] } };
129
- if (parsed.ruleContent === undefined) {
130
- if (isNamespacedCoveringRuleName(toolName)) {
143
+ const content = ruleContentOf(parsed);
144
+ if (content === undefined) {
145
+ if (isNamespacedCoveringRuleName(toolName, verb)) {
131
146
  namespacedCovering[verb].push({ ruleName: toolName, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
132
147
  continue;
133
148
  }
@@ -135,52 +150,70 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
135
150
  byTool.set(toolName, entry);
136
151
  continue;
137
152
  }
138
- const content = parsed.ruleContent;
139
153
  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.`
154
+ let face;
155
+ if (!isShellFaceToolName(toolName)) {
156
+ const resolved = faceOf(toolName);
157
+ if (resolved.judged && resolved.face === undefined) {
158
+ bad(text, "unsupported.tool_unknown", `"${toolName}" is not a tool on this leg's roster — the rule would compile and never match`);
159
+ continue;
160
+ }
161
+ face = resolved.face;
162
+ }
163
+ const lane = ruleLaneOf(toolName, content);
164
+ if (lane === "command") {
165
+ if (toolName !== COMMAND_RULE_TOOL) {
166
+ const commandWordParam = shellRuleParamOf(COMMAND_RULE_TOOL, content);
167
+ bad(text, "invalid.command_rule", commandWordParam !== undefined && !content.endsWith(":*")
168
+ ? `"${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
169
  : `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
170
  continue;
150
171
  }
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 } : {}) });
172
+ const parsedCommand = parseRuleText(text, verb);
173
+ if ("reject" in parsedCommand) {
174
+ bad(text, "invalid.command_rule", `${parsedCommand.reject.code}: ${parsedCommand.reject.message}`);
158
175
  continue;
159
176
  }
177
+ command[verb].push({ parsed: parsedCommand.rule, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
178
+ continue;
160
179
  }
161
180
  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)) {
181
+ if (lane === "name") {
169
182
  const parsedName = parseRuleText(text, verb);
170
183
  if ("reject" in parsedName) {
171
184
  bad(text, "invalid.command_rule", `${parsedName.reject.code}: ${parsedName.reject.message}`);
172
185
  continue;
173
186
  }
174
187
  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`);
188
+ if (face !== undefined && !vocabularyOf(face).includes(param)) {
189
+ 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`);
190
+ continue;
191
+ }
192
+ const mountedOnly = mountedOnlyArgumentOf(toolName, content, face?.params);
193
+ if (mountedOnly !== undefined) {
194
+ 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`);
195
+ continue;
196
+ }
197
+ const resolved = face?.nameValues !== undefined ? canonicalNameValue(parsedName.rule.command, face.nameValues) : undefined;
198
+ if (resolved?.kind === "ambiguous") {
199
+ 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
200
  continue;
178
201
  }
179
202
  entry.content[verb].push({ parsed: parsedName.rule, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
180
203
  byTool.set(toolName, entry);
181
204
  continue;
182
205
  }
183
- if (face !== undefined && face.pathTargeting === true && colon <= 0) {
206
+ if (lane === "domain") {
207
+ const parsedHost = parseRuleText(text, verb);
208
+ if ("reject" in parsedHost) {
209
+ bad(text, "invalid.command_rule", `${parsedHost.reject.code}: ${parsedHost.reject.message}`);
210
+ continue;
211
+ }
212
+ entry.content[verb].push({ parsed: parsedHost.rule, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
213
+ byTool.set(toolName, entry);
214
+ continue;
215
+ }
216
+ if (lane === "path") {
184
217
  const parsedPath = parseRuleText(text, verb);
185
218
  if ("reject" in parsedPath) {
186
219
  bad(text, "invalid.command_rule", `${parsedPath.reject.code}: ${parsedPath.reject.message}`);
@@ -189,7 +222,7 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
189
222
  for (const base of ruleBasesNeeded(parsedPath.rule)) {
190
223
  const declared = base === "cwd" ? (pathBases.cwd ?? pathBases.root) : pathBases[base];
191
224
  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`);
225
+ 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
226
  }
194
227
  }
195
228
  if (issues.length > 0 && issues[issues.length - 1].rule === text && issues[issues.length - 1].code === "unsupported.path_base")
@@ -199,15 +232,21 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
199
232
  byTool.set(toolName, entry);
200
233
  continue;
201
234
  }
202
- if (face?.params !== undefined && colon > 0) {
235
+ if (face !== undefined && colon > 0) {
203
236
  const paramPart = content.slice(0, colon).trim();
204
- if (!face.params.includes(paramPart)) {
237
+ const vocabulary = vocabularyOf(face);
238
+ if (!vocabulary.includes(paramPart)) {
205
239
  if (face.nonScalar?.includes(paramPart)) {
206
240
  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
241
  }
208
242
  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".`);
243
+ const statesNothing = face.params === undefined && vocabulary.length === 0;
244
+ bad(text, "unsupported.param_unknown", statesNothing
245
+ ? `"${paramPart}" cannot be judged on ${toolName} here (${carriedPhrase(face)}) — write the rule on the whole tool (\`${toolName}\`).`
246
+ : `"${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. ` +
247
+ (pathTargetOf(toolName) !== undefined
248
+ ? `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".`
249
+ : `${vocabulary.length > 0 ? "Name one of its parameters, or write" : "Write"} the rule on the whole tool (\`${toolName}\`).`), statesNothing ? { name: "ruleFaces" } : undefined);
211
250
  }
212
251
  continue;
213
252
  }
@@ -224,14 +263,19 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
224
263
  continue;
225
264
  }
226
265
  if (pattern.length > caps.maxPatternLength || countStars(pattern) > caps.maxStars) {
227
- bad(text, "invalid.cap_exceeded", `pattern exceeds maxPatternLength ${caps.maxPatternLength} or maxStars ${caps.maxStars}`);
266
+ 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
267
  continue;
229
268
  }
230
269
  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.`);
270
+ const form = ruleShapeOf({ toolName, args: {} }, verb);
271
+ 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\`. ` +
272
+ `Write the rule ${form === undefined ? "" : `as \`${form}\`, or `}on the whole tool (\`${toolName}\`).`, { name: "primaryFieldGeneric", value: "allow-lexical" });
232
273
  continue;
233
274
  }
234
275
  entry.param[verb].push({ param, pattern, behavior: verb, ruleText: text, source: r.source });
276
+ const valueArm = mountedValueArmOf(text, toolName, verb);
277
+ if (valueArm !== undefined)
278
+ entry.content[verb].push({ parsed: valueArm, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
235
279
  byTool.set(toolName, entry);
236
280
  }
237
281
  return { byTool, command, namespacedCovering, issues };
@@ -244,42 +288,10 @@ function isPlainObjectArgs(args) {
244
288
  return typeof args === "object" && args !== null && !Array.isArray(args);
245
289
  }
246
290
  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
- }
291
+ return rules.find((r) => paramRuleReaches(req, r.param, r.pattern, maxScalarValueChars));
280
292
  }
281
- function ruleDenial(req, ruleText, source) {
282
- return ruleDenialSentence({ source: "permission", tool: req.toolName, rule: ruleText, ...(source ? { origin: source } : {}) });
293
+ function ruleDenial(req, ruleText, source, detail) {
294
+ return ruleDenialSentence({ source: "permission", tool: req.toolName, rule: ruleText, ...(source ? { origin: source } : {}), ...(detail !== undefined ? { detail } : {}) });
283
295
  }
284
296
  function ruleAskMessage(ruleText, source) {
285
297
  return `flagged by permission rule "${ruleText}"${source ? ` (${source})` : ""}`;
@@ -386,11 +398,33 @@ export function createPermissionRulePolicy(rules, opts) {
386
398
  const judgeOthers = (lane, req) => {
387
399
  const command = isPlainObjectArgs(req.args) ? req.args[commandParam] : undefined;
388
400
  let unreadable;
401
+ let host = null;
389
402
  for (const r of lane) {
390
403
  if (r.parsed.match === "name" || r.parsed.match === "name_prefix") {
391
404
  const named = nameRuleSubjectOf(r.parsed.tool, req.args);
392
- if (named !== undefined && nameRuleAdmits(r.parsed, named))
405
+ if (named === undefined)
406
+ continue;
407
+ const reach = nameRuleReach(r.parsed, named, req.face?.nameValues);
408
+ if (reach === "reached")
393
409
  return { rule: r };
410
+ if (reach === "unread")
411
+ unreadable ??= { rule: r, unreadable: nameValuesUnreadReason(r.parsed.tool) };
412
+ continue;
413
+ }
414
+ if (r.parsed.match === "host" || r.parsed.match === "subdomain") {
415
+ if (host === null)
416
+ host = callHostTargetOf(req, "tighten");
417
+ if (host === undefined)
418
+ continue;
419
+ if ("host" in host) {
420
+ if (domainRuleAdmits(r.parsed, host.host))
421
+ return { rule: r };
422
+ continue;
423
+ }
424
+ const why = `the host the call reaches cannot be read (${HOST_UNREADABLE_SENTENCE[host.unreadable]})`;
425
+ if (r.parsed.behavior === "deny")
426
+ return { rule: r, detail: why };
427
+ unreadable ??= { rule: r, unreadable: why };
394
428
  continue;
395
429
  }
396
430
  if (typeof command !== "string")
@@ -407,7 +441,7 @@ export function createPermissionRulePolicy(rules, opts) {
407
441
  for (const r of [...entry.content.deny, ...entry.content.ask]) {
408
442
  if (r.parsed.match !== "name" || nameRuleSubjectOf(r.parsed.tool, req.args) !== undefined)
409
443
  continue;
410
- const absent = keyedValueAbsentReason(r.parsed.tool);
444
+ const absent = nameValueAbsentReason(r.parsed.tool);
411
445
  if (absent !== undefined)
412
446
  return ruleDenialSentence({ source: "permission", tool: req.toolName, rule: r.ruleText, ...(r.source ? { origin: r.source } : {}), detail: absent });
413
447
  }
@@ -454,7 +488,7 @@ export function createPermissionRulePolicy(rules, opts) {
454
488
  const denyLane = contentLaneOf("deny", entry, shellCall, callFace);
455
489
  const contentDeny = denyLane.length > 0 ? contentHit(denyLane, req) : undefined;
456
490
  if (contentDeny !== undefined && contentDeny.unreadable === undefined) {
457
- const denied = { action: "deny", message: ruleDenial(req, contentDeny.rule.ruleText, contentDeny.rule.source) };
491
+ const denied = { action: "deny", message: ruleDenial(req, contentDeny.rule.ruleText, contentDeny.rule.source, contentDeny.detail) };
458
492
  const face = contentDeny.view !== undefined ? callPathFaceOf(req) : undefined;
459
493
  return face !== undefined ? attest(denied, req, { pathDenial: { rule: contentDeny.rule.ruleText, view: contentDeny.view, face } }) : denied;
460
494
  }
@@ -61,8 +61,10 @@ 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.
@@ -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({
@@ -1,13 +1,13 @@
1
1
  import type { ProtocolNamespace } from "./protocol-table.js";
2
2
  /** The provider's tool-name pattern is `^[a-zA-Z0-9_-]{1,64}$` — the limit applies to the ASSEMBLED name,
3
- * not to its segments (design/116 W5-5, CC 2.1.187 parity `buildMcpToolName`). */
3
+ * not to its segments (design/116 W5-5). */
4
4
  export declare const TOOL_NAME_MAX_CHARS = 64;
5
5
  /** Reserved for the tool segment when budgeting the peer segment: a peer kept at the full name budget
6
6
  * overflows the assembled name on its own (prefix + 64 + separator = 71 > 64), which is how the tool
7
7
  * segment used to be handed a NEGATIVE budget. A tool name shorter than this is not recognizable. */
8
8
  export declare const MINTED_TOOL_SEGMENT_MIN_CHARS = 16;
9
9
  /**
10
- * design/116 W5-5 (CC 2.1.187 parity) — normalize a peer/tool segment to the API tool-name charset by
10
+ * design/116 W5-5 — normalize a peer/tool segment to the API tool-name charset by
11
11
  * replacing every other character with `_`. CC does exactly this on BOTH segments when composing
12
12
  * `mcp__<server>__<tool>` (services/mcp/normalization.ts `normalizeNameForMCP` + mcpStringUtils.ts
13
13
  * `buildMcpToolName`), so a peer advertising a dotted/spaced/unicode name can't mint a name the provider
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The READ-ONLY shell tables — the closed data the read-only reader (`read-only-shell.ts`) judges a
3
- * command against, transcribed from upstream's own tables (CC 2.1.250) and kept as DATA so the parity
3
+ * command against, transcribed from upstream's own tables and kept as DATA so the parity
4
4
  * question is answered by diffing two tables, never by reading two programs:
5
5
  * - {@link READ_ONLY_COMMAND_TABLE} — the flag-vetted commands: a command (one or more leading words,
6
6
  * `git status`, `gh pr view`, `grep`) with the closed set of flags it may carry, each flag's value
@@ -8,7 +8,7 @@ export type ReadOnlyShellVerdict = {
8
8
  readonly readOnly: false;
9
9
  readonly reason: string;
10
10
  };
11
- /** The reference implementation's question for a compound that changes directory and runs git (2.1.280, `cd-git-compound`). */
11
+ /** The reference implementation's question for a compound that changes directory and runs git (`cd-git-compound`). */
12
12
  export declare const CD_GIT_COMPOUND_SENTENCE = "This command changes directory before running a version-control command, which can pick up untrusted hooks or repository configuration from the target directory. Approve only if you trust it.";
13
13
  /**
14
14
  * Does this line change directory and run git — a `cd` beside a `git` — other than by ONE plain `cd <path>` that lands
@@ -3,8 +3,12 @@ import type { Model } from "../internal/llm.js";
3
3
  import { type ModelRef, type ModelRole, type ModelRoles, type RoleSpec } from "./types.js";
4
4
  export type { ModelRole, RoleSpec, ModelRoles } from "./types.js";
5
5
  export { MODEL_ROLES } from "./types.js";
6
- /** Resolve a string ModelRef against the catalog (a Model object passes through). */
7
- export declare function resolveModel(ref: ModelRef, models?: Record<string, Model>): Model;
6
+ /**
7
+ * Resolve a ModelRef against the catalog (a Model object passes through). A word the catalog does not hold, and a value that is no model
8
+ * reference, are refused by `config.unknown_role` with `detail { field: seat, reason }` — `seat` names where the caller wrote the word
9
+ * (`"model"` when the caller names none).
10
+ */
11
+ export declare function resolveModel(ref: ModelRef, models?: Record<string, Model>, seat?: string): Model;
8
12
  /** 档位降档链(强→弱)。解析某档无绑定时沿链向后找第一个有绑定的档(fail-open 可用性优先;绑定缺口
9
13
  * 在部署 catalog 审计面可见)。`ultra` 预留:排在 `max` 前,今天不绑,未来加档零码改。 */
10
14
  export declare const DEFAULT_TIER_ORDER: readonly string[];