@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
@@ -0,0 +1,120 @@
1
+ /**
2
+ * The advisor seat's two answers, each minted here once and read by every reader: whether the advisor tool attaches for
3
+ * a (main model, advisor model) pair on a deployment ({@link advisorAttachVerdict} — the prepare mount, a host's advisor
4
+ * query and its echo all ask this one function), and whether a conversation has switched the advisor off
5
+ * ({@link advisorHoldOf} — read off the transcript, its only source of truth, at the mount, at every call and by a host).
6
+ * The closed sets the answers are spelled in live beside them.
7
+ */
8
+ import type { SessionTreeEntry } from "../internal/harness-types.js";
9
+ import { type BrainErrorCode } from "../brain/errors.js";
10
+ import type { AssertAllKeysHandled } from "./ask-origin.js";
11
+ import type { EngineNotice, Model, ModelRef, RunnerDeps } from "./types.js";
12
+ /** The tool's wire name. */
13
+ export declare const ADVISOR_TOOL_NAME = "advisor";
14
+ /** What a fork is told when it inherits the advisor tool with its parent's prefix — the reference's sentence. */
15
+ export declare const ADVISOR_FORK_SENTENCE = "Never consult the advisor tool.";
16
+ /** Why the advisor tool is not attached on a leg whose spec names an advisor model. The first six are the static verdict's
17
+ * answers; the last three are the mount's (the tool selector unmounted it, its route cannot pair, the transcript could
18
+ * not be read). */
19
+ export declare const ADVISOR_NOT_ATTACHED_REASONS: readonly ["disabled", "unknown_model", "advisor_unranked", "weakest_tier", "main_unranked", "pairing", "route_refused", "excluded", "hold_unknown"];
20
+ export type AdvisorNotAttachedReason = (typeof ADVISOR_NOT_ATTACHED_REASONS)[number];
21
+ /**
22
+ * Each reason's sentence to the person (`advisor.not_attached`, once per conversation per pair) — `null` for a reason that
23
+ * tells nobody: the deployment switched the advisor off (it is ignored), the deployment's tool selector unmounted it
24
+ * (`excluded`), or its route cannot pair with the deployment's credentials (`route_refused`, told to the operator by
25
+ * `route.seat_detached` — only an operator can fix it).
26
+ */
27
+ declare const NOT_ATTACHED_SENTENCE: {
28
+ readonly disabled: null;
29
+ readonly unknown_model: (a: string) => string;
30
+ readonly advisor_unranked: (a: string) => string;
31
+ readonly weakest_tier: (a: string) => string;
32
+ readonly main_unranked: (_a: string, m: string) => string;
33
+ readonly pairing: (a: string, m: string) => string;
34
+ readonly route_refused: null;
35
+ readonly excluded: null;
36
+ readonly hold_unknown: () => string;
37
+ };
38
+ export type NotAttachedSentenceCoversEveryReason = AssertAllKeysHandled<Exclude<AdvisorNotAttachedReason, keyof typeof NOT_ATTACHED_SENTENCE>>;
39
+ /** The shape door of `TaskSpec.advisorModel` (read only while the deployment switch is on): absent, a non-empty ref, or a
40
+ * Model object; anything else refuses (`config.advisor_model_invalid`) — a model the engine cannot read names no advisor. */
41
+ export declare function assertAdvisorModelShape(ref: unknown): void;
42
+ /** The three faces of one advisor call: guidance came back, the advisor model refused, or no guidance could be had. */
43
+ export declare const ADVISOR_OUTCOMES: readonly ["reviewed", "declined", "unavailable"];
44
+ export type AdvisorOutcome = (typeof ADVISOR_OUTCOMES)[number];
45
+ /** The static verdict: the advisor attaches on `model`, or does not and says why. */
46
+ export type AdvisorAttachVerdict = {
47
+ readonly state: "on";
48
+ readonly model: Model;
49
+ } | {
50
+ readonly state: "not_attached";
51
+ readonly reason: Exclude<AdvisorNotAttachedReason, "route_refused" | "excluded" | "hold_unknown">;
52
+ };
53
+ /**
54
+ * Whether the advisor tool attaches for `advisor` beside the run's `main` model, in command order: the deployment switch,
55
+ * then the advisor itself (a model the catalog cannot resolve, one on no declared tier, one on the weakest tier — `lite`,
56
+ * the tier the `haiku` alias names), then the main model (on no declared tier, or on a WEAKER tier than the advisor's:
57
+ * an advisor at least as capable as the main model attaches). Tiers are read by the classifier seat's own reading
58
+ * ({@link tierIndexOf}) over a catalog {@link normalizeSeatDeps} expanded, so a host holding raw deps gets the engine's
59
+ * answer. No tiers declared ⇒ no ranks ⇒ not attached.
60
+ */
61
+ export declare function advisorAttachVerdict(args: {
62
+ deps: Pick<RunnerDeps, "models" | "tiers" | "advisorTool">;
63
+ main: Model;
64
+ advisor: ModelRef;
65
+ }): AdvisorAttachVerdict;
66
+ /**
67
+ * Which failure of an advisor request switches the advisor off for the conversation: the advisor model's credential refused
68
+ * (`auth`), or a provider 400 / 422 its minter ruled out as an over-window request (`invalid_request` with
69
+ * `inputTooLongRuledOut`) — deterministic client faults that repeat until the conversation is compacted. Every other code,
70
+ * an over-window refusal and an unclassified 400 pass (the next call may succeed). Total over the brain codes by its fence.
71
+ */
72
+ export declare const ADVISOR_HOLD_CAUSES: Readonly<{
73
+ readonly auth: "hold";
74
+ readonly invalid_request: "hold_unless_window";
75
+ readonly rate_limit: "pass";
76
+ readonly server: "pass";
77
+ readonly network: "pass";
78
+ readonly http: "pass";
79
+ readonly stream_torn: "pass";
80
+ readonly refusal: "pass";
81
+ readonly length_empty: "pass";
82
+ }>;
83
+ /** What one failure's code does to the conversation's advisor ({@link ADVISOR_HOLD_CAUSES}). */
84
+ export type AdvisorHoldDisposition = "hold" | "hold_unless_window" | "pass";
85
+ export type HoldCausesCoverEveryBrainCode = AssertAllKeysHandled<Exclude<BrainErrorCode, keyof typeof ADVISOR_HOLD_CAUSES>>;
86
+ /** What a failed advisor request said about itself — the fields the hold reads and the card carries. */
87
+ export interface AdvisorFailure {
88
+ readonly code?: BrainErrorCode;
89
+ readonly errorKind?: "input_too_long" | "degenerate" | "length_empty";
90
+ readonly inputTooLongRuledOut?: true;
91
+ }
92
+ /** Whether this failure switches the advisor off for the conversation ({@link ADVISOR_HOLD_CAUSES}). */
93
+ export declare function advisorFailureHolds(f: AdvisorFailure): boolean;
94
+ /** The conversation's advisor switch-off, with the cause of the call that switched it. */
95
+ export interface AdvisorHold {
96
+ readonly code?: BrainErrorCode;
97
+ readonly errorKind?: AdvisorFailure["errorKind"];
98
+ }
99
+ /**
100
+ * Whether the conversation on this branch has switched the advisor off, read off the transcript: an advisor tool result
101
+ * recorded after the latest compaction whose card says `hold: true` — the latest such card's cause. A compaction clears it
102
+ * (the card lands before it); a new conversation has none; a fork copies its parent's branch and with it the hold.
103
+ * `undefined` = not held. Members of a recorded card outside their closed sets are not carried.
104
+ */
105
+ export declare function advisorHoldOf(entries: ReadonlyArray<SessionTreeEntry>): AdvisorHold | undefined;
106
+ /** A not-attached reason the person is told about — its own fact or one they can act on — as a type. */
107
+ export type AdvisorToldReason = {
108
+ [R in AdvisorNotAttachedReason]: (typeof NOT_ATTACHED_SENTENCE)[R] extends null ? never : R;
109
+ }[AdvisorNotAttachedReason];
110
+ /** Whether the person is told about this reason ({@link NOT_ATTACHED_SENTENCE}: the reasons with a sentence). */
111
+ export declare function advisorReasonTold(reason: AdvisorNotAttachedReason): reason is AdvisorToldReason;
112
+ /** The `advisor.not_attached` notice for a reason the person is told about. */
113
+ export declare function advisorNotAttachedNotice(args: {
114
+ reason: AdvisorToldReason;
115
+ advisorModel: string;
116
+ mainModel: string;
117
+ sessionId: string;
118
+ runId?: string;
119
+ }): EngineNotice;
120
+ export {};
@@ -0,0 +1,92 @@
1
+ import { ALL_BRAIN_ERROR_CODES } from "../brain/errors.js";
2
+ import { DEFAULT_TIER_ORDER, resolveModel } from "./roles.js";
3
+ import { normalizeSeatDeps, tierIndexOf } from "./runner/classifier-ladder.js";
4
+ export const ADVISOR_TOOL_NAME = "advisor";
5
+ export const ADVISOR_FORK_SENTENCE = "Never consult the advisor tool.";
6
+ export const ADVISOR_NOT_ATTACHED_REASONS = Object.freeze(["disabled", "unknown_model", "advisor_unranked", "weakest_tier", "main_unranked", "pairing", "route_refused", "excluded", "hold_unknown"]);
7
+ const NOT_ATTACHED_SENTENCE = {
8
+ disabled: null,
9
+ unknown_model: (a) => `The advisor model "${a}" is not in this deployment's model catalog, so the advisor is off.`,
10
+ advisor_unranked: (a) => `"${a}" cannot be used as an advisor: the deployment declares no tier for it (declare RunnerDeps.tiers so the engine knows which model is stronger).`,
11
+ weakest_tier: (a) => `"${a}" cannot be used as an advisor: it is on the weakest tier.`,
12
+ main_unranked: (_a, m) => `The advisor will not activate on the main model (${m}): the deployment declares no tier for it (declare RunnerDeps.tiers). Subagents may still use it.`,
13
+ pairing: (a, m) => `${a} is less capable than the current main model (${m}), so the advisor will not activate. Choose a more capable advisor, or switch to a smaller main model.`,
14
+ route_refused: null,
15
+ excluded: null,
16
+ hold_unknown: () => `The advisor is off for this run: whether this conversation had switched it off could not be read.`,
17
+ };
18
+ export function assertAdvisorModelShape(ref) {
19
+ if (ref === undefined || (typeof ref === "string" ? ref !== "" : typeof ref === "object" && ref !== null && typeof ref.id === "string"))
20
+ return;
21
+ const shown = typeof ref === "string" ? "an empty string" : ref === null ? "null" : Array.isArray(ref) ? "an array" : typeof ref;
22
+ throw Object.assign(new Error(`TaskSpec.advisorModel must be a non-empty model ref or a Model (got ${shown}) — a model the engine cannot read names no advisor.`), { code: "config.advisor_model_invalid" });
23
+ }
24
+ export const ADVISOR_OUTCOMES = Object.freeze(["reviewed", "declined", "unavailable"]);
25
+ export function advisorAttachVerdict(args) {
26
+ if (args.deps.advisorTool === "disabled")
27
+ return { state: "not_attached", reason: "disabled" };
28
+ const deps = normalizeSeatDeps(args.deps);
29
+ let advisor;
30
+ try {
31
+ advisor = resolveModel(args.advisor, deps.models);
32
+ }
33
+ catch {
34
+ return { state: "not_attached", reason: "unknown_model" };
35
+ }
36
+ const advisorTier = tierIndexOf(deps, advisor);
37
+ if (advisorTier === undefined)
38
+ return { state: "not_attached", reason: "advisor_unranked" };
39
+ if (advisorTier === DEFAULT_TIER_ORDER.indexOf("lite"))
40
+ return { state: "not_attached", reason: "weakest_tier" };
41
+ const mainTier = tierIndexOf(deps, args.main);
42
+ if (mainTier === undefined)
43
+ return { state: "not_attached", reason: "main_unranked" };
44
+ if (advisorTier > mainTier)
45
+ return { state: "not_attached", reason: "pairing" };
46
+ return { state: "on", model: advisor };
47
+ }
48
+ export const ADVISOR_HOLD_CAUSES = Object.freeze({
49
+ auth: "hold",
50
+ invalid_request: "hold_unless_window",
51
+ rate_limit: "pass",
52
+ server: "pass",
53
+ network: "pass",
54
+ http: "pass",
55
+ stream_torn: "pass",
56
+ refusal: "pass",
57
+ length_empty: "pass",
58
+ });
59
+ export function advisorFailureHolds(f) {
60
+ if (f.code === undefined)
61
+ return false;
62
+ const row = ADVISOR_HOLD_CAUSES[f.code];
63
+ return row === "hold" || (row === "hold_unless_window" && f.errorKind !== "input_too_long" && f.inputTooLongRuledOut === true);
64
+ }
65
+ const ERROR_KINDS = new Set(["input_too_long", "degenerate", "length_empty"]);
66
+ export function advisorHoldOf(entries) {
67
+ for (let i = entries.length - 1; i >= 0; i--) {
68
+ const e = entries[i];
69
+ if (e.type === "compaction")
70
+ return undefined;
71
+ if (e.type !== "message" || e.message.role !== "toolResult" || e.message.toolName !== ADVISOR_TOOL_NAME)
72
+ continue;
73
+ const d = e.message.details;
74
+ if (d === null || typeof d !== "object" || d.type !== "advisor" || d.hold !== true)
75
+ continue;
76
+ const code = ALL_BRAIN_ERROR_CODES.find((c) => c === d.code);
77
+ const errorKind = typeof d.errorKind === "string" && ERROR_KINDS.has(d.errorKind) ? d.errorKind : undefined;
78
+ return { ...(code !== undefined ? { code } : {}), ...(errorKind !== undefined ? { errorKind } : {}) };
79
+ }
80
+ return undefined;
81
+ }
82
+ export function advisorReasonTold(reason) {
83
+ return NOT_ATTACHED_SENTENCE[reason] !== null;
84
+ }
85
+ export function advisorNotAttachedNotice(args) {
86
+ const sentence = NOT_ATTACHED_SENTENCE[args.reason];
87
+ return {
88
+ code: "advisor.not_attached",
89
+ message: sentence(args.advisorModel, args.mainModel),
90
+ detail: { advisorModel: args.advisorModel, mainModel: args.mainModel, reason: args.reason, sessionId: args.sessionId, ...(args.runId !== undefined ? { runId: args.runId } : {}) },
91
+ };
92
+ }
@@ -19,8 +19,7 @@ export interface AgentDefinition {
19
19
  /** Guidance shown to the model for WHEN to pick this agent (listed in the delegation tool's description). */
20
20
  whenToUse?: string;
21
21
  /**
22
- * F4 (CC 2.1.198 parity, `whenToUseLean` — 锚 pretty.js:409174 `rbm` + selection `tIl` :453029
23
- * `(lean && e.whenToUseLean) || e.whenToUse`): a SHORT variant of {@link whenToUse} preferred on
22
+ * F4 (`whenToUseLean`): a SHORT variant of {@link whenToUse} preferred on
24
23
  * lean-prompt surfaces. sema posture: the engine runs the CC lean-prompt arm wholesale (web.ts
25
24
  * lean-card precedent), so roster listings/descriptions prefer this text whenever present;
26
25
  * {@link whenToUse} remains the fallback. Optional — a single-text agent behaves exactly as before.
@@ -36,7 +35,7 @@ export interface AgentDefinition {
36
35
  /** Tool denylist (a deny always wins), tool NAMES: `Tool(content)` hides the whole `Tool`. See {@link allowTools} for the per-agent delegation-tool note. */
37
36
  denyTools?: string[];
38
37
  /**
39
- * F7 (CC 2.1.198 parity, per-agent `skills` — 锚 pretty.js:422126 `e.skills ?? []`, GA/ungated in 198:
38
+ * F7 (per-agent `skills`:
40
39
  * CC preloads each named skill's prompt content into the child's opening messages, warning on misses).
41
40
  * sema shape: full {@link SkillSpec} objects (sema has no ambient skill registry to resolve bare names
42
41
  * against) threaded into the chosen child's `TaskSpec.skills` — disclosed in its `<skills>` block +
@@ -44,7 +43,7 @@ export interface AgentDefinition {
44
43
  */
45
44
  skills?: SkillSpec[];
46
45
  /**
47
- * F7 (CC 2.1.198 parity, per-agent `background` — 锚 pretty.js:453611 `H.background===!0` OR-ed into
46
+ * F7 (per-agent `background`, OR-ed into
48
47
  * the background predicate, GA/ungated): `true` = this agent ALWAYS launches on the background lane
49
48
  * (an omitted `run_in_background` no longer means sync, and the per-call parameter cannot force sync —
50
49
  * CC-same OR semantics). Requires the delegation tool's `background` surface; without one the child
@@ -52,7 +51,7 @@ export interface AgentDefinition {
52
51
  */
53
52
  background?: boolean;
54
53
  /**
55
- * F7 (CC 2.1.198 parity, per-agent `isolation` — 锚 pretty.js:453599 `z = a ?? H.isolation`, GA):
54
+ * F7 (per-agent `isolation`):
56
55
  * default isolation for this agent; an explicit per-call `isolation` argument wins. sema supports
57
56
  * `"worktree"` (CC's `"remote"` arm is a claude.ai-session concern, not ported).
58
57
  */
@@ -86,8 +85,8 @@ export interface AgentDefinition {
86
85
  */
87
86
  memoryPersistenceCapable?: boolean;
88
87
  /**
89
- * Observer agents (CC 2.1.206 parity — 逐字锚 docs/CC206-OBSERVER-ANCHORS-2026-07-11.md, schema
90
- * 面 C @28385708): "Agent type auto-spawned as a background observer whenever this agent runs.
88
+ * Observer agents (schema
89
+ * 面 C): "Agent type auto-spawned as a background observer whenever this agent runs.
91
90
  * The observer receives read-only activity digests and reports via the ObserverReport tool; it
92
91
  * never participates in the task." Resolution is warn-and-unobserved on an unknown type and
93
92
  * refuses chaining (an observer's own `observer` declaration is ignored). Gated by
@@ -116,7 +115,7 @@ export interface SkillSpec {
116
115
  * either list asks once (`Execute skill: <name>`, the card listing what it releases); a skill the person invoked by
117
116
  * name ({@link import("./task-spec.js").TaskSpec.userInvokedSkills}) grants without asking. The grant holds for that
118
117
  * run (a steer it takes in does not end it) and the next runTask starts without it. An entry this grammar reads as nothing — `*` (it voids an allow list; on a deny list it is inert and the rest of the
119
- * list still refuses), `mcp__*`, a write path, a domain — grants nothing and is announced at the start of the run (`permission.allowed_tool_not_granted`). A table whose value is not a list (a string, an object…) reads as one such entry; `null` is no table.
118
+ * list still refuses), `mcp__*` / `mcp__*__*` (an allow entry names a peer), a write path, a domain — grants nothing and is announced at the start of the run (`permission.allowed_tool_not_granted`). A table whose value is not a list (a string, an object…) reads as one such entry; `null` is no table.
120
119
  */
121
120
  allowedTools?: string[];
122
121
  /** The tools refused for the rest of the run this skill is activated in — the frontmatter `disallowed-tools` list,
@@ -126,7 +126,7 @@ export declare function compileAllowList(entries: readonly string[], behavior: "
126
126
  inert: AllowEntryInert[];
127
127
  };
128
128
  /** The programs whose open allow rule the reference implementation drops in auto mode — its interpreter / launcher table
129
- * plus the shells and the run-anything builtins (2.1.280). A program that only reaches the network is not here. */
129
+ * plus the shells and the run-anything builtins. A program that only reaches the network is not here. */
130
130
  export declare const AUTO_STRIPPED_PROGRAMS: readonly ["python", "python3", "python2", "node", "deno", "tsx", "ruby", "perl", "php", "lua", "npx", "bunx", "npm run", "yarn run", "pnpm run", "bun run", "bash", "sh", "ssh", "zsh", "fish", "eval", "exec", "env", "xargs", "sudo"];
131
131
  /**
132
132
  * Does auto mode strip this allow entry for this call (see the module doc)? Read for every rule-shaped member — a list
@@ -163,17 +163,23 @@ export declare function uncoveredCommandSegment(rows: readonly AllowEntryRow[],
163
163
  * segment covered by a row — or, for a `grant` list, read-only by itself); deny: a row whose program run the call performs (the
164
164
  * wide tightening reading; a call that cannot be read against the row is refused too). PATH — the persisted path adjudication
165
165
  * (allow: the narrow reading, every view of the target inside what the row names; deny: any view reaching it). NAME / DOMAIN —
166
- * the one predicate of each (the name the call names, the host it fetches); a keyed tool's call naming no value for its key is
167
- * refused by a deny list's row of the key and granted by no allow row (the persisted walk's reading, `keyedValueAbsentReason`).
166
+ * the one predicate of each (the name the call names, the host it reaches — a deny row read on the protective reading, an allow
167
+ * row on the tool's own declared slot, `callHostTargetOf`; a mounted name tool's value resolved against the agent types the call's
168
+ * face carries, `nameRuleReach`); a closed-set tool's call naming no value is refused by a deny list's row of the tool and granted
169
+ * by no allow row (the persisted walk's reading, `nameValueAbsentReason`), a mounted tool's call whose face carries no values is
170
+ * refused by a deny list's row of the tool and granted by no allow row, and a call whose host cannot be read is refused by a deny
171
+ * list's host row and granted by no allow row (`adjudicatePersistedDomainRules`).
168
172
  */
169
173
  export declare function judgeAllowEntries<R extends AllowEntryRow>(rows: readonly R[], req: ToolCallRequest, behavior: "allow" | "deny", ctx: AllowEntryJudgeContext, posture?: AdmissionPosture): readonly R[] | undefined;
170
174
  /** The allow rows of a list, as the allow layer reads them in `mode`: the strip applied BEFORE the match (in `auto`). */
171
175
  export declare function allowingRows<R extends AllowEntryRow>(rows: readonly R[], req: ToolCallRequest, mode: PermissionMode | undefined): readonly R[];
172
176
  /** The two sources {@link AllowEntryTable} holds (a skill's list is the skill table's). */
173
177
  export type AllowEntrySource = "request" | "deployment";
174
- /** What spoke for a call: the entries it stands on, as the list spells them. */
178
+ /** What spoke for a call: the entries it stands on, as the list spells them, and — for entries of the list the run received —
179
+ * the index of every element of that list that is one of them (a string listed twice has both). */
175
180
  export interface AllowEntryHit {
176
181
  readonly entries: readonly string[];
182
+ readonly positions?: readonly number[];
177
183
  }
178
184
  /** The face the gate reads one entry list through. */
179
185
  export interface AllowEntryLane {
@@ -208,9 +214,16 @@ export interface AllowEntryGateSeats {
208
214
  export declare class AllowEntryTable {
209
215
  private held;
210
216
  private readonly heldEntries;
217
+ /** Each entry of the list the run RECEIVED for this source, with its indices in that list — what a hit's `positions` read. */
218
+ private receivedAt;
211
219
  /** Write a list's rows (a row already held is not held twice). Returns the entries that read as nothing. `roster` as in
212
- * {@link readRuleEntry}: a list the leg itself wrote is read against it, a carried one (a delegating parent's capture) is not. */
213
- seed(entries: readonly string[], roster?: ReadonlySet<string>): readonly AllowEntryInert[];
220
+ * {@link readRuleEntry}: a list the leg itself wrote is read against it, a carried one (a delegating parent's capture) is not.
221
+ * `received`: this list is the one the run received for the source (the request's `TaskSpec.allowedTools`, the deployment's
222
+ * `RunnerDeps.allowedTools`), the list a hit's positions are read in; a carried capture is not. */
223
+ seed(entries: readonly string[], reading?: {
224
+ readonly roster?: ReadonlySet<string>;
225
+ readonly received?: true;
226
+ }): readonly AllowEntryInert[];
214
227
  /** The entries held, as written (a copy) — what a delegated child is handed. */
215
228
  entries(): readonly string[];
216
229
  /** Does the table hold a path row — must the leg read each call's target views for it? */
@@ -245,21 +258,32 @@ export declare function withDeploymentAllowedTools<D extends {
245
258
  }>(deps: D): D;
246
259
  /** The code a list value that is not a list of strings refuses with — the policy compiler's family, with its issues. */
247
260
  export declare const INVALID_PERMISSION_RULES_CODE = "config.invalid_permission_rules";
261
+ /** The two seats an allow list is handed over at — the library coordinates the refusal carries as `libraryOption`, each with the
262
+ * words the sentence says instead. */
263
+ declare const ALLOW_LIST_SEATS: {
264
+ readonly "TaskSpec.allowedTools": "the request's allow list";
265
+ readonly "RunnerDeps.allowedTools": "the deployment's allow list";
266
+ };
267
+ type AllowedToolsSeat = keyof typeof ALLOW_LIST_SEATS;
248
268
  /**
249
- * Screen and snapshot one `allowedTools` value (`seat` names the key in the refusal): absent ⇒ undefined; a list of strings
250
- * ⇒ a frozen copy (the one read every later reader takes); anything else refuses loudly with
251
- * {@link INVALID_PERMISSION_RULES_CODE} and an issue per defect — never dropped, never read as "no entries".
269
+ * Screen and snapshot one `allowedTools` value (`seat` is the seat it was handed at; the sentence says it in words, the issues'
270
+ * `libraryOption` names it): absent ⇒ undefined; a list of strings ⇒ a frozen copy (the one read every later reader takes);
271
+ * anything else refuses loudly with {@link INVALID_PERMISSION_RULES_CODE} and an issue per defect — never dropped, never read
272
+ * as "no entries".
252
273
  */
253
- export declare function screenAllowedToolsValue(value: unknown, seat: string): readonly string[] | undefined;
274
+ export declare function screenAllowedToolsValue(value: unknown, seat: AllowedToolsSeat): readonly string[] | undefined;
254
275
  /** The disclosure record for one member, minted from the entries it matched: each sanitized (deployment or model-authored
255
276
  * text on a human trust boundary) and capped, the rest counted. */
256
277
  export declare function allowRuleShadowOf(member: AllowRuleMember, entries: readonly string[]): AllowRuleShadow;
257
278
  /** Read a disclosure value off a decision WITHOUT trusting it (a policy's own value, an ancestor's): every record a known
258
279
  * member with a list of strings, or nothing — a display member must never throw where a card is minted. */
259
280
  export declare function readAllowRuleShadows(value: unknown): readonly AllowRuleShadow[] | undefined;
260
- /** Why a matched entry did not clear the ask, by the ask's class — one row per class, so a class added later is a
261
- * compile error here rather than somebody else's reason on the card. Two facts the ask carries are read first, because
262
- * they name the reason more exactly than a class shared by several: a table word (`mandate` — the exact mark) and the
281
+ /** The ask class whose reason is not a row: `probe` is the class of a FINDING about this very call (the read station's, or a
282
+ * probe's), and only the ask's own account of it — its `probeReason` — can say which ({@link allowRuleShadowSentence}). */
283
+ export type AccountedClass = "probe";
284
+ /** Why a matched entry did not clear the ask, by the ask's class — one row per class that has a reason of its own, so a class
285
+ * added later is a compile error here rather than somebody else's reason on the card. Two facts the ask carries are read first,
286
+ * because they name the reason more exactly than a class shared by several: a table word (`mandate` — the exact mark) and the
263
287
  * deployment's own authorship (`authoredBy`) — {@link allowRuleShadowSentence} is the reader that applies that order.
264
288
  * Exported (frozen) so a host that renders the card's "why it cannot be cleared" half reads the engine's row, never a copy. */
265
289
  export declare const SHADOW_REASON: Readonly<{
@@ -272,26 +296,25 @@ export declare const SHADOW_REASON: Readonly<{
272
296
  readonly transcript_write: "this write targets the session transcript — it is cleared by confirming this call, never by an allow rule";
273
297
  readonly org_rule: "an organization policy rule requires approval for this call";
274
298
  readonly rule_unreadable: "a rule that may govern this call cannot currently be read (this deployment's organization policy, a partition of the person's standing rules, or this call against a deny or ask rule), so whether one forbids it is unknown";
275
- readonly ask_rule: string;
299
+ readonly ask_rule: "an explicit ask rule matched this call (a person's or the deployment's ask-me-each-time outranks a standing allow rule)";
276
300
  readonly denial_limit_fallback: "the auto-mode classifier refused too many calls in a row, so a person decides";
277
301
  readonly classifier_no_ruling: "the auto-mode classifier could not judge this call, so a person decides";
278
302
  readonly requires_user_interaction: "this tool's server declares that a call must be put to a person";
279
- readonly cross_boundary: string;
303
+ readonly cross_boundary: "this run executes on a device outside the deployment's trust boundary and the deployment is multi-tenant, so an org-side write — or, after an off-target read, a call bound for the device — is confirmed by the deployment's approver for this call: no standing allow rule and no automatic lane answers for it, and an allow the configuration gives (a blanket seat or a policy's answer) is refused";
280
304
  readonly operator_forced: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule";
281
- readonly shell_floor: string;
282
- readonly target_unresolved: string;
283
- readonly probe: string;
284
- readonly write_protection: string;
285
- readonly tool_marks_mcp: string;
286
- readonly tool_marks_a2a: string;
305
+ readonly shell_floor: "this deployment mandates per-call confirmation for shell commands (shellGate: always)";
306
+ readonly target_unresolved: "where this write leads on disk could not be determined (a link on the way could not be examined, or the environment could not resolve the target), so whether it lands on a guarded path is unknown — it is cleared by confirming this call: no standing rule and no automatic decider answers for it, though a wired approver seat can";
307
+ readonly write_protection: "this write's target is on the deployment's write-protection table (the agent's own configuration is guarded one look per write) — it is cleared by confirming this call, never by a standing allow rule";
308
+ readonly tool_marks_mcp: "this tool carries egress/irreversibility/interaction marks (a mandated confirmation a rule cannot clear)";
309
+ readonly tool_marks_a2a: "this tool carries egress/irreversibility/interaction marks (a mandated confirmation a rule cannot clear)";
287
310
  readonly policy_rra: "the deployment's policy requires a real approval for this call";
288
311
  readonly artifact_shared_read: "this read targets another task's shared artifact — it is cleared by confirming this call";
289
312
  readonly mode: "the permission mode puts this question to a person";
290
313
  readonly unstated: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule";
291
314
  readonly ordinary: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule";
292
315
  }>;
293
- /** The fence over the reason table: `never` while every class has a row. */
294
- export type ShadowReasonTableCoversEveryClass = AssertAllKeysHandled<Exclude<AskClass, keyof typeof SHADOW_REASON>>;
316
+ /** The fence over the reason table: `never` while every class that has a reason of its own has a row. */
317
+ export type ShadowReasonTableCoversEveryClass = AssertAllKeysHandled<Exclude<AskClass, keyof typeof SHADOW_REASON | AccountedClass>>;
295
318
  /**
296
319
  * The disclosure in the sentence a PERSON reads — rendered where a card or a park row is minted, never onto the decision
297
320
  * the classifier reads: "<members> match(es) this call but do(es) not clear the ask — <why>".
@@ -300,6 +323,7 @@ export declare function allowRuleShadowSentence(shadows: readonly AllowRuleShado
300
323
  askClass?: AskClass;
301
324
  mandate?: PersistedRuleMandate;
302
325
  authoredBy?: "deployment";
326
+ probeReason?: string;
303
327
  }): string;
304
328
  /** The card's two disclosure members off a surviving ask, minted at every station that builds an approval request: the
305
329
  * sanitized records, and the message with the sentence rendered onto it. */
@@ -309,6 +333,7 @@ export declare function cardDisclosureOf(decision: {
309
333
  askClass?: AskClass;
310
334
  mandate?: PersistedRuleMandate;
311
335
  authoredBy?: "deployment";
336
+ probeReason?: string;
312
337
  }, fallbackMessage: string): {
313
338
  message: string;
314
339
  allowRuleShadowed?: readonly AllowRuleShadow[];
@@ -348,3 +373,4 @@ export declare function inertEntryPhrase(e: AllowEntryInert): string;
348
373
  * `disallowed-tools` holds such an entry is named as one that does not activate.
349
374
  */
350
375
  export declare function allowedToolsNotGrantedNotice(inert: readonly AllowEntryInertNote[], sessionId: string | undefined): EngineNotice;
376
+ export {};
@@ -1,15 +1,16 @@
1
1
  import { heldBy } from "./tool-name-readings.js";
2
- import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "./permission-rules.js";
2
+ import { isNamespacedCoveringRuleName, namespacedRuleNameCovers, ruleIssue } from "./permission-rules.js";
3
3
  import { parsePermissionRule, ruleSpellingOf } from "./permission-rule-syntax.js";
4
4
  import { judgeRuleToolName, splitNamespacedName } from "./tool-name-aliases.js";
5
5
  import { catalogToolNames, isShellFaceToolName } from "./tool-registry.js";
6
6
  import { ALLOW_RULE_MEMBERS } from "./allow-rule-shadow.js";
7
- import { COMMAND_RULE_TOOL, adjudicatePersistedDomainRules, adjudicatePersistedNameRules, commandCoverageOf, domainRuleSubjectOf, laneToolNamesOf, nameRuleSubjectOf, noticeRuleText, parseRuleText, programRunReachOf, ruleToolGrammarOf } from "./permission-rule-model.js";
7
+ import { callHostTargetOf } from "./host-target.js";
8
+ import { COMMAND_RULE_TOOL, adjudicatePersistedDomainRules, adjudicatePersistedNameRules, commandCoverageOf, laneToolNamesOf, ruleContentOf, noticeRuleText, parseRuleText, programRunReachOf, ruleToolGrammarOf, commandPatternMayRun } from "./permission-rule-model.js";
8
9
  import { pathRuleLaneAnswer } from "./runner/permission-rule-lanes.js";
9
10
  import { callTargetReadingOf } from "./effective-path-target.js";
10
11
  import { splitShellCompoundSegments } from "../tools/fs/bash-readonly-classifier.js";
11
- import { mandateDisclosureOf } from "./ask-origin.js";
12
- import { inlineUntrusted } from "./untrusted-text.js";
12
+ import { ASK_RULE_DISCLOSURE, MANDATE_DISCLOSURE, mandateDisclosureOf } from "./ask-origin.js";
13
+ import { inlineUntrusted, isMintableProbeReason } from "./untrusted-text.js";
13
14
  import { valueTypeLabel } from "./tool-name-list.js";
14
15
  import { deliverEngineNotice } from "./engine-notice.js";
15
16
  export const ALLOW_ENTRY_INERT_REASONS = Object.freeze(["wildcard_all", "namespace_wildcard", "content_unsupported", "grammar", "tool_name", "near_miss", "earlier_grammar"]);
@@ -38,8 +39,8 @@ export function nearMissSpellingOf(name, roster) {
38
39
  export function rootFacingToolNames(carried) {
39
40
  return new Set([...catalogToolNames(), ...carried]);
40
41
  }
41
- function toolNameReading(name, roster) {
42
- const verdict = judgeRuleToolName(name, roster);
42
+ function toolNameReading(name, roster, behavior) {
43
+ const verdict = judgeRuleToolName(name, roster, behavior);
43
44
  if (verdict.kind === "unprefixed_namespace")
44
45
  return { kind: "inert", reason: "tool_name", verdict: verdict.kind };
45
46
  if (verdict.kind !== "current") {
@@ -60,15 +61,15 @@ export function readRuleEntry(raw, behavior, roster) {
60
61
  if (name === "*")
61
62
  return inert("wildcard_all");
62
63
  if (roster !== undefined) {
63
- const stale = toolNameReading(name, roster);
64
+ const stale = toolNameReading(name, roster, behavior);
64
65
  if (stale !== undefined)
65
66
  return stale;
66
67
  }
67
- if (parsed.ruleContent === undefined) {
68
+ if (ruleContentOf(parsed) === undefined) {
68
69
  const split = splitNamespacedName(name);
69
70
  if (split !== undefined) {
70
71
  if (split.peer.includes("*"))
71
- return inert("namespace_wildcard");
72
+ return isNamespacedCoveringRuleName(name, behavior) ? row({ kind: "namespace", pattern: name }) : inert("namespace_wildcard");
72
73
  if (isNamespacedCoveringRuleName(name))
73
74
  return row({ kind: "namespace", pattern: name });
74
75
  return row({ kind: "tool", name });
@@ -158,7 +159,7 @@ export function autoStripped(compiled, call) {
158
159
  case "tool":
159
160
  return call !== undefined && answersTo(call, isShellFaceToolName);
160
161
  case "command":
161
- return shellContentStripped(shellRuleContent(compiled.rule));
162
+ return compiled.rule.match === "pattern" ? commandPatternMayRun(compiled.rule.command, AUTO_STRIPPED_PROGRAMS) : shellContentStripped(shellRuleContent(compiled.rule));
162
163
  case "namespace":
163
164
  case "path":
164
165
  case "name":
@@ -240,7 +241,8 @@ export function judgeAllowEntries(rows, req, behavior, ctx, posture = "grant") {
240
241
  const table = familyRows.map((r) => r.compiled.rule);
241
242
  for (const name of laneToolNamesOf(req).filter((n) => ruleToolGrammarOf(n) === grammar)) {
242
243
  const at = { tool: name, cwd: ctx.root, ...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}) };
243
- const verdict = grammar === "name" ? adjudicatePersistedNameRules(table, { ...at, name: nameRuleSubjectOf(name, req.args) }) : adjudicatePersistedDomainRules(table, { ...at, host: domainRuleSubjectOf(name, req.args) });
244
+ const named = { ...req, toolName: name };
245
+ const verdict = grammar === "name" ? adjudicatePersistedNameRules(table, { ...at, request: req }) : adjudicatePersistedDomainRules(table, { ...at, hosts: { tighten: callHostTargetOf(named, "tighten"), grant: callHostTargetOf(named, "grant") } });
244
246
  if (verdict !== undefined && verdict.behavior === behavior)
245
247
  return [familyRows.find((r) => r.compiled.rule === verdict.rules[0]) ?? familyRows[0]];
246
248
  }
@@ -253,8 +255,19 @@ export function allowingRows(rows, req, mode) {
253
255
  export class AllowEntryTable {
254
256
  held = [];
255
257
  heldEntries = new Set();
256
- seed(entries, roster) {
257
- const { rows, inert } = compileAllowList(entries, "allow", roster);
258
+ receivedAt = new Map();
259
+ seed(entries, reading = {}) {
260
+ const { rows, inert } = compileAllowList(entries, "allow", reading.roster);
261
+ if (reading.received === true) {
262
+ this.receivedAt = new Map();
263
+ entries.forEach((e, i) => {
264
+ const at = this.receivedAt.get(e);
265
+ if (at === undefined)
266
+ this.receivedAt.set(e, [i]);
267
+ else
268
+ at.push(i);
269
+ });
270
+ }
258
271
  for (const r of rows) {
259
272
  if (this.heldEntries.has(r.entry))
260
273
  continue;
@@ -273,15 +286,19 @@ export class AllowEntryTable {
273
286
  return {
274
287
  allowing: (req, mode) => {
275
288
  const hit = judgeAllowEntries(allowingRows(this.held, req, mode), req, "allow", ctx);
276
- return hit === undefined ? undefined : { entries: hit.map((r) => r.entry) };
289
+ if (hit === undefined)
290
+ return undefined;
291
+ const entries = hit.map((r) => r.entry);
292
+ const positions = entries.flatMap((e) => this.receivedAt.get(e) ?? []).sort((a, b) => a - b);
293
+ return { entries, ...(positions.length > 0 ? { positions } : {}) };
277
294
  },
278
295
  };
279
296
  }
280
297
  }
281
298
  export function seedAllowEntryTables(tables, lists, roster) {
282
299
  tables.request.seed(lists.inherited ?? []);
283
- const requestInert = tables.request.seed(lists.request ?? [], roster);
284
- const deploymentInert = tables.deployment.seed(lists.deployment ?? [], roster).filter((e) => e.reason === "tool_name" || e.reason === "near_miss");
300
+ const requestInert = tables.request.seed(lists.request ?? [], { roster, received: true });
301
+ const deploymentInert = tables.deployment.seed(lists.deployment ?? [], { roster, received: true }).filter((e) => e.reason === "tool_name" || e.reason === "near_miss");
285
302
  return [
286
303
  ...lists.skillInert.map((e) => ({ source: "skill", ...e })),
287
304
  ...requestInert.map((e) => ({ source: "request", ...e })),
@@ -298,22 +315,27 @@ export function withDeploymentAllowedTools(deps) {
298
315
  return { ...deps, allowedTools };
299
316
  }
300
317
  export const INVALID_PERMISSION_RULES_CODE = "config.invalid_permission_rules";
318
+ const ALLOW_LIST_SEATS = {
319
+ "TaskSpec.allowedTools": "the request's allow list",
320
+ "RunnerDeps.allowedTools": "the deployment's allow list",
321
+ };
301
322
  export function screenAllowedToolsValue(value, seat) {
302
323
  if (value === undefined)
303
324
  return undefined;
325
+ const label = ALLOW_LIST_SEATS[seat];
304
326
  const issues = [];
305
327
  if (!Array.isArray(value)) {
306
- issues.push({ rule: "", code: "invalid.entry_type", message: `${seat} must be a list of permission-rule strings (got ${value === null ? "null" : typeof value})` });
328
+ issues.push(ruleIssue("", "invalid.entry_type", `${label} must be a list of permission-rule strings (got ${value === null ? "null" : typeof value})`, { name: seat }));
307
329
  }
308
330
  else {
309
331
  const list = value;
310
332
  list.forEach((entry, i) => {
311
333
  if (typeof entry !== "string")
312
- issues.push({ rule: "", code: "invalid.entry_type", message: `${seat}[${i}] must be a permission-rule string (got ${entry === null ? "null" : typeof entry})` });
334
+ issues.push(ruleIssue("", "invalid.entry_type", `entry ${i} of ${label} must be a permission-rule string (got ${entry === null ? "null" : typeof entry})`, { name: seat }));
313
335
  });
314
336
  }
315
337
  if (issues.length > 0) {
316
- const e = new Error(`${seat}: ${issues.length} invalid entr${issues.length === 1 ? "y" : "ies"} — refusing rather than running without them:\n${issues.map((i) => ` [${i.code}] ${i.message}`).join("\n")}`);
338
+ const e = new Error(`${label}: ${issues.length} invalid entr${issues.length === 1 ? "y" : "ies"} — refusing rather than running without them:\n${issues.map((i) => ` [${i.code}] ${i.message}`).join("\n")}`);
317
339
  e.code = INVALID_PERMISSION_RULES_CODE;
318
340
  e.issues = issues;
319
341
  throw e;
@@ -359,18 +381,17 @@ export const SHADOW_REASON = Object.freeze({
359
381
  transcript_write: "this write targets the session transcript — it is cleared by confirming this call, never by an allow rule",
360
382
  org_rule: "an organization policy rule requires approval for this call",
361
383
  rule_unreadable: "a rule that may govern this call cannot currently be read (this deployment's organization policy, a partition of the person's standing rules, or this call against a deny or ask rule), so whether one forbids it is unknown",
362
- ask_rule: mandateDisclosureOf(undefined),
384
+ ask_rule: ASK_RULE_DISCLOSURE,
363
385
  denial_limit_fallback: "the auto-mode classifier refused too many calls in a row, so a person decides",
364
386
  classifier_no_ruling: "the auto-mode classifier could not judge this call, so a person decides",
365
387
  requires_user_interaction: "this tool's server declares that a call must be put to a person",
366
- cross_boundary: mandateDisclosureOf("cross_boundary_taint"),
388
+ cross_boundary: MANDATE_DISCLOSURE.cross_boundary_taint,
367
389
  operator_forced: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule",
368
- shell_floor: mandateDisclosureOf("operator_always"),
369
- target_unresolved: mandateDisclosureOf("target_unresolved"),
370
- probe: mandateDisclosureOf("probe_mandate"),
371
- write_protection: mandateDisclosureOf("write_protection"),
372
- tool_marks_mcp: mandateDisclosureOf("tool_marks"),
373
- tool_marks_a2a: mandateDisclosureOf("tool_marks"),
390
+ shell_floor: MANDATE_DISCLOSURE.operator_always,
391
+ target_unresolved: MANDATE_DISCLOSURE.target_unresolved,
392
+ write_protection: MANDATE_DISCLOSURE.write_protection,
393
+ tool_marks_mcp: MANDATE_DISCLOSURE.tool_marks,
394
+ tool_marks_a2a: MANDATE_DISCLOSURE.tool_marks,
374
395
  policy_rra: "the deployment's policy requires a real approval for this call",
375
396
  artifact_shared_read: "this read targets another task's shared artifact — it is cleared by confirming this call",
376
397
  mode: "the permission mode puts this question to a person",
@@ -398,12 +419,16 @@ function memberPhrase(s) {
398
419
  }
399
420
  export function allowRuleShadowSentence(shadows, ask) {
400
421
  const one = shadows.length === 1 && (shadows[0].member === "hook" || shadows[0].entries.length + (shadows[0].omitted ?? 0) === 1);
401
- const why = ask.mandate !== undefined
402
- ? mandateDisclosureOf(ask.mandate)
403
- : ask.authoredBy === "deployment"
422
+ const { askClass, mandate, authoredBy, probeReason } = ask;
423
+ const account = typeof probeReason === "string" && probeReason.trim().length > 0 && isMintableProbeReason(probeReason) ? probeReason : undefined;
424
+ const why = mandate !== undefined
425
+ ? mandateDisclosureOf(mandate, account)
426
+ : authoredBy === "deployment"
404
427
  ? "this deployment requires a person's confirmation for this call"
405
- : SHADOW_REASON[ask.askClass ?? "ordinary"];
406
- return `${shadows.map(memberPhrase).join("; ")} ${one ? "matches this call but does not clear the ask" : "match this call but do not clear the ask"} — ${why}`;
428
+ : askClass === "probe"
429
+ ? account
430
+ : SHADOW_REASON[askClass ?? "ordinary"];
431
+ return `${shadows.map(memberPhrase).join("; ")} ${one ? "matches this call but does not clear the ask" : "match this call but do not clear the ask"}${why !== undefined ? ` — ${why}` : ""}`;
407
432
  }
408
433
  export function cardDisclosureOf(decision, fallbackMessage) {
409
434
  const base = decision.message ?? fallbackMessage;