@sema-agent/core 7.52.0 → 7.54.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 (357) hide show
  1. package/CHANGELOG.md +470 -0
  2. package/LICENSE +3 -1
  3. package/README.md +3 -1
  4. package/dist/agents/cross-session-envelope.d.ts +8 -0
  5. package/dist/agents/cross-session-envelope.js +6 -0
  6. package/dist/agents/cross-session-judge.d.ts +21 -1
  7. package/dist/agents/cross-session-judge.js +8 -0
  8. package/dist/agents/cross-session-ref.d.ts +5 -0
  9. package/dist/agents/cross-session-ref.js +1 -0
  10. package/dist/agents/org-delivery-gate.d.ts +122 -0
  11. package/dist/agents/org-delivery-gate.js +69 -0
  12. package/dist/agents/peer-held-queue.d.ts +9 -4
  13. package/dist/agents/peer-held-queue.js +6 -5
  14. package/dist/agents/peer-session-drain.d.ts +35 -6
  15. package/dist/agents/peer-session-drain.js +271 -182
  16. package/dist/agents/read-inbox-tool.d.ts +7 -0
  17. package/dist/agents/read-inbox-tool.js +5 -1
  18. package/dist/agents/send-message-tool.js +3 -4
  19. package/dist/agents/subagent.d.ts +6 -5
  20. package/dist/agents/subagent.js +117 -83
  21. package/dist/agents/tool-filter.d.ts +25 -4
  22. package/dist/agents/tool-filter.js +13 -3
  23. package/dist/brain/anthropic.d.ts +6 -1
  24. package/dist/brain/anthropic.js +4 -4
  25. package/dist/brain/model-presets.js +2 -1
  26. package/dist/brain/route-adjudicator.d.ts +6 -0
  27. package/dist/brain/routing.d.ts +24 -1
  28. package/dist/brain/routing.js +54 -19
  29. package/dist/brain/timeout.js +5 -4
  30. package/dist/core/a2a.d.ts +5 -2
  31. package/dist/core/a2a.js +33 -14
  32. package/dist/core/allow-entry.d.ts +3 -1
  33. package/dist/core/allow-entry.js +3 -2
  34. package/dist/core/approval-object.d.ts +87 -0
  35. package/dist/core/approval-object.js +85 -0
  36. package/dist/core/arg-summary.d.ts +3 -2
  37. package/dist/core/arg-summary.js +17 -11
  38. package/dist/core/ask-origin.d.ts +43 -27
  39. package/dist/core/ask-origin.js +20 -11
  40. package/dist/core/ask-question.d.ts +0 -1
  41. package/dist/core/ask-question.js +4 -67
  42. package/dist/core/ask-unresolvable-notice.d.ts +3 -2
  43. package/dist/core/auto-compaction.d.ts +106 -50
  44. package/dist/core/auto-compaction.js +69 -53
  45. package/dist/core/auto-mode-prompt.d.ts +4 -2
  46. package/dist/core/auto-mode-prompt.js +4 -3
  47. package/dist/core/canonical-json.d.ts +69 -0
  48. package/dist/core/canonical-json.js +130 -8
  49. package/dist/core/checkpoint-requirements.d.ts +13 -7
  50. package/dist/core/checkpoint-requirements.js +4 -1
  51. package/dist/core/checkpoint-store.d.ts +60 -36
  52. package/dist/core/checkpoint-store.js +7 -6
  53. package/dist/core/child-clamp-seats.d.ts +45 -6
  54. package/dist/core/child-clamp-seats.js +56 -4
  55. package/dist/core/compliance.js +3 -1
  56. package/dist/core/consolidate-scope.d.ts +1 -1
  57. package/dist/core/cross-boundary-taint.d.ts +213 -0
  58. package/dist/core/cross-boundary-taint.js +196 -0
  59. package/dist/core/decision-receipt.d.ts +44 -1
  60. package/dist/core/decision-receipt.js +16 -0
  61. package/dist/core/effective-path-target.d.ts +28 -6
  62. package/dist/core/effective-path-target.js +28 -2
  63. package/dist/core/engine-notice.d.ts +47 -4
  64. package/dist/core/engine-notice.js +17 -1
  65. package/dist/core/engine-storage-backend.d.ts +73 -0
  66. package/dist/core/engine-storage-backend.js +1 -0
  67. package/dist/core/file-history-store.d.ts +6 -2
  68. package/dist/core/file-history-store.js +1 -0
  69. package/dist/core/gate-fold.js +13 -4
  70. package/dist/core/gate-lanes.js +41 -34
  71. package/dist/core/gate-outcome.d.ts +18 -9
  72. package/dist/core/governance-codes.d.ts +9 -2
  73. package/dist/core/governance-codes.js +9 -0
  74. package/dist/core/hands-band-screen.d.ts +7 -0
  75. package/dist/core/hands-band-screen.js +32 -0
  76. package/dist/core/hooks.d.ts +21 -19
  77. package/dist/core/hooks.js +6 -5
  78. package/dist/core/locked-config.d.ts +110 -31
  79. package/dist/core/locked-config.js +155 -42
  80. package/dist/core/lsp.d.ts +1 -1
  81. package/dist/core/mcp-probe.js +1 -1
  82. package/dist/core/mcp-server-spec.d.ts +152 -17
  83. package/dist/core/mcp-server-spec.js +223 -40
  84. package/dist/core/mcp.d.ts +21 -14
  85. package/dist/core/mcp.js +59 -54
  86. package/dist/core/memory-engine/engine.d.ts +14 -19
  87. package/dist/core/memory-engine/engine.js +9 -6
  88. package/dist/core/memory-engine/export-bundle.d.ts +1 -1
  89. package/dist/core/memory-engine/export-bundle.js +1 -1
  90. package/dist/core/memory-engine/file-backend.d.ts +2 -6
  91. package/dist/core/memory-engine/file-backend.js +1 -12
  92. package/dist/core/memory.d.ts +3 -3
  93. package/dist/core/mode-policy.d.ts +16 -26
  94. package/dist/core/mode-policy.js +5 -18
  95. package/dist/core/mods/kernel/dispatch.js +13 -15
  96. package/dist/core/mods/kernel/events.d.ts +9 -6
  97. package/dist/core/mods/kernel/events.js +2 -2
  98. package/dist/core/mods/kernel/receive.d.ts +41 -11
  99. package/dist/core/mods/kernel/receive.js +124 -54
  100. package/dist/core/mods/kernel/site-rules.d.ts +80 -15
  101. package/dist/core/mods/kernel/site-rules.js +232 -40
  102. package/dist/core/mods/stations.d.ts +0 -6
  103. package/dist/core/mods/stations.js +0 -7
  104. package/dist/core/mounted-mcp.d.ts +57 -0
  105. package/dist/core/mounted-mcp.js +71 -2
  106. package/dist/core/own-property-receipt.d.ts +13 -0
  107. package/dist/core/own-property-receipt.js +3 -1
  108. package/dist/core/parent-spec-seat.d.ts +12 -15
  109. package/dist/core/parent-spec-seat.js +14 -6
  110. package/dist/core/pause-registry.d.ts +35 -1
  111. package/dist/core/pause-registry.js +10 -0
  112. package/dist/core/permission-rule-consent.d.ts +18 -5
  113. package/dist/core/permission-rule-consent.js +13 -8
  114. package/dist/core/permission-rule-model.d.ts +87 -15
  115. package/dist/core/permission-rule-model.js +87 -8
  116. package/dist/core/permission-rule-org.d.ts +200 -33
  117. package/dist/core/permission-rule-org.js +217 -91
  118. package/dist/core/permission-rule-session.js +2 -2
  119. package/dist/core/permission-rule-store.d.ts +8 -0
  120. package/dist/core/permission-rule-store.js +1 -0
  121. package/dist/core/permission-rule-sync.js +3 -2
  122. package/dist/core/permission-rules.d.ts +7 -1
  123. package/dist/core/permission-rules.js +37 -8
  124. package/dist/core/read-only-shell.d.ts +1 -1
  125. package/dist/core/read-only-shell.js +30 -9
  126. package/dist/core/remote-env.d.ts +41 -1
  127. package/dist/core/remote-env.js +18 -0
  128. package/dist/core/resume-startup-cause.d.ts +18 -0
  129. package/dist/core/resume-startup-cause.js +12 -0
  130. package/dist/core/retention.js +7 -2
  131. package/dist/core/retired-keys.d.ts +8 -2
  132. package/dist/core/retired-keys.js +12 -1
  133. package/dist/core/roles.js +60 -10
  134. package/dist/core/rule-lane-reads.js +1 -1
  135. package/dist/core/runner/approval-feedback.d.ts +46 -0
  136. package/dist/core/runner/approval-feedback.js +41 -0
  137. package/dist/core/runner/compaction-call-options.d.ts +3 -3
  138. package/dist/core/runner/compaction-call-options.js +2 -2
  139. package/dist/core/runner/contracts.d.ts +34 -41
  140. package/dist/core/runner/cross-boundary-lane.d.ts +87 -0
  141. package/dist/core/runner/cross-boundary-lane.js +190 -0
  142. package/dist/core/runner/decide-continuation.d.ts +4 -4
  143. package/dist/core/runner/decide-continuation.js +3 -1
  144. package/dist/core/runner/gate-exit.d.ts +32 -12
  145. package/dist/core/runner/gate-exit.js +77 -34
  146. package/dist/core/runner/inherited-ask-grants.js +2 -2
  147. package/dist/core/runner/mcp-redial.d.ts +52 -10
  148. package/dist/core/runner/mcp-redial.js +38 -9
  149. package/dist/core/runner/permission-rule-lanes.d.ts +5 -2
  150. package/dist/core/runner/permission-rule-lanes.js +22 -10
  151. package/dist/core/runner/person-path-rows.d.ts +5 -3
  152. package/dist/core/runner/person-path-rows.js +2 -2
  153. package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -4
  154. package/dist/core/runner/prepare-acquire-reconcile.js +3 -3
  155. package/dist/core/runner/prepare-ask-lane.js +3 -3
  156. package/dist/core/runner/prepare-caps-and-workflow.d.ts +6 -5
  157. package/dist/core/runner/prepare-caps-and-workflow.js +3 -3
  158. package/dist/core/runner/prepare-config-doors.d.ts +58 -15
  159. package/dist/core/runner/prepare-config-doors.js +167 -146
  160. package/dist/core/runner/prepare-context-lane.js +6 -3
  161. package/dist/core/runner/prepare-defer-classify.js +4 -7
  162. package/dist/core/runner/prepare-delegation-surface.d.ts +5 -4
  163. package/dist/core/runner/prepare-delegation-surface.js +8 -7
  164. package/dist/core/runner/prepare-execution-env.d.ts +1 -2
  165. package/dist/core/runner/prepare-execution-env.js +2 -1
  166. package/dist/core/runner/prepare-gate-stations.d.ts +2 -0
  167. package/dist/core/runner/prepare-gate-stations.js +4 -3
  168. package/dist/core/runner/prepare-hands-readface.d.ts +3 -3
  169. package/dist/core/runner/prepare-hands-readface.js +3 -2
  170. package/dist/core/runner/prepare-inherited-gate.d.ts +2 -0
  171. package/dist/core/runner/prepare-inherited-gate.js +3 -2
  172. package/dist/core/runner/prepare-listings.d.ts +1 -1
  173. package/dist/core/runner/prepare-listings.js +4 -2
  174. package/dist/core/runner/prepare-memory-engine-session.d.ts +0 -6
  175. package/dist/core/runner/prepare-memory-engine-session.js +19 -6
  176. package/dist/core/runner/prepare-memory.d.ts +3 -2
  177. package/dist/core/runner/prepare-memory.js +6 -2
  178. package/dist/core/runner/prepare-offload-wrappers.d.ts +4 -4
  179. package/dist/core/runner/prepare-offload-wrappers.js +2 -1
  180. package/dist/core/runner/prepare-park-ask.d.ts +1 -1
  181. package/dist/core/runner/prepare-park-ask.js +9 -3
  182. package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
  183. package/dist/core/runner/prepare-policy-chain.js +14 -19
  184. package/dist/core/runner/prepare-project-context.d.ts +1 -1
  185. package/dist/core/runner/prepare-project-context.js +6 -4
  186. package/dist/core/runner/prepare-prompt-assembly.d.ts +1 -1
  187. package/dist/core/runner/prepare-prompt-assembly.js +20 -16
  188. package/dist/core/runner/prepare-prompt-inputs.d.ts +12 -6
  189. package/dist/core/runner/prepare-prompt-inputs.js +6 -3
  190. package/dist/core/runner/prepare-protocol-tools.d.ts +7 -5
  191. package/dist/core/runner/prepare-protocol-tools.js +19 -12
  192. package/dist/core/runner/prepare-question-face.d.ts +4 -2
  193. package/dist/core/runner/prepare-question-face.js +4 -3
  194. package/dist/core/runner/prepare-safety-scan.d.ts +7 -2
  195. package/dist/core/runner/prepare-safety-scan.js +34 -27
  196. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -2
  197. package/dist/core/runner/prepare-suspend-saga.js +6 -2
  198. package/dist/core/runner/prepare-task.js +22 -19
  199. package/dist/core/runner/prepare-turn-wiring.d.ts +10 -5
  200. package/dist/core/runner/prepare-turn-wiring.js +14 -49
  201. package/dist/core/runner/prepare-wiring-manifest.d.ts +10 -5
  202. package/dist/core/runner/prepare-wiring-manifest.js +9 -6
  203. package/dist/core/runner/prepare-workspace-restore.js +2 -2
  204. package/dist/core/runner/resume-admission.d.ts +4 -1
  205. package/dist/core/runner/resume-admission.js +16 -14
  206. package/dist/core/runner/resume-apply.js +4 -4
  207. package/dist/core/runner/resume-internals-and-config.d.ts +3 -3
  208. package/dist/core/runner/resume-internals-and-config.js +3 -8
  209. package/dist/core/runner/resume-policy-outcome.d.ts +2 -2
  210. package/dist/core/runner/resume-policy-outcome.js +18 -15
  211. package/dist/core/runner/resume-preflight.js +2 -2
  212. package/dist/core/runner/resume-review-outcome.js +3 -3
  213. package/dist/core/runner/retired-runner-deps.d.ts +5 -6
  214. package/dist/core/runner/retired-runner-deps.js +1 -4
  215. package/dist/core/runner/run-leg.js +97 -43
  216. package/dist/core/runner/run-recovery-lanes.js +5 -3
  217. package/dist/core/runner/run-settle-and-teardown.js +2 -0
  218. package/dist/core/runner/run-terminal-adoption.js +21 -9
  219. package/dist/core/runner/run-turn-boundary.js +9 -3
  220. package/dist/core/runner/runtask.js +1 -1
  221. package/dist/core/runner/session-file-state-replay.d.ts +5 -2
  222. package/dist/core/runner/session-file-state-replay.js +3 -2
  223. package/dist/core/runner/skills-seat.d.ts +15 -0
  224. package/dist/core/runner/skills-seat.js +57 -0
  225. package/dist/core/runner/stream-steer-verb.js +2 -2
  226. package/dist/core/runner/sub-agent-deny-lists.d.ts +13 -11
  227. package/dist/core/runner/sub-agent-deny-lists.js +7 -5
  228. package/dist/core/runner/synthetic-tools.d.ts +5 -2
  229. package/dist/core/runner/synthetic-tools.js +2 -12
  230. package/dist/core/runner/tool-face-overlay.d.ts +24 -6
  231. package/dist/core/runner/tool-face-overlay.js +24 -15
  232. package/dist/core/runner-deps.d.ts +37 -22
  233. package/dist/core/session-policy-store.d.ts +19 -0
  234. package/dist/core/session-policy-store.js +22 -2
  235. package/dist/core/session-store.d.ts +35 -16
  236. package/dist/core/session-store.js +20 -12
  237. package/dist/core/{shell-lexer.d.ts → shell-run-candidates.d.ts} +36 -12
  238. package/dist/core/{shell-lexer.js → shell-run-candidates.js} +145 -225
  239. package/dist/core/shell-wrapper-table.d.ts +5 -3
  240. package/dist/core/shell-wrapper-table.js +1 -1
  241. package/dist/core/store-contracts/checkpoint-store-contract.js +2 -2
  242. package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
  243. package/dist/core/store-contracts/session-store-contract.d.ts +49 -0
  244. package/dist/core/store-contracts/session-store-contract.js +639 -0
  245. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +12 -0
  246. package/dist/core/store-contracts/session-store-incarnation-contract.js +5 -2
  247. package/dist/core/task-event.d.ts +44 -6
  248. package/dist/core/task-notification.js +2 -2
  249. package/dist/core/task-registry-agent.js +1 -0
  250. package/dist/core/task-registry-shared.d.ts +5 -0
  251. package/dist/core/task-registry.d.ts +7 -0
  252. package/dist/core/task-registry.js +17 -0
  253. package/dist/core/task-result.d.ts +1 -1
  254. package/dist/core/task-spec.d.ts +7 -7
  255. package/dist/core/tighten-task-spec.d.ts +6 -4
  256. package/dist/core/tighten-task-spec.js +2 -2
  257. package/dist/core/tool-catalog-entries.d.ts +1 -1
  258. package/dist/core/tool-catalog-entries.js +52 -52
  259. package/dist/core/tool-face-reader.d.ts +49 -0
  260. package/dist/core/tool-face-reader.js +94 -0
  261. package/dist/core/tool-face.d.ts +17 -8
  262. package/dist/core/tool-face.js +1 -0
  263. package/dist/core/tool-policy.d.ts +67 -23
  264. package/dist/core/tool-policy.js +72 -60
  265. package/dist/core/tool-roster.d.ts +46 -28
  266. package/dist/core/tool-roster.js +91 -14
  267. package/dist/core/tool-spec-members.js +2 -2
  268. package/dist/core/tool-spec.d.ts +20 -4
  269. package/dist/core/tools.js +2 -0
  270. package/dist/core/trace.d.ts +24 -2
  271. package/dist/core/types.d.ts +3 -3
  272. package/dist/core/types.js +1 -1
  273. package/dist/core/untrusted-text.d.ts +23 -0
  274. package/dist/core/untrusted-text.js +10 -10
  275. package/dist/core/user-attachment.d.ts +56 -2
  276. package/dist/core/user-attachment.js +139 -56
  277. package/dist/core/wiring-manifest.d.ts +4 -2
  278. package/dist/engine/compaction/compaction.d.ts +2 -2
  279. package/dist/engine/compaction/utils.d.ts +2 -2
  280. package/dist/engine/harness/agent-harness.js +2 -1
  281. package/dist/engine/harness/types.d.ts +10 -4
  282. package/dist/engine/llm/types.d.ts +7 -2
  283. package/dist/engine/llm/types.js +2 -1
  284. package/dist/engine/loop/agent-loop.d.ts +12 -1
  285. package/dist/engine/loop/agent-loop.js +17 -5
  286. package/dist/engine/loop/types.d.ts +7 -1
  287. package/dist/engine/session/repo-utils.d.ts +5 -0
  288. package/dist/engine/session/repo-utils.js +9 -0
  289. package/dist/engine/session/storage-base.js +2 -2
  290. package/dist/index.d.ts +37 -17
  291. package/dist/index.js +31 -14
  292. package/dist/internal/harness.d.ts +1 -0
  293. package/dist/internal/harness.js +1 -0
  294. package/dist/internal/llm.d.ts +1 -1
  295. package/dist/internal/llm.js +1 -1
  296. package/dist/orchestration/goal.d.ts +24 -1
  297. package/dist/orchestration/goal.js +3 -2
  298. package/dist/orchestration/run-workflow-tool.d.ts +3 -0
  299. package/dist/orchestration/run-workflow-tool.js +1 -0
  300. package/dist/orchestration/workflow-governance.d.ts +1 -1
  301. package/dist/orchestration/workflow.d.ts +3 -0
  302. package/dist/orchestration/workflow.js +2 -1
  303. package/dist/prompt-assembly/artifact-store.d.ts +44 -9
  304. package/dist/prompt-assembly/artifact-store.js +38 -12
  305. package/dist/prompt-assembly/artifact.d.ts +12 -11
  306. package/dist/prompt-assembly/artifact.js +52 -21
  307. package/dist/prompt-assembly/assemble.d.ts +2 -0
  308. package/dist/prompt-assembly/assemble.js +2 -1
  309. package/dist/prompt-assembly/catalog/index.js +2 -1
  310. package/dist/prompt-assembly/catalog/memory.d.ts +13 -0
  311. package/dist/prompt-assembly/catalog/memory.js +6 -0
  312. package/dist/prompt-assembly/catalog/schema.d.ts +19 -2
  313. package/dist/prompt-assembly/catalog/schema.js +3 -0
  314. package/dist/prompt-assembly/composer.d.ts +2 -0
  315. package/dist/prompt-assembly/composer.js +1 -1
  316. package/dist/prompt-assembly/overlay.d.ts +21 -11
  317. package/dist/prompt-assembly/overlay.js +57 -19
  318. package/dist/prompt-assembly/select.d.ts +21 -6
  319. package/dist/prompt-assembly/select.js +41 -4
  320. package/dist/prompts/default.d.ts +1 -12
  321. package/dist/prompts/default.js +0 -3
  322. package/dist/shell/lex.d.ts +87 -8
  323. package/dist/shell/lex.js +283 -49
  324. package/dist/stores/file/index.d.ts +8 -6
  325. package/dist/stores/file/permission-rule-store.d.ts +1 -1
  326. package/dist/stores/file/permission-rule-store.js +2 -1
  327. package/dist/tools/artifact/artifact-tool.js +14 -3
  328. package/dist/tools/fs/bash-program-position.d.ts +3 -15
  329. package/dist/tools/fs/bash-program-position.js +3 -10
  330. package/dist/tools/fs/bash-readonly-classifier.js +2 -0
  331. package/dist/tools/fs/fs-bash.d.ts +3 -3
  332. package/dist/tools/fs/fs-bash.js +72 -101
  333. package/dist/tools/fs/fs-read.d.ts +12 -0
  334. package/dist/tools/fs/fs-read.js +10 -9
  335. package/dist/tools/fs/fs-shared.d.ts +27 -31
  336. package/dist/tools/fs/fs-shared.js +12 -15
  337. package/dist/tools/fs/fs-write.js +1 -1
  338. package/dist/tools/fs/index.js +2 -2
  339. package/dist/tools/fs/read-deny-home.d.ts +1 -1
  340. package/dist/tools/fs/read-deny-home.js +5 -4
  341. package/dist/tools/fs/read-deny.d.ts +16 -3
  342. package/dist/tools/fs/read-deny.js +12 -9
  343. package/dist/tools/fs/safety.d.ts +7 -6
  344. package/dist/tools/fs/shell-read-bindings.d.ts +5 -3
  345. package/dist/tools/fs/shell-read-bindings.js +15 -16
  346. package/dist/tools/fs/shell-read-device.js +1 -1
  347. package/dist/tools/fs/shell-read-plan.js +36 -47
  348. package/dist/tools/fs/shell-read-word.d.ts +1 -6
  349. package/dist/tools/fs/shell-read-word.js +2 -20
  350. package/dist/tools/fs/shell-reentry-text.js +1 -1
  351. package/dist/tools/web.d.ts +2 -2
  352. package/package.json +4 -1
  353. package/test/export-surface.snapshot.json +5651 -5457
  354. package/wire-changes/core@7.53.0.json +1968 -0
  355. package/wire-changes/core@7.54.0.json +2870 -0
  356. package/dist/core/shell-scan.d.ts +0 -60
  357. package/dist/core/shell-scan.js +0 -183
