@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,42 @@
1
+ export function conversationSegmentOf(branch) {
2
+ for (let i = branch.length - 1; i >= 0; i--)
3
+ if (branch[i].type === "compaction")
4
+ return branch[i].id;
5
+ return null;
6
+ }
7
+ export const DATE_ANCHOR_CUSTOM_TYPE = "engine:date-anchor";
8
+ const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
9
+ function normalizeDateAnchor(v) {
10
+ if (typeof v !== "object" || v === null)
11
+ return undefined;
12
+ const { prefixDate, announcedDate, segment } = v;
13
+ if (typeof prefixDate !== "string" || !ISO_DATE.test(prefixDate) || typeof announcedDate !== "string" || !ISO_DATE.test(announcedDate))
14
+ return undefined;
15
+ if (segment !== null && (typeof segment !== "string" || segment.length > 200))
16
+ return undefined;
17
+ return { prefixDate, announcedDate, segment };
18
+ }
19
+ export async function readDateAnchor(session) {
20
+ let branch;
21
+ try {
22
+ branch = await session.getBranch();
23
+ }
24
+ catch {
25
+ return undefined;
26
+ }
27
+ let found;
28
+ for (let i = branch.length - 1; i >= 0 && branch[i].type !== "compaction"; i--) {
29
+ const e = branch[i];
30
+ if (found === undefined && e.type === "custom" && e.customType === DATE_ANCHOR_CUSTOM_TYPE)
31
+ found = normalizeDateAnchor(e.data);
32
+ }
33
+ const segment = conversationSegmentOf(branch);
34
+ return { current: found !== undefined && found.segment === segment ? { prefixDate: found.prefixDate, announcedDate: found.announcedDate } : undefined, segment };
35
+ }
36
+ export function owedDateAnchor(session, seat, state) {
37
+ const read = seat?.anchor;
38
+ if (read === undefined || state === undefined || read.current?.announcedDate === state.announcedDate)
39
+ return undefined;
40
+ const data = { prefixDate: seat.legDate, announcedDate: state.announcedDate, segment: read.segment };
41
+ return () => session.appendCustomEntry(DATE_ANCHOR_CUSTOM_TYPE, data).then(() => undefined, () => undefined);
42
+ }
@@ -5,11 +5,12 @@
5
5
  * WHERE THE STATE LIVES. The tree's state is one object, reached from the tree's opaque token (`RunInternals.crossBoundaryTree`,
6
6
  * `ToolExecuteContext.crossBoundaryTreeForChildren`) through this module alone; each leg joins into it what it knows at prepare (its
7
7
  * environment's declaration, its session's newest record, its posture) and every bit an exit sets lands there before the call
8
- * runs. Each leg's session holds a record (`CROSS_BOUNDARY_RECORD_TYPE`) of the state its content was produced under — written only
9
- * for an armed tree: at prepare and at an exit (before the call runs) when the state grew past what the session already says, and at
10
- * a leg's end (before a suspend's row is put, when the leg settles) also when conversation content follows the newest record. A
11
- * write that fails refuses its call (or its row) on a governed tree; a prepare's or a settle's, and any write on a tree that is not
12
- * governed, mints `config.cross_boundary_record_unwritten`. A record covers the content before it: a leg that takes over a session
8
+ * runs — after the record that carries it, so a call the exit refuses sets nothing. Each leg's session holds a record
9
+ * (`CROSS_BOUNDARY_RECORD_TYPE`) of the state its content was produced under — written only for an armed tree: at prepare and at an
10
+ * exit (before the call runs) when the state grew past what the session already says, and at a leg's end (before a suspend's row is
11
+ * put, when the leg settles) also when conversation content follows the newest record. A write that fails refuses its call (or its
12
+ * row) on a governed tree; a prepare's or a settle's, and any write on a tree that is not governed, mints
13
+ * `config.cross_boundary_record_unwritten`, once per state. A record covers the content before it: a leg that takes over a session
13
14
  * whose content no record covers (none on the branch, or after the newest), on an armed tree, reads that content as off-target.
14
15
  *
15
16
  * THE OBLIGATION of a call is read off three things at the moment it is asked ({@link crossBoundaryObligation}): the legs the
