@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,77 @@
1
+ import { valveLeaves } from "../../agents/tool-filter.js";
2
+ import { ADVISOR_TOOL_NAME, advisorAttachVerdict, advisorHoldOf, advisorNotAttachedNotice, advisorReasonTold } from "../advisor-verdict.js";
3
+ import { deliverEngineNotice } from "../types.js";
4
+ import { advisorInstructionFrame } from "./advisor-instructions.js";
5
+ import { createAdvisorTool } from "./advisor-tool.js";
6
+ import { announceDigest } from "./announce-once-ledger.js";
7
+ import { conversationSegmentOf } from "./conversation-segment.js";
8
+ import { derivedRouteFallsBack } from "./derived-route-fallback.js";
9
+ import { derivedLegBrain } from "./side-call-account.js";
10
+ import { withBrainCallGuardrail } from "../../brain/timeout.js";
11
+ export async function prepareAdvisor(input) {
12
+ const { spec, deps, model, onceLedger, sessionId, runId } = input;
13
+ const told = onceLedger.arms().advisor;
14
+ if (spec.advisorModel === undefined && told === undefined)
15
+ return { manifest: undefined, instruction: undefined };
16
+ const requested = spec.advisorModel === undefined || input.advisorTool === "disabled" ? undefined : typeof spec.advisorModel === "string" ? spec.advisorModel : spec.advisorModel.id;
17
+ const fact = (f) => ({ ...(requested !== undefined ? { requested } : {}), main: model.id, ...f });
18
+ const notAttached = (reason, extra = {}) => {
19
+ if (input.rootLeg && requested !== undefined && advisorReasonTold(reason)) {
20
+ onceLedger.oncePerSession(announceDigest("advisor.not_attached", `${reason}\n${requested}\n${model.id}`), () => deliverEngineNotice(deps.onNotice, advisorNotAttachedNotice({ reason, advisorModel: requested, mainModel: model.id, sessionId, ...(runId !== undefined ? { runId } : {}) })));
21
+ }
22
+ return fact({ state: "not_attached", reason, ...extra });
23
+ };
24
+ let branch;
25
+ const readBranch = async () => (branch ??= await input.session.getBranch().catch(() => undefined));
26
+ let mounted = false;
27
+ const mount = async (advisor) => {
28
+ if ((spec.tools ?? []).some((t) => t.name === ADVISOR_TOOL_NAME)) {
29
+ const e = new Error(`Tool name "${ADVISOR_TOOL_NAME}" is reserved when TaskSpec.advisorModel attaches the advisor tool.`);
30
+ e.code = "config.reserved_tool_name";
31
+ throw e;
32
+ }
33
+ if (!valveLeaves(spec, input.selector)({ name: ADVISOR_TOOL_NAME }))
34
+ return fact({ state: "not_attached", reason: "excluded" });
35
+ const entries = await readBranch();
36
+ if (entries === undefined)
37
+ return notAttached("hold_unknown");
38
+ const held = advisorHoldOf(entries);
39
+ if (held !== undefined)
40
+ return fact({ state: "held", model: advisor.id, hold: held });
41
+ const route = await derivedRouteFallsBack({ seat: "advisor", derived: advisor, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId, ...(runId !== undefined ? { runId } : {}), onBrokenPairing: "detach" });
42
+ if (route.action === "detach")
43
+ return notAttached("route_refused", { routeCode: route.cause });
44
+ input.roster.mount(createAdvisorTool(advisorSeat(input, advisor)), { source: "builtin", mountedBy: "optional" });
45
+ mounted = true;
46
+ return fact({ state: "on", model: advisor.id });
47
+ };
48
+ let manifest;
49
+ if (spec.advisorModel !== undefined) {
50
+ const verdict = advisorAttachVerdict({ deps: { ...deps, ...(input.advisorTool !== undefined ? { advisorTool: input.advisorTool } : {}) }, main: model, advisor: spec.advisorModel });
51
+ manifest = verdict.state === "on" ? await mount(verdict.model) : notAttached(verdict.reason);
52
+ }
53
+ const entries = told !== undefined || mounted ? await readBranch() : undefined;
54
+ if (entries === undefined)
55
+ return { manifest, instruction: undefined };
56
+ const segment = conversationSegmentOf(entries);
57
+ const owed = advisorInstructionFrame(told !== undefined && told.segment === segment ? told.state : undefined, mounted);
58
+ return { manifest, instruction: { ...(owed !== undefined ? { owed } : {}), segment, mounted } };
59
+ }
60
+ function advisorSeat(input, model) {
61
+ const book = (lane, m, reply) => {
62
+ const door = input.sideCallBookRef.book;
63
+ if (door === undefined)
64
+ throw new Error("the advisor was consulted before the run body bound the leg's usage account, which it does before any tool call");
65
+ door(lane, m, reply);
66
+ };
67
+ const ms = input.brainCallGuardrailMs;
68
+ const guarded = (b) => (ms === undefined ? b : { ...b, stream: withBrainCallGuardrail((m, c, o) => b.stream(m, c, o), ms, {}) });
69
+ return {
70
+ model,
71
+ brain: derivedLegBrain(() => guarded(input.deps.brain), "advisor", book),
72
+ lastSentRequest: input.lastSentRequest,
73
+ readBranch: () => input.session.getBranch(),
74
+ getApiKeyAndHeaders: input.spec.getApiKeyAndHeaders,
75
+ markUsageUnknown: () => book("advisor", model, undefined),
76
+ };
77
+ }
@@ -223,7 +223,7 @@ export async function prepareCapsAndWorkflow(input) {
223
223
  const am = autoModeFace;
224
224
  const classifierSeat = classifierSeatModel({ deps, main: model });
225
225
  let classifierModel = classifierSeat.model;
226
- if (await derivedRouteFallsBack({ seat: "auto-mode-classifier", derived: classifierModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId, runId, onBrokenPairing: autoModeClassifierFallbackOf(am.classifierFallback) === "none" ? "refuse" : "fall_back" })) {
226
+ if ((await derivedRouteFallsBack({ seat: "auto-mode-classifier", derived: classifierModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId, runId, onBrokenPairing: autoModeClassifierFallbackOf(am.classifierFallback) === "none" ? "refuse" : "fall_back" })).action === "fall_back") {
227
227
  classifierModel = model;
228
228
  }
229
229
  announceClassifierRoleDefaulted({ onNotice: deps.onNotice, seat: { ...classifierSeat, model: classifierModel }, ...(sessionId !== undefined ? { sessionId } : {}), ...(runId !== undefined ? { runId } : {}) });
@@ -86,7 +86,7 @@ export declare function resolveTaskLimits(limits: TaskLimits | undefined): TaskL
86
86
  */
87
87
  export declare function resolveAttachmentsConfig(attachments: TaskSpec["attachments"]): TaskSpec["attachments"];
88
88
  /**
89
- * R2 双形轴(追加令 2026-07-18): CC 2.1.212's fable-variant prompt gate (b9e —
89
+ * R2 双形轴(追加令 2026-07-18): the reference's fable-variant prompt gate (
90
90
  * `fable_5_mitigations` capability / claude-mythos-5), ORTHOGONAL to the simple/classic profile.
91
91
  * sema is BYOM, so the id may carry provider prefixes ("anthropic/claude-fable-5",
92
92
  * "openrouter/anthropic/claude-fable-5"): BOUNDARY-AWARE family match on the last path segment
@@ -99,8 +99,8 @@ export declare function isFableFamilyModelId(id: string): boolean;
99
99
  * The SINGLE decision point for the two prompt-shape axes.
100
100
  * Both were resolved in separate places with different mechanisms — `promptProfile` off a TaskSpec field,
101
101
  * `fableMitigations` off a raw model-id prefix test — so "which shape does this task speak" had no one
102
- * place to read. CC 2.1.220's counterpart is a model-registry `capabilities` array (one table drives
103
- * `lean_prompt` + `fable_5_mitigations` alike; anchors/2.1.220/CC-218-220-DIFF.md §2).
102
+ * place to read. The reference's counterpart is a model-registry `capabilities` array (one table drives
103
+ * `lean_prompt` + `fable_5_mitigations` alike).
104
104
  *
105
105
  * sema stays BYOM: we cannot key off a capability table for arbitrary model ids, so the RESOLUTION RULES
106
106
  * are unchanged — profile: spec > inherited internals > "simple"; mitigations: model family. This is a
@@ -213,6 +213,7 @@ export interface PrepareConfigDoorsResult {
213
213
  brainCallGuardrailMs: number | undefined;
214
214
  /** owned — the screened cross-boundary posture: the deps seat read ONCE, a bad value refused; absent stays `undefined` (undeclared is its own fact). */
215
215
  crossBoundaryPosture: CrossBoundaryPosture | undefined;
216
+ advisorTool: "disabled" | undefined;
216
217
  }
217
218
  /** The microCompact knob door (坏值响亮度默认律, the sibling knob doors' form:
218
219
  * interactionPosture / toolModelGate / staleToolResultOffload). Placement is load-bearing:
@@ -237,12 +238,13 @@ export declare const checkpointStoreSeat: (spec: {
237
238
  export declare function assertResumeConfigRecord(config: unknown): void;
238
239
  /** The spec the value doors read: a prepare's (its roster is faces) or a resume's re-supplied config (no objective, no session id). */
239
240
  type ValueDoorSpec = Omit<TaskSpec, "tools" | "objective" | "sessionId" | "userAttachments"> & Partial<Pick<TaskSpec, "objective" | "sessionId">>;
240
- type ConfigValueDoorsResult = Pick<PrepareConfigDoorsResult, "toolFaceLists" | "promptHost" | "promptBinding" | "lockedPreflight" | "microCompactKnob" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "usageWindows" | "brainCallGuardrailMs" | "crossBoundaryPosture"> & {
241
+ type ConfigValueDoorsResult = Pick<PrepareConfigDoorsResult, "toolFaceLists" | "promptHost" | "promptBinding" | "lockedPreflight" | "microCompactKnob" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "usageWindows" | "brainCallGuardrailMs" | "crossBoundaryPosture" | "advisorTool"> & {
241
242
  skillListingSeats: {
242
243
  fraction: unknown;
243
244
  maxDescChars: unknown;
244
245
  };
245
246
  skills: TaskSpec["skills"];
247
+ projectMemory: TaskSpec["projectMemory"];
246
248
  };
247
249
  /**
248
250
  * The phase's VALUE doors as ONE function with two callers — each judges a declared value against its own vocabulary, reading only the
@@ -18,6 +18,7 @@ import { assertRetentionCapability } from "../retention.js";
18
18
  import { resolveModel, resolveTaskModel, roleModelIfSet } from "../roles.js";
19
19
  import { resolveSkillListingBudget } from "../skill-listing-budget.js";
20
20
  import { describeRejectedValue } from "../tool-search-setting.js";
21
+ import { assertAdvisorModelShape } from "../advisor-verdict.js";
21
22
  import { applyToolModelGate, assertRestoreGatedToolsValue, modelIdTail } from "../tool-model-gate.js";
22
23
  import { resolveUsageWindows } from "../usage-window-store.js";
23
24
  import { deriveAskEffective, resolveAskSeat, resolveQuestionSeam, screenApprovalReach } from "../wiring-manifest.js";
@@ -155,7 +156,7 @@ function resolveClearOnRejection(bag) {
155
156
  }
156
157
  return declared ?? true;
157
158
  }
158
- function deploymentWord(raw, seat, words, absent, code, why) {
159
+ function closedWord(raw, seat, words, absent, code, why) {
159
160
  if (raw === undefined)
160
161
  return absent;
161
162
  const word = words.find((w) => w === raw);
@@ -163,7 +164,7 @@ function deploymentWord(raw, seat, words, absent, code, why) {
163
164
  return word;
164
165
  const got = typeof raw === "string" ? JSON.stringify(raw.length > 64 ? `${raw.slice(0, 64)}…` : raw) : raw === null ? "null" : Array.isArray(raw) ? "an array" : typeof raw;
165
166
  const spelled = words.map((w) => `"${w}"`);
166
- throw limitConfigError(code, `RunnerDeps.${seat} must be ${spelled.slice(0, -1).join(", ")} or ${spelled.at(-1)} when present (got ${got}) — ${why}`);
167
+ throw limitConfigError(code, `${seat} must be ${spelled.length > 1 ? `${spelled.slice(0, -1).join(", ")} or ` : ""}${spelled.at(-1)} when present (got ${got}) — ${why}`);
167
168
  }
168
169
  export const checkpointStoreSeat = (spec) => (spec.checkpointStore !== undefined ? "taskConfig" : "deps");
169
170
  export function assertResumeConfigRecord(config) {
@@ -231,10 +232,14 @@ export function configValueDoors(input, enter = ENTER_AS_IS) {
231
232
  enter("taskConfig", () => assertContainmentFaceValue(spec.writeFace, "write", "spec"));
232
233
  enter("deps", () => assertContainmentFaceValue(deps.writeFace, "write", "deps"));
233
234
  enter("taskConfig", () => assertAddOnlySeats(spec));
234
- const memoryDelegationEvidence = enter("deps", () => deploymentWord(deps.memoryDelegationEvidence, "memoryDelegationEvidence", ["static-face", "attested-only"], "static-face", "config.memory_delegation_evidence", "an unevaluable evidence standard is refused loudly, never folded to either standard."));
235
- const memoryProvenance = enter("deps", () => deploymentWord(deps.memoryProvenance, "memoryProvenance", ["off", "carry"], "carry", "config.memory_provenance", "an unevaluable provenance mode is refused loudly, never folded to either mode."));
236
- const memoryCapturePolicy = enter("deps", () => deploymentWord(deps.memoryCapturePolicy, "memoryCapturePolicy", ["open", "governed", "capture-required"], "open", "config.memory_capture_policy", "an unevaluable capture posture is refused loudly, never folded to any posture (the fault arms differ per posture, so a guess would pick a polarity nobody configured)."));
237
- const crossBoundaryPosture = enter("deps", () => deploymentWord(deps.crossBoundaryPosture, "crossBoundaryPosture", CROSS_BOUNDARY_POSTURES, undefined, "config.cross_boundary_posture", "an unevaluable posture is refused loudly, never folded to either word (an absent seat is undeclared, which is its own fact)."));
235
+ const memoryDelegationEvidence = enter("deps", () => closedWord(deps.memoryDelegationEvidence, "RunnerDeps.memoryDelegationEvidence", ["static-face", "attested-only"], "static-face", "config.memory_delegation_evidence", "an unevaluable evidence standard is refused loudly, never folded to either standard."));
236
+ const memoryProvenance = enter("deps", () => closedWord(deps.memoryProvenance, "RunnerDeps.memoryProvenance", ["off", "carry"], "carry", "config.memory_provenance", "an unevaluable provenance mode is refused loudly, never folded to either mode."));
237
+ const memoryCapturePolicy = enter("deps", () => closedWord(deps.memoryCapturePolicy, "RunnerDeps.memoryCapturePolicy", ["open", "governed", "capture-required"], "open", "config.memory_capture_policy", "an unevaluable capture posture is refused loudly, never folded to any posture (the fault arms differ per posture, so a guess would pick a polarity nobody configured)."));
238
+ const crossBoundaryPosture = enter("deps", () => closedWord(deps.crossBoundaryPosture, "RunnerDeps.crossBoundaryPosture", CROSS_BOUNDARY_POSTURES, undefined, "config.cross_boundary_posture", "an unevaluable posture is refused loudly, never folded to either word (an absent seat is undeclared, which is its own fact)."));
239
+ const advisorTool = enter("deps", () => closedWord(deps.advisorTool, "RunnerDeps.advisorTool", ["disabled"], undefined, "config.advisor_tool_invalid", "the switch has one word; anything else is refused, never read as either state."));
240
+ if (advisorTool === undefined)
241
+ enter("taskConfig", () => assertAdvisorModelShape(spec.advisorModel));
242
+ const projectMemory = enter("taskConfig", () => closedWord(spec.projectMemory, "TaskSpec.projectMemory", ["disabled"], undefined, "config.invalid_argument", "the switch has one word; omit the key to leave the deployment's project context in force."));
238
243
  enter("deps", () => assertAutoConsolidationWirable(deps));
239
244
  if (spec.resumeAtMode !== undefined)
240
245
  enter("taskConfig", () => {
@@ -317,7 +322,7 @@ export function configValueDoors(input, enter = ENTER_AS_IS) {
317
322
  }));
318
323
  if (taskStore !== undefined)
319
324
  enter("taskConfig", () => assertRetentionCapability({ ...retention, stores: [{ name: "checkpointStore", store: taskStore }] }));
320
- return { toolFaceLists, promptHost, promptBinding, lockedPreflight, skillListingSeats, skills, microCompactKnob, memoryDelegationEvidence, memoryProvenance, memoryCapturePolicy, usageWindows, brainCallGuardrailMs, crossBoundaryPosture };
325
+ return { toolFaceLists, promptHost, promptBinding, lockedPreflight, skillListingSeats, skills, projectMemory, microCompactKnob, memoryDelegationEvidence, memoryProvenance, memoryCapturePolicy, usageWindows, brainCallGuardrailMs, crossBoundaryPosture, advisorTool };
321
326
  }
322
327
  export function refuseResumeDoors(config, recordedGate, deps, sessions) {
323
328
  asResumeConfigRefusal("taskConfig", () => {
@@ -336,8 +341,9 @@ export function prepareConfigDoors(input) {
336
341
  const { deps, sessions, resume, internals } = input;
337
342
  assertToolBoundaryLegs(input.spec.tools);
338
343
  let spec = input.spec;
339
- const { toolFaceLists, promptHost, promptBinding, lockedPreflight, skillListingSeats, skills, microCompactKnob, memoryDelegationEvidence, memoryProvenance, memoryCapturePolicy, usageWindows, brainCallGuardrailMs, crossBoundaryPosture } = configValueDoors({ spec, deps, resumeLeg: resume !== undefined, sessions });
340
- spec = Object.create(Object.getPrototypeOf(spec), { ...Object.getOwnPropertyDescriptors(spec), skills: { value: skills, enumerable: skills !== undefined, writable: false, configurable: false } });
344
+ const { toolFaceLists, promptHost, promptBinding, lockedPreflight, skillListingSeats, skills, projectMemory, microCompactKnob, memoryDelegationEvidence, memoryProvenance, memoryCapturePolicy, usageWindows, brainCallGuardrailMs, crossBoundaryPosture, advisorTool } = configValueDoors({ spec, deps, resumeLeg: resume !== undefined, sessions });
345
+ const doorRead = (value) => ({ value, enumerable: value !== undefined, writable: false, configurable: false });
346
+ spec = Object.create(Object.getPrototypeOf(spec), { ...Object.getOwnPropertyDescriptors(spec), skills: doorRead(skills), projectMemory: doorRead(projectMemory) });
341
347
  const promptProfile = resolveModelPromptTraits({ id: "" }, spec, internals).promptProfile;
342
348
  const resolvedInteractionPosture = spec.interactionPosture ?? internals?.parentInteractionPosture ?? deps.interactionPosture;
343
349
  const askSeat = resolveAskSeat(spec, deps);
@@ -459,8 +465,8 @@ export function prepareConfigDoors(input) {
459
465
  discardedEnvRaw: gateDecision.discardedEnvRaw,
460
466
  });
461
467
  const thinking = spec.thinking ?? resolvedRole.thinking ?? model.defaultThinking;
462
- const compModel = spec.compactionModel
463
- ? resolveModel(spec.compactionModel, deps.models)
468
+ const compModel = spec.compactionModel !== undefined
469
+ ? resolveModel(spec.compactionModel, deps.models, "TaskSpec.compactionModel")
464
470
  : roleModelIfSet("summarize", spec, deps);
465
471
  return {
466
472
  spec,
@@ -481,7 +487,7 @@ export function prepareConfigDoors(input) {
481
487
  memoryDelegationEvidence,
482
488
  skillListingBudget,
483
489
  memoryProvenance,
484
- memoryCapturePolicy, crossBoundaryPosture,
490
+ memoryCapturePolicy, crossBoundaryPosture, advisorTool,
485
491
  usageWindows,
486
492
  brainCallGuardrailRef,
487
493
  brainCallGuardrailMs,
@@ -32,9 +32,9 @@ export interface PrepareDelegationSurfaceInput {
32
32
  * `handsReadOnly` is NOT read here (the hands mount decided the surface). Never mutated. */
33
33
  spec: Pick<TaskSpec, "tools" | "oneShot" | "retainBackgroundProcesses" | "excludeAllTools">;
34
34
  /** borrowed-readonly — the deployment seats the mounts read: `workflowRunStore` / `backgroundAgentStore` / `mailboxStore` (the
35
- * read/kill faces and the tier-3 revival seams), `rosterStore`, `peerLane`, `peerDirectory`, `onNotice`,
35
+ * read/kill faces and the tier-3 revival seams), `rosterStore`, `peerLane`, `peerDirectory`, `peerChannel`, `onNotice`,
36
36
  * `onBackgroundChildEvent`, `tracer`. */
37
- deps: Pick<RunnerDeps, "workflowRunStore" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "peerLane" | "peerDirectory" | "principalInboxConsumer" | "onNotice" | "onBackgroundChildEvent" | "tracer">;
37
+ deps: Pick<RunnerDeps, "workflowRunStore" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "peerLane" | "peerDirectory" | "peerChannel" | "principalInboxConsumer" | "onNotice" | "onBackgroundChildEvent" | "tracer">;
38
38
  /** borrowed-readonly — the trusted spawn-side channel: `parentNotify` (the delegated-child door), the uplink / sibling /
39
39
  * identity seats the SendMessage mount forwards, `onTaskNotification`, `onSubagentSpawn`. Never mutated. */
40
40
  internals: Pick<RunInternals, "parentNotify" | "parentPeerRef" | "uplinkSessionId" | "parentRetainLedger" | "explicitAgentName" | "parentTaskId" | "parentSessionId" | "peerSelfRef" | "peerInboundChainRef" | "onTaskNotification" | "onSubagentSpawn"> | undefined;
@@ -56,7 +56,7 @@ export function prepareDelegationSurface(input) {
56
56
  ...(deps.backgroundAgentStore !== undefined ? { agentStore: deps.backgroundAgentStore } : {}),
57
57
  ...(deps.mailboxStore !== undefined ? { mailbox: deps.mailboxStore } : {}),
58
58
  ...(reviveSpawn !== undefined ? { reviveSpawn } : {}),
59
- ...(peerLaneActive ? peerLaneSendMessageSeats({ peerDirectory: deps.peerDirectory, sessionId, scope: taskScope, ...(internals?.explicitAgentName !== undefined ? { name: internals.explicitAgentName } : {}), refs: peerLaneRefs, listingMounted: listAgentsMountable({ leaves, specTools: spec.tools ?? [] }) }) : {}),
59
+ ...(peerLaneActive ? peerLaneSendMessageSeats({ peerDirectory: deps.peerDirectory, ...(deps.peerChannel !== undefined ? { peerChannel: deps.peerChannel } : {}), sessionId, scope: taskScope, ...(internals?.explicitAgentName !== undefined ? { name: internals.explicitAgentName } : {}), refs: peerLaneRefs, listingMounted: listAgentsMountable({ leaves, specTools: spec.tools ?? [] }) }) : {}),
60
60
  onNotifyError: (f) => emitTrace(deps.tracer, () => ({ kind: "observer.notify_failed", version: 1, taskId: hostTaskId, site: f.site, message: f.error.message, ts: Date.now() })),
61
61
  onTranscriptIntegrityGap: (handle, scope) => deliverEngineNotice(deps.onNotice, {
62
62
  code: "delegation.transcript_integrity",
@@ -1,6 +1,8 @@
1
1
  import { NodeExecutionEnv } from "../../engine/execution-env/node-execution-env.js";
2
2
  import { isRemoteExecutionEnv } from "../remote-env.js";
3
- import { resolveTrackKey } from "../file-history-store.js";
3
+ import { FILE_HISTORY_ERROR_CODES, FileHistoryStoreError, resolveTrackKey } from "../file-history-store.js";
4
+ import { readMember, thrownText } from "../thrown-value.js";
5
+ import { isGovernanceRetryClass } from "../governance-codes.js";
4
6
  export async function prepareFileHistory(input) {
5
7
  const { deps, spec, request, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session, abortController } = input;
6
8
  const rewindNotes = [];
@@ -45,12 +47,8 @@ export async function prepareFileHistory(input) {
45
47
  }
46
48
  let restoredFilePaths = [];
47
49
  if (rewindTarget !== undefined && fileHistoryStore !== undefined && handsEnabled) {
48
- const historyStore = fileHistoryStore;
49
- if (rewindBefore && !(await historyStore.canRestore(sessionId, rewindTarget)))
50
- throw beforeWithoutBoundaryRefusal(rewindTarget, sessionId);
51
- const restoreRoot = historyRoot;
52
50
  const restoreSignal = spec.signal ? AbortSignal.any([abortController.signal, spec.signal]) : abortController.signal;
53
- const restored = await historyStore.restore(sessionId, rewindTarget, executionEnv, restoreRoot, restoreSignal);
51
+ const restored = await fileHistoryStore.restore(sessionId, rewindTarget, executionEnv, historyRoot, restoreSignal);
54
52
  const ledgerLine = (r) => `applied ${r.filesChanged.length}, identical ${r.identicalSkipped.length}, refused ${r.refused.length}${r.refused.length > 0 ? ` (${r.refused.map((f) => `${f.path}: ${f.reason}`).join("; ")})` : ""}, failed ${r.failed.length}${r.failed.length > 0 ? ` (${r.failed.map((f) => `${f.path}: ${f.reason}`).join("; ")})` : ""}`;
55
53
  if (restored.outcome === "failed") {
56
54
  if (restored.error?.code === "not_found") {
@@ -62,6 +60,8 @@ export async function prepareFileHistory(input) {
62
60
  }
63
61
  const e = new Error(`rewind-files restore failed (${restored.error?.code ?? "restore_failed"}): ${restored.error?.message ?? "unknown"} — ledger: ${ledgerLine(restored)}`);
64
62
  e.code = "rewind.restore_failed";
63
+ if (restored.error !== undefined)
64
+ e.detail = { code: restored.error.code, ...(isGovernanceRetryClass(restored.error.permanence) ? { permanence: restored.error.permanence } : {}) };
65
65
  throw e;
66
66
  }
67
67
  if (restored.outcome === "partial") {
@@ -77,22 +77,22 @@ export async function prepareFileHistory(input) {
77
77
  throw e;
78
78
  }
79
79
  }
80
- restoredFilePaths = restoredAbsPathsOf(restored, restoreRoot);
80
+ restoredFilePaths = restoredAbsPathsOf(restored, historyRoot);
81
81
  }
82
82
  const trackFileEdit = fileHistoryEnabled
83
83
  ? async (req) => {
84
- const r = await fileHistoryStore.trackEdit(historyScope, req.key, executionEnv, historyRoot, req.signal);
84
+ const r = await answerOf(() => fileHistoryStore.trackEdit(historyScope, req.key, executionEnv, historyRoot, req.signal), "track_failed");
85
85
  if (r.ok) {
86
86
  if (!r.minted)
87
87
  return { ok: true };
88
88
  return {
89
89
  ok: true,
90
90
  annul: async (proof) => {
91
- const a = await fileHistoryStore.annulTrack(historyScope, req.key, historyRoot, proof === "verify" ? { env: executionEnv, ...(req.signal !== undefined ? { signal: req.signal } : {}) } : undefined);
91
+ const a = await answerOf(() => fileHistoryStore.annulTrack(historyScope, req.key, historyRoot, proof === "verify" ? { env: executionEnv, ...(req.signal !== undefined ? { signal: req.signal } : {}) } : undefined), "track_failed");
92
92
  if (a.ok)
93
93
  return;
94
94
  try {
95
- deps.onError?.(new Error(`file-history could not retract the first-touch record for "${req.key}" after its edit failed to land (${a.error.code}: ${a.error.message}) — the path stays tracked, so a rewind to a boundary below it may converge bytes this engine never wrote`), { phase: "rewind", sessionId });
95
+ deps.onError?.(new FileHistoryStoreError(a.error, `file-history could not retract the first-touch record for "${req.key}" after its edit failed to land (${a.error.code}: ${a.error.message}) — the path stays tracked, so a rewind to a boundary below it may converge bytes this engine never wrote`, "thrown" in a ? a.thrown : undefined), { phase: "rewind", sessionId });
96
96
  }
97
97
  catch {
98
98
  }
@@ -101,16 +101,14 @@ export async function prepareFileHistory(input) {
101
101
  }
102
102
  if (onTrackFailure === "proceed-unprotected") {
103
103
  try {
104
- deps.onError?.(new Error(`file-history first-touch backup for "${req.key}" failed (${r.error.code}: ${r.error.message}) — proceeding UNPROTECTED per RunnerDeps.onTrackFailure: the pristine promise for this path is void, and only in this process's memory (no durable trace exists, so after a process restart the next edit can still mint already-modified bytes as pristine v1)`), { phase: "rewind", sessionId });
104
+ deps.onError?.(new FileHistoryStoreError(r.error, `file-history first-touch backup for "${req.key}" failed (${r.error.code}: ${r.error.message}) — proceeding UNPROTECTED per RunnerDeps.onTrackFailure: the pristine promise for this path is void, and only in this process's memory (no durable trace exists, so after a process restart the next edit can still mint already-modified bytes as pristine v1)`, "thrown" in r ? r.thrown : undefined), { phase: "rewind", sessionId });
105
105
  }
106
106
  catch {
107
107
  }
108
108
  return { ok: true };
109
109
  }
110
- return {
111
- ok: false,
112
- refusal: `Error (${req.tool}): the edit was refused because its first-touch file-history backup could not be persisted (${r.error.code}: ${r.error.message}). Proceeding would leave "${req.path}" with no durable pristine record — after the history store recovers, a retried edit would mint already-modified bytes as the pristine baseline. Retry when the file-history store is healthy.`,
113
- };
110
+ const lead = r.error.permanence === "terminal" ? "The history store reports this failure as permanent: do not retry this edit until the store is fixed." : "Retry when the file-history store is healthy.";
111
+ return { ok: false, refusal: `Error (${req.tool}): the edit was refused because its first-touch file-history backup could not be persisted (${r.error.code}). ${lead} Proceeding would leave the file with no durable pristine record. ${r.error.message}` };
114
112
  }
115
113
  : undefined;
116
114
  const fileHistoryBoundary = fileHistoryEnabled && historyScope === sessionId
@@ -147,6 +145,21 @@ function toldAlready(sink, arm) {
147
145
  return false;
148
146
  }
149
147
  const FILE_HISTORY_CARRY_MEMO = new WeakMap();
148
+ function answerOf(call, code) {
149
+ const unanswered = (message, thrown) => ({ ok: false, error: { code, message }, ...(thrown === undefined ? {} : { thrown }) });
150
+ return Promise.resolve().then(call).then((r) => {
151
+ const ok = readMember(r, "ok");
152
+ if (ok === true)
153
+ return { ok: true, minted: readMember(r, "minted") === true };
154
+ const error = readMember(r, "error"), stated = readMember(error, "code"), message = readMember(error, "message"), permanence = readMember(error, "permanence");
155
+ if (ok !== false || typeof stated !== "string")
156
+ return unanswered("the history store answered something that is not a result");
157
+ const text = typeof message === "string" ? message : "(the history store gave no message)", known = FILE_HISTORY_ERROR_CODES.find((c) => c === stated);
158
+ if (known === undefined)
159
+ return unanswered(`the history store answered a code outside the closed set (${JSON.stringify(stated)}): ${text}`);
160
+ return { ok: false, error: { code: known, message: text, ...(isGovernanceRetryClass(permanence) ? { permanence } : {}) } };
161
+ }, (value) => unanswered(`the history store threw: ${thrownText(value)}`, { value }));
162
+ }
150
163
  async function adoptForkedFileHistory(store, session, sessionId, onError) {
151
164
  const memo = FILE_HISTORY_CARRY_MEMO.get(store) ?? { settled: new Set(), disclosed: new Set(), inFlight: new Map() };
152
165
  FILE_HISTORY_CARRY_MEMO.set(store, memo);
@@ -156,6 +169,7 @@ async function adoptForkedFileHistory(store, session, sessionId, onError) {
156
169
  memo.disclosed.add(sessionId);
157
170
  onError?.(err, { phase: "rewind", sessionId });
158
171
  };
172
+ const threw = (err) => new FileHistoryStoreError({ code: "adopt_failed" }, `file-history fork carry could not run: ${thrownText(err)} — the parent's history was not carried into this session (the run itself proceeds)`, { value: err });
159
173
  try {
160
174
  if (memo.settled.has(sessionId))
161
175
  return;
@@ -167,13 +181,13 @@ async function adoptForkedFileHistory(store, session, sessionId, onError) {
167
181
  return await shared;
168
182
  if (memo.settled.has(sessionId))
169
183
  return;
170
- const attempt = store.adoptScope(forkedFrom, sessionId).then((carried) => {
184
+ const attempt = answerOf(() => store.adoptScope(forkedFrom, sessionId), "adopt_failed").then((carried) => {
171
185
  if (carried.ok || carried.error.code === "conflict") {
172
186
  memo.settled.add(sessionId);
173
187
  return;
174
188
  }
175
- discloseOnce(new Error(`file-history fork carry from session "${forkedFrom}" failed (${carried.error.code}): ${carried.error.message} — this forked session starts with an EMPTY rewind history, so boundaries recorded before the fork are not restorable from it (the run itself proceeds; the carry is retried on this session's next turn while its scope is still empty)`));
176
- }, (err) => discloseOnce(err));
189
+ discloseOnce(new FileHistoryStoreError(carried.error, `file-history fork carry from session "${forkedFrom}" failed (${carried.error.code}): ${carried.error.message} — the parent's history was not carried, so boundaries recorded before the fork are not restorable from this session (the run itself proceeds; the carry is retried on this session's next turn)`, "thrown" in carried ? carried.thrown : undefined));
190
+ });
177
191
  memo.inFlight.set(sessionId, attempt);
178
192
  try {
179
193
  await attempt;
@@ -184,7 +198,7 @@ async function adoptForkedFileHistory(store, session, sessionId, onError) {
184
198
  }
185
199
  catch (err) {
186
200
  try {
187
- discloseOnce(err);
201
+ discloseOnce(threw(err));
188
202
  }
189
203
  catch {
190
204
  }
@@ -206,30 +220,16 @@ function createFileHistoryBoundarySeat(opts) {
206
220
  resolve({ ok: false });
207
221
  }, FILE_HISTORY_BOUNDARY_TIMEOUT_MS);
208
222
  });
209
- let work;
210
- try {
211
- work = opts.store.snapshot(opts.sessionId, entryId, opts.env, opts.root, ac.signal);
212
- }
213
- catch (err) {
214
- work = Promise.resolve({ ok: false, error: { code: "snapshot_failed", message: `history store threw synchronously: ${err.message}` } });
215
- }
216
- work.catch(() => { });
223
+ const work = answerOf(() => opts.store.snapshot(opts.sessionId, entryId, opts.env, opts.root, ac.signal), "snapshot_failed");
224
+ const disclose = (failure, what, thrown) => new FileHistoryStoreError(failure, `file-history ${what} — this turn has no boundary and cannot be rewound to (the turn itself proceeds)`, thrown);
217
225
  inFlight = Promise.race([
218
- work.then((r) => (r.ok ? undefined : `boundary capture failed (${r.error.code}): ${r.error.message}`)),
219
- timeout.then(() => `boundary capture timed out after ${FILE_HISTORY_BOUNDARY_TIMEOUT_MS / 1000}s (fenced — the attempt can never publish)`),
226
+ work.then((r) => (r.ok ? undefined : disclose(r.error, `boundary capture failed (${r.error.code}): ${r.error.message}`, "thrown" in r ? r.thrown : undefined))),
227
+ timeout.then(() => disclose({ code: "aborted" }, `boundary capture timed out after ${FILE_HISTORY_BOUNDARY_TIMEOUT_MS / 1000}s (fenced — the attempt can never publish)`)),
220
228
  ])
221
229
  .then((failure) => {
222
- if (failure !== undefined) {
223
- try {
224
- opts.onError?.(new Error(`file-history ${failure} — this turn has no boundary and cannot be rewound to (the turn itself proceeds)`), { phase: "rewind", sessionId: opts.sessionId });
225
- }
226
- catch {
227
- }
228
- }
229
- })
230
- .catch((err) => {
231
230
  try {
232
- opts.onError?.(err, { phase: "rewind", sessionId: opts.sessionId });
231
+ if (failure !== undefined)
232
+ opts.onError?.(failure, { phase: "rewind", sessionId: opts.sessionId });
233
233
  }
234
234
  catch {
235
235
  }
@@ -34,7 +34,7 @@ import type { InheritedToolCheck, LegModBus } from "../mods/stations.js";
34
34
  import { type HookEnvCapabilities, type HookInvocationIdentity } from "../hooks.js";
35
35
  import type { ToolPolicy } from "../tool-policy.js";
36
36
  import { type GateOutcome } from "../gate-outcome.js";
37
- import type { RunnerDeps, TaskSpec, ToolEffect } from "../types.js";
37
+ import type { RunnerDeps, TaskSpec } from "../types.js";
38
38
  import { type WiringManifest } from "../wiring-manifest.js";
39
39
  import type { WriteProtectionCheck } from "../write-protect.js";
40
40
  import type { ShellReadCheck } from "../../tools/fs/shell-read-check.js";
@@ -82,9 +82,6 @@ export interface PrepareGateStationsInput {
82
82
  tools: readonly AgentTool[];
83
83
  /** borrowed-readonly — the leg's delta seat: its current roster is the face source for every gated call. */
84
84
  toolRosterDeltas: ToolRosterDeltaSeat;
85
- /** borrowed-mutable — the effect collection. Writer here: the final-roster sync fills MISSING entries from each
86
- * first-party tool's declared effect (never overrides a scanned one); the plan-mode deny reads it per call. */
87
- toolEffects: Map<string, ToolEffect>;
88
85
  /** borrowed-readonly — the deployment seats these stations read, as a Pick over the SAME `deps` object (receiver
89
86
  * preserved for `deps.onError?.()`): the write-protection table and its data root, the tracer, the error face, and
90
87
  * the notice sink (the gate's unresolvable-ask exit delivers `delegation.ask_unresolvable` through it). */
@@ -10,7 +10,7 @@ import { askUnresolvableNotice } from "../ask-unresolvable-notice.js";
10
10
  import { approvalRouteOf } from "../wiring-manifest.js";
11
11
  import { classifierUnavailableSeat } from "./classifier-ladder.js";
12
12
  import { PATH_CONFINABLE_WRITE_TOOLS } from "./session-rule-policy.js";
13
- import { callFaceSeat, rosterToolName, survivorsByName, toolCallFaceOf } from "../tool-roster.js";
13
+ import { callFaceSeat, rosterToolName, toolCallFaceOf } from "../tool-roster.js";
14
14
  import { heldBy, heldValues, seatOf, wireOf } from "../tool-name-readings.js";
15
15
  import { createApprovedCallScreen, createToolResultStation } from "./call-hook-stations.js";
16
16
  const PEER_MESSAGE_NAMES = new Set([SEND_MESSAGE_TOOL_NAME]);
@@ -46,7 +46,7 @@ export function maybeHumanRejectionHalt(input) {
46
46
  };
47
47
  }
48
48
  export function prepareGateStations(input) {
49
- const { askLane, parkAsk, tools, toolRosterDeltas, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, toolOccurrences, batchHaltRef, blockedTracked, hookIdentity, reminderMark, hostTaskId, sessionId, handsCwdRef, stampCallTarget, hookEnvFace, writeProtectionCheck, shellReadCheck, crossBoundaryCheck, readFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider, autoModeDenialTracking, askRoute, permissionMode, toolMarkSources, a2aIsolatePeers, ancestorArbitrations, runId, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, frameSettlement, seatInputsFor, modBus, inheritedToolChecks } = input;
49
+ const { askLane, parkAsk, tools, toolRosterDeltas, deps, toolCallGateArmedRef, effectivePolicy, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, toolOccurrences, batchHaltRef, blockedTracked, hookIdentity, reminderMark, hostTaskId, sessionId, handsCwdRef, stampCallTarget, hookEnvFace, writeProtectionCheck, shellReadCheck, crossBoundaryCheck, readFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider, autoModeDenialTracking, askRoute, permissionMode, toolMarkSources, a2aIsolatePeers, ancestorArbitrations, runId, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, frameSettlement, seatInputsFor, modBus, inheritedToolChecks } = input;
50
50
  const releasesAnnounced = new Map();
51
51
  const onModeReleased = (info) => {
52
52
  const table = info.readUnestablished === true ? input.readDenyInForce(info.toolCallId) : undefined;
@@ -72,11 +72,6 @@ export function prepareGateStations(input) {
72
72
  if (askLane !== undefined && parkAsk !== undefined) {
73
73
  const { adjudicate, resolveAskBound, notifyPermissionDenied, notifyHookError } = askLane;
74
74
  const { resolveContentAsk, suspendAsk } = parkAsk;
75
- for (const t of survivorsByName(tools).values()) {
76
- const eff = t.effect;
77
- if (eff !== undefined && !toolEffects.has(t.name))
78
- toolEffects.set(t.name, eff);
79
- }
80
75
  const writeProtectionArmed = writeProtectionCheck !== undefined && tools.some((t) => PATH_CONFINABLE_WRITE_TOOLS.has(t.name));
81
76
  toolCallGateArmedRef.armed =
82
77
  effectivePolicy !== undefined ||
@@ -43,7 +43,7 @@ import { type ChildClampSource } from "../child-clamp-seats.js";
43
43
  import type { LockedPreflight } from "../locked-config.js";
44
44
  import type { OwnOrgAdmissionVerdict } from "../memory-admission.js";
45
45
  import type { DelegationContentSafety } from "../memory-engine/delegation-provenance.js";
46
- import { type SessionPermissionRules } from "../session-policy-store.js";
46
+ import type { SessionPermissionRules } from "../session-policy-store.js";
47
47
  import type { SessionStore } from "../session.js";
48
48
  import { type OnAsk, type ToolPolicy } from "../tool-policy.js";
49
49
  import type { PathRuleBases } from "../permission-rule-model.js";
@@ -228,9 +228,10 @@ export interface PrepareInheritedGateResult {
228
228
  orgGovernedProvenance: boolean;
229
229
  /** owned — the operator's shell floor in force (the spec's, or the chain's); undefined = no floor. */
230
230
  effectiveShellGate: ShellGateDoctrine | undefined;
231
- /** borrowed-mutable — THIS task's own session-rule snapshot for its children's chain. Writers (R-3): the policy-chain
232
- * station's session-policy read, once per leg, when a store is wired and the task carries its own sessionId. Read by
233
- * `inheritedGateForChildren` at spawn time. */
231
+ /** borrowed-mutable — THIS task's own session-rule snapshot for its children's chain: present iff the leg enforces its
232
+ * own session-rule layer (a store is wired and the task carries its own sessionId), from prepare on. Writer (R-3): the
233
+ * policy-chain station — the layer's seed (the empty rev-0 row when the session has none), then each row it comes to
234
+ * enforce. Read by `inheritedGateForChildren` at spawn time. */
234
235
  ownSessionRulesRef: {
235
236
  current?: {
236
237
  sessionId: string;
@@ -4,7 +4,7 @@ import { parentSpecSeatOf } from "../parent-spec-seat.js";
4
4
  import { createPreToolUseConstraintPolicy } from "../hooks.js";
5
5
  import { chainJudges, sameInstallation } from "../mods/stations.js";
6
6
  import { childClampSeats, clampSourceOf } from "../child-clamp-seats.js";
7
- import { continuesLineage } from "../session-policy-store.js";
7
+ import { rowFollowsFloor } from "./session-rule-policy.js";
8
8
  import { StubExecutionEnv } from "../stub-env.js";
9
9
  import { durableMandateSourceOf } from "../tool-policy.js";
10
10
  import { chainAnchorRecords } from "./child-tree.js";
@@ -30,8 +30,8 @@ export function prepareInheritedGate(input) {
30
30
  return [...seedRules];
31
31
  const merged = seedRules.map((s) => {
32
32
  const live = liveRules.find((l) => l.sessionId === s.sessionId && l.principal === s.principal);
33
- const sameLineage = live === undefined || continuesLineage(live, s);
34
- return live !== undefined && sameLineage && live.rev >= s.rev ? live : s;
33
+ const follows = live !== undefined && rowFollowsFloor(live, s);
34
+ return follows && live.rev >= s.rev ? live : s;
35
35
  });
36
36
  const extras = liveRules.filter((l) => !seedRules.some((s) => s.sessionId === l.sessionId && s.principal === l.principal));
37
37
  return [...merged, ...extras];
@@ -5,13 +5,13 @@ import { Value } from "typebox/value";
5
5
  import { classifyQuestionOutcome, validateAskQuestions } from "../ask-question.js";
6
6
  import { hasBackgroundShell, sweepBackgroundShells, sweepRunBoundaryBackgroundShells } from "../background-shell.js";
7
7
  import { boundInputHashOf, exactBoundInputHashOf } from "../canonical-json.js";
8
- import { unencodableIn } from "../checkpoint-requirements.js";
9
- import { buildRiskDescriptor, debitLedger, encodeAtFidelity, mintCheckpointId, mintCheckpointToken, resolveDeclaredFidelity, samePlainValue, } from "../checkpoint-store.js";
8
+ import { buildRiskDescriptor, debitLedger, encodeAtFidelity, mintCheckpointId, mintCheckpointToken, resolveDeclaredFidelity, } from "../checkpoint-store.js";
10
9
  import { pauseOf } from "../pause-registry.js";
10
+ import { samePlainValue } from "../same-plain-value.js";
11
11
  import { askCarryRowMembers } from "../hooks.js";
12
12
  import { askMandateMember, ownedClearanceFacts } from "../ask-origin.js";
13
13
  import { defaultTaskRegistry } from "../task-registry.js";
14
- import { advertisedWritableRootsSeat, exemptRootsSeat, isLiveApproverSeat, licenseCovers, carriesBidiControls, describeThrown, ownArgs, refuseOutOfContractDecision, tryCloneArgs } from "../tool-policy.js";
14
+ import { advertisedWritableRootsSeat, bindableArgsOf, exemptRootsSeat, isLiveApproverSeat, licenseCovers, carriesBidiControls, describeThrown, ownArgs, refuseOutOfContractDecision, tryCloneArgs } from "../tool-policy.js";
15
15
  import { InMemoryToolResultStore, ScopedToolResultStore, isVolatileOffloadStore } from "../tool-result-store.js";
16
16
  import { raceAbort, raceSettlementAgainstSignal } from "./abort-race.js";
17
17
  import { CONTENT_ASK_BINDING_CAP } from "./content-ask-bindings.js";
@@ -146,12 +146,12 @@ export function prepareParkAsk(input) {
146
146
  `a durable approval row must hold an inert snapshot of exactly what a human approves and a resume executes`, { cause: captured.cause });
147
147
  }
148
148
  const parkedArgs = captured.value;
149
- const unencodable = unencodableIn(parkedArgs, "pendingAction.args");
150
- if (unencodable !== undefined)
151
- throw new ParkRefusal(`the arguments of "${req.toolName}" cannot be bound into the approval row's digest (${unencodable.kind} at ${unencodable.path}) — a durable approval row must hold an inert snapshot of exactly what a human approves and a resume executes`);
149
+ const bindable = bindableArgsOf(req.toolName, parkedArgs);
150
+ if (!bindable.ok)
151
+ throw new ParkRefusal(bindable.refusal);
152
152
  const parkedHash = exactBoundInputHashOf(parkedArgs);
153
153
  if (parkedHash === undefined)
154
- throw new ParkRefusal(`the arguments of "${req.toolName}" hold a value no exact digest binds — no approval row can be bound to them`);
154
+ throw new ParkRefusal(`the canonical form of the arguments of "${req.toolName}" cannot be built — no approval row can be bound to them`);
155
155
  const projectionMovedArgs = backendFidelity !== "structured-clone" && !samePlainValue(parked.value, parkedArgs);
156
156
  if (projectionMovedArgs && basePolicyForResumeEdit === undefined) {
157
157
  throw new ParkRefusal(`the arguments of "${req.toolName}" change shape when stored by this checkpoint backend, and no policy is wired to re-adjudicate the stored shape ` +
@@ -177,7 +177,7 @@ export interface PreparePolicyChainInput {
177
177
  /** borrowed-readonly — the injectable wall-clock (the inherited arms' human-wait timing). */
178
178
  now: () => number;
179
179
  /** borrowed-mutable — the own session-rules snapshot seat (the inherited-gate phase mints it; `inheritedGateForChildren`
180
- * reads it late). Writer: THIS phase, once, when the store returns this task's own rules. */
180
+ * reads it late). Writer: THIS phase — the own layer's seed at prepare, then each row the layer comes to enforce. */
181
181
  ownSessionRulesRef: {
182
182
  current?: {
183
183
  sessionId: string;
@@ -55,7 +55,7 @@ export async function preparePolicyChain(input) {
55
55
  for (const g of nameGroups) {
56
56
  for (const [kind, list] of [["deny", g.deny], ["ask", g.ask], ["allow", g.allow]]) {
57
57
  for (const n of list ?? []) {
58
- const verdict = judgeRuleToolName(n, known);
58
+ const verdict = judgeRuleToolName(n, known, kind);
59
59
  const twin = verdict.kind === "current" && !inherited ? nearMissSpellingOf(n, rootFacing) : undefined;
60
60
  const stale = verdict.kind !== "current" ? verdict : twin !== undefined ? { kind: "case_twin", twin, carrier: known.has(twin) || callerNames.has(twin) ? "run" : pool.names.has(twin) ? "pool" : "catalog" } : undefined;
61
61
  if (stale !== undefined) {
@@ -85,7 +85,7 @@ export async function preparePolicyChain(input) {
85
85
  }
86
86
  if (known.has(n))
87
87
  continue;
88
- if (isNamespacedCoveringRuleName(n) && [...known].some((k) => namespacedRuleNameCovers(n, k)))
88
+ if (isNamespacedCoveringRuleName(n, kind) && [...known].some((k) => namespacedRuleNameCovers(n, k)))
89
89
  continue;
90
90
  unmatched.add(`"${n}" (${kind})`);
91
91
  }
@@ -138,8 +138,7 @@ export async function preparePolicyChain(input) {
138
138
  };
139
139
  };
140
140
  sessionRulePolicy = createSessionRulePolicy({ seed, read: createLiveSessionRules(store, { ...sessionRuleKey, seed }, { onUnreadable: announceSessionRulesUnreadable, onEnforced: publishOwnRules }) }, { env: executionEnv, rootPath: taskRootFinal, toolEffects, anchors: pathRuleAnchors.leg, onEarlierGrammar: announceEarlierGrammar(sessionRuleKey.sessionId) });
141
- if (rules)
142
- publishOwnRules(rules);
141
+ publishOwnRules(seed);
143
142
  }
144
143
  const ancestorRulePolicies = [];
145
144
  for (const [position, snap] of (inheritedAncestorRules ?? []).entries()) {
@@ -153,12 +152,7 @@ export async function preparePolicyChain(input) {
153
152
  rules: row,
154
153
  });
155
154
  };
156
- ancestorRulePolicies.push(createSessionRulePolicy({
157
- seed,
158
- ...(deps.sessionPolicyStore
159
- ? { read: createLiveSessionRules(deps.sessionPolicyStore, { sessionId: snap.sessionId, ...(snap.principal !== undefined ? { principal: snap.principal } : {}), seed }, { onUnreadable: announceSessionRulesUnreadable, onEnforced: publishAncestorRules }) }
160
- : {}),
161
- }, { env: executionEnv, rootPath: taskRootFinal, toolEffects, anchors: pathRuleAnchors.leg, onEarlierGrammar: announceEarlierGrammar(snap.sessionId) }));
155
+ ancestorRulePolicies.push(createSessionRulePolicy({ seed, read: createLiveSessionRules(deps.sessionPolicyStore, { sessionId: snap.sessionId, ...(snap.principal !== undefined ? { principal: snap.principal } : {}), seed }, { onUnreadable: announceSessionRulesUnreadable, onEnforced: publishAncestorRules }) }, { env: executionEnv, rootPath: taskRootFinal, toolEffects, anchors: pathRuleAnchors.leg, onEarlierGrammar: announceEarlierGrammar(snap.sessionId) }));
162
156
  }
163
157
  const frozenConstraintLayers = (seedInheritedGate?.constraintChain ?? [])
164
158
  .filter((e) => !("opaque" in e))