@@ -1,17 +1,40 @@
1
1
  import { callerToolNameProblem } from "../caller-tool-name.js";
2
- import { engineCardTypes, handBandEffects } from "../tool-registry.js";
3
- import { callerCardIdOf, offendingResultCard, rosterMemberBoundProblem, schemaKeyBoundProblem, survivorsByName } from "../tool-roster.js";
2
+ import { describeToolCatalog } from "../tool-registry.js";
3
+ import { callerCardIdOf, rosterMemberBoundProblem, schemaKeyBoundProblem, survivorsByName } from "../tool-roster.js";
4
4
  import { toolFaceProblem } from "./tool-face-overlay.js";
5
- import { OFFLOAD_TOOL_NAME } from "../tool-result-store.js";
6
- import { PRESENT_PLAN_TOOL_NAME, ENTER_PLAN_MODE_TOOL_NAME } from "../present-plan-tool.js";
7
5
  const REPEAT_RISK = { read: 0, idempotent: 1, write: 2 };
8
6
  const leastRepeatSafe = (a, b) => (REPEAT_RISK[a] >= REPEAT_RISK[b] ? a : b);
7
+ function engineCandidatesOf(spec, deps) {
8
+ const hands = Boolean(deps.executionEnvFactory || deps.executionEnv);
9
+ const readOnlyHands = spec.handsReadOnly === true;
10
+ const out = [];
11
+ for (const e of describeToolCatalog()) {
12
+ if (!e.mountedBy.some((t) => t !== "scenario" && (t !== "hands" || hands)))
13
+ continue;
14
+ if (e.mountedBy.includes("hands") && e.face.ruleFace?.grammar === "command" && (e.face.effect === "read") !== readOnlyHands)
15
+ continue;
16
+ const effect = e.face.effect ?? "write";
17
+ for (const name of [e.name, ...(e.face.aliases ?? [])])
18
+ out.push([name, effect]);
19
+ }
20
+ return out;
21
+ }
22
+ function wakeEffectsOf(table, claimed, candidates) {
23
+ const wakeEffects = new Map(table);
24
+ const claims = new Set(claimed);
25
+ for (const [name, effect] of candidates) {
26
+ const prior = wakeEffects.get(name) ?? (claims.has(name) ? "write" : undefined);
27
+ wakeEffects.set(name, prior === undefined ? effect : leastRepeatSafe(prior, effect));
28
+ }
29
+ return wakeEffects;
30
+ }
9
31
  const tierOf = (t) => t.irreversibility ?? (t.reversibilityProbe ? "maybe" : undefined);