@@ -70,16 +70,22 @@ export async function prepareCrossBoundaryLane(input) {
70
70
  tree = joinCrossBoundaryTree(tree, { offTargetReadObserved: true });
71
71
  ref.current = tree;
72
72
  const stationEngaged = posture !== undefined || externalContentTargetActive || crossBoundaryTreeGoverned(tree);
73
- const unwritten = (phase, err) => deliverEngineNotice(deps.onNotice, crossBoundaryRecordUnwrittenNotice({ sessionId, runId, phase, governed: crossBoundaryTreeGoverned(ref.current), cause: thrownText(err) }));
73
+ let reported;
74
+ const unwritten = (phase, state, catchUp, err) => {
75
+ if (reported !== undefined && crossBoundaryTreeCovers(reported, state))
76
+ return;
77
+ reported = state;
78
+ deliverEngineNotice(deps.onNotice, crossBoundaryRecordUnwrittenNotice({ sessionId, runId, phase, governed: crossBoundaryTreeGoverned(ref.current), catchUp, cause: thrownText(err) }));
79
+ };
74
80
  let writing = Promise.resolve();
75
81
  let storeWaits = 0;
76
- const write = (phase, atLeaf) => {
82
+ const write = (phase, atLeaf, adds = {}) => {
77
83
  const next = writing.then(async () => {
78
84
  let leafAt = atLeaf;
79
85
  let cover = phase === "suspend" || phase === "settle";
80
86
  let written;
81
87
  for (;;) {
82
- const state = ref.current;
88
+ const state = joinCrossBoundaryTree(ref.current, adds);
83
89
  if (state.targetExecutionArmed !== true)
84
90
  return written;
85
91
  const grown = !crossBoundaryTreeCovers(recorded, state);
@@ -112,10 +118,12 @@ export async function prepareCrossBoundaryLane(input) {
112
118
  cover = false;
113
119
  }
114
120
  catch (err) {
115
- if (crossBoundaryTreeGoverned(ref.current))
121
+ const governed = crossBoundaryTreeGoverned(ref.current);
122
+ if (governed && (phase === "exit" || phase === "suspend"))
116
123
  throw err;
117
- unwritten(phase, err);
118
- recorded = state;
124
+ unwritten(phase, state, written !== undefined, err);
125
+ if (!governed)
126
+ recorded = state;
119
127
  return written;
120
128
  }
121
129
  }
@@ -124,12 +132,13 @@ export async function prepareCrossBoundaryLane(input) {
124
132
  return next;
125
133
  };
126
134
  const owe = (atLeaf) => write(atLeaf !== undefined ? "suspend" : "exit", atLeaf);
135
+ const OBSERVED = Object.freeze({ offTargetReadObserved: true });
127
136
  const trace = (phase, call) => emitTrace(deps.tracer, () => ({ kind: "permission.cross_boundary_taint", version: 1, taskId: hostTaskId, runId, phase, taint: bitsOf(ref.current), governed: ref.current.governed === true, ...(call !== undefined ? { toolName: call.toolName, ...(call.toolCallId !== undefined ? { toolCallId: call.toolCallId } : {}) } : {}), ts: Date.now() }));
128
137
  if (tree.targetExecutionArmed === true) {
129
138
  trace(resumeLeg ? "resume" : "prepare");
130
139
  if (posture === undefined && tree.governed !== true)
131
140
  deliverEngineNotice(deps.onNotice, crossBoundaryPostureUndeclaredNotice({ sessionId, runId, tree }));
132
- await write("prepare").catch((err) => unwritten("prepare", err));
141
+ await write("prepare");
133
142
  }
134
143
  let check;
135
144
  const lane = {
@@ -163,19 +172,21 @@ export async function prepareCrossBoundaryLane(input) {
163
172
  message: `tool "${call.toolName}" needs a person's confirmation: this run executes on a target device${ref.current.offTargetReadObserved === true ? " and has since let content from beyond it in, so a call that reaches beyond the device or back into it" : ", so a call that writes beyond the device"} is put to a person — this call was allowed by a configuration, not a person, and was not executed`,
164
173
  };
165
174
  }
166
- if (now.record && ref.current.offTargetReadObserved !== true) {
167
- ref.current = joinCrossBoundaryTree(ref.current, { offTargetReadObserved: true });
168
- trace("observed", call);
169
- }
175
+ const adds = now.record && ref.current.offTargetReadObserved !== true ? OBSERVED : undefined;
170
176
  const judged = ref.current;
171
177
  try {
172
- await owe();
178
+ await write("exit", undefined, adds);
173
179
  }
174
180
  catch (err) {
175
181
  return { kind: "unrecorded", message: `tool "${call.toolName}" was not executed: the session's cross-boundary record could not be written before it ran (${thrownText(err)}) — on a governed tree a call that owes its record does not run without it; refused fail-closed` };
176
182
  }
177
- if (ref.current === judged)
178
- return undefined;
183
+ if (ref.current !== judged)
184
+ continue;
185
+ if (adds !== undefined) {
186
+ ref.current = joinCrossBoundaryTree(ref.current, adds);
187
+ trace("observed", call);
188
+ }
189
+ return undefined;
179
190
  }
180
191
  },
181
192
  };
@@ -184,7 +195,7 @@ export async function prepareCrossBoundaryLane(input) {
184
195
  owe,
185
196
  storeWaits: () => storeWaits,
186
197
  recorded: () => ref.current.targetExecutionArmed === true,
187
- settle: () => write("settle").then(() => undefined, (err) => unwritten("settle", err)),
198
+ settle: () => write("settle").then(() => undefined),
188
199
  };
189
200
  return lane;
190
201
  }
@@ -17,7 +17,7 @@
17
17
  */
18
18
  import { type AskOrigin } from "../ask-origin.js";
19
19
  import { type OnQuestion, type QuestionAnswer } from "../ask-question.js";
20
- import { type Checkpoint, type ResolvedOutcome, type ResumeOutcome } from "../checkpoint-store.js";
20
+ import { type Checkpoint, type CheckpointErrorField, type ResolvedOutcome, type ResumeOutcome } from "../checkpoint-store.js";
21
21
  import { type GateOutcome, type HostDecisionFacts } from "../gate-outcome.js";
22
22
  import type { ResumeRun } from "./contracts.js";
23
23
  /**
@@ -130,10 +130,13 @@ export declare function mintDecideRecord(cp: Checkpoint, facts: HostDecisionFact
130
130
  * answer differently each time — the check passing on text it never inspected. Refused pre-CAS so the
131
131
  * row stays `pending` for a well-formed decide, exactly like the other capture-time domain refusals,
132
132
  * and BEFORE the hygiene check so no guard ever consults a value outside the domain. The rejected field
133
- * is named in the message only — `CheckpointError`'s structured `detail.field` is a closed set covering
134
- * the approval lane's payload names, and widening it is a wire-surface change of its own.
133
+ * is named in the message, and in `detail` where the caller hands the closed set's word for the cell
134
+ * (`CheckpointErrorField`: `feedback` has one; `reason` and `editedPlan` have none, and widening the set is a
135
+ * wire-surface change of its own).
135
136
  */
136
- export declare function assertOutcomeText(value: string | undefined, field: "editedPlan" | "reason" | "feedback"): void;
137
+ export declare function assertOutcomeText(value: string | undefined, field: "editedPlan" | "reason" | "feedback", detail?: {
138
+ field: CheckpointErrorField;
139
+ }): void;
137
140
  /**
138
141
  * The continuation prompt for a resumed run. The vendored harness only exposes
139
142
  * `prompt(text)` (it always appends a user message — there is no "continue from tool results" entry), so
@@ -123,9 +123,9 @@ export function mintDecideRecord(cp, facts, verdict) {
123
123
  const settlement = settlementOfHostDecision(facts, verdict.allowed ? "allowed" : "refused", verdict.note);
124
124
  return mintGateOutcome({ ...(verdict.allowed ? {} : { deniedBy: "ask_resolution" }), settled: { settlement, origin } });
125
125
  }
126
- export function assertOutcomeText(value, field) {
126
+ export function assertOutcomeText(value, field, detail) {
127
127
  if (value !== undefined && typeof value !== "string") {
128
- throw new CheckpointError("checkpoint.invalid_outcome", `resume \`${field}\` is not a plain string (got ${typeof value}) — a decide's text payload is an operator's plain data, not a live object; refusing pre-CAS, the checkpoint stays pending`);
128
+ throw new CheckpointError("checkpoint.invalid_outcome", `resume \`${field}\` is not a plain string (got ${typeof value}) — a decide's text payload is an operator's plain data, not a live object; refusing pre-CAS, the checkpoint stays pending`, detail);
129
129
  }
130
130
  }
131
131
  function reorientClause(fullShellReachable) {
@@ -170,13 +170,13 @@ export type InheritedClassifierJudgment<A extends InheritedAsk> =
170
170
  };
171
171
  /**
172
172
  * The ancestor's frozen classifier, run BEFORE its frozen approver in the ancestor's own gate order,
173
- * with the denial-limit count folded in (CC 2.1.250 count-then-judge): `allow` ⇒ the classifier's
173
+ * with the denial-limit count folded in (count-then-judge): `allow` ⇒ the classifier's
174
174
  * auto-allow (and the streak resets); `block` below the bound ⇒ deny, the exact verdict the ancestor's
175
175
  * gate would have produced; `block` AT the bound ⇒ the ask is re-spoken in the classifier's voice as
176
176
  * the fallback (`decisionReason:"classifier"`, `requiresRealApproval`, the member carrying counts +
177
177
  * window) for the arm to resolve at the frozen approver; a classification that did not rule (`unavailable`, or a reply
178
178
  * with no verdict) ⇒ the gate's own exit (`classifierNoRulingArm`) on the frozen approver — a live one resolves the incoming
179
- * ask carrying why (never counted); none ⇒ the unavailable form is a DENY that says so (CC 2.1.250 form, never counted) and
179
+ * ask carrying why (never counted); none ⇒ the unavailable form is a DENY that says so (never counted) and
180
180
  * a reply with no verdict takes the block path with the CC parse-failure sentence (counted); a CONFLICTING reply takes the
181
181
  * block path too; excluded / no classifier ⇒ the incoming ask, unchanged. The member may ALREADY be on the incoming
182
182
  * ask (a deeper ancestor's fallback, minted inside the nested fold — the case the exclusion names):
@@ -1,22 +1,25 @@
1
1
  /**
2
- * The derived-leg route pre-flight shared by prepareTask's two derived seats: the compaction-summary model (the
3
- * driver's own seat, resolved before the offload prelude) and the auto-mode classifier model (the caps-and-workflow
4
- * phase's arming). Moved whole out of the orchestrator so the phase reaches DOWN for it instead of the two callers
5
- * spelling it twice. The judgment law and both announcements live in the brain's route adjudicator; this is the one
6
- * guarded seat around them.
2
+ * The derived-leg route pre-flight shared by prepareTask's derived seats: the compaction-summary model, the auto-mode
3
+ * classifier model and the advisor model. One guarded seat, reached DOWN for by each phase instead of spelled again; the
4
+ * judgment law and the announcements live in the brain's route adjudicator.
7
5
  */
8
- import type { Model } from "../../internal/llm.js";
6
+ import type { Model, RouteRefusalCode } from "../../internal/llm.js";
9
7
  import type { RunnerDeps, TaskSpec } from "../types.js";
8
+ /** What the pre-flight decided: keep the seat's model (same route as the primary, the pairing holds, the judge abstained, or
9
+ * the deployment declined a fallback — the seat is kept and its calls refused), swap it for the primary, or take the seat
10
+ * off this run. A move carries the refusal that caused it. */
11
+ export type DerivedSeatOutcome = {
12
+ readonly action: "keep";
13
+ } | {
14
+ readonly action: "fall_back" | "detach";
15
+ readonly cause: RouteRefusalCode;
16
+ };
10
17
  /**
11
- * The derived-leg pairing pre-flight as ONE guarded seat: judge the derived model where its route
12
- * differs from the primary's, announce what a broken pairing means for THIS seat (`onBrokenPairing` —
13
- * one judgment, and the POSTURE is the deployment's), and ABSTAIN (keep the derived model) on ANY throw. The pre-flight is advisory — the brain's request gate re-runs the
14
- * same law — so neither a throwing judge face nor a garbage catalog value (the route-identity
15
- * normalization throws a TypeError on a non-string baseUrl) may widen into "task preparation
16
- * failed": at the compaction seat the session is already acquired and the throw-cleanup contract
17
- * is not yet armed, so a throw here would leak the acquired session view, and the garbage value
18
- * still earns its loud refusal at the request gate the moment the derived leg is actually used.
19
- * Returns whether the seat should fall back to the primary model.
18
+ * Judge the derived model where its route differs from the primary's, announce what a broken pairing means for THIS seat
19
+ * (`onBrokenPairing`), and ABSTAIN (keep) on ANY throw. The pre-flight is advisory — the brain's request gate re-runs the
20
+ * same law — so neither a throwing judge face nor a garbage catalog value may widen into "task preparation failed": at the
21
+ * compaction seat the session is already acquired and the throw-cleanup contract is not yet armed, and the garbage value
22
+ * still earns its loud refusal at the request gate the moment the derived leg is used.
20
23
  */
21
24
  export declare function derivedRouteFallsBack(args: {
22
25
  seat: string;
@@ -25,14 +28,11 @@ export declare function derivedRouteFallsBack(args: {
25
28
  brain: RunnerDeps["brain"];
26
29
  getApiKeyAndHeaders: TaskSpec["getApiKeyAndHeaders"];
27
30
  onNotice: RunnerDeps["onNotice"];
28
- /** The run this seat resolution belongs to; carried onto the notice as its routing key
29
- * (the audience stays operator: correlation, not entitlement). Absent ⇒ nothing is fabricated. */
31
+ /** The session / INVOCATION this resolution belongs to: correlation keys on the notice (the audience stays operator). */
30
32
  sessionId?: string;
31
- /** The INVOCATION this seat resolution belongs to. The session cannot stand in for it: two
32
- * runs of one session that both fall back on the same seat mint otherwise byte-identical lines. */
33
33
  runId?: string;
34
- /** What this seat's DEPLOYMENT asked for on a broken pairing. Absent / `"fall_back"`: swap and announce `route.fallback_to_primary`
35
- * (the only posture a seat with no knob of its own has). `"refuse"`: keep the seat and announce `route.classifier_unroutable` — never
36
- * quietly granting a fallback the deployment declined (`autoMode.classifierFallback: "none"`); announcing is why no swap is not no word. */
37
- onBrokenPairing?: "fall_back" | "refuse";
38
- }): Promise<boolean>;
34
+ /** Absent / `"fall_back"`: swap and announce `route.fallback_to_primary`. `"refuse"`: keep the seat and announce
35
+ * `route.classifier_unroutable` (the deployment declined a fallback — never granted quietly). `"detach"`: take the seat
36
+ * off the run and announce `route.seat_detached` (a seat the primary model cannot stand in for). */
37
+ onBrokenPairing?: "fall_back" | "refuse" | "detach";
38
+ }): Promise<DerivedSeatOutcome>;
@@ -1,21 +1,23 @@
1
- import { adjudicateDerivedRoute, fallbackToPrimaryNotice, sameRouteIdentity, unroutableSeatNotice } from "../../brain/route-adjudicator.js";
1
+ import { adjudicateDerivedRoute, fallbackToPrimaryNotice, sameRouteIdentity, seatDetachedNotice, unroutableSeatNotice } from "../../brain/route-adjudicator.js";
2
2
  import { deliverEngineNotice } from "../types.js";
3
3
  export async function derivedRouteFallsBack(args) {
4
4
  try {
5
5
  if (sameRouteIdentity(args.derived, args.primary))
6
- return false;
6
+ return { action: "keep" };
7
7
  const verdict = await adjudicateDerivedRoute({ brain: args.brain, model: args.derived, getApiKeyAndHeaders: args.getApiKeyAndHeaders });
8
8
  if (verdict === undefined || verdict.ok)
9
- return false;
9
+ return { action: "keep" };
10
10
  const shared = { seat: args.seat, from: args.derived.id, verdict, ...(args.sessionId !== undefined ? { sessionId: args.sessionId } : {}), ...(args.runId !== undefined ? { runId: args.runId } : {}) };
11
- const refuse = args.onBrokenPairing === "refuse";
12
- if (refuse)
11
+ const posture = args.onBrokenPairing ?? "fall_back";
12
+ if (posture === "refuse")
13
13
  deliverEngineNotice(args.onNotice, unroutableSeatNotice({ ...shared, primary: args.primary.id }));
14
+ else if (posture === "detach")
15
+ deliverEngineNotice(args.onNotice, seatDetachedNotice(shared));
14
16
  else
15
17
  deliverEngineNotice(args.onNotice, fallbackToPrimaryNotice({ ...shared, to: args.primary.id }));
16
- return !refuse;
18
+ return posture === "refuse" ? { action: "keep" } : { action: posture, cause: verdict.code };
17
19
  }
18
20
  catch {
19
- return false;
21
+ return { action: "keep" };
20
22
  }
21
23
  }
@@ -22,6 +22,7 @@
22
22
  * contract (`ToolGateInput`, `ToolGateResult`, the observer payload), which stays declared there.
23
23
  */
24
24
  import { type ClassifierDenyCause, type DeniedBy, type GateOutcome, type ModeRefusal, type ModeRelease, type Settlement } from "../gate-outcome.js";
25
+ import type { AllowRuleClearance } from "../allow-rule-shadow.js";
25
26
  import type { AutoModeClassifierRound } from "../auto-mode.js";
26
27
  import { type Arbitration, type AskClassification, type AskFace, type AskOrigin, type AskOriginFacts } from "../ask-origin.js";
27
28
  import { type PermissionResult, type ResolvedAsk, type ToolCallRequest } from "../tool-policy.js";
@@ -49,6 +50,8 @@ export interface GateExitFacts {
49
50
  classifier?: AutoModeClassifierRound;
50
51
  /** The permission mode RELEASED the surviving ask (the allow exit's account of it); never beside `deniedBy`. */
51
52
  released?: ModeRelease;
53
+ /** An allow-layer member CLEARED the standing ask (the allow exit's account of it); never beside `deniedBy`, a settlement or a release. */
54
+ clearedBy?: AllowRuleClearance;
52
55
  /** The permission mode REFUSED the surviving ask — only beside `deniedBy: "mode"`. */
53
56
  modeRefusal?: ModeRefusal;
54
57
  }
@@ -333,6 +336,9 @@ export interface GatePass {
333
336
  arbitration?: Exclude<Arbitration, {
334
337
  kind: "ask";
335
338
  }>;
339
+ /** borrowed-mutable — the allow-layer member that CLEARED the standing ask and the entries it stood on (the allow exit projects
340
+ * it onto the disposition when nobody answered an ask on this pass). Writer: the lanes' allow layer. */
341
+ clearedBy?: AllowRuleClearance;
336
342
  }
337
343
  /**
338
344
  * The engine's fail-closed block of phase 1 — the PreToolUse face THREW or never ANSWERED, so the engine
@@ -23,7 +23,12 @@ export function mintGateOutcome(facts) {
23
23
  ...(attribution !== undefined ? { classifier: attribution } : {}),
24
24
  ...(facts.modeRefusal !== undefined ? { mode: facts.modeRefusal.mode, askClass: facts.modeRefusal.askClass, classes: Object.freeze([...facts.modeRefusal.classes]) } : {}),
25
25
  }
26
- : { kind: "allowed", ...(attribution !== undefined ? { classifier: attribution } : {}), ...(facts.released !== undefined ? { released: Object.freeze({ ...facts.released, classes: Object.freeze([...facts.released.classes]) }) } : {}) }),
26
+ : {
27
+ kind: "allowed",
28
+ ...(attribution !== undefined ? { classifier: attribution } : {}),
29
+ ...(facts.released !== undefined ? { released: Object.freeze({ ...facts.released, classes: Object.freeze([...facts.released.classes]) }) } : {}),
30
+ ...(facts.clearedBy !== undefined ? { clearedBy: Object.freeze({ ...facts.clearedBy, entries: Object.freeze([...facts.clearedBy.entries]), ...(facts.clearedBy.positions !== undefined ? { positions: Object.freeze([...facts.clearedBy.positions]) } : {}) }) } : {}),
31
+ }),
27
32
  ...(facts.settled !== undefined ? { settlement: settlement, origin: facts.settled.origin } : {}),
28
33
  });
29
34
  const defects = screenGateOutcome(outcome, { reading: "producer" });
@@ -315,7 +320,7 @@ export async function exitGate(pass) {
315
320
  return undefined; const a = pass.arbitration === undefined ? input.ancestorArbitrationOf?.(toolCallId) : undefined; return a?.kind === "released" ? a : undefined; })();
316
321
  return {
317
322
  updatedInput: pass.currentInput,
318
- gate: mintGateOutcome({ ...(ledger.settled !== undefined ? { settled: ledger.settled } : {}), ...(pass.classifierRound !== undefined ? { classifier: pass.classifierRound } : {}), ...(release !== undefined ? { released: releaseRecordOf(release) } : {}) }),
323
+ gate: mintGateOutcome({ ...(ledger.settled !== undefined ? { settled: ledger.settled } : {}), ...(pass.classifierRound !== undefined ? { classifier: pass.classifierRound } : {}), ...(release !== undefined ? { released: releaseRecordOf(release) } : {}), ...(pass.clearedBy !== undefined && ledger.settled === undefined && release === undefined ? { clearedBy: pass.clearedBy } : {}) }),
319
324
  finalInput: frozenInputSnapshot(pass.currentInput),
320
325
  preToolContext: pass.preToolContext,
321
326
  };
@@ -4,7 +4,7 @@ export function createRunState() {
4
4
  degrade: { degradeToModel: undefined, degraded: undefined, outputErrorStreak: 0, outputInvalid: false, recordDegraded: () => { } },
5
5
  limits: { turnsExceeded: false, budgetHit: undefined, budgetAxis: undefined, platformTerminal: undefined, outputRetryCap: 0, effectiveMaxTurns: undefined },
6
6
  budget: { remainingMicroUsd: undefined, maxCostMicroUsd: undefined, remainingTokens: undefined, maxTokensWindow: undefined, overBudget: () => undefined, streamCancel: false, callOutputChars: 0, lastStreamBudgetCheck: 0, projectedOverBudget: () => undefined },
7
- turn: { callStartAt: undefined, firstTokenAt: undefined, turnUsage: undefined, turnUsageMissing: false, turnStopReason: undefined, turnResponseModel: undefined, lastTurnHadToolCalls: false, toolBatch: [] },
7
+ turn: { callStartAt: undefined, firstTokenAt: undefined, turnUsage: undefined, turnUsageMissing: false, turnStopReason: undefined, turnResponseModel: undefined, toolBatch: [] },
8
8
  counters: { approachNoticesSent: 0, walltimeSyncBackstopFired: false, compactionFloor: 0, trimForceBackoff: false, compactionPasses: 0, repetitionCuts: 0, repetitionSpared: 0, repetitionEvents: [], REPETITION_EVENTS_CAP: 0, preemptIgnoredReported: false, wroteThisRun: false, finalVerifyInjections: 0, groundingSignalPreR9: false, groundingSignalPostR9: false, cadenceTurns: 0 },
9
9
  attach: { attachmentsCfg: undefined, agentListingOn: false, skillsListingOn: false, attachState: undefined, dateState: undefined, instrProbe: undefined, instrState: undefined, sizeGuidelineState: undefined, attachmentsInjected: 0 },
10
10
  };
@@ -32,7 +32,7 @@ import { type HeadLeads } from "../path-rule-binding.js";
32
32
  import type { ToolCallLike } from "../tool-registry.js";
33
33
  import { type OrgRuleResolution } from "../permission-rule-org.js";
34
34
  import { type EffectivePermissionRules, type PermissionRuleStoreProvider, type PersonRowsRead } from "../permission-rule-provider.js";
35
- /** The one SHELL tool the persisted-rule lane's COMMAND grammar speaks for (the rule-offer face mints for it and the name tools); the other grammars' tools are derived (`ruleToolGrammarOf`). */
35
+ /** The one SHELL tool the persisted-rule lane's COMMAND grammar speaks for (the rule-offer face mints for it, the name tools and the host tools); the other grammars' tools are derived (`ruleToolGrammarOf`). */
36
36
  export declare const PERSISTED_RULE_TOOL = "Bash";
37
37
  /**
38
38
  * The evidence an INHERITED-lane ask carries.
@@ -225,7 +225,7 @@ interface RuleOffersAskFacts extends RuleClearanceFacts {
225
225
  * "stop asking me this" on a card that will keep asking lets a person mint a rule that never
226
226
  * takes effect where they minted it.
227
227
  *
228
- * (CC 2.1.245 toolPolicy 对表, F11: "wildcard `ask` … keeps every matching tool behind a
228
+ * (toolPolicy 对表, F11: "wildcard `ask` … keeps every matching tool behind a
229
229
  * per-call prompt (no persistent always-allow)") — `matchedAskRule` was the one conjunct of the
230
230
  * lane's own clearing predicate this door did not mirror, and the asymmetry was live: the
231
231
  * persisted-rule lane refuses to clear ANY ask carrying it (`hooks.ts`, the
@@ -1,6 +1,7 @@
1
1
  import { persistedRuleMandateOf, ruleClearanceOf } from "../ask-origin.js";
2
2
  import {} from "../hooks.js";
3
- import { adjudicatePersistedDomainRules, adjudicatePersistedNameRules, adjudicatePersistedPathRules, adjudicatePersistedRules, callPathFaceOf, domainRuleSubjectOf, escapeForDisclosure, faceRowsSpeakFor, laneToolNamesOf, nameRuleSubjectOf, ruleToolGrammarOf, segmentCoverageOf, suggestRuleForName, suggestRulesForCommand } from "../permission-rule-model.js";
3
+ import { adjudicatePersistedDomainRules, adjudicatePersistedNameRules, adjudicatePersistedPathRules, adjudicatePersistedRules, callPathFaceOf, escapeForDisclosure, faceRowsSpeakFor, laneToolNamesOf, nameRuleSubjectOf, ruleToolGrammarOf, segmentCoverageOf, suggestRuleForHost, suggestRuleForName, suggestRulesForCommand } from "../permission-rule-model.js";
4
+ import { callHostTargetOf } from "../host-target.js";
4
5
  import { callTargetViewsOf, validatePath } from "../effective-path-target.js";
5
6
  import { bindPathRules, persistedRowAnchors, projectScopeIdentity } from "../path-rule-binding.js";
6
7
  import { heldBy, seatOf, wireOf } from "../tool-name-readings.js";
@@ -120,9 +121,9 @@ export function createPermissionRuleLanes(cfg) {
120
121
  const judged = laneToolNamesOf(req).map((n) => [n, ruleToolGrammarOf(n)]);
121
122
  if (!judged.some(([, g]) => g === "path") && faceRowsSpeakFor(callPathFaceOf(req)))
122
123
  judged.push([req.toolName, "path"]);
123
- if (judged.length === 0)
124
- return undefined;
125
124
  const view = await reader.pin(req.toolCallId);
125
+ if (judged.length === 0)
126
+ return view.unreadable !== undefined ? { unreadable: true } : undefined;
126
127
  try {
127
128
  const table = view.rules.filter((r) => r.behavior !== "allow" || cfg.stripsAllow?.(r, req) !== true);
128
129
  const leads = judged.some(([, g]) => g === "path") ? await cfg.leads.resolve(bindPathRules(table.filter((r) => r.match === "path" || r.match === "subpath").map((r) => ({ parsed: r, ruleText: r.rule, rule: r })), (spec) => anchorsOf(spec.rule))) : NO_LEADS;
@@ -144,9 +145,9 @@ export function createPermissionRuleLanes(cfg) {
144
145
  if (grammar === "path")
145
146
  return pathRuleLaneAnswer(table, req, { root: cfg.root, sessionId: cfg.sessionId, anchorsOf, leads, ...scope });
146
147
  if (grammar === "name")
147
- return persistedRuleAnswerOf(adjudicatePersistedNameRules(table, { tool: req.toolName, name: nameRuleSubjectOf(req.toolName, req.args), cwd: cfg.root, sessionId: cfg.sessionId, ...scope }));
148
+ return persistedRuleAnswerOf(adjudicatePersistedNameRules(table, { tool: req.toolName, request: req, cwd: cfg.root, sessionId: cfg.sessionId, ...scope }));
148
149
  if (grammar === "domain")
149
- return persistedRuleAnswerOf(adjudicatePersistedDomainRules(table, { tool: req.toolName, host: domainRuleSubjectOf(req.toolName, req.args), cwd: cfg.root, sessionId: cfg.sessionId, ...scope }));
150
+ return persistedRuleAnswerOf(adjudicatePersistedDomainRules(table, { tool: req.toolName, hosts: { tighten: callHostTargetOf(req, "tighten"), grant: callHostTargetOf(req, "grant") }, cwd: cfg.root, sessionId: cfg.sessionId, ...scope }));
150
151
  const command = req.args?.command;
151
152
  if (typeof command !== "string")
152
153
  return undefined;
@@ -163,7 +164,8 @@ export function createPermissionRuleLanes(cfg) {
163
164
  export function createRuleOffersOf(cfg) {
164
165
  return (call, args, ask) => {
165
166
  const toolName = wireOf("offer.laneTool", call);
166
- if (!cfg.laneArmed || (toolName !== PERSISTED_RULE_TOOL && ruleToolGrammarOf(toolName) !== "name"))
167
+ const grammar = ruleToolGrammarOf(toolName);
168
+ if (!cfg.laneArmed || (toolName !== PERSISTED_RULE_TOOL && grammar !== "name" && grammar !== "domain"))
167
169
  return {};
168
170
  if ((cfg.principal === undefined || cfg.principal === "") && !cfg.localOwnerDeclared)
169
171
  return {};
@@ -175,10 +177,15 @@ export function createRuleOffersOf(cfg) {
175
177
  }).word;
176
178
  if (closedDoor !== undefined)
177
179
  return { ruleOffersAbsence: closedDoor };
178
- if (ruleToolGrammarOf(toolName) === "name") {
180
+ if (grammar === "name") {
179
181
  const offer = suggestRuleForName(toolName, nameRuleSubjectOf(toolName, args) ?? "");
180
182
  return offer !== undefined ? { ruleOffers: [offer] } : { ruleOffersAbsence: "lane_cannot_speak" };
181
183
  }
184
+ if (grammar === "domain") {
185
+ const host = callHostTargetOf({ toolName: call.toolName, args, face: call.face }, "grant");
186
+ const offer = host !== undefined && "host" in host ? suggestRuleForHost(toolName, host.host) : undefined;
187
+ return offer !== undefined ? { ruleOffers: [offer] } : { ruleOffersAbsence: "lane_cannot_speak" };
188
+ }
182
189
  const command = args?.command;
183
190
  if (typeof command !== "string")
184
191
  return { ruleOffersAbsence: "lane_cannot_speak" };
@@ -367,7 +367,7 @@ export function ruleStoreUnreadableNotice(onNotice, ids) {
367
367
  const which = sources !== undefined && sources.length > 0 ? `your persisted permission rules from the ${sourcesWord(sources)} sources` : "your persisted permission rules";
368
368
  deliverEngineNotice(onNotice, {
369
369
  code: "permission.rule_store_unavailable",
370
- message: `${which} could not be read ${at === "prepare" ? "when this run started" : "for a call on this run"}. Until a read of them succeeds, none of their allow rows (Read directory rows included) applies, while the deny and ask rows most recently read from them this run still apply — a deny row you removed since that read keeps refusing until then. While they cannot be read, every call your rules judge (a file read, a write, a command) is asked about rather than allowed, until a read of them succeeds. Every later check reads them again.`,
370
+ message: `${which} could not be read ${at === "prepare" ? "when this run started" : "for a call on this run"}. Until a read of them succeeds, none of their allow rows (Read directory rows included) applies, while the deny and ask rows most recently read from them this run still apply — a deny row you removed since that read keeps refusing until then. While they cannot be read, every call is asked about rather than allowed, whatever its tool (rules nobody can read may name any), until a read of them succeeds. Every later check reads them again.`,
371
371
  detail: { at, sessionId: ids.sessionId, runId: ids.runId },
372
372
  });
373
373
  };
@@ -0,0 +1,63 @@
1
+ /**
2
+ * PrepareTask's ADVISOR phase: whether this leg mounts the `advisor` tool, and what it owes the model about it. In order —
3
+ * the deployment switch (`RunnerDeps.advisorTool: "disabled"` ignores the spec's advisor model unread); the static verdict
4
+ * (`advisorAttachVerdict`, the one answer a host's advisor query reads too); then the mount chain — the reserved name, the
5
+ * leg's tool selector (its valve's own predicate, asked of the tool's name), the conversation's hold (the transcript), the
6
+ * advisor route (the shared derived-seat pre-flight, posture `detach`) — and the mount. Its answer is the manifest fact,
7
+ * the person's notice for a reason they are told (root legs only, once per conversation per pair), and the leg's
8
+ * instruction seat (what the model is owed, against what it was told in the conversation's current segment).
9
+ *
10
+ * Runs after the scaffold mounts and before the tool-face fold, so the deferred classification, the prompt and the
11
+ * manifest see the roster the leg runs with. A leg whose spec names no advisor model and whose conversation never told
12
+ * the model about one does nothing here and reads nothing.
13
+ */
14
+ import type { SessionTreeEntry } from "../../internal/harness-types.js";
15
+ import type { Model } from "../../internal/llm.js";
16
+ import type { CompactionForkContext } from "../auto-compaction.js";
17
+ import type { ToolSelector } from "../tool-face.js";
18
+ import type { RosterBuilder } from "../tool-roster.js";
19
+ import { type RunnerDeps, type TaskSpec } from "../types.js";
20
+ import type { WiringAdvisorFact } from "../wiring-manifest.js";
21
+ import { type AdvisorInstructionSeat } from "./advisor-instructions.js";
22
+ import { type AnnounceOnceLedger } from "./announce-once-ledger.js";
23
+ import type { Prepared } from "./contracts.js";
24
+ export interface PrepareAdvisorInput {
25
+ /** borrowed-readonly — the REBOUND spec: the advisor model, the caller's tools (the reserved name), the whole-face switch, the auth hook. */
26
+ spec: Pick<TaskSpec, "advisorModel" | "tools" | "excludeAllTools" | "getApiKeyAndHeaders">;
27
+ /** borrowed-readonly — the deployment switch as the value door screened it. */
28
+ advisorTool: "disabled" | undefined;
29
+ /** borrowed-readonly — the catalog and tiers the verdict reads, the brain the advisor lane books, the notice sink. */
30
+ deps: Pick<RunnerDeps, "models" | "tiers" | "brain" | "onNotice">;
31
+ /** borrowed-readonly — the leg's resolved main model. */
32
+ model: Model;
33
+ /** borrowed-mutable — the mount array (the advisor tool is mounted on it). */
34
+ roster: RosterBuilder;
35
+ /** borrowed-readonly — the leg's frozen tool selector (the valve's predicate). */
36
+ selector: ToolSelector;
37
+ /** borrowed-readonly — the acquired session: its branch (the hold, the segment). */
38
+ session: {
39
+ getBranch(): Promise<ReadonlyArray<SessionTreeEntry>>;
40
+ };
41
+ /** borrowed-readonly — the once-per-session ledger: what the model was told (`arms().advisor`), and the notice's dedupe. */
42
+ onceLedger: Pick<AnnounceOnceLedger, "arms" | "oncePerSession">;
43
+ /** borrowed-readonly — a leg the person reads (not a delegated child): only such a leg tells them. */
44
+ rootLeg: boolean;
45
+ /** borrowed-readonly — the acquired session's id (the notice's routing key). */
46
+ sessionId: string;
47
+ /** borrowed-readonly — this invocation's id (the notices' correlation key). */
48
+ runId: string | undefined;
49
+ /** borrowed-readonly — the leg's usage-account door (the run body binds it before any tool call). */
50
+ sideCallBookRef: Prepared["sideCallBookRef"];
51
+ /** borrowed-readonly — the request the main lane last sent (read at each call). */
52
+ lastSentRequest: () => CompactionForkContext | undefined;
53
+ /** borrowed-readonly — the leg's resolved brain-call guardrail (the value doors' answer; `undefined` = off). */
54
+ brainCallGuardrailMs: number | undefined;
55
+ }
56
+ export interface PrepareAdvisorResult {
57
+ /** The manifest's `advisor` fact; absent ⇔ the spec names no advisor model. */
58
+ manifest: WiringAdvisorFact | undefined;
59
+ /** The leg's instruction seat; absent when there is nothing to tell and nothing told. */
60
+ instruction: AdvisorInstructionSeat | undefined;
61
+ }
62
+ /** The phase body — see the module header. Throws only `config.reserved_tool_name` (a caller tool named `advisor` on a leg that mounts it). */
63
+ export declare function prepareAdvisor(input: PrepareAdvisorInput): Promise<PrepareAdvisorResult>;