10
32
  export function prepareSafetyScan(input) {
11
33
  const { spec, deps } = input;
12
34
  const toolEffects = new Map();
13
35
  const survivors = survivorsByName(spec.tools ?? []);
14
36
  const claimedAliases = new Set();
37
+ const aliasClaims = [];
15
38
  const egressTools = new Set();
16
39
  const irreversibleTools = new Set();
17
40
  const irreversibilityTier = new Map();
@@ -52,18 +75,12 @@ export function prepareSafetyScan(input) {
52
75
  ...(t.ruleFace !== undefined ? { ruleFace: t.ruleFace } : {}),
53
76
  ...(t.renderHints !== undefined ? { renderHints: t.renderHints } : {}),
54
77
  };
55
- const faceProblem = toolFaceProblem(declared, t.parameters, { toolName: t.name });
78
+ const faceProblem = toolFaceProblem(declared, t.parameters, { toolName: t.name, cardId: callerCardIdOf(t) });
56
79
  if (faceProblem !== undefined) {
57
80
  const e = new Error(`Tool "${t.name}" declares a face its schema cannot carry: ${faceProblem}.`);
58
81
  e.code = "config.tool_face_invalid";
59
82
  throw e;
60
83
  }
61
- const foreignCard = offendingResultCard(t.renderHints, callerCardIdOf(t), engineCardTypes());
62
- if (foreignCard !== undefined) {
63
- const e = new Error(`Tool "${t.name}" declares a result card outside its own namespace: ${JSON.stringify(foreignCard)} (a caller card is "${callerCardIdOf(t)}/<card>"; engine cards and other contracts' namespaces are reserved).`);
64
- e.code = "config.tool_face_invalid";
65
- throw e;
66
- }
67
84
  }
68
85
  for (const [what, n] of [["name", t.name], ...(t.aliases ?? []).map((a) => ["alias", a])]) {
69
86
  const problem = callerToolNameProblem(n);
@@ -96,16 +113,21 @@ export function prepareSafetyScan(input) {
96
113
  markedBy(t.name, "deployment");
97
114
  }
98
115
  }
116
+ const candidates = engineCandidatesOf(spec, deps);
117
+ const engineNames = new Set(candidates.map(([n]) => n));
99
118
  for (const t of survivors.values()) {
100
119
  const tier = tierOf(t);
101
120
  for (const alias of t.aliases ?? []) {
102
121
  if (alias === t.name || survivors.has(alias))
103
122
  continue;
123
+ aliasClaims.push([alias, t.effect ?? "write"]);
104
124
  if (claimedAliases.has(alias))
105
125
  continue;
106
126
  claimedAliases.add(alias);
107
127
  if (t.effect)
108
128
  toolEffects.set(alias, t.effect);
129
+ if (engineNames.has(alias))
130
+ continue;
109
131
  if (tier !== undefined) {
110
132
  irreversibilityTier.set(alias, tier);
111
133
  if (tier === "always" || tier === "maybe") {
@@ -121,24 +143,9 @@ export function prepareSafetyScan(input) {
121
143
  }
122
144
  }
123
145
  }
124
- toolEffects.set(OFFLOAD_TOOL_NAME, "read");
125
- const claimerEffects = new Map([...claimedAliases, ...survivors.keys()].map((a) => [a, toolEffects.get(a) ?? "write"]));
126
- const recordHandEffect = (name, effect) => {
127
- const claimed = claimerEffects.get(name);
128
- toolEffects.set(name, claimed === undefined ? effect : leastRepeatSafe(claimed, effect));
129
- };
130
- if (deps.executionEnvFactory || deps.executionEnv) {
131
- for (const [name, effect] of handBandEffects())
132
- recordHandEffect(name, effect);
133
- if (spec.handsReadOnly === true)
134
- recordHandEffect("Bash", "read");
135
- }
136
- if (spec.enablePlanMode === true) {
137
- toolEffects.set(PRESENT_PLAN_TOOL_NAME, "read");
138
- toolEffects.set(ENTER_PLAN_MODE_TOOL_NAME, "read");
139
- }
140
146
  return {
141
147
  toolEffects,
148
+ wakeEffects: wakeEffectsOf(toolEffects, [...claimedAliases, ...survivors.keys()], [...aliasClaims, ...candidates]),
142
149
  egressTools,
143
150
  irreversibleTools,
144
151
  irreversibilityTier,
@@ -177,8 +177,8 @@ export interface PrepareSuspendSagaInput {
177
177
  readonly definition?: string;
178
178
  readonly lists: string;
179
179
  } | undefined;
180
- /** borrowed-readonly — the external-content-target fold (the row's monotonic bit). */
181
- externalContentTargetActive: boolean;
180
+ /** borrowed-readonly — the external-content-target fold (the row's monotonic bit). */ externalContentTargetActive: boolean;
181
+ /** borrowed-readonly — the leg's cross-boundary lane: the row's mark, and the record written before the row as the row's leaf. */ crossBoundary: import("./cross-boundary-lane.js").CrossBoundaryLane;
182
182
  /** borrowed-mutable — the run-scoped remote-lifecycle failure log (`Prepared.remoteEnvFailures`). Writer here: the
183
183
  * compensation's note binding (`push`). */
184
184
  remoteEnvFailures: Prepared["remoteEnvFailures"];
@@ -82,7 +82,7 @@ function stampPlacementRootSessionId(placementRootResolved) {
82
82
  return placementValueOrAbsent(placementRootResolved);
83
83
  }
84
84
  export function prepareSuspendSaga(input) {
85
- const { gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, reminderMark, handsCwdRef, handsRoot, handsHome, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, inheritedPathRuleAnchors, inheritedPathRuleInstallations, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, checkpointScope, toolCeiling, toolListsJudged, ownToolLists, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter } = input;
85
+ const { gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, reminderMark, handsCwdRef, handsRoot, handsHome, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, inheritedPathRuleAnchors, inheritedPathRuleInstallations, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, checkpointScope, toolCeiling, toolListsJudged, ownToolLists, externalContentTargetActive, crossBoundary, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter } = input;
86
86
  if (!gateMachineryActive)
87
87
  return { saga: undefined };
88
88
  const inFlightSpendMicroUsd = () => {
@@ -182,6 +182,7 @@ export function prepareSuspendSaga(input) {
182
182
  toolCeiling: toolCeiling !== undefined ? toolCeiling.map((l) => ({ ...(l.allow !== undefined ? { allow: persistedToolNameList(l.allow, "allowed") } : {}), deny: persistedToolNameList(l.deny, "denied") })) : undefined,
183
183
  toolListsJudged,
184
184
  ownToolLists: ownToolLists !== undefined ? { toolName: ownToolLists.toolName, ...(ownToolLists.definition !== undefined ? { definition: ownToolLists.definition } : {}), lists: ownToolLists.lists } : undefined,
185
+ crossBoundaryRecorded: crossBoundary.recorded() ? true : undefined,
185
186
  });
186
187
  const compensatePausedVM = (remoteEnv, snapshotId) => compensateUnparkedPause(remoteEnv, snapshotId, {
187
188
  boundMs: PARK_COMPENSATION_TIMEOUT_MS,
@@ -199,6 +200,7 @@ export function prepareSuspendSaga(input) {
199
200
  return { tag: "absent" };
200
201
  if (memoryEngineSession)
201
202
  await memoryEngineSession.harvest("checkpoint");
203
+ const recordUnwritten = await crossBoundary.owe(cp.leafId).then((entryId) => void (entryId !== undefined && (cp = { ...cp, leafId: entryId })), (err) => ({ err }));
202
204
  if (cutSignal?.aborted) {
203
205
  if (remoteEnv !== undefined && remoteHandle?.snapshotId !== undefined) {
204
206
  const back = await compensatePausedVM(remoteEnv, remoteHandle.snapshotId);
@@ -262,6 +264,8 @@ export function prepareSuspendSaga(input) {
262
264
  const own = judgeAsStored(stamped, fidelity);
263
265
  if (own.kind !== "ok")
264
266
  throw new Error(`the checkpoint row was not written: ${own.kind === "damaged" ? own.why : "it lists words this engine lacks"}`);
267
+ if (recordUnwritten !== undefined)
268
+ throw new Error(`the checkpoint row was not written: the session's cross-boundary record it points at could not be written first (${thrownText(recordUnwritten.err)})`);
265
269
  putAttempted = true;
266
270
  await checkpointStore.put(token, stamped);
267
271
  announceCommittedScreeningPark();
@@ -270,7 +274,7 @@ export function prepareSuspendSaga(input) {
270
274
  catch (putErr) {
271
275
  deps.onError?.(putErr, { phase: "config", sessionId });
272
276
  if (!putAttempted)
273
- return compensateNotWritten("the approval checkpoint was not written (the row failed its own requirement judge before the write; the deployment's error face carries why)");
277
+ return compensateNotWritten(recordUnwritten !== undefined ? `the session's cross-boundary record could not be written before its approval could be parked (${thrownText(recordUnwritten.err)}) — on a governed tree a row is not put without its record` : "the approval checkpoint was not written (a check before the write refused it — the row's own requirement judge; the deployment's error face carries why)");
274
278
  const confirmed = await confirmPutOutcome(putErr);
275
279
  if (confirmed === "committed") {
276
280
  try {
@@ -43,6 +43,7 @@ import { prepareTurnWiring } from "./prepare-turn-wiring.js";
43
43
  export { runGuardChain } from "./prepare-context-lane.js";
44
44
  import { preparePromptAssembly } from "./prepare-prompt-assembly.js";
45
45
  import { limitConfigError, prepareConfigDoors } from "./prepare-config-doors.js";
46
+ import { joinedCrossBoundaryTree, prepareCrossBoundaryLane } from "./cross-boundary-lane.js";
46
47
  import { prepareSafetyScan } from "./prepare-safety-scan.js";
47
48
  import { prepareAcquireReconcile } from "./prepare-acquire-reconcile.js";
48
49
  import { settleBranchWriteBack } from "./branch-writeback.js";
@@ -86,7 +87,7 @@ import { announcePeerLaneMount, judgeSessionBoxDrain } from "../../agents/peer-s
86
87
  import { createFrameSettlement } from "../frame-settlement.js";
87
88
  import { createSchedulerTools } from "../../tools/scheduler-tools.js";
88
89
  import { selfOrchestrationFailClosedReason } from "../../orchestration/workflow-script-runner.js";
89
- import { compileToolSelector } from "../../agents/tool-filter.js";
90
+ import { compileToolSelector, valveLeaves } from "../../agents/tool-filter.js";
90
91
  import { boundOwnToolLists, boundToolListsJudgment, judgeRunToolLists } from "./sub-agent-deny-lists.js";
91
92
  import { remainingBudgetMicroUsd, resolveCheckpointStore } from "../checkpoint-store.js";
92
93
  import { checkpointSeatOf } from "../checkpoint-seat.js";
@@ -305,7 +306,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
305
306
  const { toolFaceLists, promptProfile, promptHost, promptBinding, lockedPreflight, resolvedInteractionPosture, microCompactKnob, resolvedRole, model, thinking, compModel, fableMitigations, memoryDelegationEvidence, memoryProvenance, memoryCapturePolicy, usageWindows, brainCallGuardrailRef, brainCallGuardrailMs } = doors;
306
307
  announceToolModelGate(deps.onNotice, model.id, doors.modelGate);
307
308
  const modelGateManifest = toolModelGateManifest(doors.modelGate);
308
- const { toolEffects, egressTools, irreversibleTools, irreversibilityTier, axisExplicitNegatives, reversibilityProbes, toolMarkSources } = prepareSafetyScan({ spec, deps });
309
+ const { toolEffects, wakeEffects, egressTools, irreversibleTools, irreversibilityTier, axisExplicitNegatives, reversibilityProbes, toolMarkSources } = prepareSafetyScan({ spec, deps });
309
310
  let shellGatedTools = new Set();
310
311
  refuseRequireExistingWithoutSession(spec);
311
312
  refuseRegistryScopeMismatch(spec, internals);
@@ -318,7 +319,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
318
319
  throw e;
319
320
  }
320
321
  const fileHistoryRequest = resolveFileHistoryRequest(spec, deps);
321
- const { acquired, session, conflictRef, wakeRecovered, branch } = await prepareAcquireReconcile({ sessions, spec, resume, toolEffects, report: (e, id) => deps.onError?.(e, { phase: "config", sessionId: id }), ...(internals?.sessionPlacement !== undefined ? { placement: internals.sessionPlacement } : {}), ...(() => { const g = durableParkGapFor(deps, spec); return g !== undefined ? { durableParkGap: g } : {}; })() });
322
+ const { acquired, session, conflictRef, wakeRecovered, branch } = await prepareAcquireReconcile({ sessions, spec, resume, wakeEffects, report: (e, id) => deps.onError?.(e, { phase: "config", sessionId: id }), ...(internals?.sessionPlacement !== undefined ? { placement: internals.sessionPlacement } : {}), ...(() => { const g = durableParkGapFor(deps, spec); return g !== undefined ? { durableParkGap: g } : {}; })() });
322
323
  const sessionId = acquired.sessionId;
323
324
  await holdSessionLock?.(sessionId);
324
325
  const onceLedger = await loadAnnounceOnceLedger(session, resume?.seed.announcedListings, deps.onError);
@@ -355,7 +356,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
355
356
  const sessionBox = judgeSessionBoxDrain(deps, { sessionId, scope: taskScope, isDelegatedChild: delegation.isDelegatedChild });
356
357
  const peerLaneRefs = {};
357
358
  const frameSettlement = createFrameSettlement();
358
- const peerSendMessageBuiltIn = runnerSelf !== undefined && toolFaceSnapshot.selector.admits({ name: SEND_MESSAGE_TOOL_NAME }) && !(spec.tools ?? []).some((t) => t.name === SEND_MESSAGE_TOOL_NAME);
359
+ const peerSendMessageBuiltIn = runnerSelf !== undefined && valveLeaves(spec, toolFaceSnapshot.selector)({ name: SEND_MESSAGE_TOOL_NAME }) && !(spec.tools ?? []).some((t) => t.name === SEND_MESSAGE_TOOL_NAME);
359
360
  const { reminderMark, reminderDisclosureCounts } = await adoptReminderMark(session, sessionId, resume?.seed.reminderMark, internals?.reminderMark, deps.onError);
360
361
  const offloadScope = spec.principal ?? "default";
361
362
  if (internals?.registryScope !== undefined && internals.registryScope !== offloadScope) {
@@ -377,6 +378,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
377
378
  if (!handsEnabled)
378
379
  refuseUserAttachmentPathsWithoutWorkspace(userAttachmentsSeat);
379
380
  const externalContentTargetActive = executionEnv.externalContentTarget === true || resume?.seed.externalContentTarget === true;
381
+ const crossBoundaryTree = joinedCrossBoundaryTree(internals?.crossBoundaryTree, (m) => deps.onError?.(new Error(m), { phase: "config", sessionId }));
380
382
  const abortController = new AbortController();
381
383
  if (spec.signal?.aborted)
382
384
  abortController.abort();
@@ -457,7 +459,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
457
459
  let handsLessResolvedWriteFace;
458
460
  const mcpPool = installedPreflight.mcp?.length ? { pool: internals?.mcpPool ?? new McpConnectionPool(), owned: internals?.mcpPool === undefined } : undefined;
459
461
  const mountedMcpNow = mcpPool !== undefined ? () => mountedMcpOf({ declared: installedPreflight.mcp, roster: roster.tools, aggregateNames: new Set(mcp.tools.filter((t) => t.mcpRemoteName === undefined).map((t) => t.name)), pool: mcpPool.pool }) : undefined;
460
- const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, permissionMode, commitModeSeats, endModeCeiling, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, ancestorSessionRulesRef, ancestorRulesNow, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, runClampSource, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, frozenOnAsk, hookEnvSource, frozenOnQuestion, parentSpecSeat, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, carrierWriteFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, askSeat: doors.askSeat, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight: installedPreflight, pathRuleAnchors: { chainTop, onLeg: onLeg.chained }, checkpointSeat, checkpointScope, toolFaceSnapshot, mountsCallerTool, ...(mountedMcpNow !== undefined ? { mountedMcp: mountedMcpNow } : {}), promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, requestAllowedTools: allowedToolTables.request, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, modBus: legMods.bus, ownModChain, hookEnvFace: () => hookEnvFace, autoModeDecider: () => autoModeDeciderRef.current, autoModeDenialTracking: () => autoModeDenialTrackingRef.current, autoModeArming: () => autoModeArmingRef.current, agentForkDenial: () => agentForkDenial, observersActive: () => observersActive, resolvedReadFace: () => resolvedReadFace, resolvedWriteFace: () => resolvedWriteFace, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized, handsLessResolvedFace: () => handsLessResolvedFace, handsLessResolvedWriteFace: () => handsLessResolvedWriteFace, centerAdoption: () => centerAdoptionRef.current, memoryEngineSession: () => memoryEngineSession });
462
+ const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, permissionMode, commitModeSeats, endModeCeiling, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, ancestorSessionRulesRef, ancestorRulesNow, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, runClampSource, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, frozenOnAsk, hookEnvSource, frozenOnQuestion, parentSpecSeat, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, carrierWriteFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, askSeat: doors.askSeat, crossBoundaryTree, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight: installedPreflight, pathRuleAnchors: { chainTop, onLeg: onLeg.chained }, checkpointSeat, checkpointScope, toolFaceSnapshot, mountsCallerTool, ...(mountedMcpNow !== undefined ? { mountedMcp: mountedMcpNow } : {}), promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, requestAllowedTools: allowedToolTables.request, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, modBus: legMods.bus, ownModChain, hookEnvFace: () => hookEnvFace, autoModeDecider: () => autoModeDeciderRef.current, autoModeDenialTracking: () => autoModeDenialTrackingRef.current, autoModeArming: () => autoModeArmingRef.current, agentForkDenial: () => agentForkDenial, observersActive: () => observersActive, resolvedReadFace: () => resolvedReadFace, resolvedWriteFace: () => resolvedWriteFace, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized, handsLessResolvedFace: () => handsLessResolvedFace, handsLessResolvedWriteFace: () => handsLessResolvedWriteFace, centerAdoption: () => centerAdoptionRef.current, memoryEngineSession: () => memoryEngineSession });
461
463
  bindPermissionModeSeat(permissionMode);
462
464
  const personRowNotices = { onUnread: ruleStoreUnreadableNotice(deps.onNotice, { sessionId, runId }), onRowsDropped: ruleRowsDroppedNotice(deps.onNotice, { sessionId, runId }) };
463
465
  const readerOf = (signals) => personPathRowsOfTask({ deps, notices: personRowNotices, principal: spec.principal, ids: { sessionId, runId, taskId: hostTaskId }, root: taskRootFinal, rootCanonical: taskRootCanonical, leads: headLeads, chainTop, occurrences: toolOccurrences, signals });
@@ -475,8 +477,9 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
475
477
  const legExemptRoots = Object.freeze(dataRootSpellings(deps.memoryEngineDir));
476
478
  const legWriteGuard = { exemptRoots: legExemptRoots, rows: toolPolicyWriteGuardRows([installedToolPolicy, ...(inheritedParentConstraints ?? []).map((c) => c.policy)]) };
477
479
  const sideCallBookRef = {};
478
- const { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDeciderRef, autoModeDenialTrackingRef, autoModeArmingRef, armAutoMode, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline } = await prepareCapsAndWorkflow({ spec, deps, askSeat: doors.askSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, checkpointSeat, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, parentSpecSeat, runClampSource, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries: () => personRows.tablesReady().then(() => ({ entries: readDenyMatcher?.entries ?? [], ruleRows: pathTables?.ruleRows() ?? effectivePathDenyRules })), peerLaneActive, peerSendMessageBuiltIn, runnerSelf, memoryEngineSession: () => memoryEngineSession, centerAdoption: () => centerAdoptionRef.current, delegated: delegation.isDelegatedChild, sideCallBookRef });
480
+ const { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDeciderRef, autoModeDenialTrackingRef, autoModeArmingRef, armAutoMode, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline } = await prepareCapsAndWorkflow({ spec, deps, askSeat: doors.askSeat, internals, crossBoundaryTree, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, checkpointSeat, toolEffects, safetyAxes: { irreversibilityTier, irreversibleTools, reversibilityProbes, egressTools, toolMarkSources }, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, parentSpecSeat, runClampSource, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries: () => personRows.tablesReady().then(() => ({ entries: readDenyMatcher?.entries ?? [], ruleRows: pathTables?.ruleRows() ?? effectivePathDenyRules })), peerLaneActive, peerSendMessageBuiltIn, runnerSelf, memoryEngineSession: () => memoryEngineSession, centerAdoption: () => centerAdoptionRef.current, delegated: delegation.isDelegatedChild, sideCallBookRef });
479
481
  const tools = roster.tools;
482
+ const crossBoundary = await prepareCrossBoundaryLane({ token: crossBoundaryTree, posture: doors.crossBoundaryPosture, externalContentTargetActive, env: executionEnv, session, resumeLeg: resume !== undefined, sessionId, runId, hostTaskId, deps });
480
483
  const pausedRef = {};
481
484
  const undeliveredContinuationRef = { current: { parkedSteers: [], orphanTasks: [] } };
482
485
  const remoteEnvFailures = [];
@@ -549,7 +552,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
549
552
  for (const alias of t.aliases ?? [])
550
553
  memoryPairNameDomain.add(alias);
551
554
  }
552
- const memoryPairExcludedName = MEMORY_ENGINE_TOOL_NAMES.find((n) => !toolFaceSnapshot.selector.admits({ name: n }));
555
+ const memoryPairExcludedName = MEMORY_ENGINE_TOOL_NAMES.find((n) => !valveLeaves(spec, toolFaceSnapshot.selector)({ name: n }));
553
556
  const memoryPairOccupiedName = MEMORY_ENGINE_TOOL_NAMES.find((n) => memoryPairNameDomain.has(n));
554
557
  const memorySearchToolsPlanned = memoryPairExcludedName === undefined && memoryPairOccupiedName === undefined;
555
558
  const captureLineage = await (async () => {
@@ -569,7 +572,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
569
572
  taskRootPath: taskRootFinal,
570
573
  reminderMark,
571
574
  writeToolsMounted: (handsWriteHalfPlanned || tools.some((t) => t.name === "Write")) &&
572
- toolFaceSnapshot.selector.admits({ name: "Write" }) &&
575
+ valveLeaves(spec, toolFaceSnapshot.selector)({ name: "Write" }) &&
573
576
  !(handsEnabled && isRemoteExecutionEnv(executionEnv) && spec.memoryPersistenceCapable !== true),
574
577
  memoryProvenance,
575
578
  memoryCapturePolicy,
@@ -626,7 +629,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
626
629
  shellGatedTools = handsReadFace.shellGatedTools;
627
630
  await armAutoMode();
628
631
  const { worktreeSessionRef } = prepareDelegationSurface({ spec, deps, internals, resume, sessionId, hostTaskId, taskScope, taskRootFinal, taskRootCanonical, executionEnv, runnerSelf, backgroundTaskToolsActive, shellReadAdmission, workflowToolsActive, peerLaneActive, peerSendMessageBuiltIn, peerLaneRefs, sessionBox, roster, toolEffects, axisExplicitNegatives, envHandToolNames, toolFaceSnapshot, firstPartyOffload, offloadStore, subagentRetain, enrichSpecToolCtx, checkpointSeat, handsCwdRef, wsSnapshot, rebaseWsPath, rebaseRestoredPath, workspaceStateSettle });
629
- const { liveQuestionFace, contentAskBindings, contentAskRoutable, lateStrandedAnswers, discloseStrandedAnswers, settleContentAskBindings, durableQuestionFace, questionToolMounted, mountedQuestionTool } = prepareQuestionFace({ frozenOnQuestion, spec, deps, checkpointStore, runtimeCaps, resolvedInteractionPosture, resume, sessionId, roster, inheritedUnavailableAsks: () => inheritedUnavailableAsks });
632
+ const { liveQuestionFace, contentAskBindings, contentAskRoutable, lateStrandedAnswers, discloseStrandedAnswers, settleContentAskBindings, durableQuestionFace, questionToolMounted, mountedQuestionTool } = prepareQuestionFace({ frozenOnQuestion, spec, deps, checkpointStore, runtimeCaps, resolvedInteractionPosture, resume, sessionId, roster, toolFaceSnapshot, inheritedUnavailableAsks: () => inheritedUnavailableAsks });
630
633
  if (spec.handsReadOnly !== true) {
631
634
  const sessionScope = sessionId ?? spec.principal ?? spec.taskId ?? "default";
632
635
  roster.mountAll(createSchedulerTools(executionEnv, {
@@ -659,8 +662,8 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
659
662
  live.incomplete = true;
660
663
  }
661
664
  }
662
- const rosterCanPersist = rosterCanPersistMemory(tools.filter((t) => toolFaceSnapshot.selector.admits(t)), { effects: toolEffects, remoteHands: handsEnabled && isRemoteExecutionEnv(executionEnv) }, spec.memoryPersistenceCapable);
663
- const { memoryBlock: memoryBlockFromEngine, recallDisciplineSegment: memoryRecallSegment, seedFiles: memorySeedFiles } = composeMemoryInjection({ rosterCanPersist });
665
+ const rosterCanPersist = rosterCanPersistMemory(tools.filter(valveLeaves(spec, toolFaceSnapshot.selector)), { effects: toolEffects, remoteHands: handsEnabled && isRemoteExecutionEnv(executionEnv) }, spec.memoryPersistenceCapable);
666
+ const { memoryBlock: memoryBlockFromEngine, recallDisciplineSegment: memoryRecallSegment, seedFiles: memorySeedFiles } = composeMemoryInjection({ rosterCanPersist, isSubagent: delegation.isNonForkChild });
664
667
  if (memorySeedFiles?.length && seedContextFiles) {
665
668
  try {
666
669
  await seedContextFiles(memorySeedFiles);
@@ -671,10 +674,10 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
671
674
  }
672
675
  const projectContext = await prepareProjectContext({ deps, spec, internals, session, sessionId, runId, hostTaskId, taskRootFinal, handsEnabled, delegation, seedContextFiles, memoryBlockFromEngine, skillGrants, allowedTools, allowedToolTables, roster, toolFaceSnapshot, onceLedger, memoryTools, memoryEngineSession, memorySearchToolsPlanned, memoryPairExcludedName, memoryPairOccupiedName, resume, skillListingBudget: doors.skillListingBudget });
673
676
  const { memoryBlock: memoryBlockWithProject, instructionSources, projectInstructionContent, skillSpecs, skillSeatOf, skillsListing, sharedMemoryPairMounted, memoryEnginePairMounted } = projectContext;
674
- const { featureFlags, sugar, mcpInstructionsBlock, envFacts, tzValid, userTz, dateAnchor, gitStatusRef } = await preparePromptInputs({ modBus: legMods.bus, spec, deps, contextOverlay: legContextOverlay(), failClosedReason: selfOrchestrationFailClosedReason(spec, deps), lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, resolvedWriteFace: resolvedWriteFace?.inForce(), toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical: (await readRoots.ready().then(readRoots)).filter((r) => !additionalRootsCanonical.includes(r)), sessionId, session, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}) });
677
+ const { featureFlags, sugar, mcpInstructionsBlock, envFacts, tzValid, userTz, dateAnchor, gitStatusRef } = await preparePromptInputs({ modBus: legMods.bus, spec, deps, contextOverlay: legContextOverlay(), failClosedReason: selfOrchestrationFailClosedReason(spec, deps), lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, resolvedWriteFace: resolvedWriteFace?.inForce(), toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, roster, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical: (await readRoots.ready().then(readRoots)).filter((r) => !additionalRootsCanonical.includes(r)), sessionId, session, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}) });
675
678
  judgeRunToolLists({ spec, tools: roster.tools, declaredPeers: { mcp: lockedPreflight.mcp, a2a: a2a.statuses }, own: { allow: toolFaceLists.allow, exclude: toolFaceLists.exclude }, layers: toolFaceSnapshot.selector.layers, legs: toolLegs, judgedUpstream: toolListsJudged !== undefined, toldUpstream: internals?.ownToolLists !== undefined && ownToolLists !== undefined && toolCeiling !== undefined, ownBy: ownToolLists, onceLedger, sessionId });
676
679
  const { deferred, memoryBlock, toolSearch: toolSearchPolicy } = prepareDeferClassify({ spec, deps, roster, toolFaceSnapshot, handsEnabled, fullShellReachable, promptProfile, model, mcp, a2a, sharedMemoryPairMounted, memoryEnginePairMounted, memoryBlock: memoryBlockWithProject, memoryRecallSegment, onceLedger, sessionId });
677
- prepareMemoryEngineSession({ memoryEngineSession, internals, memoryDelegationEvidence, externalContentTargetActive, lockedPreflight, mcp, ...(mountedMcpNow !== undefined ? { mountedMcp: mountedMcpNow } : {}), sessionId, runId, deps, provenanceForChildrenRef, delegationSettlementRef, spec, envHandToolNames, roster, contentOriginWrapRef });
680
+ prepareMemoryEngineSession({ memoryEngineSession, internals, memoryDelegationEvidence, externalContentTargetActive, lockedPreflight, ...(mountedMcpNow !== undefined ? { mountedMcp: mountedMcpNow } : {}), sessionId, runId, deps, provenanceForChildrenRef, delegationSettlementRef, spec, envHandToolNames, roster, contentOriginWrapRef });
678
681
  const { systemPromptSeat, renderWithDate, systemBlocks, promptManifest, promptIdentity, buildAssembleInputs, identityFor, adoptsCandidates, centerAdoptionRef } = await preparePromptAssembly({ session, deps, internals, resume, sugar, host: promptHost, binding: promptBinding, modBus: legMods.bus, signal: abortController.signal, featureFlags, mcpInstructionsBlock, memoryBlock, envFacts, promptProfile, fableMitigations, tools, model, sessionId, onceLedger });
679
682
  const { activeTools, fpRef, turnSnapshotRef, harnessTools, toolsDeltaRef, toolMaterializeStatic, deferDirectCall, staticFaceForRef, listingRideRef, toolSearch, toolDisclosureSeat } = await prepareToolDisclosureMount({ spec, deps, session, resume, deferred, tools, onceLedger, mcp, promptManifest, toolSearchPolicy, offloadReachableToolsRef, contentOriginWrapRef, rebuildHarnessToolsRef, harnessRef });
680
683
  if (toolSearch !== undefined)
@@ -786,7 +789,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
786
789
  }
787
790
  }
788
791
  const { basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, grantBindingOf, permissionRuleLane, ruleLaneFacts, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations, inheritedToolChecks } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight: installedPreflight, pathRuleAnchors: { leg: legAnchors, chainTop }, headLeads, tools, harnessTools, selector: toolFaceSnapshot.selector, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, personRows, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, modBus: legMods.bus, ownModChain, autoModeDecider: () => autoModeDeciderRef.current, readFace: () => resolvedReadFace, permissionMode, scratchpadDir: spec.envFacts?.scratchpadDir, toolRosterDeltas: rosterSeat, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
789
- const { onAsk, preToolContexts, blockedToolCalls, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtection, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound } = prepareWiringManifest({ spec, deps, askSeat: doors.askSeat, internals, resume, sessionId, runId, hostTaskId, taskScope, modBus: legMods.bus, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, legWriteGuard, mcp, irreversibleTools, egressTools, shellReadStationArmed: handsReadFace.shellReadStationArmed, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, harness, pausedRef, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined, fileHistoryFact, sessionBox, checkpointScope });
792
+ const { onAsk, preToolContexts, blockedToolCalls, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtection, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound } = prepareWiringManifest({ spec, deps, askSeat: doors.askSeat, crossBoundaryStationEngaged: crossBoundary.stationEngaged, internals, resume, sessionId, runId, hostTaskId, taskScope, modBus: legMods.bus, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, legWriteGuard, mcp, irreversibleTools, egressTools, shellReadStationArmed: handsReadFace.shellReadStationArmed, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, harness, pausedRef, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined, fileHistoryFact, sessionBox, checkpointScope, memoryPollution: () => memoryEngineSession?.pollution });
790
793
  const writeProtectionCheck = writeProtection.mount?.check;
791
794
  writeTargetJudgeRef.current = writeProtection.judgeWriteTarget;
792
795
  if (fileHistoryBoundary !== undefined) {
@@ -796,20 +799,20 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
796
799
  });
797
800
  }
798
801
  const listPathRows = () => skillSpecs.flatMap((s) => compileSkillGrant(s, "model").rows).flatMap((r) => (r.behavior === "deny" && r.compiled.kind === "path" ? [r.compiled.rule] : []));
799
- const stampCallTarget = attachmentRootCanonical === undefined ? undefined : legCallTargetStamp({ env: executionEnv, root: attachmentRootCanonical, cwd: () => handsCwdRef?.current, judgesPaths: () => effectivePolicy?.pathRules !== undefined || basePolicyForResumeEdit?.pathRules !== undefined || permissionRuleLane !== undefined || skillSpecs.some((s) => compileSkillGrant(s, "model").rows.some((r) => r.compiled.kind === "path")) || allowedToolTables.request.holdsPathRows() || allowedToolTables.deployment.holdsPathRows(), leads: () => headLeads.resolve([...toolPolicyPathRules([effectivePolicy, basePolicyForResumeEdit, ...(inheritedParentConstraints ?? []).map((c) => c.policy)], legAnchors), ...bindPathRules(listPathRows().map((rule) => ({ parsed: rule, ruleText: rule.rule })), legAnchors)]) });
802
+ const stampCallTarget = attachmentRootCanonical === undefined ? undefined : legCallTargetStamp({ env: executionEnv, root: attachmentRootCanonical, cwd: () => handsCwdRef?.current, judgesPaths: () => parkLaneArmed || effectivePolicy?.pathRules !== undefined || basePolicyForResumeEdit?.pathRules !== undefined || permissionRuleLane !== undefined || skillSpecs.some((s) => compileSkillGrant(s, "model").rows.some((r) => r.compiled.kind === "path")) || allowedToolTables.request.holdsPathRows() || allowedToolTables.deployment.holdsPathRows(), leads: () => headLeads.resolve([...toolPolicyPathRules([effectivePolicy, basePolicyForResumeEdit, ...(inheritedParentConstraints ?? []).map((c) => c.policy)], legAnchors), ...bindPathRules(listPathRows().map((rule) => ({ parsed: rule, ruleText: rule.rule })), legAnchors)]) });
800
803
  const { askLane } = prepareAskLane({ gateMachineryActive, abortController, effectivePolicy, budgetSnapshot, handsCwdRef, handsRoot: attachmentRootCanonical, stampCallTarget, advertisedWritableDirs, exemptRoots: legExemptRoots, tools, inheritedUnavailableAsks, inheritedAskGrants, onAsk, humanReviewRef, now, ruleOffersOf, grantBindingOf, askSourceIdentity, riskAxesOf, autoModeDenialTracking: autoModeDenialTrackingRef, spec, deps, sessionId, runId, modBus: legMods.bus, notifyOwnHookCrash, grantReadRoot: handsReadFace.grantReadRoot });
801
804
  const inheritedAnchorRecords = chainAnchorRecords(chainTop, inheritedParentConstraints ?? []);
802
- const { saga } = prepareSuspendSaga({ gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, reminderMark, handsCwdRef, handsRoot: attachmentRootCanonical, handsHome: attachmentRootCanonical !== undefined ? legAnchors.home : undefined, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, inheritedPathRuleAnchors: chainTop !== legAnchors ? inheritedAnchorRecords.pathRuleAnchors : undefined, inheritedPathRuleInstallations: inheritedAnchorRecords.pathRuleInstallations, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, checkpointScope, toolCeiling, toolListsJudged, ownToolLists, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
805
+ const { saga } = prepareSuspendSaga({ gateMachineryActive, crossBoundary, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, reminderMark, handsCwdRef, handsRoot: attachmentRootCanonical, handsHome: attachmentRootCanonical !== undefined ? legAnchors.home : undefined, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, inheritedPathRuleAnchors: chainTop !== legAnchors ? inheritedAnchorRecords.pathRuleAnchors : undefined, inheritedPathRuleInstallations: inheritedAnchorRecords.pathRuleInstallations, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, checkpointScope, toolCeiling, toolListsJudged, ownToolLists, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
803
806
  const { suspendForResource, suspendForPlatformLimit, suspendForReview } = prepareBoundaryParks({ saga, spec, checkpointStore, checkpointScope, abortController, harness, session, sessions, sessionId, deps, priorLedger, maxSlices, maxSuspends, resourceTotal, priorSuspendCount, suspendChainBase, humanReviewRef, liveSpendRef, now, pausedRef, remoteEnvFailures, resourceSuspendEligible, durableSuspendInfraReady, incompleteSuspendAdapter });
804
807
  const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, checkpointScope, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, handsRoot: attachmentRootCanonical, stampCallTarget, advertisedWritableDirs, exemptRoots: legExemptRoots, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, irreversibilityTier, toolMarkSources, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, ruleOffersOf, grantBindingOf, now, humanReviewRef, abortController, harness, pausedRef });
805
808
  const seatInputsFor = skillGateWiring({ tools, skillToolName: SKILL_TOOL_NAME, seatOf: skillSeatOf, mode: () => permissionMode.current, lane: skillGrantLane, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.skill_allowed", version: 1, taskId: hostTaskId, ...info, entries: [...info.entries], ts: Date.now() })), allowEntries: { deploymentAllows: { ...allowEntryLanes.deployment, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.allowed_tools_allowed", version: 1, taskId: hostTaskId, source: "deployment", ...info, entries: [...info.entries], ts: Date.now() })) }, requestAllows: { ...allowEntryLanes.request, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.allowed_tools_allowed", version: 1, taskId: hostTaskId, source: "request", ...info, entries: [...info.entries], ts: Date.now() })) } } });
806
- const { approvedCallScreen } = prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, modBus: legMods.bus, inheritedToolChecks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, toolOccurrences, batchHaltRef, blockedTracked, hookIdentity, reminderMark, hostTaskId, sessionId, handsCwdRef, stampCallTarget, readDenyInForce: (toolCallId) => ({ tiers: handsReadFace.readDenyBuiltinTiersActive, rows: [...readDenyAdditionsNormalized.map((e) => e.pattern), ...(pathTables?.forCall(toolCallId).ruleRows ?? handsReadFaceInput.denyRuleRows).filter((r) => r.faces.includes("read")).map((r) => r.rule)] }), hookEnvFace, writeProtectionCheck, shellReadCheck, readFace: () => resolvedReadFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider: autoModeDeciderRef, autoModeDenialTracking: autoModeDenialTrackingRef, askRoute: { ...wiringManifest.ask, effective: askSeatEffective(wiringManifest) }, permissionMode, toolMarkSources, ...(deps.a2a?.isolatePeers === true ? { a2aIsolatePeers: true } : {}), ancestorArbitrations, runId, stopForDenialLimit, permissionRuleLane, seatInputsFor, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, frameSettlement });
809
+ const { approvedCallScreen } = prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, crossBoundaryCheck: crossBoundary.seat({ tools, roster: rosterSeat }), toolEffects, deps, toolCallGateArmedRef, effectivePolicy, modBus: legMods.bus, inheritedToolChecks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, toolOccurrences, batchHaltRef, blockedTracked, hookIdentity, reminderMark, hostTaskId, sessionId, handsCwdRef, stampCallTarget, readDenyInForce: (toolCallId) => ({ tiers: handsReadFace.readDenyBuiltinTiersActive, rows: [...readDenyAdditionsNormalized.map((e) => e.pattern), ...(pathTables?.forCall(toolCallId).ruleRows ?? handsReadFaceInput.denyRuleRows).filter((r) => r.faces.includes("read")).map((r) => r.rule)] }), hookEnvFace, writeProtectionCheck, shellReadCheck, readFace: () => resolvedReadFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider: autoModeDeciderRef, autoModeDenialTracking: autoModeDenialTrackingRef, askRoute: { ...wiringManifest.ask, effective: askSeatEffective(wiringManifest) }, permissionMode, toolMarkSources, ...(deps.a2a?.isolatePeers === true ? { a2aIsolatePeers: true } : {}), ancestorArbitrations, runId, stopForDenialLimit, permissionRuleLane, seatInputsFor, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, frameSettlement });
807
810
  const postureFrameRef = { report: (err) => deps.onError?.(err, { phase: "degraded", sessionId }) };
808
811
  const { microCompact, charsPerToken } = prepareContextLane({ model, deps, sessionId, runId, hostTaskId, offloadStore, toolRosterDeltas: rosterSeat, microCompactKnob, harness, batchHaltRef, gitStatusRef, postureFrameRef, requestLossyRef, trimPressureRef, contextOverlay: legContextOverlay, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}) });
809
812
  const preparedHolder = {};
810
- const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, syntheticReadVerdict, consolidationWriteJudge, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved } = prepareTurnWiring({ deps, systemPromptSeat, harnessTools, fpRef, model, promptIdentityDigest: promptManifest.identity.artifact, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, readRoots, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, skillGrants: skillGrantLane, callerPolicy: installedToolPolicy, inheritedPolicies: (inheritedParentConstraints ?? []).map((c) => c.policy), persistedRuleLane: permissionRuleLane, ruleLaneFacts, personRowsBeyondRun, orgRuleLane: permissionRuleOrgLane, stampCallTarget, abortController, hostTaskId, taskScope, buildAssembleInputs, identityFor, adoptsCandidates, centerAdoptionRef, harnessRef, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder });
813
+ const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, compactionRestore, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, syntheticReadVerdict, consolidationWriteJudge, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved } = prepareTurnWiring({ deps, systemPromptSeat, harnessTools, fpRef, model, promptIdentityDigest: promptManifest.identity.artifact, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, readRoots, modelFileReader: modelFileReaderSeat.current, reminderMark, reminderDisclosureCounts, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, skillGrants: skillGrantLane, callerPolicy: installedToolPolicy, inheritedPolicies: (inheritedParentConstraints ?? []).map((c) => c.policy), persistedRuleLane: permissionRuleLane, ruleLaneFacts, personRowsBeyondRun, orgRuleLane: permissionRuleOrgLane, stampCallTarget, abortController, hostTaskId, taskScope, buildAssembleInputs, identityFor, adoptsCandidates, centerAdoptionRef, harnessRef, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder });
811
814
  await onceLedger.settle(session, announcedListingsRef);
812
- const buildPrepared = () => ({ harness, session, sessionId, runId, registryAccess: { owner: hostTaskId, scope: taskScope }, reminderMark, reminderDisclosureCounts, fullShellReachable, approvalPosture: { get mode() { return permissionMode.current; }, askEffective: askSeatEffective(wiringManifest) }, ...(outputStyleFrame !== undefined ? { outputStyleFrame } : {}), permissionMode, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(mcpRedial !== undefined ? { mcpRedial } : {}), ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, toolOccurrences, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, ...(attachmentRootCanonical !== undefined ? { handsRoot: attachmentRootCanonical } : {}), ...(stampCallTarget !== undefined ? { stampCallTarget } : {}), toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), exemptRoots: legExemptRoots, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, skillGrants: skillGrantLane, skillSpecs, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), consolidationWriteJudge, ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, endModeCeiling, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, promptIdentity, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, undeliveredContinuationRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, stopForDenialLimit, suspendForReview, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}), resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit && withheldDiagnosticsOf ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent, withheldOf: withheldDiagnosticsOf } } : {}), stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, frameReceipts: { pending: [], listingSnapshotOwed: false }, frameSettlement, ...(userAttachmentsSeat !== undefined ? { userAttachments: userAttachmentsSeat } : {}), attachmentDelivery: createAttachmentDelivery(), ...(modelFileReaderSeat.current !== undefined ? { modelFileReader: modelFileReaderSeat.current } : {}), syntheticReadVerdict, ...(peerLaneRefs.boundaryRound !== undefined ? { peerBoundaryRound: peerLaneRefs.boundaryRound } : {}), gitStatusRef, postureFrameRef, listBackgroundTasks, hookIdentity, modBus: legMods.bus, sideCallBookRef, ...(sessionBoxBound !== undefined ? { sessionBox: sessionBoxBound } : {}), ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(shellReadCheck !== undefined ? { shellReadCheck } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}), ...(approvedCallScreen !== undefined ? { approvedCallScreen } : {}) });
815
+ const buildPrepared = () => ({ harness, session, sessionId, runId, crossBoundary, registryAccess: { owner: hostTaskId, scope: taskScope }, reminderMark, reminderDisclosureCounts, fullShellReachable, approvalPosture: { get mode() { return permissionMode.current; }, askEffective: askSeatEffective(wiringManifest) }, ...(outputStyleFrame !== undefined ? { outputStyleFrame } : {}), permissionMode, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(mcpRedial !== undefined ? { mcpRedial } : {}), ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, toolOccurrences, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, ...(attachmentRootCanonical !== undefined ? { handsRoot: attachmentRootCanonical } : {}), ...(stampCallTarget !== undefined ? { stampCallTarget } : {}), toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), exemptRoots: legExemptRoots, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, skillGrants: skillGrantLane, skillSpecs, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), consolidationWriteJudge, ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, endModeCeiling, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, promptIdentity, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, undeliveredContinuationRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, stopForDenialLimit, suspendForReview, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}), resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, ...(compactionRestore !== undefined ? { compactionRestore } : {}), recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit && withheldDiagnosticsOf ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent, withheldOf: withheldDiagnosticsOf } } : {}), stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, frameReceipts: { pending: [], listingSnapshotOwed: false }, frameSettlement, ...(userAttachmentsSeat !== undefined ? { userAttachments: userAttachmentsSeat } : {}), attachmentDelivery: createAttachmentDelivery(), ...(modelFileReaderSeat.current !== undefined ? { modelFileReader: modelFileReaderSeat.current } : {}), syntheticReadVerdict, ...(peerLaneRefs.boundaryRound !== undefined ? { peerBoundaryRound: peerLaneRefs.boundaryRound } : {}), gitStatusRef, postureFrameRef, listBackgroundTasks, hookIdentity, modBus: legMods.bus, sideCallBookRef, ...(sessionBoxBound !== undefined ? { sessionBox: sessionBoxBound } : {}), ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(shellReadCheck !== undefined ? { shellReadCheck } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}), ...(approvedCallScreen !== undefined ? { approvedCallScreen } : {}) });
813
816
  refuseLateRosterChanges(callerRoster.roster);
814
817
  rollback.commit();
815
818
  commitModeSeats(abortController.signal);
@@ -12,10 +12,11 @@ import { type ConsolidationWriteJudgeLeg } from "./memory-consolidation-write-ju
12
12
  import type { RunnerDeps, TaskSpec } from "../types.js";
13
13
  import type { CwdRef } from "../../tools/fs/fs-shared.js";
14
14
  import { type ContainmentFace } from "../../tools/fs/index.js";
15
- import type { PlacedReadDenyMatcher } from "../../tools/fs/read-deny-home.js";
16
15
  import type { ReadRootsSeat } from "./person-path-rows.js";
17
16
  import { type ReadFileState } from "../../tools/fs/safety.js";
18
17
  import type { Prepared } from "./contracts.js";
18
+ import type { ModelFileReader } from "../../tools/fs/fs-read.js";
19
+ import type { ReminderDisclosureCounts } from "../reminder-disclosure.js";
19
20
  export interface PrepareTurnWiringInput {
20
21
  /** borrowed-readonly — the deployment seats: `cacheBreakDetection` (the detector knob), `onError` (the attachment-skip
21
22
  * degraded line), `promptSource` (the center candidate's state and current artifact), `permissionRuleStore` and
@@ -73,8 +74,12 @@ export interface PrepareTurnWiringInput {
73
74
  /** borrowed-readonly — the read face's root set beside the attachment root, read per use: the write roots, the read
74
75
  * roots with the run's grants, the person's read directories as the run read them last (no call: `ready` first). */
75
76
  readRoots: (() => readonly string[]) & Pick<ReadRootsSeat, "ready">;
76
- /** borrowed-readonly — the run's read deny table (its latest; these readers are no call), or undefined (the reader's withheld arm). */
77
- readDenyMatcher: PlacedReadDenyMatcher | undefined;
77
+ /** borrowed-readonly — the leg's one file reader (the hands band's), or undefined without hands: the restore reads through it. */
78
+ modelFileReader: ModelFileReader | undefined;
79
+ /** borrowed-readonly — the run's reminder mark (the restore frames' marked blocks). */
80
+ reminderMark: string | undefined;
81
+ /** borrowed-mutable — the run's disclosure counters; the restore frames' scans bump them when a frame is delivered. */
82
+ reminderDisclosureCounts: ReminderDisclosureCounts | undefined;
78
83
  /** borrowed-readonly — the resolved read face, or undefined (the fence's ninth argument). */
79
84
  resolvedReadFace: ContainmentFace | undefined;
80
85
  /** borrowed-readonly — the tracked-cwd seat, read per call by the kept-tail normalizer (never written here). */
@@ -148,8 +153,8 @@ export interface PrepareTurnWiringResult {
148
153
  } | undefined;
149
154
  /** owned — the fixed prompt-overhead term in the compaction trigger's coordinate (`Prepared.promptOverheadTokens`). */
150
155
  promptOverheadTokens: number;
151
- /** owned — the fenced working-file reader, or undefined without hands (`Prepared.readTaskFile`). */
152
- readTaskFile: Prepared["readTaskFile"];
156
+ /** owned — the post-compaction restore, or undefined without hands (`Prepared.compactionRestore`). */
157
+ compactionRestore: Prepared["compactionRestore"];
153
158
  /** owned — the kept-tail path normalizer, or undefined without hands. */
154
159
  normalizeAttachmentPath: Prepared["normalizeAttachmentPath"];
155
160
  /** owned — the Read tool's dedup-stub predicate, or undefined without hands. */
@@ -8,14 +8,13 @@ import { createSyntheticReadJudge } from "../synthetic-read-verdict.js";
8
8
  import { createConsolidationWriteJudge } from "./memory-consolidation-write-judge.js";
9
9
  import { toolCallFaceOf } from "../tool-roster.js";
10
10
  import { ORG_ADJUDICATION_TIMEOUT_MS } from "../permission-rule-org.js";
11
- import { decodeTextBytes } from "../../tools/fs/encoding.js";
12
- import { applyContextShrinkToReadFileState, isReadDedupStubResult } from "../../tools/fs/index.js";
11
+ import { applyContextShrinkToReadFileState, isReadDedupStubResult, readFileStateAfterSummary } from "../../tools/fs/index.js";
13
12
  import { resolveKey } from "../../tools/fs/safety.js";
14
13
  import { PROMPT_HASH_SALT } from "./prompt-hash-salt.js";
15
14
  import { CHANGED_FILES_MTIME_EPS_MS } from "./turn-attachments.js";
16
- import { thrownText } from "../thrown-value.js";
15
+ import { readCompactionRestore } from "../user-attachment.js";
17
16
  export function prepareTurnWiring(input) {
18
- const { deps, systemPromptSeat, harnessTools, fpRef, model, promptIdentityDigest, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, readRoots, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, skillGrants, callerPolicy, inheritedPolicies, persistedRuleLane, ruleLaneFacts, personRowsBeyondRun, orgRuleLane, stampCallTarget, abortController, hostTaskId, taskScope, buildAssembleInputs, identityFor, adoptsCandidates, centerAdoptionRef, harnessRef, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder } = input;
17
+ const { deps, systemPromptSeat, harnessTools, fpRef, model, promptIdentityDigest, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, readRoots, modelFileReader, reminderMark, reminderDisclosureCounts, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, skillGrants, callerPolicy, inheritedPolicies, persistedRuleLane, ruleLaneFacts, personRowsBeyondRun, orgRuleLane, stampCallTarget, abortController, hostTaskId, taskScope, buildAssembleInputs, identityFor, adoptsCandidates, centerAdoptionRef, harnessRef, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder } = input;
19
18
  const cacheBreakDetector = deps.cacheBreakDetection === false ? undefined : new CacheBreakDetector();
20
19
  const cacheFingerprint = cacheBreakDetector
21
20
  ? { systemPrompt: systemPromptSeat.current, tools: toolsToFingerprintInputs(harnessTools) }
@@ -41,49 +40,6 @@ export function prepareTurnWiring(input) {
41
40
  promptManifest.lowering = turnSnapshot.lowering;
42
41
  const promptOverheadTokens = Math.ceil((systemPromptSeat.current.length +
43
42
  harnessTools.reduce((a, t) => a + t.name.length + (t.description?.length ?? 0) + JSON.stringify(t.parameters ?? {}).length, 0)) / charsPerToken);
44
- const announceAttachmentSkip = (path, reason) => {
45
- deps.onError?.(new Error(`working-file attachment skipped — ${path}: ${reason}`), {
46
- phase: "degraded",
47
- sessionId,
48
- classification: "attachment-read",
49
- });
50
- };
51
- const readTaskFile = handsEnabled
52
- ? async (path) => {
53
- try {
54
- let key = path;
55
- if (attachmentRootCanonical !== undefined) {
56
- await readRoots.ready(abortController.signal);
57
- if (abortController.signal.aborted)
58
- return null;
59
- const rk = await resolveKey(executionEnv, attachmentRootCanonical, path, abortController.signal, undefined, readRoots(), undefined, readDenyMatcher, resolvedReadFace);
60
- if (!rk.ok) {
61
- announceAttachmentSkip(path, rk.violation.message);
62
- if (rk.violation.code === "read_path_denied" && rk.violation.pattern !== undefined) {
63
- return { withheld: { pattern: rk.violation.pattern } };
64
- }
65
- return null;
66
- }
67
- key = rk.key;
68
- }
69
- const r = await executionEnv.readBinaryFile(key, abortController.signal);
70
- if (!r.ok) {
71
- announceAttachmentSkip(path, r.error.message);
72
- return null;
73
- }
74
- const d = decodeTextBytes(r.value);
75
- if (d.malformed) {
76
- announceAttachmentSkip(path, "malformed text encoding (truncated UTF-16 body)");
77
- return null;
78
- }
79
- return d.text;
80
- }
81
- catch (err) {
82
- announceAttachmentSkip(path, thrownText(err));
83
- return null;
84
- }
85
- }
86
- : undefined;
87
43
  const normalizeAttachmentPath = handsEnabled
88
44
  ? async (path) => {
89
45
  if (attachmentRootCanonical === undefined)
@@ -108,7 +64,7 @@ export function prepareTurnWiring(input) {
108
64
  .map(([path]) => path)
109
65
  : undefined;
110
66
  const onCompactionApplied = handsEnabled && readFileStateForCheckpoint
111
- ? (attachedComplete, preserveReadState) => applyContextShrinkToReadFileState(readFileStateForCheckpoint, { kind: "summarized", attachedComplete, ...(preserveReadState !== undefined ? { preserveKeys: preserveReadState } : {}) })
67
+ ? (preserveReadState) => applyContextShrinkToReadFileState(readFileStateForCheckpoint, { kind: "summarized", preserveKeys: preserveReadState })
112
68
  : undefined;
113
69
  const syntheticLayers = {
114
70
  skillGrants,
@@ -120,6 +76,15 @@ export function prepareTurnWiring(input) {
120
76
  ...(stampCallTarget !== undefined ? { stampCallTarget } : {}),
121
77
  };
122
78
  const syntheticReadVerdict = createSyntheticReadJudge({ ...syntheticLayers, signal: abortController.signal });
79
+ const announceRestoreSkip = (path, reason) => {
80
+ deps.onError?.(new Error(`compaction restore did not deliver ${path}: ${reason}`), { phase: "degraded", sessionId, classification: "attachment-read" });
81
+ };
82
+ const compactionRestore = handsEnabled && modelFileReader !== undefined
83
+ ? {
84
+ restore: (ask) => readCompactionRestore({ reader: modelFileReader, judge: syntheticReadVerdict, cwd: () => handsCwdRef?.current, mark: reminderMark, counts: reminderDisclosureCounts, signal: abortController.signal, report: announceRestoreSkip }, { candidates: ask.candidates, maxFiles: ask.maxFiles, perFileChars: ask.perFileChars, totalChars: ask.totalChars, charsPerToken: ask.charsPerToken, dedupAgainst: readFileStateAfterSummary(readFileStateForCheckpoint ?? new Map(), ask.preserveKeys) }),
85
+ undelivered: announceRestoreSkip,
86
+ }
87
+ : undefined;
123
88
  const consolidationWriteJudge = createConsolidationWriteJudge({ ruleStoreProvider: deps.permissionRuleStore, principal: spec.principal, localOwnerDeclared: deps.localOwnerRules === true, ...(callerPolicy !== undefined ? { callerPolicy } : {}) }, { rows: personRowsBeyondRun, lanes: ruleLaneFacts, layers: { skillGrants, ...(denyNarrowingPolicy !== undefined ? { denyNarrowingPolicy } : {}), inheritedPolicies, ...(stampCallTarget !== undefined ? { stampCallTarget } : {}) }, facts: () => {
124
89
  const p = preparedHolder.current;
125
90
  return { face: toolCallFaceOf(p?.toolRoster, "Write"), cwd: p?.cwdRef?.current, root: p?.handsRoot, advertisedWritableDirs: p?.advertisedWritableDirs, exemptRoots: p?.exemptRoots };
@@ -218,5 +183,5 @@ export function prepareTurnWiring(input) {
218
183
  const effectiveReadFaceObserved = carrierReadFace();
219
184
  const effectiveWriteFaceObserved = carrierWriteFace();
220
185
  const effectiveReadDenyObserved = readDenyAdditionsNormalized.length > 0 ? readDenyAdditionsNormalized.map((e) => ({ ...e })) : undefined;
221
- return { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, syntheticReadVerdict, consolidationWriteJudge, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved };
186
+ return { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, compactionRestore, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, syntheticReadVerdict, consolidationWriteJudge, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved };
222
187
  }
@@ -82,9 +82,9 @@ export interface PrepareWiringManifestInput {
82
82
  irreversibleTools: ReadonlySet<string>;
83
83
  /** borrowed-readonly — see `irreversibleTools`. */
84
84
  egressTools: ReadonlySet<string>;
85
- /** borrowed-readonly — the hands phase mounted the shell READ STATION (a real shell was mounted): the gate
86
- * machinery must run for it, under every doctrine — the read-only face's containment IS that station. */
85
+ /** borrowed-readonly — the hands phase mounted the shell READ STATION (a real shell was mounted): the gate machinery must run for it, under every doctrine. */
87
86
  shellReadStationArmed: boolean;
87
+ /** borrowed-readonly — the leg's cross-boundary station is engaged (a declared posture, a target leg, a governed tree): the gate machinery runs for it. */ crossBoundaryStationEngaged: boolean;
88
88
  /** borrowed-readonly — the effect collection; read only here (the ungated scans). */
89
89
  toolEffects: ReadonlyMap<string, ToolEffect>;
90
90
  /** borrowed-readonly — the per-task owned env when a factory minted one (durable infra, the hook-env predicate). */
@@ -114,7 +114,8 @@ export interface PrepareWiringManifestInput {
114
114
  /** borrowed-readonly — the model gate's per-leg read face, or undefined. */
115
115
  modelGateManifest: WiringManifest["modelGate"];
116
116
  /** borrowed-readonly — the leg's minted tool roster: rides the manifest's `tools` section and is the
117
- * source of the hand band's write-capable names for the ungated-write warning (what actually MOUNTED). */
117
+ * source of the hand band's write-capable names for the ungated-write warning (what actually MOUNTED) and of each MCP server's
118
+ * `toolCount` (its tools among the roster's names). */
118
119
  toolRoster: ToolRoster;
119
120
  /** borrowed-readonly — from the read-face phase: the built-in read-deny TIERS that leg's own
120
121
  * resolution materially activated; relayed onto the manifest (present iff non-empty), never
@@ -140,6 +141,9 @@ export interface PrepareWiringManifestInput {
140
141
  frameSettlement: import("../frame-settlement.js").FrameSettlement;
141
142
  /** borrowed-readonly — the session-box drain's mount verdict (prepare-task's one judgment): present ⇒ this leg drains its own box. */
142
143
  sessionBox: SessionBoxBinding | undefined;
144
+ /** borrowed-readonly, read late — the memory session's one-way pollution face (absent with no memory session). The drain marks
145
+ * it when it INJECTS a letter from another principal (the injection path; the tool path is accounted by `ReadInbox`'s class). */
146
+ memoryPollution?: () => Pick<NonNullable<Prepared["memoryEngineSession"]>["pollution"], "markPolluted"> | undefined;
143
147
  /** borrowed-readonly — the built harness the peer drain binds to. */
144
148
  harness: AgentHarness;
145
149
  /** borrowed-readonly — the durable-suspend holder; the drain's parked predicate reads `token` at run time. Not written here. */
@@ -202,7 +206,8 @@ export interface PrepareWiringManifestResult {
202
206
  * The wiring manifest's per-server MCP read face for one leg ({@link WiringManifest.mcp}): every
203
207
  * server the leg's FROZEN entry snapshot declared, in declaration order, joined by name to this leg's
204
208
  * materialization statuses. Pure projection — no connection logic, no second look at any transport:
205
- * · a status `connected` ⇒ `connected` with the mounted roster size (the intake's post-filter count);
209
+ * · a status `connected` ⇒ `connected` with the server's tools among `rosterNames` — the names of the roster the row is read
210
+ * against: a run's (the valve and the deployment's overlay applied), or the no-run probe's own dials (no run, so no lists apply);
206
211
  * · a status `failed` ⇒ `failed` with the failure record the materialization stamped (`errorCode`/`delivered`/
207
212
  * `httpStatus` = the MCP vocabulary's `McpFailure` spread flat) and the remote text SECRET-REDACTED (an HTTP endpoint's error body rides the SDK's message
208
213
  * verbatim, and a body that echoes the bearer it rejected must not reach a stream consumer),
@@ -213,6 +218,6 @@ export interface PrepareWiringManifestResult {
213
218
  * `liveness` is the status record's own observation deep-copied (see {@link WiringManifestMcpEntry.liveness}).
214
219
  * The entries are fresh objects so the manifest never aliases the status records the refresh face mutates.
215
220
  */
216
- export declare function mcpManifestEntries(entries: ReadonlyArray<import("../types.js").McpServerSpec> | undefined, statuses: ReadonlyArray<import("../mcp.js").McpServerStatus>): WiringManifestMcpEntry[];
221
+ export declare function mcpManifestEntries(entries: ReadonlyArray<import("../types.js").McpServerSpec> | undefined, statuses: ReadonlyArray<import("../mcp.js").McpServerStatus>, rosterNames: ReadonlyArray<string>): WiringManifestMcpEntry[];
217
222
  /** The M18 phase body — prepareTask's wiring-manifest stretch, verbatim (see the module header). */
218
223
  export declare function prepareWiringManifest(input: PrepareWiringManifestInput): PrepareWiringManifestResult;